mirror of
https://github.com/ThaUnknown/miru.git
synced 2026-04-27 09:52:59 +00:00
84168 lines
No EOL
2.4 MiB
84168 lines
No EOL
2.4 MiB
/******/ (() => { // webpackBootstrap
|
|
/******/ var __webpack_modules__ = ({
|
|
|
|
/***/ "./app/js/anilist.js":
|
|
/*!***************************!*\
|
|
!*** ./app/js/anilist.js ***!
|
|
\***************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "alEntry": () => (/* binding */ alEntry),
|
|
/* harmony export */ "alRequest": () => (/* binding */ alRequest)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _main_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./main.js */ "./app/js/main.js");
|
|
/* harmony import */ var _interface_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./interface.js */ "./app/js/interface.js");
|
|
/* harmony import */ var halfmoon__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! halfmoon */ "halfmoon");
|
|
/* harmony import */ var halfmoon__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(halfmoon__WEBPACK_IMPORTED_MODULE_2__);
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
/* eslint-env browser */
|
|
/* global */
|
|
|
|
|
|
|
|
|
|
async function handleRequest (opts) {
|
|
return await fetch('https://graphql.anilist.co', opts).then(async res => {
|
|
const json = await res.json()
|
|
if (!res.ok) {
|
|
for (const error of json.errors) {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_2___default().initStickyAlert({
|
|
content: `Failed making request to anilist!<br>${error.status} - ${error.message}`,
|
|
title: 'Search Failed',
|
|
alertType: 'alert-danger',
|
|
fillType: ''
|
|
})
|
|
console.error(error)
|
|
}
|
|
}
|
|
return json
|
|
})
|
|
}
|
|
|
|
function alEntry () {
|
|
if (_main_js__WEBPACK_IMPORTED_MODULE_0__.client.nowPlaying.media && localStorage.getItem('ALtoken')) {
|
|
alRequest({ method: 'SearchIDStatus', id: _main_js__WEBPACK_IMPORTED_MODULE_0__.client.nowPlaying.media.id }).then(res => {
|
|
if ((res.errors && res.errors[0].status === 404) || res.data.MediaList.progress <= _main_js__WEBPACK_IMPORTED_MODULE_0__.client.nowPlaying.episodeNumber) {
|
|
const query = `
|
|
mutation ($id: Int, $status: MediaListStatus, $episode: Int, $repeat: Int) {
|
|
SaveMediaListEntry (mediaId: $id, status: $status, progress: $episode, repeat: $repeat) {
|
|
id,
|
|
status,
|
|
progress,
|
|
repeat
|
|
}
|
|
}`
|
|
const variables = {
|
|
repeat: 0,
|
|
id: _main_js__WEBPACK_IMPORTED_MODULE_0__.client.nowPlaying.media.id,
|
|
status: 'CURRENT',
|
|
episode: _main_js__WEBPACK_IMPORTED_MODULE_0__.client.nowPlaying.episodeNumber
|
|
}
|
|
if (_main_js__WEBPACK_IMPORTED_MODULE_0__.client.nowPlaying.episodeNumber === _main_js__WEBPACK_IMPORTED_MODULE_0__.client.nowPlaying.media.episodes) {
|
|
variables.status = 'COMPLETED'
|
|
if (res.data.MediaList.status === 'COMPLETED') {
|
|
variables.repeat = res.data.MediaList.repeat + 1
|
|
}
|
|
}
|
|
const options = {
|
|
method: 'POST',
|
|
headers: {
|
|
Authorization: 'Bearer ' + localStorage.getItem('ALtoken'),
|
|
'Content-Type': 'application/json',
|
|
Accept: 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
query: query,
|
|
variables: variables
|
|
})
|
|
}
|
|
handleRequest(options)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
async function alRequest (opts) {
|
|
let query
|
|
const variables = {
|
|
type: 'ANIME',
|
|
sort: opts.sort || 'TRENDING_DESC',
|
|
page: opts.page || 1,
|
|
perPage: opts.perPage || 30,
|
|
status_in: opts.status_in || '[CURRENT,PLANNING]',
|
|
chunk: opts.chunk || 1,
|
|
perchunk: opts.perChunk || 30
|
|
}
|
|
const options = {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
Accept: 'application/json'
|
|
},
|
|
body: undefined
|
|
}
|
|
const queryObjects = `
|
|
id,
|
|
title {
|
|
romaji,
|
|
english,
|
|
native,
|
|
userPreferred
|
|
},
|
|
description(
|
|
asHtml: true
|
|
),
|
|
season,
|
|
seasonYear,
|
|
format,
|
|
status,
|
|
episodes,
|
|
duration,
|
|
averageScore,
|
|
genres,
|
|
coverImage {
|
|
extraLarge,
|
|
medium,
|
|
color
|
|
},
|
|
countryOfOrigin,
|
|
isAdult,
|
|
bannerImage,
|
|
synonyms,
|
|
nextAiringEpisode {
|
|
timeUntilAiring,
|
|
episode
|
|
},
|
|
trailer {
|
|
id,
|
|
site
|
|
},
|
|
streamingEpisodes {
|
|
title,
|
|
thumbnail
|
|
},
|
|
relations {
|
|
edges {
|
|
relationType(version:2)
|
|
node {
|
|
id,
|
|
title {
|
|
userPreferred
|
|
},
|
|
coverImage {
|
|
medium
|
|
},
|
|
type,
|
|
status,
|
|
format,
|
|
episodes
|
|
}
|
|
}
|
|
}`
|
|
if (opts.status) variables.status = opts.status
|
|
if (localStorage.getItem('ALtoken')) options.headers.Authorization = localStorage.getItem('ALtoken')
|
|
switch (opts.method) {
|
|
case 'SearchName': {
|
|
variables.search = opts.name
|
|
query = `
|
|
query ($page: Int, $perPage: Int, $sort: [MediaSort], $type: MediaType, $search: String, $status: MediaStatus) {
|
|
Page (page: $page, perPage: $perPage) {
|
|
media(type: $type, search: $search, sort: $sort, status: $status) {
|
|
${queryObjects}
|
|
}
|
|
}
|
|
}`
|
|
break
|
|
} case 'SearchIDSingle': {
|
|
variables.id = opts.id
|
|
query = `
|
|
query ($id: Int, $type: MediaType) {
|
|
Media (id: $id, type: $type) {
|
|
${queryObjects}
|
|
}
|
|
}`
|
|
break
|
|
} case 'SearchIDS': {
|
|
variables.id = opts.id
|
|
query = `
|
|
query ($id: [Int], $type: MediaType, $page: Int, $perPage: Int) {
|
|
Page (page: $page, perPage: $perPage) {
|
|
media (id_in: $id, type: $type) {
|
|
${queryObjects}
|
|
}
|
|
}
|
|
}`
|
|
break
|
|
} case 'Viewer': {
|
|
query = `
|
|
query {
|
|
Viewer {
|
|
avatar {
|
|
medium
|
|
},
|
|
name,
|
|
id
|
|
}
|
|
}`
|
|
break
|
|
} case 'UserLists': {
|
|
variables.id = opts.id
|
|
query = `
|
|
query ($page: Int, $perPage: Int, $id: Int, $type: MediaType, $status_in: [MediaListStatus]){
|
|
Page (page: $page, perPage: $perPage) {
|
|
mediaList (userId: $id, type: $type, status_in: $status_in) {
|
|
media {
|
|
${queryObjects}
|
|
}
|
|
}
|
|
}
|
|
}`
|
|
break
|
|
} case 'SearchIDStatus': {
|
|
variables.id = _interface_js__WEBPACK_IMPORTED_MODULE_1__.alID
|
|
variables.mediaId = opts.id
|
|
query = `
|
|
query ($id: Int, $mediaId: Int){
|
|
MediaList(userId: $id, mediaId: $mediaId) {
|
|
status,
|
|
progress,
|
|
repeat
|
|
}
|
|
}`
|
|
break
|
|
} case 'AiringSchedule': {
|
|
const date = new Date()
|
|
const diff = date.getDay() >= 1 ? date.getDay() - 1 : 6 - date.getDay()
|
|
date.setDate(date.getDate() - diff)
|
|
date.setHours(0, 0, 0, 0)
|
|
variables.from = date.getTime() / 1000
|
|
variables.to = (date.getTime() + 7 * 24 * 60 * 60 * 1000) / 1000
|
|
query = `
|
|
query ($page: Int, $perPage: Int, $from: Int, $to: Int) {
|
|
Page (page: $page, perPage: $perPage) {
|
|
airingSchedules(airingAt_greater: $from, airingAt_lesser: $to) {
|
|
episode,
|
|
timeUntilAiring,
|
|
airingAt,
|
|
media{
|
|
${queryObjects}
|
|
}
|
|
}
|
|
}
|
|
}`
|
|
break
|
|
} case 'Search': {
|
|
variables.genre = opts.genre
|
|
variables.search = opts.search
|
|
variables.year = opts.year
|
|
variables.season = opts.season
|
|
variables.format = opts.format
|
|
variables.status = opts.status
|
|
variables.sort = opts.sort || 'SEARCH_MATCH'
|
|
query = `
|
|
query ($page: Int, $perPage: Int, $sort: [MediaSort], $type: MediaType, $search: String, $status: MediaStatus, $season: MediaSeason, $year: Int, $genre: String, $format: MediaFormat) {
|
|
Page (page: $page, perPage: $perPage) {
|
|
media(type: $type, search: $search, sort: $sort, status: $status, season: $season, seasonYear: $year, genre: $genre, format: $format) {
|
|
${queryObjects}
|
|
}
|
|
}
|
|
}`
|
|
}
|
|
}
|
|
options.body = JSON.stringify({
|
|
query: query.replace(/\s/g, ''),
|
|
variables: variables
|
|
})
|
|
|
|
return await handleRequest(options)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./app/js/anime.js":
|
|
/*!*************************!*\
|
|
!*** ./app/js/anime.js ***!
|
|
\*************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "viewAnime": () => (/* binding */ viewAnime),
|
|
/* harmony export */ "nyaaSearch": () => (/* binding */ nyaaSearch),
|
|
/* harmony export */ "resolveFileMedia": () => (/* binding */ resolveFileMedia),
|
|
/* harmony export */ "relations": () => (/* binding */ relations)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _main_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./main.js */ "./app/js/main.js");
|
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util.js */ "./app/js/util.js");
|
|
/* harmony import */ var _anilist_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./anilist.js */ "./app/js/anilist.js");
|
|
/* harmony import */ var _rss_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./rss.js */ "./app/js/rss.js");
|
|
/* harmony import */ var halfmoon__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! halfmoon */ "halfmoon");
|
|
/* harmony import */ var halfmoon__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(halfmoon__WEBPACK_IMPORTED_MODULE_4__);
|
|
/* harmony import */ var anitomyscript__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! anitomyscript */ "anitomyscript");
|
|
/* harmony import */ var anitomyscript__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(anitomyscript__WEBPACK_IMPORTED_MODULE_5__);
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
/* eslint-env browser */
|
|
/* global searchText, navNowPlaying */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const torrentRx = /(magnet:){1}|(^[A-F\d]{8,40}$){1}|(.*\.torrent){1}/i
|
|
const imageRx = /\.(jpeg|jpg|gif|png|webp)/i
|
|
window.addEventListener('paste', async e => { // WAIT image lookup on paste, or add torrent on paste
|
|
const item = e.clipboardData.items[0]
|
|
if (item && item.type.indexOf('image') === 0) {
|
|
e.preventDefault()
|
|
const reader = new FileReader()
|
|
reader.onload = e => {
|
|
traceAnime(e.target.result, 'uri')
|
|
}
|
|
reader.readAsDataURL(item.getAsFile())
|
|
} else if (item && item.type === 'text/plain') {
|
|
item.getAsString(text => {
|
|
if (torrentRx.exec(text)) {
|
|
e.preventDefault()
|
|
searchText.value = ''
|
|
_main_js__WEBPACK_IMPORTED_MODULE_0__.client.playTorrent(text)
|
|
} else if (imageRx.exec(text)) {
|
|
e.preventDefault()
|
|
searchText.value = ''
|
|
traceAnime(text)
|
|
}
|
|
})
|
|
} else if (item && item.type === 'text/html') {
|
|
item.getAsString(text => {
|
|
const img = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.DOMPARSER)(text, 'text/html').querySelectorAll('img')[0]
|
|
if (img) {
|
|
e.preventDefault()
|
|
searchText.value = ''
|
|
traceAnime(img.src)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
if (_util_js__WEBPACK_IMPORTED_MODULE_1__.searchParams.get('link')) {
|
|
traceAnime(_util_js__WEBPACK_IMPORTED_MODULE_1__.searchParams.get('link'))
|
|
window.location = '/app/#home'
|
|
}
|
|
function traceAnime (image, type) { // WAIT lookup logic
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_4___default().initStickyAlert({
|
|
content: `Looking up anime for image.<br><img class="w-200 rounded pt-5" src="${image}">`
|
|
})
|
|
let options
|
|
let url = `https://trace.moe/api/search?url=${image}`
|
|
if (type === 'uri') {
|
|
options = {
|
|
method: 'POST',
|
|
body: JSON.stringify({ image: image }),
|
|
headers: { 'Content-Type': 'application/json' }
|
|
}
|
|
url = 'https://trace.moe/api/search'
|
|
}
|
|
fetch(url, options).then(res => res.json()).then(async result => {
|
|
if (result.docs[0].similarity >= 0.85) {
|
|
const res = await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_2__.alRequest)({ method: 'SearchIDSingle', id: result.docs[0].anilist_id })
|
|
viewAnime(res.data.Media)
|
|
} else {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_4___default().initStickyAlert({
|
|
content: 'Couldn\'t find anime for specified image! Try to remove black bars, or use a more detailed image.',
|
|
title: 'Search Failed',
|
|
alertType: 'alert-danger',
|
|
fillType: ''
|
|
})
|
|
}
|
|
})
|
|
}
|
|
// events
|
|
navNowPlaying.onclick = () => viewAnime(_main_js__WEBPACK_IMPORTED_MODULE_0__.client.nowPlaying.media)
|
|
// AL lookup logic
|
|
|
|
// these really shouldnt be global
|
|
const detailsfrag = document.createDocumentFragment()
|
|
const details = {
|
|
averageScore: 'Average Score',
|
|
// duration: "Episode Duration",
|
|
// episodes: "Episodes",
|
|
// format: "Format",
|
|
genres: 'Genres',
|
|
// season: "Season",
|
|
// seasonYear: "Year",
|
|
status: 'Status',
|
|
english: 'English',
|
|
romaji: 'Romaji',
|
|
native: 'Native',
|
|
synonyms: 'Synonyms'
|
|
}
|
|
const episodeRx = /Episode (\d+) - (.*)/
|
|
// this is fucked beyond belief, this is why you use frameworks
|
|
/* global view, viewImg, viewTitle, viewDesc, viewDetails, viewSeason, viewMediaInfo, viewPlay, viewTrailer, viewRelationsGallery, viewSynonym, viewSynonymText, viewEpisodesWrapper, episodes, trailerVideo, trailerClose */
|
|
function viewAnime (media) {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_4___default().showModal('view')
|
|
view.setAttribute('style', `background-image: url(${media.bannerImage}) !important`)
|
|
viewImg.src = media.coverImage.extraLarge
|
|
viewTitle.innerHTML = media.title.userPreferred
|
|
viewDesc.innerHTML = media.description || ''
|
|
|
|
viewDetails.innerHTML = ''
|
|
detailsCreator(media)
|
|
viewDetails.appendChild(detailsfrag)
|
|
if (media.nextAiringEpisode) {
|
|
const temp = document.createElement('p')
|
|
temp.innerHTML = `<span class="font-weight-bold">Airing</span><br><span class="text-muted"> Episode ${media.nextAiringEpisode.episode}: ${(0,_util_js__WEBPACK_IMPORTED_MODULE_1__.countdown)(media.nextAiringEpisode.timeUntilAiring)}</span>`
|
|
viewDetails.prepend(temp)
|
|
}
|
|
viewSeason.innerHTML = `${(media.season ? media.season.toLowerCase() + ' ' : '') + (media.seasonYear ? media.seasonYear : '')}`
|
|
viewMediaInfo.innerHTML = `${media.format ? '<span>' + media.format + '</span>' : ''}${media.episodes ? '<span>' + media.episodes + ' Episodes</span>' : ''}${media.duration ? '<span>' + media.duration + ' Minutes</span>' : ''}`
|
|
viewPlay.onclick = () => { nyaaSearch(media, 1); halfmoon__WEBPACK_IMPORTED_MODULE_4___default().toggleModal('view') }
|
|
if (media.trailer) {
|
|
viewTrailer.removeAttribute('disabled', '')
|
|
viewTrailer.onclick = () =>
|
|
trailerPopup(media.trailer)
|
|
} else {
|
|
viewTrailer.setAttribute('disabled', '')
|
|
}
|
|
if (media.status === 'NOT_YET_RELEASED') {
|
|
viewPlay.setAttribute('disabled', '')
|
|
} else {
|
|
viewPlay.removeAttribute('disabled', '')
|
|
}
|
|
if (media.relations.edges.length) {
|
|
viewRelationsGallery.classList.remove('d-none')
|
|
viewRelationsGallery.innerHTML = ''
|
|
const frag = document.createDocumentFragment()
|
|
media.relations.edges.forEach(edge => {
|
|
const template = document.createElement('div')
|
|
template.classList.add('card', 'm-0', 'p-0')
|
|
template.innerHTML = `
|
|
<div class="row h-full">
|
|
<div class="col-4">
|
|
<img loading="lazy" src="${edge.node.coverImage.medium}"
|
|
class="cover-img w-full h-full">
|
|
</div>
|
|
<div class="col-8 h-full card-grid">
|
|
<div class="px-15 py-10">
|
|
<p class="m-0 text-capitalize font-weight-bold font-size-14">
|
|
${edge.node.title.userPreferred}
|
|
</p>
|
|
<p class="m-0 text-capitalize font-size-12">
|
|
${edge.relationType.toLowerCase()}
|
|
</p>
|
|
</div>
|
|
<span>
|
|
</span>
|
|
<div class="px-15 pb-10 pt-5 details text-capitalize font-size-12">
|
|
<span>${edge.node.type.toLowerCase()}</span><span>${edge.node.status.toLowerCase()}</span>
|
|
</div>
|
|
</div>
|
|
</div>`
|
|
template.onclick = async () => {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_4___default().hideModal('view')
|
|
const res = await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_2__.alRequest)({ method: 'SearchIDSingle', id: edge.node.id })
|
|
viewAnime(res.data.Media)
|
|
}
|
|
frag.appendChild(template)
|
|
})
|
|
viewRelationsGallery.appendChild(frag)
|
|
} else {
|
|
viewRelationsGallery.classList.add('d-none')
|
|
}
|
|
viewSynonym.onclick = () => {
|
|
relations[viewSynonymText.value] = media.id
|
|
viewSynonymText.value = ''
|
|
localStorage.setItem('relations', JSON.stringify(relations))
|
|
}
|
|
episodes.innerHTML = ''
|
|
if (media.streamingEpisodes.length) {
|
|
viewEpisodesWrapper.classList.add('remove')
|
|
const frag = document.createDocumentFragment()
|
|
media.streamingEpisodes.forEach(episode => {
|
|
const temp = document.createElement('div')
|
|
temp.classList.add('position-relative', 'w-250', 'rounded', 'mr-10', 'overflow-hidden', 'pointer')
|
|
temp.innerHTML = `
|
|
<img loading="lazy" src="${episode.thumbnail}" class="w-full h-full">
|
|
<div class="position-absolute ep-title w-full p-10 text-truncate bottom-0">${episode.title}</div>`
|
|
temp.onclick = () => { nyaaSearch(media, episodeRx.exec(episode.title)[1]); halfmoon__WEBPACK_IMPORTED_MODULE_4___default().toggleModal('view') }
|
|
frag.appendChild(temp)
|
|
})
|
|
episodes.appendChild(frag)
|
|
} else {
|
|
viewEpisodesWrapper.classList.add('hidden')
|
|
}
|
|
}
|
|
trailerClose.onclick = () => {
|
|
trailerVideo.src = ''
|
|
}
|
|
function trailerPopup (trailer) {
|
|
trailerVideo.src = ''
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_4___default().toggleModal('trailer')
|
|
switch (trailer.site) { // should support the other possible sites too, but i cant find any examples
|
|
case 'youtube':
|
|
trailerVideo.src = 'https://www.youtube.com/embed/' + trailer.id
|
|
break
|
|
}
|
|
}
|
|
// details list factory
|
|
function detailsCreator (entry) {
|
|
if (entry) {
|
|
Object.entries(entry).forEach(value => {
|
|
const template = document.createElement('p')
|
|
if (typeof value[1] === 'object') {
|
|
if (Array.isArray(value[1])) {
|
|
if (details[value[0]] && value[1].length > 0) {
|
|
template.innerHTML = `<span class="font-weight-bold">${details[value[0]]}</span><br><span class="text-muted">${value[1].map(key => (key)).join(', ')}</span>`
|
|
detailsfrag.appendChild(template)
|
|
}
|
|
} else {
|
|
detailsCreator(value[1])
|
|
}
|
|
} else {
|
|
if (details[value[0]]) {
|
|
template.innerHTML = `<span class="font-weight-bold">${details[value[0]]}</span><br><span class="text-muted">${value[1].toString()}</span>`
|
|
detailsfrag.appendChild(template)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
async function nyaaSearch (media, episode) {
|
|
if (parseInt(episode) < 10) {
|
|
episode = `0${episode}`
|
|
}
|
|
|
|
const table = document.querySelector('tbody.results')
|
|
const results = await (0,_rss_js__WEBPACK_IMPORTED_MODULE_3__.nyaaRss)(media, episode)
|
|
|
|
if (results.children.length === 0) {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_4___default().initStickyAlert({
|
|
content: `Couldn't find torrent for ${media.title.userPreferred} Episode ${parseInt(episode)}! Try specifying a torrent manually.`,
|
|
title: 'Search Failed',
|
|
alertType: 'alert-danger',
|
|
fillType: ''
|
|
})
|
|
} else {
|
|
table.innerHTML = ''
|
|
table.appendChild(results)
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_4___default().toggleModal('tsearch')
|
|
}
|
|
}
|
|
|
|
// resolve anime name based on file name and store it
|
|
|
|
async function resolveFileMedia (opts) {
|
|
// opts.fileName opts.method opts.isRelease
|
|
|
|
async function resolveTitle (title) {
|
|
if (!relations[title]) {
|
|
// resolve name and shit
|
|
let method, res
|
|
if (opts.isRelease) {
|
|
method = { name: title, method: 'SearchName', perPage: 1, status: 'RELEASING', sort: 'TRENDING_DESC' }
|
|
// maybe releases should include this and last season? idfk
|
|
} else {
|
|
method = { name: title, method: opts.method, perPage: 1, sort: 'SEARCH_MATCH' }
|
|
}
|
|
res = await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_2__.alRequest)(method)
|
|
if (!res.data.Page.media[0]) {
|
|
method.sort = 'SEARCH_MATCH'
|
|
method.name = method.name.replace('(TV)', '').replace(` (${new Date().getFullYear()})`, '').replace('-', '').replace('S2', '2') // this needs to be improved!!!
|
|
method.status = undefined
|
|
res = await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_2__.alRequest)(method)
|
|
}
|
|
if (res.data.Page.media[0]) {
|
|
relations[title] = res.data.Page.media[0].id
|
|
}
|
|
}
|
|
}
|
|
const parsePromises = opts.fileName.constructor === Array
|
|
? opts.fileName.map(name => anitomyscript__WEBPACK_IMPORTED_MODULE_5___default()(name))
|
|
: [anitomyscript__WEBPACK_IMPORTED_MODULE_5___default()(opts.fileName)]
|
|
const parseObjs = await Promise.all(parsePromises)
|
|
await Promise.all([...new Set(parseObjs.map(obj => obj.anime_title))].map(title => resolveTitle(title)))
|
|
const assoc = {}
|
|
for (const media of (await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_2__.alRequest)({ method: 'SearchIDS', id: [...new Set(parseObjs.map(obj => relations[obj.anime_title]))], perPage: 50 })).data.Page.media) assoc[media.id] = media
|
|
const fileMedias = []
|
|
for (const praseObj of parseObjs) {
|
|
let episode
|
|
let media = assoc[relations[praseObj.anime_title]]
|
|
async function resolveSeason (opts) {
|
|
// opts.media, opts.episode, opts.increment, opts.offset
|
|
let epMin, epMax
|
|
if (opts.episode.constructor === Array) { // support batch episode ranges
|
|
epMin = Number(opts.episode[0])
|
|
epMax = Number(opts.episode[opts.episode.length - 1])
|
|
} else {
|
|
epMin = epMax = Number(opts.episode)
|
|
}
|
|
let tempMedia, increment
|
|
if (opts.media.relations.edges.some(edge => edge.relationType === 'PREQUEL' && (edge.node.format === 'TV' || 'TV_SHORT')) && !opts.increment) {
|
|
// media has prequel and we dont want to move up in the tree
|
|
tempMedia = opts.media.relations.edges.filter(edge => edge.relationType === 'PREQUEL' && (edge.node.format === 'TV' || 'TV_SHORT'))[0].node
|
|
} else if (opts.media.relations.edges.some(edge => edge.relationType === 'SEQUEL' && (edge.node.format === 'TV' || 'TV_SHORT'))) {
|
|
// media doesnt have prequel, or we want to move up in the tree
|
|
tempMedia = opts.media.relations.edges.filter(edge => edge.relationType === 'SEQUEL' && (edge.node.format === 'TV' || 'TV_SHORT'))[0].node
|
|
increment = true
|
|
}
|
|
if (tempMedia?.episodes && epMax - (opts.offset + tempMedia.episodes) > (media.nextAiringEpisode?.episode || media.episodes)) {
|
|
// episode is still out of bounds
|
|
const nextEdge = await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_2__.alRequest)({ method: 'SearchIDSingle', id: tempMedia.id })
|
|
await resolveSeason({ media: nextEdge.data.Media, episode: opts.episode, offset: opts.offset + nextEdge.data.Media.episodes, increment: increment })
|
|
} else if (tempMedia?.episodes && epMax - (opts.offset + tempMedia.episodes) <= (media.nextAiringEpisode?.episode || media.episodes) && epMin - (opts.offset + tempMedia.episodes) > 0) {
|
|
// episode is in range, seems good! overwriting media to count up "seasons"
|
|
if (opts.episode.constructor === Array) {
|
|
episode = `${praseObj.episode_number[0] - (opts.offset + tempMedia.episodes)} ~ ${praseObj.episode_number[praseObj.episode_number.length - 1] - (opts.offset + tempMedia.episodes)}`
|
|
} else {
|
|
episode = opts.episode - (opts.offset + tempMedia.episodes)
|
|
}
|
|
if (opts.increment) {
|
|
const nextEdge = await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_2__.alRequest)({ method: 'SearchIDSingle', id: tempMedia.id })
|
|
media = nextEdge.data.Media
|
|
}
|
|
} else {
|
|
console.log('error in parsing!', opts.media, tempMedia)
|
|
// something failed, most likely couldnt find an edge or processing failed, force episode number even if its invalid/out of bounds, better than nothing
|
|
if (opts.episode.constructor === Array) {
|
|
episode = `${Number(praseObj.episode_number[0])} ~ ${Number(praseObj.episode_number[praseObj.episode_number.length - 1])}`
|
|
} else {
|
|
episode = Number(opts.episode)
|
|
}
|
|
}
|
|
}
|
|
|
|
// resolve episode, if movie, dont.
|
|
if ((media?.format !== 'MOVIE' || (media.episodes || media.nextAiringEpisode.episode)) && praseObj.episode_number) {
|
|
if (praseObj.episode_number.constructor === Array) {
|
|
// is an episode range
|
|
if (parseInt(praseObj.episode_number[0]) === 1) {
|
|
// if it starts with #1 and overflows then it includes more than 1 season in a batch, cant fix this cleanly, name is parsed per file basis so this shouldnt be an issue
|
|
episode = `${praseObj.episode_number[0]} ~ ${praseObj.episode_number[praseObj.episode_number.length - 1]}`
|
|
} else {
|
|
if ((media?.episodes || media?.nextAiringEpisode?.episode) && parseInt(praseObj.episode_number[praseObj.episode_number.length - 1]) > (media.episodes || media.nextAiringEpisode.episode)) {
|
|
// if highest value is bigger than episode count or latest streamed episode +1 for safety, parseint to math.floor a number like 12.5 - specials - in 1 go
|
|
await resolveSeason({ media: media, episode: praseObj.episode_number, offset: 0 })
|
|
} else {
|
|
// cant find ep count or range seems fine
|
|
episode = `${Number(praseObj.episode_number[0])} ~ ${Number(praseObj.episode_number[praseObj.episode_number.length - 1])}`
|
|
}
|
|
}
|
|
} else {
|
|
if ((media?.episodes || media?.nextAiringEpisode?.episode) && parseInt(praseObj.episode_number) > (media.episodes || media.nextAiringEpisode.episode)) {
|
|
// value bigger than episode count
|
|
await resolveSeason({ media: media, episode: praseObj.episode_number, offset: 0 })
|
|
} else {
|
|
// cant find ep count or episode seems fine
|
|
episode = Number(praseObj.episode_number)
|
|
}
|
|
}
|
|
}
|
|
const streamingEpisode = media?.streamingEpisodes.filter(episode => episodeRx.exec(episode.title) && Number(episodeRx.exec(episode.title)[1]) === Number(praseObj.episode_number))[0]
|
|
fileMedias.push({
|
|
mediaTitle: media?.title.userPreferred,
|
|
episodeNumber: episode,
|
|
episodeTitle: streamingEpisode ? episodeRx.exec(streamingEpisode.title)[2] : undefined,
|
|
episodeThumbnail: streamingEpisode?.thumbnail,
|
|
mediaCover: media?.coverImage.medium,
|
|
name: 'Miru',
|
|
parseObject: praseObj,
|
|
media: media
|
|
})
|
|
}
|
|
return fileMedias.length === 1 ? fileMedias[0] : fileMedias
|
|
}
|
|
|
|
const relations = JSON.parse(localStorage.getItem('relations')) || {}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./app/js/interface.js":
|
|
/*!*****************************!*\
|
|
!*** ./app/js/interface.js ***!
|
|
\*****************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "loadHomePage": () => (/* binding */ loadHomePage),
|
|
/* harmony export */ "cardCreator": () => (/* binding */ cardCreator),
|
|
/* harmony export */ "releasesCards": () => (/* binding */ releasesCards),
|
|
/* harmony export */ "alID": () => (/* binding */ alID),
|
|
/* harmony export */ "initMenu": () => (/* binding */ initMenu)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _anilist_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./anilist.js */ "./app/js/anilist.js");
|
|
/* harmony import */ var _anime_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./anime.js */ "./app/js/anime.js");
|
|
/* harmony import */ var _rss_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./rss.js */ "./app/js/rss.js");
|
|
/* harmony import */ var _settings_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./settings.js */ "./app/js/settings.js");
|
|
/* harmony import */ var _main_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./main.js */ "./app/js/main.js");
|
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./util.js */ "./app/js/util.js");
|
|
/* eslint-env browser */
|
|
/* global navHome, searchClear, searchWrapper, skeletonCardTemplate, bareCardTemplate, fullCardTemplate, home, searchText, searchGenre, searchYear, searchSeason, searchFormat, searchStatus, searchSort, navSchedule, homeContinueMore, homeReleasesMore, homePlanningMore, homeTrendingMore, homeRomanceMore, homeActionMore, homeContinue, homeReleases, homePlanning, homeTrending, homeRomance, homeAction */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function loadHomePage () {
|
|
const homeLoadElements = [navSchedule, homeContinueMore, homeReleasesMore, homePlanningMore, homeTrendingMore, homeRomanceMore, homeActionMore]
|
|
const homePreviewElements = [homeContinue, homeReleases, homePlanning, homeTrending, homeRomance, homeAction]
|
|
const homeSearchElements = [searchText, searchGenre, searchYear, searchSeason, searchFormat, searchStatus, searchSort]
|
|
const browseGallery = document.querySelector('.browse')
|
|
const homeLoadFunctions = {
|
|
continue: async function (page) {
|
|
if (!page) gallerySkeleton(browseGallery)
|
|
await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)({ method: 'UserLists', status_in: 'CURRENT', id: alID, page: page || 1 }).then(res => {
|
|
galleryAppend({ media: res.data.Page.mediaList.map(i => i.media), gallery: browseGallery, method: 'continue', page: page || 1 })
|
|
})
|
|
},
|
|
releases: async function () {
|
|
gallerySkeleton(browseGallery)
|
|
await (0,_rss_js__WEBPACK_IMPORTED_MODULE_2__.releasesRss)().then(cards => {
|
|
browseGallery.textContent = ''
|
|
browseGallery.append(...cards)
|
|
home.classList.remove('loading')
|
|
home.onscroll = undefined
|
|
})
|
|
},
|
|
planning: async function (page) {
|
|
if (!page) gallerySkeleton(browseGallery)
|
|
await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)({ method: 'UserLists', status_in: 'PLANNING', id: alID, page: page || 1 }).then(res => {
|
|
galleryAppend({ media: res.data.Page.mediaList.map(i => i.media), gallery: browseGallery, method: 'planning', page: page || 1 })
|
|
})
|
|
},
|
|
trending: async function () {
|
|
gallerySkeleton(browseGallery)
|
|
clearSearch()
|
|
searchSort.value = 'TRENDING_DESC'
|
|
await homeLoadFunctions.search()
|
|
},
|
|
romance: async function () {
|
|
gallerySkeleton(browseGallery)
|
|
clearSearch()
|
|
searchGenre.value = 'romance'
|
|
searchSort.value = 'TRENDING_DESC'
|
|
await homeLoadFunctions.search()
|
|
},
|
|
action: async function () {
|
|
gallerySkeleton(browseGallery)
|
|
clearSearch()
|
|
searchGenre.value = 'action'
|
|
searchSort.value = 'TRENDING_DESC'
|
|
await homeLoadFunctions.search()
|
|
},
|
|
schedule: async function (page) {
|
|
if (!page) gallerySkeleton(browseGallery)
|
|
await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)({ method: 'AiringSchedule', page: page || 1 }).then(res => {
|
|
galleryAppend({ media: res.data.Page.airingSchedules.filter(entry => entry.media.countryOfOrigin !== 'CN' && entry.media.isAdult === false), gallery: browseGallery, method: 'schedule', page: page || 1, schedule: true })
|
|
})
|
|
},
|
|
search: async function (page) {
|
|
const opts = {
|
|
method: 'Search',
|
|
page: page || 1
|
|
}
|
|
for (const element of homeSearchElements) {
|
|
if (element.value) opts[element.dataset.option] = element.value
|
|
}
|
|
await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)(opts).then(res => {
|
|
galleryAppend({ media: res.data.Page.media, gallery: browseGallery, method: 'search', page: page || 1 })
|
|
})
|
|
}
|
|
}
|
|
const homePreviewFunctions = {
|
|
continue: function () {
|
|
;(0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)({ method: 'UserLists', status_in: 'CURRENT', id: alID, perPage: 5 }).then((res) => {
|
|
galleryAppend({ media: res.data.Page.mediaList.map(i => i.media), gallery: homeContinue })
|
|
})
|
|
},
|
|
releases: async function () { // this could be cleaner, but oh well
|
|
await fetch((0,_rss_js__WEBPACK_IMPORTED_MODULE_2__.getRSSurl)()).then(res => res.text().then(xmlTxt => {
|
|
const doc = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__.DOMPARSER)(xmlTxt, 'text/xml')
|
|
const pubDate = doc.querySelector('pubDate').textContent
|
|
if (lastRSSDate !== pubDate) {
|
|
if (lastRSSDate) {
|
|
homeReleases.append(...gallerySkeletonFrag(5))
|
|
;(0,_anime_js__WEBPACK_IMPORTED_MODULE_1__.resolveFileMedia)({ fileName: doc.querySelector('item').querySelector('title').textContent, method: 'SearchName', isRelease: true }).then(mediaInformation => {
|
|
if (_settings_js__WEBPACK_IMPORTED_MODULE_3__.settings.other1) {
|
|
const notification = new Notification(mediaInformation.media.title.userPreferred, {
|
|
body: `Episode ${mediaInformation.episode} was just released!`,
|
|
icon: mediaInformation.media.coverImage.medium
|
|
})
|
|
notification.onclick = async () => {
|
|
window.parent.focus()
|
|
_main_js__WEBPACK_IMPORTED_MODULE_4__.client.playTorrent(doc.querySelector('item').querySelector('link').textContent, { media: mediaInformation, episode: mediaInformation.episode })
|
|
_anime_js__WEBPACK_IMPORTED_MODULE_1__.relations[mediaInformation.parseObject.anime_title] = await (0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)({ id: mediaInformation.media.id, method: 'SearchIDSingle' }).then(res => res.data.Media.id)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
lastRSSDate = pubDate
|
|
releasesCards(doc.querySelectorAll('item'), 5).then(cards => {
|
|
homeReleases.textContent = ''
|
|
homeReleases.append(...cards)
|
|
})
|
|
}
|
|
}))
|
|
setTimeout(homePreviewFunctions.releases, 30000)
|
|
},
|
|
planning: function () {
|
|
(0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)({ method: 'UserLists', status_in: 'PLANNING', id: alID, perPage: 5 }).then((res) => {
|
|
galleryAppend({ media: res.data.Page.mediaList.map(i => i.media), gallery: homePlanning })
|
|
})
|
|
},
|
|
trending: function () {
|
|
(0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)({ method: 'Search', id: alID, perPage: 5, sort: 'TRENDING_DESC' }).then((res) => {
|
|
galleryAppend({ media: res.data.Page.media, gallery: homeTrending })
|
|
})
|
|
},
|
|
romance: function () {
|
|
(0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)({ method: 'Search', genre: 'Romance', perPage: 5, sort: 'TRENDING_DESC' }).then((res) => {
|
|
galleryAppend({ media: res.data.Page.media, gallery: homeRomance })
|
|
})
|
|
},
|
|
action: function () {
|
|
(0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)({ method: 'Search', genre: 'Action', perPage: 5, sort: 'TRENDING_DESC' }).then((res) => {
|
|
galleryAppend({ media: res.data.Page.media, gallery: homeAction })
|
|
})
|
|
}
|
|
}
|
|
const gallerySkeletonFrag = function (limit) {
|
|
const cards = []
|
|
while (limit--) {
|
|
cards.push(skeletonCard.cloneNode(true))
|
|
}
|
|
return cards
|
|
}
|
|
let loadTimeout
|
|
let lastDate
|
|
let lastRSSDate
|
|
let canScroll = true
|
|
|
|
function gallerySkeleton (gallery) {
|
|
home.classList.add('loading')
|
|
gallery.textContent = ''
|
|
gallery.append(...gallerySkeletonFrag(10))
|
|
}
|
|
function galleryAppend (opts) {
|
|
if (opts.page === 1) {
|
|
home.classList.remove('loading')
|
|
}
|
|
if (opts.method) {
|
|
canScroll = false
|
|
home.onscroll = function () {
|
|
if (this.scrollTop + this.clientHeight > this.scrollHeight - 800 && !loadTimeout && canScroll) {
|
|
canScroll = false
|
|
loadTimeout = setTimeout(function () { loadTimeout = undefined }, 1000)
|
|
homeLoadFunctions[opts.method](opts.page + 1).then(() => { canScroll = true })
|
|
}
|
|
}
|
|
}
|
|
if (!opts.page || opts.page === 1) {
|
|
opts.gallery.textContent = ''
|
|
}
|
|
const date = new Date()
|
|
const cards = []
|
|
opts.media.forEach(media => {
|
|
if (opts.schedule) {
|
|
if (media.timeUntilAiring && (!lastDate || (new Date(+date + media.timeUntilAiring * 1000).getDay() !== lastDate.getDay()))) {
|
|
const div = document.createElement('div')
|
|
lastDate = new Date(+date + media.timeUntilAiring * 1000)
|
|
div.classList.add('day-row', 'font-size-24', 'font-weight-bold', 'h-50', 'd-flex', 'align-items-end')
|
|
div.textContent = lastDate.toLocaleDateString('en-US', { weekday: 'long' })
|
|
cards.push(div)
|
|
}
|
|
media = media.media
|
|
}
|
|
cards.push(cardCreator({ media: media, schedule: opts.schedule, onclick: () => (0,_anime_js__WEBPACK_IMPORTED_MODULE_1__.viewAnime)(media) }))
|
|
})
|
|
opts.gallery.append(...cards)
|
|
canScroll = true
|
|
}
|
|
|
|
for (const item of homePreviewElements) {
|
|
homePreviewFunctions[item.dataset.function]()
|
|
}
|
|
for (const item of homeLoadElements) {
|
|
item.onclick = function () {
|
|
home.scrollTop = 0
|
|
home.classList.add('browsing')
|
|
homeLoadFunctions[item.dataset.function]()
|
|
}
|
|
}
|
|
function reloadHome () {
|
|
clearSearch()
|
|
home.classList.remove('browsing')
|
|
lastRSSDate = undefined
|
|
for (const item of homePreviewElements) {
|
|
item.textContent = ''
|
|
item.append(...gallerySkeletonFrag(5))
|
|
homePreviewFunctions[item.dataset.function]()
|
|
}
|
|
document.querySelector('.browse').textContent = ''
|
|
}
|
|
navHome.onclick = reloadHome
|
|
searchClear.onclick = reloadHome
|
|
function clearSearch () {
|
|
for (const element of homeSearchElements) {
|
|
element.value = ''
|
|
}
|
|
}
|
|
let searchTimeout
|
|
searchWrapper.oninput = e => {
|
|
if (!searchTimeout) {
|
|
home.classList.add('browsing')
|
|
gallerySkeleton(browseGallery)
|
|
} else {
|
|
clearTimeout(searchTimeout)
|
|
}
|
|
searchTimeout = setTimeout(() => {
|
|
homeLoadFunctions.search()
|
|
searchTimeout = undefined
|
|
}, 500)
|
|
}
|
|
}
|
|
|
|
const skeletonCard = skeletonCardTemplate.cloneNode(true).content
|
|
const bareCard = bareCardTemplate.cloneNode(true).content
|
|
const fullCard = fullCardTemplate.cloneNode(true).content
|
|
function cardCreator (opts) {
|
|
if (opts.media) {
|
|
const card = fullCard.cloneNode(true)
|
|
const nodes = card.querySelectorAll('*')
|
|
nodes[0].onclick = opts.onclick
|
|
nodes[0].style = `--color:${opts.media.coverImage.color || '#1890ff'};`
|
|
nodes[3].src = opts.media.coverImage.extraLarge || ''
|
|
nodes[6].textContent = [opts.media.title.userPreferred, opts.episodeNumber].filter(s => s).join(' - ')
|
|
if (opts.schedule && opts.media.nextAiringEpisode) nodes[7].textContent = opts.media.nextAiringEpisode.episode + ' in ' + (0,_util_js__WEBPACK_IMPORTED_MODULE_5__.countdown)(opts.media.nextAiringEpisode.timeUntilAiring)
|
|
nodes[8].innerHTML = '<span>' + [
|
|
opts.media.format === 'TV' ? 'TV Show' : opts.media.format?.toLowerCase().replace(/_/g, ' '),
|
|
opts.media.episodes ? opts.media.episodes + ' Episodes' : opts.media.duration ? opts.media.duration + ' Minutes' : undefined,
|
|
opts.media.status?.toLowerCase().replace(/_/g, ' '),
|
|
[opts.media.season?.toLowerCase(), opts.media.seasonYear].filter(s => s).join(' ')
|
|
].filter(s => s).join('</span><span>') + '</span>'
|
|
nodes[13].innerHTML = opts.media.description
|
|
nodes[14].innerHTML = opts.media.genres.map(key => (`<span class="badge badge-pill badge-color text-dark mt-5 font-weight-bold">${key}</span> `)).join('')
|
|
return card
|
|
} else if (opts.parseObject) {
|
|
const card = bareCard.cloneNode(true)
|
|
card.querySelector('h5').textContent = [opts.parseObject.anime_title, opts.parseObject.episode_number].filter(s => s).join(' - ')
|
|
card.firstElementChild.onclick = opts.onclick
|
|
return card
|
|
} else {
|
|
return skeletonCard.cloneNode(true)
|
|
}
|
|
}
|
|
|
|
async function releasesCards (items, limit) {
|
|
const cards = []
|
|
await (0,_anime_js__WEBPACK_IMPORTED_MODULE_1__.resolveFileMedia)({ fileName: [...items].map(item => item.querySelector('title').textContent).slice(0, limit), method: 'SearchName', isRelease: true }).then(results => {
|
|
results.forEach((mediaInformation, index) => {
|
|
const o = items[index].querySelector.bind(items[index])
|
|
mediaInformation.onclick = () => _main_js__WEBPACK_IMPORTED_MODULE_4__.client.playTorrent(o('link').textContent, { media: mediaInformation, episode: mediaInformation.episode })
|
|
cards.push(cardCreator(mediaInformation))
|
|
})
|
|
})
|
|
localStorage.setItem('relations', JSON.stringify(_anime_js__WEBPACK_IMPORTED_MODULE_1__.relations))
|
|
return cards
|
|
}
|
|
|
|
let alID // login icon
|
|
/* global oauth */
|
|
function initMenu () {
|
|
if (localStorage.getItem('ALtoken')) {
|
|
(0,_anilist_js__WEBPACK_IMPORTED_MODULE_0__.alRequest)({ method: 'Viewer' }).then(result => {
|
|
oauth.removeAttribute('href')
|
|
oauth.setAttribute('data-title', `${result.data.Viewer.name}\nClick To Logout`)
|
|
oauth.innerHTML = `
|
|
<span class="text-nowrap d-flex align-items-center">
|
|
<img src="${result.data.Viewer.avatar.medium}">
|
|
<span class="text">${result.data.Viewer.name}</span>
|
|
<span class="material-icons menu text">logout</span>
|
|
</span>`
|
|
oauth.onclick = () => {
|
|
localStorage.removeItem('ALtoken')
|
|
location.reload()
|
|
}
|
|
alID = result.data.Viewer.id
|
|
loadHomePage()
|
|
})
|
|
} else {
|
|
loadHomePage()
|
|
home.classList.add('noauth')
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./app/js/main.js":
|
|
/*!************************!*\
|
|
!*** ./app/js/main.js ***!
|
|
\************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "client": () => (/* binding */ client)
|
|
/* harmony export */ });
|
|
/* harmony import */ var webtorrent_player__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! webtorrent-player */ "./node_modules/webtorrent-player/index.js");
|
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util.js */ "./app/js/util.js");
|
|
/* harmony import */ var _anime_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./anime.js */ "./app/js/anime.js");
|
|
/* harmony import */ var _anilist_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./anilist.js */ "./app/js/anilist.js");
|
|
/* harmony import */ var _settings_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./settings.js */ "./app/js/settings.js");
|
|
/* harmony import */ var _interface_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./interface.js */ "./app/js/interface.js");
|
|
/* harmony import */ var halfmoon__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! halfmoon */ "halfmoon");
|
|
/* harmony import */ var halfmoon__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(halfmoon__WEBPACK_IMPORTED_MODULE_6__);
|
|
/* globals video, player, pageWrapper, subtitle1list */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const announceList = [
|
|
'wss://tracker.openwebtorrent.com',
|
|
'wss://tracker.sloppyta.co:443/announce',
|
|
'wss://hub.bugout.link:443/announce'
|
|
]
|
|
const playerControls = {}
|
|
for (const item of document.getElementsByClassName('ctrl')) {
|
|
if (!playerControls[item.dataset.name]) {
|
|
playerControls[item.dataset.name] = item
|
|
} else {
|
|
playerControls[item.dataset.name] = [playerControls[item.dataset.name], item]
|
|
}
|
|
}
|
|
const client = new webtorrent_player__WEBPACK_IMPORTED_MODULE_0__.default({
|
|
WebTorrentOpts: {
|
|
maxConns: 127,
|
|
downloadLimit: _settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.torrent7 * 1048576,
|
|
uploadLimit: _settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.torrent7 * 1572864,
|
|
tracker: {
|
|
announce: announceList
|
|
}
|
|
},
|
|
controls: playerControls,
|
|
video: video,
|
|
player: player,
|
|
playerWrapper: pageWrapper,
|
|
burnIn: _settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.subtitle3,
|
|
seekTime: Number(_settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.player3),
|
|
immerseTime: Number(_settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.player2),
|
|
visibilityLossPause: _settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.player10,
|
|
autoNext: _settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.player6,
|
|
streamedDownload: _settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.torrent8,
|
|
generateThumbnails: _settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.player5,
|
|
defaultSSAStyles: Object.values(subtitle1list.options).filter(item => item.value === _settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.subtitle1)[0].textContent,
|
|
resolveFileMedia: _anime_js__WEBPACK_IMPORTED_MODULE_2__.resolveFileMedia
|
|
})
|
|
client.on('download-done', ({ file }) => {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_6___default().initStickyAlert({
|
|
content: `<span class="text-break">${file.name}</span> has finished downloading. Now seeding.`,
|
|
title: 'Download Complete',
|
|
alertType: 'alert-success',
|
|
fillType: ''
|
|
})
|
|
})
|
|
client.on('watched', ({ filemedia }) => {
|
|
if (filemedia?.media?.episodes || filemedia?.media?.nextAiringEpisode?.episode) {
|
|
if (_settings_js__WEBPACK_IMPORTED_MODULE_4__.settings.other2 && (filemedia.media.episodes || filemedia.media.nextAiringEpisode?.episode > filemedia.episodeNumber)) {
|
|
(0,_anilist_js__WEBPACK_IMPORTED_MODULE_3__.alEntry)()
|
|
} else {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_6___default().initStickyAlert({
|
|
content: `Do You Want To Mark <br><b>${filemedia.mediaTitle}</b><br>Episode ${filemedia.episodeNumber} As Completed?<br>
|
|
<button class="btn btn-sm btn-square btn-success mt-5" onclick="alEntry()" data-dismiss="alert" type="button" aria-label="Close">✓</button>
|
|
<button class="btn btn-sm btn-square mt-5" data-dismiss="alert" type="button" aria-label="Close"><span aria-hidden="true">X</span></button>`,
|
|
title: 'Episode Complete',
|
|
timeShown: 180000
|
|
})
|
|
}
|
|
}
|
|
})
|
|
client.on('playlist', () => {
|
|
window.location.hash = '#playlist'
|
|
})
|
|
client.on('next', ({ filemedia }) => {
|
|
if (filemedia.media) {
|
|
(0,_anime_js__WEBPACK_IMPORTED_MODULE_2__.nyaaSearch)(filemedia.media, filemedia.episodeNumber + 1)
|
|
} else {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_6___default().initStickyAlert({
|
|
content: 'Couldn\'t find anime name! Try specifying a torrent manually.',
|
|
title: 'Search Failed',
|
|
alertType: 'alert-danger',
|
|
fillType: ''
|
|
})
|
|
}
|
|
})
|
|
client.on('prev', ({ filemedia }) => {
|
|
if (filemedia.media) {
|
|
(0,_anime_js__WEBPACK_IMPORTED_MODULE_2__.nyaaSearch)(filemedia.media, filemedia.episodeNumber - 1)
|
|
} else {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_6___default().initStickyAlert({
|
|
content: 'Couldn\'t find anime name! Try specifying a torrent manually.',
|
|
title: 'Search Failed',
|
|
alertType: 'alert-danger',
|
|
fillType: ''
|
|
})
|
|
}
|
|
})
|
|
client.on('offline-torrent', torrent => {
|
|
;(0,_anime_js__WEBPACK_IMPORTED_MODULE_2__.resolveFileMedia)({ fileName: torrent.name, method: 'SearchName' }).then(mediaInformation => {
|
|
mediaInformation.onclick = () => client.addTorrent(torrent, { media: mediaInformation, episode: mediaInformation.episode })
|
|
const template = (0,_interface_js__WEBPACK_IMPORTED_MODULE_5__.cardCreator)(mediaInformation)
|
|
document.querySelector('.downloads').appendChild(template)
|
|
})
|
|
})
|
|
client.on('video-files', async ({ files, torrent }) => {
|
|
document.querySelector('.playlist').textContent = ''
|
|
const cards = []
|
|
for (const file of files) {
|
|
const mediaInformation = await (0,_anime_js__WEBPACK_IMPORTED_MODULE_2__.resolveFileMedia)({ fileName: file.name, method: 'SearchName' })
|
|
mediaInformation.onclick = () => {
|
|
client.buildVideo(torrent, {
|
|
media: mediaInformation,
|
|
episode: mediaInformation.parseObject.episode,
|
|
file: file
|
|
})
|
|
}
|
|
cards.push((0,_interface_js__WEBPACK_IMPORTED_MODULE_5__.cardCreator)(mediaInformation))
|
|
}
|
|
document.querySelector('.playlist').append(...cards)
|
|
})
|
|
client.on('no-files', torrent => {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_6___default().initStickyAlert({
|
|
content: `Couldn't find video file for <span class="text-break">${torrent.infoHash}</span>!`,
|
|
title: 'Search Failed',
|
|
alertType: 'alert-danger',
|
|
fillType: ''
|
|
})
|
|
})
|
|
client.on('no peers', torrent => {
|
|
if (torrent.progress !== 1) {
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_6___default().initStickyAlert({
|
|
content: `Couldn't find peers for <span class="text-break">${torrent.infoHash}</span>! Try a torrent with more seeders.`,
|
|
title: 'Search Failed',
|
|
alertType: 'alert-danger',
|
|
fillType: ''
|
|
})
|
|
}
|
|
})
|
|
client.nowPlaying = { name: 'Miru' }
|
|
|
|
window.client = client
|
|
|
|
window.onbeforeunload = () => { return '' }
|
|
if (_util_js__WEBPACK_IMPORTED_MODULE_1__.searchParams.get('file')) client.playTorrent(_util_js__WEBPACK_IMPORTED_MODULE_1__.searchParams.get('file'))
|
|
|
|
queueMicrotask(_interface_js__WEBPACK_IMPORTED_MODULE_5__.initMenu)
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./app/js/rss.js":
|
|
/*!***********************!*\
|
|
!*** ./app/js/rss.js ***!
|
|
\***********************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "nyaaRss": () => (/* binding */ nyaaRss),
|
|
/* harmony export */ "releasesRss": () => (/* binding */ releasesRss),
|
|
/* harmony export */ "getRSSurl": () => (/* binding */ getRSSurl)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _settings_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./settings.js */ "./app/js/settings.js");
|
|
/* harmony import */ var _interface_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./interface.js */ "./app/js/interface.js");
|
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util.js */ "./app/js/util.js");
|
|
/* harmony import */ var _main_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./main.js */ "./app/js/main.js");
|
|
/* harmony import */ var halfmoon__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! halfmoon */ "halfmoon");
|
|
/* harmony import */ var halfmoon__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(halfmoon__WEBPACK_IMPORTED_MODULE_4__);
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
/* eslint-env browser */
|
|
/* global torrent4list */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const exclusions = {
|
|
edge: ['DTS'],
|
|
chromium: ['DTS', 'AC3', 'HEVC', 'x265', 'H.265'],
|
|
firefox: ['DTS', 'AC3', 'HEVC', 'x265', 'H.265', '.3gp', '.mkv']
|
|
}
|
|
if (!('audioTracks' in HTMLVideoElement.prototype)) {
|
|
exclusions[_util_js__WEBPACK_IMPORTED_MODULE_2__.userBrowser].push('mutli audio', 'dual audio')
|
|
}
|
|
|
|
async function nyaaRss (media, episode) {
|
|
const frag = document.createDocumentFragment()
|
|
const ep = (media.status === 'FINISHED' && _settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent9) ? `"01-${media.episodes}"|"01~${media.episodes}"|"Batch"|"Complete"|"+${episode}+"|"+${episode}v"` : `"+${episode}+"|"+${episode}v"`
|
|
const url = new URL(`https://meowinjapanese.cf/?page=rss&c=1_2&f=${_settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent3 === true ? 2 : 0}&s=seeders&o=desc&q=(${[...new Set(Object.values(media.title).concat(media.synonyms).filter(name => name != null))].join(')|(')})${ep}"${_settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent1}"-(${exclusions[_util_js__WEBPACK_IMPORTED_MODULE_2__.userBrowser].join('|')})`)
|
|
await fetch(url).then(res => {
|
|
res.text().then((xmlTxt) => {
|
|
try {
|
|
const doc = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.DOMPARSER)(xmlTxt, 'text/xml')
|
|
if (_settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent2 && doc.querySelector('infoHash')) {
|
|
_main_js__WEBPACK_IMPORTED_MODULE_3__.client.playTorrent(doc.querySelector('infoHash').textContent, { media: media, episode: episode })
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_4___default().toggleModal('tsearch')
|
|
}
|
|
doc.querySelectorAll('item').forEach((item, index) => {
|
|
const i = item.querySelectorAll('*')
|
|
const template = document.createElement('tr')
|
|
template.innerHTML += `
|
|
<th>${(index + 1)}</th>
|
|
<td>${i[0].textContent}</td>
|
|
<td>${i[10].textContent}</td>
|
|
<td>${i[4].textContent}</td>
|
|
<td>${i[5].textContent}</td>
|
|
<td>${i[6].textContent}</td>
|
|
<td class="pointer">Play</td>`
|
|
template.onclick = () => {
|
|
_main_js__WEBPACK_IMPORTED_MODULE_3__.client.playTorrent(i[7].textContent, { media: media, episode: episode })
|
|
halfmoon__WEBPACK_IMPORTED_MODULE_4___default().hideModal('tsearch')
|
|
}
|
|
frag.appendChild(template)
|
|
})
|
|
} catch (e) {
|
|
console.error(e)
|
|
}
|
|
})
|
|
})
|
|
return frag
|
|
}
|
|
|
|
async function releasesRss (limit) {
|
|
return await fetch(getRSSurl()).then(res => res.text().then(async xmlTxt => {
|
|
return await (0,_interface_js__WEBPACK_IMPORTED_MODULE_1__.releasesCards)((0,_util_js__WEBPACK_IMPORTED_MODULE_2__.DOMPARSER)(xmlTxt, 'text/xml').querySelectorAll('item'), limit)
|
|
}))
|
|
}
|
|
|
|
function getRSSurl () {
|
|
if (Object.values(torrent4list.options).filter(item => item.value === _settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent4)[0]) {
|
|
return _settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent4 === 'Erai-raws' ? new URL(Object.values(torrent4list.options).filter(item => item.value === _settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent4)[0].innerHTML + _settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent1 + '-magnet') : new URL(Object.values(torrent4list.options).filter(item => item.value === _settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent4)[0].innerHTML + _settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent1)
|
|
} else {
|
|
return _settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent4 + _settings_js__WEBPACK_IMPORTED_MODULE_0__.settings.torrent1 // add custom RSS
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./app/js/settings.js":
|
|
/*!****************************!*\
|
|
!*** ./app/js/settings.js ***!
|
|
\****************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "settingsElements": () => (/* binding */ settingsElements),
|
|
/* harmony export */ "settings": () => (/* binding */ settings)
|
|
/* harmony export */ });
|
|
/* eslint-env browser */
|
|
/* global volume, player2, player3, player5, player6, player10, subtitle1, subtitle3, torrent1, torrent2, torrent3, torrent4, torrent5, torrent7, torrent8, torrent9, other1, other2, setRes, settingsTab, regProtButton, clearRelCache */
|
|
const settingsElements = [
|
|
volume, player2, player3, player5, player6, player10, subtitle1, subtitle3, torrent1, torrent2, torrent3, torrent4, torrent5, torrent7, torrent8, torrent9, other1, other2
|
|
]
|
|
setRes.addEventListener('click', restoreDefaults)
|
|
settingsTab.addEventListener('click', applySettingsTimeout)
|
|
volume.addEventListener('click', applySettingsTimeout)
|
|
regProtButton.addEventListener('click', registerProtocol)
|
|
const settings = JSON.parse(localStorage.getItem('settings')) || {}
|
|
function restoreDefaults () {
|
|
localStorage.removeItem('settings')
|
|
location.reload()
|
|
}
|
|
let applyTimeout
|
|
function applySettingsTimeout () {
|
|
clearTimeout(applyTimeout)
|
|
applyTimeout = setTimeout(saveSettings, 500)
|
|
}
|
|
function saveSettings () {
|
|
for (const element of settingsElements) {
|
|
settings[element.id] = element.type === 'checkbox' ? element.checked : element.value
|
|
}
|
|
localStorage.setItem('settings', JSON.stringify(settings))
|
|
}
|
|
function registerProtocol () {
|
|
if ('registerProtocolHandler' in navigator) {
|
|
navigator.registerProtocolHandler(
|
|
'magnet',
|
|
`${location.href.replace(location.hash, '')}#home&file=%s`,
|
|
'Miru'
|
|
)
|
|
}
|
|
}
|
|
|
|
if (!Object.values(settings).length) {
|
|
saveSettings()
|
|
location.reload()
|
|
}
|
|
clearRelCache.onclick = () => {
|
|
localStorage.removeItem('relations')
|
|
}
|
|
|
|
for (const setting of Object.entries(settings)) {
|
|
const settingElement = settingsElements.filter(e => e.id === setting[0])[0]
|
|
if (settingElement) settingElement.type === 'checkbox' ? settingElement.checked = setting[1] : settingElement.value = setting[1]
|
|
}
|
|
|
|
other1.onclick = () => Notification.requestPermission().then(perm => { perm === 'denied' ? other1.checked = false : other1.checked = true })
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./app/js/util.js":
|
|
/*!************************!*\
|
|
!*** ./app/js/util.js ***!
|
|
\************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "searchParams": () => (/* binding */ searchParams),
|
|
/* harmony export */ "userBrowser": () => (/* binding */ userBrowser),
|
|
/* harmony export */ "countdown": () => (/* binding */ countdown),
|
|
/* harmony export */ "DOMPARSER": () => (/* binding */ DOMPARSER)
|
|
/* harmony export */ });
|
|
/* harmony import */ var halfmoon__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! halfmoon */ "halfmoon");
|
|
/* harmony import */ var halfmoon__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(halfmoon__WEBPACK_IMPORTED_MODULE_0__);
|
|
/* eslint-env browser */
|
|
|
|
;(halfmoon__WEBPACK_IMPORTED_MODULE_0___default().showModal) = id => {
|
|
const t = document.getElementById(id)
|
|
t && t.classList.add('show')
|
|
}
|
|
;(halfmoon__WEBPACK_IMPORTED_MODULE_0___default().hideModal) = id => {
|
|
const t = document.getElementById(id)
|
|
t && t.classList.remove('show')
|
|
}
|
|
const searchParams = new URLSearchParams(location.href)
|
|
if (searchParams.get('access_token')) {
|
|
localStorage.setItem('ALtoken', searchParams.get('access_token'))
|
|
window.location = '/app/#settingsTab'
|
|
}
|
|
const userBrowser = (() => {
|
|
if (window.chrome) {
|
|
return (navigator.userAgent.indexOf('Edg') !== -1) ? 'edge' : 'chromium'
|
|
}
|
|
return 'firefox'
|
|
})()
|
|
function countdown (s) {
|
|
const d = Math.floor(s / (3600 * 24))
|
|
s -= d * 3600 * 24
|
|
const h = Math.floor(s / 3600)
|
|
s -= h * 3600
|
|
const m = Math.floor(s / 60)
|
|
s -= m * 60
|
|
const tmp = []
|
|
if (d) tmp.push(d + 'd')
|
|
if (d || h) tmp.push(h + 'h')
|
|
if (d || h || m) tmp.push(m + 'm')
|
|
return tmp.join(' ')
|
|
}
|
|
|
|
const DOMPARSER = new DOMParser().parseFromString.bind(new DOMParser())
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/addr-to-ip-port/index.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/addr-to-ip-port/index.js ***!
|
|
\***********************************************/
|
|
/***/ ((module) => {
|
|
|
|
const ADDR_RE = /^\[?([^\]]+)\]?:(\d+)$/ // ipv4/ipv6/hostname + port
|
|
|
|
let cache = {}
|
|
|
|
// reset cache when it gets to 100,000 elements (~ 600KB of ipv4 addresses)
|
|
// so it will not grow to consume all memory in long-running processes
|
|
let size = 0
|
|
|
|
module.exports = function addrToIPPort (addr) {
|
|
if (size === 100000) module.exports.reset()
|
|
if (!cache[addr]) {
|
|
const m = ADDR_RE.exec(addr)
|
|
if (!m) throw new Error(`invalid addr: ${addr}`)
|
|
cache[addr] = [ m[1], Number(m[2]) ]
|
|
size += 1
|
|
}
|
|
return cache[addr]
|
|
}
|
|
|
|
module.exports.reset = function reset () {
|
|
cache = {}
|
|
size = 0
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1.js ***!
|
|
\******************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const asn1 = exports;
|
|
|
|
asn1.bignum = __webpack_require__(/*! bn.js */ "./node_modules/asn1.js/node_modules/bn.js/lib/bn.js");
|
|
|
|
asn1.define = __webpack_require__(/*! ./asn1/api */ "./node_modules/asn1.js/lib/asn1/api.js").define;
|
|
asn1.base = __webpack_require__(/*! ./asn1/base */ "./node_modules/asn1.js/lib/asn1/base/index.js");
|
|
asn1.constants = __webpack_require__(/*! ./asn1/constants */ "./node_modules/asn1.js/lib/asn1/constants/index.js");
|
|
asn1.decoders = __webpack_require__(/*! ./asn1/decoders */ "./node_modules/asn1.js/lib/asn1/decoders/index.js");
|
|
asn1.encoders = __webpack_require__(/*! ./asn1/encoders */ "./node_modules/asn1.js/lib/asn1/encoders/index.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/api.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/api.js ***!
|
|
\**********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const encoders = __webpack_require__(/*! ./encoders */ "./node_modules/asn1.js/lib/asn1/encoders/index.js");
|
|
const decoders = __webpack_require__(/*! ./decoders */ "./node_modules/asn1.js/lib/asn1/decoders/index.js");
|
|
const inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
|
|
const api = exports;
|
|
|
|
api.define = function define(name, body) {
|
|
return new Entity(name, body);
|
|
};
|
|
|
|
function Entity(name, body) {
|
|
this.name = name;
|
|
this.body = body;
|
|
|
|
this.decoders = {};
|
|
this.encoders = {};
|
|
}
|
|
|
|
Entity.prototype._createNamed = function createNamed(Base) {
|
|
const name = this.name;
|
|
|
|
function Generated(entity) {
|
|
this._initNamed(entity, name);
|
|
}
|
|
inherits(Generated, Base);
|
|
Generated.prototype._initNamed = function _initNamed(entity, name) {
|
|
Base.call(this, entity, name);
|
|
};
|
|
|
|
return new Generated(this);
|
|
};
|
|
|
|
Entity.prototype._getDecoder = function _getDecoder(enc) {
|
|
enc = enc || 'der';
|
|
// Lazily create decoder
|
|
if (!this.decoders.hasOwnProperty(enc))
|
|
this.decoders[enc] = this._createNamed(decoders[enc]);
|
|
return this.decoders[enc];
|
|
};
|
|
|
|
Entity.prototype.decode = function decode(data, enc, options) {
|
|
return this._getDecoder(enc).decode(data, options);
|
|
};
|
|
|
|
Entity.prototype._getEncoder = function _getEncoder(enc) {
|
|
enc = enc || 'der';
|
|
// Lazily create encoder
|
|
if (!this.encoders.hasOwnProperty(enc))
|
|
this.encoders[enc] = this._createNamed(encoders[enc]);
|
|
return this.encoders[enc];
|
|
};
|
|
|
|
Entity.prototype.encode = function encode(data, enc, /* internal */ reporter) {
|
|
return this._getEncoder(enc).encode(data, reporter);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/base/buffer.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/base/buffer.js ***!
|
|
\******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
const Reporter = __webpack_require__(/*! ../base/reporter */ "./node_modules/asn1.js/lib/asn1/base/reporter.js").Reporter;
|
|
const Buffer = __webpack_require__(/*! safer-buffer */ "./node_modules/safer-buffer/safer.js").Buffer;
|
|
|
|
function DecoderBuffer(base, options) {
|
|
Reporter.call(this, options);
|
|
if (!Buffer.isBuffer(base)) {
|
|
this.error('Input not Buffer');
|
|
return;
|
|
}
|
|
|
|
this.base = base;
|
|
this.offset = 0;
|
|
this.length = base.length;
|
|
}
|
|
inherits(DecoderBuffer, Reporter);
|
|
exports.DecoderBuffer = DecoderBuffer;
|
|
|
|
DecoderBuffer.isDecoderBuffer = function isDecoderBuffer(data) {
|
|
if (data instanceof DecoderBuffer) {
|
|
return true;
|
|
}
|
|
|
|
// Or accept compatible API
|
|
const isCompatible = typeof data === 'object' &&
|
|
Buffer.isBuffer(data.base) &&
|
|
data.constructor.name === 'DecoderBuffer' &&
|
|
typeof data.offset === 'number' &&
|
|
typeof data.length === 'number' &&
|
|
typeof data.save === 'function' &&
|
|
typeof data.restore === 'function' &&
|
|
typeof data.isEmpty === 'function' &&
|
|
typeof data.readUInt8 === 'function' &&
|
|
typeof data.skip === 'function' &&
|
|
typeof data.raw === 'function';
|
|
|
|
return isCompatible;
|
|
};
|
|
|
|
DecoderBuffer.prototype.save = function save() {
|
|
return { offset: this.offset, reporter: Reporter.prototype.save.call(this) };
|
|
};
|
|
|
|
DecoderBuffer.prototype.restore = function restore(save) {
|
|
// Return skipped data
|
|
const res = new DecoderBuffer(this.base);
|
|
res.offset = save.offset;
|
|
res.length = this.offset;
|
|
|
|
this.offset = save.offset;
|
|
Reporter.prototype.restore.call(this, save.reporter);
|
|
|
|
return res;
|
|
};
|
|
|
|
DecoderBuffer.prototype.isEmpty = function isEmpty() {
|
|
return this.offset === this.length;
|
|
};
|
|
|
|
DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) {
|
|
if (this.offset + 1 <= this.length)
|
|
return this.base.readUInt8(this.offset++, true);
|
|
else
|
|
return this.error(fail || 'DecoderBuffer overrun');
|
|
};
|
|
|
|
DecoderBuffer.prototype.skip = function skip(bytes, fail) {
|
|
if (!(this.offset + bytes <= this.length))
|
|
return this.error(fail || 'DecoderBuffer overrun');
|
|
|
|
const res = new DecoderBuffer(this.base);
|
|
|
|
// Share reporter state
|
|
res._reporterState = this._reporterState;
|
|
|
|
res.offset = this.offset;
|
|
res.length = this.offset + bytes;
|
|
this.offset += bytes;
|
|
return res;
|
|
};
|
|
|
|
DecoderBuffer.prototype.raw = function raw(save) {
|
|
return this.base.slice(save ? save.offset : this.offset, this.length);
|
|
};
|
|
|
|
function EncoderBuffer(value, reporter) {
|
|
if (Array.isArray(value)) {
|
|
this.length = 0;
|
|
this.value = value.map(function(item) {
|
|
if (!EncoderBuffer.isEncoderBuffer(item))
|
|
item = new EncoderBuffer(item, reporter);
|
|
this.length += item.length;
|
|
return item;
|
|
}, this);
|
|
} else if (typeof value === 'number') {
|
|
if (!(0 <= value && value <= 0xff))
|
|
return reporter.error('non-byte EncoderBuffer value');
|
|
this.value = value;
|
|
this.length = 1;
|
|
} else if (typeof value === 'string') {
|
|
this.value = value;
|
|
this.length = Buffer.byteLength(value);
|
|
} else if (Buffer.isBuffer(value)) {
|
|
this.value = value;
|
|
this.length = value.length;
|
|
} else {
|
|
return reporter.error('Unsupported type: ' + typeof value);
|
|
}
|
|
}
|
|
exports.EncoderBuffer = EncoderBuffer;
|
|
|
|
EncoderBuffer.isEncoderBuffer = function isEncoderBuffer(data) {
|
|
if (data instanceof EncoderBuffer) {
|
|
return true;
|
|
}
|
|
|
|
// Or accept compatible API
|
|
const isCompatible = typeof data === 'object' &&
|
|
data.constructor.name === 'EncoderBuffer' &&
|
|
typeof data.length === 'number' &&
|
|
typeof data.join === 'function';
|
|
|
|
return isCompatible;
|
|
};
|
|
|
|
EncoderBuffer.prototype.join = function join(out, offset) {
|
|
if (!out)
|
|
out = Buffer.alloc(this.length);
|
|
if (!offset)
|
|
offset = 0;
|
|
|
|
if (this.length === 0)
|
|
return out;
|
|
|
|
if (Array.isArray(this.value)) {
|
|
this.value.forEach(function(item) {
|
|
item.join(out, offset);
|
|
offset += item.length;
|
|
});
|
|
} else {
|
|
if (typeof this.value === 'number')
|
|
out[offset] = this.value;
|
|
else if (typeof this.value === 'string')
|
|
out.write(this.value, offset);
|
|
else if (Buffer.isBuffer(this.value))
|
|
this.value.copy(out, offset);
|
|
offset += this.length;
|
|
}
|
|
|
|
return out;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/base/index.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/base/index.js ***!
|
|
\*****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const base = exports;
|
|
|
|
base.Reporter = __webpack_require__(/*! ./reporter */ "./node_modules/asn1.js/lib/asn1/base/reporter.js").Reporter;
|
|
base.DecoderBuffer = __webpack_require__(/*! ./buffer */ "./node_modules/asn1.js/lib/asn1/base/buffer.js").DecoderBuffer;
|
|
base.EncoderBuffer = __webpack_require__(/*! ./buffer */ "./node_modules/asn1.js/lib/asn1/base/buffer.js").EncoderBuffer;
|
|
base.Node = __webpack_require__(/*! ./node */ "./node_modules/asn1.js/lib/asn1/base/node.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/base/node.js":
|
|
/*!****************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/base/node.js ***!
|
|
\****************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const Reporter = __webpack_require__(/*! ../base/reporter */ "./node_modules/asn1.js/lib/asn1/base/reporter.js").Reporter;
|
|
const EncoderBuffer = __webpack_require__(/*! ../base/buffer */ "./node_modules/asn1.js/lib/asn1/base/buffer.js").EncoderBuffer;
|
|
const DecoderBuffer = __webpack_require__(/*! ../base/buffer */ "./node_modules/asn1.js/lib/asn1/base/buffer.js").DecoderBuffer;
|
|
const assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
|
|
// Supported tags
|
|
const tags = [
|
|
'seq', 'seqof', 'set', 'setof', 'objid', 'bool',
|
|
'gentime', 'utctime', 'null_', 'enum', 'int', 'objDesc',
|
|
'bitstr', 'bmpstr', 'charstr', 'genstr', 'graphstr', 'ia5str', 'iso646str',
|
|
'numstr', 'octstr', 'printstr', 't61str', 'unistr', 'utf8str', 'videostr'
|
|
];
|
|
|
|
// Public methods list
|
|
const methods = [
|
|
'key', 'obj', 'use', 'optional', 'explicit', 'implicit', 'def', 'choice',
|
|
'any', 'contains'
|
|
].concat(tags);
|
|
|
|
// Overrided methods list
|
|
const overrided = [
|
|
'_peekTag', '_decodeTag', '_use',
|
|
'_decodeStr', '_decodeObjid', '_decodeTime',
|
|
'_decodeNull', '_decodeInt', '_decodeBool', '_decodeList',
|
|
|
|
'_encodeComposite', '_encodeStr', '_encodeObjid', '_encodeTime',
|
|
'_encodeNull', '_encodeInt', '_encodeBool'
|
|
];
|
|
|
|
function Node(enc, parent, name) {
|
|
const state = {};
|
|
this._baseState = state;
|
|
|
|
state.name = name;
|
|
state.enc = enc;
|
|
|
|
state.parent = parent || null;
|
|
state.children = null;
|
|
|
|
// State
|
|
state.tag = null;
|
|
state.args = null;
|
|
state.reverseArgs = null;
|
|
state.choice = null;
|
|
state.optional = false;
|
|
state.any = false;
|
|
state.obj = false;
|
|
state.use = null;
|
|
state.useDecoder = null;
|
|
state.key = null;
|
|
state['default'] = null;
|
|
state.explicit = null;
|
|
state.implicit = null;
|
|
state.contains = null;
|
|
|
|
// Should create new instance on each method
|
|
if (!state.parent) {
|
|
state.children = [];
|
|
this._wrap();
|
|
}
|
|
}
|
|
module.exports = Node;
|
|
|
|
const stateProps = [
|
|
'enc', 'parent', 'children', 'tag', 'args', 'reverseArgs', 'choice',
|
|
'optional', 'any', 'obj', 'use', 'alteredUse', 'key', 'default', 'explicit',
|
|
'implicit', 'contains'
|
|
];
|
|
|
|
Node.prototype.clone = function clone() {
|
|
const state = this._baseState;
|
|
const cstate = {};
|
|
stateProps.forEach(function(prop) {
|
|
cstate[prop] = state[prop];
|
|
});
|
|
const res = new this.constructor(cstate.parent);
|
|
res._baseState = cstate;
|
|
return res;
|
|
};
|
|
|
|
Node.prototype._wrap = function wrap() {
|
|
const state = this._baseState;
|
|
methods.forEach(function(method) {
|
|
this[method] = function _wrappedMethod() {
|
|
const clone = new this.constructor(this);
|
|
state.children.push(clone);
|
|
return clone[method].apply(clone, arguments);
|
|
};
|
|
}, this);
|
|
};
|
|
|
|
Node.prototype._init = function init(body) {
|
|
const state = this._baseState;
|
|
|
|
assert(state.parent === null);
|
|
body.call(this);
|
|
|
|
// Filter children
|
|
state.children = state.children.filter(function(child) {
|
|
return child._baseState.parent === this;
|
|
}, this);
|
|
assert.equal(state.children.length, 1, 'Root node can have only one child');
|
|
};
|
|
|
|
Node.prototype._useArgs = function useArgs(args) {
|
|
const state = this._baseState;
|
|
|
|
// Filter children and args
|
|
const children = args.filter(function(arg) {
|
|
return arg instanceof this.constructor;
|
|
}, this);
|
|
args = args.filter(function(arg) {
|
|
return !(arg instanceof this.constructor);
|
|
}, this);
|
|
|
|
if (children.length !== 0) {
|
|
assert(state.children === null);
|
|
state.children = children;
|
|
|
|
// Replace parent to maintain backward link
|
|
children.forEach(function(child) {
|
|
child._baseState.parent = this;
|
|
}, this);
|
|
}
|
|
if (args.length !== 0) {
|
|
assert(state.args === null);
|
|
state.args = args;
|
|
state.reverseArgs = args.map(function(arg) {
|
|
if (typeof arg !== 'object' || arg.constructor !== Object)
|
|
return arg;
|
|
|
|
const res = {};
|
|
Object.keys(arg).forEach(function(key) {
|
|
if (key == (key | 0))
|
|
key |= 0;
|
|
const value = arg[key];
|
|
res[value] = key;
|
|
});
|
|
return res;
|
|
});
|
|
}
|
|
};
|
|
|
|
//
|
|
// Overrided methods
|
|
//
|
|
|
|
overrided.forEach(function(method) {
|
|
Node.prototype[method] = function _overrided() {
|
|
const state = this._baseState;
|
|
throw new Error(method + ' not implemented for encoding: ' + state.enc);
|
|
};
|
|
});
|
|
|
|
//
|
|
// Public methods
|
|
//
|
|
|
|
tags.forEach(function(tag) {
|
|
Node.prototype[tag] = function _tagMethod() {
|
|
const state = this._baseState;
|
|
const args = Array.prototype.slice.call(arguments);
|
|
|
|
assert(state.tag === null);
|
|
state.tag = tag;
|
|
|
|
this._useArgs(args);
|
|
|
|
return this;
|
|
};
|
|
});
|
|
|
|
Node.prototype.use = function use(item) {
|
|
assert(item);
|
|
const state = this._baseState;
|
|
|
|
assert(state.use === null);
|
|
state.use = item;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.optional = function optional() {
|
|
const state = this._baseState;
|
|
|
|
state.optional = true;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.def = function def(val) {
|
|
const state = this._baseState;
|
|
|
|
assert(state['default'] === null);
|
|
state['default'] = val;
|
|
state.optional = true;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.explicit = function explicit(num) {
|
|
const state = this._baseState;
|
|
|
|
assert(state.explicit === null && state.implicit === null);
|
|
state.explicit = num;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.implicit = function implicit(num) {
|
|
const state = this._baseState;
|
|
|
|
assert(state.explicit === null && state.implicit === null);
|
|
state.implicit = num;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.obj = function obj() {
|
|
const state = this._baseState;
|
|
const args = Array.prototype.slice.call(arguments);
|
|
|
|
state.obj = true;
|
|
|
|
if (args.length !== 0)
|
|
this._useArgs(args);
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.key = function key(newKey) {
|
|
const state = this._baseState;
|
|
|
|
assert(state.key === null);
|
|
state.key = newKey;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.any = function any() {
|
|
const state = this._baseState;
|
|
|
|
state.any = true;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.choice = function choice(obj) {
|
|
const state = this._baseState;
|
|
|
|
assert(state.choice === null);
|
|
state.choice = obj;
|
|
this._useArgs(Object.keys(obj).map(function(key) {
|
|
return obj[key];
|
|
}));
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.contains = function contains(item) {
|
|
const state = this._baseState;
|
|
|
|
assert(state.use === null);
|
|
state.contains = item;
|
|
|
|
return this;
|
|
};
|
|
|
|
//
|
|
// Decoding
|
|
//
|
|
|
|
Node.prototype._decode = function decode(input, options) {
|
|
const state = this._baseState;
|
|
|
|
// Decode root node
|
|
if (state.parent === null)
|
|
return input.wrapResult(state.children[0]._decode(input, options));
|
|
|
|
let result = state['default'];
|
|
let present = true;
|
|
|
|
let prevKey = null;
|
|
if (state.key !== null)
|
|
prevKey = input.enterKey(state.key);
|
|
|
|
// Check if tag is there
|
|
if (state.optional) {
|
|
let tag = null;
|
|
if (state.explicit !== null)
|
|
tag = state.explicit;
|
|
else if (state.implicit !== null)
|
|
tag = state.implicit;
|
|
else if (state.tag !== null)
|
|
tag = state.tag;
|
|
|
|
if (tag === null && !state.any) {
|
|
// Trial and Error
|
|
const save = input.save();
|
|
try {
|
|
if (state.choice === null)
|
|
this._decodeGeneric(state.tag, input, options);
|
|
else
|
|
this._decodeChoice(input, options);
|
|
present = true;
|
|
} catch (e) {
|
|
present = false;
|
|
}
|
|
input.restore(save);
|
|
} else {
|
|
present = this._peekTag(input, tag, state.any);
|
|
|
|
if (input.isError(present))
|
|
return present;
|
|
}
|
|
}
|
|
|
|
// Push object on stack
|
|
let prevObj;
|
|
if (state.obj && present)
|
|
prevObj = input.enterObject();
|
|
|
|
if (present) {
|
|
// Unwrap explicit values
|
|
if (state.explicit !== null) {
|
|
const explicit = this._decodeTag(input, state.explicit);
|
|
if (input.isError(explicit))
|
|
return explicit;
|
|
input = explicit;
|
|
}
|
|
|
|
const start = input.offset;
|
|
|
|
// Unwrap implicit and normal values
|
|
if (state.use === null && state.choice === null) {
|
|
let save;
|
|
if (state.any)
|
|
save = input.save();
|
|
const body = this._decodeTag(
|
|
input,
|
|
state.implicit !== null ? state.implicit : state.tag,
|
|
state.any
|
|
);
|
|
if (input.isError(body))
|
|
return body;
|
|
|
|
if (state.any)
|
|
result = input.raw(save);
|
|
else
|
|
input = body;
|
|
}
|
|
|
|
if (options && options.track && state.tag !== null)
|
|
options.track(input.path(), start, input.length, 'tagged');
|
|
|
|
if (options && options.track && state.tag !== null)
|
|
options.track(input.path(), input.offset, input.length, 'content');
|
|
|
|
// Select proper method for tag
|
|
if (state.any) {
|
|
// no-op
|
|
} else if (state.choice === null) {
|
|
result = this._decodeGeneric(state.tag, input, options);
|
|
} else {
|
|
result = this._decodeChoice(input, options);
|
|
}
|
|
|
|
if (input.isError(result))
|
|
return result;
|
|
|
|
// Decode children
|
|
if (!state.any && state.choice === null && state.children !== null) {
|
|
state.children.forEach(function decodeChildren(child) {
|
|
// NOTE: We are ignoring errors here, to let parser continue with other
|
|
// parts of encoded data
|
|
child._decode(input, options);
|
|
});
|
|
}
|
|
|
|
// Decode contained/encoded by schema, only in bit or octet strings
|
|
if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) {
|
|
const data = new DecoderBuffer(result);
|
|
result = this._getUse(state.contains, input._reporterState.obj)
|
|
._decode(data, options);
|
|
}
|
|
}
|
|
|
|
// Pop object
|
|
if (state.obj && present)
|
|
result = input.leaveObject(prevObj);
|
|
|
|
// Set key
|
|
if (state.key !== null && (result !== null || present === true))
|
|
input.leaveKey(prevKey, state.key, result);
|
|
else if (prevKey !== null)
|
|
input.exitKey(prevKey);
|
|
|
|
return result;
|
|
};
|
|
|
|
Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) {
|
|
const state = this._baseState;
|
|
|
|
if (tag === 'seq' || tag === 'set')
|
|
return null;
|
|
if (tag === 'seqof' || tag === 'setof')
|
|
return this._decodeList(input, tag, state.args[0], options);
|
|
else if (/str$/.test(tag))
|
|
return this._decodeStr(input, tag, options);
|
|
else if (tag === 'objid' && state.args)
|
|
return this._decodeObjid(input, state.args[0], state.args[1], options);
|
|
else if (tag === 'objid')
|
|
return this._decodeObjid(input, null, null, options);
|
|
else if (tag === 'gentime' || tag === 'utctime')
|
|
return this._decodeTime(input, tag, options);
|
|
else if (tag === 'null_')
|
|
return this._decodeNull(input, options);
|
|
else if (tag === 'bool')
|
|
return this._decodeBool(input, options);
|
|
else if (tag === 'objDesc')
|
|
return this._decodeStr(input, tag, options);
|
|
else if (tag === 'int' || tag === 'enum')
|
|
return this._decodeInt(input, state.args && state.args[0], options);
|
|
|
|
if (state.use !== null) {
|
|
return this._getUse(state.use, input._reporterState.obj)
|
|
._decode(input, options);
|
|
} else {
|
|
return input.error('unknown tag: ' + tag);
|
|
}
|
|
};
|
|
|
|
Node.prototype._getUse = function _getUse(entity, obj) {
|
|
|
|
const state = this._baseState;
|
|
// Create altered use decoder if implicit is set
|
|
state.useDecoder = this._use(entity, obj);
|
|
assert(state.useDecoder._baseState.parent === null);
|
|
state.useDecoder = state.useDecoder._baseState.children[0];
|
|
if (state.implicit !== state.useDecoder._baseState.implicit) {
|
|
state.useDecoder = state.useDecoder.clone();
|
|
state.useDecoder._baseState.implicit = state.implicit;
|
|
}
|
|
return state.useDecoder;
|
|
};
|
|
|
|
Node.prototype._decodeChoice = function decodeChoice(input, options) {
|
|
const state = this._baseState;
|
|
let result = null;
|
|
let match = false;
|
|
|
|
Object.keys(state.choice).some(function(key) {
|
|
const save = input.save();
|
|
const node = state.choice[key];
|
|
try {
|
|
const value = node._decode(input, options);
|
|
if (input.isError(value))
|
|
return false;
|
|
|
|
result = { type: key, value: value };
|
|
match = true;
|
|
} catch (e) {
|
|
input.restore(save);
|
|
return false;
|
|
}
|
|
return true;
|
|
}, this);
|
|
|
|
if (!match)
|
|
return input.error('Choice not matched');
|
|
|
|
return result;
|
|
};
|
|
|
|
//
|
|
// Encoding
|
|
//
|
|
|
|
Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) {
|
|
return new EncoderBuffer(data, this.reporter);
|
|
};
|
|
|
|
Node.prototype._encode = function encode(data, reporter, parent) {
|
|
const state = this._baseState;
|
|
if (state['default'] !== null && state['default'] === data)
|
|
return;
|
|
|
|
const result = this._encodeValue(data, reporter, parent);
|
|
if (result === undefined)
|
|
return;
|
|
|
|
if (this._skipDefault(result, reporter, parent))
|
|
return;
|
|
|
|
return result;
|
|
};
|
|
|
|
Node.prototype._encodeValue = function encode(data, reporter, parent) {
|
|
const state = this._baseState;
|
|
|
|
// Decode root node
|
|
if (state.parent === null)
|
|
return state.children[0]._encode(data, reporter || new Reporter());
|
|
|
|
let result = null;
|
|
|
|
// Set reporter to share it with a child class
|
|
this.reporter = reporter;
|
|
|
|
// Check if data is there
|
|
if (state.optional && data === undefined) {
|
|
if (state['default'] !== null)
|
|
data = state['default'];
|
|
else
|
|
return;
|
|
}
|
|
|
|
// Encode children first
|
|
let content = null;
|
|
let primitive = false;
|
|
if (state.any) {
|
|
// Anything that was given is translated to buffer
|
|
result = this._createEncoderBuffer(data);
|
|
} else if (state.choice) {
|
|
result = this._encodeChoice(data, reporter);
|
|
} else if (state.contains) {
|
|
content = this._getUse(state.contains, parent)._encode(data, reporter);
|
|
primitive = true;
|
|
} else if (state.children) {
|
|
content = state.children.map(function(child) {
|
|
if (child._baseState.tag === 'null_')
|
|
return child._encode(null, reporter, data);
|
|
|
|
if (child._baseState.key === null)
|
|
return reporter.error('Child should have a key');
|
|
const prevKey = reporter.enterKey(child._baseState.key);
|
|
|
|
if (typeof data !== 'object')
|
|
return reporter.error('Child expected, but input is not object');
|
|
|
|
const res = child._encode(data[child._baseState.key], reporter, data);
|
|
reporter.leaveKey(prevKey);
|
|
|
|
return res;
|
|
}, this).filter(function(child) {
|
|
return child;
|
|
});
|
|
content = this._createEncoderBuffer(content);
|
|
} else {
|
|
if (state.tag === 'seqof' || state.tag === 'setof') {
|
|
// TODO(indutny): this should be thrown on DSL level
|
|
if (!(state.args && state.args.length === 1))
|
|
return reporter.error('Too many args for : ' + state.tag);
|
|
|
|
if (!Array.isArray(data))
|
|
return reporter.error('seqof/setof, but data is not Array');
|
|
|
|
const child = this.clone();
|
|
child._baseState.implicit = null;
|
|
content = this._createEncoderBuffer(data.map(function(item) {
|
|
const state = this._baseState;
|
|
|
|
return this._getUse(state.args[0], data)._encode(item, reporter);
|
|
}, child));
|
|
} else if (state.use !== null) {
|
|
result = this._getUse(state.use, parent)._encode(data, reporter);
|
|
} else {
|
|
content = this._encodePrimitive(state.tag, data);
|
|
primitive = true;
|
|
}
|
|
}
|
|
|
|
// Encode data itself
|
|
if (!state.any && state.choice === null) {
|
|
const tag = state.implicit !== null ? state.implicit : state.tag;
|
|
const cls = state.implicit === null ? 'universal' : 'context';
|
|
|
|
if (tag === null) {
|
|
if (state.use === null)
|
|
reporter.error('Tag could be omitted only for .use()');
|
|
} else {
|
|
if (state.use === null)
|
|
result = this._encodeComposite(tag, primitive, cls, content);
|
|
}
|
|
}
|
|
|
|
// Wrap in explicit
|
|
if (state.explicit !== null)
|
|
result = this._encodeComposite(state.explicit, false, 'context', result);
|
|
|
|
return result;
|
|
};
|
|
|
|
Node.prototype._encodeChoice = function encodeChoice(data, reporter) {
|
|
const state = this._baseState;
|
|
|
|
const node = state.choice[data.type];
|
|
if (!node) {
|
|
assert(
|
|
false,
|
|
data.type + ' not found in ' +
|
|
JSON.stringify(Object.keys(state.choice)));
|
|
}
|
|
return node._encode(data.value, reporter);
|
|
};
|
|
|
|
Node.prototype._encodePrimitive = function encodePrimitive(tag, data) {
|
|
const state = this._baseState;
|
|
|
|
if (/str$/.test(tag))
|
|
return this._encodeStr(data, tag);
|
|
else if (tag === 'objid' && state.args)
|
|
return this._encodeObjid(data, state.reverseArgs[0], state.args[1]);
|
|
else if (tag === 'objid')
|
|
return this._encodeObjid(data, null, null);
|
|
else if (tag === 'gentime' || tag === 'utctime')
|
|
return this._encodeTime(data, tag);
|
|
else if (tag === 'null_')
|
|
return this._encodeNull();
|
|
else if (tag === 'int' || tag === 'enum')
|
|
return this._encodeInt(data, state.args && state.reverseArgs[0]);
|
|
else if (tag === 'bool')
|
|
return this._encodeBool(data);
|
|
else if (tag === 'objDesc')
|
|
return this._encodeStr(data, tag);
|
|
else
|
|
throw new Error('Unsupported tag: ' + tag);
|
|
};
|
|
|
|
Node.prototype._isNumstr = function isNumstr(str) {
|
|
return /^[0-9 ]*$/.test(str);
|
|
};
|
|
|
|
Node.prototype._isPrintstr = function isPrintstr(str) {
|
|
return /^[A-Za-z0-9 '()+,-./:=?]*$/.test(str);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/base/reporter.js":
|
|
/*!********************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/base/reporter.js ***!
|
|
\********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
|
|
function Reporter(options) {
|
|
this._reporterState = {
|
|
obj: null,
|
|
path: [],
|
|
options: options || {},
|
|
errors: []
|
|
};
|
|
}
|
|
exports.Reporter = Reporter;
|
|
|
|
Reporter.prototype.isError = function isError(obj) {
|
|
return obj instanceof ReporterError;
|
|
};
|
|
|
|
Reporter.prototype.save = function save() {
|
|
const state = this._reporterState;
|
|
|
|
return { obj: state.obj, pathLen: state.path.length };
|
|
};
|
|
|
|
Reporter.prototype.restore = function restore(data) {
|
|
const state = this._reporterState;
|
|
|
|
state.obj = data.obj;
|
|
state.path = state.path.slice(0, data.pathLen);
|
|
};
|
|
|
|
Reporter.prototype.enterKey = function enterKey(key) {
|
|
return this._reporterState.path.push(key);
|
|
};
|
|
|
|
Reporter.prototype.exitKey = function exitKey(index) {
|
|
const state = this._reporterState;
|
|
|
|
state.path = state.path.slice(0, index - 1);
|
|
};
|
|
|
|
Reporter.prototype.leaveKey = function leaveKey(index, key, value) {
|
|
const state = this._reporterState;
|
|
|
|
this.exitKey(index);
|
|
if (state.obj !== null)
|
|
state.obj[key] = value;
|
|
};
|
|
|
|
Reporter.prototype.path = function path() {
|
|
return this._reporterState.path.join('/');
|
|
};
|
|
|
|
Reporter.prototype.enterObject = function enterObject() {
|
|
const state = this._reporterState;
|
|
|
|
const prev = state.obj;
|
|
state.obj = {};
|
|
return prev;
|
|
};
|
|
|
|
Reporter.prototype.leaveObject = function leaveObject(prev) {
|
|
const state = this._reporterState;
|
|
|
|
const now = state.obj;
|
|
state.obj = prev;
|
|
return now;
|
|
};
|
|
|
|
Reporter.prototype.error = function error(msg) {
|
|
let err;
|
|
const state = this._reporterState;
|
|
|
|
const inherited = msg instanceof ReporterError;
|
|
if (inherited) {
|
|
err = msg;
|
|
} else {
|
|
err = new ReporterError(state.path.map(function(elem) {
|
|
return '[' + JSON.stringify(elem) + ']';
|
|
}).join(''), msg.message || msg, msg.stack);
|
|
}
|
|
|
|
if (!state.options.partial)
|
|
throw err;
|
|
|
|
if (!inherited)
|
|
state.errors.push(err);
|
|
|
|
return err;
|
|
};
|
|
|
|
Reporter.prototype.wrapResult = function wrapResult(result) {
|
|
const state = this._reporterState;
|
|
if (!state.options.partial)
|
|
return result;
|
|
|
|
return {
|
|
result: this.isError(result) ? null : result,
|
|
errors: state.errors
|
|
};
|
|
};
|
|
|
|
function ReporterError(path, msg) {
|
|
this.path = path;
|
|
this.rethrow(msg);
|
|
}
|
|
inherits(ReporterError, Error);
|
|
|
|
ReporterError.prototype.rethrow = function rethrow(msg) {
|
|
this.message = msg + ' at: ' + (this.path || '(shallow)');
|
|
if (Error.captureStackTrace)
|
|
Error.captureStackTrace(this, ReporterError);
|
|
|
|
if (!this.stack) {
|
|
try {
|
|
// IE only adds stack when thrown
|
|
throw new Error(this.message);
|
|
} catch (e) {
|
|
this.stack = e.stack;
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/constants/der.js":
|
|
/*!********************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/constants/der.js ***!
|
|
\********************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// Helper
|
|
function reverse(map) {
|
|
const res = {};
|
|
|
|
Object.keys(map).forEach(function(key) {
|
|
// Convert key to integer if it is stringified
|
|
if ((key | 0) == key)
|
|
key = key | 0;
|
|
|
|
const value = map[key];
|
|
res[value] = key;
|
|
});
|
|
|
|
return res;
|
|
}
|
|
|
|
exports.tagClass = {
|
|
0: 'universal',
|
|
1: 'application',
|
|
2: 'context',
|
|
3: 'private'
|
|
};
|
|
exports.tagClassByName = reverse(exports.tagClass);
|
|
|
|
exports.tag = {
|
|
0x00: 'end',
|
|
0x01: 'bool',
|
|
0x02: 'int',
|
|
0x03: 'bitstr',
|
|
0x04: 'octstr',
|
|
0x05: 'null_',
|
|
0x06: 'objid',
|
|
0x07: 'objDesc',
|
|
0x08: 'external',
|
|
0x09: 'real',
|
|
0x0a: 'enum',
|
|
0x0b: 'embed',
|
|
0x0c: 'utf8str',
|
|
0x0d: 'relativeOid',
|
|
0x10: 'seq',
|
|
0x11: 'set',
|
|
0x12: 'numstr',
|
|
0x13: 'printstr',
|
|
0x14: 't61str',
|
|
0x15: 'videostr',
|
|
0x16: 'ia5str',
|
|
0x17: 'utctime',
|
|
0x18: 'gentime',
|
|
0x19: 'graphstr',
|
|
0x1a: 'iso646str',
|
|
0x1b: 'genstr',
|
|
0x1c: 'unistr',
|
|
0x1d: 'charstr',
|
|
0x1e: 'bmpstr'
|
|
};
|
|
exports.tagByName = reverse(exports.tag);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/constants/index.js":
|
|
/*!**********************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/constants/index.js ***!
|
|
\**********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const constants = exports;
|
|
|
|
// Helper
|
|
constants._reverse = function reverse(map) {
|
|
const res = {};
|
|
|
|
Object.keys(map).forEach(function(key) {
|
|
// Convert key to integer if it is stringified
|
|
if ((key | 0) == key)
|
|
key = key | 0;
|
|
|
|
const value = map[key];
|
|
res[value] = key;
|
|
});
|
|
|
|
return res;
|
|
};
|
|
|
|
constants.der = __webpack_require__(/*! ./der */ "./node_modules/asn1.js/lib/asn1/constants/der.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/decoders/der.js":
|
|
/*!*******************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/decoders/der.js ***!
|
|
\*******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
|
|
const bignum = __webpack_require__(/*! bn.js */ "./node_modules/asn1.js/node_modules/bn.js/lib/bn.js");
|
|
const DecoderBuffer = __webpack_require__(/*! ../base/buffer */ "./node_modules/asn1.js/lib/asn1/base/buffer.js").DecoderBuffer;
|
|
const Node = __webpack_require__(/*! ../base/node */ "./node_modules/asn1.js/lib/asn1/base/node.js");
|
|
|
|
// Import DER constants
|
|
const der = __webpack_require__(/*! ../constants/der */ "./node_modules/asn1.js/lib/asn1/constants/der.js");
|
|
|
|
function DERDecoder(entity) {
|
|
this.enc = 'der';
|
|
this.name = entity.name;
|
|
this.entity = entity;
|
|
|
|
// Construct base tree
|
|
this.tree = new DERNode();
|
|
this.tree._init(entity.body);
|
|
}
|
|
module.exports = DERDecoder;
|
|
|
|
DERDecoder.prototype.decode = function decode(data, options) {
|
|
if (!DecoderBuffer.isDecoderBuffer(data)) {
|
|
data = new DecoderBuffer(data, options);
|
|
}
|
|
|
|
return this.tree._decode(data, options);
|
|
};
|
|
|
|
// Tree methods
|
|
|
|
function DERNode(parent) {
|
|
Node.call(this, 'der', parent);
|
|
}
|
|
inherits(DERNode, Node);
|
|
|
|
DERNode.prototype._peekTag = function peekTag(buffer, tag, any) {
|
|
if (buffer.isEmpty())
|
|
return false;
|
|
|
|
const state = buffer.save();
|
|
const decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"');
|
|
if (buffer.isError(decodedTag))
|
|
return decodedTag;
|
|
|
|
buffer.restore(state);
|
|
|
|
return decodedTag.tag === tag || decodedTag.tagStr === tag ||
|
|
(decodedTag.tagStr + 'of') === tag || any;
|
|
};
|
|
|
|
DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) {
|
|
const decodedTag = derDecodeTag(buffer,
|
|
'Failed to decode tag of "' + tag + '"');
|
|
if (buffer.isError(decodedTag))
|
|
return decodedTag;
|
|
|
|
let len = derDecodeLen(buffer,
|
|
decodedTag.primitive,
|
|
'Failed to get length of "' + tag + '"');
|
|
|
|
// Failure
|
|
if (buffer.isError(len))
|
|
return len;
|
|
|
|
if (!any &&
|
|
decodedTag.tag !== tag &&
|
|
decodedTag.tagStr !== tag &&
|
|
decodedTag.tagStr + 'of' !== tag) {
|
|
return buffer.error('Failed to match tag: "' + tag + '"');
|
|
}
|
|
|
|
if (decodedTag.primitive || len !== null)
|
|
return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
|
|
|
|
// Indefinite length... find END tag
|
|
const state = buffer.save();
|
|
const res = this._skipUntilEnd(
|
|
buffer,
|
|
'Failed to skip indefinite length body: "' + this.tag + '"');
|
|
if (buffer.isError(res))
|
|
return res;
|
|
|
|
len = buffer.offset - state.offset;
|
|
buffer.restore(state);
|
|
return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
|
|
};
|
|
|
|
DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) {
|
|
for (;;) {
|
|
const tag = derDecodeTag(buffer, fail);
|
|
if (buffer.isError(tag))
|
|
return tag;
|
|
const len = derDecodeLen(buffer, tag.primitive, fail);
|
|
if (buffer.isError(len))
|
|
return len;
|
|
|
|
let res;
|
|
if (tag.primitive || len !== null)
|
|
res = buffer.skip(len);
|
|
else
|
|
res = this._skipUntilEnd(buffer, fail);
|
|
|
|
// Failure
|
|
if (buffer.isError(res))
|
|
return res;
|
|
|
|
if (tag.tagStr === 'end')
|
|
break;
|
|
}
|
|
};
|
|
|
|
DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder,
|
|
options) {
|
|
const result = [];
|
|
while (!buffer.isEmpty()) {
|
|
const possibleEnd = this._peekTag(buffer, 'end');
|
|
if (buffer.isError(possibleEnd))
|
|
return possibleEnd;
|
|
|
|
const res = decoder.decode(buffer, 'der', options);
|
|
if (buffer.isError(res) && possibleEnd)
|
|
break;
|
|
result.push(res);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
DERNode.prototype._decodeStr = function decodeStr(buffer, tag) {
|
|
if (tag === 'bitstr') {
|
|
const unused = buffer.readUInt8();
|
|
if (buffer.isError(unused))
|
|
return unused;
|
|
return { unused: unused, data: buffer.raw() };
|
|
} else if (tag === 'bmpstr') {
|
|
const raw = buffer.raw();
|
|
if (raw.length % 2 === 1)
|
|
return buffer.error('Decoding of string type: bmpstr length mismatch');
|
|
|
|
let str = '';
|
|
for (let i = 0; i < raw.length / 2; i++) {
|
|
str += String.fromCharCode(raw.readUInt16BE(i * 2));
|
|
}
|
|
return str;
|
|
} else if (tag === 'numstr') {
|
|
const numstr = buffer.raw().toString('ascii');
|
|
if (!this._isNumstr(numstr)) {
|
|
return buffer.error('Decoding of string type: ' +
|
|
'numstr unsupported characters');
|
|
}
|
|
return numstr;
|
|
} else if (tag === 'octstr') {
|
|
return buffer.raw();
|
|
} else if (tag === 'objDesc') {
|
|
return buffer.raw();
|
|
} else if (tag === 'printstr') {
|
|
const printstr = buffer.raw().toString('ascii');
|
|
if (!this._isPrintstr(printstr)) {
|
|
return buffer.error('Decoding of string type: ' +
|
|
'printstr unsupported characters');
|
|
}
|
|
return printstr;
|
|
} else if (/str$/.test(tag)) {
|
|
return buffer.raw().toString();
|
|
} else {
|
|
return buffer.error('Decoding of string type: ' + tag + ' unsupported');
|
|
}
|
|
};
|
|
|
|
DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) {
|
|
let result;
|
|
const identifiers = [];
|
|
let ident = 0;
|
|
let subident = 0;
|
|
while (!buffer.isEmpty()) {
|
|
subident = buffer.readUInt8();
|
|
ident <<= 7;
|
|
ident |= subident & 0x7f;
|
|
if ((subident & 0x80) === 0) {
|
|
identifiers.push(ident);
|
|
ident = 0;
|
|
}
|
|
}
|
|
if (subident & 0x80)
|
|
identifiers.push(ident);
|
|
|
|
const first = (identifiers[0] / 40) | 0;
|
|
const second = identifiers[0] % 40;
|
|
|
|
if (relative)
|
|
result = identifiers;
|
|
else
|
|
result = [first, second].concat(identifiers.slice(1));
|
|
|
|
if (values) {
|
|
let tmp = values[result.join(' ')];
|
|
if (tmp === undefined)
|
|
tmp = values[result.join('.')];
|
|
if (tmp !== undefined)
|
|
result = tmp;
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
DERNode.prototype._decodeTime = function decodeTime(buffer, tag) {
|
|
const str = buffer.raw().toString();
|
|
|
|
let year;
|
|
let mon;
|
|
let day;
|
|
let hour;
|
|
let min;
|
|
let sec;
|
|
if (tag === 'gentime') {
|
|
year = str.slice(0, 4) | 0;
|
|
mon = str.slice(4, 6) | 0;
|
|
day = str.slice(6, 8) | 0;
|
|
hour = str.slice(8, 10) | 0;
|
|
min = str.slice(10, 12) | 0;
|
|
sec = str.slice(12, 14) | 0;
|
|
} else if (tag === 'utctime') {
|
|
year = str.slice(0, 2) | 0;
|
|
mon = str.slice(2, 4) | 0;
|
|
day = str.slice(4, 6) | 0;
|
|
hour = str.slice(6, 8) | 0;
|
|
min = str.slice(8, 10) | 0;
|
|
sec = str.slice(10, 12) | 0;
|
|
if (year < 70)
|
|
year = 2000 + year;
|
|
else
|
|
year = 1900 + year;
|
|
} else {
|
|
return buffer.error('Decoding ' + tag + ' time is not supported yet');
|
|
}
|
|
|
|
return Date.UTC(year, mon - 1, day, hour, min, sec, 0);
|
|
};
|
|
|
|
DERNode.prototype._decodeNull = function decodeNull() {
|
|
return null;
|
|
};
|
|
|
|
DERNode.prototype._decodeBool = function decodeBool(buffer) {
|
|
const res = buffer.readUInt8();
|
|
if (buffer.isError(res))
|
|
return res;
|
|
else
|
|
return res !== 0;
|
|
};
|
|
|
|
DERNode.prototype._decodeInt = function decodeInt(buffer, values) {
|
|
// Bigint, return as it is (assume big endian)
|
|
const raw = buffer.raw();
|
|
let res = new bignum(raw);
|
|
|
|
if (values)
|
|
res = values[res.toString(10)] || res;
|
|
|
|
return res;
|
|
};
|
|
|
|
DERNode.prototype._use = function use(entity, obj) {
|
|
if (typeof entity === 'function')
|
|
entity = entity(obj);
|
|
return entity._getDecoder('der').tree;
|
|
};
|
|
|
|
// Utility methods
|
|
|
|
function derDecodeTag(buf, fail) {
|
|
let tag = buf.readUInt8(fail);
|
|
if (buf.isError(tag))
|
|
return tag;
|
|
|
|
const cls = der.tagClass[tag >> 6];
|
|
const primitive = (tag & 0x20) === 0;
|
|
|
|
// Multi-octet tag - load
|
|
if ((tag & 0x1f) === 0x1f) {
|
|
let oct = tag;
|
|
tag = 0;
|
|
while ((oct & 0x80) === 0x80) {
|
|
oct = buf.readUInt8(fail);
|
|
if (buf.isError(oct))
|
|
return oct;
|
|
|
|
tag <<= 7;
|
|
tag |= oct & 0x7f;
|
|
}
|
|
} else {
|
|
tag &= 0x1f;
|
|
}
|
|
const tagStr = der.tag[tag];
|
|
|
|
return {
|
|
cls: cls,
|
|
primitive: primitive,
|
|
tag: tag,
|
|
tagStr: tagStr
|
|
};
|
|
}
|
|
|
|
function derDecodeLen(buf, primitive, fail) {
|
|
let len = buf.readUInt8(fail);
|
|
if (buf.isError(len))
|
|
return len;
|
|
|
|
// Indefinite form
|
|
if (!primitive && len === 0x80)
|
|
return null;
|
|
|
|
// Definite form
|
|
if ((len & 0x80) === 0) {
|
|
// Short form
|
|
return len;
|
|
}
|
|
|
|
// Long form
|
|
const num = len & 0x7f;
|
|
if (num > 4)
|
|
return buf.error('length octect is too long');
|
|
|
|
len = 0;
|
|
for (let i = 0; i < num; i++) {
|
|
len <<= 8;
|
|
const j = buf.readUInt8(fail);
|
|
if (buf.isError(j))
|
|
return j;
|
|
len |= j;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/decoders/index.js":
|
|
/*!*********************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/decoders/index.js ***!
|
|
\*********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const decoders = exports;
|
|
|
|
decoders.der = __webpack_require__(/*! ./der */ "./node_modules/asn1.js/lib/asn1/decoders/der.js");
|
|
decoders.pem = __webpack_require__(/*! ./pem */ "./node_modules/asn1.js/lib/asn1/decoders/pem.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/decoders/pem.js":
|
|
/*!*******************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/decoders/pem.js ***!
|
|
\*******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
const Buffer = __webpack_require__(/*! safer-buffer */ "./node_modules/safer-buffer/safer.js").Buffer;
|
|
|
|
const DERDecoder = __webpack_require__(/*! ./der */ "./node_modules/asn1.js/lib/asn1/decoders/der.js");
|
|
|
|
function PEMDecoder(entity) {
|
|
DERDecoder.call(this, entity);
|
|
this.enc = 'pem';
|
|
}
|
|
inherits(PEMDecoder, DERDecoder);
|
|
module.exports = PEMDecoder;
|
|
|
|
PEMDecoder.prototype.decode = function decode(data, options) {
|
|
const lines = data.toString().split(/[\r\n]+/g);
|
|
|
|
const label = options.label.toUpperCase();
|
|
|
|
const re = /^-----(BEGIN|END) ([^-]+)-----$/;
|
|
let start = -1;
|
|
let end = -1;
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const match = lines[i].match(re);
|
|
if (match === null)
|
|
continue;
|
|
|
|
if (match[2] !== label)
|
|
continue;
|
|
|
|
if (start === -1) {
|
|
if (match[1] !== 'BEGIN')
|
|
break;
|
|
start = i;
|
|
} else {
|
|
if (match[1] !== 'END')
|
|
break;
|
|
end = i;
|
|
break;
|
|
}
|
|
}
|
|
if (start === -1 || end === -1)
|
|
throw new Error('PEM section not found for: ' + label);
|
|
|
|
const base64 = lines.slice(start + 1, end).join('');
|
|
// Remove excessive symbols
|
|
base64.replace(/[^a-z0-9+/=]+/gi, '');
|
|
|
|
const input = Buffer.from(base64, 'base64');
|
|
return DERDecoder.prototype.decode.call(this, input, options);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/encoders/der.js":
|
|
/*!*******************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/encoders/der.js ***!
|
|
\*******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
const Buffer = __webpack_require__(/*! safer-buffer */ "./node_modules/safer-buffer/safer.js").Buffer;
|
|
const Node = __webpack_require__(/*! ../base/node */ "./node_modules/asn1.js/lib/asn1/base/node.js");
|
|
|
|
// Import DER constants
|
|
const der = __webpack_require__(/*! ../constants/der */ "./node_modules/asn1.js/lib/asn1/constants/der.js");
|
|
|
|
function DEREncoder(entity) {
|
|
this.enc = 'der';
|
|
this.name = entity.name;
|
|
this.entity = entity;
|
|
|
|
// Construct base tree
|
|
this.tree = new DERNode();
|
|
this.tree._init(entity.body);
|
|
}
|
|
module.exports = DEREncoder;
|
|
|
|
DEREncoder.prototype.encode = function encode(data, reporter) {
|
|
return this.tree._encode(data, reporter).join();
|
|
};
|
|
|
|
// Tree methods
|
|
|
|
function DERNode(parent) {
|
|
Node.call(this, 'der', parent);
|
|
}
|
|
inherits(DERNode, Node);
|
|
|
|
DERNode.prototype._encodeComposite = function encodeComposite(tag,
|
|
primitive,
|
|
cls,
|
|
content) {
|
|
const encodedTag = encodeTag(tag, primitive, cls, this.reporter);
|
|
|
|
// Short form
|
|
if (content.length < 0x80) {
|
|
const header = Buffer.alloc(2);
|
|
header[0] = encodedTag;
|
|
header[1] = content.length;
|
|
return this._createEncoderBuffer([ header, content ]);
|
|
}
|
|
|
|
// Long form
|
|
// Count octets required to store length
|
|
let lenOctets = 1;
|
|
for (let i = content.length; i >= 0x100; i >>= 8)
|
|
lenOctets++;
|
|
|
|
const header = Buffer.alloc(1 + 1 + lenOctets);
|
|
header[0] = encodedTag;
|
|
header[1] = 0x80 | lenOctets;
|
|
|
|
for (let i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8)
|
|
header[i] = j & 0xff;
|
|
|
|
return this._createEncoderBuffer([ header, content ]);
|
|
};
|
|
|
|
DERNode.prototype._encodeStr = function encodeStr(str, tag) {
|
|
if (tag === 'bitstr') {
|
|
return this._createEncoderBuffer([ str.unused | 0, str.data ]);
|
|
} else if (tag === 'bmpstr') {
|
|
const buf = Buffer.alloc(str.length * 2);
|
|
for (let i = 0; i < str.length; i++) {
|
|
buf.writeUInt16BE(str.charCodeAt(i), i * 2);
|
|
}
|
|
return this._createEncoderBuffer(buf);
|
|
} else if (tag === 'numstr') {
|
|
if (!this._isNumstr(str)) {
|
|
return this.reporter.error('Encoding of string type: numstr supports ' +
|
|
'only digits and space');
|
|
}
|
|
return this._createEncoderBuffer(str);
|
|
} else if (tag === 'printstr') {
|
|
if (!this._isPrintstr(str)) {
|
|
return this.reporter.error('Encoding of string type: printstr supports ' +
|
|
'only latin upper and lower case letters, ' +
|
|
'digits, space, apostrophe, left and rigth ' +
|
|
'parenthesis, plus sign, comma, hyphen, ' +
|
|
'dot, slash, colon, equal sign, ' +
|
|
'question mark');
|
|
}
|
|
return this._createEncoderBuffer(str);
|
|
} else if (/str$/.test(tag)) {
|
|
return this._createEncoderBuffer(str);
|
|
} else if (tag === 'objDesc') {
|
|
return this._createEncoderBuffer(str);
|
|
} else {
|
|
return this.reporter.error('Encoding of string type: ' + tag +
|
|
' unsupported');
|
|
}
|
|
};
|
|
|
|
DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) {
|
|
if (typeof id === 'string') {
|
|
if (!values)
|
|
return this.reporter.error('string objid given, but no values map found');
|
|
if (!values.hasOwnProperty(id))
|
|
return this.reporter.error('objid not found in values map');
|
|
id = values[id].split(/[\s.]+/g);
|
|
for (let i = 0; i < id.length; i++)
|
|
id[i] |= 0;
|
|
} else if (Array.isArray(id)) {
|
|
id = id.slice();
|
|
for (let i = 0; i < id.length; i++)
|
|
id[i] |= 0;
|
|
}
|
|
|
|
if (!Array.isArray(id)) {
|
|
return this.reporter.error('objid() should be either array or string, ' +
|
|
'got: ' + JSON.stringify(id));
|
|
}
|
|
|
|
if (!relative) {
|
|
if (id[1] >= 40)
|
|
return this.reporter.error('Second objid identifier OOB');
|
|
id.splice(0, 2, id[0] * 40 + id[1]);
|
|
}
|
|
|
|
// Count number of octets
|
|
let size = 0;
|
|
for (let i = 0; i < id.length; i++) {
|
|
let ident = id[i];
|
|
for (size++; ident >= 0x80; ident >>= 7)
|
|
size++;
|
|
}
|
|
|
|
const objid = Buffer.alloc(size);
|
|
let offset = objid.length - 1;
|
|
for (let i = id.length - 1; i >= 0; i--) {
|
|
let ident = id[i];
|
|
objid[offset--] = ident & 0x7f;
|
|
while ((ident >>= 7) > 0)
|
|
objid[offset--] = 0x80 | (ident & 0x7f);
|
|
}
|
|
|
|
return this._createEncoderBuffer(objid);
|
|
};
|
|
|
|
function two(num) {
|
|
if (num < 10)
|
|
return '0' + num;
|
|
else
|
|
return num;
|
|
}
|
|
|
|
DERNode.prototype._encodeTime = function encodeTime(time, tag) {
|
|
let str;
|
|
const date = new Date(time);
|
|
|
|
if (tag === 'gentime') {
|
|
str = [
|
|
two(date.getUTCFullYear()),
|
|
two(date.getUTCMonth() + 1),
|
|
two(date.getUTCDate()),
|
|
two(date.getUTCHours()),
|
|
two(date.getUTCMinutes()),
|
|
two(date.getUTCSeconds()),
|
|
'Z'
|
|
].join('');
|
|
} else if (tag === 'utctime') {
|
|
str = [
|
|
two(date.getUTCFullYear() % 100),
|
|
two(date.getUTCMonth() + 1),
|
|
two(date.getUTCDate()),
|
|
two(date.getUTCHours()),
|
|
two(date.getUTCMinutes()),
|
|
two(date.getUTCSeconds()),
|
|
'Z'
|
|
].join('');
|
|
} else {
|
|
this.reporter.error('Encoding ' + tag + ' time is not supported yet');
|
|
}
|
|
|
|
return this._encodeStr(str, 'octstr');
|
|
};
|
|
|
|
DERNode.prototype._encodeNull = function encodeNull() {
|
|
return this._createEncoderBuffer('');
|
|
};
|
|
|
|
DERNode.prototype._encodeInt = function encodeInt(num, values) {
|
|
if (typeof num === 'string') {
|
|
if (!values)
|
|
return this.reporter.error('String int or enum given, but no values map');
|
|
if (!values.hasOwnProperty(num)) {
|
|
return this.reporter.error('Values map doesn\'t contain: ' +
|
|
JSON.stringify(num));
|
|
}
|
|
num = values[num];
|
|
}
|
|
|
|
// Bignum, assume big endian
|
|
if (typeof num !== 'number' && !Buffer.isBuffer(num)) {
|
|
const numArray = num.toArray();
|
|
if (!num.sign && numArray[0] & 0x80) {
|
|
numArray.unshift(0);
|
|
}
|
|
num = Buffer.from(numArray);
|
|
}
|
|
|
|
if (Buffer.isBuffer(num)) {
|
|
let size = num.length;
|
|
if (num.length === 0)
|
|
size++;
|
|
|
|
const out = Buffer.alloc(size);
|
|
num.copy(out);
|
|
if (num.length === 0)
|
|
out[0] = 0;
|
|
return this._createEncoderBuffer(out);
|
|
}
|
|
|
|
if (num < 0x80)
|
|
return this._createEncoderBuffer(num);
|
|
|
|
if (num < 0x100)
|
|
return this._createEncoderBuffer([0, num]);
|
|
|
|
let size = 1;
|
|
for (let i = num; i >= 0x100; i >>= 8)
|
|
size++;
|
|
|
|
const out = new Array(size);
|
|
for (let i = out.length - 1; i >= 0; i--) {
|
|
out[i] = num & 0xff;
|
|
num >>= 8;
|
|
}
|
|
if(out[0] & 0x80) {
|
|
out.unshift(0);
|
|
}
|
|
|
|
return this._createEncoderBuffer(Buffer.from(out));
|
|
};
|
|
|
|
DERNode.prototype._encodeBool = function encodeBool(value) {
|
|
return this._createEncoderBuffer(value ? 0xff : 0);
|
|
};
|
|
|
|
DERNode.prototype._use = function use(entity, obj) {
|
|
if (typeof entity === 'function')
|
|
entity = entity(obj);
|
|
return entity._getEncoder('der').tree;
|
|
};
|
|
|
|
DERNode.prototype._skipDefault = function skipDefault(dataBuffer, reporter, parent) {
|
|
const state = this._baseState;
|
|
let i;
|
|
if (state['default'] === null)
|
|
return false;
|
|
|
|
const data = dataBuffer.join();
|
|
if (state.defaultBuffer === undefined)
|
|
state.defaultBuffer = this._encodeValue(state['default'], reporter, parent).join();
|
|
|
|
if (data.length !== state.defaultBuffer.length)
|
|
return false;
|
|
|
|
for (i=0; i < data.length; i++)
|
|
if (data[i] !== state.defaultBuffer[i])
|
|
return false;
|
|
|
|
return true;
|
|
};
|
|
|
|
// Utility methods
|
|
|
|
function encodeTag(tag, primitive, cls, reporter) {
|
|
let res;
|
|
|
|
if (tag === 'seqof')
|
|
tag = 'seq';
|
|
else if (tag === 'setof')
|
|
tag = 'set';
|
|
|
|
if (der.tagByName.hasOwnProperty(tag))
|
|
res = der.tagByName[tag];
|
|
else if (typeof tag === 'number' && (tag | 0) === tag)
|
|
res = tag;
|
|
else
|
|
return reporter.error('Unknown tag: ' + tag);
|
|
|
|
if (res >= 0x1f)
|
|
return reporter.error('Multi-octet tag encoding unsupported');
|
|
|
|
if (!primitive)
|
|
res |= 0x20;
|
|
|
|
res |= (der.tagClassByName[cls || 'universal'] << 6);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/encoders/index.js":
|
|
/*!*********************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/encoders/index.js ***!
|
|
\*********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const encoders = exports;
|
|
|
|
encoders.der = __webpack_require__(/*! ./der */ "./node_modules/asn1.js/lib/asn1/encoders/der.js");
|
|
encoders.pem = __webpack_require__(/*! ./pem */ "./node_modules/asn1.js/lib/asn1/encoders/pem.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/lib/asn1/encoders/pem.js":
|
|
/*!*******************************************************!*\
|
|
!*** ./node_modules/asn1.js/lib/asn1/encoders/pem.js ***!
|
|
\*******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
|
|
const DEREncoder = __webpack_require__(/*! ./der */ "./node_modules/asn1.js/lib/asn1/encoders/der.js");
|
|
|
|
function PEMEncoder(entity) {
|
|
DEREncoder.call(this, entity);
|
|
this.enc = 'pem';
|
|
}
|
|
inherits(PEMEncoder, DEREncoder);
|
|
module.exports = PEMEncoder;
|
|
|
|
PEMEncoder.prototype.encode = function encode(data, options) {
|
|
const buf = DEREncoder.prototype.encode.call(this, data);
|
|
|
|
const p = buf.toString('base64');
|
|
const out = [ '-----BEGIN ' + options.label + '-----' ];
|
|
for (let i = 0; i < p.length; i += 64)
|
|
out.push(p.slice(i, i + 64));
|
|
out.push('-----END ' + options.label + '-----');
|
|
return out.join('\n');
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/asn1.js/node_modules/bn.js/lib/bn.js":
|
|
/*!***********************************************************!*\
|
|
!*** ./node_modules/asn1.js/node_modules/bn.js/lib/bn.js ***!
|
|
\***********************************************************/
|
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
/* module decorator */ module = __webpack_require__.nmd(module);
|
|
(function (module, exports) {
|
|
'use strict';
|
|
|
|
// Utils
|
|
function assert (val, msg) {
|
|
if (!val) throw new Error(msg || 'Assertion failed');
|
|
}
|
|
|
|
// Could use `inherits` module, but don't want to move from single file
|
|
// architecture yet.
|
|
function inherits (ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
var TempCtor = function () {};
|
|
TempCtor.prototype = superCtor.prototype;
|
|
ctor.prototype = new TempCtor();
|
|
ctor.prototype.constructor = ctor;
|
|
}
|
|
|
|
// BN
|
|
|
|
function BN (number, base, endian) {
|
|
if (BN.isBN(number)) {
|
|
return number;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.words = null;
|
|
this.length = 0;
|
|
|
|
// Reduction context
|
|
this.red = null;
|
|
|
|
if (number !== null) {
|
|
if (base === 'le' || base === 'be') {
|
|
endian = base;
|
|
base = 10;
|
|
}
|
|
|
|
this._init(number || 0, base || 10, endian || 'be');
|
|
}
|
|
}
|
|
if (typeof module === 'object') {
|
|
module.exports = BN;
|
|
} else {
|
|
exports.BN = BN;
|
|
}
|
|
|
|
BN.BN = BN;
|
|
BN.wordSize = 26;
|
|
|
|
var Buffer;
|
|
try {
|
|
if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') {
|
|
Buffer = window.Buffer;
|
|
} else {
|
|
Buffer = __webpack_require__(/*! buffer */ "?d546").Buffer;
|
|
}
|
|
} catch (e) {
|
|
}
|
|
|
|
BN.isBN = function isBN (num) {
|
|
if (num instanceof BN) {
|
|
return true;
|
|
}
|
|
|
|
return num !== null && typeof num === 'object' &&
|
|
num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
|
|
};
|
|
|
|
BN.max = function max (left, right) {
|
|
if (left.cmp(right) > 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.min = function min (left, right) {
|
|
if (left.cmp(right) < 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.prototype._init = function init (number, base, endian) {
|
|
if (typeof number === 'number') {
|
|
return this._initNumber(number, base, endian);
|
|
}
|
|
|
|
if (typeof number === 'object') {
|
|
return this._initArray(number, base, endian);
|
|
}
|
|
|
|
if (base === 'hex') {
|
|
base = 16;
|
|
}
|
|
assert(base === (base | 0) && base >= 2 && base <= 36);
|
|
|
|
number = number.toString().replace(/\s+/g, '');
|
|
var start = 0;
|
|
if (number[0] === '-') {
|
|
start++;
|
|
this.negative = 1;
|
|
}
|
|
|
|
if (start < number.length) {
|
|
if (base === 16) {
|
|
this._parseHex(number, start, endian);
|
|
} else {
|
|
this._parseBase(number, base, start);
|
|
if (endian === 'le') {
|
|
this._initArray(this.toArray(), base, endian);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
BN.prototype._initNumber = function _initNumber (number, base, endian) {
|
|
if (number < 0) {
|
|
this.negative = 1;
|
|
number = -number;
|
|
}
|
|
if (number < 0x4000000) {
|
|
this.words = [ number & 0x3ffffff ];
|
|
this.length = 1;
|
|
} else if (number < 0x10000000000000) {
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff
|
|
];
|
|
this.length = 2;
|
|
} else {
|
|
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff,
|
|
1
|
|
];
|
|
this.length = 3;
|
|
}
|
|
|
|
if (endian !== 'le') return;
|
|
|
|
// Reverse the bytes
|
|
this._initArray(this.toArray(), base, endian);
|
|
};
|
|
|
|
BN.prototype._initArray = function _initArray (number, base, endian) {
|
|
// Perhaps a Uint8Array
|
|
assert(typeof number.length === 'number');
|
|
if (number.length <= 0) {
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
return this;
|
|
}
|
|
|
|
this.length = Math.ceil(number.length / 3);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
var j, w;
|
|
var off = 0;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
|
|
w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
} else if (endian === 'le') {
|
|
for (i = 0, j = 0; i < number.length; i += 3) {
|
|
w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
return this.strip();
|
|
};
|
|
|
|
function parseHex4Bits (string, index) {
|
|
var c = string.charCodeAt(index);
|
|
// 'A' - 'F'
|
|
if (c >= 65 && c <= 70) {
|
|
return c - 55;
|
|
// 'a' - 'f'
|
|
} else if (c >= 97 && c <= 102) {
|
|
return c - 87;
|
|
// '0' - '9'
|
|
} else {
|
|
return (c - 48) & 0xf;
|
|
}
|
|
}
|
|
|
|
function parseHexByte (string, lowerBound, index) {
|
|
var r = parseHex4Bits(string, index);
|
|
if (index - 1 >= lowerBound) {
|
|
r |= parseHex4Bits(string, index - 1) << 4;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseHex = function _parseHex (number, start, endian) {
|
|
// Create possibly bigger array to ensure that it fits the number
|
|
this.length = Math.ceil((number.length - start) / 6);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
// 24-bits chunks
|
|
var off = 0;
|
|
var j = 0;
|
|
|
|
var w;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1; i >= start; i -= 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
} else {
|
|
var parseLength = number.length - start;
|
|
for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
function parseBase (str, start, end, mul) {
|
|
var r = 0;
|
|
var len = Math.min(str.length, end);
|
|
for (var i = start; i < len; i++) {
|
|
var c = str.charCodeAt(i) - 48;
|
|
|
|
r *= mul;
|
|
|
|
// 'a'
|
|
if (c >= 49) {
|
|
r += c - 49 + 0xa;
|
|
|
|
// 'A'
|
|
} else if (c >= 17) {
|
|
r += c - 17 + 0xa;
|
|
|
|
// '0' - '9'
|
|
} else {
|
|
r += c;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseBase = function _parseBase (number, base, start) {
|
|
// Initialize as zero
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
|
|
// Find length of limb in base
|
|
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
|
|
limbLen++;
|
|
}
|
|
limbLen--;
|
|
limbPow = (limbPow / base) | 0;
|
|
|
|
var total = number.length - start;
|
|
var mod = total % limbLen;
|
|
var end = Math.min(total, total - mod) + start;
|
|
|
|
var word = 0;
|
|
for (var i = start; i < end; i += limbLen) {
|
|
word = parseBase(number, i, i + limbLen, base);
|
|
|
|
this.imuln(limbPow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
if (mod !== 0) {
|
|
var pow = 1;
|
|
word = parseBase(number, i, number.length, base);
|
|
|
|
for (i = 0; i < mod; i++) {
|
|
pow *= base;
|
|
}
|
|
|
|
this.imuln(pow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
BN.prototype.copy = function copy (dest) {
|
|
dest.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
dest.words[i] = this.words[i];
|
|
}
|
|
dest.length = this.length;
|
|
dest.negative = this.negative;
|
|
dest.red = this.red;
|
|
};
|
|
|
|
BN.prototype.clone = function clone () {
|
|
var r = new BN(null);
|
|
this.copy(r);
|
|
return r;
|
|
};
|
|
|
|
BN.prototype._expand = function _expand (size) {
|
|
while (this.length < size) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
// Remove leading `0` from `this`
|
|
BN.prototype.strip = function strip () {
|
|
while (this.length > 1 && this.words[this.length - 1] === 0) {
|
|
this.length--;
|
|
}
|
|
return this._normSign();
|
|
};
|
|
|
|
BN.prototype._normSign = function _normSign () {
|
|
// -0 = 0
|
|
if (this.length === 1 && this.words[0] === 0) {
|
|
this.negative = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.inspect = function inspect () {
|
|
return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
|
|
};
|
|
|
|
/*
|
|
|
|
var zeros = [];
|
|
var groupSizes = [];
|
|
var groupBases = [];
|
|
|
|
var s = '';
|
|
var i = -1;
|
|
while (++i < BN.wordSize) {
|
|
zeros[i] = s;
|
|
s += '0';
|
|
}
|
|
groupSizes[0] = 0;
|
|
groupSizes[1] = 0;
|
|
groupBases[0] = 0;
|
|
groupBases[1] = 0;
|
|
var base = 2 - 1;
|
|
while (++base < 36 + 1) {
|
|
var groupSize = 0;
|
|
var groupBase = 1;
|
|
while (groupBase < (1 << BN.wordSize) / base) {
|
|
groupBase *= base;
|
|
groupSize += 1;
|
|
}
|
|
groupSizes[base] = groupSize;
|
|
groupBases[base] = groupBase;
|
|
}
|
|
|
|
*/
|
|
|
|
var zeros = [
|
|
'',
|
|
'0',
|
|
'00',
|
|
'000',
|
|
'0000',
|
|
'00000',
|
|
'000000',
|
|
'0000000',
|
|
'00000000',
|
|
'000000000',
|
|
'0000000000',
|
|
'00000000000',
|
|
'000000000000',
|
|
'0000000000000',
|
|
'00000000000000',
|
|
'000000000000000',
|
|
'0000000000000000',
|
|
'00000000000000000',
|
|
'000000000000000000',
|
|
'0000000000000000000',
|
|
'00000000000000000000',
|
|
'000000000000000000000',
|
|
'0000000000000000000000',
|
|
'00000000000000000000000',
|
|
'000000000000000000000000',
|
|
'0000000000000000000000000'
|
|
];
|
|
|
|
var groupSizes = [
|
|
0, 0,
|
|
25, 16, 12, 11, 10, 9, 8,
|
|
8, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5
|
|
];
|
|
|
|
var groupBases = [
|
|
0, 0,
|
|
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
|
|
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
|
|
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
|
|
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
|
|
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
|
|
];
|
|
|
|
BN.prototype.toString = function toString (base, padding) {
|
|
base = base || 10;
|
|
padding = padding | 0 || 1;
|
|
|
|
var out;
|
|
if (base === 16 || base === 'hex') {
|
|
out = '';
|
|
var off = 0;
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = this.words[i];
|
|
var word = (((w << off) | carry) & 0xffffff).toString(16);
|
|
carry = (w >>> (24 - off)) & 0xffffff;
|
|
if (carry !== 0 || i !== this.length - 1) {
|
|
out = zeros[6 - word.length] + word + out;
|
|
} else {
|
|
out = word + out;
|
|
}
|
|
off += 2;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
i--;
|
|
}
|
|
}
|
|
if (carry !== 0) {
|
|
out = carry.toString(16) + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
if (base === (base | 0) && base >= 2 && base <= 36) {
|
|
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
|
|
var groupSize = groupSizes[base];
|
|
// var groupBase = Math.pow(base, groupSize);
|
|
var groupBase = groupBases[base];
|
|
out = '';
|
|
var c = this.clone();
|
|
c.negative = 0;
|
|
while (!c.isZero()) {
|
|
var r = c.modn(groupBase).toString(base);
|
|
c = c.idivn(groupBase);
|
|
|
|
if (!c.isZero()) {
|
|
out = zeros[groupSize - r.length] + r + out;
|
|
} else {
|
|
out = r + out;
|
|
}
|
|
}
|
|
if (this.isZero()) {
|
|
out = '0' + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
assert(false, 'Base should be between 2 and 36');
|
|
};
|
|
|
|
BN.prototype.toNumber = function toNumber () {
|
|
var ret = this.words[0];
|
|
if (this.length === 2) {
|
|
ret += this.words[1] * 0x4000000;
|
|
} else if (this.length === 3 && this.words[2] === 0x01) {
|
|
// NOTE: at this stage it is known that the top bit is set
|
|
ret += 0x10000000000000 + (this.words[1] * 0x4000000);
|
|
} else if (this.length > 2) {
|
|
assert(false, 'Number can only safely store up to 53 bits');
|
|
}
|
|
return (this.negative !== 0) ? -ret : ret;
|
|
};
|
|
|
|
BN.prototype.toJSON = function toJSON () {
|
|
return this.toString(16);
|
|
};
|
|
|
|
BN.prototype.toBuffer = function toBuffer (endian, length) {
|
|
assert(typeof Buffer !== 'undefined');
|
|
return this.toArrayLike(Buffer, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArray = function toArray (endian, length) {
|
|
return this.toArrayLike(Array, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
|
|
var byteLength = this.byteLength();
|
|
var reqLength = length || Math.max(1, byteLength);
|
|
assert(byteLength <= reqLength, 'byte array longer than desired length');
|
|
assert(reqLength > 0, 'Requested array length <= 0');
|
|
|
|
this.strip();
|
|
var littleEndian = endian === 'le';
|
|
var res = new ArrayType(reqLength);
|
|
|
|
var b, i;
|
|
var q = this.clone();
|
|
if (!littleEndian) {
|
|
// Assume big-endian
|
|
for (i = 0; i < reqLength - byteLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[reqLength - i - 1] = b;
|
|
}
|
|
} else {
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[i] = b;
|
|
}
|
|
|
|
for (; i < reqLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
if (Math.clz32) {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
return 32 - Math.clz32(w);
|
|
};
|
|
} else {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
var t = w;
|
|
var r = 0;
|
|
if (t >= 0x1000) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if (t >= 0x40) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if (t >= 0x8) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if (t >= 0x02) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
return r + t;
|
|
};
|
|
}
|
|
|
|
BN.prototype._zeroBits = function _zeroBits (w) {
|
|
// Short-cut
|
|
if (w === 0) return 26;
|
|
|
|
var t = w;
|
|
var r = 0;
|
|
if ((t & 0x1fff) === 0) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if ((t & 0x7f) === 0) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if ((t & 0xf) === 0) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if ((t & 0x3) === 0) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
if ((t & 0x1) === 0) {
|
|
r++;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
// Return number of used bits in a BN
|
|
BN.prototype.bitLength = function bitLength () {
|
|
var w = this.words[this.length - 1];
|
|
var hi = this._countBits(w);
|
|
return (this.length - 1) * 26 + hi;
|
|
};
|
|
|
|
function toBitArray (num) {
|
|
var w = new Array(num.bitLength());
|
|
|
|
for (var bit = 0; bit < w.length; bit++) {
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
// Number of trailing zero bits
|
|
BN.prototype.zeroBits = function zeroBits () {
|
|
if (this.isZero()) return 0;
|
|
|
|
var r = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var b = this._zeroBits(this.words[i]);
|
|
r += b;
|
|
if (b !== 26) break;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
BN.prototype.byteLength = function byteLength () {
|
|
return Math.ceil(this.bitLength() / 8);
|
|
};
|
|
|
|
BN.prototype.toTwos = function toTwos (width) {
|
|
if (this.negative !== 0) {
|
|
return this.abs().inotn(width).iaddn(1);
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.fromTwos = function fromTwos (width) {
|
|
if (this.testn(width - 1)) {
|
|
return this.notn(width).iaddn(1).ineg();
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.isNeg = function isNeg () {
|
|
return this.negative !== 0;
|
|
};
|
|
|
|
// Return negative clone of `this`
|
|
BN.prototype.neg = function neg () {
|
|
return this.clone().ineg();
|
|
};
|
|
|
|
BN.prototype.ineg = function ineg () {
|
|
if (!this.isZero()) {
|
|
this.negative ^= 1;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Or `num` with `this` in-place
|
|
BN.prototype.iuor = function iuor (num) {
|
|
while (this.length < num.length) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
|
|
for (var i = 0; i < num.length; i++) {
|
|
this.words[i] = this.words[i] | num.words[i];
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ior = function ior (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuor(num);
|
|
};
|
|
|
|
// Or `num` with `this`
|
|
BN.prototype.or = function or (num) {
|
|
if (this.length > num.length) return this.clone().ior(num);
|
|
return num.clone().ior(this);
|
|
};
|
|
|
|
BN.prototype.uor = function uor (num) {
|
|
if (this.length > num.length) return this.clone().iuor(num);
|
|
return num.clone().iuor(this);
|
|
};
|
|
|
|
// And `num` with `this` in-place
|
|
BN.prototype.iuand = function iuand (num) {
|
|
// b = min-length(num, this)
|
|
var b;
|
|
if (this.length > num.length) {
|
|
b = num;
|
|
} else {
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = this.words[i] & num.words[i];
|
|
}
|
|
|
|
this.length = b.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.iand = function iand (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuand(num);
|
|
};
|
|
|
|
// And `num` with `this`
|
|
BN.prototype.and = function and (num) {
|
|
if (this.length > num.length) return this.clone().iand(num);
|
|
return num.clone().iand(this);
|
|
};
|
|
|
|
BN.prototype.uand = function uand (num) {
|
|
if (this.length > num.length) return this.clone().iuand(num);
|
|
return num.clone().iuand(this);
|
|
};
|
|
|
|
// Xor `num` with `this` in-place
|
|
BN.prototype.iuxor = function iuxor (num) {
|
|
// a.length > b.length
|
|
var a;
|
|
var b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = a.words[i] ^ b.words[i];
|
|
}
|
|
|
|
if (this !== a) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = a.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ixor = function ixor (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuxor(num);
|
|
};
|
|
|
|
// Xor `num` with `this`
|
|
BN.prototype.xor = function xor (num) {
|
|
if (this.length > num.length) return this.clone().ixor(num);
|
|
return num.clone().ixor(this);
|
|
};
|
|
|
|
BN.prototype.uxor = function uxor (num) {
|
|
if (this.length > num.length) return this.clone().iuxor(num);
|
|
return num.clone().iuxor(this);
|
|
};
|
|
|
|
// Not ``this`` with ``width`` bitwidth
|
|
BN.prototype.inotn = function inotn (width) {
|
|
assert(typeof width === 'number' && width >= 0);
|
|
|
|
var bytesNeeded = Math.ceil(width / 26) | 0;
|
|
var bitsLeft = width % 26;
|
|
|
|
// Extend the buffer with leading zeroes
|
|
this._expand(bytesNeeded);
|
|
|
|
if (bitsLeft > 0) {
|
|
bytesNeeded--;
|
|
}
|
|
|
|
// Handle complete words
|
|
for (var i = 0; i < bytesNeeded; i++) {
|
|
this.words[i] = ~this.words[i] & 0x3ffffff;
|
|
}
|
|
|
|
// Handle the residue
|
|
if (bitsLeft > 0) {
|
|
this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
|
|
}
|
|
|
|
// And remove leading zeroes
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.notn = function notn (width) {
|
|
return this.clone().inotn(width);
|
|
};
|
|
|
|
// Set `bit` of `this`
|
|
BN.prototype.setn = function setn (bit, val) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
this._expand(off + 1);
|
|
|
|
if (val) {
|
|
this.words[off] = this.words[off] | (1 << wbit);
|
|
} else {
|
|
this.words[off] = this.words[off] & ~(1 << wbit);
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Add `num` to `this` in-place
|
|
BN.prototype.iadd = function iadd (num) {
|
|
var r;
|
|
|
|
// negative + positive
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
this.negative = 0;
|
|
r = this.isub(num);
|
|
this.negative ^= 1;
|
|
return this._normSign();
|
|
|
|
// positive + negative
|
|
} else if (this.negative === 0 && num.negative !== 0) {
|
|
num.negative = 0;
|
|
r = this.isub(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
}
|
|
|
|
// a.length > b.length
|
|
var a, b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
|
|
this.length = a.length;
|
|
if (carry !== 0) {
|
|
this.words[this.length] = carry;
|
|
this.length++;
|
|
// Copy the rest of the words
|
|
} else if (a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Add `num` to `this`
|
|
BN.prototype.add = function add (num) {
|
|
var res;
|
|
if (num.negative !== 0 && this.negative === 0) {
|
|
num.negative = 0;
|
|
res = this.sub(num);
|
|
num.negative ^= 1;
|
|
return res;
|
|
} else if (num.negative === 0 && this.negative !== 0) {
|
|
this.negative = 0;
|
|
res = num.sub(this);
|
|
this.negative = 1;
|
|
return res;
|
|
}
|
|
|
|
if (this.length > num.length) return this.clone().iadd(num);
|
|
|
|
return num.clone().iadd(this);
|
|
};
|
|
|
|
// Subtract `num` from `this` in-place
|
|
BN.prototype.isub = function isub (num) {
|
|
// this - (-num) = this + num
|
|
if (num.negative !== 0) {
|
|
num.negative = 0;
|
|
var r = this.iadd(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
|
|
// -this - num = -(this + num)
|
|
} else if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iadd(num);
|
|
this.negative = 1;
|
|
return this._normSign();
|
|
}
|
|
|
|
// At this point both numbers are positive
|
|
var cmp = this.cmp(num);
|
|
|
|
// Optimization - zeroify
|
|
if (cmp === 0) {
|
|
this.negative = 0;
|
|
this.length = 1;
|
|
this.words[0] = 0;
|
|
return this;
|
|
}
|
|
|
|
// a > b
|
|
var a, b;
|
|
if (cmp > 0) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
|
|
// Copy rest of the words
|
|
if (carry === 0 && i < a.length && a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = Math.max(this.length, i);
|
|
|
|
if (a !== this) {
|
|
this.negative = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Subtract `num` from `this`
|
|
BN.prototype.sub = function sub (num) {
|
|
return this.clone().isub(num);
|
|
};
|
|
|
|
function smallMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
var len = (self.length + num.length) | 0;
|
|
out.length = len;
|
|
len = (len - 1) | 0;
|
|
|
|
// Peel one iteration (compiler can't do it, because of code complexity)
|
|
var a = self.words[0] | 0;
|
|
var b = num.words[0] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
var carry = (r / 0x4000000) | 0;
|
|
out.words[0] = lo;
|
|
|
|
for (var k = 1; k < len; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = carry >>> 26;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = (k - j) | 0;
|
|
a = self.words[i] | 0;
|
|
b = num.words[j] | 0;
|
|
r = a * b + rword;
|
|
ncarry += (r / 0x4000000) | 0;
|
|
rword = r & 0x3ffffff;
|
|
}
|
|
out.words[k] = rword | 0;
|
|
carry = ncarry | 0;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry | 0;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
// TODO(indutny): it may be reasonable to omit it for users who don't need
|
|
// to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
|
|
// multiplication (like elliptic secp256k1).
|
|
var comb10MulTo = function comb10MulTo (self, num, out) {
|
|
var a = self.words;
|
|
var b = num.words;
|
|
var o = out.words;
|
|
var c = 0;
|
|
var lo;
|
|
var mid;
|
|
var hi;
|
|
var a0 = a[0] | 0;
|
|
var al0 = a0 & 0x1fff;
|
|
var ah0 = a0 >>> 13;
|
|
var a1 = a[1] | 0;
|
|
var al1 = a1 & 0x1fff;
|
|
var ah1 = a1 >>> 13;
|
|
var a2 = a[2] | 0;
|
|
var al2 = a2 & 0x1fff;
|
|
var ah2 = a2 >>> 13;
|
|
var a3 = a[3] | 0;
|
|
var al3 = a3 & 0x1fff;
|
|
var ah3 = a3 >>> 13;
|
|
var a4 = a[4] | 0;
|
|
var al4 = a4 & 0x1fff;
|
|
var ah4 = a4 >>> 13;
|
|
var a5 = a[5] | 0;
|
|
var al5 = a5 & 0x1fff;
|
|
var ah5 = a5 >>> 13;
|
|
var a6 = a[6] | 0;
|
|
var al6 = a6 & 0x1fff;
|
|
var ah6 = a6 >>> 13;
|
|
var a7 = a[7] | 0;
|
|
var al7 = a7 & 0x1fff;
|
|
var ah7 = a7 >>> 13;
|
|
var a8 = a[8] | 0;
|
|
var al8 = a8 & 0x1fff;
|
|
var ah8 = a8 >>> 13;
|
|
var a9 = a[9] | 0;
|
|
var al9 = a9 & 0x1fff;
|
|
var ah9 = a9 >>> 13;
|
|
var b0 = b[0] | 0;
|
|
var bl0 = b0 & 0x1fff;
|
|
var bh0 = b0 >>> 13;
|
|
var b1 = b[1] | 0;
|
|
var bl1 = b1 & 0x1fff;
|
|
var bh1 = b1 >>> 13;
|
|
var b2 = b[2] | 0;
|
|
var bl2 = b2 & 0x1fff;
|
|
var bh2 = b2 >>> 13;
|
|
var b3 = b[3] | 0;
|
|
var bl3 = b3 & 0x1fff;
|
|
var bh3 = b3 >>> 13;
|
|
var b4 = b[4] | 0;
|
|
var bl4 = b4 & 0x1fff;
|
|
var bh4 = b4 >>> 13;
|
|
var b5 = b[5] | 0;
|
|
var bl5 = b5 & 0x1fff;
|
|
var bh5 = b5 >>> 13;
|
|
var b6 = b[6] | 0;
|
|
var bl6 = b6 & 0x1fff;
|
|
var bh6 = b6 >>> 13;
|
|
var b7 = b[7] | 0;
|
|
var bl7 = b7 & 0x1fff;
|
|
var bh7 = b7 >>> 13;
|
|
var b8 = b[8] | 0;
|
|
var bl8 = b8 & 0x1fff;
|
|
var bh8 = b8 >>> 13;
|
|
var b9 = b[9] | 0;
|
|
var bl9 = b9 & 0x1fff;
|
|
var bh9 = b9 >>> 13;
|
|
|
|
out.negative = self.negative ^ num.negative;
|
|
out.length = 19;
|
|
/* k = 0 */
|
|
lo = Math.imul(al0, bl0);
|
|
mid = Math.imul(al0, bh0);
|
|
mid = (mid + Math.imul(ah0, bl0)) | 0;
|
|
hi = Math.imul(ah0, bh0);
|
|
var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
|
|
w0 &= 0x3ffffff;
|
|
/* k = 1 */
|
|
lo = Math.imul(al1, bl0);
|
|
mid = Math.imul(al1, bh0);
|
|
mid = (mid + Math.imul(ah1, bl0)) | 0;
|
|
hi = Math.imul(ah1, bh0);
|
|
lo = (lo + Math.imul(al0, bl1)) | 0;
|
|
mid = (mid + Math.imul(al0, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh1)) | 0;
|
|
var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
|
|
w1 &= 0x3ffffff;
|
|
/* k = 2 */
|
|
lo = Math.imul(al2, bl0);
|
|
mid = Math.imul(al2, bh0);
|
|
mid = (mid + Math.imul(ah2, bl0)) | 0;
|
|
hi = Math.imul(ah2, bh0);
|
|
lo = (lo + Math.imul(al1, bl1)) | 0;
|
|
mid = (mid + Math.imul(al1, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh1)) | 0;
|
|
lo = (lo + Math.imul(al0, bl2)) | 0;
|
|
mid = (mid + Math.imul(al0, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh2)) | 0;
|
|
var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
|
|
w2 &= 0x3ffffff;
|
|
/* k = 3 */
|
|
lo = Math.imul(al3, bl0);
|
|
mid = Math.imul(al3, bh0);
|
|
mid = (mid + Math.imul(ah3, bl0)) | 0;
|
|
hi = Math.imul(ah3, bh0);
|
|
lo = (lo + Math.imul(al2, bl1)) | 0;
|
|
mid = (mid + Math.imul(al2, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh1)) | 0;
|
|
lo = (lo + Math.imul(al1, bl2)) | 0;
|
|
mid = (mid + Math.imul(al1, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh2)) | 0;
|
|
lo = (lo + Math.imul(al0, bl3)) | 0;
|
|
mid = (mid + Math.imul(al0, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh3)) | 0;
|
|
var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
|
|
w3 &= 0x3ffffff;
|
|
/* k = 4 */
|
|
lo = Math.imul(al4, bl0);
|
|
mid = Math.imul(al4, bh0);
|
|
mid = (mid + Math.imul(ah4, bl0)) | 0;
|
|
hi = Math.imul(ah4, bh0);
|
|
lo = (lo + Math.imul(al3, bl1)) | 0;
|
|
mid = (mid + Math.imul(al3, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh1)) | 0;
|
|
lo = (lo + Math.imul(al2, bl2)) | 0;
|
|
mid = (mid + Math.imul(al2, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh2)) | 0;
|
|
lo = (lo + Math.imul(al1, bl3)) | 0;
|
|
mid = (mid + Math.imul(al1, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh3)) | 0;
|
|
lo = (lo + Math.imul(al0, bl4)) | 0;
|
|
mid = (mid + Math.imul(al0, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh4)) | 0;
|
|
var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
|
|
w4 &= 0x3ffffff;
|
|
/* k = 5 */
|
|
lo = Math.imul(al5, bl0);
|
|
mid = Math.imul(al5, bh0);
|
|
mid = (mid + Math.imul(ah5, bl0)) | 0;
|
|
hi = Math.imul(ah5, bh0);
|
|
lo = (lo + Math.imul(al4, bl1)) | 0;
|
|
mid = (mid + Math.imul(al4, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh1)) | 0;
|
|
lo = (lo + Math.imul(al3, bl2)) | 0;
|
|
mid = (mid + Math.imul(al3, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh2)) | 0;
|
|
lo = (lo + Math.imul(al2, bl3)) | 0;
|
|
mid = (mid + Math.imul(al2, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh3)) | 0;
|
|
lo = (lo + Math.imul(al1, bl4)) | 0;
|
|
mid = (mid + Math.imul(al1, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh4)) | 0;
|
|
lo = (lo + Math.imul(al0, bl5)) | 0;
|
|
mid = (mid + Math.imul(al0, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh5)) | 0;
|
|
var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
|
|
w5 &= 0x3ffffff;
|
|
/* k = 6 */
|
|
lo = Math.imul(al6, bl0);
|
|
mid = Math.imul(al6, bh0);
|
|
mid = (mid + Math.imul(ah6, bl0)) | 0;
|
|
hi = Math.imul(ah6, bh0);
|
|
lo = (lo + Math.imul(al5, bl1)) | 0;
|
|
mid = (mid + Math.imul(al5, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh1)) | 0;
|
|
lo = (lo + Math.imul(al4, bl2)) | 0;
|
|
mid = (mid + Math.imul(al4, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh2)) | 0;
|
|
lo = (lo + Math.imul(al3, bl3)) | 0;
|
|
mid = (mid + Math.imul(al3, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh3)) | 0;
|
|
lo = (lo + Math.imul(al2, bl4)) | 0;
|
|
mid = (mid + Math.imul(al2, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh4)) | 0;
|
|
lo = (lo + Math.imul(al1, bl5)) | 0;
|
|
mid = (mid + Math.imul(al1, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh5)) | 0;
|
|
lo = (lo + Math.imul(al0, bl6)) | 0;
|
|
mid = (mid + Math.imul(al0, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh6)) | 0;
|
|
var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
|
|
w6 &= 0x3ffffff;
|
|
/* k = 7 */
|
|
lo = Math.imul(al7, bl0);
|
|
mid = Math.imul(al7, bh0);
|
|
mid = (mid + Math.imul(ah7, bl0)) | 0;
|
|
hi = Math.imul(ah7, bh0);
|
|
lo = (lo + Math.imul(al6, bl1)) | 0;
|
|
mid = (mid + Math.imul(al6, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh1)) | 0;
|
|
lo = (lo + Math.imul(al5, bl2)) | 0;
|
|
mid = (mid + Math.imul(al5, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh2)) | 0;
|
|
lo = (lo + Math.imul(al4, bl3)) | 0;
|
|
mid = (mid + Math.imul(al4, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh3)) | 0;
|
|
lo = (lo + Math.imul(al3, bl4)) | 0;
|
|
mid = (mid + Math.imul(al3, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh4)) | 0;
|
|
lo = (lo + Math.imul(al2, bl5)) | 0;
|
|
mid = (mid + Math.imul(al2, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh5)) | 0;
|
|
lo = (lo + Math.imul(al1, bl6)) | 0;
|
|
mid = (mid + Math.imul(al1, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh6)) | 0;
|
|
lo = (lo + Math.imul(al0, bl7)) | 0;
|
|
mid = (mid + Math.imul(al0, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh7)) | 0;
|
|
var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
|
|
w7 &= 0x3ffffff;
|
|
/* k = 8 */
|
|
lo = Math.imul(al8, bl0);
|
|
mid = Math.imul(al8, bh0);
|
|
mid = (mid + Math.imul(ah8, bl0)) | 0;
|
|
hi = Math.imul(ah8, bh0);
|
|
lo = (lo + Math.imul(al7, bl1)) | 0;
|
|
mid = (mid + Math.imul(al7, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh1)) | 0;
|
|
lo = (lo + Math.imul(al6, bl2)) | 0;
|
|
mid = (mid + Math.imul(al6, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh2)) | 0;
|
|
lo = (lo + Math.imul(al5, bl3)) | 0;
|
|
mid = (mid + Math.imul(al5, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh3)) | 0;
|
|
lo = (lo + Math.imul(al4, bl4)) | 0;
|
|
mid = (mid + Math.imul(al4, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh4)) | 0;
|
|
lo = (lo + Math.imul(al3, bl5)) | 0;
|
|
mid = (mid + Math.imul(al3, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh5)) | 0;
|
|
lo = (lo + Math.imul(al2, bl6)) | 0;
|
|
mid = (mid + Math.imul(al2, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh6)) | 0;
|
|
lo = (lo + Math.imul(al1, bl7)) | 0;
|
|
mid = (mid + Math.imul(al1, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh7)) | 0;
|
|
lo = (lo + Math.imul(al0, bl8)) | 0;
|
|
mid = (mid + Math.imul(al0, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh8)) | 0;
|
|
var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
|
|
w8 &= 0x3ffffff;
|
|
/* k = 9 */
|
|
lo = Math.imul(al9, bl0);
|
|
mid = Math.imul(al9, bh0);
|
|
mid = (mid + Math.imul(ah9, bl0)) | 0;
|
|
hi = Math.imul(ah9, bh0);
|
|
lo = (lo + Math.imul(al8, bl1)) | 0;
|
|
mid = (mid + Math.imul(al8, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh1)) | 0;
|
|
lo = (lo + Math.imul(al7, bl2)) | 0;
|
|
mid = (mid + Math.imul(al7, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh2)) | 0;
|
|
lo = (lo + Math.imul(al6, bl3)) | 0;
|
|
mid = (mid + Math.imul(al6, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh3)) | 0;
|
|
lo = (lo + Math.imul(al5, bl4)) | 0;
|
|
mid = (mid + Math.imul(al5, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh4)) | 0;
|
|
lo = (lo + Math.imul(al4, bl5)) | 0;
|
|
mid = (mid + Math.imul(al4, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh5)) | 0;
|
|
lo = (lo + Math.imul(al3, bl6)) | 0;
|
|
mid = (mid + Math.imul(al3, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh6)) | 0;
|
|
lo = (lo + Math.imul(al2, bl7)) | 0;
|
|
mid = (mid + Math.imul(al2, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh7)) | 0;
|
|
lo = (lo + Math.imul(al1, bl8)) | 0;
|
|
mid = (mid + Math.imul(al1, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh8)) | 0;
|
|
lo = (lo + Math.imul(al0, bl9)) | 0;
|
|
mid = (mid + Math.imul(al0, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh9)) | 0;
|
|
var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
|
|
w9 &= 0x3ffffff;
|
|
/* k = 10 */
|
|
lo = Math.imul(al9, bl1);
|
|
mid = Math.imul(al9, bh1);
|
|
mid = (mid + Math.imul(ah9, bl1)) | 0;
|
|
hi = Math.imul(ah9, bh1);
|
|
lo = (lo + Math.imul(al8, bl2)) | 0;
|
|
mid = (mid + Math.imul(al8, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh2)) | 0;
|
|
lo = (lo + Math.imul(al7, bl3)) | 0;
|
|
mid = (mid + Math.imul(al7, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh3)) | 0;
|
|
lo = (lo + Math.imul(al6, bl4)) | 0;
|
|
mid = (mid + Math.imul(al6, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh4)) | 0;
|
|
lo = (lo + Math.imul(al5, bl5)) | 0;
|
|
mid = (mid + Math.imul(al5, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh5)) | 0;
|
|
lo = (lo + Math.imul(al4, bl6)) | 0;
|
|
mid = (mid + Math.imul(al4, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh6)) | 0;
|
|
lo = (lo + Math.imul(al3, bl7)) | 0;
|
|
mid = (mid + Math.imul(al3, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh7)) | 0;
|
|
lo = (lo + Math.imul(al2, bl8)) | 0;
|
|
mid = (mid + Math.imul(al2, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh8)) | 0;
|
|
lo = (lo + Math.imul(al1, bl9)) | 0;
|
|
mid = (mid + Math.imul(al1, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh9)) | 0;
|
|
var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
|
|
w10 &= 0x3ffffff;
|
|
/* k = 11 */
|
|
lo = Math.imul(al9, bl2);
|
|
mid = Math.imul(al9, bh2);
|
|
mid = (mid + Math.imul(ah9, bl2)) | 0;
|
|
hi = Math.imul(ah9, bh2);
|
|
lo = (lo + Math.imul(al8, bl3)) | 0;
|
|
mid = (mid + Math.imul(al8, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh3)) | 0;
|
|
lo = (lo + Math.imul(al7, bl4)) | 0;
|
|
mid = (mid + Math.imul(al7, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh4)) | 0;
|
|
lo = (lo + Math.imul(al6, bl5)) | 0;
|
|
mid = (mid + Math.imul(al6, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh5)) | 0;
|
|
lo = (lo + Math.imul(al5, bl6)) | 0;
|
|
mid = (mid + Math.imul(al5, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh6)) | 0;
|
|
lo = (lo + Math.imul(al4, bl7)) | 0;
|
|
mid = (mid + Math.imul(al4, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh7)) | 0;
|
|
lo = (lo + Math.imul(al3, bl8)) | 0;
|
|
mid = (mid + Math.imul(al3, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh8)) | 0;
|
|
lo = (lo + Math.imul(al2, bl9)) | 0;
|
|
mid = (mid + Math.imul(al2, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh9)) | 0;
|
|
var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
|
|
w11 &= 0x3ffffff;
|
|
/* k = 12 */
|
|
lo = Math.imul(al9, bl3);
|
|
mid = Math.imul(al9, bh3);
|
|
mid = (mid + Math.imul(ah9, bl3)) | 0;
|
|
hi = Math.imul(ah9, bh3);
|
|
lo = (lo + Math.imul(al8, bl4)) | 0;
|
|
mid = (mid + Math.imul(al8, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh4)) | 0;
|
|
lo = (lo + Math.imul(al7, bl5)) | 0;
|
|
mid = (mid + Math.imul(al7, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh5)) | 0;
|
|
lo = (lo + Math.imul(al6, bl6)) | 0;
|
|
mid = (mid + Math.imul(al6, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh6)) | 0;
|
|
lo = (lo + Math.imul(al5, bl7)) | 0;
|
|
mid = (mid + Math.imul(al5, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh7)) | 0;
|
|
lo = (lo + Math.imul(al4, bl8)) | 0;
|
|
mid = (mid + Math.imul(al4, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh8)) | 0;
|
|
lo = (lo + Math.imul(al3, bl9)) | 0;
|
|
mid = (mid + Math.imul(al3, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh9)) | 0;
|
|
var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
|
|
w12 &= 0x3ffffff;
|
|
/* k = 13 */
|
|
lo = Math.imul(al9, bl4);
|
|
mid = Math.imul(al9, bh4);
|
|
mid = (mid + Math.imul(ah9, bl4)) | 0;
|
|
hi = Math.imul(ah9, bh4);
|
|
lo = (lo + Math.imul(al8, bl5)) | 0;
|
|
mid = (mid + Math.imul(al8, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh5)) | 0;
|
|
lo = (lo + Math.imul(al7, bl6)) | 0;
|
|
mid = (mid + Math.imul(al7, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh6)) | 0;
|
|
lo = (lo + Math.imul(al6, bl7)) | 0;
|
|
mid = (mid + Math.imul(al6, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh7)) | 0;
|
|
lo = (lo + Math.imul(al5, bl8)) | 0;
|
|
mid = (mid + Math.imul(al5, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh8)) | 0;
|
|
lo = (lo + Math.imul(al4, bl9)) | 0;
|
|
mid = (mid + Math.imul(al4, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh9)) | 0;
|
|
var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
|
|
w13 &= 0x3ffffff;
|
|
/* k = 14 */
|
|
lo = Math.imul(al9, bl5);
|
|
mid = Math.imul(al9, bh5);
|
|
mid = (mid + Math.imul(ah9, bl5)) | 0;
|
|
hi = Math.imul(ah9, bh5);
|
|
lo = (lo + Math.imul(al8, bl6)) | 0;
|
|
mid = (mid + Math.imul(al8, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh6)) | 0;
|
|
lo = (lo + Math.imul(al7, bl7)) | 0;
|
|
mid = (mid + Math.imul(al7, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh7)) | 0;
|
|
lo = (lo + Math.imul(al6, bl8)) | 0;
|
|
mid = (mid + Math.imul(al6, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh8)) | 0;
|
|
lo = (lo + Math.imul(al5, bl9)) | 0;
|
|
mid = (mid + Math.imul(al5, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh9)) | 0;
|
|
var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
|
|
w14 &= 0x3ffffff;
|
|
/* k = 15 */
|
|
lo = Math.imul(al9, bl6);
|
|
mid = Math.imul(al9, bh6);
|
|
mid = (mid + Math.imul(ah9, bl6)) | 0;
|
|
hi = Math.imul(ah9, bh6);
|
|
lo = (lo + Math.imul(al8, bl7)) | 0;
|
|
mid = (mid + Math.imul(al8, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh7)) | 0;
|
|
lo = (lo + Math.imul(al7, bl8)) | 0;
|
|
mid = (mid + Math.imul(al7, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh8)) | 0;
|
|
lo = (lo + Math.imul(al6, bl9)) | 0;
|
|
mid = (mid + Math.imul(al6, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh9)) | 0;
|
|
var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
|
|
w15 &= 0x3ffffff;
|
|
/* k = 16 */
|
|
lo = Math.imul(al9, bl7);
|
|
mid = Math.imul(al9, bh7);
|
|
mid = (mid + Math.imul(ah9, bl7)) | 0;
|
|
hi = Math.imul(ah9, bh7);
|
|
lo = (lo + Math.imul(al8, bl8)) | 0;
|
|
mid = (mid + Math.imul(al8, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh8)) | 0;
|
|
lo = (lo + Math.imul(al7, bl9)) | 0;
|
|
mid = (mid + Math.imul(al7, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh9)) | 0;
|
|
var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
|
|
w16 &= 0x3ffffff;
|
|
/* k = 17 */
|
|
lo = Math.imul(al9, bl8);
|
|
mid = Math.imul(al9, bh8);
|
|
mid = (mid + Math.imul(ah9, bl8)) | 0;
|
|
hi = Math.imul(ah9, bh8);
|
|
lo = (lo + Math.imul(al8, bl9)) | 0;
|
|
mid = (mid + Math.imul(al8, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh9)) | 0;
|
|
var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
|
|
w17 &= 0x3ffffff;
|
|
/* k = 18 */
|
|
lo = Math.imul(al9, bl9);
|
|
mid = Math.imul(al9, bh9);
|
|
mid = (mid + Math.imul(ah9, bl9)) | 0;
|
|
hi = Math.imul(ah9, bh9);
|
|
var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
|
|
w18 &= 0x3ffffff;
|
|
o[0] = w0;
|
|
o[1] = w1;
|
|
o[2] = w2;
|
|
o[3] = w3;
|
|
o[4] = w4;
|
|
o[5] = w5;
|
|
o[6] = w6;
|
|
o[7] = w7;
|
|
o[8] = w8;
|
|
o[9] = w9;
|
|
o[10] = w10;
|
|
o[11] = w11;
|
|
o[12] = w12;
|
|
o[13] = w13;
|
|
o[14] = w14;
|
|
o[15] = w15;
|
|
o[16] = w16;
|
|
o[17] = w17;
|
|
o[18] = w18;
|
|
if (c !== 0) {
|
|
o[19] = c;
|
|
out.length++;
|
|
}
|
|
return out;
|
|
};
|
|
|
|
// Polyfill comb
|
|
if (!Math.imul) {
|
|
comb10MulTo = smallMulTo;
|
|
}
|
|
|
|
function bigMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
out.length = self.length + num.length;
|
|
|
|
var carry = 0;
|
|
var hncarry = 0;
|
|
for (var k = 0; k < out.length - 1; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = hncarry;
|
|
hncarry = 0;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = k - j;
|
|
var a = self.words[i] | 0;
|
|
var b = num.words[j] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
|
|
lo = (lo + rword) | 0;
|
|
rword = lo & 0x3ffffff;
|
|
ncarry = (ncarry + (lo >>> 26)) | 0;
|
|
|
|
hncarry += ncarry >>> 26;
|
|
ncarry &= 0x3ffffff;
|
|
}
|
|
out.words[k] = rword;
|
|
carry = ncarry;
|
|
ncarry = hncarry;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
function jumboMulTo (self, num, out) {
|
|
var fftm = new FFTM();
|
|
return fftm.mulp(self, num, out);
|
|
}
|
|
|
|
BN.prototype.mulTo = function mulTo (num, out) {
|
|
var res;
|
|
var len = this.length + num.length;
|
|
if (this.length === 10 && num.length === 10) {
|
|
res = comb10MulTo(this, num, out);
|
|
} else if (len < 63) {
|
|
res = smallMulTo(this, num, out);
|
|
} else if (len < 1024) {
|
|
res = bigMulTo(this, num, out);
|
|
} else {
|
|
res = jumboMulTo(this, num, out);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Cooley-Tukey algorithm for FFT
|
|
// slightly revisited to rely on looping instead of recursion
|
|
|
|
function FFTM (x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
FFTM.prototype.makeRBT = function makeRBT (N) {
|
|
var t = new Array(N);
|
|
var l = BN.prototype._countBits(N) - 1;
|
|
for (var i = 0; i < N; i++) {
|
|
t[i] = this.revBin(i, l, N);
|
|
}
|
|
|
|
return t;
|
|
};
|
|
|
|
// Returns binary-reversed representation of `x`
|
|
FFTM.prototype.revBin = function revBin (x, l, N) {
|
|
if (x === 0 || x === N - 1) return x;
|
|
|
|
var rb = 0;
|
|
for (var i = 0; i < l; i++) {
|
|
rb |= (x & 1) << (l - i - 1);
|
|
x >>= 1;
|
|
}
|
|
|
|
return rb;
|
|
};
|
|
|
|
// Performs "tweedling" phase, therefore 'emulating'
|
|
// behaviour of the recursive algorithm
|
|
FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
|
|
for (var i = 0; i < N; i++) {
|
|
rtws[i] = rws[rbt[i]];
|
|
itws[i] = iws[rbt[i]];
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
|
|
this.permute(rbt, rws, iws, rtws, itws, N);
|
|
|
|
for (var s = 1; s < N; s <<= 1) {
|
|
var l = s << 1;
|
|
|
|
var rtwdf = Math.cos(2 * Math.PI / l);
|
|
var itwdf = Math.sin(2 * Math.PI / l);
|
|
|
|
for (var p = 0; p < N; p += l) {
|
|
var rtwdf_ = rtwdf;
|
|
var itwdf_ = itwdf;
|
|
|
|
for (var j = 0; j < s; j++) {
|
|
var re = rtws[p + j];
|
|
var ie = itws[p + j];
|
|
|
|
var ro = rtws[p + j + s];
|
|
var io = itws[p + j + s];
|
|
|
|
var rx = rtwdf_ * ro - itwdf_ * io;
|
|
|
|
io = rtwdf_ * io + itwdf_ * ro;
|
|
ro = rx;
|
|
|
|
rtws[p + j] = re + ro;
|
|
itws[p + j] = ie + io;
|
|
|
|
rtws[p + j + s] = re - ro;
|
|
itws[p + j + s] = ie - io;
|
|
|
|
/* jshint maxdepth : false */
|
|
if (j !== l) {
|
|
rx = rtwdf * rtwdf_ - itwdf * itwdf_;
|
|
|
|
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
|
|
rtwdf_ = rx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
|
|
var N = Math.max(m, n) | 1;
|
|
var odd = N & 1;
|
|
var i = 0;
|
|
for (N = N / 2 | 0; N; N = N >>> 1) {
|
|
i++;
|
|
}
|
|
|
|
return 1 << i + 1 + odd;
|
|
};
|
|
|
|
FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
|
|
if (N <= 1) return;
|
|
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var t = rws[i];
|
|
|
|
rws[i] = rws[N - i - 1];
|
|
rws[N - i - 1] = t;
|
|
|
|
t = iws[i];
|
|
|
|
iws[i] = -iws[N - i - 1];
|
|
iws[N - i - 1] = -t;
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.normalize13b = function normalize13b (ws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
|
|
Math.round(ws[2 * i] / N) +
|
|
carry;
|
|
|
|
ws[i] = w & 0x3ffffff;
|
|
|
|
if (w < 0x4000000) {
|
|
carry = 0;
|
|
} else {
|
|
carry = w / 0x4000000 | 0;
|
|
}
|
|
}
|
|
|
|
return ws;
|
|
};
|
|
|
|
FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < len; i++) {
|
|
carry = carry + (ws[i] | 0);
|
|
|
|
rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
|
|
rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
|
|
}
|
|
|
|
// Pad with zeroes
|
|
for (i = 2 * len; i < N; ++i) {
|
|
rws[i] = 0;
|
|
}
|
|
|
|
assert(carry === 0);
|
|
assert((carry & ~0x1fff) === 0);
|
|
};
|
|
|
|
FFTM.prototype.stub = function stub (N) {
|
|
var ph = new Array(N);
|
|
for (var i = 0; i < N; i++) {
|
|
ph[i] = 0;
|
|
}
|
|
|
|
return ph;
|
|
};
|
|
|
|
FFTM.prototype.mulp = function mulp (x, y, out) {
|
|
var N = 2 * this.guessLen13b(x.length, y.length);
|
|
|
|
var rbt = this.makeRBT(N);
|
|
|
|
var _ = this.stub(N);
|
|
|
|
var rws = new Array(N);
|
|
var rwst = new Array(N);
|
|
var iwst = new Array(N);
|
|
|
|
var nrws = new Array(N);
|
|
var nrwst = new Array(N);
|
|
var niwst = new Array(N);
|
|
|
|
var rmws = out.words;
|
|
rmws.length = N;
|
|
|
|
this.convert13b(x.words, x.length, rws, N);
|
|
this.convert13b(y.words, y.length, nrws, N);
|
|
|
|
this.transform(rws, _, rwst, iwst, N, rbt);
|
|
this.transform(nrws, _, nrwst, niwst, N, rbt);
|
|
|
|
for (var i = 0; i < N; i++) {
|
|
var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
|
|
iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
|
|
rwst[i] = rx;
|
|
}
|
|
|
|
this.conjugate(rwst, iwst, N);
|
|
this.transform(rwst, iwst, rmws, _, N, rbt);
|
|
this.conjugate(rmws, _, N);
|
|
this.normalize13b(rmws, N);
|
|
|
|
out.negative = x.negative ^ y.negative;
|
|
out.length = x.length + y.length;
|
|
return out.strip();
|
|
};
|
|
|
|
// Multiply `this` by `num`
|
|
BN.prototype.mul = function mul (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return this.mulTo(num, out);
|
|
};
|
|
|
|
// Multiply employing FFT
|
|
BN.prototype.mulf = function mulf (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return jumboMulTo(this, num, out);
|
|
};
|
|
|
|
// In-place Multiplication
|
|
BN.prototype.imul = function imul (num) {
|
|
return this.clone().mulTo(num, this);
|
|
};
|
|
|
|
BN.prototype.imuln = function imuln (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
|
|
// Carry
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = (this.words[i] | 0) * num;
|
|
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
|
|
carry >>= 26;
|
|
carry += (w / 0x4000000) | 0;
|
|
// NOTE: lo is 27bit maximum
|
|
carry += lo >>> 26;
|
|
this.words[i] = lo & 0x3ffffff;
|
|
}
|
|
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.muln = function muln (num) {
|
|
return this.clone().imuln(num);
|
|
};
|
|
|
|
// `this` * `this`
|
|
BN.prototype.sqr = function sqr () {
|
|
return this.mul(this);
|
|
};
|
|
|
|
// `this` * `this` in-place
|
|
BN.prototype.isqr = function isqr () {
|
|
return this.imul(this.clone());
|
|
};
|
|
|
|
// Math.pow(`this`, `num`)
|
|
BN.prototype.pow = function pow (num) {
|
|
var w = toBitArray(num);
|
|
if (w.length === 0) return new BN(1);
|
|
|
|
// Skip leading zeroes
|
|
var res = this;
|
|
for (var i = 0; i < w.length; i++, res = res.sqr()) {
|
|
if (w[i] !== 0) break;
|
|
}
|
|
|
|
if (++i < w.length) {
|
|
for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
|
|
if (w[i] === 0) continue;
|
|
|
|
res = res.mul(q);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Shift-left in-place
|
|
BN.prototype.iushln = function iushln (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
|
|
var i;
|
|
|
|
if (r !== 0) {
|
|
var carry = 0;
|
|
|
|
for (i = 0; i < this.length; i++) {
|
|
var newCarry = this.words[i] & carryMask;
|
|
var c = ((this.words[i] | 0) - newCarry) << r;
|
|
this.words[i] = c | carry;
|
|
carry = newCarry >>> (26 - r);
|
|
}
|
|
|
|
if (carry) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
}
|
|
|
|
if (s !== 0) {
|
|
for (i = this.length - 1; i >= 0; i--) {
|
|
this.words[i + s] = this.words[i];
|
|
}
|
|
|
|
for (i = 0; i < s; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
this.length += s;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishln = function ishln (bits) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushln(bits);
|
|
};
|
|
|
|
// Shift-right in-place
|
|
// NOTE: `hint` is a lowest bit before trailing zeroes
|
|
// NOTE: if `extended` is present - it will be filled with destroyed bits
|
|
BN.prototype.iushrn = function iushrn (bits, hint, extended) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var h;
|
|
if (hint) {
|
|
h = (hint - (hint % 26)) / 26;
|
|
} else {
|
|
h = 0;
|
|
}
|
|
|
|
var r = bits % 26;
|
|
var s = Math.min((bits - r) / 26, this.length);
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
var maskedWords = extended;
|
|
|
|
h -= s;
|
|
h = Math.max(0, h);
|
|
|
|
// Extended mode, copy masked part
|
|
if (maskedWords) {
|
|
for (var i = 0; i < s; i++) {
|
|
maskedWords.words[i] = this.words[i];
|
|
}
|
|
maskedWords.length = s;
|
|
}
|
|
|
|
if (s === 0) {
|
|
// No-op, we should not move anything at all
|
|
} else if (this.length > s) {
|
|
this.length -= s;
|
|
for (i = 0; i < this.length; i++) {
|
|
this.words[i] = this.words[i + s];
|
|
}
|
|
} else {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
|
|
var word = this.words[i] | 0;
|
|
this.words[i] = (carry << (26 - r)) | (word >>> r);
|
|
carry = word & mask;
|
|
}
|
|
|
|
// Push carried bits as a mask
|
|
if (maskedWords && carry !== 0) {
|
|
maskedWords.words[maskedWords.length++] = carry;
|
|
}
|
|
|
|
if (this.length === 0) {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishrn = function ishrn (bits, hint, extended) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushrn(bits, hint, extended);
|
|
};
|
|
|
|
// Shift-left
|
|
BN.prototype.shln = function shln (bits) {
|
|
return this.clone().ishln(bits);
|
|
};
|
|
|
|
BN.prototype.ushln = function ushln (bits) {
|
|
return this.clone().iushln(bits);
|
|
};
|
|
|
|
// Shift-right
|
|
BN.prototype.shrn = function shrn (bits) {
|
|
return this.clone().ishrn(bits);
|
|
};
|
|
|
|
BN.prototype.ushrn = function ushrn (bits) {
|
|
return this.clone().iushrn(bits);
|
|
};
|
|
|
|
// Test if n bit is set
|
|
BN.prototype.testn = function testn (bit) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) return false;
|
|
|
|
// Check bit and return
|
|
var w = this.words[s];
|
|
|
|
return !!(w & q);
|
|
};
|
|
|
|
// Return only lowers bits of number (in-place)
|
|
BN.prototype.imaskn = function imaskn (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
|
|
assert(this.negative === 0, 'imaskn works only with positive numbers');
|
|
|
|
if (this.length <= s) {
|
|
return this;
|
|
}
|
|
|
|
if (r !== 0) {
|
|
s++;
|
|
}
|
|
this.length = Math.min(s, this.length);
|
|
|
|
if (r !== 0) {
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
this.words[this.length - 1] &= mask;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Return only lowers bits of number
|
|
BN.prototype.maskn = function maskn (bits) {
|
|
return this.clone().imaskn(bits);
|
|
};
|
|
|
|
// Add plain number `num` to `this`
|
|
BN.prototype.iaddn = function iaddn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.isubn(-num);
|
|
|
|
// Possible sign change
|
|
if (this.negative !== 0) {
|
|
if (this.length === 1 && (this.words[0] | 0) < num) {
|
|
this.words[0] = num - (this.words[0] | 0);
|
|
this.negative = 0;
|
|
return this;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.isubn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
// Add without checks
|
|
return this._iaddn(num);
|
|
};
|
|
|
|
BN.prototype._iaddn = function _iaddn (num) {
|
|
this.words[0] += num;
|
|
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
|
|
this.words[i] -= 0x4000000;
|
|
if (i === this.length - 1) {
|
|
this.words[i + 1] = 1;
|
|
} else {
|
|
this.words[i + 1]++;
|
|
}
|
|
}
|
|
this.length = Math.max(this.length, i + 1);
|
|
|
|
return this;
|
|
};
|
|
|
|
// Subtract plain number `num` from `this`
|
|
BN.prototype.isubn = function isubn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.iaddn(-num);
|
|
|
|
if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iaddn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
this.words[0] -= num;
|
|
|
|
if (this.length === 1 && this.words[0] < 0) {
|
|
this.words[0] = -this.words[0];
|
|
this.negative = 1;
|
|
} else {
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
|
|
this.words[i] += 0x4000000;
|
|
this.words[i + 1] -= 1;
|
|
}
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.addn = function addn (num) {
|
|
return this.clone().iaddn(num);
|
|
};
|
|
|
|
BN.prototype.subn = function subn (num) {
|
|
return this.clone().isubn(num);
|
|
};
|
|
|
|
BN.prototype.iabs = function iabs () {
|
|
this.negative = 0;
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.abs = function abs () {
|
|
return this.clone().iabs();
|
|
};
|
|
|
|
BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
|
|
var len = num.length + shift;
|
|
var i;
|
|
|
|
this._expand(len);
|
|
|
|
var w;
|
|
var carry = 0;
|
|
for (i = 0; i < num.length; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
var right = (num.words[i] | 0) * mul;
|
|
w -= right & 0x3ffffff;
|
|
carry = (w >> 26) - ((right / 0x4000000) | 0);
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
for (; i < this.length - shift; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
|
|
if (carry === 0) return this.strip();
|
|
|
|
// Subtraction overflow
|
|
assert(carry === -1);
|
|
carry = 0;
|
|
for (i = 0; i < this.length; i++) {
|
|
w = -(this.words[i] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i] = w & 0x3ffffff;
|
|
}
|
|
this.negative = 1;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype._wordDiv = function _wordDiv (num, mode) {
|
|
var shift = this.length - num.length;
|
|
|
|
var a = this.clone();
|
|
var b = num;
|
|
|
|
// Normalize
|
|
var bhi = b.words[b.length - 1] | 0;
|
|
var bhiBits = this._countBits(bhi);
|
|
shift = 26 - bhiBits;
|
|
if (shift !== 0) {
|
|
b = b.ushln(shift);
|
|
a.iushln(shift);
|
|
bhi = b.words[b.length - 1] | 0;
|
|
}
|
|
|
|
// Initialize quotient
|
|
var m = a.length - b.length;
|
|
var q;
|
|
|
|
if (mode !== 'mod') {
|
|
q = new BN(null);
|
|
q.length = m + 1;
|
|
q.words = new Array(q.length);
|
|
for (var i = 0; i < q.length; i++) {
|
|
q.words[i] = 0;
|
|
}
|
|
}
|
|
|
|
var diff = a.clone()._ishlnsubmul(b, 1, m);
|
|
if (diff.negative === 0) {
|
|
a = diff;
|
|
if (q) {
|
|
q.words[m] = 1;
|
|
}
|
|
}
|
|
|
|
for (var j = m - 1; j >= 0; j--) {
|
|
var qj = (a.words[b.length + j] | 0) * 0x4000000 +
|
|
(a.words[b.length + j - 1] | 0);
|
|
|
|
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
|
|
// (0x7ffffff)
|
|
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
|
|
|
|
a._ishlnsubmul(b, qj, j);
|
|
while (a.negative !== 0) {
|
|
qj--;
|
|
a.negative = 0;
|
|
a._ishlnsubmul(b, 1, j);
|
|
if (!a.isZero()) {
|
|
a.negative ^= 1;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.words[j] = qj;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.strip();
|
|
}
|
|
a.strip();
|
|
|
|
// Denormalize
|
|
if (mode !== 'div' && shift !== 0) {
|
|
a.iushrn(shift);
|
|
}
|
|
|
|
return {
|
|
div: q || null,
|
|
mod: a
|
|
};
|
|
};
|
|
|
|
// NOTE: 1) `mode` can be set to `mod` to request mod only,
|
|
// to `div` to request div only, or be absent to
|
|
// request both div & mod
|
|
// 2) `positive` is true if unsigned mod is requested
|
|
BN.prototype.divmod = function divmod (num, mode, positive) {
|
|
assert(!num.isZero());
|
|
|
|
if (this.isZero()) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: new BN(0)
|
|
};
|
|
}
|
|
|
|
var div, mod, res;
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
res = this.neg().divmod(num, mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.iadd(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
if (this.negative === 0 && num.negative !== 0) {
|
|
res = this.divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: res.mod
|
|
};
|
|
}
|
|
|
|
if ((this.negative & num.negative) !== 0) {
|
|
res = this.neg().divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.isub(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: res.div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
// Both numbers are positive at this point
|
|
|
|
// Strip both numbers to approximate shift value
|
|
if (num.length > this.length || this.cmp(num) < 0) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: this
|
|
};
|
|
}
|
|
|
|
// Very short reduction
|
|
if (num.length === 1) {
|
|
if (mode === 'div') {
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: null
|
|
};
|
|
}
|
|
|
|
if (mode === 'mod') {
|
|
return {
|
|
div: null,
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return this._wordDiv(num, mode);
|
|
};
|
|
|
|
// Find `this` / `num`
|
|
BN.prototype.div = function div (num) {
|
|
return this.divmod(num, 'div', false).div;
|
|
};
|
|
|
|
// Find `this` % `num`
|
|
BN.prototype.mod = function mod (num) {
|
|
return this.divmod(num, 'mod', false).mod;
|
|
};
|
|
|
|
BN.prototype.umod = function umod (num) {
|
|
return this.divmod(num, 'mod', true).mod;
|
|
};
|
|
|
|
// Find Round(`this` / `num`)
|
|
BN.prototype.divRound = function divRound (num) {
|
|
var dm = this.divmod(num);
|
|
|
|
// Fast case - exact division
|
|
if (dm.mod.isZero()) return dm.div;
|
|
|
|
var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
|
|
|
|
var half = num.ushrn(1);
|
|
var r2 = num.andln(1);
|
|
var cmp = mod.cmp(half);
|
|
|
|
// Round down
|
|
if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
|
|
|
|
// Round up
|
|
return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
|
|
};
|
|
|
|
BN.prototype.modn = function modn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
var p = (1 << 26) % num;
|
|
|
|
var acc = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
acc = (p * acc + (this.words[i] | 0)) % num;
|
|
}
|
|
|
|
return acc;
|
|
};
|
|
|
|
// In-place division by number
|
|
BN.prototype.idivn = function idivn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
|
|
var carry = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var w = (this.words[i] | 0) + carry * 0x4000000;
|
|
this.words[i] = (w / num) | 0;
|
|
carry = w % num;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.divn = function divn (num) {
|
|
return this.clone().idivn(num);
|
|
};
|
|
|
|
BN.prototype.egcd = function egcd (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var x = this;
|
|
var y = p.clone();
|
|
|
|
if (x.negative !== 0) {
|
|
x = x.umod(p);
|
|
} else {
|
|
x = x.clone();
|
|
}
|
|
|
|
// A * x + B * y = x
|
|
var A = new BN(1);
|
|
var B = new BN(0);
|
|
|
|
// C * x + D * y = y
|
|
var C = new BN(0);
|
|
var D = new BN(1);
|
|
|
|
var g = 0;
|
|
|
|
while (x.isEven() && y.isEven()) {
|
|
x.iushrn(1);
|
|
y.iushrn(1);
|
|
++g;
|
|
}
|
|
|
|
var yp = y.clone();
|
|
var xp = x.clone();
|
|
|
|
while (!x.isZero()) {
|
|
for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
x.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (A.isOdd() || B.isOdd()) {
|
|
A.iadd(yp);
|
|
B.isub(xp);
|
|
}
|
|
|
|
A.iushrn(1);
|
|
B.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
y.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (C.isOdd() || D.isOdd()) {
|
|
C.iadd(yp);
|
|
D.isub(xp);
|
|
}
|
|
|
|
C.iushrn(1);
|
|
D.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (x.cmp(y) >= 0) {
|
|
x.isub(y);
|
|
A.isub(C);
|
|
B.isub(D);
|
|
} else {
|
|
y.isub(x);
|
|
C.isub(A);
|
|
D.isub(B);
|
|
}
|
|
}
|
|
|
|
return {
|
|
a: C,
|
|
b: D,
|
|
gcd: y.iushln(g)
|
|
};
|
|
};
|
|
|
|
// This is reduced incarnation of the binary EEA
|
|
// above, designated to invert members of the
|
|
// _prime_ fields F(p) at a maximal speed
|
|
BN.prototype._invmp = function _invmp (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var a = this;
|
|
var b = p.clone();
|
|
|
|
if (a.negative !== 0) {
|
|
a = a.umod(p);
|
|
} else {
|
|
a = a.clone();
|
|
}
|
|
|
|
var x1 = new BN(1);
|
|
var x2 = new BN(0);
|
|
|
|
var delta = b.clone();
|
|
|
|
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
|
|
for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
a.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (x1.isOdd()) {
|
|
x1.iadd(delta);
|
|
}
|
|
|
|
x1.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
b.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (x2.isOdd()) {
|
|
x2.iadd(delta);
|
|
}
|
|
|
|
x2.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (a.cmp(b) >= 0) {
|
|
a.isub(b);
|
|
x1.isub(x2);
|
|
} else {
|
|
b.isub(a);
|
|
x2.isub(x1);
|
|
}
|
|
}
|
|
|
|
var res;
|
|
if (a.cmpn(1) === 0) {
|
|
res = x1;
|
|
} else {
|
|
res = x2;
|
|
}
|
|
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(p);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gcd = function gcd (num) {
|
|
if (this.isZero()) return num.abs();
|
|
if (num.isZero()) return this.abs();
|
|
|
|
var a = this.clone();
|
|
var b = num.clone();
|
|
a.negative = 0;
|
|
b.negative = 0;
|
|
|
|
// Remove common factor of two
|
|
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
|
|
a.iushrn(1);
|
|
b.iushrn(1);
|
|
}
|
|
|
|
do {
|
|
while (a.isEven()) {
|
|
a.iushrn(1);
|
|
}
|
|
while (b.isEven()) {
|
|
b.iushrn(1);
|
|
}
|
|
|
|
var r = a.cmp(b);
|
|
if (r < 0) {
|
|
// Swap `a` and `b` to make `a` always bigger than `b`
|
|
var t = a;
|
|
a = b;
|
|
b = t;
|
|
} else if (r === 0 || b.cmpn(1) === 0) {
|
|
break;
|
|
}
|
|
|
|
a.isub(b);
|
|
} while (true);
|
|
|
|
return b.iushln(shift);
|
|
};
|
|
|
|
// Invert number in the field F(num)
|
|
BN.prototype.invm = function invm (num) {
|
|
return this.egcd(num).a.umod(num);
|
|
};
|
|
|
|
BN.prototype.isEven = function isEven () {
|
|
return (this.words[0] & 1) === 0;
|
|
};
|
|
|
|
BN.prototype.isOdd = function isOdd () {
|
|
return (this.words[0] & 1) === 1;
|
|
};
|
|
|
|
// And first word and num
|
|
BN.prototype.andln = function andln (num) {
|
|
return this.words[0] & num;
|
|
};
|
|
|
|
// Increment at the bit position in-line
|
|
BN.prototype.bincn = function bincn (bit) {
|
|
assert(typeof bit === 'number');
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) {
|
|
this._expand(s + 1);
|
|
this.words[s] |= q;
|
|
return this;
|
|
}
|
|
|
|
// Add bit and propagate, if needed
|
|
var carry = q;
|
|
for (var i = s; carry !== 0 && i < this.length; i++) {
|
|
var w = this.words[i] | 0;
|
|
w += carry;
|
|
carry = w >>> 26;
|
|
w &= 0x3ffffff;
|
|
this.words[i] = w;
|
|
}
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.isZero = function isZero () {
|
|
return this.length === 1 && this.words[0] === 0;
|
|
};
|
|
|
|
BN.prototype.cmpn = function cmpn (num) {
|
|
var negative = num < 0;
|
|
|
|
if (this.negative !== 0 && !negative) return -1;
|
|
if (this.negative === 0 && negative) return 1;
|
|
|
|
this.strip();
|
|
|
|
var res;
|
|
if (this.length > 1) {
|
|
res = 1;
|
|
} else {
|
|
if (negative) {
|
|
num = -num;
|
|
}
|
|
|
|
assert(num <= 0x3ffffff, 'Number is too big');
|
|
|
|
var w = this.words[0] | 0;
|
|
res = w === num ? 0 : w < num ? -1 : 1;
|
|
}
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Compare two numbers and return:
|
|
// 1 - if `this` > `num`
|
|
// 0 - if `this` == `num`
|
|
// -1 - if `this` < `num`
|
|
BN.prototype.cmp = function cmp (num) {
|
|
if (this.negative !== 0 && num.negative === 0) return -1;
|
|
if (this.negative === 0 && num.negative !== 0) return 1;
|
|
|
|
var res = this.ucmp(num);
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Unsigned comparison
|
|
BN.prototype.ucmp = function ucmp (num) {
|
|
// At this point both numbers have the same sign
|
|
if (this.length > num.length) return 1;
|
|
if (this.length < num.length) return -1;
|
|
|
|
var res = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var a = this.words[i] | 0;
|
|
var b = num.words[i] | 0;
|
|
|
|
if (a === b) continue;
|
|
if (a < b) {
|
|
res = -1;
|
|
} else if (a > b) {
|
|
res = 1;
|
|
}
|
|
break;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gtn = function gtn (num) {
|
|
return this.cmpn(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gt = function gt (num) {
|
|
return this.cmp(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gten = function gten (num) {
|
|
return this.cmpn(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.gte = function gte (num) {
|
|
return this.cmp(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.ltn = function ltn (num) {
|
|
return this.cmpn(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lt = function lt (num) {
|
|
return this.cmp(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lten = function lten (num) {
|
|
return this.cmpn(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.lte = function lte (num) {
|
|
return this.cmp(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.eqn = function eqn (num) {
|
|
return this.cmpn(num) === 0;
|
|
};
|
|
|
|
BN.prototype.eq = function eq (num) {
|
|
return this.cmp(num) === 0;
|
|
};
|
|
|
|
//
|
|
// A reduce context, could be using montgomery or something better, depending
|
|
// on the `m` itself.
|
|
//
|
|
BN.red = function red (num) {
|
|
return new Red(num);
|
|
};
|
|
|
|
BN.prototype.toRed = function toRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
assert(this.negative === 0, 'red works only with positives');
|
|
return ctx.convertTo(this)._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.fromRed = function fromRed () {
|
|
assert(this.red, 'fromRed works only with numbers in reduction context');
|
|
return this.red.convertFrom(this);
|
|
};
|
|
|
|
BN.prototype._forceRed = function _forceRed (ctx) {
|
|
this.red = ctx;
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.forceRed = function forceRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
return this._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.redAdd = function redAdd (num) {
|
|
assert(this.red, 'redAdd works only with red numbers');
|
|
return this.red.add(this, num);
|
|
};
|
|
|
|
BN.prototype.redIAdd = function redIAdd (num) {
|
|
assert(this.red, 'redIAdd works only with red numbers');
|
|
return this.red.iadd(this, num);
|
|
};
|
|
|
|
BN.prototype.redSub = function redSub (num) {
|
|
assert(this.red, 'redSub works only with red numbers');
|
|
return this.red.sub(this, num);
|
|
};
|
|
|
|
BN.prototype.redISub = function redISub (num) {
|
|
assert(this.red, 'redISub works only with red numbers');
|
|
return this.red.isub(this, num);
|
|
};
|
|
|
|
BN.prototype.redShl = function redShl (num) {
|
|
assert(this.red, 'redShl works only with red numbers');
|
|
return this.red.shl(this, num);
|
|
};
|
|
|
|
BN.prototype.redMul = function redMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.mul(this, num);
|
|
};
|
|
|
|
BN.prototype.redIMul = function redIMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.imul(this, num);
|
|
};
|
|
|
|
BN.prototype.redSqr = function redSqr () {
|
|
assert(this.red, 'redSqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqr(this);
|
|
};
|
|
|
|
BN.prototype.redISqr = function redISqr () {
|
|
assert(this.red, 'redISqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.isqr(this);
|
|
};
|
|
|
|
// Square root over p
|
|
BN.prototype.redSqrt = function redSqrt () {
|
|
assert(this.red, 'redSqrt works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqrt(this);
|
|
};
|
|
|
|
BN.prototype.redInvm = function redInvm () {
|
|
assert(this.red, 'redInvm works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.invm(this);
|
|
};
|
|
|
|
// Return negative clone of `this` % `red modulo`
|
|
BN.prototype.redNeg = function redNeg () {
|
|
assert(this.red, 'redNeg works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.neg(this);
|
|
};
|
|
|
|
BN.prototype.redPow = function redPow (num) {
|
|
assert(this.red && !num.red, 'redPow(normalNum)');
|
|
this.red._verify1(this);
|
|
return this.red.pow(this, num);
|
|
};
|
|
|
|
// Prime numbers with efficient reduction
|
|
var primes = {
|
|
k256: null,
|
|
p224: null,
|
|
p192: null,
|
|
p25519: null
|
|
};
|
|
|
|
// Pseudo-Mersenne prime
|
|
function MPrime (name, p) {
|
|
// P = 2 ^ N - K
|
|
this.name = name;
|
|
this.p = new BN(p, 16);
|
|
this.n = this.p.bitLength();
|
|
this.k = new BN(1).iushln(this.n).isub(this.p);
|
|
|
|
this.tmp = this._tmp();
|
|
}
|
|
|
|
MPrime.prototype._tmp = function _tmp () {
|
|
var tmp = new BN(null);
|
|
tmp.words = new Array(Math.ceil(this.n / 13));
|
|
return tmp;
|
|
};
|
|
|
|
MPrime.prototype.ireduce = function ireduce (num) {
|
|
// Assumes that `num` is less than `P^2`
|
|
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
|
|
var r = num;
|
|
var rlen;
|
|
|
|
do {
|
|
this.split(r, this.tmp);
|
|
r = this.imulK(r);
|
|
r = r.iadd(this.tmp);
|
|
rlen = r.bitLength();
|
|
} while (rlen > this.n);
|
|
|
|
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
|
|
if (cmp === 0) {
|
|
r.words[0] = 0;
|
|
r.length = 1;
|
|
} else if (cmp > 0) {
|
|
r.isub(this.p);
|
|
} else {
|
|
if (r.strip !== undefined) {
|
|
// r is BN v4 instance
|
|
r.strip();
|
|
} else {
|
|
// r is BN v5 instance
|
|
r._strip();
|
|
}
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
MPrime.prototype.split = function split (input, out) {
|
|
input.iushrn(this.n, 0, out);
|
|
};
|
|
|
|
MPrime.prototype.imulK = function imulK (num) {
|
|
return num.imul(this.k);
|
|
};
|
|
|
|
function K256 () {
|
|
MPrime.call(
|
|
this,
|
|
'k256',
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
|
|
}
|
|
inherits(K256, MPrime);
|
|
|
|
K256.prototype.split = function split (input, output) {
|
|
// 256 = 9 * 26 + 22
|
|
var mask = 0x3fffff;
|
|
|
|
var outLen = Math.min(input.length, 9);
|
|
for (var i = 0; i < outLen; i++) {
|
|
output.words[i] = input.words[i];
|
|
}
|
|
output.length = outLen;
|
|
|
|
if (input.length <= 9) {
|
|
input.words[0] = 0;
|
|
input.length = 1;
|
|
return;
|
|
}
|
|
|
|
// Shift by 9 limbs
|
|
var prev = input.words[9];
|
|
output.words[output.length++] = prev & mask;
|
|
|
|
for (i = 10; i < input.length; i++) {
|
|
var next = input.words[i] | 0;
|
|
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
|
|
prev = next;
|
|
}
|
|
prev >>>= 22;
|
|
input.words[i - 10] = prev;
|
|
if (prev === 0 && input.length > 10) {
|
|
input.length -= 10;
|
|
} else {
|
|
input.length -= 9;
|
|
}
|
|
};
|
|
|
|
K256.prototype.imulK = function imulK (num) {
|
|
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
|
|
num.words[num.length] = 0;
|
|
num.words[num.length + 1] = 0;
|
|
num.length += 2;
|
|
|
|
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
|
|
var lo = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var w = num.words[i] | 0;
|
|
lo += w * 0x3d1;
|
|
num.words[i] = lo & 0x3ffffff;
|
|
lo = w * 0x40 + ((lo / 0x4000000) | 0);
|
|
}
|
|
|
|
// Fast length reduction
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
}
|
|
}
|
|
return num;
|
|
};
|
|
|
|
function P224 () {
|
|
MPrime.call(
|
|
this,
|
|
'p224',
|
|
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
|
|
}
|
|
inherits(P224, MPrime);
|
|
|
|
function P192 () {
|
|
MPrime.call(
|
|
this,
|
|
'p192',
|
|
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
|
|
}
|
|
inherits(P192, MPrime);
|
|
|
|
function P25519 () {
|
|
// 2 ^ 255 - 19
|
|
MPrime.call(
|
|
this,
|
|
'25519',
|
|
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
|
|
}
|
|
inherits(P25519, MPrime);
|
|
|
|
P25519.prototype.imulK = function imulK (num) {
|
|
// K = 0x13
|
|
var carry = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var hi = (num.words[i] | 0) * 0x13 + carry;
|
|
var lo = hi & 0x3ffffff;
|
|
hi >>>= 26;
|
|
|
|
num.words[i] = lo;
|
|
carry = hi;
|
|
}
|
|
if (carry !== 0) {
|
|
num.words[num.length++] = carry;
|
|
}
|
|
return num;
|
|
};
|
|
|
|
// Exported mostly for testing purposes, use plain name instead
|
|
BN._prime = function prime (name) {
|
|
// Cached version of prime
|
|
if (primes[name]) return primes[name];
|
|
|
|
var prime;
|
|
if (name === 'k256') {
|
|
prime = new K256();
|
|
} else if (name === 'p224') {
|
|
prime = new P224();
|
|
} else if (name === 'p192') {
|
|
prime = new P192();
|
|
} else if (name === 'p25519') {
|
|
prime = new P25519();
|
|
} else {
|
|
throw new Error('Unknown prime ' + name);
|
|
}
|
|
primes[name] = prime;
|
|
|
|
return prime;
|
|
};
|
|
|
|
//
|
|
// Base reduction engine
|
|
//
|
|
function Red (m) {
|
|
if (typeof m === 'string') {
|
|
var prime = BN._prime(m);
|
|
this.m = prime.p;
|
|
this.prime = prime;
|
|
} else {
|
|
assert(m.gtn(1), 'modulus must be greater than 1');
|
|
this.m = m;
|
|
this.prime = null;
|
|
}
|
|
}
|
|
|
|
Red.prototype._verify1 = function _verify1 (a) {
|
|
assert(a.negative === 0, 'red works only with positives');
|
|
assert(a.red, 'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype._verify2 = function _verify2 (a, b) {
|
|
assert((a.negative | b.negative) === 0, 'red works only with positives');
|
|
assert(a.red && a.red === b.red,
|
|
'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype.imod = function imod (a) {
|
|
if (this.prime) return this.prime.ireduce(a)._forceRed(this);
|
|
return a.umod(this.m)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.neg = function neg (a) {
|
|
if (a.isZero()) {
|
|
return a.clone();
|
|
}
|
|
|
|
return this.m.sub(a)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.add = function add (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.add(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.iadd = function iadd (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.iadd(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.sub = function sub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.sub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.isub = function isub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.isub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.shl = function shl (a, num) {
|
|
this._verify1(a);
|
|
return this.imod(a.ushln(num));
|
|
};
|
|
|
|
Red.prototype.imul = function imul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.imul(b));
|
|
};
|
|
|
|
Red.prototype.mul = function mul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.mul(b));
|
|
};
|
|
|
|
Red.prototype.isqr = function isqr (a) {
|
|
return this.imul(a, a.clone());
|
|
};
|
|
|
|
Red.prototype.sqr = function sqr (a) {
|
|
return this.mul(a, a);
|
|
};
|
|
|
|
Red.prototype.sqrt = function sqrt (a) {
|
|
if (a.isZero()) return a.clone();
|
|
|
|
var mod3 = this.m.andln(3);
|
|
assert(mod3 % 2 === 1);
|
|
|
|
// Fast case
|
|
if (mod3 === 3) {
|
|
var pow = this.m.add(new BN(1)).iushrn(2);
|
|
return this.pow(a, pow);
|
|
}
|
|
|
|
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
|
|
//
|
|
// Find Q and S, that Q * 2 ^ S = (P - 1)
|
|
var q = this.m.subn(1);
|
|
var s = 0;
|
|
while (!q.isZero() && q.andln(1) === 0) {
|
|
s++;
|
|
q.iushrn(1);
|
|
}
|
|
assert(!q.isZero());
|
|
|
|
var one = new BN(1).toRed(this);
|
|
var nOne = one.redNeg();
|
|
|
|
// Find quadratic non-residue
|
|
// NOTE: Max is such because of generalized Riemann hypothesis.
|
|
var lpow = this.m.subn(1).iushrn(1);
|
|
var z = this.m.bitLength();
|
|
z = new BN(2 * z * z).toRed(this);
|
|
|
|
while (this.pow(z, lpow).cmp(nOne) !== 0) {
|
|
z.redIAdd(nOne);
|
|
}
|
|
|
|
var c = this.pow(z, q);
|
|
var r = this.pow(a, q.addn(1).iushrn(1));
|
|
var t = this.pow(a, q);
|
|
var m = s;
|
|
while (t.cmp(one) !== 0) {
|
|
var tmp = t;
|
|
for (var i = 0; tmp.cmp(one) !== 0; i++) {
|
|
tmp = tmp.redSqr();
|
|
}
|
|
assert(i < m);
|
|
var b = this.pow(c, new BN(1).iushln(m - i - 1));
|
|
|
|
r = r.redMul(b);
|
|
c = b.redSqr();
|
|
t = t.redMul(c);
|
|
m = i;
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
Red.prototype.invm = function invm (a) {
|
|
var inv = a._invmp(this.m);
|
|
if (inv.negative !== 0) {
|
|
inv.negative = 0;
|
|
return this.imod(inv).redNeg();
|
|
} else {
|
|
return this.imod(inv);
|
|
}
|
|
};
|
|
|
|
Red.prototype.pow = function pow (a, num) {
|
|
if (num.isZero()) return new BN(1).toRed(this);
|
|
if (num.cmpn(1) === 0) return a.clone();
|
|
|
|
var windowSize = 4;
|
|
var wnd = new Array(1 << windowSize);
|
|
wnd[0] = new BN(1).toRed(this);
|
|
wnd[1] = a;
|
|
for (var i = 2; i < wnd.length; i++) {
|
|
wnd[i] = this.mul(wnd[i - 1], a);
|
|
}
|
|
|
|
var res = wnd[0];
|
|
var current = 0;
|
|
var currentLen = 0;
|
|
var start = num.bitLength() % 26;
|
|
if (start === 0) {
|
|
start = 26;
|
|
}
|
|
|
|
for (i = num.length - 1; i >= 0; i--) {
|
|
var word = num.words[i];
|
|
for (var j = start - 1; j >= 0; j--) {
|
|
var bit = (word >> j) & 1;
|
|
if (res !== wnd[0]) {
|
|
res = this.sqr(res);
|
|
}
|
|
|
|
if (bit === 0 && current === 0) {
|
|
currentLen = 0;
|
|
continue;
|
|
}
|
|
|
|
current <<= 1;
|
|
current |= bit;
|
|
currentLen++;
|
|
if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
|
|
|
|
res = this.mul(res, wnd[current]);
|
|
currentLen = 0;
|
|
current = 0;
|
|
}
|
|
start = 26;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.convertTo = function convertTo (num) {
|
|
var r = num.umod(this.m);
|
|
|
|
return r === num ? r.clone() : r;
|
|
};
|
|
|
|
Red.prototype.convertFrom = function convertFrom (num) {
|
|
var res = num.clone();
|
|
res.red = null;
|
|
return res;
|
|
};
|
|
|
|
//
|
|
// Montgomery method engine
|
|
//
|
|
|
|
BN.mont = function mont (num) {
|
|
return new Mont(num);
|
|
};
|
|
|
|
function Mont (m) {
|
|
Red.call(this, m);
|
|
|
|
this.shift = this.m.bitLength();
|
|
if (this.shift % 26 !== 0) {
|
|
this.shift += 26 - (this.shift % 26);
|
|
}
|
|
|
|
this.r = new BN(1).iushln(this.shift);
|
|
this.r2 = this.imod(this.r.sqr());
|
|
this.rinv = this.r._invmp(this.m);
|
|
|
|
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
|
|
this.minv = this.minv.umod(this.r);
|
|
this.minv = this.r.sub(this.minv);
|
|
}
|
|
inherits(Mont, Red);
|
|
|
|
Mont.prototype.convertTo = function convertTo (num) {
|
|
return this.imod(num.ushln(this.shift));
|
|
};
|
|
|
|
Mont.prototype.convertFrom = function convertFrom (num) {
|
|
var r = this.imod(num.mul(this.rinv));
|
|
r.red = null;
|
|
return r;
|
|
};
|
|
|
|
Mont.prototype.imul = function imul (a, b) {
|
|
if (a.isZero() || b.isZero()) {
|
|
a.words[0] = 0;
|
|
a.length = 1;
|
|
return a;
|
|
}
|
|
|
|
var t = a.imul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.mul = function mul (a, b) {
|
|
if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
|
|
|
|
var t = a.mul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.invm = function invm (a) {
|
|
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
|
|
var res = this.imod(a._invmp(this.m).mul(this.r2));
|
|
return res._forceRed(this);
|
|
};
|
|
})( false || module, this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/assert/build/assert.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/assert/build/assert.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
// Currently in sync with Node.js lib/assert.js
|
|
// https://github.com/nodejs/node/commit/2a51ae424a513ec9a6aa3466baa0cc1d55dd4f3b
|
|
// Originally from narwhal.js (http://narwhaljs.org)
|
|
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the 'Software'), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
var _require = __webpack_require__(/*! ./internal/errors */ "./node_modules/assert/build/internal/errors.js"),
|
|
_require$codes = _require.codes,
|
|
ERR_AMBIGUOUS_ARGUMENT = _require$codes.ERR_AMBIGUOUS_ARGUMENT,
|
|
ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE,
|
|
ERR_INVALID_ARG_VALUE = _require$codes.ERR_INVALID_ARG_VALUE,
|
|
ERR_INVALID_RETURN_VALUE = _require$codes.ERR_INVALID_RETURN_VALUE,
|
|
ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS;
|
|
|
|
var AssertionError = __webpack_require__(/*! ./internal/assert/assertion_error */ "./node_modules/assert/build/internal/assert/assertion_error.js");
|
|
|
|
var _require2 = __webpack_require__(/*! util/ */ "./node_modules/util/util.js"),
|
|
inspect = _require2.inspect;
|
|
|
|
var _require$types = __webpack_require__(/*! util/ */ "./node_modules/util/util.js").types,
|
|
isPromise = _require$types.isPromise,
|
|
isRegExp = _require$types.isRegExp;
|
|
|
|
var objectAssign = Object.assign ? Object.assign : __webpack_require__(/*! es6-object-assign */ "./node_modules/es6-object-assign/index.js").assign;
|
|
var objectIs = Object.is ? Object.is : __webpack_require__(/*! object-is */ "./node_modules/object-is/index.js");
|
|
var errorCache = new Map();
|
|
var isDeepEqual;
|
|
var isDeepStrictEqual;
|
|
var parseExpressionAt;
|
|
var findNodeAround;
|
|
var decoder;
|
|
|
|
function lazyLoadComparison() {
|
|
var comparison = __webpack_require__(/*! ./internal/util/comparisons */ "./node_modules/assert/build/internal/util/comparisons.js");
|
|
|
|
isDeepEqual = comparison.isDeepEqual;
|
|
isDeepStrictEqual = comparison.isDeepStrictEqual;
|
|
} // Escape control characters but not \n and \t to keep the line breaks and
|
|
// indentation intact.
|
|
// eslint-disable-next-line no-control-regex
|
|
|
|
|
|
var escapeSequencesRegExp = /[\x00-\x08\x0b\x0c\x0e-\x1f]/g;
|
|
var meta = ["\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", '\\b', '', '', "\\u000b", '\\f', '', "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f"];
|
|
|
|
var escapeFn = function escapeFn(str) {
|
|
return meta[str.charCodeAt(0)];
|
|
};
|
|
|
|
var warned = false; // The assert module provides functions that throw
|
|
// AssertionError's when particular conditions are not met. The
|
|
// assert module must conform to the following interface.
|
|
|
|
var assert = module.exports = ok;
|
|
var NO_EXCEPTION_SENTINEL = {}; // All of the following functions must throw an AssertionError
|
|
// when a corresponding condition is not met, with a message that
|
|
// may be undefined if not provided. All assertion methods provide
|
|
// both the actual and expected values to the assertion error for
|
|
// display purposes.
|
|
|
|
function innerFail(obj) {
|
|
if (obj.message instanceof Error) throw obj.message;
|
|
throw new AssertionError(obj);
|
|
}
|
|
|
|
function fail(actual, expected, message, operator, stackStartFn) {
|
|
var argsLen = arguments.length;
|
|
var internalMessage;
|
|
|
|
if (argsLen === 0) {
|
|
internalMessage = 'Failed';
|
|
} else if (argsLen === 1) {
|
|
message = actual;
|
|
actual = undefined;
|
|
} else {
|
|
if (warned === false) {
|
|
warned = true;
|
|
var warn = process.emitWarning ? process.emitWarning : console.warn.bind(console);
|
|
warn('assert.fail() with more than one argument is deprecated. ' + 'Please use assert.strictEqual() instead or only pass a message.', 'DeprecationWarning', 'DEP0094');
|
|
}
|
|
|
|
if (argsLen === 2) operator = '!=';
|
|
}
|
|
|
|
if (message instanceof Error) throw message;
|
|
var errArgs = {
|
|
actual: actual,
|
|
expected: expected,
|
|
operator: operator === undefined ? 'fail' : operator,
|
|
stackStartFn: stackStartFn || fail
|
|
};
|
|
|
|
if (message !== undefined) {
|
|
errArgs.message = message;
|
|
}
|
|
|
|
var err = new AssertionError(errArgs);
|
|
|
|
if (internalMessage) {
|
|
err.message = internalMessage;
|
|
err.generatedMessage = true;
|
|
}
|
|
|
|
throw err;
|
|
}
|
|
|
|
assert.fail = fail; // The AssertionError is defined in internal/error.
|
|
|
|
assert.AssertionError = AssertionError;
|
|
|
|
function innerOk(fn, argLen, value, message) {
|
|
if (!value) {
|
|
var generatedMessage = false;
|
|
|
|
if (argLen === 0) {
|
|
generatedMessage = true;
|
|
message = 'No value argument passed to `assert.ok()`';
|
|
} else if (message instanceof Error) {
|
|
throw message;
|
|
}
|
|
|
|
var err = new AssertionError({
|
|
actual: value,
|
|
expected: true,
|
|
message: message,
|
|
operator: '==',
|
|
stackStartFn: fn
|
|
});
|
|
err.generatedMessage = generatedMessage;
|
|
throw err;
|
|
}
|
|
} // Pure assertion tests whether a value is truthy, as determined
|
|
// by !!value.
|
|
|
|
|
|
function ok() {
|
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
|
|
innerOk.apply(void 0, [ok, args.length].concat(args));
|
|
}
|
|
|
|
assert.ok = ok; // The equality assertion tests shallow, coercive equality with ==.
|
|
|
|
/* eslint-disable no-restricted-properties */
|
|
|
|
assert.equal = function equal(actual, expected, message) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
|
} // eslint-disable-next-line eqeqeq
|
|
|
|
|
|
if (actual != expected) {
|
|
innerFail({
|
|
actual: actual,
|
|
expected: expected,
|
|
message: message,
|
|
operator: '==',
|
|
stackStartFn: equal
|
|
});
|
|
}
|
|
}; // The non-equality assertion tests for whether two objects are not
|
|
// equal with !=.
|
|
|
|
|
|
assert.notEqual = function notEqual(actual, expected, message) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
|
} // eslint-disable-next-line eqeqeq
|
|
|
|
|
|
if (actual == expected) {
|
|
innerFail({
|
|
actual: actual,
|
|
expected: expected,
|
|
message: message,
|
|
operator: '!=',
|
|
stackStartFn: notEqual
|
|
});
|
|
}
|
|
}; // The equivalence assertion tests a deep equality relation.
|
|
|
|
|
|
assert.deepEqual = function deepEqual(actual, expected, message) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
|
}
|
|
|
|
if (isDeepEqual === undefined) lazyLoadComparison();
|
|
|
|
if (!isDeepEqual(actual, expected)) {
|
|
innerFail({
|
|
actual: actual,
|
|
expected: expected,
|
|
message: message,
|
|
operator: 'deepEqual',
|
|
stackStartFn: deepEqual
|
|
});
|
|
}
|
|
}; // The non-equivalence assertion tests for any deep inequality.
|
|
|
|
|
|
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
|
}
|
|
|
|
if (isDeepEqual === undefined) lazyLoadComparison();
|
|
|
|
if (isDeepEqual(actual, expected)) {
|
|
innerFail({
|
|
actual: actual,
|
|
expected: expected,
|
|
message: message,
|
|
operator: 'notDeepEqual',
|
|
stackStartFn: notDeepEqual
|
|
});
|
|
}
|
|
};
|
|
/* eslint-enable */
|
|
|
|
|
|
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
|
}
|
|
|
|
if (isDeepEqual === undefined) lazyLoadComparison();
|
|
|
|
if (!isDeepStrictEqual(actual, expected)) {
|
|
innerFail({
|
|
actual: actual,
|
|
expected: expected,
|
|
message: message,
|
|
operator: 'deepStrictEqual',
|
|
stackStartFn: deepStrictEqual
|
|
});
|
|
}
|
|
};
|
|
|
|
assert.notDeepStrictEqual = notDeepStrictEqual;
|
|
|
|
function notDeepStrictEqual(actual, expected, message) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
|
}
|
|
|
|
if (isDeepEqual === undefined) lazyLoadComparison();
|
|
|
|
if (isDeepStrictEqual(actual, expected)) {
|
|
innerFail({
|
|
actual: actual,
|
|
expected: expected,
|
|
message: message,
|
|
operator: 'notDeepStrictEqual',
|
|
stackStartFn: notDeepStrictEqual
|
|
});
|
|
}
|
|
}
|
|
|
|
assert.strictEqual = function strictEqual(actual, expected, message) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
|
}
|
|
|
|
if (!objectIs(actual, expected)) {
|
|
innerFail({
|
|
actual: actual,
|
|
expected: expected,
|
|
message: message,
|
|
operator: 'strictEqual',
|
|
stackStartFn: strictEqual
|
|
});
|
|
}
|
|
};
|
|
|
|
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
|
if (arguments.length < 2) {
|
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
|
}
|
|
|
|
if (objectIs(actual, expected)) {
|
|
innerFail({
|
|
actual: actual,
|
|
expected: expected,
|
|
message: message,
|
|
operator: 'notStrictEqual',
|
|
stackStartFn: notStrictEqual
|
|
});
|
|
}
|
|
};
|
|
|
|
var Comparison = function Comparison(obj, keys, actual) {
|
|
var _this = this;
|
|
|
|
_classCallCheck(this, Comparison);
|
|
|
|
keys.forEach(function (key) {
|
|
if (key in obj) {
|
|
if (actual !== undefined && typeof actual[key] === 'string' && isRegExp(obj[key]) && obj[key].test(actual[key])) {
|
|
_this[key] = actual[key];
|
|
} else {
|
|
_this[key] = obj[key];
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
function compareExceptionKey(actual, expected, key, message, keys, fn) {
|
|
if (!(key in actual) || !isDeepStrictEqual(actual[key], expected[key])) {
|
|
if (!message) {
|
|
// Create placeholder objects to create a nice output.
|
|
var a = new Comparison(actual, keys);
|
|
var b = new Comparison(expected, keys, actual);
|
|
var err = new AssertionError({
|
|
actual: a,
|
|
expected: b,
|
|
operator: 'deepStrictEqual',
|
|
stackStartFn: fn
|
|
});
|
|
err.actual = actual;
|
|
err.expected = expected;
|
|
err.operator = fn.name;
|
|
throw err;
|
|
}
|
|
|
|
innerFail({
|
|
actual: actual,
|
|
expected: expected,
|
|
message: message,
|
|
operator: fn.name,
|
|
stackStartFn: fn
|
|
});
|
|
}
|
|
}
|
|
|
|
function expectedException(actual, expected, msg, fn) {
|
|
if (typeof expected !== 'function') {
|
|
if (isRegExp(expected)) return expected.test(actual); // assert.doesNotThrow does not accept objects.
|
|
|
|
if (arguments.length === 2) {
|
|
throw new ERR_INVALID_ARG_TYPE('expected', ['Function', 'RegExp'], expected);
|
|
} // Handle primitives properly.
|
|
|
|
|
|
if (_typeof(actual) !== 'object' || actual === null) {
|
|
var err = new AssertionError({
|
|
actual: actual,
|
|
expected: expected,
|
|
message: msg,
|
|
operator: 'deepStrictEqual',
|
|
stackStartFn: fn
|
|
});
|
|
err.operator = fn.name;
|
|
throw err;
|
|
}
|
|
|
|
var keys = Object.keys(expected); // Special handle errors to make sure the name and the message are compared
|
|
// as well.
|
|
|
|
if (expected instanceof Error) {
|
|
keys.push('name', 'message');
|
|
} else if (keys.length === 0) {
|
|
throw new ERR_INVALID_ARG_VALUE('error', expected, 'may not be an empty object');
|
|
}
|
|
|
|
if (isDeepEqual === undefined) lazyLoadComparison();
|
|
keys.forEach(function (key) {
|
|
if (typeof actual[key] === 'string' && isRegExp(expected[key]) && expected[key].test(actual[key])) {
|
|
return;
|
|
}
|
|
|
|
compareExceptionKey(actual, expected, key, msg, keys, fn);
|
|
});
|
|
return true;
|
|
} // Guard instanceof against arrow functions as they don't have a prototype.
|
|
|
|
|
|
if (expected.prototype !== undefined && actual instanceof expected) {
|
|
return true;
|
|
}
|
|
|
|
if (Error.isPrototypeOf(expected)) {
|
|
return false;
|
|
}
|
|
|
|
return expected.call({}, actual) === true;
|
|
}
|
|
|
|
function getActual(fn) {
|
|
if (typeof fn !== 'function') {
|
|
throw new ERR_INVALID_ARG_TYPE('fn', 'Function', fn);
|
|
}
|
|
|
|
try {
|
|
fn();
|
|
} catch (e) {
|
|
return e;
|
|
}
|
|
|
|
return NO_EXCEPTION_SENTINEL;
|
|
}
|
|
|
|
function checkIsPromise(obj) {
|
|
// Accept native ES6 promises and promises that are implemented in a similar
|
|
// way. Do not accept thenables that use a function as `obj` and that have no
|
|
// `catch` handler.
|
|
// TODO: thenables are checked up until they have the correct methods,
|
|
// but according to documentation, the `then` method should receive
|
|
// the `fulfill` and `reject` arguments as well or it may be never resolved.
|
|
return isPromise(obj) || obj !== null && _typeof(obj) === 'object' && typeof obj.then === 'function' && typeof obj.catch === 'function';
|
|
}
|
|
|
|
function waitForActual(promiseFn) {
|
|
return Promise.resolve().then(function () {
|
|
var resultPromise;
|
|
|
|
if (typeof promiseFn === 'function') {
|
|
// Return a rejected promise if `promiseFn` throws synchronously.
|
|
resultPromise = promiseFn(); // Fail in case no promise is returned.
|
|
|
|
if (!checkIsPromise(resultPromise)) {
|
|
throw new ERR_INVALID_RETURN_VALUE('instance of Promise', 'promiseFn', resultPromise);
|
|
}
|
|
} else if (checkIsPromise(promiseFn)) {
|
|
resultPromise = promiseFn;
|
|
} else {
|
|
throw new ERR_INVALID_ARG_TYPE('promiseFn', ['Function', 'Promise'], promiseFn);
|
|
}
|
|
|
|
return Promise.resolve().then(function () {
|
|
return resultPromise;
|
|
}).then(function () {
|
|
return NO_EXCEPTION_SENTINEL;
|
|
}).catch(function (e) {
|
|
return e;
|
|
});
|
|
});
|
|
}
|
|
|
|
function expectsError(stackStartFn, actual, error, message) {
|
|
if (typeof error === 'string') {
|
|
if (arguments.length === 4) {
|
|
throw new ERR_INVALID_ARG_TYPE('error', ['Object', 'Error', 'Function', 'RegExp'], error);
|
|
}
|
|
|
|
if (_typeof(actual) === 'object' && actual !== null) {
|
|
if (actual.message === error) {
|
|
throw new ERR_AMBIGUOUS_ARGUMENT('error/message', "The error message \"".concat(actual.message, "\" is identical to the message."));
|
|
}
|
|
} else if (actual === error) {
|
|
throw new ERR_AMBIGUOUS_ARGUMENT('error/message', "The error \"".concat(actual, "\" is identical to the message."));
|
|
}
|
|
|
|
message = error;
|
|
error = undefined;
|
|
} else if (error != null && _typeof(error) !== 'object' && typeof error !== 'function') {
|
|
throw new ERR_INVALID_ARG_TYPE('error', ['Object', 'Error', 'Function', 'RegExp'], error);
|
|
}
|
|
|
|
if (actual === NO_EXCEPTION_SENTINEL) {
|
|
var details = '';
|
|
|
|
if (error && error.name) {
|
|
details += " (".concat(error.name, ")");
|
|
}
|
|
|
|
details += message ? ": ".concat(message) : '.';
|
|
var fnType = stackStartFn.name === 'rejects' ? 'rejection' : 'exception';
|
|
innerFail({
|
|
actual: undefined,
|
|
expected: error,
|
|
operator: stackStartFn.name,
|
|
message: "Missing expected ".concat(fnType).concat(details),
|
|
stackStartFn: stackStartFn
|
|
});
|
|
}
|
|
|
|
if (error && !expectedException(actual, error, message, stackStartFn)) {
|
|
throw actual;
|
|
}
|
|
}
|
|
|
|
function expectsNoError(stackStartFn, actual, error, message) {
|
|
if (actual === NO_EXCEPTION_SENTINEL) return;
|
|
|
|
if (typeof error === 'string') {
|
|
message = error;
|
|
error = undefined;
|
|
}
|
|
|
|
if (!error || expectedException(actual, error)) {
|
|
var details = message ? ": ".concat(message) : '.';
|
|
var fnType = stackStartFn.name === 'doesNotReject' ? 'rejection' : 'exception';
|
|
innerFail({
|
|
actual: actual,
|
|
expected: error,
|
|
operator: stackStartFn.name,
|
|
message: "Got unwanted ".concat(fnType).concat(details, "\n") + "Actual message: \"".concat(actual && actual.message, "\""),
|
|
stackStartFn: stackStartFn
|
|
});
|
|
}
|
|
|
|
throw actual;
|
|
}
|
|
|
|
assert.throws = function throws(promiseFn) {
|
|
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
|
args[_key2 - 1] = arguments[_key2];
|
|
}
|
|
|
|
expectsError.apply(void 0, [throws, getActual(promiseFn)].concat(args));
|
|
};
|
|
|
|
assert.rejects = function rejects(promiseFn) {
|
|
for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
|
|
args[_key3 - 1] = arguments[_key3];
|
|
}
|
|
|
|
return waitForActual(promiseFn).then(function (result) {
|
|
return expectsError.apply(void 0, [rejects, result].concat(args));
|
|
});
|
|
};
|
|
|
|
assert.doesNotThrow = function doesNotThrow(fn) {
|
|
for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
|
|
args[_key4 - 1] = arguments[_key4];
|
|
}
|
|
|
|
expectsNoError.apply(void 0, [doesNotThrow, getActual(fn)].concat(args));
|
|
};
|
|
|
|
assert.doesNotReject = function doesNotReject(fn) {
|
|
for (var _len5 = arguments.length, args = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {
|
|
args[_key5 - 1] = arguments[_key5];
|
|
}
|
|
|
|
return waitForActual(fn).then(function (result) {
|
|
return expectsNoError.apply(void 0, [doesNotReject, result].concat(args));
|
|
});
|
|
};
|
|
|
|
assert.ifError = function ifError(err) {
|
|
if (err !== null && err !== undefined) {
|
|
var message = 'ifError got unwanted exception: ';
|
|
|
|
if (_typeof(err) === 'object' && typeof err.message === 'string') {
|
|
if (err.message.length === 0 && err.constructor) {
|
|
message += err.constructor.name;
|
|
} else {
|
|
message += err.message;
|
|
}
|
|
} else {
|
|
message += inspect(err);
|
|
}
|
|
|
|
var newErr = new AssertionError({
|
|
actual: err,
|
|
expected: null,
|
|
operator: 'ifError',
|
|
message: message,
|
|
stackStartFn: ifError
|
|
}); // Make sure we actually have a stack trace!
|
|
|
|
var origStack = err.stack;
|
|
|
|
if (typeof origStack === 'string') {
|
|
// This will remove any duplicated frames from the error frames taken
|
|
// from within `ifError` and add the original error frames to the newly
|
|
// created ones.
|
|
var tmp2 = origStack.split('\n');
|
|
tmp2.shift(); // Filter all frames existing in err.stack.
|
|
|
|
var tmp1 = newErr.stack.split('\n');
|
|
|
|
for (var i = 0; i < tmp2.length; i++) {
|
|
// Find the first occurrence of the frame.
|
|
var pos = tmp1.indexOf(tmp2[i]);
|
|
|
|
if (pos !== -1) {
|
|
// Only keep new frames.
|
|
tmp1 = tmp1.slice(0, pos);
|
|
break;
|
|
}
|
|
}
|
|
|
|
newErr.stack = "".concat(tmp1.join('\n'), "\n").concat(tmp2.join('\n'));
|
|
}
|
|
|
|
throw newErr;
|
|
}
|
|
}; // Expose a strict only variant of assert
|
|
|
|
|
|
function strict() {
|
|
for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
|
|
args[_key6] = arguments[_key6];
|
|
}
|
|
|
|
innerOk.apply(void 0, [strict, args.length].concat(args));
|
|
}
|
|
|
|
assert.strict = objectAssign(strict, assert, {
|
|
equal: assert.strictEqual,
|
|
deepEqual: assert.deepStrictEqual,
|
|
notEqual: assert.notStrictEqual,
|
|
notDeepEqual: assert.notDeepStrictEqual
|
|
});
|
|
assert.strict.strict = assert.strict;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/assert/build/internal/assert/assertion_error.js":
|
|
/*!**********************************************************************!*\
|
|
!*** ./node_modules/assert/build/internal/assert/assertion_error.js ***!
|
|
\**********************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
// Currently in sync with Node.js lib/internal/assert/assertion_error.js
|
|
// https://github.com/nodejs/node/commit/0817840f775032169ddd70c85ac059f18ffcc81c
|
|
|
|
|
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
|
|
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
|
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
|
|
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
|
|
|
|
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
|
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
|
|
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
|
|
|
|
function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
|
|
|
|
function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
|
|
|
|
function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }
|
|
|
|
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
|
|
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
|
|
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
|
|
var _require = __webpack_require__(/*! util/ */ "./node_modules/util/util.js"),
|
|
inspect = _require.inspect;
|
|
|
|
var _require2 = __webpack_require__(/*! ../errors */ "./node_modules/assert/build/internal/errors.js"),
|
|
ERR_INVALID_ARG_TYPE = _require2.codes.ERR_INVALID_ARG_TYPE; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
|
|
|
|
|
|
function endsWith(str, search, this_len) {
|
|
if (this_len === undefined || this_len > str.length) {
|
|
this_len = str.length;
|
|
}
|
|
|
|
return str.substring(this_len - search.length, this_len) === search;
|
|
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
|
|
|
|
|
function repeat(str, count) {
|
|
count = Math.floor(count);
|
|
if (str.length == 0 || count == 0) return '';
|
|
var maxCount = str.length * count;
|
|
count = Math.floor(Math.log(count) / Math.log(2));
|
|
|
|
while (count) {
|
|
str += str;
|
|
count--;
|
|
}
|
|
|
|
str += str.substring(0, maxCount - str.length);
|
|
return str;
|
|
}
|
|
|
|
var blue = '';
|
|
var green = '';
|
|
var red = '';
|
|
var white = '';
|
|
var kReadableOperator = {
|
|
deepStrictEqual: 'Expected values to be strictly deep-equal:',
|
|
strictEqual: 'Expected values to be strictly equal:',
|
|
strictEqualObject: 'Expected "actual" to be reference-equal to "expected":',
|
|
deepEqual: 'Expected values to be loosely deep-equal:',
|
|
equal: 'Expected values to be loosely equal:',
|
|
notDeepStrictEqual: 'Expected "actual" not to be strictly deep-equal to:',
|
|
notStrictEqual: 'Expected "actual" to be strictly unequal to:',
|
|
notStrictEqualObject: 'Expected "actual" not to be reference-equal to "expected":',
|
|
notDeepEqual: 'Expected "actual" not to be loosely deep-equal to:',
|
|
notEqual: 'Expected "actual" to be loosely unequal to:',
|
|
notIdentical: 'Values identical but not reference-equal:'
|
|
}; // Comparing short primitives should just show === / !== instead of using the
|
|
// diff.
|
|
|
|
var kMaxShortLength = 10;
|
|
|
|
function copyError(source) {
|
|
var keys = Object.keys(source);
|
|
var target = Object.create(Object.getPrototypeOf(source));
|
|
keys.forEach(function (key) {
|
|
target[key] = source[key];
|
|
});
|
|
Object.defineProperty(target, 'message', {
|
|
value: source.message
|
|
});
|
|
return target;
|
|
}
|
|
|
|
function inspectValue(val) {
|
|
// The util.inspect default values could be changed. This makes sure the
|
|
// error messages contain the necessary information nevertheless.
|
|
return inspect(val, {
|
|
compact: false,
|
|
customInspect: false,
|
|
depth: 1000,
|
|
maxArrayLength: Infinity,
|
|
// Assert compares only enumerable properties (with a few exceptions).
|
|
showHidden: false,
|
|
// Having a long line as error is better than wrapping the line for
|
|
// comparison for now.
|
|
// TODO(BridgeAR): `breakLength` should be limited as soon as soon as we
|
|
// have meta information about the inspected properties (i.e., know where
|
|
// in what line the property starts and ends).
|
|
breakLength: Infinity,
|
|
// Assert does not detect proxies currently.
|
|
showProxy: false,
|
|
sorted: true,
|
|
// Inspect getters as we also check them when comparing entries.
|
|
getters: true
|
|
});
|
|
}
|
|
|
|
function createErrDiff(actual, expected, operator) {
|
|
var other = '';
|
|
var res = '';
|
|
var lastPos = 0;
|
|
var end = '';
|
|
var skipped = false;
|
|
var actualInspected = inspectValue(actual);
|
|
var actualLines = actualInspected.split('\n');
|
|
var expectedLines = inspectValue(expected).split('\n');
|
|
var i = 0;
|
|
var indicator = ''; // In case both values are objects explicitly mark them as not reference equal
|
|
// for the `strictEqual` operator.
|
|
|
|
if (operator === 'strictEqual' && _typeof(actual) === 'object' && _typeof(expected) === 'object' && actual !== null && expected !== null) {
|
|
operator = 'strictEqualObject';
|
|
} // If "actual" and "expected" fit on a single line and they are not strictly
|
|
// equal, check further special handling.
|
|
|
|
|
|
if (actualLines.length === 1 && expectedLines.length === 1 && actualLines[0] !== expectedLines[0]) {
|
|
var inputLength = actualLines[0].length + expectedLines[0].length; // If the character length of "actual" and "expected" together is less than
|
|
// kMaxShortLength and if neither is an object and at least one of them is
|
|
// not `zero`, use the strict equal comparison to visualize the output.
|
|
|
|
if (inputLength <= kMaxShortLength) {
|
|
if ((_typeof(actual) !== 'object' || actual === null) && (_typeof(expected) !== 'object' || expected === null) && (actual !== 0 || expected !== 0)) {
|
|
// -0 === +0
|
|
return "".concat(kReadableOperator[operator], "\n\n") + "".concat(actualLines[0], " !== ").concat(expectedLines[0], "\n");
|
|
}
|
|
} else if (operator !== 'strictEqualObject') {
|
|
// If the stderr is a tty and the input length is lower than the current
|
|
// columns per line, add a mismatch indicator below the output. If it is
|
|
// not a tty, use a default value of 80 characters.
|
|
var maxLength = process.stderr && process.stderr.isTTY ? process.stderr.columns : 80;
|
|
|
|
if (inputLength < maxLength) {
|
|
while (actualLines[0][i] === expectedLines[0][i]) {
|
|
i++;
|
|
} // Ignore the first characters.
|
|
|
|
|
|
if (i > 2) {
|
|
// Add position indicator for the first mismatch in case it is a
|
|
// single line and the input length is less than the column length.
|
|
indicator = "\n ".concat(repeat(' ', i), "^");
|
|
i = 0;
|
|
}
|
|
}
|
|
}
|
|
} // Remove all ending lines that match (this optimizes the output for
|
|
// readability by reducing the number of total changed lines).
|
|
|
|
|
|
var a = actualLines[actualLines.length - 1];
|
|
var b = expectedLines[expectedLines.length - 1];
|
|
|
|
while (a === b) {
|
|
if (i++ < 2) {
|
|
end = "\n ".concat(a).concat(end);
|
|
} else {
|
|
other = a;
|
|
}
|
|
|
|
actualLines.pop();
|
|
expectedLines.pop();
|
|
if (actualLines.length === 0 || expectedLines.length === 0) break;
|
|
a = actualLines[actualLines.length - 1];
|
|
b = expectedLines[expectedLines.length - 1];
|
|
}
|
|
|
|
var maxLines = Math.max(actualLines.length, expectedLines.length); // Strict equal with identical objects that are not identical by reference.
|
|
// E.g., assert.deepStrictEqual({ a: Symbol() }, { a: Symbol() })
|
|
|
|
if (maxLines === 0) {
|
|
// We have to get the result again. The lines were all removed before.
|
|
var _actualLines = actualInspected.split('\n'); // Only remove lines in case it makes sense to collapse those.
|
|
// TODO: Accept env to always show the full error.
|
|
|
|
|
|
if (_actualLines.length > 30) {
|
|
_actualLines[26] = "".concat(blue, "...").concat(white);
|
|
|
|
while (_actualLines.length > 27) {
|
|
_actualLines.pop();
|
|
}
|
|
}
|
|
|
|
return "".concat(kReadableOperator.notIdentical, "\n\n").concat(_actualLines.join('\n'), "\n");
|
|
}
|
|
|
|
if (i > 3) {
|
|
end = "\n".concat(blue, "...").concat(white).concat(end);
|
|
skipped = true;
|
|
}
|
|
|
|
if (other !== '') {
|
|
end = "\n ".concat(other).concat(end);
|
|
other = '';
|
|
}
|
|
|
|
var printedLines = 0;
|
|
var msg = kReadableOperator[operator] + "\n".concat(green, "+ actual").concat(white, " ").concat(red, "- expected").concat(white);
|
|
var skippedMsg = " ".concat(blue, "...").concat(white, " Lines skipped");
|
|
|
|
for (i = 0; i < maxLines; i++) {
|
|
// Only extra expected lines exist
|
|
var cur = i - lastPos;
|
|
|
|
if (actualLines.length < i + 1) {
|
|
// If the last diverging line is more than one line above and the
|
|
// current line is at least line three, add some of the former lines and
|
|
// also add dots to indicate skipped entries.
|
|
if (cur > 1 && i > 2) {
|
|
if (cur > 4) {
|
|
res += "\n".concat(blue, "...").concat(white);
|
|
skipped = true;
|
|
} else if (cur > 3) {
|
|
res += "\n ".concat(expectedLines[i - 2]);
|
|
printedLines++;
|
|
}
|
|
|
|
res += "\n ".concat(expectedLines[i - 1]);
|
|
printedLines++;
|
|
} // Mark the current line as the last diverging one.
|
|
|
|
|
|
lastPos = i; // Add the expected line to the cache.
|
|
|
|
other += "\n".concat(red, "-").concat(white, " ").concat(expectedLines[i]);
|
|
printedLines++; // Only extra actual lines exist
|
|
} else if (expectedLines.length < i + 1) {
|
|
// If the last diverging line is more than one line above and the
|
|
// current line is at least line three, add some of the former lines and
|
|
// also add dots to indicate skipped entries.
|
|
if (cur > 1 && i > 2) {
|
|
if (cur > 4) {
|
|
res += "\n".concat(blue, "...").concat(white);
|
|
skipped = true;
|
|
} else if (cur > 3) {
|
|
res += "\n ".concat(actualLines[i - 2]);
|
|
printedLines++;
|
|
}
|
|
|
|
res += "\n ".concat(actualLines[i - 1]);
|
|
printedLines++;
|
|
} // Mark the current line as the last diverging one.
|
|
|
|
|
|
lastPos = i; // Add the actual line to the result.
|
|
|
|
res += "\n".concat(green, "+").concat(white, " ").concat(actualLines[i]);
|
|
printedLines++; // Lines diverge
|
|
} else {
|
|
var expectedLine = expectedLines[i];
|
|
var actualLine = actualLines[i]; // If the lines diverge, specifically check for lines that only diverge by
|
|
// a trailing comma. In that case it is actually identical and we should
|
|
// mark it as such.
|
|
|
|
var divergingLines = actualLine !== expectedLine && (!endsWith(actualLine, ',') || actualLine.slice(0, -1) !== expectedLine); // If the expected line has a trailing comma but is otherwise identical,
|
|
// add a comma at the end of the actual line. Otherwise the output could
|
|
// look weird as in:
|
|
//
|
|
// [
|
|
// 1 // No comma at the end!
|
|
// + 2
|
|
// ]
|
|
//
|
|
|
|
if (divergingLines && endsWith(expectedLine, ',') && expectedLine.slice(0, -1) === actualLine) {
|
|
divergingLines = false;
|
|
actualLine += ',';
|
|
}
|
|
|
|
if (divergingLines) {
|
|
// If the last diverging line is more than one line above and the
|
|
// current line is at least line three, add some of the former lines and
|
|
// also add dots to indicate skipped entries.
|
|
if (cur > 1 && i > 2) {
|
|
if (cur > 4) {
|
|
res += "\n".concat(blue, "...").concat(white);
|
|
skipped = true;
|
|
} else if (cur > 3) {
|
|
res += "\n ".concat(actualLines[i - 2]);
|
|
printedLines++;
|
|
}
|
|
|
|
res += "\n ".concat(actualLines[i - 1]);
|
|
printedLines++;
|
|
} // Mark the current line as the last diverging one.
|
|
|
|
|
|
lastPos = i; // Add the actual line to the result and cache the expected diverging
|
|
// line so consecutive diverging lines show up as +++--- and not +-+-+-.
|
|
|
|
res += "\n".concat(green, "+").concat(white, " ").concat(actualLine);
|
|
other += "\n".concat(red, "-").concat(white, " ").concat(expectedLine);
|
|
printedLines += 2; // Lines are identical
|
|
} else {
|
|
// Add all cached information to the result before adding other things
|
|
// and reset the cache.
|
|
res += other;
|
|
other = ''; // If the last diverging line is exactly one line above or if it is the
|
|
// very first line, add the line to the result.
|
|
|
|
if (cur === 1 || i === 0) {
|
|
res += "\n ".concat(actualLine);
|
|
printedLines++;
|
|
}
|
|
}
|
|
} // Inspected object to big (Show ~20 rows max)
|
|
|
|
|
|
if (printedLines > 20 && i < maxLines - 2) {
|
|
return "".concat(msg).concat(skippedMsg, "\n").concat(res, "\n").concat(blue, "...").concat(white).concat(other, "\n") + "".concat(blue, "...").concat(white);
|
|
}
|
|
}
|
|
|
|
return "".concat(msg).concat(skipped ? skippedMsg : '', "\n").concat(res).concat(other).concat(end).concat(indicator);
|
|
}
|
|
|
|
var AssertionError =
|
|
/*#__PURE__*/
|
|
function (_Error) {
|
|
_inherits(AssertionError, _Error);
|
|
|
|
function AssertionError(options) {
|
|
var _this;
|
|
|
|
_classCallCheck(this, AssertionError);
|
|
|
|
if (_typeof(options) !== 'object' || options === null) {
|
|
throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
|
|
}
|
|
|
|
var message = options.message,
|
|
operator = options.operator,
|
|
stackStartFn = options.stackStartFn;
|
|
var actual = options.actual,
|
|
expected = options.expected;
|
|
var limit = Error.stackTraceLimit;
|
|
Error.stackTraceLimit = 0;
|
|
|
|
if (message != null) {
|
|
_this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError).call(this, String(message)));
|
|
} else {
|
|
if (process.stderr && process.stderr.isTTY) {
|
|
// Reset on each call to make sure we handle dynamically set environment
|
|
// variables correct.
|
|
if (process.stderr && process.stderr.getColorDepth && process.stderr.getColorDepth() !== 1) {
|
|
blue = "\x1B[34m";
|
|
green = "\x1B[32m";
|
|
white = "\x1B[39m";
|
|
red = "\x1B[31m";
|
|
} else {
|
|
blue = '';
|
|
green = '';
|
|
white = '';
|
|
red = '';
|
|
}
|
|
} // Prevent the error stack from being visible by duplicating the error
|
|
// in a very close way to the original in case both sides are actually
|
|
// instances of Error.
|
|
|
|
|
|
if (_typeof(actual) === 'object' && actual !== null && _typeof(expected) === 'object' && expected !== null && 'stack' in actual && actual instanceof Error && 'stack' in expected && expected instanceof Error) {
|
|
actual = copyError(actual);
|
|
expected = copyError(expected);
|
|
}
|
|
|
|
if (operator === 'deepStrictEqual' || operator === 'strictEqual') {
|
|
_this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError).call(this, createErrDiff(actual, expected, operator)));
|
|
} else if (operator === 'notDeepStrictEqual' || operator === 'notStrictEqual') {
|
|
// In case the objects are equal but the operator requires unequal, show
|
|
// the first object and say A equals B
|
|
var base = kReadableOperator[operator];
|
|
var res = inspectValue(actual).split('\n'); // In case "actual" is an object, it should not be reference equal.
|
|
|
|
if (operator === 'notStrictEqual' && _typeof(actual) === 'object' && actual !== null) {
|
|
base = kReadableOperator.notStrictEqualObject;
|
|
} // Only remove lines in case it makes sense to collapse those.
|
|
// TODO: Accept env to always show the full error.
|
|
|
|
|
|
if (res.length > 30) {
|
|
res[26] = "".concat(blue, "...").concat(white);
|
|
|
|
while (res.length > 27) {
|
|
res.pop();
|
|
}
|
|
} // Only print a single input.
|
|
|
|
|
|
if (res.length === 1) {
|
|
_this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError).call(this, "".concat(base, " ").concat(res[0])));
|
|
} else {
|
|
_this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError).call(this, "".concat(base, "\n\n").concat(res.join('\n'), "\n")));
|
|
}
|
|
} else {
|
|
var _res = inspectValue(actual);
|
|
|
|
var other = '';
|
|
var knownOperators = kReadableOperator[operator];
|
|
|
|
if (operator === 'notDeepEqual' || operator === 'notEqual') {
|
|
_res = "".concat(kReadableOperator[operator], "\n\n").concat(_res);
|
|
|
|
if (_res.length > 1024) {
|
|
_res = "".concat(_res.slice(0, 1021), "...");
|
|
}
|
|
} else {
|
|
other = "".concat(inspectValue(expected));
|
|
|
|
if (_res.length > 512) {
|
|
_res = "".concat(_res.slice(0, 509), "...");
|
|
}
|
|
|
|
if (other.length > 512) {
|
|
other = "".concat(other.slice(0, 509), "...");
|
|
}
|
|
|
|
if (operator === 'deepEqual' || operator === 'equal') {
|
|
_res = "".concat(knownOperators, "\n\n").concat(_res, "\n\nshould equal\n\n");
|
|
} else {
|
|
other = " ".concat(operator, " ").concat(other);
|
|
}
|
|
}
|
|
|
|
_this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError).call(this, "".concat(_res).concat(other)));
|
|
}
|
|
}
|
|
|
|
Error.stackTraceLimit = limit;
|
|
_this.generatedMessage = !message;
|
|
Object.defineProperty(_assertThisInitialized(_this), 'name', {
|
|
value: 'AssertionError [ERR_ASSERTION]',
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
});
|
|
_this.code = 'ERR_ASSERTION';
|
|
_this.actual = actual;
|
|
_this.expected = expected;
|
|
_this.operator = operator;
|
|
|
|
if (Error.captureStackTrace) {
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
Error.captureStackTrace(_assertThisInitialized(_this), stackStartFn);
|
|
} // Create error message including the error code in the name.
|
|
|
|
|
|
_this.stack; // Reset the name.
|
|
|
|
_this.name = 'AssertionError';
|
|
return _possibleConstructorReturn(_this);
|
|
}
|
|
|
|
_createClass(AssertionError, [{
|
|
key: "toString",
|
|
value: function toString() {
|
|
return "".concat(this.name, " [").concat(this.code, "]: ").concat(this.message);
|
|
}
|
|
}, {
|
|
key: inspect.custom,
|
|
value: function value(recurseTimes, ctx) {
|
|
// This limits the `actual` and `expected` property default inspection to
|
|
// the minimum depth. Otherwise those values would be too verbose compared
|
|
// to the actual error message which contains a combined view of these two
|
|
// input values.
|
|
return inspect(this, _objectSpread({}, ctx, {
|
|
customInspect: false,
|
|
depth: 0
|
|
}));
|
|
}
|
|
}]);
|
|
|
|
return AssertionError;
|
|
}(_wrapNativeSuper(Error));
|
|
|
|
module.exports = AssertionError;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/assert/build/internal/errors.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/assert/build/internal/errors.js ***!
|
|
\******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// Currently in sync with Node.js lib/internal/errors.js
|
|
// https://github.com/nodejs/node/commit/3b044962c48fe313905877a96b5d0894a5404f6f
|
|
|
|
/* eslint node-core/documented-errors: "error" */
|
|
|
|
/* eslint node-core/alphabetize-errors: "error" */
|
|
|
|
/* eslint node-core/prefer-util-format-errors: "error" */
|
|
// The whole point behind this internal module is to allow Node.js to no
|
|
// longer be forced to treat every error message change as a semver-major
|
|
// change. The NodeError classes here all expose a `code` property whose
|
|
// value statically and permanently identifies the error. While the error
|
|
// message may change, the code should not.
|
|
|
|
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
|
|
|
|
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
|
|
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
|
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
|
|
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
|
|
var codes = {}; // Lazy loaded
|
|
|
|
var assert;
|
|
var util;
|
|
|
|
function createErrorType(code, message, Base) {
|
|
if (!Base) {
|
|
Base = Error;
|
|
}
|
|
|
|
function getMessage(arg1, arg2, arg3) {
|
|
if (typeof message === 'string') {
|
|
return message;
|
|
} else {
|
|
return message(arg1, arg2, arg3);
|
|
}
|
|
}
|
|
|
|
var NodeError =
|
|
/*#__PURE__*/
|
|
function (_Base) {
|
|
_inherits(NodeError, _Base);
|
|
|
|
function NodeError(arg1, arg2, arg3) {
|
|
var _this;
|
|
|
|
_classCallCheck(this, NodeError);
|
|
|
|
_this = _possibleConstructorReturn(this, _getPrototypeOf(NodeError).call(this, getMessage(arg1, arg2, arg3)));
|
|
_this.code = code;
|
|
return _this;
|
|
}
|
|
|
|
return NodeError;
|
|
}(Base);
|
|
|
|
codes[code] = NodeError;
|
|
} // https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js
|
|
|
|
|
|
function oneOf(expected, thing) {
|
|
if (Array.isArray(expected)) {
|
|
var len = expected.length;
|
|
expected = expected.map(function (i) {
|
|
return String(i);
|
|
});
|
|
|
|
if (len > 2) {
|
|
return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(', '), ", or ") + expected[len - 1];
|
|
} else if (len === 2) {
|
|
return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]);
|
|
} else {
|
|
return "of ".concat(thing, " ").concat(expected[0]);
|
|
}
|
|
} else {
|
|
return "of ".concat(thing, " ").concat(String(expected));
|
|
}
|
|
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
|
|
|
|
|
|
function startsWith(str, search, pos) {
|
|
return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
|
|
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
|
|
|
|
|
|
function endsWith(str, search, this_len) {
|
|
if (this_len === undefined || this_len > str.length) {
|
|
this_len = str.length;
|
|
}
|
|
|
|
return str.substring(this_len - search.length, this_len) === search;
|
|
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
|
|
|
|
|
|
function includes(str, search, start) {
|
|
if (typeof start !== 'number') {
|
|
start = 0;
|
|
}
|
|
|
|
if (start + search.length > str.length) {
|
|
return false;
|
|
} else {
|
|
return str.indexOf(search, start) !== -1;
|
|
}
|
|
}
|
|
|
|
createErrorType('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError);
|
|
createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) {
|
|
if (assert === undefined) assert = __webpack_require__(/*! ../assert */ "./node_modules/assert/build/assert.js");
|
|
assert(typeof name === 'string', "'name' must be a string"); // determiner: 'must be' or 'must not be'
|
|
|
|
var determiner;
|
|
|
|
if (typeof expected === 'string' && startsWith(expected, 'not ')) {
|
|
determiner = 'must not be';
|
|
expected = expected.replace(/^not /, '');
|
|
} else {
|
|
determiner = 'must be';
|
|
}
|
|
|
|
var msg;
|
|
|
|
if (endsWith(name, ' argument')) {
|
|
// For cases like 'first argument'
|
|
msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, 'type'));
|
|
} else {
|
|
var type = includes(name, '.') ? 'property' : 'argument';
|
|
msg = "The \"".concat(name, "\" ").concat(type, " ").concat(determiner, " ").concat(oneOf(expected, 'type'));
|
|
} // TODO(BridgeAR): Improve the output by showing `null` and similar.
|
|
|
|
|
|
msg += ". Received type ".concat(_typeof(actual));
|
|
return msg;
|
|
}, TypeError);
|
|
createErrorType('ERR_INVALID_ARG_VALUE', function (name, value) {
|
|
var reason = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'is invalid';
|
|
if (util === undefined) util = __webpack_require__(/*! util/ */ "./node_modules/util/util.js");
|
|
var inspected = util.inspect(value);
|
|
|
|
if (inspected.length > 128) {
|
|
inspected = "".concat(inspected.slice(0, 128), "...");
|
|
}
|
|
|
|
return "The argument '".concat(name, "' ").concat(reason, ". Received ").concat(inspected);
|
|
}, TypeError, RangeError);
|
|
createErrorType('ERR_INVALID_RETURN_VALUE', function (input, name, value) {
|
|
var type;
|
|
|
|
if (value && value.constructor && value.constructor.name) {
|
|
type = "instance of ".concat(value.constructor.name);
|
|
} else {
|
|
type = "type ".concat(_typeof(value));
|
|
}
|
|
|
|
return "Expected ".concat(input, " to be returned from the \"").concat(name, "\"") + " function but got ".concat(type, ".");
|
|
}, TypeError);
|
|
createErrorType('ERR_MISSING_ARGS', function () {
|
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
|
|
if (assert === undefined) assert = __webpack_require__(/*! ../assert */ "./node_modules/assert/build/assert.js");
|
|
assert(args.length > 0, 'At least one arg needs to be specified');
|
|
var msg = 'The ';
|
|
var len = args.length;
|
|
args = args.map(function (a) {
|
|
return "\"".concat(a, "\"");
|
|
});
|
|
|
|
switch (len) {
|
|
case 1:
|
|
msg += "".concat(args[0], " argument");
|
|
break;
|
|
|
|
case 2:
|
|
msg += "".concat(args[0], " and ").concat(args[1], " arguments");
|
|
break;
|
|
|
|
default:
|
|
msg += args.slice(0, len - 1).join(', ');
|
|
msg += ", and ".concat(args[len - 1], " arguments");
|
|
break;
|
|
}
|
|
|
|
return "".concat(msg, " must be specified");
|
|
}, TypeError);
|
|
module.exports.codes = codes;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/assert/build/internal/util/comparisons.js":
|
|
/*!****************************************************************!*\
|
|
!*** ./node_modules/assert/build/internal/util/comparisons.js ***!
|
|
\****************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// Currently in sync with Node.js lib/internal/util/comparisons.js
|
|
// https://github.com/nodejs/node/commit/112cc7c27551254aa2b17098fb774867f05ed0d9
|
|
|
|
|
|
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
|
|
|
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
|
|
|
|
function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
|
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
|
|
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
|
|
var regexFlagsSupported = /a/g.flags !== undefined;
|
|
|
|
var arrayFromSet = function arrayFromSet(set) {
|
|
var array = [];
|
|
set.forEach(function (value) {
|
|
return array.push(value);
|
|
});
|
|
return array;
|
|
};
|
|
|
|
var arrayFromMap = function arrayFromMap(map) {
|
|
var array = [];
|
|
map.forEach(function (value, key) {
|
|
return array.push([key, value]);
|
|
});
|
|
return array;
|
|
};
|
|
|
|
var objectIs = Object.is ? Object.is : __webpack_require__(/*! object-is */ "./node_modules/object-is/index.js");
|
|
var objectGetOwnPropertySymbols = Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols : function () {
|
|
return [];
|
|
};
|
|
var numberIsNaN = Number.isNaN ? Number.isNaN : __webpack_require__(/*! is-nan */ "./node_modules/is-nan/index.js");
|
|
|
|
function uncurryThis(f) {
|
|
return f.call.bind(f);
|
|
}
|
|
|
|
var hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
|
|
var propertyIsEnumerable = uncurryThis(Object.prototype.propertyIsEnumerable);
|
|
var objectToString = uncurryThis(Object.prototype.toString);
|
|
|
|
var _require$types = __webpack_require__(/*! util/ */ "./node_modules/util/util.js").types,
|
|
isAnyArrayBuffer = _require$types.isAnyArrayBuffer,
|
|
isArrayBufferView = _require$types.isArrayBufferView,
|
|
isDate = _require$types.isDate,
|
|
isMap = _require$types.isMap,
|
|
isRegExp = _require$types.isRegExp,
|
|
isSet = _require$types.isSet,
|
|
isNativeError = _require$types.isNativeError,
|
|
isBoxedPrimitive = _require$types.isBoxedPrimitive,
|
|
isNumberObject = _require$types.isNumberObject,
|
|
isStringObject = _require$types.isStringObject,
|
|
isBooleanObject = _require$types.isBooleanObject,
|
|
isBigIntObject = _require$types.isBigIntObject,
|
|
isSymbolObject = _require$types.isSymbolObject,
|
|
isFloat32Array = _require$types.isFloat32Array,
|
|
isFloat64Array = _require$types.isFloat64Array;
|
|
|
|
function isNonIndex(key) {
|
|
if (key.length === 0 || key.length > 10) return true;
|
|
|
|
for (var i = 0; i < key.length; i++) {
|
|
var code = key.charCodeAt(i);
|
|
if (code < 48 || code > 57) return true;
|
|
} // The maximum size for an array is 2 ** 32 -1.
|
|
|
|
|
|
return key.length === 10 && key >= Math.pow(2, 32);
|
|
}
|
|
|
|
function getOwnNonIndexProperties(value) {
|
|
return Object.keys(value).filter(isNonIndex).concat(objectGetOwnPropertySymbols(value).filter(Object.prototype.propertyIsEnumerable.bind(value)));
|
|
} // Taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js
|
|
// original notice:
|
|
|
|
/*!
|
|
* The buffer module from node.js, for the browser.
|
|
*
|
|
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
|
* @license MIT
|
|
*/
|
|
|
|
|
|
function compare(a, b) {
|
|
if (a === b) {
|
|
return 0;
|
|
}
|
|
|
|
var x = a.length;
|
|
var y = b.length;
|
|
|
|
for (var 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;
|
|
}
|
|
|
|
var ONLY_ENUMERABLE = undefined;
|
|
var kStrict = true;
|
|
var kLoose = false;
|
|
var kNoIterator = 0;
|
|
var kIsArray = 1;
|
|
var kIsSet = 2;
|
|
var kIsMap = 3; // Check if they have the same source and flags
|
|
|
|
function areSimilarRegExps(a, b) {
|
|
return regexFlagsSupported ? a.source === b.source && a.flags === b.flags : RegExp.prototype.toString.call(a) === RegExp.prototype.toString.call(b);
|
|
}
|
|
|
|
function areSimilarFloatArrays(a, b) {
|
|
if (a.byteLength !== b.byteLength) {
|
|
return false;
|
|
}
|
|
|
|
for (var offset = 0; offset < a.byteLength; offset++) {
|
|
if (a[offset] !== b[offset]) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function areSimilarTypedArrays(a, b) {
|
|
if (a.byteLength !== b.byteLength) {
|
|
return false;
|
|
}
|
|
|
|
return compare(new Uint8Array(a.buffer, a.byteOffset, a.byteLength), new Uint8Array(b.buffer, b.byteOffset, b.byteLength)) === 0;
|
|
}
|
|
|
|
function areEqualArrayBuffers(buf1, buf2) {
|
|
return buf1.byteLength === buf2.byteLength && compare(new Uint8Array(buf1), new Uint8Array(buf2)) === 0;
|
|
}
|
|
|
|
function isEqualBoxedPrimitive(val1, val2) {
|
|
if (isNumberObject(val1)) {
|
|
return isNumberObject(val2) && objectIs(Number.prototype.valueOf.call(val1), Number.prototype.valueOf.call(val2));
|
|
}
|
|
|
|
if (isStringObject(val1)) {
|
|
return isStringObject(val2) && String.prototype.valueOf.call(val1) === String.prototype.valueOf.call(val2);
|
|
}
|
|
|
|
if (isBooleanObject(val1)) {
|
|
return isBooleanObject(val2) && Boolean.prototype.valueOf.call(val1) === Boolean.prototype.valueOf.call(val2);
|
|
}
|
|
|
|
if (isBigIntObject(val1)) {
|
|
return isBigIntObject(val2) && BigInt.prototype.valueOf.call(val1) === BigInt.prototype.valueOf.call(val2);
|
|
}
|
|
|
|
return isSymbolObject(val2) && Symbol.prototype.valueOf.call(val1) === Symbol.prototype.valueOf.call(val2);
|
|
} // Notes: Type tags are historical [[Class]] properties that can be set by
|
|
// FunctionTemplate::SetClassName() in C++ or Symbol.toStringTag in JS
|
|
// and retrieved using Object.prototype.toString.call(obj) in JS
|
|
// See https://tc39.github.io/ecma262/#sec-object.prototype.tostring
|
|
// for a list of tags pre-defined in the spec.
|
|
// There are some unspecified tags in the wild too (e.g. typed array tags).
|
|
// Since tags can be altered, they only serve fast failures
|
|
//
|
|
// Typed arrays and buffers are checked by comparing the content in their
|
|
// underlying ArrayBuffer. This optimization requires that it's
|
|
// reasonable to interpret their underlying memory in the same way,
|
|
// which is checked by comparing their type tags.
|
|
// (e.g. a Uint8Array and a Uint16Array with the same memory content
|
|
// could still be different because they will be interpreted differently).
|
|
//
|
|
// For strict comparison, objects should have
|
|
// a) The same built-in type tags
|
|
// b) The same prototypes.
|
|
|
|
|
|
function innerDeepEqual(val1, val2, strict, memos) {
|
|
// All identical values are equivalent, as determined by ===.
|
|
if (val1 === val2) {
|
|
if (val1 !== 0) return true;
|
|
return strict ? objectIs(val1, val2) : true;
|
|
} // Check more closely if val1 and val2 are equal.
|
|
|
|
|
|
if (strict) {
|
|
if (_typeof(val1) !== 'object') {
|
|
return typeof val1 === 'number' && numberIsNaN(val1) && numberIsNaN(val2);
|
|
}
|
|
|
|
if (_typeof(val2) !== 'object' || val1 === null || val2 === null) {
|
|
return false;
|
|
}
|
|
|
|
if (Object.getPrototypeOf(val1) !== Object.getPrototypeOf(val2)) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (val1 === null || _typeof(val1) !== 'object') {
|
|
if (val2 === null || _typeof(val2) !== 'object') {
|
|
// eslint-disable-next-line eqeqeq
|
|
return val1 == val2;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if (val2 === null || _typeof(val2) !== 'object') {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
var val1Tag = objectToString(val1);
|
|
var val2Tag = objectToString(val2);
|
|
|
|
if (val1Tag !== val2Tag) {
|
|
return false;
|
|
}
|
|
|
|
if (Array.isArray(val1)) {
|
|
// Check for sparse arrays and general fast path
|
|
if (val1.length !== val2.length) {
|
|
return false;
|
|
}
|
|
|
|
var keys1 = getOwnNonIndexProperties(val1, ONLY_ENUMERABLE);
|
|
var keys2 = getOwnNonIndexProperties(val2, ONLY_ENUMERABLE);
|
|
|
|
if (keys1.length !== keys2.length) {
|
|
return false;
|
|
}
|
|
|
|
return keyCheck(val1, val2, strict, memos, kIsArray, keys1);
|
|
} // [browserify] This triggers on certain types in IE (Map/Set) so we don't
|
|
// wan't to early return out of the rest of the checks. However we can check
|
|
// if the second value is one of these values and the first isn't.
|
|
|
|
|
|
if (val1Tag === '[object Object]') {
|
|
// return keyCheck(val1, val2, strict, memos, kNoIterator);
|
|
if (!isMap(val1) && isMap(val2) || !isSet(val1) && isSet(val2)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (isDate(val1)) {
|
|
if (!isDate(val2) || Date.prototype.getTime.call(val1) !== Date.prototype.getTime.call(val2)) {
|
|
return false;
|
|
}
|
|
} else if (isRegExp(val1)) {
|
|
if (!isRegExp(val2) || !areSimilarRegExps(val1, val2)) {
|
|
return false;
|
|
}
|
|
} else if (isNativeError(val1) || val1 instanceof Error) {
|
|
// Do not compare the stack as it might differ even though the error itself
|
|
// is otherwise identical.
|
|
if (val1.message !== val2.message || val1.name !== val2.name) {
|
|
return false;
|
|
}
|
|
} else if (isArrayBufferView(val1)) {
|
|
if (!strict && (isFloat32Array(val1) || isFloat64Array(val1))) {
|
|
if (!areSimilarFloatArrays(val1, val2)) {
|
|
return false;
|
|
}
|
|
} else if (!areSimilarTypedArrays(val1, val2)) {
|
|
return false;
|
|
} // Buffer.compare returns true, so val1.length === val2.length. If they both
|
|
// only contain numeric keys, we don't need to exam further than checking
|
|
// the symbols.
|
|
|
|
|
|
var _keys = getOwnNonIndexProperties(val1, ONLY_ENUMERABLE);
|
|
|
|
var _keys2 = getOwnNonIndexProperties(val2, ONLY_ENUMERABLE);
|
|
|
|
if (_keys.length !== _keys2.length) {
|
|
return false;
|
|
}
|
|
|
|
return keyCheck(val1, val2, strict, memos, kNoIterator, _keys);
|
|
} else if (isSet(val1)) {
|
|
if (!isSet(val2) || val1.size !== val2.size) {
|
|
return false;
|
|
}
|
|
|
|
return keyCheck(val1, val2, strict, memos, kIsSet);
|
|
} else if (isMap(val1)) {
|
|
if (!isMap(val2) || val1.size !== val2.size) {
|
|
return false;
|
|
}
|
|
|
|
return keyCheck(val1, val2, strict, memos, kIsMap);
|
|
} else if (isAnyArrayBuffer(val1)) {
|
|
if (!areEqualArrayBuffers(val1, val2)) {
|
|
return false;
|
|
}
|
|
} else if (isBoxedPrimitive(val1) && !isEqualBoxedPrimitive(val1, val2)) {
|
|
return false;
|
|
}
|
|
|
|
return keyCheck(val1, val2, strict, memos, kNoIterator);
|
|
}
|
|
|
|
function getEnumerables(val, keys) {
|
|
return keys.filter(function (k) {
|
|
return propertyIsEnumerable(val, k);
|
|
});
|
|
}
|
|
|
|
function keyCheck(val1, val2, strict, memos, iterationType, aKeys) {
|
|
// For all remaining Object pairs, including Array, objects and Maps,
|
|
// equivalence is determined by having:
|
|
// a) The same number of owned enumerable properties
|
|
// b) The same set of keys/indexes (although not necessarily the same order)
|
|
// c) Equivalent values for every corresponding key/index
|
|
// d) For Sets and Maps, equal contents
|
|
// Note: this accounts for both named and indexed properties on Arrays.
|
|
if (arguments.length === 5) {
|
|
aKeys = Object.keys(val1);
|
|
var bKeys = Object.keys(val2); // The pair must have the same number of owned properties.
|
|
|
|
if (aKeys.length !== bKeys.length) {
|
|
return false;
|
|
}
|
|
} // Cheap key test
|
|
|
|
|
|
var i = 0;
|
|
|
|
for (; i < aKeys.length; i++) {
|
|
if (!hasOwnProperty(val2, aKeys[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (strict && arguments.length === 5) {
|
|
var symbolKeysA = objectGetOwnPropertySymbols(val1);
|
|
|
|
if (symbolKeysA.length !== 0) {
|
|
var count = 0;
|
|
|
|
for (i = 0; i < symbolKeysA.length; i++) {
|
|
var key = symbolKeysA[i];
|
|
|
|
if (propertyIsEnumerable(val1, key)) {
|
|
if (!propertyIsEnumerable(val2, key)) {
|
|
return false;
|
|
}
|
|
|
|
aKeys.push(key);
|
|
count++;
|
|
} else if (propertyIsEnumerable(val2, key)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
var symbolKeysB = objectGetOwnPropertySymbols(val2);
|
|
|
|
if (symbolKeysA.length !== symbolKeysB.length && getEnumerables(val2, symbolKeysB).length !== count) {
|
|
return false;
|
|
}
|
|
} else {
|
|
var _symbolKeysB = objectGetOwnPropertySymbols(val2);
|
|
|
|
if (_symbolKeysB.length !== 0 && getEnumerables(val2, _symbolKeysB).length !== 0) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aKeys.length === 0 && (iterationType === kNoIterator || iterationType === kIsArray && val1.length === 0 || val1.size === 0)) {
|
|
return true;
|
|
} // Use memos to handle cycles.
|
|
|
|
|
|
if (memos === undefined) {
|
|
memos = {
|
|
val1: new Map(),
|
|
val2: new Map(),
|
|
position: 0
|
|
};
|
|
} else {
|
|
// We prevent up to two map.has(x) calls by directly retrieving the value
|
|
// and checking for undefined. The map can only contain numbers, so it is
|
|
// safe to check for undefined only.
|
|
var val2MemoA = memos.val1.get(val1);
|
|
|
|
if (val2MemoA !== undefined) {
|
|
var val2MemoB = memos.val2.get(val2);
|
|
|
|
if (val2MemoB !== undefined) {
|
|
return val2MemoA === val2MemoB;
|
|
}
|
|
}
|
|
|
|
memos.position++;
|
|
}
|
|
|
|
memos.val1.set(val1, memos.position);
|
|
memos.val2.set(val2, memos.position);
|
|
var areEq = objEquiv(val1, val2, strict, aKeys, memos, iterationType);
|
|
memos.val1.delete(val1);
|
|
memos.val2.delete(val2);
|
|
return areEq;
|
|
}
|
|
|
|
function setHasEqualElement(set, val1, strict, memo) {
|
|
// Go looking.
|
|
var setValues = arrayFromSet(set);
|
|
|
|
for (var i = 0; i < setValues.length; i++) {
|
|
var val2 = setValues[i];
|
|
|
|
if (innerDeepEqual(val1, val2, strict, memo)) {
|
|
// Remove the matching element to make sure we do not check that again.
|
|
set.delete(val2);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
} // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#Loose_equality_using
|
|
// Sadly it is not possible to detect corresponding values properly in case the
|
|
// type is a string, number, bigint or boolean. The reason is that those values
|
|
// can match lots of different string values (e.g., 1n == '+00001').
|
|
|
|
|
|
function findLooseMatchingPrimitives(prim) {
|
|
switch (_typeof(prim)) {
|
|
case 'undefined':
|
|
return null;
|
|
|
|
case 'object':
|
|
// Only pass in null as object!
|
|
return undefined;
|
|
|
|
case 'symbol':
|
|
return false;
|
|
|
|
case 'string':
|
|
prim = +prim;
|
|
// Loose equal entries exist only if the string is possible to convert to
|
|
// a regular number and not NaN.
|
|
// Fall through
|
|
|
|
case 'number':
|
|
if (numberIsNaN(prim)) {
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function setMightHaveLoosePrim(a, b, prim) {
|
|
var altValue = findLooseMatchingPrimitives(prim);
|
|
if (altValue != null) return altValue;
|
|
return b.has(altValue) && !a.has(altValue);
|
|
}
|
|
|
|
function mapMightHaveLoosePrim(a, b, prim, item, memo) {
|
|
var altValue = findLooseMatchingPrimitives(prim);
|
|
|
|
if (altValue != null) {
|
|
return altValue;
|
|
}
|
|
|
|
var curB = b.get(altValue);
|
|
|
|
if (curB === undefined && !b.has(altValue) || !innerDeepEqual(item, curB, false, memo)) {
|
|
return false;
|
|
}
|
|
|
|
return !a.has(altValue) && innerDeepEqual(item, curB, false, memo);
|
|
}
|
|
|
|
function setEquiv(a, b, strict, memo) {
|
|
// This is a lazily initiated Set of entries which have to be compared
|
|
// pairwise.
|
|
var set = null;
|
|
var aValues = arrayFromSet(a);
|
|
|
|
for (var i = 0; i < aValues.length; i++) {
|
|
var val = aValues[i]; // Note: Checking for the objects first improves the performance for object
|
|
// heavy sets but it is a minor slow down for primitives. As they are fast
|
|
// to check this improves the worst case scenario instead.
|
|
|
|
if (_typeof(val) === 'object' && val !== null) {
|
|
if (set === null) {
|
|
set = new Set();
|
|
} // If the specified value doesn't exist in the second set its an not null
|
|
// object (or non strict only: a not matching primitive) we'll need to go
|
|
// hunting for something thats deep-(strict-)equal to it. To make this
|
|
// O(n log n) complexity we have to copy these values in a new set first.
|
|
|
|
|
|
set.add(val);
|
|
} else if (!b.has(val)) {
|
|
if (strict) return false; // Fast path to detect missing string, symbol, undefined and null values.
|
|
|
|
if (!setMightHaveLoosePrim(a, b, val)) {
|
|
return false;
|
|
}
|
|
|
|
if (set === null) {
|
|
set = new Set();
|
|
}
|
|
|
|
set.add(val);
|
|
}
|
|
}
|
|
|
|
if (set !== null) {
|
|
var bValues = arrayFromSet(b);
|
|
|
|
for (var _i = 0; _i < bValues.length; _i++) {
|
|
var _val = bValues[_i]; // We have to check if a primitive value is already
|
|
// matching and only if it's not, go hunting for it.
|
|
|
|
if (_typeof(_val) === 'object' && _val !== null) {
|
|
if (!setHasEqualElement(set, _val, strict, memo)) return false;
|
|
} else if (!strict && !a.has(_val) && !setHasEqualElement(set, _val, strict, memo)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return set.size === 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function mapHasEqualEntry(set, map, key1, item1, strict, memo) {
|
|
// To be able to handle cases like:
|
|
// Map([[{}, 'a'], [{}, 'b']]) vs Map([[{}, 'b'], [{}, 'a']])
|
|
// ... we need to consider *all* matching keys, not just the first we find.
|
|
var setValues = arrayFromSet(set);
|
|
|
|
for (var i = 0; i < setValues.length; i++) {
|
|
var key2 = setValues[i];
|
|
|
|
if (innerDeepEqual(key1, key2, strict, memo) && innerDeepEqual(item1, map.get(key2), strict, memo)) {
|
|
set.delete(key2);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function mapEquiv(a, b, strict, memo) {
|
|
var set = null;
|
|
var aEntries = arrayFromMap(a);
|
|
|
|
for (var i = 0; i < aEntries.length; i++) {
|
|
var _aEntries$i = _slicedToArray(aEntries[i], 2),
|
|
key = _aEntries$i[0],
|
|
item1 = _aEntries$i[1];
|
|
|
|
if (_typeof(key) === 'object' && key !== null) {
|
|
if (set === null) {
|
|
set = new Set();
|
|
}
|
|
|
|
set.add(key);
|
|
} else {
|
|
// By directly retrieving the value we prevent another b.has(key) check in
|
|
// almost all possible cases.
|
|
var item2 = b.get(key);
|
|
|
|
if (item2 === undefined && !b.has(key) || !innerDeepEqual(item1, item2, strict, memo)) {
|
|
if (strict) return false; // Fast path to detect missing string, symbol, undefined and null
|
|
// keys.
|
|
|
|
if (!mapMightHaveLoosePrim(a, b, key, item1, memo)) return false;
|
|
|
|
if (set === null) {
|
|
set = new Set();
|
|
}
|
|
|
|
set.add(key);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (set !== null) {
|
|
var bEntries = arrayFromMap(b);
|
|
|
|
for (var _i2 = 0; _i2 < bEntries.length; _i2++) {
|
|
var _bEntries$_i = _slicedToArray(bEntries[_i2], 2),
|
|
key = _bEntries$_i[0],
|
|
item = _bEntries$_i[1];
|
|
|
|
if (_typeof(key) === 'object' && key !== null) {
|
|
if (!mapHasEqualEntry(set, a, key, item, strict, memo)) return false;
|
|
} else if (!strict && (!a.has(key) || !innerDeepEqual(a.get(key), item, false, memo)) && !mapHasEqualEntry(set, a, key, item, false, memo)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return set.size === 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function objEquiv(a, b, strict, keys, memos, iterationType) {
|
|
// Sets and maps don't have their entries accessible via normal object
|
|
// properties.
|
|
var i = 0;
|
|
|
|
if (iterationType === kIsSet) {
|
|
if (!setEquiv(a, b, strict, memos)) {
|
|
return false;
|
|
}
|
|
} else if (iterationType === kIsMap) {
|
|
if (!mapEquiv(a, b, strict, memos)) {
|
|
return false;
|
|
}
|
|
} else if (iterationType === kIsArray) {
|
|
for (; i < a.length; i++) {
|
|
if (hasOwnProperty(a, i)) {
|
|
if (!hasOwnProperty(b, i) || !innerDeepEqual(a[i], b[i], strict, memos)) {
|
|
return false;
|
|
}
|
|
} else if (hasOwnProperty(b, i)) {
|
|
return false;
|
|
} else {
|
|
// Array is sparse.
|
|
var keysA = Object.keys(a);
|
|
|
|
for (; i < keysA.length; i++) {
|
|
var key = keysA[i];
|
|
|
|
if (!hasOwnProperty(b, key) || !innerDeepEqual(a[key], b[key], strict, memos)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (keysA.length !== Object.keys(b).length) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
} // The pair must have equivalent values for every corresponding key.
|
|
// Possibly expensive deep test:
|
|
|
|
|
|
for (i = 0; i < keys.length; i++) {
|
|
var _key = keys[i];
|
|
|
|
if (!innerDeepEqual(a[_key], b[_key], strict, memos)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function isDeepEqual(val1, val2) {
|
|
return innerDeepEqual(val1, val2, kLoose);
|
|
}
|
|
|
|
function isDeepStrictEqual(val1, val2) {
|
|
return innerDeepEqual(val1, val2, kStrict);
|
|
}
|
|
|
|
module.exports = {
|
|
isDeepEqual: isDeepEqual,
|
|
isDeepStrictEqual: isDeepStrictEqual
|
|
};
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/available-typed-arrays/index.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/available-typed-arrays/index.js ***!
|
|
\******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var possibleNames = [
|
|
'BigInt64Array',
|
|
'BigUint64Array',
|
|
'Float32Array',
|
|
'Float64Array',
|
|
'Int16Array',
|
|
'Int32Array',
|
|
'Int8Array',
|
|
'Uint16Array',
|
|
'Uint32Array',
|
|
'Uint8Array',
|
|
'Uint8ClampedArray'
|
|
];
|
|
|
|
module.exports = function availableTypedArrays() {
|
|
var out = [];
|
|
for (var i = 0; i < possibleNames.length; i++) {
|
|
if (typeof __webpack_require__.g[possibleNames[i]] === 'function') {
|
|
out[out.length] = possibleNames[i];
|
|
}
|
|
}
|
|
return out;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./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/bencode/lib/decode.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/bencode/lib/decode.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
const INTEGER_START = 0x69 // 'i'
|
|
const STRING_DELIM = 0x3A // ':'
|
|
const DICTIONARY_START = 0x64 // 'd'
|
|
const LIST_START = 0x6C // 'l'
|
|
const END_OF_TYPE = 0x65 // 'e'
|
|
|
|
/**
|
|
* replaces parseInt(buffer.toString('ascii', start, end)).
|
|
* For strings with less then ~30 charachters, this is actually a lot faster.
|
|
*
|
|
* @param {Buffer} data
|
|
* @param {Number} start
|
|
* @param {Number} end
|
|
* @return {Number} calculated number
|
|
*/
|
|
function getIntFromBuffer (buffer, start, end) {
|
|
var sum = 0
|
|
var sign = 1
|
|
|
|
for (var i = start; i < end; i++) {
|
|
var num = buffer[i]
|
|
|
|
if (num < 58 && num >= 48) {
|
|
sum = sum * 10 + (num - 48)
|
|
continue
|
|
}
|
|
|
|
if (i === start && num === 43) { // +
|
|
continue
|
|
}
|
|
|
|
if (i === start && num === 45) { // -
|
|
sign = -1
|
|
continue
|
|
}
|
|
|
|
if (num === 46) { // .
|
|
// its a float. break here.
|
|
break
|
|
}
|
|
|
|
throw new Error('not a number: buffer[' + i + '] = ' + num)
|
|
}
|
|
|
|
return sum * sign
|
|
}
|
|
|
|
/**
|
|
* Decodes bencoded data.
|
|
*
|
|
* @param {Buffer} data
|
|
* @param {Number} start (optional)
|
|
* @param {Number} end (optional)
|
|
* @param {String} encoding (optional)
|
|
* @return {Object|Array|Buffer|String|Number}
|
|
*/
|
|
function decode (data, start, end, encoding) {
|
|
if (data == null || data.length === 0) {
|
|
return null
|
|
}
|
|
|
|
if (typeof start !== 'number' && encoding == null) {
|
|
encoding = start
|
|
start = undefined
|
|
}
|
|
|
|
if (typeof end !== 'number' && encoding == null) {
|
|
encoding = end
|
|
end = undefined
|
|
}
|
|
|
|
decode.position = 0
|
|
decode.encoding = encoding || null
|
|
|
|
decode.data = !(Buffer.isBuffer(data))
|
|
? Buffer.from(data)
|
|
: data.slice(start, end)
|
|
|
|
decode.bytes = decode.data.length
|
|
|
|
return decode.next()
|
|
}
|
|
|
|
decode.bytes = 0
|
|
decode.position = 0
|
|
decode.data = null
|
|
decode.encoding = null
|
|
|
|
decode.next = function () {
|
|
switch (decode.data[decode.position]) {
|
|
case DICTIONARY_START:
|
|
return decode.dictionary()
|
|
case LIST_START:
|
|
return decode.list()
|
|
case INTEGER_START:
|
|
return decode.integer()
|
|
default:
|
|
return decode.buffer()
|
|
}
|
|
}
|
|
|
|
decode.find = function (chr) {
|
|
var i = decode.position
|
|
var c = decode.data.length
|
|
var d = decode.data
|
|
|
|
while (i < c) {
|
|
if (d[i] === chr) return i
|
|
i++
|
|
}
|
|
|
|
throw new Error(
|
|
'Invalid data: Missing delimiter "' +
|
|
String.fromCharCode(chr) + '" [0x' +
|
|
chr.toString(16) + ']'
|
|
)
|
|
}
|
|
|
|
decode.dictionary = function () {
|
|
decode.position++
|
|
|
|
var dict = {}
|
|
|
|
while (decode.data[decode.position] !== END_OF_TYPE) {
|
|
dict[decode.buffer()] = decode.next()
|
|
}
|
|
|
|
decode.position++
|
|
|
|
return dict
|
|
}
|
|
|
|
decode.list = function () {
|
|
decode.position++
|
|
|
|
var lst = []
|
|
|
|
while (decode.data[decode.position] !== END_OF_TYPE) {
|
|
lst.push(decode.next())
|
|
}
|
|
|
|
decode.position++
|
|
|
|
return lst
|
|
}
|
|
|
|
decode.integer = function () {
|
|
var end = decode.find(END_OF_TYPE)
|
|
var number = getIntFromBuffer(decode.data, decode.position + 1, end)
|
|
|
|
decode.position += end + 1 - decode.position
|
|
|
|
return number
|
|
}
|
|
|
|
decode.buffer = function () {
|
|
var sep = decode.find(STRING_DELIM)
|
|
var length = getIntFromBuffer(decode.data, decode.position, sep)
|
|
var end = ++sep + length
|
|
|
|
decode.position = end
|
|
|
|
return decode.encoding
|
|
? decode.data.toString(decode.encoding, sep, end)
|
|
: decode.data.slice(sep, end)
|
|
}
|
|
|
|
module.exports = decode
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/bencode/lib/encode.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/bencode/lib/encode.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
/**
|
|
* Encodes data in bencode.
|
|
*
|
|
* @param {Buffer|Array|String|Object|Number|Boolean} data
|
|
* @return {Buffer}
|
|
*/
|
|
function encode (data, buffer, offset) {
|
|
var buffers = []
|
|
var result = null
|
|
|
|
encode._encode(buffers, data)
|
|
result = Buffer.concat(buffers)
|
|
encode.bytes = result.length
|
|
|
|
if (Buffer.isBuffer(buffer)) {
|
|
result.copy(buffer, offset)
|
|
return buffer
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
encode.bytes = -1
|
|
encode._floatConversionDetected = false
|
|
|
|
encode.getType = function (value) {
|
|
if (Buffer.isBuffer(value)) return 'buffer'
|
|
if (Array.isArray(value)) return 'array'
|
|
if (ArrayBuffer.isView(value)) return 'arraybufferview'
|
|
if (value instanceof Number) return 'number'
|
|
if (value instanceof Boolean) return 'boolean'
|
|
if (value instanceof ArrayBuffer) return 'arraybuffer'
|
|
return typeof value
|
|
}
|
|
|
|
encode._encode = function (buffers, data) {
|
|
if (data == null) { return }
|
|
|
|
switch (encode.getType(data)) {
|
|
case 'buffer': encode.buffer(buffers, data); break
|
|
case 'object': encode.dict(buffers, data); break
|
|
case 'array': encode.list(buffers, data); break
|
|
case 'string': encode.string(buffers, data); break
|
|
case 'number': encode.number(buffers, data); break
|
|
case 'boolean': encode.number(buffers, data); break
|
|
case 'arraybufferview': encode.buffer(buffers, Buffer.from(data.buffer, data.byteOffset, data.byteLength)); break
|
|
case 'arraybuffer': encode.buffer(buffers, Buffer.from(data)); break
|
|
}
|
|
}
|
|
|
|
var buffE = Buffer.from('e')
|
|
var buffD = Buffer.from('d')
|
|
var buffL = Buffer.from('l')
|
|
|
|
encode.buffer = function (buffers, data) {
|
|
buffers.push(Buffer.from(data.length + ':'), data)
|
|
}
|
|
|
|
encode.string = function (buffers, data) {
|
|
buffers.push(Buffer.from(Buffer.byteLength(data) + ':' + data))
|
|
}
|
|
|
|
encode.number = function (buffers, data) {
|
|
var maxLo = 0x80000000
|
|
var hi = (data / maxLo) << 0
|
|
var lo = (data % maxLo) << 0
|
|
var val = hi * maxLo + lo
|
|
|
|
buffers.push(Buffer.from('i' + val + 'e'))
|
|
|
|
if (val !== data && !encode._floatConversionDetected) {
|
|
encode._floatConversionDetected = true
|
|
console.warn(
|
|
'WARNING: Possible data corruption detected with value "' + data + '":',
|
|
'Bencoding only defines support for integers, value was converted to "' + val + '"'
|
|
)
|
|
console.trace()
|
|
}
|
|
}
|
|
|
|
encode.dict = function (buffers, data) {
|
|
buffers.push(buffD)
|
|
|
|
var j = 0
|
|
var k
|
|
// fix for issue #13 - sorted dicts
|
|
var keys = Object.keys(data).sort()
|
|
var kl = keys.length
|
|
|
|
for (; j < kl; j++) {
|
|
k = keys[j]
|
|
if (data[k] == null) continue
|
|
encode.string(buffers, k)
|
|
encode._encode(buffers, data[k])
|
|
}
|
|
|
|
buffers.push(buffE)
|
|
}
|
|
|
|
encode.list = function (buffers, data) {
|
|
var i = 0
|
|
var c = data.length
|
|
buffers.push(buffL)
|
|
|
|
for (; i < c; i++) {
|
|
if (data[i] == null) continue
|
|
encode._encode(buffers, data[i])
|
|
}
|
|
|
|
buffers.push(buffE)
|
|
}
|
|
|
|
module.exports = encode
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/bencode/lib/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/bencode/lib/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var bencode = module.exports
|
|
|
|
bencode.encode = __webpack_require__(/*! ./encode */ "./node_modules/bencode/lib/encode.js")
|
|
bencode.decode = __webpack_require__(/*! ./decode */ "./node_modules/bencode/lib/decode.js")
|
|
|
|
/**
|
|
* Determines the amount of bytes
|
|
* needed to encode the given value
|
|
* @param {Object|Array|Buffer|String|Number|Boolean} value
|
|
* @return {Number} byteCount
|
|
*/
|
|
bencode.byteLength = bencode.encodingLength = function (value) {
|
|
return bencode.encode(value).length
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/bep53-range/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/bep53-range/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = parseRange
|
|
module.exports.parse = parseRange
|
|
module.exports.compose = composeRange
|
|
|
|
function composeRange (range) {
|
|
return range
|
|
.reduce((acc, cur, idx, arr) => {
|
|
if (idx === 0 || cur !== arr[idx - 1] + 1) acc.push([])
|
|
acc[acc.length - 1].push(cur)
|
|
return acc
|
|
}, [])
|
|
.map((cur) => {
|
|
return cur.length > 1 ? `${cur[0]}-${cur[cur.length - 1]}` : `${cur[0]}`
|
|
})
|
|
}
|
|
|
|
function parseRange (range) {
|
|
const generateRange = (start, end = start) => Array.from({ length: end - start + 1 }, (cur, idx) => idx + start)
|
|
|
|
return range
|
|
.reduce((acc, cur, idx, arr) => {
|
|
const r = cur.split('-').map(cur => parseInt(cur))
|
|
return acc.concat(generateRange(...r))
|
|
}, [])
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/binary-search/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/binary-search/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = function(haystack, needle, comparator, low, high) {
|
|
var mid, cmp;
|
|
|
|
if(low === undefined)
|
|
low = 0;
|
|
|
|
else {
|
|
low = low|0;
|
|
if(low < 0 || low >= haystack.length)
|
|
throw new RangeError("invalid lower bound");
|
|
}
|
|
|
|
if(high === undefined)
|
|
high = haystack.length - 1;
|
|
|
|
else {
|
|
high = high|0;
|
|
if(high < low || high >= haystack.length)
|
|
throw new RangeError("invalid upper bound");
|
|
}
|
|
|
|
while(low <= high) {
|
|
// The naive `low + high >>> 1` could fail for array lengths > 2**31
|
|
// because `>>>` converts its operands to int32. `low + (high - low >>> 1)`
|
|
// works for array lengths <= 2**32-1 which is also Javascript's max array
|
|
// length.
|
|
mid = low + ((high - low) >>> 1);
|
|
cmp = +comparator(haystack[mid], needle, mid, haystack);
|
|
|
|
// Too low.
|
|
if(cmp < 0.0)
|
|
low = mid + 1;
|
|
|
|
// Too high.
|
|
else if(cmp > 0.0)
|
|
high = mid - 1;
|
|
|
|
// Key found.
|
|
else
|
|
return mid;
|
|
}
|
|
|
|
// Key not found.
|
|
return ~low;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/bitfield/lib/index.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/bitfield/lib/index.js ***!
|
|
\********************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
function getByteSize(num) {
|
|
var out = num >> 3;
|
|
if (num % 8 !== 0)
|
|
out++;
|
|
return out;
|
|
}
|
|
var BitField = /** @class */ (function () {
|
|
/**
|
|
*
|
|
*
|
|
* @param data Either a number representing the maximum number of supported bytes, or a Uint8Array.
|
|
* @param opts Options for the bitfield.
|
|
*/
|
|
function BitField(data, opts) {
|
|
if (data === void 0) { data = 0; }
|
|
var grow = opts === null || opts === void 0 ? void 0 : opts.grow;
|
|
this.grow = (grow && isFinite(grow) && getByteSize(grow)) || grow || 0;
|
|
this.buffer =
|
|
typeof data === "number" ? new Uint8Array(getByteSize(data)) : data;
|
|
}
|
|
/**
|
|
* Get a particular bit.
|
|
*
|
|
* @param i Bit index to retrieve.
|
|
* @returns A boolean indicating whether the `i`th bit is set.
|
|
*/
|
|
BitField.prototype.get = function (i) {
|
|
var j = i >> 3;
|
|
return j < this.buffer.length && !!(this.buffer[j] & (128 >> i % 8));
|
|
};
|
|
/**
|
|
* Set a particular bit.
|
|
*
|
|
* Will grow the underlying array if the bit is out of bounds and the `grow` option is set.
|
|
*
|
|
* @param i Bit index to set.
|
|
* @param value Value to set the bit to. Defaults to `true`.
|
|
*/
|
|
BitField.prototype.set = function (i, value) {
|
|
if (value === void 0) { value = true; }
|
|
var j = i >> 3;
|
|
if (value) {
|
|
if (this.buffer.length < j + 1) {
|
|
var length_1 = Math.max(j + 1, Math.min(2 * this.buffer.length, this.grow));
|
|
if (length_1 <= this.grow) {
|
|
var newBuffer = new Uint8Array(length_1);
|
|
newBuffer.set(this.buffer);
|
|
this.buffer = newBuffer;
|
|
}
|
|
}
|
|
// Set
|
|
this.buffer[j] |= 128 >> i % 8;
|
|
}
|
|
else if (j < this.buffer.length) {
|
|
// Clear
|
|
this.buffer[j] &= ~(128 >> i % 8);
|
|
}
|
|
};
|
|
/**
|
|
* Loop through the bits in the bitfield.
|
|
*
|
|
* @param fn Function to be called with the bit value and index.
|
|
* @param start Index of the first bit to look at.
|
|
* @param end Index of the first bit that should no longer be considered.
|
|
*/
|
|
BitField.prototype.forEach = function (fn, start, end) {
|
|
if (start === void 0) { start = 0; }
|
|
if (end === void 0) { end = this.buffer.length * 8; }
|
|
for (var i = start, j = i >> 3, y = 128 >> i % 8, byte = this.buffer[j]; i < end; i++) {
|
|
fn(!!(byte & y), i);
|
|
y = y === 1 ? ((byte = this.buffer[++j]), 128) : y >> 1;
|
|
}
|
|
};
|
|
return BitField;
|
|
}());
|
|
exports.default = BitField;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/bittorrent-protocol/index.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/bittorrent-protocol/index.js ***!
|
|
\***************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! bittorrent-protocol. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */
|
|
const arrayRemove = __webpack_require__(/*! unordered-array-remove */ "./node_modules/unordered-array-remove/index.js")
|
|
const bencode = __webpack_require__(/*! bencode */ "./node_modules/bencode/lib/index.js")
|
|
const BitField = __webpack_require__(/*! bitfield */ "./node_modules/bitfield/lib/index.js").default
|
|
const crypto = __webpack_require__(/*! crypto */ "./node_modules/crypto-browserify/index.js")
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('bittorrent-protocol')
|
|
const randombytes = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js")
|
|
const sha1 = __webpack_require__(/*! simple-sha1 */ "./node_modules/simple-sha1/browser.js")
|
|
const speedometer = __webpack_require__(/*! speedometer */ "./node_modules/speedometer/index.js")
|
|
const stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
const RC4 = __webpack_require__(/*! rc4 */ "./node_modules/rc4/rc4.js")
|
|
|
|
const BITFIELD_GROW = 400000
|
|
const KEEP_ALIVE_TIMEOUT = 55000
|
|
|
|
const MESSAGE_PROTOCOL = Buffer.from('\u0013BitTorrent protocol')
|
|
const MESSAGE_KEEP_ALIVE = Buffer.from([0x00, 0x00, 0x00, 0x00])
|
|
const MESSAGE_CHOKE = Buffer.from([0x00, 0x00, 0x00, 0x01, 0x00])
|
|
const MESSAGE_UNCHOKE = Buffer.from([0x00, 0x00, 0x00, 0x01, 0x01])
|
|
const MESSAGE_INTERESTED = Buffer.from([0x00, 0x00, 0x00, 0x01, 0x02])
|
|
const MESSAGE_UNINTERESTED = Buffer.from([0x00, 0x00, 0x00, 0x01, 0x03])
|
|
|
|
const MESSAGE_RESERVED = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
const MESSAGE_PORT = [0x00, 0x00, 0x00, 0x03, 0x09, 0x00, 0x00]
|
|
|
|
const DH_PRIME = 'ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a36210000000000090563'
|
|
const DH_GENERATOR = 2
|
|
const VC = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
|
|
const CRYPTO_PROVIDE = Buffer.from([0x00, 0x00, 0x01, 0x02])
|
|
const CRYPTO_SELECT = Buffer.from([0x00, 0x00, 0x00, 0x02]) // always try to choose RC4 encryption instead of plaintext
|
|
|
|
function xor (a, b) {
|
|
for (let len = a.length; len--;) a[len] ^= b[len]
|
|
return a
|
|
}
|
|
|
|
class Request {
|
|
constructor (piece, offset, length, callback) {
|
|
this.piece = piece
|
|
this.offset = offset
|
|
this.length = length
|
|
this.callback = callback
|
|
}
|
|
}
|
|
|
|
class Wire extends stream.Duplex {
|
|
constructor (type = null, retries = 0, peEnabled = false) {
|
|
super()
|
|
|
|
this._debugId = randombytes(4).toString('hex')
|
|
this._debug('new wire')
|
|
|
|
this.peerId = null // remote peer id (hex string)
|
|
this.peerIdBuffer = null // remote peer id (buffer)
|
|
this.type = type // connection type ('webrtc', 'tcpIncoming', 'tcpOutgoing', 'webSeed')
|
|
|
|
this.amChoking = true // are we choking the peer?
|
|
this.amInterested = false // are we interested in the peer?
|
|
|
|
this.peerChoking = true // is the peer choking us?
|
|
this.peerInterested = false // is the peer interested in us?
|
|
|
|
// The largest torrent that I know of (the Geocities archive) is ~641 GB and has
|
|
// ~41,000 pieces. Therefore, cap bitfield to 10x larger (400,000 bits) to support all
|
|
// possible torrents but prevent malicious peers from growing bitfield to fill memory.
|
|
this.peerPieces = new BitField(0, { grow: BITFIELD_GROW })
|
|
|
|
this.peerExtensions = {}
|
|
|
|
this.requests = [] // outgoing
|
|
this.peerRequests = [] // incoming
|
|
|
|
this.extendedMapping = {} // number -> string, ex: 1 -> 'ut_metadata'
|
|
this.peerExtendedMapping = {} // string -> number, ex: 9 -> 'ut_metadata'
|
|
|
|
// The extended handshake to send, minus the "m" field, which gets automatically
|
|
// filled from `this.extendedMapping`
|
|
this.extendedHandshake = {}
|
|
|
|
this.peerExtendedHandshake = {} // remote peer's extended handshake
|
|
|
|
this._ext = {} // string -> function, ex 'ut_metadata' -> ut_metadata()
|
|
this._nextExt = 1
|
|
|
|
this.uploaded = 0
|
|
this.downloaded = 0
|
|
this.uploadSpeed = speedometer()
|
|
this.downloadSpeed = speedometer()
|
|
|
|
this._keepAliveInterval = null
|
|
this._timeout = null
|
|
this._timeoutMs = 0
|
|
this._timeoutExpiresAt = null
|
|
|
|
this.destroyed = false // was the wire ended by calling `destroy`?
|
|
this._finished = false
|
|
|
|
this._parserSize = 0 // number of needed bytes to parse next message from remote peer
|
|
this._parser = null // function to call once `this._parserSize` bytes are available
|
|
|
|
this._buffer = [] // incomplete message data
|
|
this._bufferSize = 0 // cached total length of buffers in `this._buffer`
|
|
|
|
this._peEnabled = peEnabled
|
|
if (peEnabled) {
|
|
this._dh = crypto.createDiffieHellman(DH_PRIME, 'hex', DH_GENERATOR) // crypto object used to generate keys/secret
|
|
this._myPubKey = this._dh.generateKeys('hex') // my DH public key
|
|
} else {
|
|
this._myPubKey = null
|
|
}
|
|
this._peerPubKey = null // peer's DH public key
|
|
this._sharedSecret = null // shared DH secret
|
|
this._peerCryptoProvide = [] // encryption methods provided by peer; we expect this to always contain 0x02
|
|
this._cryptoHandshakeDone = false
|
|
|
|
this._cryptoSyncPattern = null // the pattern to search for when resynchronizing after receiving pe1/pe2
|
|
this._waitMaxBytes = null // the maximum number of bytes resynchronization must occur within
|
|
this._encryptionMethod = null // 1 for plaintext, 2 for RC4
|
|
this._encryptGenerator = null // RC4 keystream generator for encryption
|
|
this._decryptGenerator = null // RC4 keystream generator for decryption
|
|
this._setGenerators = false // a flag for whether setEncrypt() has successfully completed
|
|
|
|
this.once('finish', () => this._onFinish())
|
|
|
|
this.on('finish', this._onFinish)
|
|
this._debug('type:', this.type)
|
|
|
|
if (this.type === 'tcpIncoming' && this._peEnabled) {
|
|
// If we are not the initiator, we should wait to see if the client begins
|
|
// with PE/MSE handshake or the standard bittorrent handshake.
|
|
this._determineHandshakeType()
|
|
} else if (this.type === 'tcpOutgoing' && this._peEnabled && retries === 0) {
|
|
this._parsePe2()
|
|
} else {
|
|
this._parseHandshake(null)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set whether to send a "keep-alive" ping (sent every 55s)
|
|
* @param {boolean} enable
|
|
*/
|
|
setKeepAlive (enable) {
|
|
this._debug('setKeepAlive %s', enable)
|
|
clearInterval(this._keepAliveInterval)
|
|
if (enable === false) return
|
|
this._keepAliveInterval = setInterval(() => {
|
|
this.keepAlive()
|
|
}, KEEP_ALIVE_TIMEOUT)
|
|
}
|
|
|
|
/**
|
|
* Set the amount of time to wait before considering a request to be "timed out"
|
|
* @param {number} ms
|
|
* @param {boolean=} unref (should the timer be unref'd? default: false)
|
|
*/
|
|
setTimeout (ms, unref) {
|
|
this._debug('setTimeout ms=%d unref=%s', ms, unref)
|
|
this._timeoutMs = ms
|
|
this._timeoutUnref = !!unref
|
|
this._resetTimeout(true)
|
|
}
|
|
|
|
destroy () {
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
this._debug('destroy')
|
|
this.emit('close')
|
|
this.end()
|
|
}
|
|
|
|
end (...args) {
|
|
this._debug('end')
|
|
this._onUninterested()
|
|
this._onChoke()
|
|
super.end(...args)
|
|
}
|
|
|
|
/**
|
|
* Use the specified protocol extension.
|
|
* @param {function} Extension
|
|
*/
|
|
use (Extension) {
|
|
const name = Extension.prototype.name
|
|
if (!name) {
|
|
throw new Error('Extension class requires a "name" property on the prototype')
|
|
}
|
|
this._debug('use extension.name=%s', name)
|
|
|
|
const ext = this._nextExt
|
|
const handler = new Extension(this)
|
|
|
|
function noop () {}
|
|
|
|
if (typeof handler.onHandshake !== 'function') {
|
|
handler.onHandshake = noop
|
|
}
|
|
if (typeof handler.onExtendedHandshake !== 'function') {
|
|
handler.onExtendedHandshake = noop
|
|
}
|
|
if (typeof handler.onMessage !== 'function') {
|
|
handler.onMessage = noop
|
|
}
|
|
|
|
this.extendedMapping[ext] = name
|
|
this._ext[name] = handler
|
|
this[name] = handler
|
|
|
|
this._nextExt += 1
|
|
}
|
|
|
|
//
|
|
// OUTGOING MESSAGES
|
|
//
|
|
|
|
/**
|
|
* Message "keep-alive": <len=0000>
|
|
*/
|
|
keepAlive () {
|
|
this._debug('keep-alive')
|
|
this._push(MESSAGE_KEEP_ALIVE)
|
|
}
|
|
|
|
sendPe1 () {
|
|
if (this._peEnabled) {
|
|
const padALen = Math.floor(Math.random() * 513)
|
|
const padA = randombytes(padALen)
|
|
this._push(Buffer.concat([Buffer.from(this._myPubKey, 'hex'), padA]))
|
|
}
|
|
}
|
|
|
|
sendPe2 () {
|
|
const padBLen = Math.floor(Math.random() * 513)
|
|
const padB = randombytes(padBLen)
|
|
this._push(Buffer.concat([Buffer.from(this._myPubKey, 'hex'), padB]))
|
|
}
|
|
|
|
sendPe3 (infoHash) {
|
|
this.setEncrypt(this._sharedSecret, infoHash)
|
|
|
|
const hash1Buffer = Buffer.from(sha1.sync(Buffer.from(this._utfToHex('req1') + this._sharedSecret, 'hex')), 'hex')
|
|
|
|
const hash2Buffer = Buffer.from(sha1.sync(Buffer.from(this._utfToHex('req2') + infoHash, 'hex')), 'hex')
|
|
const hash3Buffer = Buffer.from(sha1.sync(Buffer.from(this._utfToHex('req3') + this._sharedSecret, 'hex')), 'hex')
|
|
const hashesXorBuffer = xor(hash2Buffer, hash3Buffer)
|
|
|
|
const padCLen = randombytes(2).readUInt16BE(0) % 512
|
|
const padCBuffer = randombytes(padCLen)
|
|
|
|
let vcAndProvideBuffer = Buffer.alloc(8 + 4 + 2 + padCLen + 2)
|
|
VC.copy(vcAndProvideBuffer)
|
|
CRYPTO_PROVIDE.copy(vcAndProvideBuffer, 8)
|
|
|
|
vcAndProvideBuffer.writeInt16BE(padCLen, 12) // pad C length
|
|
padCBuffer.copy(vcAndProvideBuffer, 14)
|
|
vcAndProvideBuffer.writeInt16BE(0, 14 + padCLen) // IA length
|
|
vcAndProvideBuffer = this._encryptHandshake(vcAndProvideBuffer)
|
|
|
|
this._push(Buffer.concat([hash1Buffer, hashesXorBuffer, vcAndProvideBuffer]))
|
|
}
|
|
|
|
sendPe4 (infoHash) {
|
|
this.setEncrypt(this._sharedSecret, infoHash)
|
|
|
|
const padDLen = randombytes(2).readUInt16BE(0) % 512
|
|
const padDBuffer = randombytes(padDLen)
|
|
let vcAndSelectBuffer = Buffer.alloc(8 + 4 + 2 + padDLen)
|
|
VC.copy(vcAndSelectBuffer)
|
|
CRYPTO_SELECT.copy(vcAndSelectBuffer, 8)
|
|
vcAndSelectBuffer.writeInt16BE(padDLen, 12) // lenD?
|
|
padDBuffer.copy(vcAndSelectBuffer, 14)
|
|
vcAndSelectBuffer = this._encryptHandshake(vcAndSelectBuffer)
|
|
this._push(vcAndSelectBuffer)
|
|
this._cryptoHandshakeDone = true
|
|
this._debug('completed crypto handshake')
|
|
}
|
|
|
|
/**
|
|
* Message: "handshake" <pstrlen><pstr><reserved><info_hash><peer_id>
|
|
* @param {Buffer|string} infoHash (as Buffer or *hex* string)
|
|
* @param {Buffer|string} peerId
|
|
* @param {Object} extensions
|
|
*/
|
|
handshake (infoHash, peerId, extensions) {
|
|
let infoHashBuffer
|
|
let peerIdBuffer
|
|
if (typeof infoHash === 'string') {
|
|
infoHash = infoHash.toLowerCase()
|
|
infoHashBuffer = Buffer.from(infoHash, 'hex')
|
|
} else {
|
|
infoHashBuffer = infoHash
|
|
infoHash = infoHashBuffer.toString('hex')
|
|
}
|
|
if (typeof peerId === 'string') {
|
|
peerIdBuffer = Buffer.from(peerId, 'hex')
|
|
} else {
|
|
peerIdBuffer = peerId
|
|
peerId = peerIdBuffer.toString('hex')
|
|
}
|
|
|
|
this._infoHash = infoHashBuffer
|
|
|
|
if (infoHashBuffer.length !== 20 || peerIdBuffer.length !== 20) {
|
|
throw new Error('infoHash and peerId MUST have length 20')
|
|
}
|
|
|
|
this._debug('handshake i=%s p=%s exts=%o', infoHash, peerId, extensions)
|
|
|
|
const reserved = Buffer.from(MESSAGE_RESERVED)
|
|
|
|
// enable extended message
|
|
reserved[5] |= 0x10
|
|
|
|
if (extensions && extensions.dht) reserved[7] |= 1
|
|
|
|
this._push(Buffer.concat([MESSAGE_PROTOCOL, reserved, infoHashBuffer, peerIdBuffer]))
|
|
this._handshakeSent = true
|
|
|
|
if (this.peerExtensions.extended && !this._extendedHandshakeSent) {
|
|
// Peer's handshake indicated support already
|
|
// (incoming connection)
|
|
this._sendExtendedHandshake()
|
|
}
|
|
}
|
|
|
|
/* Peer supports BEP-0010, send extended handshake.
|
|
*
|
|
* This comes after the 'handshake' event to give the user a chance to populate
|
|
* `this.extendedHandshake` and `this.extendedMapping` before the extended handshake
|
|
* is sent to the remote peer.
|
|
*/
|
|
_sendExtendedHandshake () {
|
|
// Create extended message object from registered extensions
|
|
const msg = Object.assign({}, this.extendedHandshake)
|
|
msg.m = {}
|
|
for (const ext in this.extendedMapping) {
|
|
const name = this.extendedMapping[ext]
|
|
msg.m[name] = Number(ext)
|
|
}
|
|
|
|
// Send extended handshake
|
|
this.extended(0, bencode.encode(msg))
|
|
this._extendedHandshakeSent = true
|
|
}
|
|
|
|
/**
|
|
* Message "choke": <len=0001><id=0>
|
|
*/
|
|
choke () {
|
|
if (this.amChoking) return
|
|
this.amChoking = true
|
|
this._debug('choke')
|
|
while (this.peerRequests.length) {
|
|
this.peerRequests.pop()
|
|
}
|
|
this._push(MESSAGE_CHOKE)
|
|
}
|
|
|
|
/**
|
|
* Message "unchoke": <len=0001><id=1>
|
|
*/
|
|
unchoke () {
|
|
if (!this.amChoking) return
|
|
this.amChoking = false
|
|
this._debug('unchoke')
|
|
this._push(MESSAGE_UNCHOKE)
|
|
}
|
|
|
|
/**
|
|
* Message "interested": <len=0001><id=2>
|
|
*/
|
|
interested () {
|
|
if (this.amInterested) return
|
|
this.amInterested = true
|
|
this._debug('interested')
|
|
this._push(MESSAGE_INTERESTED)
|
|
}
|
|
|
|
/**
|
|
* Message "uninterested": <len=0001><id=3>
|
|
*/
|
|
uninterested () {
|
|
if (!this.amInterested) return
|
|
this.amInterested = false
|
|
this._debug('uninterested')
|
|
this._push(MESSAGE_UNINTERESTED)
|
|
}
|
|
|
|
/**
|
|
* Message "have": <len=0005><id=4><piece index>
|
|
* @param {number} index
|
|
*/
|
|
have (index) {
|
|
this._debug('have %d', index)
|
|
this._message(4, [index], null)
|
|
}
|
|
|
|
/**
|
|
* Message "bitfield": <len=0001+X><id=5><bitfield>
|
|
* @param {BitField|Buffer} bitfield
|
|
*/
|
|
bitfield (bitfield) {
|
|
this._debug('bitfield')
|
|
if (!Buffer.isBuffer(bitfield)) bitfield = bitfield.buffer
|
|
this._message(5, [], bitfield)
|
|
}
|
|
|
|
/**
|
|
* Message "request": <len=0013><id=6><index><begin><length>
|
|
* @param {number} index
|
|
* @param {number} offset
|
|
* @param {number} length
|
|
* @param {function} cb
|
|
*/
|
|
request (index, offset, length, cb) {
|
|
if (!cb) cb = () => {}
|
|
if (this._finished) return cb(new Error('wire is closed'))
|
|
if (this.peerChoking) return cb(new Error('peer is choking'))
|
|
|
|
this._debug('request index=%d offset=%d length=%d', index, offset, length)
|
|
|
|
this.requests.push(new Request(index, offset, length, cb))
|
|
if (!this._timeout) {
|
|
this._resetTimeout(true)
|
|
}
|
|
this._message(6, [index, offset, length], null)
|
|
}
|
|
|
|
/**
|
|
* Message "piece": <len=0009+X><id=7><index><begin><block>
|
|
* @param {number} index
|
|
* @param {number} offset
|
|
* @param {Buffer} buffer
|
|
*/
|
|
piece (index, offset, buffer) {
|
|
this._debug('piece index=%d offset=%d', index, offset)
|
|
this._message(7, [index, offset], buffer)
|
|
this.uploaded += buffer.length
|
|
this.uploadSpeed(buffer.length)
|
|
this.emit('upload', buffer.length)
|
|
}
|
|
|
|
/**
|
|
* Message "cancel": <len=0013><id=8><index><begin><length>
|
|
* @param {number} index
|
|
* @param {number} offset
|
|
* @param {number} length
|
|
*/
|
|
cancel (index, offset, length) {
|
|
this._debug('cancel index=%d offset=%d length=%d', index, offset, length)
|
|
this._callback(
|
|
this._pull(this.requests, index, offset, length),
|
|
new Error('request was cancelled'),
|
|
null
|
|
)
|
|
this._message(8, [index, offset, length], null)
|
|
}
|
|
|
|
/**
|
|
* Message: "port" <len=0003><id=9><listen-port>
|
|
* @param {Number} port
|
|
*/
|
|
port (port) {
|
|
this._debug('port %d', port)
|
|
const message = Buffer.from(MESSAGE_PORT)
|
|
message.writeUInt16BE(port, 5)
|
|
this._push(message)
|
|
}
|
|
|
|
/**
|
|
* Message: "extended" <len=0005+X><id=20><ext-number><payload>
|
|
* @param {number|string} ext
|
|
* @param {Object} obj
|
|
*/
|
|
extended (ext, obj) {
|
|
this._debug('extended ext=%s', ext)
|
|
if (typeof ext === 'string' && this.peerExtendedMapping[ext]) {
|
|
ext = this.peerExtendedMapping[ext]
|
|
}
|
|
if (typeof ext === 'number') {
|
|
const extId = Buffer.from([ext])
|
|
const buf = Buffer.isBuffer(obj) ? obj : bencode.encode(obj)
|
|
|
|
this._message(20, [], Buffer.concat([extId, buf]))
|
|
} else {
|
|
throw new Error(`Unrecognized extension: ${ext}`)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the encryption method for this wire, as per PSE/ME specification
|
|
*
|
|
* @param {string} sharedSecret: A hex-encoded string, which is the shared secret agreed
|
|
* upon from DH key exchange
|
|
* @param {string} infoHash: A hex-encoded info hash
|
|
* @returns boolean, true if encryption setting succeeds, false if it fails.
|
|
*/
|
|
setEncrypt (sharedSecret, infoHash) {
|
|
let encryptKey
|
|
let decryptKey
|
|
let encryptKeyBuf
|
|
let encryptKeyIntArray
|
|
let decryptKeyBuf
|
|
let decryptKeyIntArray
|
|
switch (this.type) {
|
|
case 'tcpIncoming':
|
|
encryptKey = sha1.sync(Buffer.from(this._utfToHex('keyB') + sharedSecret + infoHash, 'hex'))
|
|
decryptKey = sha1.sync(Buffer.from(this._utfToHex('keyA') + sharedSecret + infoHash, 'hex'))
|
|
encryptKeyBuf = Buffer.from(encryptKey, 'hex')
|
|
encryptKeyIntArray = []
|
|
for (const value of encryptKeyBuf.values()) {
|
|
encryptKeyIntArray.push(value)
|
|
}
|
|
decryptKeyBuf = Buffer.from(decryptKey, 'hex')
|
|
decryptKeyIntArray = []
|
|
for (const value of decryptKeyBuf.values()) {
|
|
decryptKeyIntArray.push(value)
|
|
}
|
|
this._encryptGenerator = new RC4(encryptKeyIntArray)
|
|
this._decryptGenerator = new RC4(decryptKeyIntArray)
|
|
break
|
|
case 'tcpOutgoing':
|
|
encryptKey = sha1.sync(Buffer.from(this._utfToHex('keyA') + sharedSecret + infoHash, 'hex'))
|
|
decryptKey = sha1.sync(Buffer.from(this._utfToHex('keyB') + sharedSecret + infoHash, 'hex'))
|
|
encryptKeyBuf = Buffer.from(encryptKey, 'hex')
|
|
encryptKeyIntArray = []
|
|
for (const value of encryptKeyBuf.values()) {
|
|
encryptKeyIntArray.push(value)
|
|
}
|
|
decryptKeyBuf = Buffer.from(decryptKey, 'hex')
|
|
decryptKeyIntArray = []
|
|
for (const value of decryptKeyBuf.values()) {
|
|
decryptKeyIntArray.push(value)
|
|
}
|
|
this._encryptGenerator = new RC4(encryptKeyIntArray)
|
|
this._decryptGenerator = new RC4(decryptKeyIntArray)
|
|
break
|
|
default:
|
|
return false
|
|
}
|
|
|
|
// Discard the first 1024 bytes, as per MSE/PE implementation
|
|
for (let i = 0; i < 1024; i++) {
|
|
this._encryptGenerator.randomByte()
|
|
this._decryptGenerator.randomByte()
|
|
}
|
|
|
|
this._setGenerators = true
|
|
return true
|
|
}
|
|
|
|
/**
|
|
* Duplex stream method. Called whenever the remote peer stream wants data. No-op
|
|
* since we'll just push data whenever we get it.
|
|
*/
|
|
_read () {}
|
|
|
|
/**
|
|
* Send a message to the remote peer.
|
|
*/
|
|
_message (id, numbers, data) {
|
|
const dataLength = data ? data.length : 0
|
|
const buffer = Buffer.allocUnsafe(5 + (4 * numbers.length))
|
|
|
|
buffer.writeUInt32BE(buffer.length + dataLength - 4, 0)
|
|
buffer[4] = id
|
|
for (let i = 0; i < numbers.length; i++) {
|
|
buffer.writeUInt32BE(numbers[i], 5 + (4 * i))
|
|
}
|
|
|
|
this._push(buffer)
|
|
if (data) this._push(data)
|
|
}
|
|
|
|
_push (data) {
|
|
if (this._finished) return
|
|
if (this._encryptionMethod === 2 && this._cryptoHandshakeDone) {
|
|
data = this._encrypt(data)
|
|
}
|
|
return this.push(data)
|
|
}
|
|
|
|
//
|
|
// INCOMING MESSAGES
|
|
//
|
|
|
|
_onKeepAlive () {
|
|
this._debug('got keep-alive')
|
|
this.emit('keep-alive')
|
|
}
|
|
|
|
_onPe1 (pubKeyBuffer) {
|
|
this._peerPubKey = pubKeyBuffer.toString('hex')
|
|
this._sharedSecret = this._dh.computeSecret(this._peerPubKey, 'hex', 'hex')
|
|
this.emit('pe1')
|
|
}
|
|
|
|
_onPe2 (pubKeyBuffer) {
|
|
this._peerPubKey = pubKeyBuffer.toString('hex')
|
|
this._sharedSecret = this._dh.computeSecret(this._peerPubKey, 'hex', 'hex')
|
|
this.emit('pe2')
|
|
}
|
|
|
|
_onPe3 (hashesXorBuffer) {
|
|
const hash3 = sha1.sync(Buffer.from(this._utfToHex('req3') + this._sharedSecret, 'hex'))
|
|
const sKeyHash = xor(Buffer.from(hash3, 'hex'), hashesXorBuffer).toString('hex')
|
|
this.emit('pe3', sKeyHash)
|
|
}
|
|
|
|
_onPe3Encrypted (vcBuffer, peerProvideBuffer) {
|
|
if (!vcBuffer.equals(VC)) {
|
|
this._debug('Error: verification constant did not match')
|
|
this.destroy()
|
|
return
|
|
}
|
|
|
|
for (const provideByte of peerProvideBuffer.values()) {
|
|
if (provideByte !== 0) {
|
|
this._peerCryptoProvide.push(provideByte)
|
|
}
|
|
}
|
|
if (this._peerCryptoProvide.includes(2)) {
|
|
this._encryptionMethod = 2
|
|
} else {
|
|
this._debug('Error: RC4 encryption method not provided by peer')
|
|
this.destroy()
|
|
}
|
|
}
|
|
|
|
_onPe4 (peerSelectBuffer) {
|
|
this._encryptionMethod = peerSelectBuffer.readUInt8(3)
|
|
if (!CRYPTO_PROVIDE.includes(this._encryptionMethod)) {
|
|
this._debug('Error: peer selected invalid crypto method')
|
|
this.destroy()
|
|
}
|
|
this._cryptoHandshakeDone = true
|
|
this._debug('crypto handshake done')
|
|
this.emit('pe4')
|
|
}
|
|
|
|
_onHandshake (infoHashBuffer, peerIdBuffer, extensions) {
|
|
const infoHash = infoHashBuffer.toString('hex')
|
|
const peerId = peerIdBuffer.toString('hex')
|
|
|
|
this._debug('got handshake i=%s p=%s exts=%o', infoHash, peerId, extensions)
|
|
|
|
this.peerId = peerId
|
|
this.peerIdBuffer = peerIdBuffer
|
|
this.peerExtensions = extensions
|
|
|
|
this.emit('handshake', infoHash, peerId, extensions)
|
|
|
|
for (const name in this._ext) {
|
|
this._ext[name].onHandshake(infoHash, peerId, extensions)
|
|
}
|
|
|
|
if (extensions.extended && this._handshakeSent &&
|
|
!this._extendedHandshakeSent) {
|
|
// outgoing connection
|
|
this._sendExtendedHandshake()
|
|
}
|
|
}
|
|
|
|
_onChoke () {
|
|
this.peerChoking = true
|
|
this._debug('got choke')
|
|
this.emit('choke')
|
|
while (this.requests.length) {
|
|
this._callback(this.requests.pop(), new Error('peer is choking'), null)
|
|
}
|
|
}
|
|
|
|
_onUnchoke () {
|
|
this.peerChoking = false
|
|
this._debug('got unchoke')
|
|
this.emit('unchoke')
|
|
}
|
|
|
|
_onInterested () {
|
|
this.peerInterested = true
|
|
this._debug('got interested')
|
|
this.emit('interested')
|
|
}
|
|
|
|
_onUninterested () {
|
|
this.peerInterested = false
|
|
this._debug('got uninterested')
|
|
this.emit('uninterested')
|
|
}
|
|
|
|
_onHave (index) {
|
|
if (this.peerPieces.get(index)) return
|
|
this._debug('got have %d', index)
|
|
|
|
this.peerPieces.set(index, true)
|
|
this.emit('have', index)
|
|
}
|
|
|
|
_onBitField (buffer) {
|
|
this.peerPieces = new BitField(buffer)
|
|
this._debug('got bitfield')
|
|
this.emit('bitfield', this.peerPieces)
|
|
}
|
|
|
|
_onRequest (index, offset, length) {
|
|
if (this.amChoking) return
|
|
this._debug('got request index=%d offset=%d length=%d', index, offset, length)
|
|
|
|
const respond = (err, buffer) => {
|
|
if (request !== this._pull(this.peerRequests, index, offset, length)) return
|
|
if (err) return this._debug('error satisfying request index=%d offset=%d length=%d (%s)', index, offset, length, err.message)
|
|
this.piece(index, offset, buffer)
|
|
}
|
|
|
|
const request = new Request(index, offset, length, respond)
|
|
this.peerRequests.push(request)
|
|
this.emit('request', index, offset, length, respond)
|
|
}
|
|
|
|
_onPiece (index, offset, buffer) {
|
|
this._debug('got piece index=%d offset=%d', index, offset)
|
|
this._callback(this._pull(this.requests, index, offset, buffer.length), null, buffer)
|
|
this.downloaded += buffer.length
|
|
this.downloadSpeed(buffer.length)
|
|
this.emit('download', buffer.length)
|
|
this.emit('piece', index, offset, buffer)
|
|
}
|
|
|
|
_onCancel (index, offset, length) {
|
|
this._debug('got cancel index=%d offset=%d length=%d', index, offset, length)
|
|
this._pull(this.peerRequests, index, offset, length)
|
|
this.emit('cancel', index, offset, length)
|
|
}
|
|
|
|
_onPort (port) {
|
|
this._debug('got port %d', port)
|
|
this.emit('port', port)
|
|
}
|
|
|
|
_onExtended (ext, buf) {
|
|
if (ext === 0) {
|
|
let info
|
|
try {
|
|
info = bencode.decode(buf)
|
|
} catch (err) {
|
|
this._debug('ignoring invalid extended handshake: %s', err.message || err)
|
|
}
|
|
|
|
if (!info) return
|
|
this.peerExtendedHandshake = info
|
|
|
|
if (typeof info.m === 'object') {
|
|
for (const name in info.m) {
|
|
this.peerExtendedMapping[name] = Number(info.m[name].toString())
|
|
}
|
|
}
|
|
for (const name in this._ext) {
|
|
if (this.peerExtendedMapping[name]) {
|
|
this._ext[name].onExtendedHandshake(this.peerExtendedHandshake)
|
|
}
|
|
}
|
|
this._debug('got extended handshake')
|
|
this.emit('extended', 'handshake', this.peerExtendedHandshake)
|
|
} else {
|
|
if (this.extendedMapping[ext]) {
|
|
ext = this.extendedMapping[ext] // friendly name for extension
|
|
if (this._ext[ext]) {
|
|
// there is an registered extension handler, so call it
|
|
this._ext[ext].onMessage(buf)
|
|
}
|
|
}
|
|
this._debug('got extended message ext=%s', ext)
|
|
this.emit('extended', ext, buf)
|
|
}
|
|
}
|
|
|
|
_onTimeout () {
|
|
this._debug('request timed out')
|
|
this._callback(this.requests.shift(), new Error('request has timed out'), null)
|
|
this.emit('timeout')
|
|
}
|
|
|
|
/**
|
|
* Duplex stream method. Called whenever the remote peer has data for us. Data that the
|
|
* remote peer sends gets buffered (i.e. not actually processed) until the right number
|
|
* of bytes have arrived, determined by the last call to `this._parse(number, callback)`.
|
|
* Once enough bytes have arrived to process the message, the callback function
|
|
* (i.e. `this._parser`) gets called with the full buffer of data.
|
|
* @param {Buffer} data
|
|
* @param {string} encoding
|
|
* @param {function} cb
|
|
*/
|
|
_write (data, encoding, cb) {
|
|
if (this._encryptionMethod === 2 && this._cryptoHandshakeDone) {
|
|
data = this._decrypt(data)
|
|
}
|
|
this._bufferSize += data.length
|
|
this._buffer.push(data)
|
|
if (this._buffer.length > 1) {
|
|
this._buffer = [Buffer.concat(this._buffer, this._bufferSize)]
|
|
}
|
|
// now this._buffer is an array containing a single Buffer
|
|
if (this._cryptoSyncPattern) {
|
|
const index = this._buffer[0].indexOf(this._cryptoSyncPattern)
|
|
if (index !== -1) {
|
|
this._buffer[0] = this._buffer[0].slice(index + this._cryptoSyncPattern.length)
|
|
this._bufferSize -= (index + this._cryptoSyncPattern.length)
|
|
this._cryptoSyncPattern = null
|
|
} else if (this._bufferSize + data.length > this._waitMaxBytes + this._cryptoSyncPattern.length) {
|
|
this._debug('Error: could not resynchronize')
|
|
this.destroy()
|
|
return
|
|
}
|
|
}
|
|
|
|
while (this._bufferSize >= this._parserSize && !this._cryptoSyncPattern) {
|
|
if (this._parserSize === 0) {
|
|
this._parser(Buffer.from([]))
|
|
} else {
|
|
const buffer = this._buffer[0]
|
|
// console.log('buffer:', this._buffer)
|
|
this._bufferSize -= this._parserSize
|
|
this._buffer = this._bufferSize
|
|
? [buffer.slice(this._parserSize)]
|
|
: []
|
|
this._parser(buffer.slice(0, this._parserSize))
|
|
}
|
|
}
|
|
|
|
cb(null) // Signal that we're ready for more data
|
|
}
|
|
|
|
_callback (request, err, buffer) {
|
|
if (!request) return
|
|
|
|
this._resetTimeout(!this.peerChoking && !this._finished)
|
|
|
|
request.callback(err, buffer)
|
|
}
|
|
|
|
_resetTimeout (setAgain) {
|
|
if (!setAgain || !this._timeoutMs || !this.requests.length) {
|
|
clearTimeout(this._timeout)
|
|
this._timeout = null
|
|
this._timeoutExpiresAt = null
|
|
return
|
|
}
|
|
|
|
const timeoutExpiresAt = Date.now() + this._timeoutMs
|
|
|
|
if (this._timeout) {
|
|
// If existing expiration is already within 5% of correct, it's close enough
|
|
if (timeoutExpiresAt - this._timeoutExpiresAt < this._timeoutMs * 0.05) {
|
|
return
|
|
}
|
|
clearTimeout(this._timeout)
|
|
}
|
|
|
|
this._timeoutExpiresAt = timeoutExpiresAt
|
|
this._timeout = setTimeout(() => this._onTimeout(), this._timeoutMs)
|
|
if (this._timeoutUnref && this._timeout.unref) this._timeout.unref()
|
|
}
|
|
|
|
/**
|
|
* Takes a number of bytes that the local peer is waiting to receive from the remote peer
|
|
* in order to parse a complete message, and a callback function to be called once enough
|
|
* bytes have arrived.
|
|
* @param {number} size
|
|
* @param {function} parser
|
|
*/
|
|
_parse (size, parser) {
|
|
this._parserSize = size
|
|
this._parser = parser
|
|
}
|
|
|
|
_parseUntil (pattern, maxBytes) {
|
|
this._cryptoSyncPattern = pattern
|
|
this._waitMaxBytes = maxBytes
|
|
}
|
|
|
|
/**
|
|
* Handle the first 4 bytes of a message, to determine the length of bytes that must be
|
|
* waited for in order to have the whole message.
|
|
* @param {Buffer} buffer
|
|
*/
|
|
_onMessageLength (buffer) {
|
|
const length = buffer.readUInt32BE(0)
|
|
if (length > 0) {
|
|
this._parse(length, this._onMessage)
|
|
} else {
|
|
this._onKeepAlive()
|
|
this._parse(4, this._onMessageLength)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle a message from the remote peer.
|
|
* @param {Buffer} buffer
|
|
*/
|
|
_onMessage (buffer) {
|
|
this._parse(4, this._onMessageLength)
|
|
switch (buffer[0]) {
|
|
case 0:
|
|
return this._onChoke()
|
|
case 1:
|
|
return this._onUnchoke()
|
|
case 2:
|
|
return this._onInterested()
|
|
case 3:
|
|
return this._onUninterested()
|
|
case 4:
|
|
return this._onHave(buffer.readUInt32BE(1))
|
|
case 5:
|
|
return this._onBitField(buffer.slice(1))
|
|
case 6:
|
|
return this._onRequest(
|
|
buffer.readUInt32BE(1),
|
|
buffer.readUInt32BE(5),
|
|
buffer.readUInt32BE(9)
|
|
)
|
|
case 7:
|
|
return this._onPiece(
|
|
buffer.readUInt32BE(1),
|
|
buffer.readUInt32BE(5),
|
|
buffer.slice(9)
|
|
)
|
|
case 8:
|
|
return this._onCancel(
|
|
buffer.readUInt32BE(1),
|
|
buffer.readUInt32BE(5),
|
|
buffer.readUInt32BE(9)
|
|
)
|
|
case 9:
|
|
return this._onPort(buffer.readUInt16BE(1))
|
|
case 20:
|
|
return this._onExtended(buffer.readUInt8(1), buffer.slice(2))
|
|
default:
|
|
this._debug('got unknown message')
|
|
return this.emit('unknownmessage', buffer)
|
|
}
|
|
}
|
|
|
|
_determineHandshakeType () {
|
|
this._parse(1, pstrLenBuffer => {
|
|
const pstrlen = pstrLenBuffer.readUInt8(0)
|
|
if (pstrlen === 19) {
|
|
this._parse(pstrlen + 48, this._onHandshakeBuffer)
|
|
} else {
|
|
this._parsePe1(pstrLenBuffer)
|
|
}
|
|
})
|
|
}
|
|
|
|
_parsePe1 (pubKeyPrefix) {
|
|
this._parse(95, pubKeySuffix => {
|
|
this._onPe1(Buffer.concat([pubKeyPrefix, pubKeySuffix]))
|
|
this._parsePe3()
|
|
})
|
|
}
|
|
|
|
_parsePe2 () {
|
|
this._parse(96, pubKey => {
|
|
this._onPe2(pubKey)
|
|
while (!this._setGenerators) {
|
|
// Wait until generators have been set
|
|
}
|
|
this._parsePe4()
|
|
})
|
|
}
|
|
|
|
// Handles the unencrypted portion of step 4
|
|
_parsePe3 () {
|
|
const hash1Buffer = Buffer.from(sha1.sync(Buffer.from(this._utfToHex('req1') + this._sharedSecret, 'hex')), 'hex')
|
|
// synchronize on HASH('req1', S)
|
|
this._parseUntil(hash1Buffer, 512)
|
|
this._parse(20, buffer => {
|
|
this._onPe3(buffer)
|
|
while (!this._setGenerators) {
|
|
// Wait until generators have been set
|
|
}
|
|
this._parsePe3Encrypted()
|
|
})
|
|
}
|
|
|
|
_parsePe3Encrypted () {
|
|
this._parse(14, buffer => {
|
|
const vcBuffer = this._decryptHandshake(buffer.slice(0, 8))
|
|
const peerProvideBuffer = this._decryptHandshake(buffer.slice(8, 12))
|
|
const padCLen = this._decryptHandshake(buffer.slice(12, 14)).readUInt16BE(0)
|
|
this._parse(padCLen, padCBuffer => {
|
|
padCBuffer = this._decryptHandshake(padCBuffer)
|
|
this._parse(2, iaLenBuf => {
|
|
const iaLen = this._decryptHandshake(iaLenBuf).readUInt16BE(0)
|
|
this._parse(iaLen, iaBuffer => {
|
|
iaBuffer = this._decryptHandshake(iaBuffer)
|
|
this._onPe3Encrypted(vcBuffer, peerProvideBuffer, padCBuffer, iaBuffer)
|
|
const pstrlen = iaLen ? iaBuffer.readUInt8(0) : null
|
|
const protocol = iaLen ? iaBuffer.slice(1, 20) : null
|
|
if (pstrlen === 19 && protocol.toString() === 'BitTorrent protocol') {
|
|
this._onHandshakeBuffer(iaBuffer.slice(1))
|
|
} else {
|
|
this._parseHandshake()
|
|
}
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
_parsePe4 () {
|
|
// synchronize on ENCRYPT(VC).
|
|
// since we encrypt using bitwise xor, decryption and encryption are the same operation.
|
|
// calling _decryptHandshake here advances the decrypt generator keystream forward 8 bytes
|
|
const vcBufferEncrypted = this._decryptHandshake(VC)
|
|
this._parseUntil(vcBufferEncrypted, 512)
|
|
this._parse(6, buffer => {
|
|
const peerSelectBuffer = this._decryptHandshake(buffer.slice(0, 4))
|
|
const padDLen = this._decryptHandshake(buffer.slice(4, 6)).readUInt16BE(0)
|
|
this._parse(padDLen, padDBuf => {
|
|
this._decryptHandshake(padDBuf)
|
|
this._onPe4(peerSelectBuffer)
|
|
this._parseHandshake(null)
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Reads the handshake as specified by the bittorrent wire protocol.
|
|
*/
|
|
_parseHandshake () {
|
|
this._parse(1, buffer => {
|
|
const pstrlen = buffer.readUInt8(0)
|
|
if (pstrlen !== 19) {
|
|
this._debug('Error: wire not speaking BitTorrent protocol (%s)', pstrlen.toString())
|
|
this.end()
|
|
return
|
|
}
|
|
this._parse(pstrlen + 48, this._onHandshakeBuffer)
|
|
})
|
|
}
|
|
|
|
_onHandshakeBuffer (handshake) {
|
|
const protocol = handshake.slice(0, 19)
|
|
if (protocol.toString() !== 'BitTorrent protocol') {
|
|
this._debug('Error: wire not speaking BitTorrent protocol (%s)', protocol.toString())
|
|
this.end()
|
|
return
|
|
}
|
|
handshake = handshake.slice(19)
|
|
this._onHandshake(handshake.slice(8, 28), handshake.slice(28, 48), {
|
|
dht: !!(handshake[7] & 0x01), // see bep_0005
|
|
extended: !!(handshake[5] & 0x10) // see bep_0010
|
|
})
|
|
this._parse(4, this._onMessageLength)
|
|
}
|
|
|
|
_onFinish () {
|
|
this._finished = true
|
|
|
|
this.push(null) // stream cannot be half open, so signal the end of it
|
|
while (this.read()) {
|
|
// body intentionally empty
|
|
// consume and discard the rest of the stream data
|
|
}
|
|
|
|
clearInterval(this._keepAliveInterval)
|
|
this._parse(Number.MAX_VALUE, () => {})
|
|
while (this.peerRequests.length) {
|
|
this.peerRequests.pop()
|
|
}
|
|
while (this.requests.length) {
|
|
this._callback(this.requests.pop(), new Error('wire was closed'), null)
|
|
}
|
|
}
|
|
|
|
_debug (...args) {
|
|
args[0] = `[${this._debugId}] ${args[0]}`
|
|
debug(...args)
|
|
}
|
|
|
|
_pull (requests, piece, offset, length) {
|
|
for (let i = 0; i < requests.length; i++) {
|
|
const req = requests[i]
|
|
if (req.piece === piece && req.offset === offset && req.length === length) {
|
|
arrayRemove(requests, i)
|
|
return req
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
_encryptHandshake (buf) {
|
|
const crypt = Buffer.from(buf)
|
|
if (!this._encryptGenerator) {
|
|
this._debug('Warning: Encrypting without any generator')
|
|
return crypt
|
|
}
|
|
|
|
for (let i = 0; i < buf.length; i++) {
|
|
const keystream = this._encryptGenerator.randomByte()
|
|
crypt[i] = crypt[i] ^ keystream
|
|
}
|
|
|
|
return crypt
|
|
}
|
|
|
|
_encrypt (buf) {
|
|
const crypt = Buffer.from(buf)
|
|
|
|
if (!this._encryptGenerator || this._encryptionMethod !== 2) {
|
|
return crypt
|
|
}
|
|
for (let i = 0; i < buf.length; i++) {
|
|
const keystream = this._encryptGenerator.randomByte()
|
|
crypt[i] = crypt[i] ^ keystream
|
|
}
|
|
|
|
return crypt
|
|
}
|
|
|
|
_decryptHandshake (buf) {
|
|
const decrypt = Buffer.from(buf)
|
|
|
|
if (!this._decryptGenerator) {
|
|
this._debug('Warning: Decrypting without any generator')
|
|
return decrypt
|
|
}
|
|
for (let i = 0; i < buf.length; i++) {
|
|
const keystream = this._decryptGenerator.randomByte()
|
|
decrypt[i] = decrypt[i] ^ keystream
|
|
}
|
|
|
|
return decrypt
|
|
}
|
|
|
|
_decrypt (buf) {
|
|
const decrypt = Buffer.from(buf)
|
|
|
|
if (!this._decryptGenerator || this._encryptionMethod !== 2) {
|
|
return decrypt
|
|
}
|
|
for (let i = 0; i < buf.length; i++) {
|
|
const keystream = this._decryptGenerator.randomByte()
|
|
decrypt[i] = decrypt[i] ^ keystream
|
|
}
|
|
|
|
return decrypt
|
|
}
|
|
|
|
_utfToHex (str) {
|
|
return Buffer.from(str, 'utf8').toString('hex')
|
|
}
|
|
}
|
|
|
|
module.exports = Wire
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/bittorrent-tracker/client.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/bittorrent-tracker/client.js ***!
|
|
\***************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('bittorrent-tracker:client')
|
|
const EventEmitter = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
const once = __webpack_require__(/*! once */ "./node_modules/once/once.js")
|
|
const parallel = __webpack_require__(/*! run-parallel */ "./node_modules/run-parallel/index.js")
|
|
const Peer = __webpack_require__(/*! simple-peer */ "./node_modules/simple-peer/index.js")
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
|
|
const common = __webpack_require__(/*! ./lib/common */ "./node_modules/bittorrent-tracker/lib/common.js")
|
|
const HTTPTracker = __webpack_require__(/*! ./lib/client/http-tracker */ "?ed7a") // empty object in browser
|
|
const UDPTracker = __webpack_require__(/*! ./lib/client/udp-tracker */ "?5c78") // empty object in browser
|
|
const WebSocketTracker = __webpack_require__(/*! ./lib/client/websocket-tracker */ "./node_modules/bittorrent-tracker/lib/client/websocket-tracker.js")
|
|
|
|
/**
|
|
* BitTorrent tracker client.
|
|
*
|
|
* Find torrent peers, to help a torrent client participate in a torrent swarm.
|
|
*
|
|
* @param {Object} opts options object
|
|
* @param {string|Buffer} opts.infoHash torrent info hash
|
|
* @param {string|Buffer} opts.peerId peer id
|
|
* @param {string|Array.<string>} opts.announce announce
|
|
* @param {number} opts.port torrent client listening port
|
|
* @param {function} opts.getAnnounceOpts callback to provide data to tracker
|
|
* @param {number} opts.rtcConfig RTCPeerConnection configuration object
|
|
* @param {number} opts.userAgent User-Agent header for http requests
|
|
* @param {number} opts.wrtc custom webrtc impl (useful in node.js)
|
|
*/
|
|
class Client extends EventEmitter {
|
|
constructor (opts = {}) {
|
|
super()
|
|
|
|
if (!opts.peerId) throw new Error('Option `peerId` is required')
|
|
if (!opts.infoHash) throw new Error('Option `infoHash` is required')
|
|
if (!opts.announce) throw new Error('Option `announce` is required')
|
|
if (!process.browser && !opts.port) throw new Error('Option `port` is required')
|
|
|
|
this.peerId = typeof opts.peerId === 'string'
|
|
? opts.peerId
|
|
: opts.peerId.toString('hex')
|
|
this._peerIdBuffer = Buffer.from(this.peerId, 'hex')
|
|
this._peerIdBinary = this._peerIdBuffer.toString('binary')
|
|
|
|
this.infoHash = typeof opts.infoHash === 'string'
|
|
? opts.infoHash.toLowerCase()
|
|
: opts.infoHash.toString('hex')
|
|
this._infoHashBuffer = Buffer.from(this.infoHash, 'hex')
|
|
this._infoHashBinary = this._infoHashBuffer.toString('binary')
|
|
|
|
debug('new client %s', this.infoHash)
|
|
|
|
this.destroyed = false
|
|
|
|
this._port = opts.port
|
|
this._getAnnounceOpts = opts.getAnnounceOpts
|
|
this._rtcConfig = opts.rtcConfig
|
|
this._userAgent = opts.userAgent
|
|
|
|
// Support lazy 'wrtc' module initialization
|
|
// See: https://github.com/webtorrent/webtorrent-hybrid/issues/46
|
|
this._wrtc = typeof opts.wrtc === 'function' ? opts.wrtc() : opts.wrtc
|
|
|
|
let announce = typeof opts.announce === 'string'
|
|
? [opts.announce]
|
|
: opts.announce == null ? [] : opts.announce
|
|
|
|
// Remove trailing slash from trackers to catch duplicates
|
|
announce = announce.map(announceUrl => {
|
|
announceUrl = announceUrl.toString()
|
|
if (announceUrl[announceUrl.length - 1] === '/') {
|
|
announceUrl = announceUrl.substring(0, announceUrl.length - 1)
|
|
}
|
|
return announceUrl
|
|
})
|
|
// remove duplicates by converting to Set and back
|
|
announce = Array.from(new Set(announce))
|
|
|
|
const webrtcSupport = this._wrtc !== false && (!!this._wrtc || Peer.WEBRTC_SUPPORT)
|
|
|
|
const nextTickWarn = err => {
|
|
queueMicrotask(() => {
|
|
this.emit('warning', err)
|
|
})
|
|
}
|
|
|
|
this._trackers = announce
|
|
.map(announceUrl => {
|
|
let parsedUrl
|
|
try {
|
|
parsedUrl = common.parseUrl(announceUrl)
|
|
} catch (err) {
|
|
nextTickWarn(new Error(`Invalid tracker URL: ${announceUrl}`))
|
|
return null
|
|
}
|
|
|
|
const port = parsedUrl.port
|
|
if (port < 0 || port > 65535) {
|
|
nextTickWarn(new Error(`Invalid tracker port: ${announceUrl}`))
|
|
return null
|
|
}
|
|
|
|
const protocol = parsedUrl.protocol
|
|
if ((protocol === 'http:' || protocol === 'https:') &&
|
|
typeof HTTPTracker === 'function') {
|
|
return new HTTPTracker(this, announceUrl)
|
|
} else if (protocol === 'udp:' && typeof UDPTracker === 'function') {
|
|
return new UDPTracker(this, announceUrl)
|
|
} else if ((protocol === 'ws:' || protocol === 'wss:') && webrtcSupport) {
|
|
// Skip ws:// trackers on https:// sites because they throw SecurityError
|
|
if (protocol === 'ws:' && typeof window !== 'undefined' &&
|
|
window.location.protocol === 'https:') {
|
|
nextTickWarn(new Error(`Unsupported tracker protocol: ${announceUrl}`))
|
|
return null
|
|
}
|
|
return new WebSocketTracker(this, announceUrl)
|
|
} else {
|
|
nextTickWarn(new Error(`Unsupported tracker protocol: ${announceUrl}`))
|
|
return null
|
|
}
|
|
})
|
|
.filter(Boolean)
|
|
}
|
|
|
|
/**
|
|
* Send a `start` announce to the trackers.
|
|
* @param {Object} opts
|
|
* @param {number=} opts.uploaded
|
|
* @param {number=} opts.downloaded
|
|
* @param {number=} opts.left (if not set, calculated automatically)
|
|
*/
|
|
start (opts) {
|
|
opts = this._defaultAnnounceOpts(opts)
|
|
opts.event = 'started'
|
|
debug('send `start` %o', opts)
|
|
this._announce(opts)
|
|
|
|
// start announcing on intervals
|
|
this._trackers.forEach(tracker => {
|
|
tracker.setInterval()
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Send a `stop` announce to the trackers.
|
|
* @param {Object} opts
|
|
* @param {number=} opts.uploaded
|
|
* @param {number=} opts.downloaded
|
|
* @param {number=} opts.numwant
|
|
* @param {number=} opts.left (if not set, calculated automatically)
|
|
*/
|
|
stop (opts) {
|
|
opts = this._defaultAnnounceOpts(opts)
|
|
opts.event = 'stopped'
|
|
debug('send `stop` %o', opts)
|
|
this._announce(opts)
|
|
}
|
|
|
|
/**
|
|
* Send a `complete` announce to the trackers.
|
|
* @param {Object} opts
|
|
* @param {number=} opts.uploaded
|
|
* @param {number=} opts.downloaded
|
|
* @param {number=} opts.numwant
|
|
* @param {number=} opts.left (if not set, calculated automatically)
|
|
*/
|
|
complete (opts) {
|
|
if (!opts) opts = {}
|
|
opts = this._defaultAnnounceOpts(opts)
|
|
opts.event = 'completed'
|
|
debug('send `complete` %o', opts)
|
|
this._announce(opts)
|
|
}
|
|
|
|
/**
|
|
* Send a `update` announce to the trackers.
|
|
* @param {Object} opts
|
|
* @param {number=} opts.uploaded
|
|
* @param {number=} opts.downloaded
|
|
* @param {number=} opts.numwant
|
|
* @param {number=} opts.left (if not set, calculated automatically)
|
|
*/
|
|
update (opts) {
|
|
opts = this._defaultAnnounceOpts(opts)
|
|
if (opts.event) delete opts.event
|
|
debug('send `update` %o', opts)
|
|
this._announce(opts)
|
|
}
|
|
|
|
_announce (opts) {
|
|
this._trackers.forEach(tracker => {
|
|
// tracker should not modify `opts` object, it's passed to all trackers
|
|
tracker.announce(opts)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Send a scrape request to the trackers.
|
|
* @param {Object} opts
|
|
*/
|
|
scrape (opts) {
|
|
debug('send `scrape`')
|
|
if (!opts) opts = {}
|
|
this._trackers.forEach(tracker => {
|
|
// tracker should not modify `opts` object, it's passed to all trackers
|
|
tracker.scrape(opts)
|
|
})
|
|
}
|
|
|
|
setInterval (intervalMs) {
|
|
debug('setInterval %d', intervalMs)
|
|
this._trackers.forEach(tracker => {
|
|
tracker.setInterval(intervalMs)
|
|
})
|
|
}
|
|
|
|
destroy (cb) {
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
debug('destroy')
|
|
|
|
const tasks = this._trackers.map(tracker => cb => {
|
|
tracker.destroy(cb)
|
|
})
|
|
|
|
parallel(tasks, cb)
|
|
|
|
this._trackers = []
|
|
this._getAnnounceOpts = null
|
|
}
|
|
|
|
_defaultAnnounceOpts (opts = {}) {
|
|
if (opts.numwant == null) opts.numwant = common.DEFAULT_ANNOUNCE_PEERS
|
|
|
|
if (opts.uploaded == null) opts.uploaded = 0
|
|
if (opts.downloaded == null) opts.downloaded = 0
|
|
|
|
if (this._getAnnounceOpts) opts = Object.assign({}, opts, this._getAnnounceOpts())
|
|
|
|
return opts
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Simple convenience function to scrape a tracker for an info hash without needing to
|
|
* create a Client, pass it a parsed torrent, etc. Support scraping a tracker for multiple
|
|
* torrents at the same time.
|
|
* @params {Object} opts
|
|
* @param {string|Array.<string>} opts.infoHash
|
|
* @param {string} opts.announce
|
|
* @param {function} cb
|
|
*/
|
|
Client.scrape = (opts, cb) => {
|
|
cb = once(cb)
|
|
|
|
if (!opts.infoHash) throw new Error('Option `infoHash` is required')
|
|
if (!opts.announce) throw new Error('Option `announce` is required')
|
|
|
|
const clientOpts = Object.assign({}, opts, {
|
|
infoHash: Array.isArray(opts.infoHash) ? opts.infoHash[0] : opts.infoHash,
|
|
peerId: Buffer.from('01234567890123456789'), // dummy value
|
|
port: 6881 // dummy value
|
|
})
|
|
|
|
const client = new Client(clientOpts)
|
|
client.once('error', cb)
|
|
client.once('warning', cb)
|
|
|
|
let len = Array.isArray(opts.infoHash) ? opts.infoHash.length : 1
|
|
const results = {}
|
|
client.on('scrape', data => {
|
|
len -= 1
|
|
results[data.infoHash] = data
|
|
if (len === 0) {
|
|
client.destroy()
|
|
const keys = Object.keys(results)
|
|
if (keys.length === 1) {
|
|
cb(null, results[keys[0]])
|
|
} else {
|
|
cb(null, results)
|
|
}
|
|
}
|
|
})
|
|
|
|
opts.infoHash = Array.isArray(opts.infoHash)
|
|
? opts.infoHash.map(infoHash => Buffer.from(infoHash, 'hex'))
|
|
: Buffer.from(opts.infoHash, 'hex')
|
|
client.scrape({ infoHash: opts.infoHash })
|
|
return client
|
|
}
|
|
|
|
module.exports = Client
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/bittorrent-tracker/lib/client/tracker.js":
|
|
/*!***************************************************************!*\
|
|
!*** ./node_modules/bittorrent-tracker/lib/client/tracker.js ***!
|
|
\***************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const EventEmitter = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
|
|
class Tracker extends EventEmitter {
|
|
constructor (client, announceUrl) {
|
|
super()
|
|
|
|
this.client = client
|
|
this.announceUrl = announceUrl
|
|
|
|
this.interval = null
|
|
this.destroyed = false
|
|
}
|
|
|
|
setInterval (intervalMs) {
|
|
if (intervalMs == null) intervalMs = this.DEFAULT_ANNOUNCE_INTERVAL
|
|
|
|
clearInterval(this.interval)
|
|
|
|
if (intervalMs) {
|
|
this.interval = setInterval(() => {
|
|
this.announce(this.client._defaultAnnounceOpts())
|
|
}, intervalMs)
|
|
if (this.interval.unref) this.interval.unref()
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = Tracker
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/bittorrent-tracker/lib/client/websocket-tracker.js":
|
|
/*!*************************************************************************!*\
|
|
!*** ./node_modules/bittorrent-tracker/lib/client/websocket-tracker.js ***!
|
|
\*************************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('bittorrent-tracker:websocket-tracker')
|
|
const Peer = __webpack_require__(/*! simple-peer */ "./node_modules/simple-peer/index.js")
|
|
const randombytes = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js")
|
|
const Socket = __webpack_require__(/*! simple-websocket */ "./node_modules/simple-websocket/index.js")
|
|
|
|
const common = __webpack_require__(/*! ../common */ "./node_modules/bittorrent-tracker/lib/common.js")
|
|
const Tracker = __webpack_require__(/*! ./tracker */ "./node_modules/bittorrent-tracker/lib/client/tracker.js")
|
|
|
|
// Use a socket pool, so tracker clients share WebSocket objects for the same server.
|
|
// In practice, WebSockets are pretty slow to establish, so this gives a nice performance
|
|
// boost, and saves browser resources.
|
|
const socketPool = {}
|
|
|
|
const RECONNECT_MINIMUM = 10 * 1000
|
|
const RECONNECT_MAXIMUM = 60 * 60 * 1000
|
|
const RECONNECT_VARIANCE = 5 * 60 * 1000
|
|
const OFFER_TIMEOUT = 50 * 1000
|
|
|
|
class WebSocketTracker extends Tracker {
|
|
constructor (client, announceUrl) {
|
|
super(client, announceUrl)
|
|
debug('new websocket tracker %s', announceUrl)
|
|
|
|
this.peers = {} // peers (offer id -> peer)
|
|
this.socket = null
|
|
|
|
this.reconnecting = false
|
|
this.retries = 0
|
|
this.reconnectTimer = null
|
|
|
|
// Simple boolean flag to track whether the socket has received data from
|
|
// the websocket server since the last time socket.send() was called.
|
|
this.expectingResponse = false
|
|
|
|
this._openSocket()
|
|
}
|
|
|
|
announce (opts) {
|
|
if (this.destroyed || this.reconnecting) return
|
|
if (!this.socket.connected) {
|
|
this.socket.once('connect', () => {
|
|
this.announce(opts)
|
|
})
|
|
return
|
|
}
|
|
|
|
const params = Object.assign({}, opts, {
|
|
action: 'announce',
|
|
info_hash: this.client._infoHashBinary,
|
|
peer_id: this.client._peerIdBinary
|
|
})
|
|
if (this._trackerId) params.trackerid = this._trackerId
|
|
|
|
if (opts.event === 'stopped' || opts.event === 'completed') {
|
|
// Don't include offers with 'stopped' or 'completed' event
|
|
this._send(params)
|
|
} else {
|
|
// Limit the number of offers that are generated, since it can be slow
|
|
const numwant = Math.min(opts.numwant, 5)
|
|
|
|
this._generateOffers(numwant, offers => {
|
|
params.numwant = numwant
|
|
params.offers = offers
|
|
this._send(params)
|
|
})
|
|
}
|
|
}
|
|
|
|
scrape (opts) {
|
|
if (this.destroyed || this.reconnecting) return
|
|
if (!this.socket.connected) {
|
|
this.socket.once('connect', () => {
|
|
this.scrape(opts)
|
|
})
|
|
return
|
|
}
|
|
|
|
const infoHashes = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0)
|
|
? opts.infoHash.map(infoHash => infoHash.toString('binary'))
|
|
: (opts.infoHash && opts.infoHash.toString('binary')) || this.client._infoHashBinary
|
|
const params = {
|
|
action: 'scrape',
|
|
info_hash: infoHashes
|
|
}
|
|
|
|
this._send(params)
|
|
}
|
|
|
|
destroy (cb = noop) {
|
|
if (this.destroyed) return cb(null)
|
|
|
|
this.destroyed = true
|
|
|
|
clearInterval(this.interval)
|
|
clearTimeout(this.reconnectTimer)
|
|
|
|
// Destroy peers
|
|
for (const peerId in this.peers) {
|
|
const peer = this.peers[peerId]
|
|
clearTimeout(peer.trackerTimeout)
|
|
peer.destroy()
|
|
}
|
|
this.peers = null
|
|
|
|
if (this.socket) {
|
|
this.socket.removeListener('connect', this._onSocketConnectBound)
|
|
this.socket.removeListener('data', this._onSocketDataBound)
|
|
this.socket.removeListener('close', this._onSocketCloseBound)
|
|
this.socket.removeListener('error', this._onSocketErrorBound)
|
|
this.socket = null
|
|
}
|
|
|
|
this._onSocketConnectBound = null
|
|
this._onSocketErrorBound = null
|
|
this._onSocketDataBound = null
|
|
this._onSocketCloseBound = null
|
|
|
|
if (socketPool[this.announceUrl]) {
|
|
socketPool[this.announceUrl].consumers -= 1
|
|
}
|
|
|
|
// Other instances are using the socket, so there's nothing left to do here
|
|
if (socketPool[this.announceUrl].consumers > 0) return cb()
|
|
|
|
let socket = socketPool[this.announceUrl]
|
|
delete socketPool[this.announceUrl]
|
|
socket.on('error', noop) // ignore all future errors
|
|
socket.once('close', cb)
|
|
|
|
let timeout
|
|
|
|
// If there is no data response expected, destroy immediately.
|
|
if (!this.expectingResponse) return destroyCleanup()
|
|
|
|
// Otherwise, wait a short time for potential responses to come in from the
|
|
// server, then force close the socket.
|
|
timeout = setTimeout(destroyCleanup, common.DESTROY_TIMEOUT)
|
|
|
|
// But, if a response comes from the server before the timeout fires, do cleanup
|
|
// right away.
|
|
socket.once('data', destroyCleanup)
|
|
|
|
function destroyCleanup () {
|
|
if (timeout) {
|
|
clearTimeout(timeout)
|
|
timeout = null
|
|
}
|
|
socket.removeListener('data', destroyCleanup)
|
|
socket.destroy()
|
|
socket = null
|
|
}
|
|
}
|
|
|
|
_openSocket () {
|
|
this.destroyed = false
|
|
|
|
if (!this.peers) this.peers = {}
|
|
|
|
this._onSocketConnectBound = () => {
|
|
this._onSocketConnect()
|
|
}
|
|
this._onSocketErrorBound = err => {
|
|
this._onSocketError(err)
|
|
}
|
|
this._onSocketDataBound = data => {
|
|
this._onSocketData(data)
|
|
}
|
|
this._onSocketCloseBound = () => {
|
|
this._onSocketClose()
|
|
}
|
|
|
|
this.socket = socketPool[this.announceUrl]
|
|
if (this.socket) {
|
|
socketPool[this.announceUrl].consumers += 1
|
|
if (this.socket.connected) {
|
|
this._onSocketConnectBound()
|
|
}
|
|
} else {
|
|
this.socket = socketPool[this.announceUrl] = new Socket(this.announceUrl)
|
|
this.socket.consumers = 1
|
|
this.socket.once('connect', this._onSocketConnectBound)
|
|
}
|
|
|
|
this.socket.on('data', this._onSocketDataBound)
|
|
this.socket.once('close', this._onSocketCloseBound)
|
|
this.socket.once('error', this._onSocketErrorBound)
|
|
}
|
|
|
|
_onSocketConnect () {
|
|
if (this.destroyed) return
|
|
|
|
if (this.reconnecting) {
|
|
this.reconnecting = false
|
|
this.retries = 0
|
|
this.announce(this.client._defaultAnnounceOpts())
|
|
}
|
|
}
|
|
|
|
_onSocketData (data) {
|
|
if (this.destroyed) return
|
|
|
|
this.expectingResponse = false
|
|
|
|
try {
|
|
data = JSON.parse(data)
|
|
} catch (err) {
|
|
this.client.emit('warning', new Error('Invalid tracker response'))
|
|
return
|
|
}
|
|
|
|
if (data.action === 'announce') {
|
|
this._onAnnounceResponse(data)
|
|
} else if (data.action === 'scrape') {
|
|
this._onScrapeResponse(data)
|
|
} else {
|
|
this._onSocketError(new Error(`invalid action in WS response: ${data.action}`))
|
|
}
|
|
}
|
|
|
|
_onAnnounceResponse (data) {
|
|
if (data.info_hash !== this.client._infoHashBinary) {
|
|
debug(
|
|
'ignoring websocket data from %s for %s (looking for %s: reused socket)',
|
|
this.announceUrl, common.binaryToHex(data.info_hash), this.client.infoHash
|
|
)
|
|
return
|
|
}
|
|
|
|
if (data.peer_id && data.peer_id === this.client._peerIdBinary) {
|
|
// ignore offers/answers from this client
|
|
return
|
|
}
|
|
|
|
debug(
|
|
'received %s from %s for %s',
|
|
JSON.stringify(data), this.announceUrl, this.client.infoHash
|
|
)
|
|
|
|
const failure = data['failure reason']
|
|
if (failure) return this.client.emit('warning', new Error(failure))
|
|
|
|
const warning = data['warning message']
|
|
if (warning) this.client.emit('warning', new Error(warning))
|
|
|
|
const interval = data.interval || data['min interval']
|
|
if (interval) this.setInterval(interval * 1000)
|
|
|
|
const trackerId = data['tracker id']
|
|
if (trackerId) {
|
|
// If absent, do not discard previous trackerId value
|
|
this._trackerId = trackerId
|
|
}
|
|
|
|
if (data.complete != null) {
|
|
const response = Object.assign({}, data, {
|
|
announce: this.announceUrl,
|
|
infoHash: common.binaryToHex(data.info_hash)
|
|
})
|
|
this.client.emit('update', response)
|
|
}
|
|
|
|
let peer
|
|
if (data.offer && data.peer_id) {
|
|
debug('creating peer (from remote offer)')
|
|
peer = this._createPeer()
|
|
peer.id = common.binaryToHex(data.peer_id)
|
|
peer.once('signal', answer => {
|
|
const params = {
|
|
action: 'announce',
|
|
info_hash: this.client._infoHashBinary,
|
|
peer_id: this.client._peerIdBinary,
|
|
to_peer_id: data.peer_id,
|
|
answer,
|
|
offer_id: data.offer_id
|
|
}
|
|
if (this._trackerId) params.trackerid = this._trackerId
|
|
this._send(params)
|
|
})
|
|
this.client.emit('peer', peer)
|
|
peer.signal(data.offer)
|
|
}
|
|
|
|
if (data.answer && data.peer_id) {
|
|
const offerId = common.binaryToHex(data.offer_id)
|
|
peer = this.peers[offerId]
|
|
if (peer) {
|
|
peer.id = common.binaryToHex(data.peer_id)
|
|
this.client.emit('peer', peer)
|
|
peer.signal(data.answer)
|
|
|
|
clearTimeout(peer.trackerTimeout)
|
|
peer.trackerTimeout = null
|
|
delete this.peers[offerId]
|
|
} else {
|
|
debug(`got unexpected answer: ${JSON.stringify(data.answer)}`)
|
|
}
|
|
}
|
|
}
|
|
|
|
_onScrapeResponse (data) {
|
|
data = data.files || {}
|
|
|
|
const keys = Object.keys(data)
|
|
if (keys.length === 0) {
|
|
this.client.emit('warning', new Error('invalid scrape response'))
|
|
return
|
|
}
|
|
|
|
keys.forEach(infoHash => {
|
|
// TODO: optionally handle data.flags.min_request_interval
|
|
// (separate from announce interval)
|
|
const response = Object.assign(data[infoHash], {
|
|
announce: this.announceUrl,
|
|
infoHash: common.binaryToHex(infoHash)
|
|
})
|
|
this.client.emit('scrape', response)
|
|
})
|
|
}
|
|
|
|
_onSocketClose () {
|
|
if (this.destroyed) return
|
|
this.destroy()
|
|
this._startReconnectTimer()
|
|
}
|
|
|
|
_onSocketError (err) {
|
|
if (this.destroyed) return
|
|
this.destroy()
|
|
// errors will often happen if a tracker is offline, so don't treat it as fatal
|
|
this.client.emit('warning', err)
|
|
this._startReconnectTimer()
|
|
}
|
|
|
|
_startReconnectTimer () {
|
|
const ms = Math.floor(Math.random() * RECONNECT_VARIANCE) + Math.min(Math.pow(2, this.retries) * RECONNECT_MINIMUM, RECONNECT_MAXIMUM)
|
|
|
|
this.reconnecting = true
|
|
clearTimeout(this.reconnectTimer)
|
|
this.reconnectTimer = setTimeout(() => {
|
|
this.retries++
|
|
this._openSocket()
|
|
}, ms)
|
|
if (this.reconnectTimer.unref) this.reconnectTimer.unref()
|
|
|
|
debug('reconnecting socket in %s ms', ms)
|
|
}
|
|
|
|
_send (params) {
|
|
if (this.destroyed) return
|
|
this.expectingResponse = true
|
|
const message = JSON.stringify(params)
|
|
debug('send %s', message)
|
|
this.socket.send(message)
|
|
}
|
|
|
|
_generateOffers (numwant, cb) {
|
|
const self = this
|
|
const offers = []
|
|
debug('generating %s offers', numwant)
|
|
|
|
for (let i = 0; i < numwant; ++i) {
|
|
generateOffer()
|
|
}
|
|
checkDone()
|
|
|
|
function generateOffer () {
|
|
const offerId = randombytes(20).toString('hex')
|
|
debug('creating peer (from _generateOffers)')
|
|
const peer = self.peers[offerId] = self._createPeer({ initiator: true })
|
|
peer.once('signal', offer => {
|
|
offers.push({
|
|
offer,
|
|
offer_id: common.hexToBinary(offerId)
|
|
})
|
|
checkDone()
|
|
})
|
|
peer.trackerTimeout = setTimeout(() => {
|
|
debug('tracker timeout: destroying peer')
|
|
peer.trackerTimeout = null
|
|
delete self.peers[offerId]
|
|
peer.destroy()
|
|
}, OFFER_TIMEOUT)
|
|
if (peer.trackerTimeout.unref) peer.trackerTimeout.unref()
|
|
}
|
|
|
|
function checkDone () {
|
|
if (offers.length === numwant) {
|
|
debug('generated %s offers', numwant)
|
|
cb(offers)
|
|
}
|
|
}
|
|
}
|
|
|
|
_createPeer (opts) {
|
|
const self = this
|
|
|
|
opts = Object.assign({
|
|
trickle: false,
|
|
config: self.client._rtcConfig,
|
|
wrtc: self.client._wrtc
|
|
}, opts)
|
|
|
|
const peer = new Peer(opts)
|
|
|
|
peer.once('error', onError)
|
|
peer.once('connect', onConnect)
|
|
|
|
return peer
|
|
|
|
// Handle peer 'error' events that are fired *before* the peer is emitted in
|
|
// a 'peer' event.
|
|
function onError (err) {
|
|
self.client.emit('warning', new Error(`Connection error: ${err.message}`))
|
|
peer.destroy()
|
|
}
|
|
|
|
// Once the peer is emitted in a 'peer' event, then it's the consumer's
|
|
// responsibility to listen for errors, so the listeners are removed here.
|
|
function onConnect () {
|
|
peer.removeListener('error', onError)
|
|
peer.removeListener('connect', onConnect)
|
|
}
|
|
}
|
|
}
|
|
|
|
WebSocketTracker.prototype.DEFAULT_ANNOUNCE_INTERVAL = 30 * 1000 // 30 seconds
|
|
// Normally this shouldn't be accessed but is occasionally useful
|
|
WebSocketTracker._socketPool = socketPool
|
|
|
|
function noop () {}
|
|
|
|
module.exports = WebSocketTracker
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/bittorrent-tracker/lib/common.js":
|
|
/*!*******************************************************!*\
|
|
!*** ./node_modules/bittorrent-tracker/lib/common.js ***!
|
|
\*******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/**
|
|
* Functions/constants needed by both the client and server.
|
|
*/
|
|
|
|
exports.DEFAULT_ANNOUNCE_PEERS = 50
|
|
exports.MAX_ANNOUNCE_PEERS = 82
|
|
|
|
exports.binaryToHex = str => {
|
|
if (typeof str !== 'string') {
|
|
str = String(str)
|
|
}
|
|
return Buffer.from(str, 'binary').toString('hex')
|
|
}
|
|
|
|
exports.hexToBinary = str => {
|
|
if (typeof str !== 'string') {
|
|
str = String(str)
|
|
}
|
|
return Buffer.from(str, 'hex').toString('binary')
|
|
}
|
|
|
|
// HACK: Fix for WHATWG URL object not parsing non-standard URL schemes like
|
|
// 'udp:'. Just replace it with 'http:' since we only need a few properties.
|
|
//
|
|
// Note: Only affects Chrome and Firefox. Works fine in Node.js, Safari, and
|
|
// Edge.
|
|
//
|
|
// Note: UDP trackers aren't used in the normal browser build, but they are
|
|
// used in a Chrome App build (i.e. by Brave Browser).
|
|
//
|
|
// Bug reports:
|
|
// - Chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=734880
|
|
// - Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1374505
|
|
exports.parseUrl = str => {
|
|
const url = new URL(str.replace(/^udp:/, 'http:'))
|
|
|
|
if (str.match(/^udp:/)) {
|
|
Object.defineProperties(url, {
|
|
href: { value: url.href.replace(/^http/, 'udp') },
|
|
protocol: { value: url.protocol.replace(/^http/, 'udp') },
|
|
origin: { value: url.origin.replace(/^http/, 'udp') }
|
|
})
|
|
}
|
|
|
|
return url
|
|
}
|
|
|
|
const config = __webpack_require__(/*! ./common-node */ "?5a06")
|
|
Object.assign(exports, config)
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/blob-to-buffer/index.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/blob-to-buffer/index.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! blob-to-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
/* global Blob, FileReader */
|
|
|
|
module.exports = function blobToBuffer (blob, cb) {
|
|
if (typeof Blob === 'undefined' || !(blob instanceof Blob)) {
|
|
throw new Error('first argument must be a Blob')
|
|
}
|
|
if (typeof cb !== 'function') {
|
|
throw new Error('second argument must be a function')
|
|
}
|
|
|
|
const reader = new FileReader()
|
|
|
|
function onLoadEnd (e) {
|
|
reader.removeEventListener('loadend', onLoadEnd, false)
|
|
if (e.error) cb(e.error)
|
|
else cb(null, Buffer.from(reader.result))
|
|
}
|
|
|
|
reader.addEventListener('loadend', onLoadEnd, false)
|
|
reader.readAsArrayBuffer(blob)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/block-stream2/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/block-stream2/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
const { Transform } = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
|
|
class Block extends Transform {
|
|
constructor (size, opts = {}) {
|
|
super(opts)
|
|
|
|
if (typeof size === 'object') {
|
|
opts = size
|
|
size = opts.size
|
|
}
|
|
|
|
this.size = size || 512
|
|
|
|
const { nopad, zeroPadding = true } = opts
|
|
|
|
if (nopad) this._zeroPadding = false
|
|
else this._zeroPadding = !!zeroPadding
|
|
|
|
this._buffered = []
|
|
this._bufferedBytes = 0
|
|
}
|
|
|
|
_transform (buf, enc, next) {
|
|
this._bufferedBytes += buf.length
|
|
this._buffered.push(buf)
|
|
|
|
while (this._bufferedBytes >= this.size) {
|
|
this._bufferedBytes -= this.size
|
|
|
|
// Assemble the buffers that will compose the final block
|
|
const blockBufs = []
|
|
let blockBufsBytes = 0
|
|
while (blockBufsBytes < this.size) {
|
|
const b = this._buffered.shift()
|
|
|
|
if (blockBufsBytes + b.length <= this.size) {
|
|
blockBufs.push(b)
|
|
blockBufsBytes += b.length
|
|
} else {
|
|
// If the last buffer is larger than needed for the block, just
|
|
// use the needed part
|
|
const neededSize = this.size - blockBufsBytes
|
|
blockBufs.push(b.slice(0, neededSize))
|
|
blockBufsBytes += neededSize
|
|
this._buffered.unshift(b.slice(neededSize))
|
|
}
|
|
}
|
|
|
|
// Then concat just those buffers, leaving the rest untouched in _buffered
|
|
this.push(Buffer.concat(blockBufs, this.size))
|
|
}
|
|
next()
|
|
}
|
|
|
|
_flush () {
|
|
if (this._bufferedBytes && this._zeroPadding) {
|
|
const zeroes = Buffer.alloc(this.size - this._bufferedBytes)
|
|
this._buffered.push(zeroes)
|
|
this.push(Buffer.concat(this._buffered))
|
|
this._buffered = null
|
|
} else if (this._bufferedBytes) {
|
|
this.push(Buffer.concat(this._buffered))
|
|
this._buffered = null
|
|
}
|
|
this.push(null)
|
|
}
|
|
}
|
|
|
|
module.exports = Block
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/bn.js/lib/bn.js":
|
|
/*!**************************************!*\
|
|
!*** ./node_modules/bn.js/lib/bn.js ***!
|
|
\**************************************/
|
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
/* module decorator */ module = __webpack_require__.nmd(module);
|
|
(function (module, exports) {
|
|
'use strict';
|
|
|
|
// Utils
|
|
function assert (val, msg) {
|
|
if (!val) throw new Error(msg || 'Assertion failed');
|
|
}
|
|
|
|
// Could use `inherits` module, but don't want to move from single file
|
|
// architecture yet.
|
|
function inherits (ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
var TempCtor = function () {};
|
|
TempCtor.prototype = superCtor.prototype;
|
|
ctor.prototype = new TempCtor();
|
|
ctor.prototype.constructor = ctor;
|
|
}
|
|
|
|
// BN
|
|
|
|
function BN (number, base, endian) {
|
|
if (BN.isBN(number)) {
|
|
return number;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.words = null;
|
|
this.length = 0;
|
|
|
|
// Reduction context
|
|
this.red = null;
|
|
|
|
if (number !== null) {
|
|
if (base === 'le' || base === 'be') {
|
|
endian = base;
|
|
base = 10;
|
|
}
|
|
|
|
this._init(number || 0, base || 10, endian || 'be');
|
|
}
|
|
}
|
|
if (typeof module === 'object') {
|
|
module.exports = BN;
|
|
} else {
|
|
exports.BN = BN;
|
|
}
|
|
|
|
BN.BN = BN;
|
|
BN.wordSize = 26;
|
|
|
|
var Buffer;
|
|
try {
|
|
if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') {
|
|
Buffer = window.Buffer;
|
|
} else {
|
|
Buffer = __webpack_require__(/*! buffer */ "?8131").Buffer;
|
|
}
|
|
} catch (e) {
|
|
}
|
|
|
|
BN.isBN = function isBN (num) {
|
|
if (num instanceof BN) {
|
|
return true;
|
|
}
|
|
|
|
return num !== null && typeof num === 'object' &&
|
|
num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
|
|
};
|
|
|
|
BN.max = function max (left, right) {
|
|
if (left.cmp(right) > 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.min = function min (left, right) {
|
|
if (left.cmp(right) < 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.prototype._init = function init (number, base, endian) {
|
|
if (typeof number === 'number') {
|
|
return this._initNumber(number, base, endian);
|
|
}
|
|
|
|
if (typeof number === 'object') {
|
|
return this._initArray(number, base, endian);
|
|
}
|
|
|
|
if (base === 'hex') {
|
|
base = 16;
|
|
}
|
|
assert(base === (base | 0) && base >= 2 && base <= 36);
|
|
|
|
number = number.toString().replace(/\s+/g, '');
|
|
var start = 0;
|
|
if (number[0] === '-') {
|
|
start++;
|
|
this.negative = 1;
|
|
}
|
|
|
|
if (start < number.length) {
|
|
if (base === 16) {
|
|
this._parseHex(number, start, endian);
|
|
} else {
|
|
this._parseBase(number, base, start);
|
|
if (endian === 'le') {
|
|
this._initArray(this.toArray(), base, endian);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
BN.prototype._initNumber = function _initNumber (number, base, endian) {
|
|
if (number < 0) {
|
|
this.negative = 1;
|
|
number = -number;
|
|
}
|
|
if (number < 0x4000000) {
|
|
this.words = [number & 0x3ffffff];
|
|
this.length = 1;
|
|
} else if (number < 0x10000000000000) {
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff
|
|
];
|
|
this.length = 2;
|
|
} else {
|
|
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff,
|
|
1
|
|
];
|
|
this.length = 3;
|
|
}
|
|
|
|
if (endian !== 'le') return;
|
|
|
|
// Reverse the bytes
|
|
this._initArray(this.toArray(), base, endian);
|
|
};
|
|
|
|
BN.prototype._initArray = function _initArray (number, base, endian) {
|
|
// Perhaps a Uint8Array
|
|
assert(typeof number.length === 'number');
|
|
if (number.length <= 0) {
|
|
this.words = [0];
|
|
this.length = 1;
|
|
return this;
|
|
}
|
|
|
|
this.length = Math.ceil(number.length / 3);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
var j, w;
|
|
var off = 0;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
|
|
w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
} else if (endian === 'le') {
|
|
for (i = 0, j = 0; i < number.length; i += 3) {
|
|
w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
return this._strip();
|
|
};
|
|
|
|
function parseHex4Bits (string, index) {
|
|
var c = string.charCodeAt(index);
|
|
// '0' - '9'
|
|
if (c >= 48 && c <= 57) {
|
|
return c - 48;
|
|
// 'A' - 'F'
|
|
} else if (c >= 65 && c <= 70) {
|
|
return c - 55;
|
|
// 'a' - 'f'
|
|
} else if (c >= 97 && c <= 102) {
|
|
return c - 87;
|
|
} else {
|
|
assert(false, 'Invalid character in ' + string);
|
|
}
|
|
}
|
|
|
|
function parseHexByte (string, lowerBound, index) {
|
|
var r = parseHex4Bits(string, index);
|
|
if (index - 1 >= lowerBound) {
|
|
r |= parseHex4Bits(string, index - 1) << 4;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseHex = function _parseHex (number, start, endian) {
|
|
// Create possibly bigger array to ensure that it fits the number
|
|
this.length = Math.ceil((number.length - start) / 6);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
// 24-bits chunks
|
|
var off = 0;
|
|
var j = 0;
|
|
|
|
var w;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1; i >= start; i -= 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
} else {
|
|
var parseLength = number.length - start;
|
|
for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
this._strip();
|
|
};
|
|
|
|
function parseBase (str, start, end, mul) {
|
|
var r = 0;
|
|
var b = 0;
|
|
var len = Math.min(str.length, end);
|
|
for (var i = start; i < len; i++) {
|
|
var c = str.charCodeAt(i) - 48;
|
|
|
|
r *= mul;
|
|
|
|
// 'a'
|
|
if (c >= 49) {
|
|
b = c - 49 + 0xa;
|
|
|
|
// 'A'
|
|
} else if (c >= 17) {
|
|
b = c - 17 + 0xa;
|
|
|
|
// '0' - '9'
|
|
} else {
|
|
b = c;
|
|
}
|
|
assert(c >= 0 && b < mul, 'Invalid character');
|
|
r += b;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseBase = function _parseBase (number, base, start) {
|
|
// Initialize as zero
|
|
this.words = [0];
|
|
this.length = 1;
|
|
|
|
// Find length of limb in base
|
|
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
|
|
limbLen++;
|
|
}
|
|
limbLen--;
|
|
limbPow = (limbPow / base) | 0;
|
|
|
|
var total = number.length - start;
|
|
var mod = total % limbLen;
|
|
var end = Math.min(total, total - mod) + start;
|
|
|
|
var word = 0;
|
|
for (var i = start; i < end; i += limbLen) {
|
|
word = parseBase(number, i, i + limbLen, base);
|
|
|
|
this.imuln(limbPow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
if (mod !== 0) {
|
|
var pow = 1;
|
|
word = parseBase(number, i, number.length, base);
|
|
|
|
for (i = 0; i < mod; i++) {
|
|
pow *= base;
|
|
}
|
|
|
|
this.imuln(pow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
this._strip();
|
|
};
|
|
|
|
BN.prototype.copy = function copy (dest) {
|
|
dest.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
dest.words[i] = this.words[i];
|
|
}
|
|
dest.length = this.length;
|
|
dest.negative = this.negative;
|
|
dest.red = this.red;
|
|
};
|
|
|
|
function move (dest, src) {
|
|
dest.words = src.words;
|
|
dest.length = src.length;
|
|
dest.negative = src.negative;
|
|
dest.red = src.red;
|
|
}
|
|
|
|
BN.prototype._move = function _move (dest) {
|
|
move(dest, this);
|
|
};
|
|
|
|
BN.prototype.clone = function clone () {
|
|
var r = new BN(null);
|
|
this.copy(r);
|
|
return r;
|
|
};
|
|
|
|
BN.prototype._expand = function _expand (size) {
|
|
while (this.length < size) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
// Remove leading `0` from `this`
|
|
BN.prototype._strip = function strip () {
|
|
while (this.length > 1 && this.words[this.length - 1] === 0) {
|
|
this.length--;
|
|
}
|
|
return this._normSign();
|
|
};
|
|
|
|
BN.prototype._normSign = function _normSign () {
|
|
// -0 = 0
|
|
if (this.length === 1 && this.words[0] === 0) {
|
|
this.negative = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
// Check Symbol.for because not everywhere where Symbol defined
|
|
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Browser_compatibility
|
|
if (typeof Symbol !== 'undefined' && typeof Symbol.for === 'function') {
|
|
try {
|
|
BN.prototype[Symbol.for('nodejs.util.inspect.custom')] = inspect;
|
|
} catch (e) {
|
|
BN.prototype.inspect = inspect;
|
|
}
|
|
} else {
|
|
BN.prototype.inspect = inspect;
|
|
}
|
|
|
|
function inspect () {
|
|
return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
|
|
}
|
|
|
|
/*
|
|
|
|
var zeros = [];
|
|
var groupSizes = [];
|
|
var groupBases = [];
|
|
|
|
var s = '';
|
|
var i = -1;
|
|
while (++i < BN.wordSize) {
|
|
zeros[i] = s;
|
|
s += '0';
|
|
}
|
|
groupSizes[0] = 0;
|
|
groupSizes[1] = 0;
|
|
groupBases[0] = 0;
|
|
groupBases[1] = 0;
|
|
var base = 2 - 1;
|
|
while (++base < 36 + 1) {
|
|
var groupSize = 0;
|
|
var groupBase = 1;
|
|
while (groupBase < (1 << BN.wordSize) / base) {
|
|
groupBase *= base;
|
|
groupSize += 1;
|
|
}
|
|
groupSizes[base] = groupSize;
|
|
groupBases[base] = groupBase;
|
|
}
|
|
|
|
*/
|
|
|
|
var zeros = [
|
|
'',
|
|
'0',
|
|
'00',
|
|
'000',
|
|
'0000',
|
|
'00000',
|
|
'000000',
|
|
'0000000',
|
|
'00000000',
|
|
'000000000',
|
|
'0000000000',
|
|
'00000000000',
|
|
'000000000000',
|
|
'0000000000000',
|
|
'00000000000000',
|
|
'000000000000000',
|
|
'0000000000000000',
|
|
'00000000000000000',
|
|
'000000000000000000',
|
|
'0000000000000000000',
|
|
'00000000000000000000',
|
|
'000000000000000000000',
|
|
'0000000000000000000000',
|
|
'00000000000000000000000',
|
|
'000000000000000000000000',
|
|
'0000000000000000000000000'
|
|
];
|
|
|
|
var groupSizes = [
|
|
0, 0,
|
|
25, 16, 12, 11, 10, 9, 8,
|
|
8, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5
|
|
];
|
|
|
|
var groupBases = [
|
|
0, 0,
|
|
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
|
|
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
|
|
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
|
|
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
|
|
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
|
|
];
|
|
|
|
BN.prototype.toString = function toString (base, padding) {
|
|
base = base || 10;
|
|
padding = padding | 0 || 1;
|
|
|
|
var out;
|
|
if (base === 16 || base === 'hex') {
|
|
out = '';
|
|
var off = 0;
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = this.words[i];
|
|
var word = (((w << off) | carry) & 0xffffff).toString(16);
|
|
carry = (w >>> (24 - off)) & 0xffffff;
|
|
if (carry !== 0 || i !== this.length - 1) {
|
|
out = zeros[6 - word.length] + word + out;
|
|
} else {
|
|
out = word + out;
|
|
}
|
|
off += 2;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
i--;
|
|
}
|
|
}
|
|
if (carry !== 0) {
|
|
out = carry.toString(16) + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
if (base === (base | 0) && base >= 2 && base <= 36) {
|
|
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
|
|
var groupSize = groupSizes[base];
|
|
// var groupBase = Math.pow(base, groupSize);
|
|
var groupBase = groupBases[base];
|
|
out = '';
|
|
var c = this.clone();
|
|
c.negative = 0;
|
|
while (!c.isZero()) {
|
|
var r = c.modrn(groupBase).toString(base);
|
|
c = c.idivn(groupBase);
|
|
|
|
if (!c.isZero()) {
|
|
out = zeros[groupSize - r.length] + r + out;
|
|
} else {
|
|
out = r + out;
|
|
}
|
|
}
|
|
if (this.isZero()) {
|
|
out = '0' + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
assert(false, 'Base should be between 2 and 36');
|
|
};
|
|
|
|
BN.prototype.toNumber = function toNumber () {
|
|
var ret = this.words[0];
|
|
if (this.length === 2) {
|
|
ret += this.words[1] * 0x4000000;
|
|
} else if (this.length === 3 && this.words[2] === 0x01) {
|
|
// NOTE: at this stage it is known that the top bit is set
|
|
ret += 0x10000000000000 + (this.words[1] * 0x4000000);
|
|
} else if (this.length > 2) {
|
|
assert(false, 'Number can only safely store up to 53 bits');
|
|
}
|
|
return (this.negative !== 0) ? -ret : ret;
|
|
};
|
|
|
|
BN.prototype.toJSON = function toJSON () {
|
|
return this.toString(16, 2);
|
|
};
|
|
|
|
if (Buffer) {
|
|
BN.prototype.toBuffer = function toBuffer (endian, length) {
|
|
return this.toArrayLike(Buffer, endian, length);
|
|
};
|
|
}
|
|
|
|
BN.prototype.toArray = function toArray (endian, length) {
|
|
return this.toArrayLike(Array, endian, length);
|
|
};
|
|
|
|
var allocate = function allocate (ArrayType, size) {
|
|
if (ArrayType.allocUnsafe) {
|
|
return ArrayType.allocUnsafe(size);
|
|
}
|
|
return new ArrayType(size);
|
|
};
|
|
|
|
BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
|
|
this._strip();
|
|
|
|
var byteLength = this.byteLength();
|
|
var reqLength = length || Math.max(1, byteLength);
|
|
assert(byteLength <= reqLength, 'byte array longer than desired length');
|
|
assert(reqLength > 0, 'Requested array length <= 0');
|
|
|
|
var res = allocate(ArrayType, reqLength);
|
|
var postfix = endian === 'le' ? 'LE' : 'BE';
|
|
this['_toArrayLike' + postfix](res, byteLength);
|
|
return res;
|
|
};
|
|
|
|
BN.prototype._toArrayLikeLE = function _toArrayLikeLE (res, byteLength) {
|
|
var position = 0;
|
|
var carry = 0;
|
|
|
|
for (var i = 0, shift = 0; i < this.length; i++) {
|
|
var word = (this.words[i] << shift) | carry;
|
|
|
|
res[position++] = word & 0xff;
|
|
if (position < res.length) {
|
|
res[position++] = (word >> 8) & 0xff;
|
|
}
|
|
if (position < res.length) {
|
|
res[position++] = (word >> 16) & 0xff;
|
|
}
|
|
|
|
if (shift === 6) {
|
|
if (position < res.length) {
|
|
res[position++] = (word >> 24) & 0xff;
|
|
}
|
|
carry = 0;
|
|
shift = 0;
|
|
} else {
|
|
carry = word >>> 24;
|
|
shift += 2;
|
|
}
|
|
}
|
|
|
|
if (position < res.length) {
|
|
res[position++] = carry;
|
|
|
|
while (position < res.length) {
|
|
res[position++] = 0;
|
|
}
|
|
}
|
|
};
|
|
|
|
BN.prototype._toArrayLikeBE = function _toArrayLikeBE (res, byteLength) {
|
|
var position = res.length - 1;
|
|
var carry = 0;
|
|
|
|
for (var i = 0, shift = 0; i < this.length; i++) {
|
|
var word = (this.words[i] << shift) | carry;
|
|
|
|
res[position--] = word & 0xff;
|
|
if (position >= 0) {
|
|
res[position--] = (word >> 8) & 0xff;
|
|
}
|
|
if (position >= 0) {
|
|
res[position--] = (word >> 16) & 0xff;
|
|
}
|
|
|
|
if (shift === 6) {
|
|
if (position >= 0) {
|
|
res[position--] = (word >> 24) & 0xff;
|
|
}
|
|
carry = 0;
|
|
shift = 0;
|
|
} else {
|
|
carry = word >>> 24;
|
|
shift += 2;
|
|
}
|
|
}
|
|
|
|
if (position >= 0) {
|
|
res[position--] = carry;
|
|
|
|
while (position >= 0) {
|
|
res[position--] = 0;
|
|
}
|
|
}
|
|
};
|
|
|
|
if (Math.clz32) {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
return 32 - Math.clz32(w);
|
|
};
|
|
} else {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
var t = w;
|
|
var r = 0;
|
|
if (t >= 0x1000) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if (t >= 0x40) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if (t >= 0x8) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if (t >= 0x02) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
return r + t;
|
|
};
|
|
}
|
|
|
|
BN.prototype._zeroBits = function _zeroBits (w) {
|
|
// Short-cut
|
|
if (w === 0) return 26;
|
|
|
|
var t = w;
|
|
var r = 0;
|
|
if ((t & 0x1fff) === 0) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if ((t & 0x7f) === 0) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if ((t & 0xf) === 0) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if ((t & 0x3) === 0) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
if ((t & 0x1) === 0) {
|
|
r++;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
// Return number of used bits in a BN
|
|
BN.prototype.bitLength = function bitLength () {
|
|
var w = this.words[this.length - 1];
|
|
var hi = this._countBits(w);
|
|
return (this.length - 1) * 26 + hi;
|
|
};
|
|
|
|
function toBitArray (num) {
|
|
var w = new Array(num.bitLength());
|
|
|
|
for (var bit = 0; bit < w.length; bit++) {
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
w[bit] = (num.words[off] >>> wbit) & 0x01;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
// Number of trailing zero bits
|
|
BN.prototype.zeroBits = function zeroBits () {
|
|
if (this.isZero()) return 0;
|
|
|
|
var r = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var b = this._zeroBits(this.words[i]);
|
|
r += b;
|
|
if (b !== 26) break;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
BN.prototype.byteLength = function byteLength () {
|
|
return Math.ceil(this.bitLength() / 8);
|
|
};
|
|
|
|
BN.prototype.toTwos = function toTwos (width) {
|
|
if (this.negative !== 0) {
|
|
return this.abs().inotn(width).iaddn(1);
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.fromTwos = function fromTwos (width) {
|
|
if (this.testn(width - 1)) {
|
|
return this.notn(width).iaddn(1).ineg();
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.isNeg = function isNeg () {
|
|
return this.negative !== 0;
|
|
};
|
|
|
|
// Return negative clone of `this`
|
|
BN.prototype.neg = function neg () {
|
|
return this.clone().ineg();
|
|
};
|
|
|
|
BN.prototype.ineg = function ineg () {
|
|
if (!this.isZero()) {
|
|
this.negative ^= 1;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Or `num` with `this` in-place
|
|
BN.prototype.iuor = function iuor (num) {
|
|
while (this.length < num.length) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
|
|
for (var i = 0; i < num.length; i++) {
|
|
this.words[i] = this.words[i] | num.words[i];
|
|
}
|
|
|
|
return this._strip();
|
|
};
|
|
|
|
BN.prototype.ior = function ior (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuor(num);
|
|
};
|
|
|
|
// Or `num` with `this`
|
|
BN.prototype.or = function or (num) {
|
|
if (this.length > num.length) return this.clone().ior(num);
|
|
return num.clone().ior(this);
|
|
};
|
|
|
|
BN.prototype.uor = function uor (num) {
|
|
if (this.length > num.length) return this.clone().iuor(num);
|
|
return num.clone().iuor(this);
|
|
};
|
|
|
|
// And `num` with `this` in-place
|
|
BN.prototype.iuand = function iuand (num) {
|
|
// b = min-length(num, this)
|
|
var b;
|
|
if (this.length > num.length) {
|
|
b = num;
|
|
} else {
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = this.words[i] & num.words[i];
|
|
}
|
|
|
|
this.length = b.length;
|
|
|
|
return this._strip();
|
|
};
|
|
|
|
BN.prototype.iand = function iand (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuand(num);
|
|
};
|
|
|
|
// And `num` with `this`
|
|
BN.prototype.and = function and (num) {
|
|
if (this.length > num.length) return this.clone().iand(num);
|
|
return num.clone().iand(this);
|
|
};
|
|
|
|
BN.prototype.uand = function uand (num) {
|
|
if (this.length > num.length) return this.clone().iuand(num);
|
|
return num.clone().iuand(this);
|
|
};
|
|
|
|
// Xor `num` with `this` in-place
|
|
BN.prototype.iuxor = function iuxor (num) {
|
|
// a.length > b.length
|
|
var a;
|
|
var b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = a.words[i] ^ b.words[i];
|
|
}
|
|
|
|
if (this !== a) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = a.length;
|
|
|
|
return this._strip();
|
|
};
|
|
|
|
BN.prototype.ixor = function ixor (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuxor(num);
|
|
};
|
|
|
|
// Xor `num` with `this`
|
|
BN.prototype.xor = function xor (num) {
|
|
if (this.length > num.length) return this.clone().ixor(num);
|
|
return num.clone().ixor(this);
|
|
};
|
|
|
|
BN.prototype.uxor = function uxor (num) {
|
|
if (this.length > num.length) return this.clone().iuxor(num);
|
|
return num.clone().iuxor(this);
|
|
};
|
|
|
|
// Not ``this`` with ``width`` bitwidth
|
|
BN.prototype.inotn = function inotn (width) {
|
|
assert(typeof width === 'number' && width >= 0);
|
|
|
|
var bytesNeeded = Math.ceil(width / 26) | 0;
|
|
var bitsLeft = width % 26;
|
|
|
|
// Extend the buffer with leading zeroes
|
|
this._expand(bytesNeeded);
|
|
|
|
if (bitsLeft > 0) {
|
|
bytesNeeded--;
|
|
}
|
|
|
|
// Handle complete words
|
|
for (var i = 0; i < bytesNeeded; i++) {
|
|
this.words[i] = ~this.words[i] & 0x3ffffff;
|
|
}
|
|
|
|
// Handle the residue
|
|
if (bitsLeft > 0) {
|
|
this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
|
|
}
|
|
|
|
// And remove leading zeroes
|
|
return this._strip();
|
|
};
|
|
|
|
BN.prototype.notn = function notn (width) {
|
|
return this.clone().inotn(width);
|
|
};
|
|
|
|
// Set `bit` of `this`
|
|
BN.prototype.setn = function setn (bit, val) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
this._expand(off + 1);
|
|
|
|
if (val) {
|
|
this.words[off] = this.words[off] | (1 << wbit);
|
|
} else {
|
|
this.words[off] = this.words[off] & ~(1 << wbit);
|
|
}
|
|
|
|
return this._strip();
|
|
};
|
|
|
|
// Add `num` to `this` in-place
|
|
BN.prototype.iadd = function iadd (num) {
|
|
var r;
|
|
|
|
// negative + positive
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
this.negative = 0;
|
|
r = this.isub(num);
|
|
this.negative ^= 1;
|
|
return this._normSign();
|
|
|
|
// positive + negative
|
|
} else if (this.negative === 0 && num.negative !== 0) {
|
|
num.negative = 0;
|
|
r = this.isub(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
}
|
|
|
|
// a.length > b.length
|
|
var a, b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
|
|
this.length = a.length;
|
|
if (carry !== 0) {
|
|
this.words[this.length] = carry;
|
|
this.length++;
|
|
// Copy the rest of the words
|
|
} else if (a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Add `num` to `this`
|
|
BN.prototype.add = function add (num) {
|
|
var res;
|
|
if (num.negative !== 0 && this.negative === 0) {
|
|
num.negative = 0;
|
|
res = this.sub(num);
|
|
num.negative ^= 1;
|
|
return res;
|
|
} else if (num.negative === 0 && this.negative !== 0) {
|
|
this.negative = 0;
|
|
res = num.sub(this);
|
|
this.negative = 1;
|
|
return res;
|
|
}
|
|
|
|
if (this.length > num.length) return this.clone().iadd(num);
|
|
|
|
return num.clone().iadd(this);
|
|
};
|
|
|
|
// Subtract `num` from `this` in-place
|
|
BN.prototype.isub = function isub (num) {
|
|
// this - (-num) = this + num
|
|
if (num.negative !== 0) {
|
|
num.negative = 0;
|
|
var r = this.iadd(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
|
|
// -this - num = -(this + num)
|
|
} else if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iadd(num);
|
|
this.negative = 1;
|
|
return this._normSign();
|
|
}
|
|
|
|
// At this point both numbers are positive
|
|
var cmp = this.cmp(num);
|
|
|
|
// Optimization - zeroify
|
|
if (cmp === 0) {
|
|
this.negative = 0;
|
|
this.length = 1;
|
|
this.words[0] = 0;
|
|
return this;
|
|
}
|
|
|
|
// a > b
|
|
var a, b;
|
|
if (cmp > 0) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
|
|
// Copy rest of the words
|
|
if (carry === 0 && i < a.length && a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = Math.max(this.length, i);
|
|
|
|
if (a !== this) {
|
|
this.negative = 1;
|
|
}
|
|
|
|
return this._strip();
|
|
};
|
|
|
|
// Subtract `num` from `this`
|
|
BN.prototype.sub = function sub (num) {
|
|
return this.clone().isub(num);
|
|
};
|
|
|
|
function smallMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
var len = (self.length + num.length) | 0;
|
|
out.length = len;
|
|
len = (len - 1) | 0;
|
|
|
|
// Peel one iteration (compiler can't do it, because of code complexity)
|
|
var a = self.words[0] | 0;
|
|
var b = num.words[0] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
var carry = (r / 0x4000000) | 0;
|
|
out.words[0] = lo;
|
|
|
|
for (var k = 1; k < len; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = carry >>> 26;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = (k - j) | 0;
|
|
a = self.words[i] | 0;
|
|
b = num.words[j] | 0;
|
|
r = a * b + rword;
|
|
ncarry += (r / 0x4000000) | 0;
|
|
rword = r & 0x3ffffff;
|
|
}
|
|
out.words[k] = rword | 0;
|
|
carry = ncarry | 0;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry | 0;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out._strip();
|
|
}
|
|
|
|
// TODO(indutny): it may be reasonable to omit it for users who don't need
|
|
// to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
|
|
// multiplication (like elliptic secp256k1).
|
|
var comb10MulTo = function comb10MulTo (self, num, out) {
|
|
var a = self.words;
|
|
var b = num.words;
|
|
var o = out.words;
|
|
var c = 0;
|
|
var lo;
|
|
var mid;
|
|
var hi;
|
|
var a0 = a[0] | 0;
|
|
var al0 = a0 & 0x1fff;
|
|
var ah0 = a0 >>> 13;
|
|
var a1 = a[1] | 0;
|
|
var al1 = a1 & 0x1fff;
|
|
var ah1 = a1 >>> 13;
|
|
var a2 = a[2] | 0;
|
|
var al2 = a2 & 0x1fff;
|
|
var ah2 = a2 >>> 13;
|
|
var a3 = a[3] | 0;
|
|
var al3 = a3 & 0x1fff;
|
|
var ah3 = a3 >>> 13;
|
|
var a4 = a[4] | 0;
|
|
var al4 = a4 & 0x1fff;
|
|
var ah4 = a4 >>> 13;
|
|
var a5 = a[5] | 0;
|
|
var al5 = a5 & 0x1fff;
|
|
var ah5 = a5 >>> 13;
|
|
var a6 = a[6] | 0;
|
|
var al6 = a6 & 0x1fff;
|
|
var ah6 = a6 >>> 13;
|
|
var a7 = a[7] | 0;
|
|
var al7 = a7 & 0x1fff;
|
|
var ah7 = a7 >>> 13;
|
|
var a8 = a[8] | 0;
|
|
var al8 = a8 & 0x1fff;
|
|
var ah8 = a8 >>> 13;
|
|
var a9 = a[9] | 0;
|
|
var al9 = a9 & 0x1fff;
|
|
var ah9 = a9 >>> 13;
|
|
var b0 = b[0] | 0;
|
|
var bl0 = b0 & 0x1fff;
|
|
var bh0 = b0 >>> 13;
|
|
var b1 = b[1] | 0;
|
|
var bl1 = b1 & 0x1fff;
|
|
var bh1 = b1 >>> 13;
|
|
var b2 = b[2] | 0;
|
|
var bl2 = b2 & 0x1fff;
|
|
var bh2 = b2 >>> 13;
|
|
var b3 = b[3] | 0;
|
|
var bl3 = b3 & 0x1fff;
|
|
var bh3 = b3 >>> 13;
|
|
var b4 = b[4] | 0;
|
|
var bl4 = b4 & 0x1fff;
|
|
var bh4 = b4 >>> 13;
|
|
var b5 = b[5] | 0;
|
|
var bl5 = b5 & 0x1fff;
|
|
var bh5 = b5 >>> 13;
|
|
var b6 = b[6] | 0;
|
|
var bl6 = b6 & 0x1fff;
|
|
var bh6 = b6 >>> 13;
|
|
var b7 = b[7] | 0;
|
|
var bl7 = b7 & 0x1fff;
|
|
var bh7 = b7 >>> 13;
|
|
var b8 = b[8] | 0;
|
|
var bl8 = b8 & 0x1fff;
|
|
var bh8 = b8 >>> 13;
|
|
var b9 = b[9] | 0;
|
|
var bl9 = b9 & 0x1fff;
|
|
var bh9 = b9 >>> 13;
|
|
|
|
out.negative = self.negative ^ num.negative;
|
|
out.length = 19;
|
|
/* k = 0 */
|
|
lo = Math.imul(al0, bl0);
|
|
mid = Math.imul(al0, bh0);
|
|
mid = (mid + Math.imul(ah0, bl0)) | 0;
|
|
hi = Math.imul(ah0, bh0);
|
|
var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
|
|
w0 &= 0x3ffffff;
|
|
/* k = 1 */
|
|
lo = Math.imul(al1, bl0);
|
|
mid = Math.imul(al1, bh0);
|
|
mid = (mid + Math.imul(ah1, bl0)) | 0;
|
|
hi = Math.imul(ah1, bh0);
|
|
lo = (lo + Math.imul(al0, bl1)) | 0;
|
|
mid = (mid + Math.imul(al0, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh1)) | 0;
|
|
var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
|
|
w1 &= 0x3ffffff;
|
|
/* k = 2 */
|
|
lo = Math.imul(al2, bl0);
|
|
mid = Math.imul(al2, bh0);
|
|
mid = (mid + Math.imul(ah2, bl0)) | 0;
|
|
hi = Math.imul(ah2, bh0);
|
|
lo = (lo + Math.imul(al1, bl1)) | 0;
|
|
mid = (mid + Math.imul(al1, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh1)) | 0;
|
|
lo = (lo + Math.imul(al0, bl2)) | 0;
|
|
mid = (mid + Math.imul(al0, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh2)) | 0;
|
|
var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
|
|
w2 &= 0x3ffffff;
|
|
/* k = 3 */
|
|
lo = Math.imul(al3, bl0);
|
|
mid = Math.imul(al3, bh0);
|
|
mid = (mid + Math.imul(ah3, bl0)) | 0;
|
|
hi = Math.imul(ah3, bh0);
|
|
lo = (lo + Math.imul(al2, bl1)) | 0;
|
|
mid = (mid + Math.imul(al2, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh1)) | 0;
|
|
lo = (lo + Math.imul(al1, bl2)) | 0;
|
|
mid = (mid + Math.imul(al1, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh2)) | 0;
|
|
lo = (lo + Math.imul(al0, bl3)) | 0;
|
|
mid = (mid + Math.imul(al0, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh3)) | 0;
|
|
var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
|
|
w3 &= 0x3ffffff;
|
|
/* k = 4 */
|
|
lo = Math.imul(al4, bl0);
|
|
mid = Math.imul(al4, bh0);
|
|
mid = (mid + Math.imul(ah4, bl0)) | 0;
|
|
hi = Math.imul(ah4, bh0);
|
|
lo = (lo + Math.imul(al3, bl1)) | 0;
|
|
mid = (mid + Math.imul(al3, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh1)) | 0;
|
|
lo = (lo + Math.imul(al2, bl2)) | 0;
|
|
mid = (mid + Math.imul(al2, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh2)) | 0;
|
|
lo = (lo + Math.imul(al1, bl3)) | 0;
|
|
mid = (mid + Math.imul(al1, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh3)) | 0;
|
|
lo = (lo + Math.imul(al0, bl4)) | 0;
|
|
mid = (mid + Math.imul(al0, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh4)) | 0;
|
|
var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
|
|
w4 &= 0x3ffffff;
|
|
/* k = 5 */
|
|
lo = Math.imul(al5, bl0);
|
|
mid = Math.imul(al5, bh0);
|
|
mid = (mid + Math.imul(ah5, bl0)) | 0;
|
|
hi = Math.imul(ah5, bh0);
|
|
lo = (lo + Math.imul(al4, bl1)) | 0;
|
|
mid = (mid + Math.imul(al4, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh1)) | 0;
|
|
lo = (lo + Math.imul(al3, bl2)) | 0;
|
|
mid = (mid + Math.imul(al3, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh2)) | 0;
|
|
lo = (lo + Math.imul(al2, bl3)) | 0;
|
|
mid = (mid + Math.imul(al2, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh3)) | 0;
|
|
lo = (lo + Math.imul(al1, bl4)) | 0;
|
|
mid = (mid + Math.imul(al1, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh4)) | 0;
|
|
lo = (lo + Math.imul(al0, bl5)) | 0;
|
|
mid = (mid + Math.imul(al0, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh5)) | 0;
|
|
var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
|
|
w5 &= 0x3ffffff;
|
|
/* k = 6 */
|
|
lo = Math.imul(al6, bl0);
|
|
mid = Math.imul(al6, bh0);
|
|
mid = (mid + Math.imul(ah6, bl0)) | 0;
|
|
hi = Math.imul(ah6, bh0);
|
|
lo = (lo + Math.imul(al5, bl1)) | 0;
|
|
mid = (mid + Math.imul(al5, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh1)) | 0;
|
|
lo = (lo + Math.imul(al4, bl2)) | 0;
|
|
mid = (mid + Math.imul(al4, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh2)) | 0;
|
|
lo = (lo + Math.imul(al3, bl3)) | 0;
|
|
mid = (mid + Math.imul(al3, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh3)) | 0;
|
|
lo = (lo + Math.imul(al2, bl4)) | 0;
|
|
mid = (mid + Math.imul(al2, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh4)) | 0;
|
|
lo = (lo + Math.imul(al1, bl5)) | 0;
|
|
mid = (mid + Math.imul(al1, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh5)) | 0;
|
|
lo = (lo + Math.imul(al0, bl6)) | 0;
|
|
mid = (mid + Math.imul(al0, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh6)) | 0;
|
|
var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
|
|
w6 &= 0x3ffffff;
|
|
/* k = 7 */
|
|
lo = Math.imul(al7, bl0);
|
|
mid = Math.imul(al7, bh0);
|
|
mid = (mid + Math.imul(ah7, bl0)) | 0;
|
|
hi = Math.imul(ah7, bh0);
|
|
lo = (lo + Math.imul(al6, bl1)) | 0;
|
|
mid = (mid + Math.imul(al6, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh1)) | 0;
|
|
lo = (lo + Math.imul(al5, bl2)) | 0;
|
|
mid = (mid + Math.imul(al5, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh2)) | 0;
|
|
lo = (lo + Math.imul(al4, bl3)) | 0;
|
|
mid = (mid + Math.imul(al4, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh3)) | 0;
|
|
lo = (lo + Math.imul(al3, bl4)) | 0;
|
|
mid = (mid + Math.imul(al3, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh4)) | 0;
|
|
lo = (lo + Math.imul(al2, bl5)) | 0;
|
|
mid = (mid + Math.imul(al2, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh5)) | 0;
|
|
lo = (lo + Math.imul(al1, bl6)) | 0;
|
|
mid = (mid + Math.imul(al1, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh6)) | 0;
|
|
lo = (lo + Math.imul(al0, bl7)) | 0;
|
|
mid = (mid + Math.imul(al0, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh7)) | 0;
|
|
var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
|
|
w7 &= 0x3ffffff;
|
|
/* k = 8 */
|
|
lo = Math.imul(al8, bl0);
|
|
mid = Math.imul(al8, bh0);
|
|
mid = (mid + Math.imul(ah8, bl0)) | 0;
|
|
hi = Math.imul(ah8, bh0);
|
|
lo = (lo + Math.imul(al7, bl1)) | 0;
|
|
mid = (mid + Math.imul(al7, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh1)) | 0;
|
|
lo = (lo + Math.imul(al6, bl2)) | 0;
|
|
mid = (mid + Math.imul(al6, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh2)) | 0;
|
|
lo = (lo + Math.imul(al5, bl3)) | 0;
|
|
mid = (mid + Math.imul(al5, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh3)) | 0;
|
|
lo = (lo + Math.imul(al4, bl4)) | 0;
|
|
mid = (mid + Math.imul(al4, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh4)) | 0;
|
|
lo = (lo + Math.imul(al3, bl5)) | 0;
|
|
mid = (mid + Math.imul(al3, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh5)) | 0;
|
|
lo = (lo + Math.imul(al2, bl6)) | 0;
|
|
mid = (mid + Math.imul(al2, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh6)) | 0;
|
|
lo = (lo + Math.imul(al1, bl7)) | 0;
|
|
mid = (mid + Math.imul(al1, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh7)) | 0;
|
|
lo = (lo + Math.imul(al0, bl8)) | 0;
|
|
mid = (mid + Math.imul(al0, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh8)) | 0;
|
|
var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
|
|
w8 &= 0x3ffffff;
|
|
/* k = 9 */
|
|
lo = Math.imul(al9, bl0);
|
|
mid = Math.imul(al9, bh0);
|
|
mid = (mid + Math.imul(ah9, bl0)) | 0;
|
|
hi = Math.imul(ah9, bh0);
|
|
lo = (lo + Math.imul(al8, bl1)) | 0;
|
|
mid = (mid + Math.imul(al8, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh1)) | 0;
|
|
lo = (lo + Math.imul(al7, bl2)) | 0;
|
|
mid = (mid + Math.imul(al7, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh2)) | 0;
|
|
lo = (lo + Math.imul(al6, bl3)) | 0;
|
|
mid = (mid + Math.imul(al6, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh3)) | 0;
|
|
lo = (lo + Math.imul(al5, bl4)) | 0;
|
|
mid = (mid + Math.imul(al5, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh4)) | 0;
|
|
lo = (lo + Math.imul(al4, bl5)) | 0;
|
|
mid = (mid + Math.imul(al4, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh5)) | 0;
|
|
lo = (lo + Math.imul(al3, bl6)) | 0;
|
|
mid = (mid + Math.imul(al3, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh6)) | 0;
|
|
lo = (lo + Math.imul(al2, bl7)) | 0;
|
|
mid = (mid + Math.imul(al2, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh7)) | 0;
|
|
lo = (lo + Math.imul(al1, bl8)) | 0;
|
|
mid = (mid + Math.imul(al1, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh8)) | 0;
|
|
lo = (lo + Math.imul(al0, bl9)) | 0;
|
|
mid = (mid + Math.imul(al0, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh9)) | 0;
|
|
var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
|
|
w9 &= 0x3ffffff;
|
|
/* k = 10 */
|
|
lo = Math.imul(al9, bl1);
|
|
mid = Math.imul(al9, bh1);
|
|
mid = (mid + Math.imul(ah9, bl1)) | 0;
|
|
hi = Math.imul(ah9, bh1);
|
|
lo = (lo + Math.imul(al8, bl2)) | 0;
|
|
mid = (mid + Math.imul(al8, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh2)) | 0;
|
|
lo = (lo + Math.imul(al7, bl3)) | 0;
|
|
mid = (mid + Math.imul(al7, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh3)) | 0;
|
|
lo = (lo + Math.imul(al6, bl4)) | 0;
|
|
mid = (mid + Math.imul(al6, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh4)) | 0;
|
|
lo = (lo + Math.imul(al5, bl5)) | 0;
|
|
mid = (mid + Math.imul(al5, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh5)) | 0;
|
|
lo = (lo + Math.imul(al4, bl6)) | 0;
|
|
mid = (mid + Math.imul(al4, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh6)) | 0;
|
|
lo = (lo + Math.imul(al3, bl7)) | 0;
|
|
mid = (mid + Math.imul(al3, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh7)) | 0;
|
|
lo = (lo + Math.imul(al2, bl8)) | 0;
|
|
mid = (mid + Math.imul(al2, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh8)) | 0;
|
|
lo = (lo + Math.imul(al1, bl9)) | 0;
|
|
mid = (mid + Math.imul(al1, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh9)) | 0;
|
|
var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
|
|
w10 &= 0x3ffffff;
|
|
/* k = 11 */
|
|
lo = Math.imul(al9, bl2);
|
|
mid = Math.imul(al9, bh2);
|
|
mid = (mid + Math.imul(ah9, bl2)) | 0;
|
|
hi = Math.imul(ah9, bh2);
|
|
lo = (lo + Math.imul(al8, bl3)) | 0;
|
|
mid = (mid + Math.imul(al8, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh3)) | 0;
|
|
lo = (lo + Math.imul(al7, bl4)) | 0;
|
|
mid = (mid + Math.imul(al7, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh4)) | 0;
|
|
lo = (lo + Math.imul(al6, bl5)) | 0;
|
|
mid = (mid + Math.imul(al6, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh5)) | 0;
|
|
lo = (lo + Math.imul(al5, bl6)) | 0;
|
|
mid = (mid + Math.imul(al5, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh6)) | 0;
|
|
lo = (lo + Math.imul(al4, bl7)) | 0;
|
|
mid = (mid + Math.imul(al4, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh7)) | 0;
|
|
lo = (lo + Math.imul(al3, bl8)) | 0;
|
|
mid = (mid + Math.imul(al3, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh8)) | 0;
|
|
lo = (lo + Math.imul(al2, bl9)) | 0;
|
|
mid = (mid + Math.imul(al2, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh9)) | 0;
|
|
var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
|
|
w11 &= 0x3ffffff;
|
|
/* k = 12 */
|
|
lo = Math.imul(al9, bl3);
|
|
mid = Math.imul(al9, bh3);
|
|
mid = (mid + Math.imul(ah9, bl3)) | 0;
|
|
hi = Math.imul(ah9, bh3);
|
|
lo = (lo + Math.imul(al8, bl4)) | 0;
|
|
mid = (mid + Math.imul(al8, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh4)) | 0;
|
|
lo = (lo + Math.imul(al7, bl5)) | 0;
|
|
mid = (mid + Math.imul(al7, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh5)) | 0;
|
|
lo = (lo + Math.imul(al6, bl6)) | 0;
|
|
mid = (mid + Math.imul(al6, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh6)) | 0;
|
|
lo = (lo + Math.imul(al5, bl7)) | 0;
|
|
mid = (mid + Math.imul(al5, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh7)) | 0;
|
|
lo = (lo + Math.imul(al4, bl8)) | 0;
|
|
mid = (mid + Math.imul(al4, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh8)) | 0;
|
|
lo = (lo + Math.imul(al3, bl9)) | 0;
|
|
mid = (mid + Math.imul(al3, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh9)) | 0;
|
|
var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
|
|
w12 &= 0x3ffffff;
|
|
/* k = 13 */
|
|
lo = Math.imul(al9, bl4);
|
|
mid = Math.imul(al9, bh4);
|
|
mid = (mid + Math.imul(ah9, bl4)) | 0;
|
|
hi = Math.imul(ah9, bh4);
|
|
lo = (lo + Math.imul(al8, bl5)) | 0;
|
|
mid = (mid + Math.imul(al8, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh5)) | 0;
|
|
lo = (lo + Math.imul(al7, bl6)) | 0;
|
|
mid = (mid + Math.imul(al7, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh6)) | 0;
|
|
lo = (lo + Math.imul(al6, bl7)) | 0;
|
|
mid = (mid + Math.imul(al6, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh7)) | 0;
|
|
lo = (lo + Math.imul(al5, bl8)) | 0;
|
|
mid = (mid + Math.imul(al5, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh8)) | 0;
|
|
lo = (lo + Math.imul(al4, bl9)) | 0;
|
|
mid = (mid + Math.imul(al4, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh9)) | 0;
|
|
var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
|
|
w13 &= 0x3ffffff;
|
|
/* k = 14 */
|
|
lo = Math.imul(al9, bl5);
|
|
mid = Math.imul(al9, bh5);
|
|
mid = (mid + Math.imul(ah9, bl5)) | 0;
|
|
hi = Math.imul(ah9, bh5);
|
|
lo = (lo + Math.imul(al8, bl6)) | 0;
|
|
mid = (mid + Math.imul(al8, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh6)) | 0;
|
|
lo = (lo + Math.imul(al7, bl7)) | 0;
|
|
mid = (mid + Math.imul(al7, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh7)) | 0;
|
|
lo = (lo + Math.imul(al6, bl8)) | 0;
|
|
mid = (mid + Math.imul(al6, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh8)) | 0;
|
|
lo = (lo + Math.imul(al5, bl9)) | 0;
|
|
mid = (mid + Math.imul(al5, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh9)) | 0;
|
|
var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
|
|
w14 &= 0x3ffffff;
|
|
/* k = 15 */
|
|
lo = Math.imul(al9, bl6);
|
|
mid = Math.imul(al9, bh6);
|
|
mid = (mid + Math.imul(ah9, bl6)) | 0;
|
|
hi = Math.imul(ah9, bh6);
|
|
lo = (lo + Math.imul(al8, bl7)) | 0;
|
|
mid = (mid + Math.imul(al8, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh7)) | 0;
|
|
lo = (lo + Math.imul(al7, bl8)) | 0;
|
|
mid = (mid + Math.imul(al7, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh8)) | 0;
|
|
lo = (lo + Math.imul(al6, bl9)) | 0;
|
|
mid = (mid + Math.imul(al6, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh9)) | 0;
|
|
var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
|
|
w15 &= 0x3ffffff;
|
|
/* k = 16 */
|
|
lo = Math.imul(al9, bl7);
|
|
mid = Math.imul(al9, bh7);
|
|
mid = (mid + Math.imul(ah9, bl7)) | 0;
|
|
hi = Math.imul(ah9, bh7);
|
|
lo = (lo + Math.imul(al8, bl8)) | 0;
|
|
mid = (mid + Math.imul(al8, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh8)) | 0;
|
|
lo = (lo + Math.imul(al7, bl9)) | 0;
|
|
mid = (mid + Math.imul(al7, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh9)) | 0;
|
|
var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
|
|
w16 &= 0x3ffffff;
|
|
/* k = 17 */
|
|
lo = Math.imul(al9, bl8);
|
|
mid = Math.imul(al9, bh8);
|
|
mid = (mid + Math.imul(ah9, bl8)) | 0;
|
|
hi = Math.imul(ah9, bh8);
|
|
lo = (lo + Math.imul(al8, bl9)) | 0;
|
|
mid = (mid + Math.imul(al8, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh9)) | 0;
|
|
var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
|
|
w17 &= 0x3ffffff;
|
|
/* k = 18 */
|
|
lo = Math.imul(al9, bl9);
|
|
mid = Math.imul(al9, bh9);
|
|
mid = (mid + Math.imul(ah9, bl9)) | 0;
|
|
hi = Math.imul(ah9, bh9);
|
|
var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
|
|
w18 &= 0x3ffffff;
|
|
o[0] = w0;
|
|
o[1] = w1;
|
|
o[2] = w2;
|
|
o[3] = w3;
|
|
o[4] = w4;
|
|
o[5] = w5;
|
|
o[6] = w6;
|
|
o[7] = w7;
|
|
o[8] = w8;
|
|
o[9] = w9;
|
|
o[10] = w10;
|
|
o[11] = w11;
|
|
o[12] = w12;
|
|
o[13] = w13;
|
|
o[14] = w14;
|
|
o[15] = w15;
|
|
o[16] = w16;
|
|
o[17] = w17;
|
|
o[18] = w18;
|
|
if (c !== 0) {
|
|
o[19] = c;
|
|
out.length++;
|
|
}
|
|
return out;
|
|
};
|
|
|
|
// Polyfill comb
|
|
if (!Math.imul) {
|
|
comb10MulTo = smallMulTo;
|
|
}
|
|
|
|
function bigMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
out.length = self.length + num.length;
|
|
|
|
var carry = 0;
|
|
var hncarry = 0;
|
|
for (var k = 0; k < out.length - 1; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = hncarry;
|
|
hncarry = 0;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = k - j;
|
|
var a = self.words[i] | 0;
|
|
var b = num.words[j] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
|
|
lo = (lo + rword) | 0;
|
|
rword = lo & 0x3ffffff;
|
|
ncarry = (ncarry + (lo >>> 26)) | 0;
|
|
|
|
hncarry += ncarry >>> 26;
|
|
ncarry &= 0x3ffffff;
|
|
}
|
|
out.words[k] = rword;
|
|
carry = ncarry;
|
|
ncarry = hncarry;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out._strip();
|
|
}
|
|
|
|
function jumboMulTo (self, num, out) {
|
|
// Temporary disable, see https://github.com/indutny/bn.js/issues/211
|
|
// var fftm = new FFTM();
|
|
// return fftm.mulp(self, num, out);
|
|
return bigMulTo(self, num, out);
|
|
}
|
|
|
|
BN.prototype.mulTo = function mulTo (num, out) {
|
|
var res;
|
|
var len = this.length + num.length;
|
|
if (this.length === 10 && num.length === 10) {
|
|
res = comb10MulTo(this, num, out);
|
|
} else if (len < 63) {
|
|
res = smallMulTo(this, num, out);
|
|
} else if (len < 1024) {
|
|
res = bigMulTo(this, num, out);
|
|
} else {
|
|
res = jumboMulTo(this, num, out);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Cooley-Tukey algorithm for FFT
|
|
// slightly revisited to rely on looping instead of recursion
|
|
|
|
function FFTM (x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
FFTM.prototype.makeRBT = function makeRBT (N) {
|
|
var t = new Array(N);
|
|
var l = BN.prototype._countBits(N) - 1;
|
|
for (var i = 0; i < N; i++) {
|
|
t[i] = this.revBin(i, l, N);
|
|
}
|
|
|
|
return t;
|
|
};
|
|
|
|
// Returns binary-reversed representation of `x`
|
|
FFTM.prototype.revBin = function revBin (x, l, N) {
|
|
if (x === 0 || x === N - 1) return x;
|
|
|
|
var rb = 0;
|
|
for (var i = 0; i < l; i++) {
|
|
rb |= (x & 1) << (l - i - 1);
|
|
x >>= 1;
|
|
}
|
|
|
|
return rb;
|
|
};
|
|
|
|
// Performs "tweedling" phase, therefore 'emulating'
|
|
// behaviour of the recursive algorithm
|
|
FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
|
|
for (var i = 0; i < N; i++) {
|
|
rtws[i] = rws[rbt[i]];
|
|
itws[i] = iws[rbt[i]];
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
|
|
this.permute(rbt, rws, iws, rtws, itws, N);
|
|
|
|
for (var s = 1; s < N; s <<= 1) {
|
|
var l = s << 1;
|
|
|
|
var rtwdf = Math.cos(2 * Math.PI / l);
|
|
var itwdf = Math.sin(2 * Math.PI / l);
|
|
|
|
for (var p = 0; p < N; p += l) {
|
|
var rtwdf_ = rtwdf;
|
|
var itwdf_ = itwdf;
|
|
|
|
for (var j = 0; j < s; j++) {
|
|
var re = rtws[p + j];
|
|
var ie = itws[p + j];
|
|
|
|
var ro = rtws[p + j + s];
|
|
var io = itws[p + j + s];
|
|
|
|
var rx = rtwdf_ * ro - itwdf_ * io;
|
|
|
|
io = rtwdf_ * io + itwdf_ * ro;
|
|
ro = rx;
|
|
|
|
rtws[p + j] = re + ro;
|
|
itws[p + j] = ie + io;
|
|
|
|
rtws[p + j + s] = re - ro;
|
|
itws[p + j + s] = ie - io;
|
|
|
|
/* jshint maxdepth : false */
|
|
if (j !== l) {
|
|
rx = rtwdf * rtwdf_ - itwdf * itwdf_;
|
|
|
|
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
|
|
rtwdf_ = rx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
|
|
var N = Math.max(m, n) | 1;
|
|
var odd = N & 1;
|
|
var i = 0;
|
|
for (N = N / 2 | 0; N; N = N >>> 1) {
|
|
i++;
|
|
}
|
|
|
|
return 1 << i + 1 + odd;
|
|
};
|
|
|
|
FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
|
|
if (N <= 1) return;
|
|
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var t = rws[i];
|
|
|
|
rws[i] = rws[N - i - 1];
|
|
rws[N - i - 1] = t;
|
|
|
|
t = iws[i];
|
|
|
|
iws[i] = -iws[N - i - 1];
|
|
iws[N - i - 1] = -t;
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.normalize13b = function normalize13b (ws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
|
|
Math.round(ws[2 * i] / N) +
|
|
carry;
|
|
|
|
ws[i] = w & 0x3ffffff;
|
|
|
|
if (w < 0x4000000) {
|
|
carry = 0;
|
|
} else {
|
|
carry = w / 0x4000000 | 0;
|
|
}
|
|
}
|
|
|
|
return ws;
|
|
};
|
|
|
|
FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < len; i++) {
|
|
carry = carry + (ws[i] | 0);
|
|
|
|
rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
|
|
rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
|
|
}
|
|
|
|
// Pad with zeroes
|
|
for (i = 2 * len; i < N; ++i) {
|
|
rws[i] = 0;
|
|
}
|
|
|
|
assert(carry === 0);
|
|
assert((carry & ~0x1fff) === 0);
|
|
};
|
|
|
|
FFTM.prototype.stub = function stub (N) {
|
|
var ph = new Array(N);
|
|
for (var i = 0; i < N; i++) {
|
|
ph[i] = 0;
|
|
}
|
|
|
|
return ph;
|
|
};
|
|
|
|
FFTM.prototype.mulp = function mulp (x, y, out) {
|
|
var N = 2 * this.guessLen13b(x.length, y.length);
|
|
|
|
var rbt = this.makeRBT(N);
|
|
|
|
var _ = this.stub(N);
|
|
|
|
var rws = new Array(N);
|
|
var rwst = new Array(N);
|
|
var iwst = new Array(N);
|
|
|
|
var nrws = new Array(N);
|
|
var nrwst = new Array(N);
|
|
var niwst = new Array(N);
|
|
|
|
var rmws = out.words;
|
|
rmws.length = N;
|
|
|
|
this.convert13b(x.words, x.length, rws, N);
|
|
this.convert13b(y.words, y.length, nrws, N);
|
|
|
|
this.transform(rws, _, rwst, iwst, N, rbt);
|
|
this.transform(nrws, _, nrwst, niwst, N, rbt);
|
|
|
|
for (var i = 0; i < N; i++) {
|
|
var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
|
|
iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
|
|
rwst[i] = rx;
|
|
}
|
|
|
|
this.conjugate(rwst, iwst, N);
|
|
this.transform(rwst, iwst, rmws, _, N, rbt);
|
|
this.conjugate(rmws, _, N);
|
|
this.normalize13b(rmws, N);
|
|
|
|
out.negative = x.negative ^ y.negative;
|
|
out.length = x.length + y.length;
|
|
return out._strip();
|
|
};
|
|
|
|
// Multiply `this` by `num`
|
|
BN.prototype.mul = function mul (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return this.mulTo(num, out);
|
|
};
|
|
|
|
// Multiply employing FFT
|
|
BN.prototype.mulf = function mulf (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return jumboMulTo(this, num, out);
|
|
};
|
|
|
|
// In-place Multiplication
|
|
BN.prototype.imul = function imul (num) {
|
|
return this.clone().mulTo(num, this);
|
|
};
|
|
|
|
BN.prototype.imuln = function imuln (num) {
|
|
var isNegNum = num < 0;
|
|
if (isNegNum) num = -num;
|
|
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
|
|
// Carry
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = (this.words[i] | 0) * num;
|
|
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
|
|
carry >>= 26;
|
|
carry += (w / 0x4000000) | 0;
|
|
// NOTE: lo is 27bit maximum
|
|
carry += lo >>> 26;
|
|
this.words[i] = lo & 0x3ffffff;
|
|
}
|
|
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
|
|
return isNegNum ? this.ineg() : this;
|
|
};
|
|
|
|
BN.prototype.muln = function muln (num) {
|
|
return this.clone().imuln(num);
|
|
};
|
|
|
|
// `this` * `this`
|
|
BN.prototype.sqr = function sqr () {
|
|
return this.mul(this);
|
|
};
|
|
|
|
// `this` * `this` in-place
|
|
BN.prototype.isqr = function isqr () {
|
|
return this.imul(this.clone());
|
|
};
|
|
|
|
// Math.pow(`this`, `num`)
|
|
BN.prototype.pow = function pow (num) {
|
|
var w = toBitArray(num);
|
|
if (w.length === 0) return new BN(1);
|
|
|
|
// Skip leading zeroes
|
|
var res = this;
|
|
for (var i = 0; i < w.length; i++, res = res.sqr()) {
|
|
if (w[i] !== 0) break;
|
|
}
|
|
|
|
if (++i < w.length) {
|
|
for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
|
|
if (w[i] === 0) continue;
|
|
|
|
res = res.mul(q);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Shift-left in-place
|
|
BN.prototype.iushln = function iushln (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
|
|
var i;
|
|
|
|
if (r !== 0) {
|
|
var carry = 0;
|
|
|
|
for (i = 0; i < this.length; i++) {
|
|
var newCarry = this.words[i] & carryMask;
|
|
var c = ((this.words[i] | 0) - newCarry) << r;
|
|
this.words[i] = c | carry;
|
|
carry = newCarry >>> (26 - r);
|
|
}
|
|
|
|
if (carry) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
}
|
|
|
|
if (s !== 0) {
|
|
for (i = this.length - 1; i >= 0; i--) {
|
|
this.words[i + s] = this.words[i];
|
|
}
|
|
|
|
for (i = 0; i < s; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
this.length += s;
|
|
}
|
|
|
|
return this._strip();
|
|
};
|
|
|
|
BN.prototype.ishln = function ishln (bits) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushln(bits);
|
|
};
|
|
|
|
// Shift-right in-place
|
|
// NOTE: `hint` is a lowest bit before trailing zeroes
|
|
// NOTE: if `extended` is present - it will be filled with destroyed bits
|
|
BN.prototype.iushrn = function iushrn (bits, hint, extended) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var h;
|
|
if (hint) {
|
|
h = (hint - (hint % 26)) / 26;
|
|
} else {
|
|
h = 0;
|
|
}
|
|
|
|
var r = bits % 26;
|
|
var s = Math.min((bits - r) / 26, this.length);
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
var maskedWords = extended;
|
|
|
|
h -= s;
|
|
h = Math.max(0, h);
|
|
|
|
// Extended mode, copy masked part
|
|
if (maskedWords) {
|
|
for (var i = 0; i < s; i++) {
|
|
maskedWords.words[i] = this.words[i];
|
|
}
|
|
maskedWords.length = s;
|
|
}
|
|
|
|
if (s === 0) {
|
|
// No-op, we should not move anything at all
|
|
} else if (this.length > s) {
|
|
this.length -= s;
|
|
for (i = 0; i < this.length; i++) {
|
|
this.words[i] = this.words[i + s];
|
|
}
|
|
} else {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
|
|
var word = this.words[i] | 0;
|
|
this.words[i] = (carry << (26 - r)) | (word >>> r);
|
|
carry = word & mask;
|
|
}
|
|
|
|
// Push carried bits as a mask
|
|
if (maskedWords && carry !== 0) {
|
|
maskedWords.words[maskedWords.length++] = carry;
|
|
}
|
|
|
|
if (this.length === 0) {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
return this._strip();
|
|
};
|
|
|
|
BN.prototype.ishrn = function ishrn (bits, hint, extended) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushrn(bits, hint, extended);
|
|
};
|
|
|
|
// Shift-left
|
|
BN.prototype.shln = function shln (bits) {
|
|
return this.clone().ishln(bits);
|
|
};
|
|
|
|
BN.prototype.ushln = function ushln (bits) {
|
|
return this.clone().iushln(bits);
|
|
};
|
|
|
|
// Shift-right
|
|
BN.prototype.shrn = function shrn (bits) {
|
|
return this.clone().ishrn(bits);
|
|
};
|
|
|
|
BN.prototype.ushrn = function ushrn (bits) {
|
|
return this.clone().iushrn(bits);
|
|
};
|
|
|
|
// Test if n bit is set
|
|
BN.prototype.testn = function testn (bit) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) return false;
|
|
|
|
// Check bit and return
|
|
var w = this.words[s];
|
|
|
|
return !!(w & q);
|
|
};
|
|
|
|
// Return only lowers bits of number (in-place)
|
|
BN.prototype.imaskn = function imaskn (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
|
|
assert(this.negative === 0, 'imaskn works only with positive numbers');
|
|
|
|
if (this.length <= s) {
|
|
return this;
|
|
}
|
|
|
|
if (r !== 0) {
|
|
s++;
|
|
}
|
|
this.length = Math.min(s, this.length);
|
|
|
|
if (r !== 0) {
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
this.words[this.length - 1] &= mask;
|
|
}
|
|
|
|
return this._strip();
|
|
};
|
|
|
|
// Return only lowers bits of number
|
|
BN.prototype.maskn = function maskn (bits) {
|
|
return this.clone().imaskn(bits);
|
|
};
|
|
|
|
// Add plain number `num` to `this`
|
|
BN.prototype.iaddn = function iaddn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.isubn(-num);
|
|
|
|
// Possible sign change
|
|
if (this.negative !== 0) {
|
|
if (this.length === 1 && (this.words[0] | 0) <= num) {
|
|
this.words[0] = num - (this.words[0] | 0);
|
|
this.negative = 0;
|
|
return this;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.isubn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
// Add without checks
|
|
return this._iaddn(num);
|
|
};
|
|
|
|
BN.prototype._iaddn = function _iaddn (num) {
|
|
this.words[0] += num;
|
|
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
|
|
this.words[i] -= 0x4000000;
|
|
if (i === this.length - 1) {
|
|
this.words[i + 1] = 1;
|
|
} else {
|
|
this.words[i + 1]++;
|
|
}
|
|
}
|
|
this.length = Math.max(this.length, i + 1);
|
|
|
|
return this;
|
|
};
|
|
|
|
// Subtract plain number `num` from `this`
|
|
BN.prototype.isubn = function isubn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.iaddn(-num);
|
|
|
|
if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iaddn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
this.words[0] -= num;
|
|
|
|
if (this.length === 1 && this.words[0] < 0) {
|
|
this.words[0] = -this.words[0];
|
|
this.negative = 1;
|
|
} else {
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
|
|
this.words[i] += 0x4000000;
|
|
this.words[i + 1] -= 1;
|
|
}
|
|
}
|
|
|
|
return this._strip();
|
|
};
|
|
|
|
BN.prototype.addn = function addn (num) {
|
|
return this.clone().iaddn(num);
|
|
};
|
|
|
|
BN.prototype.subn = function subn (num) {
|
|
return this.clone().isubn(num);
|
|
};
|
|
|
|
BN.prototype.iabs = function iabs () {
|
|
this.negative = 0;
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.abs = function abs () {
|
|
return this.clone().iabs();
|
|
};
|
|
|
|
BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
|
|
var len = num.length + shift;
|
|
var i;
|
|
|
|
this._expand(len);
|
|
|
|
var w;
|
|
var carry = 0;
|
|
for (i = 0; i < num.length; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
var right = (num.words[i] | 0) * mul;
|
|
w -= right & 0x3ffffff;
|
|
carry = (w >> 26) - ((right / 0x4000000) | 0);
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
for (; i < this.length - shift; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
|
|
if (carry === 0) return this._strip();
|
|
|
|
// Subtraction overflow
|
|
assert(carry === -1);
|
|
carry = 0;
|
|
for (i = 0; i < this.length; i++) {
|
|
w = -(this.words[i] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i] = w & 0x3ffffff;
|
|
}
|
|
this.negative = 1;
|
|
|
|
return this._strip();
|
|
};
|
|
|
|
BN.prototype._wordDiv = function _wordDiv (num, mode) {
|
|
var shift = this.length - num.length;
|
|
|
|
var a = this.clone();
|
|
var b = num;
|
|
|
|
// Normalize
|
|
var bhi = b.words[b.length - 1] | 0;
|
|
var bhiBits = this._countBits(bhi);
|
|
shift = 26 - bhiBits;
|
|
if (shift !== 0) {
|
|
b = b.ushln(shift);
|
|
a.iushln(shift);
|
|
bhi = b.words[b.length - 1] | 0;
|
|
}
|
|
|
|
// Initialize quotient
|
|
var m = a.length - b.length;
|
|
var q;
|
|
|
|
if (mode !== 'mod') {
|
|
q = new BN(null);
|
|
q.length = m + 1;
|
|
q.words = new Array(q.length);
|
|
for (var i = 0; i < q.length; i++) {
|
|
q.words[i] = 0;
|
|
}
|
|
}
|
|
|
|
var diff = a.clone()._ishlnsubmul(b, 1, m);
|
|
if (diff.negative === 0) {
|
|
a = diff;
|
|
if (q) {
|
|
q.words[m] = 1;
|
|
}
|
|
}
|
|
|
|
for (var j = m - 1; j >= 0; j--) {
|
|
var qj = (a.words[b.length + j] | 0) * 0x4000000 +
|
|
(a.words[b.length + j - 1] | 0);
|
|
|
|
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
|
|
// (0x7ffffff)
|
|
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
|
|
|
|
a._ishlnsubmul(b, qj, j);
|
|
while (a.negative !== 0) {
|
|
qj--;
|
|
a.negative = 0;
|
|
a._ishlnsubmul(b, 1, j);
|
|
if (!a.isZero()) {
|
|
a.negative ^= 1;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.words[j] = qj;
|
|
}
|
|
}
|
|
if (q) {
|
|
q._strip();
|
|
}
|
|
a._strip();
|
|
|
|
// Denormalize
|
|
if (mode !== 'div' && shift !== 0) {
|
|
a.iushrn(shift);
|
|
}
|
|
|
|
return {
|
|
div: q || null,
|
|
mod: a
|
|
};
|
|
};
|
|
|
|
// NOTE: 1) `mode` can be set to `mod` to request mod only,
|
|
// to `div` to request div only, or be absent to
|
|
// request both div & mod
|
|
// 2) `positive` is true if unsigned mod is requested
|
|
BN.prototype.divmod = function divmod (num, mode, positive) {
|
|
assert(!num.isZero());
|
|
|
|
if (this.isZero()) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: new BN(0)
|
|
};
|
|
}
|
|
|
|
var div, mod, res;
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
res = this.neg().divmod(num, mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.iadd(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
if (this.negative === 0 && num.negative !== 0) {
|
|
res = this.divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: res.mod
|
|
};
|
|
}
|
|
|
|
if ((this.negative & num.negative) !== 0) {
|
|
res = this.neg().divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.isub(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: res.div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
// Both numbers are positive at this point
|
|
|
|
// Strip both numbers to approximate shift value
|
|
if (num.length > this.length || this.cmp(num) < 0) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: this
|
|
};
|
|
}
|
|
|
|
// Very short reduction
|
|
if (num.length === 1) {
|
|
if (mode === 'div') {
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: null
|
|
};
|
|
}
|
|
|
|
if (mode === 'mod') {
|
|
return {
|
|
div: null,
|
|
mod: new BN(this.modrn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: new BN(this.modrn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return this._wordDiv(num, mode);
|
|
};
|
|
|
|
// Find `this` / `num`
|
|
BN.prototype.div = function div (num) {
|
|
return this.divmod(num, 'div', false).div;
|
|
};
|
|
|
|
// Find `this` % `num`
|
|
BN.prototype.mod = function mod (num) {
|
|
return this.divmod(num, 'mod', false).mod;
|
|
};
|
|
|
|
BN.prototype.umod = function umod (num) {
|
|
return this.divmod(num, 'mod', true).mod;
|
|
};
|
|
|
|
// Find Round(`this` / `num`)
|
|
BN.prototype.divRound = function divRound (num) {
|
|
var dm = this.divmod(num);
|
|
|
|
// Fast case - exact division
|
|
if (dm.mod.isZero()) return dm.div;
|
|
|
|
var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
|
|
|
|
var half = num.ushrn(1);
|
|
var r2 = num.andln(1);
|
|
var cmp = mod.cmp(half);
|
|
|
|
// Round down
|
|
if (cmp < 0 || (r2 === 1 && cmp === 0)) return dm.div;
|
|
|
|
// Round up
|
|
return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
|
|
};
|
|
|
|
BN.prototype.modrn = function modrn (num) {
|
|
var isNegNum = num < 0;
|
|
if (isNegNum) num = -num;
|
|
|
|
assert(num <= 0x3ffffff);
|
|
var p = (1 << 26) % num;
|
|
|
|
var acc = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
acc = (p * acc + (this.words[i] | 0)) % num;
|
|
}
|
|
|
|
return isNegNum ? -acc : acc;
|
|
};
|
|
|
|
// WARNING: DEPRECATED
|
|
BN.prototype.modn = function modn (num) {
|
|
return this.modrn(num);
|
|
};
|
|
|
|
// In-place division by number
|
|
BN.prototype.idivn = function idivn (num) {
|
|
var isNegNum = num < 0;
|
|
if (isNegNum) num = -num;
|
|
|
|
assert(num <= 0x3ffffff);
|
|
|
|
var carry = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var w = (this.words[i] | 0) + carry * 0x4000000;
|
|
this.words[i] = (w / num) | 0;
|
|
carry = w % num;
|
|
}
|
|
|
|
this._strip();
|
|
return isNegNum ? this.ineg() : this;
|
|
};
|
|
|
|
BN.prototype.divn = function divn (num) {
|
|
return this.clone().idivn(num);
|
|
};
|
|
|
|
BN.prototype.egcd = function egcd (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var x = this;
|
|
var y = p.clone();
|
|
|
|
if (x.negative !== 0) {
|
|
x = x.umod(p);
|
|
} else {
|
|
x = x.clone();
|
|
}
|
|
|
|
// A * x + B * y = x
|
|
var A = new BN(1);
|
|
var B = new BN(0);
|
|
|
|
// C * x + D * y = y
|
|
var C = new BN(0);
|
|
var D = new BN(1);
|
|
|
|
var g = 0;
|
|
|
|
while (x.isEven() && y.isEven()) {
|
|
x.iushrn(1);
|
|
y.iushrn(1);
|
|
++g;
|
|
}
|
|
|
|
var yp = y.clone();
|
|
var xp = x.clone();
|
|
|
|
while (!x.isZero()) {
|
|
for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
x.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (A.isOdd() || B.isOdd()) {
|
|
A.iadd(yp);
|
|
B.isub(xp);
|
|
}
|
|
|
|
A.iushrn(1);
|
|
B.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
y.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (C.isOdd() || D.isOdd()) {
|
|
C.iadd(yp);
|
|
D.isub(xp);
|
|
}
|
|
|
|
C.iushrn(1);
|
|
D.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (x.cmp(y) >= 0) {
|
|
x.isub(y);
|
|
A.isub(C);
|
|
B.isub(D);
|
|
} else {
|
|
y.isub(x);
|
|
C.isub(A);
|
|
D.isub(B);
|
|
}
|
|
}
|
|
|
|
return {
|
|
a: C,
|
|
b: D,
|
|
gcd: y.iushln(g)
|
|
};
|
|
};
|
|
|
|
// This is reduced incarnation of the binary EEA
|
|
// above, designated to invert members of the
|
|
// _prime_ fields F(p) at a maximal speed
|
|
BN.prototype._invmp = function _invmp (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var a = this;
|
|
var b = p.clone();
|
|
|
|
if (a.negative !== 0) {
|
|
a = a.umod(p);
|
|
} else {
|
|
a = a.clone();
|
|
}
|
|
|
|
var x1 = new BN(1);
|
|
var x2 = new BN(0);
|
|
|
|
var delta = b.clone();
|
|
|
|
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
|
|
for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
a.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (x1.isOdd()) {
|
|
x1.iadd(delta);
|
|
}
|
|
|
|
x1.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
b.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (x2.isOdd()) {
|
|
x2.iadd(delta);
|
|
}
|
|
|
|
x2.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (a.cmp(b) >= 0) {
|
|
a.isub(b);
|
|
x1.isub(x2);
|
|
} else {
|
|
b.isub(a);
|
|
x2.isub(x1);
|
|
}
|
|
}
|
|
|
|
var res;
|
|
if (a.cmpn(1) === 0) {
|
|
res = x1;
|
|
} else {
|
|
res = x2;
|
|
}
|
|
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(p);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gcd = function gcd (num) {
|
|
if (this.isZero()) return num.abs();
|
|
if (num.isZero()) return this.abs();
|
|
|
|
var a = this.clone();
|
|
var b = num.clone();
|
|
a.negative = 0;
|
|
b.negative = 0;
|
|
|
|
// Remove common factor of two
|
|
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
|
|
a.iushrn(1);
|
|
b.iushrn(1);
|
|
}
|
|
|
|
do {
|
|
while (a.isEven()) {
|
|
a.iushrn(1);
|
|
}
|
|
while (b.isEven()) {
|
|
b.iushrn(1);
|
|
}
|
|
|
|
var r = a.cmp(b);
|
|
if (r < 0) {
|
|
// Swap `a` and `b` to make `a` always bigger than `b`
|
|
var t = a;
|
|
a = b;
|
|
b = t;
|
|
} else if (r === 0 || b.cmpn(1) === 0) {
|
|
break;
|
|
}
|
|
|
|
a.isub(b);
|
|
} while (true);
|
|
|
|
return b.iushln(shift);
|
|
};
|
|
|
|
// Invert number in the field F(num)
|
|
BN.prototype.invm = function invm (num) {
|
|
return this.egcd(num).a.umod(num);
|
|
};
|
|
|
|
BN.prototype.isEven = function isEven () {
|
|
return (this.words[0] & 1) === 0;
|
|
};
|
|
|
|
BN.prototype.isOdd = function isOdd () {
|
|
return (this.words[0] & 1) === 1;
|
|
};
|
|
|
|
// And first word and num
|
|
BN.prototype.andln = function andln (num) {
|
|
return this.words[0] & num;
|
|
};
|
|
|
|
// Increment at the bit position in-line
|
|
BN.prototype.bincn = function bincn (bit) {
|
|
assert(typeof bit === 'number');
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) {
|
|
this._expand(s + 1);
|
|
this.words[s] |= q;
|
|
return this;
|
|
}
|
|
|
|
// Add bit and propagate, if needed
|
|
var carry = q;
|
|
for (var i = s; carry !== 0 && i < this.length; i++) {
|
|
var w = this.words[i] | 0;
|
|
w += carry;
|
|
carry = w >>> 26;
|
|
w &= 0x3ffffff;
|
|
this.words[i] = w;
|
|
}
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.isZero = function isZero () {
|
|
return this.length === 1 && this.words[0] === 0;
|
|
};
|
|
|
|
BN.prototype.cmpn = function cmpn (num) {
|
|
var negative = num < 0;
|
|
|
|
if (this.negative !== 0 && !negative) return -1;
|
|
if (this.negative === 0 && negative) return 1;
|
|
|
|
this._strip();
|
|
|
|
var res;
|
|
if (this.length > 1) {
|
|
res = 1;
|
|
} else {
|
|
if (negative) {
|
|
num = -num;
|
|
}
|
|
|
|
assert(num <= 0x3ffffff, 'Number is too big');
|
|
|
|
var w = this.words[0] | 0;
|
|
res = w === num ? 0 : w < num ? -1 : 1;
|
|
}
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Compare two numbers and return:
|
|
// 1 - if `this` > `num`
|
|
// 0 - if `this` == `num`
|
|
// -1 - if `this` < `num`
|
|
BN.prototype.cmp = function cmp (num) {
|
|
if (this.negative !== 0 && num.negative === 0) return -1;
|
|
if (this.negative === 0 && num.negative !== 0) return 1;
|
|
|
|
var res = this.ucmp(num);
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Unsigned comparison
|
|
BN.prototype.ucmp = function ucmp (num) {
|
|
// At this point both numbers have the same sign
|
|
if (this.length > num.length) return 1;
|
|
if (this.length < num.length) return -1;
|
|
|
|
var res = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var a = this.words[i] | 0;
|
|
var b = num.words[i] | 0;
|
|
|
|
if (a === b) continue;
|
|
if (a < b) {
|
|
res = -1;
|
|
} else if (a > b) {
|
|
res = 1;
|
|
}
|
|
break;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gtn = function gtn (num) {
|
|
return this.cmpn(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gt = function gt (num) {
|
|
return this.cmp(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gten = function gten (num) {
|
|
return this.cmpn(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.gte = function gte (num) {
|
|
return this.cmp(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.ltn = function ltn (num) {
|
|
return this.cmpn(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lt = function lt (num) {
|
|
return this.cmp(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lten = function lten (num) {
|
|
return this.cmpn(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.lte = function lte (num) {
|
|
return this.cmp(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.eqn = function eqn (num) {
|
|
return this.cmpn(num) === 0;
|
|
};
|
|
|
|
BN.prototype.eq = function eq (num) {
|
|
return this.cmp(num) === 0;
|
|
};
|
|
|
|
//
|
|
// A reduce context, could be using montgomery or something better, depending
|
|
// on the `m` itself.
|
|
//
|
|
BN.red = function red (num) {
|
|
return new Red(num);
|
|
};
|
|
|
|
BN.prototype.toRed = function toRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
assert(this.negative === 0, 'red works only with positives');
|
|
return ctx.convertTo(this)._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.fromRed = function fromRed () {
|
|
assert(this.red, 'fromRed works only with numbers in reduction context');
|
|
return this.red.convertFrom(this);
|
|
};
|
|
|
|
BN.prototype._forceRed = function _forceRed (ctx) {
|
|
this.red = ctx;
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.forceRed = function forceRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
return this._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.redAdd = function redAdd (num) {
|
|
assert(this.red, 'redAdd works only with red numbers');
|
|
return this.red.add(this, num);
|
|
};
|
|
|
|
BN.prototype.redIAdd = function redIAdd (num) {
|
|
assert(this.red, 'redIAdd works only with red numbers');
|
|
return this.red.iadd(this, num);
|
|
};
|
|
|
|
BN.prototype.redSub = function redSub (num) {
|
|
assert(this.red, 'redSub works only with red numbers');
|
|
return this.red.sub(this, num);
|
|
};
|
|
|
|
BN.prototype.redISub = function redISub (num) {
|
|
assert(this.red, 'redISub works only with red numbers');
|
|
return this.red.isub(this, num);
|
|
};
|
|
|
|
BN.prototype.redShl = function redShl (num) {
|
|
assert(this.red, 'redShl works only with red numbers');
|
|
return this.red.shl(this, num);
|
|
};
|
|
|
|
BN.prototype.redMul = function redMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.mul(this, num);
|
|
};
|
|
|
|
BN.prototype.redIMul = function redIMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.imul(this, num);
|
|
};
|
|
|
|
BN.prototype.redSqr = function redSqr () {
|
|
assert(this.red, 'redSqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqr(this);
|
|
};
|
|
|
|
BN.prototype.redISqr = function redISqr () {
|
|
assert(this.red, 'redISqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.isqr(this);
|
|
};
|
|
|
|
// Square root over p
|
|
BN.prototype.redSqrt = function redSqrt () {
|
|
assert(this.red, 'redSqrt works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqrt(this);
|
|
};
|
|
|
|
BN.prototype.redInvm = function redInvm () {
|
|
assert(this.red, 'redInvm works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.invm(this);
|
|
};
|
|
|
|
// Return negative clone of `this` % `red modulo`
|
|
BN.prototype.redNeg = function redNeg () {
|
|
assert(this.red, 'redNeg works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.neg(this);
|
|
};
|
|
|
|
BN.prototype.redPow = function redPow (num) {
|
|
assert(this.red && !num.red, 'redPow(normalNum)');
|
|
this.red._verify1(this);
|
|
return this.red.pow(this, num);
|
|
};
|
|
|
|
// Prime numbers with efficient reduction
|
|
var primes = {
|
|
k256: null,
|
|
p224: null,
|
|
p192: null,
|
|
p25519: null
|
|
};
|
|
|
|
// Pseudo-Mersenne prime
|
|
function MPrime (name, p) {
|
|
// P = 2 ^ N - K
|
|
this.name = name;
|
|
this.p = new BN(p, 16);
|
|
this.n = this.p.bitLength();
|
|
this.k = new BN(1).iushln(this.n).isub(this.p);
|
|
|
|
this.tmp = this._tmp();
|
|
}
|
|
|
|
MPrime.prototype._tmp = function _tmp () {
|
|
var tmp = new BN(null);
|
|
tmp.words = new Array(Math.ceil(this.n / 13));
|
|
return tmp;
|
|
};
|
|
|
|
MPrime.prototype.ireduce = function ireduce (num) {
|
|
// Assumes that `num` is less than `P^2`
|
|
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
|
|
var r = num;
|
|
var rlen;
|
|
|
|
do {
|
|
this.split(r, this.tmp);
|
|
r = this.imulK(r);
|
|
r = r.iadd(this.tmp);
|
|
rlen = r.bitLength();
|
|
} while (rlen > this.n);
|
|
|
|
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
|
|
if (cmp === 0) {
|
|
r.words[0] = 0;
|
|
r.length = 1;
|
|
} else if (cmp > 0) {
|
|
r.isub(this.p);
|
|
} else {
|
|
if (r.strip !== undefined) {
|
|
// r is a BN v4 instance
|
|
r.strip();
|
|
} else {
|
|
// r is a BN v5 instance
|
|
r._strip();
|
|
}
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
MPrime.prototype.split = function split (input, out) {
|
|
input.iushrn(this.n, 0, out);
|
|
};
|
|
|
|
MPrime.prototype.imulK = function imulK (num) {
|
|
return num.imul(this.k);
|
|
};
|
|
|
|
function K256 () {
|
|
MPrime.call(
|
|
this,
|
|
'k256',
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
|
|
}
|
|
inherits(K256, MPrime);
|
|
|
|
K256.prototype.split = function split (input, output) {
|
|
// 256 = 9 * 26 + 22
|
|
var mask = 0x3fffff;
|
|
|
|
var outLen = Math.min(input.length, 9);
|
|
for (var i = 0; i < outLen; i++) {
|
|
output.words[i] = input.words[i];
|
|
}
|
|
output.length = outLen;
|
|
|
|
if (input.length <= 9) {
|
|
input.words[0] = 0;
|
|
input.length = 1;
|
|
return;
|
|
}
|
|
|
|
// Shift by 9 limbs
|
|
var prev = input.words[9];
|
|
output.words[output.length++] = prev & mask;
|
|
|
|
for (i = 10; i < input.length; i++) {
|
|
var next = input.words[i] | 0;
|
|
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
|
|
prev = next;
|
|
}
|
|
prev >>>= 22;
|
|
input.words[i - 10] = prev;
|
|
if (prev === 0 && input.length > 10) {
|
|
input.length -= 10;
|
|
} else {
|
|
input.length -= 9;
|
|
}
|
|
};
|
|
|
|
K256.prototype.imulK = function imulK (num) {
|
|
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
|
|
num.words[num.length] = 0;
|
|
num.words[num.length + 1] = 0;
|
|
num.length += 2;
|
|
|
|
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
|
|
var lo = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var w = num.words[i] | 0;
|
|
lo += w * 0x3d1;
|
|
num.words[i] = lo & 0x3ffffff;
|
|
lo = w * 0x40 + ((lo / 0x4000000) | 0);
|
|
}
|
|
|
|
// Fast length reduction
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
}
|
|
}
|
|
return num;
|
|
};
|
|
|
|
function P224 () {
|
|
MPrime.call(
|
|
this,
|
|
'p224',
|
|
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
|
|
}
|
|
inherits(P224, MPrime);
|
|
|
|
function P192 () {
|
|
MPrime.call(
|
|
this,
|
|
'p192',
|
|
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
|
|
}
|
|
inherits(P192, MPrime);
|
|
|
|
function P25519 () {
|
|
// 2 ^ 255 - 19
|
|
MPrime.call(
|
|
this,
|
|
'25519',
|
|
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
|
|
}
|
|
inherits(P25519, MPrime);
|
|
|
|
P25519.prototype.imulK = function imulK (num) {
|
|
// K = 0x13
|
|
var carry = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var hi = (num.words[i] | 0) * 0x13 + carry;
|
|
var lo = hi & 0x3ffffff;
|
|
hi >>>= 26;
|
|
|
|
num.words[i] = lo;
|
|
carry = hi;
|
|
}
|
|
if (carry !== 0) {
|
|
num.words[num.length++] = carry;
|
|
}
|
|
return num;
|
|
};
|
|
|
|
// Exported mostly for testing purposes, use plain name instead
|
|
BN._prime = function prime (name) {
|
|
// Cached version of prime
|
|
if (primes[name]) return primes[name];
|
|
|
|
var prime;
|
|
if (name === 'k256') {
|
|
prime = new K256();
|
|
} else if (name === 'p224') {
|
|
prime = new P224();
|
|
} else if (name === 'p192') {
|
|
prime = new P192();
|
|
} else if (name === 'p25519') {
|
|
prime = new P25519();
|
|
} else {
|
|
throw new Error('Unknown prime ' + name);
|
|
}
|
|
primes[name] = prime;
|
|
|
|
return prime;
|
|
};
|
|
|
|
//
|
|
// Base reduction engine
|
|
//
|
|
function Red (m) {
|
|
if (typeof m === 'string') {
|
|
var prime = BN._prime(m);
|
|
this.m = prime.p;
|
|
this.prime = prime;
|
|
} else {
|
|
assert(m.gtn(1), 'modulus must be greater than 1');
|
|
this.m = m;
|
|
this.prime = null;
|
|
}
|
|
}
|
|
|
|
Red.prototype._verify1 = function _verify1 (a) {
|
|
assert(a.negative === 0, 'red works only with positives');
|
|
assert(a.red, 'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype._verify2 = function _verify2 (a, b) {
|
|
assert((a.negative | b.negative) === 0, 'red works only with positives');
|
|
assert(a.red && a.red === b.red,
|
|
'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype.imod = function imod (a) {
|
|
if (this.prime) return this.prime.ireduce(a)._forceRed(this);
|
|
|
|
move(a, a.umod(this.m)._forceRed(this));
|
|
return a;
|
|
};
|
|
|
|
Red.prototype.neg = function neg (a) {
|
|
if (a.isZero()) {
|
|
return a.clone();
|
|
}
|
|
|
|
return this.m.sub(a)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.add = function add (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.add(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.iadd = function iadd (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.iadd(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.sub = function sub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.sub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.isub = function isub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.isub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.shl = function shl (a, num) {
|
|
this._verify1(a);
|
|
return this.imod(a.ushln(num));
|
|
};
|
|
|
|
Red.prototype.imul = function imul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.imul(b));
|
|
};
|
|
|
|
Red.prototype.mul = function mul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.mul(b));
|
|
};
|
|
|
|
Red.prototype.isqr = function isqr (a) {
|
|
return this.imul(a, a.clone());
|
|
};
|
|
|
|
Red.prototype.sqr = function sqr (a) {
|
|
return this.mul(a, a);
|
|
};
|
|
|
|
Red.prototype.sqrt = function sqrt (a) {
|
|
if (a.isZero()) return a.clone();
|
|
|
|
var mod3 = this.m.andln(3);
|
|
assert(mod3 % 2 === 1);
|
|
|
|
// Fast case
|
|
if (mod3 === 3) {
|
|
var pow = this.m.add(new BN(1)).iushrn(2);
|
|
return this.pow(a, pow);
|
|
}
|
|
|
|
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
|
|
//
|
|
// Find Q and S, that Q * 2 ^ S = (P - 1)
|
|
var q = this.m.subn(1);
|
|
var s = 0;
|
|
while (!q.isZero() && q.andln(1) === 0) {
|
|
s++;
|
|
q.iushrn(1);
|
|
}
|
|
assert(!q.isZero());
|
|
|
|
var one = new BN(1).toRed(this);
|
|
var nOne = one.redNeg();
|
|
|
|
// Find quadratic non-residue
|
|
// NOTE: Max is such because of generalized Riemann hypothesis.
|
|
var lpow = this.m.subn(1).iushrn(1);
|
|
var z = this.m.bitLength();
|
|
z = new BN(2 * z * z).toRed(this);
|
|
|
|
while (this.pow(z, lpow).cmp(nOne) !== 0) {
|
|
z.redIAdd(nOne);
|
|
}
|
|
|
|
var c = this.pow(z, q);
|
|
var r = this.pow(a, q.addn(1).iushrn(1));
|
|
var t = this.pow(a, q);
|
|
var m = s;
|
|
while (t.cmp(one) !== 0) {
|
|
var tmp = t;
|
|
for (var i = 0; tmp.cmp(one) !== 0; i++) {
|
|
tmp = tmp.redSqr();
|
|
}
|
|
assert(i < m);
|
|
var b = this.pow(c, new BN(1).iushln(m - i - 1));
|
|
|
|
r = r.redMul(b);
|
|
c = b.redSqr();
|
|
t = t.redMul(c);
|
|
m = i;
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
Red.prototype.invm = function invm (a) {
|
|
var inv = a._invmp(this.m);
|
|
if (inv.negative !== 0) {
|
|
inv.negative = 0;
|
|
return this.imod(inv).redNeg();
|
|
} else {
|
|
return this.imod(inv);
|
|
}
|
|
};
|
|
|
|
Red.prototype.pow = function pow (a, num) {
|
|
if (num.isZero()) return new BN(1).toRed(this);
|
|
if (num.cmpn(1) === 0) return a.clone();
|
|
|
|
var windowSize = 4;
|
|
var wnd = new Array(1 << windowSize);
|
|
wnd[0] = new BN(1).toRed(this);
|
|
wnd[1] = a;
|
|
for (var i = 2; i < wnd.length; i++) {
|
|
wnd[i] = this.mul(wnd[i - 1], a);
|
|
}
|
|
|
|
var res = wnd[0];
|
|
var current = 0;
|
|
var currentLen = 0;
|
|
var start = num.bitLength() % 26;
|
|
if (start === 0) {
|
|
start = 26;
|
|
}
|
|
|
|
for (i = num.length - 1; i >= 0; i--) {
|
|
var word = num.words[i];
|
|
for (var j = start - 1; j >= 0; j--) {
|
|
var bit = (word >> j) & 1;
|
|
if (res !== wnd[0]) {
|
|
res = this.sqr(res);
|
|
}
|
|
|
|
if (bit === 0 && current === 0) {
|
|
currentLen = 0;
|
|
continue;
|
|
}
|
|
|
|
current <<= 1;
|
|
current |= bit;
|
|
currentLen++;
|
|
if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
|
|
|
|
res = this.mul(res, wnd[current]);
|
|
currentLen = 0;
|
|
current = 0;
|
|
}
|
|
start = 26;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.convertTo = function convertTo (num) {
|
|
var r = num.umod(this.m);
|
|
|
|
return r === num ? r.clone() : r;
|
|
};
|
|
|
|
Red.prototype.convertFrom = function convertFrom (num) {
|
|
var res = num.clone();
|
|
res.red = null;
|
|
return res;
|
|
};
|
|
|
|
//
|
|
// Montgomery method engine
|
|
//
|
|
|
|
BN.mont = function mont (num) {
|
|
return new Mont(num);
|
|
};
|
|
|
|
function Mont (m) {
|
|
Red.call(this, m);
|
|
|
|
this.shift = this.m.bitLength();
|
|
if (this.shift % 26 !== 0) {
|
|
this.shift += 26 - (this.shift % 26);
|
|
}
|
|
|
|
this.r = new BN(1).iushln(this.shift);
|
|
this.r2 = this.imod(this.r.sqr());
|
|
this.rinv = this.r._invmp(this.m);
|
|
|
|
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
|
|
this.minv = this.minv.umod(this.r);
|
|
this.minv = this.r.sub(this.minv);
|
|
}
|
|
inherits(Mont, Red);
|
|
|
|
Mont.prototype.convertTo = function convertTo (num) {
|
|
return this.imod(num.ushln(this.shift));
|
|
};
|
|
|
|
Mont.prototype.convertFrom = function convertFrom (num) {
|
|
var r = this.imod(num.mul(this.rinv));
|
|
r.red = null;
|
|
return r;
|
|
};
|
|
|
|
Mont.prototype.imul = function imul (a, b) {
|
|
if (a.isZero() || b.isZero()) {
|
|
a.words[0] = 0;
|
|
a.length = 1;
|
|
return a;
|
|
}
|
|
|
|
var t = a.imul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.mul = function mul (a, b) {
|
|
if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
|
|
|
|
var t = a.mul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.invm = function invm (a) {
|
|
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
|
|
var res = this.imod(a._invmp(this.m).mul(this.r2));
|
|
return res._forceRed(this);
|
|
};
|
|
})( false || module, this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/brorand/index.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/brorand/index.js ***!
|
|
\***************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var r;
|
|
|
|
module.exports = function rand(len) {
|
|
if (!r)
|
|
r = new Rand(null);
|
|
|
|
return r.generate(len);
|
|
};
|
|
|
|
function Rand(rand) {
|
|
this.rand = rand;
|
|
}
|
|
module.exports.Rand = Rand;
|
|
|
|
Rand.prototype.generate = function generate(len) {
|
|
return this._rand(len);
|
|
};
|
|
|
|
// Emulate crypto API using randy
|
|
Rand.prototype._rand = function _rand(n) {
|
|
if (this.rand.getBytes)
|
|
return this.rand.getBytes(n);
|
|
|
|
var res = new Uint8Array(n);
|
|
for (var i = 0; i < res.length; i++)
|
|
res[i] = this.rand.getByte();
|
|
return res;
|
|
};
|
|
|
|
if (typeof self === 'object') {
|
|
if (self.crypto && self.crypto.getRandomValues) {
|
|
// Modern browsers
|
|
Rand.prototype._rand = function _rand(n) {
|
|
var arr = new Uint8Array(n);
|
|
self.crypto.getRandomValues(arr);
|
|
return arr;
|
|
};
|
|
} else if (self.msCrypto && self.msCrypto.getRandomValues) {
|
|
// IE
|
|
Rand.prototype._rand = function _rand(n) {
|
|
var arr = new Uint8Array(n);
|
|
self.msCrypto.getRandomValues(arr);
|
|
return arr;
|
|
};
|
|
|
|
// Safari's WebWorkers do not have `crypto`
|
|
} else if (typeof window === 'object') {
|
|
// Old junk
|
|
Rand.prototype._rand = function() {
|
|
throw new Error('Not implemented yet');
|
|
};
|
|
}
|
|
} else {
|
|
// Node.js or Web worker with no crypto support
|
|
try {
|
|
var crypto = __webpack_require__(/*! crypto */ "?3fc0");
|
|
if (typeof crypto.randomBytes !== 'function')
|
|
throw new Error('Not supported');
|
|
|
|
Rand.prototype._rand = function _rand(n) {
|
|
return crypto.randomBytes(n);
|
|
};
|
|
} catch (e) {
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/aes.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/browserify-aes/aes.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
// based on the aes implimentation in triple sec
|
|
// https://github.com/keybase/triplesec
|
|
// which is in turn based on the one from crypto-js
|
|
// https://code.google.com/p/crypto-js/
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
function asUInt32Array (buf) {
|
|
if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf)
|
|
|
|
var len = (buf.length / 4) | 0
|
|
var out = new Array(len)
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
out[i] = buf.readUInt32BE(i * 4)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
function scrubVec (v) {
|
|
for (var i = 0; i < v.length; v++) {
|
|
v[i] = 0
|
|
}
|
|
}
|
|
|
|
function cryptBlock (M, keySchedule, SUB_MIX, SBOX, nRounds) {
|
|
var SUB_MIX0 = SUB_MIX[0]
|
|
var SUB_MIX1 = SUB_MIX[1]
|
|
var SUB_MIX2 = SUB_MIX[2]
|
|
var SUB_MIX3 = SUB_MIX[3]
|
|
|
|
var s0 = M[0] ^ keySchedule[0]
|
|
var s1 = M[1] ^ keySchedule[1]
|
|
var s2 = M[2] ^ keySchedule[2]
|
|
var s3 = M[3] ^ keySchedule[3]
|
|
var t0, t1, t2, t3
|
|
var ksRow = 4
|
|
|
|
for (var round = 1; round < nRounds; round++) {
|
|
t0 = SUB_MIX0[s0 >>> 24] ^ SUB_MIX1[(s1 >>> 16) & 0xff] ^ SUB_MIX2[(s2 >>> 8) & 0xff] ^ SUB_MIX3[s3 & 0xff] ^ keySchedule[ksRow++]
|
|
t1 = SUB_MIX0[s1 >>> 24] ^ SUB_MIX1[(s2 >>> 16) & 0xff] ^ SUB_MIX2[(s3 >>> 8) & 0xff] ^ SUB_MIX3[s0 & 0xff] ^ keySchedule[ksRow++]
|
|
t2 = SUB_MIX0[s2 >>> 24] ^ SUB_MIX1[(s3 >>> 16) & 0xff] ^ SUB_MIX2[(s0 >>> 8) & 0xff] ^ SUB_MIX3[s1 & 0xff] ^ keySchedule[ksRow++]
|
|
t3 = SUB_MIX0[s3 >>> 24] ^ SUB_MIX1[(s0 >>> 16) & 0xff] ^ SUB_MIX2[(s1 >>> 8) & 0xff] ^ SUB_MIX3[s2 & 0xff] ^ keySchedule[ksRow++]
|
|
s0 = t0
|
|
s1 = t1
|
|
s2 = t2
|
|
s3 = t3
|
|
}
|
|
|
|
t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]
|
|
t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]
|
|
t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]
|
|
t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]
|
|
t0 = t0 >>> 0
|
|
t1 = t1 >>> 0
|
|
t2 = t2 >>> 0
|
|
t3 = t3 >>> 0
|
|
|
|
return [t0, t1, t2, t3]
|
|
}
|
|
|
|
// AES constants
|
|
var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]
|
|
var G = (function () {
|
|
// Compute double table
|
|
var d = new Array(256)
|
|
for (var j = 0; j < 256; j++) {
|
|
if (j < 128) {
|
|
d[j] = j << 1
|
|
} else {
|
|
d[j] = (j << 1) ^ 0x11b
|
|
}
|
|
}
|
|
|
|
var SBOX = []
|
|
var INV_SBOX = []
|
|
var SUB_MIX = [[], [], [], []]
|
|
var INV_SUB_MIX = [[], [], [], []]
|
|
|
|
// Walk GF(2^8)
|
|
var x = 0
|
|
var xi = 0
|
|
for (var i = 0; i < 256; ++i) {
|
|
// Compute sbox
|
|
var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4)
|
|
sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63
|
|
SBOX[x] = sx
|
|
INV_SBOX[sx] = x
|
|
|
|
// Compute multiplication
|
|
var x2 = d[x]
|
|
var x4 = d[x2]
|
|
var x8 = d[x4]
|
|
|
|
// Compute sub bytes, mix columns tables
|
|
var t = (d[sx] * 0x101) ^ (sx * 0x1010100)
|
|
SUB_MIX[0][x] = (t << 24) | (t >>> 8)
|
|
SUB_MIX[1][x] = (t << 16) | (t >>> 16)
|
|
SUB_MIX[2][x] = (t << 8) | (t >>> 24)
|
|
SUB_MIX[3][x] = t
|
|
|
|
// Compute inv sub bytes, inv mix columns tables
|
|
t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100)
|
|
INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8)
|
|
INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16)
|
|
INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24)
|
|
INV_SUB_MIX[3][sx] = t
|
|
|
|
if (x === 0) {
|
|
x = xi = 1
|
|
} else {
|
|
x = x2 ^ d[d[d[x8 ^ x2]]]
|
|
xi ^= d[d[xi]]
|
|
}
|
|
}
|
|
|
|
return {
|
|
SBOX: SBOX,
|
|
INV_SBOX: INV_SBOX,
|
|
SUB_MIX: SUB_MIX,
|
|
INV_SUB_MIX: INV_SUB_MIX
|
|
}
|
|
})()
|
|
|
|
function AES (key) {
|
|
this._key = asUInt32Array(key)
|
|
this._reset()
|
|
}
|
|
|
|
AES.blockSize = 4 * 4
|
|
AES.keySize = 256 / 8
|
|
AES.prototype.blockSize = AES.blockSize
|
|
AES.prototype.keySize = AES.keySize
|
|
AES.prototype._reset = function () {
|
|
var keyWords = this._key
|
|
var keySize = keyWords.length
|
|
var nRounds = keySize + 6
|
|
var ksRows = (nRounds + 1) * 4
|
|
|
|
var keySchedule = []
|
|
for (var k = 0; k < keySize; k++) {
|
|
keySchedule[k] = keyWords[k]
|
|
}
|
|
|
|
for (k = keySize; k < ksRows; k++) {
|
|
var t = keySchedule[k - 1]
|
|
|
|
if (k % keySize === 0) {
|
|
t = (t << 8) | (t >>> 24)
|
|
t =
|
|
(G.SBOX[t >>> 24] << 24) |
|
|
(G.SBOX[(t >>> 16) & 0xff] << 16) |
|
|
(G.SBOX[(t >>> 8) & 0xff] << 8) |
|
|
(G.SBOX[t & 0xff])
|
|
|
|
t ^= RCON[(k / keySize) | 0] << 24
|
|
} else if (keySize > 6 && k % keySize === 4) {
|
|
t =
|
|
(G.SBOX[t >>> 24] << 24) |
|
|
(G.SBOX[(t >>> 16) & 0xff] << 16) |
|
|
(G.SBOX[(t >>> 8) & 0xff] << 8) |
|
|
(G.SBOX[t & 0xff])
|
|
}
|
|
|
|
keySchedule[k] = keySchedule[k - keySize] ^ t
|
|
}
|
|
|
|
var invKeySchedule = []
|
|
for (var ik = 0; ik < ksRows; ik++) {
|
|
var ksR = ksRows - ik
|
|
var tt = keySchedule[ksR - (ik % 4 ? 0 : 4)]
|
|
|
|
if (ik < 4 || ksR <= 4) {
|
|
invKeySchedule[ik] = tt
|
|
} else {
|
|
invKeySchedule[ik] =
|
|
G.INV_SUB_MIX[0][G.SBOX[tt >>> 24]] ^
|
|
G.INV_SUB_MIX[1][G.SBOX[(tt >>> 16) & 0xff]] ^
|
|
G.INV_SUB_MIX[2][G.SBOX[(tt >>> 8) & 0xff]] ^
|
|
G.INV_SUB_MIX[3][G.SBOX[tt & 0xff]]
|
|
}
|
|
}
|
|
|
|
this._nRounds = nRounds
|
|
this._keySchedule = keySchedule
|
|
this._invKeySchedule = invKeySchedule
|
|
}
|
|
|
|
AES.prototype.encryptBlockRaw = function (M) {
|
|
M = asUInt32Array(M)
|
|
return cryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX, this._nRounds)
|
|
}
|
|
|
|
AES.prototype.encryptBlock = function (M) {
|
|
var out = this.encryptBlockRaw(M)
|
|
var buf = Buffer.allocUnsafe(16)
|
|
buf.writeUInt32BE(out[0], 0)
|
|
buf.writeUInt32BE(out[1], 4)
|
|
buf.writeUInt32BE(out[2], 8)
|
|
buf.writeUInt32BE(out[3], 12)
|
|
return buf
|
|
}
|
|
|
|
AES.prototype.decryptBlock = function (M) {
|
|
M = asUInt32Array(M)
|
|
|
|
// swap
|
|
var m1 = M[1]
|
|
M[1] = M[3]
|
|
M[3] = m1
|
|
|
|
var out = cryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX, this._nRounds)
|
|
var buf = Buffer.allocUnsafe(16)
|
|
buf.writeUInt32BE(out[0], 0)
|
|
buf.writeUInt32BE(out[3], 4)
|
|
buf.writeUInt32BE(out[2], 8)
|
|
buf.writeUInt32BE(out[1], 12)
|
|
return buf
|
|
}
|
|
|
|
AES.prototype.scrub = function () {
|
|
scrubVec(this._keySchedule)
|
|
scrubVec(this._invKeySchedule)
|
|
scrubVec(this._key)
|
|
}
|
|
|
|
module.exports.AES = AES
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/authCipher.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/browserify-aes/authCipher.js ***!
|
|
\***************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var aes = __webpack_require__(/*! ./aes */ "./node_modules/browserify-aes/aes.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var Transform = __webpack_require__(/*! cipher-base */ "./node_modules/cipher-base/index.js")
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var GHASH = __webpack_require__(/*! ./ghash */ "./node_modules/browserify-aes/ghash.js")
|
|
var xor = __webpack_require__(/*! buffer-xor */ "./node_modules/buffer-xor/index.js")
|
|
var incr32 = __webpack_require__(/*! ./incr32 */ "./node_modules/browserify-aes/incr32.js")
|
|
|
|
function xorTest (a, b) {
|
|
var out = 0
|
|
if (a.length !== b.length) out++
|
|
|
|
var len = Math.min(a.length, b.length)
|
|
for (var i = 0; i < len; ++i) {
|
|
out += (a[i] ^ b[i])
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
function calcIv (self, iv, ck) {
|
|
if (iv.length === 12) {
|
|
self._finID = Buffer.concat([iv, Buffer.from([0, 0, 0, 1])])
|
|
return Buffer.concat([iv, Buffer.from([0, 0, 0, 2])])
|
|
}
|
|
var ghash = new GHASH(ck)
|
|
var len = iv.length
|
|
var toPad = len % 16
|
|
ghash.update(iv)
|
|
if (toPad) {
|
|
toPad = 16 - toPad
|
|
ghash.update(Buffer.alloc(toPad, 0))
|
|
}
|
|
ghash.update(Buffer.alloc(8, 0))
|
|
var ivBits = len * 8
|
|
var tail = Buffer.alloc(8)
|
|
tail.writeUIntBE(ivBits, 0, 8)
|
|
ghash.update(tail)
|
|
self._finID = ghash.state
|
|
var out = Buffer.from(self._finID)
|
|
incr32(out)
|
|
return out
|
|
}
|
|
function StreamCipher (mode, key, iv, decrypt) {
|
|
Transform.call(this)
|
|
|
|
var h = Buffer.alloc(4, 0)
|
|
|
|
this._cipher = new aes.AES(key)
|
|
var ck = this._cipher.encryptBlock(h)
|
|
this._ghash = new GHASH(ck)
|
|
iv = calcIv(this, iv, ck)
|
|
|
|
this._prev = Buffer.from(iv)
|
|
this._cache = Buffer.allocUnsafe(0)
|
|
this._secCache = Buffer.allocUnsafe(0)
|
|
this._decrypt = decrypt
|
|
this._alen = 0
|
|
this._len = 0
|
|
this._mode = mode
|
|
|
|
this._authTag = null
|
|
this._called = false
|
|
}
|
|
|
|
inherits(StreamCipher, Transform)
|
|
|
|
StreamCipher.prototype._update = function (chunk) {
|
|
if (!this._called && this._alen) {
|
|
var rump = 16 - (this._alen % 16)
|
|
if (rump < 16) {
|
|
rump = Buffer.alloc(rump, 0)
|
|
this._ghash.update(rump)
|
|
}
|
|
}
|
|
|
|
this._called = true
|
|
var out = this._mode.encrypt(this, chunk)
|
|
if (this._decrypt) {
|
|
this._ghash.update(chunk)
|
|
} else {
|
|
this._ghash.update(out)
|
|
}
|
|
this._len += chunk.length
|
|
return out
|
|
}
|
|
|
|
StreamCipher.prototype._final = function () {
|
|
if (this._decrypt && !this._authTag) throw new Error('Unsupported state or unable to authenticate data')
|
|
|
|
var tag = xor(this._ghash.final(this._alen * 8, this._len * 8), this._cipher.encryptBlock(this._finID))
|
|
if (this._decrypt && xorTest(tag, this._authTag)) throw new Error('Unsupported state or unable to authenticate data')
|
|
|
|
this._authTag = tag
|
|
this._cipher.scrub()
|
|
}
|
|
|
|
StreamCipher.prototype.getAuthTag = function getAuthTag () {
|
|
if (this._decrypt || !Buffer.isBuffer(this._authTag)) throw new Error('Attempting to get auth tag in unsupported state')
|
|
|
|
return this._authTag
|
|
}
|
|
|
|
StreamCipher.prototype.setAuthTag = function setAuthTag (tag) {
|
|
if (!this._decrypt) throw new Error('Attempting to set auth tag in unsupported state')
|
|
|
|
this._authTag = tag
|
|
}
|
|
|
|
StreamCipher.prototype.setAAD = function setAAD (buf) {
|
|
if (this._called) throw new Error('Attempting to set AAD in unsupported state')
|
|
|
|
this._ghash.update(buf)
|
|
this._alen += buf.length
|
|
}
|
|
|
|
module.exports = StreamCipher
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/browser.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/browserify-aes/browser.js ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var ciphers = __webpack_require__(/*! ./encrypter */ "./node_modules/browserify-aes/encrypter.js")
|
|
var deciphers = __webpack_require__(/*! ./decrypter */ "./node_modules/browserify-aes/decrypter.js")
|
|
var modes = __webpack_require__(/*! ./modes/list.json */ "./node_modules/browserify-aes/modes/list.json")
|
|
|
|
function getCiphers () {
|
|
return Object.keys(modes)
|
|
}
|
|
|
|
exports.createCipher = exports.Cipher = ciphers.createCipher
|
|
exports.createCipheriv = exports.Cipheriv = ciphers.createCipheriv
|
|
exports.createDecipher = exports.Decipher = deciphers.createDecipher
|
|
exports.createDecipheriv = exports.Decipheriv = deciphers.createDecipheriv
|
|
exports.listCiphers = exports.getCiphers = getCiphers
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/decrypter.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/browserify-aes/decrypter.js ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var AuthCipher = __webpack_require__(/*! ./authCipher */ "./node_modules/browserify-aes/authCipher.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var MODES = __webpack_require__(/*! ./modes */ "./node_modules/browserify-aes/modes/index.js")
|
|
var StreamCipher = __webpack_require__(/*! ./streamCipher */ "./node_modules/browserify-aes/streamCipher.js")
|
|
var Transform = __webpack_require__(/*! cipher-base */ "./node_modules/cipher-base/index.js")
|
|
var aes = __webpack_require__(/*! ./aes */ "./node_modules/browserify-aes/aes.js")
|
|
var ebtk = __webpack_require__(/*! evp_bytestokey */ "./node_modules/evp_bytestokey/index.js")
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
|
|
function Decipher (mode, key, iv) {
|
|
Transform.call(this)
|
|
|
|
this._cache = new Splitter()
|
|
this._last = void 0
|
|
this._cipher = new aes.AES(key)
|
|
this._prev = Buffer.from(iv)
|
|
this._mode = mode
|
|
this._autopadding = true
|
|
}
|
|
|
|
inherits(Decipher, Transform)
|
|
|
|
Decipher.prototype._update = function (data) {
|
|
this._cache.add(data)
|
|
var chunk
|
|
var thing
|
|
var out = []
|
|
while ((chunk = this._cache.get(this._autopadding))) {
|
|
thing = this._mode.decrypt(this, chunk)
|
|
out.push(thing)
|
|
}
|
|
return Buffer.concat(out)
|
|
}
|
|
|
|
Decipher.prototype._final = function () {
|
|
var chunk = this._cache.flush()
|
|
if (this._autopadding) {
|
|
return unpad(this._mode.decrypt(this, chunk))
|
|
} else if (chunk) {
|
|
throw new Error('data not multiple of block length')
|
|
}
|
|
}
|
|
|
|
Decipher.prototype.setAutoPadding = function (setTo) {
|
|
this._autopadding = !!setTo
|
|
return this
|
|
}
|
|
|
|
function Splitter () {
|
|
this.cache = Buffer.allocUnsafe(0)
|
|
}
|
|
|
|
Splitter.prototype.add = function (data) {
|
|
this.cache = Buffer.concat([this.cache, data])
|
|
}
|
|
|
|
Splitter.prototype.get = function (autoPadding) {
|
|
var out
|
|
if (autoPadding) {
|
|
if (this.cache.length > 16) {
|
|
out = this.cache.slice(0, 16)
|
|
this.cache = this.cache.slice(16)
|
|
return out
|
|
}
|
|
} else {
|
|
if (this.cache.length >= 16) {
|
|
out = this.cache.slice(0, 16)
|
|
this.cache = this.cache.slice(16)
|
|
return out
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
Splitter.prototype.flush = function () {
|
|
if (this.cache.length) return this.cache
|
|
}
|
|
|
|
function unpad (last) {
|
|
var padded = last[15]
|
|
if (padded < 1 || padded > 16) {
|
|
throw new Error('unable to decrypt data')
|
|
}
|
|
var i = -1
|
|
while (++i < padded) {
|
|
if (last[(i + (16 - padded))] !== padded) {
|
|
throw new Error('unable to decrypt data')
|
|
}
|
|
}
|
|
if (padded === 16) return
|
|
|
|
return last.slice(0, 16 - padded)
|
|
}
|
|
|
|
function createDecipheriv (suite, password, iv) {
|
|
var config = MODES[suite.toLowerCase()]
|
|
if (!config) throw new TypeError('invalid suite type')
|
|
|
|
if (typeof iv === 'string') iv = Buffer.from(iv)
|
|
if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length)
|
|
|
|
if (typeof password === 'string') password = Buffer.from(password)
|
|
if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length)
|
|
|
|
if (config.type === 'stream') {
|
|
return new StreamCipher(config.module, password, iv, true)
|
|
} else if (config.type === 'auth') {
|
|
return new AuthCipher(config.module, password, iv, true)
|
|
}
|
|
|
|
return new Decipher(config.module, password, iv)
|
|
}
|
|
|
|
function createDecipher (suite, password) {
|
|
var config = MODES[suite.toLowerCase()]
|
|
if (!config) throw new TypeError('invalid suite type')
|
|
|
|
var keys = ebtk(password, false, config.key, config.iv)
|
|
return createDecipheriv(suite, keys.key, keys.iv)
|
|
}
|
|
|
|
exports.createDecipher = createDecipher
|
|
exports.createDecipheriv = createDecipheriv
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/encrypter.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/browserify-aes/encrypter.js ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var MODES = __webpack_require__(/*! ./modes */ "./node_modules/browserify-aes/modes/index.js")
|
|
var AuthCipher = __webpack_require__(/*! ./authCipher */ "./node_modules/browserify-aes/authCipher.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var StreamCipher = __webpack_require__(/*! ./streamCipher */ "./node_modules/browserify-aes/streamCipher.js")
|
|
var Transform = __webpack_require__(/*! cipher-base */ "./node_modules/cipher-base/index.js")
|
|
var aes = __webpack_require__(/*! ./aes */ "./node_modules/browserify-aes/aes.js")
|
|
var ebtk = __webpack_require__(/*! evp_bytestokey */ "./node_modules/evp_bytestokey/index.js")
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
|
|
function Cipher (mode, key, iv) {
|
|
Transform.call(this)
|
|
|
|
this._cache = new Splitter()
|
|
this._cipher = new aes.AES(key)
|
|
this._prev = Buffer.from(iv)
|
|
this._mode = mode
|
|
this._autopadding = true
|
|
}
|
|
|
|
inherits(Cipher, Transform)
|
|
|
|
Cipher.prototype._update = function (data) {
|
|
this._cache.add(data)
|
|
var chunk
|
|
var thing
|
|
var out = []
|
|
|
|
while ((chunk = this._cache.get())) {
|
|
thing = this._mode.encrypt(this, chunk)
|
|
out.push(thing)
|
|
}
|
|
|
|
return Buffer.concat(out)
|
|
}
|
|
|
|
var PADDING = Buffer.alloc(16, 0x10)
|
|
|
|
Cipher.prototype._final = function () {
|
|
var chunk = this._cache.flush()
|
|
if (this._autopadding) {
|
|
chunk = this._mode.encrypt(this, chunk)
|
|
this._cipher.scrub()
|
|
return chunk
|
|
}
|
|
|
|
if (!chunk.equals(PADDING)) {
|
|
this._cipher.scrub()
|
|
throw new Error('data not multiple of block length')
|
|
}
|
|
}
|
|
|
|
Cipher.prototype.setAutoPadding = function (setTo) {
|
|
this._autopadding = !!setTo
|
|
return this
|
|
}
|
|
|
|
function Splitter () {
|
|
this.cache = Buffer.allocUnsafe(0)
|
|
}
|
|
|
|
Splitter.prototype.add = function (data) {
|
|
this.cache = Buffer.concat([this.cache, data])
|
|
}
|
|
|
|
Splitter.prototype.get = function () {
|
|
if (this.cache.length > 15) {
|
|
var out = this.cache.slice(0, 16)
|
|
this.cache = this.cache.slice(16)
|
|
return out
|
|
}
|
|
return null
|
|
}
|
|
|
|
Splitter.prototype.flush = function () {
|
|
var len = 16 - this.cache.length
|
|
var padBuff = Buffer.allocUnsafe(len)
|
|
|
|
var i = -1
|
|
while (++i < len) {
|
|
padBuff.writeUInt8(len, i)
|
|
}
|
|
|
|
return Buffer.concat([this.cache, padBuff])
|
|
}
|
|
|
|
function createCipheriv (suite, password, iv) {
|
|
var config = MODES[suite.toLowerCase()]
|
|
if (!config) throw new TypeError('invalid suite type')
|
|
|
|
if (typeof password === 'string') password = Buffer.from(password)
|
|
if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length)
|
|
|
|
if (typeof iv === 'string') iv = Buffer.from(iv)
|
|
if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length)
|
|
|
|
if (config.type === 'stream') {
|
|
return new StreamCipher(config.module, password, iv)
|
|
} else if (config.type === 'auth') {
|
|
return new AuthCipher(config.module, password, iv)
|
|
}
|
|
|
|
return new Cipher(config.module, password, iv)
|
|
}
|
|
|
|
function createCipher (suite, password) {
|
|
var config = MODES[suite.toLowerCase()]
|
|
if (!config) throw new TypeError('invalid suite type')
|
|
|
|
var keys = ebtk(password, false, config.key, config.iv)
|
|
return createCipheriv(suite, keys.key, keys.iv)
|
|
}
|
|
|
|
exports.createCipheriv = createCipheriv
|
|
exports.createCipher = createCipher
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/ghash.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/browserify-aes/ghash.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var ZEROES = Buffer.alloc(16, 0)
|
|
|
|
function toArray (buf) {
|
|
return [
|
|
buf.readUInt32BE(0),
|
|
buf.readUInt32BE(4),
|
|
buf.readUInt32BE(8),
|
|
buf.readUInt32BE(12)
|
|
]
|
|
}
|
|
|
|
function fromArray (out) {
|
|
var buf = Buffer.allocUnsafe(16)
|
|
buf.writeUInt32BE(out[0] >>> 0, 0)
|
|
buf.writeUInt32BE(out[1] >>> 0, 4)
|
|
buf.writeUInt32BE(out[2] >>> 0, 8)
|
|
buf.writeUInt32BE(out[3] >>> 0, 12)
|
|
return buf
|
|
}
|
|
|
|
function GHASH (key) {
|
|
this.h = key
|
|
this.state = Buffer.alloc(16, 0)
|
|
this.cache = Buffer.allocUnsafe(0)
|
|
}
|
|
|
|
// from http://bitwiseshiftleft.github.io/sjcl/doc/symbols/src/core_gcm.js.html
|
|
// by Juho Vähä-Herttua
|
|
GHASH.prototype.ghash = function (block) {
|
|
var i = -1
|
|
while (++i < block.length) {
|
|
this.state[i] ^= block[i]
|
|
}
|
|
this._multiply()
|
|
}
|
|
|
|
GHASH.prototype._multiply = function () {
|
|
var Vi = toArray(this.h)
|
|
var Zi = [0, 0, 0, 0]
|
|
var j, xi, lsbVi
|
|
var i = -1
|
|
while (++i < 128) {
|
|
xi = (this.state[~~(i / 8)] & (1 << (7 - (i % 8)))) !== 0
|
|
if (xi) {
|
|
// Z_i+1 = Z_i ^ V_i
|
|
Zi[0] ^= Vi[0]
|
|
Zi[1] ^= Vi[1]
|
|
Zi[2] ^= Vi[2]
|
|
Zi[3] ^= Vi[3]
|
|
}
|
|
|
|
// Store the value of LSB(V_i)
|
|
lsbVi = (Vi[3] & 1) !== 0
|
|
|
|
// V_i+1 = V_i >> 1
|
|
for (j = 3; j > 0; j--) {
|
|
Vi[j] = (Vi[j] >>> 1) | ((Vi[j - 1] & 1) << 31)
|
|
}
|
|
Vi[0] = Vi[0] >>> 1
|
|
|
|
// If LSB(V_i) is 1, V_i+1 = (V_i >> 1) ^ R
|
|
if (lsbVi) {
|
|
Vi[0] = Vi[0] ^ (0xe1 << 24)
|
|
}
|
|
}
|
|
this.state = fromArray(Zi)
|
|
}
|
|
|
|
GHASH.prototype.update = function (buf) {
|
|
this.cache = Buffer.concat([this.cache, buf])
|
|
var chunk
|
|
while (this.cache.length >= 16) {
|
|
chunk = this.cache.slice(0, 16)
|
|
this.cache = this.cache.slice(16)
|
|
this.ghash(chunk)
|
|
}
|
|
}
|
|
|
|
GHASH.prototype.final = function (abl, bl) {
|
|
if (this.cache.length) {
|
|
this.ghash(Buffer.concat([this.cache, ZEROES], 16))
|
|
}
|
|
|
|
this.ghash(fromArray([0, abl, 0, bl]))
|
|
return this.state
|
|
}
|
|
|
|
module.exports = GHASH
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/incr32.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/browserify-aes/incr32.js ***!
|
|
\***********************************************/
|
|
/***/ ((module) => {
|
|
|
|
function incr32 (iv) {
|
|
var len = iv.length
|
|
var item
|
|
while (len--) {
|
|
item = iv.readUInt8(len)
|
|
if (item === 255) {
|
|
iv.writeUInt8(0, len)
|
|
} else {
|
|
item++
|
|
iv.writeUInt8(item, len)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
module.exports = incr32
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/modes/cbc.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/browserify-aes/modes/cbc.js ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var xor = __webpack_require__(/*! buffer-xor */ "./node_modules/buffer-xor/index.js")
|
|
|
|
exports.encrypt = function (self, block) {
|
|
var data = xor(block, self._prev)
|
|
|
|
self._prev = self._cipher.encryptBlock(data)
|
|
return self._prev
|
|
}
|
|
|
|
exports.decrypt = function (self, block) {
|
|
var pad = self._prev
|
|
|
|
self._prev = block
|
|
var out = self._cipher.decryptBlock(block)
|
|
|
|
return xor(out, pad)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/modes/cfb.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/browserify-aes/modes/cfb.js ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var xor = __webpack_require__(/*! buffer-xor */ "./node_modules/buffer-xor/index.js")
|
|
|
|
function encryptStart (self, data, decrypt) {
|
|
var len = data.length
|
|
var out = xor(data, self._cache)
|
|
self._cache = self._cache.slice(len)
|
|
self._prev = Buffer.concat([self._prev, decrypt ? data : out])
|
|
return out
|
|
}
|
|
|
|
exports.encrypt = function (self, data, decrypt) {
|
|
var out = Buffer.allocUnsafe(0)
|
|
var len
|
|
|
|
while (data.length) {
|
|
if (self._cache.length === 0) {
|
|
self._cache = self._cipher.encryptBlock(self._prev)
|
|
self._prev = Buffer.allocUnsafe(0)
|
|
}
|
|
|
|
if (self._cache.length <= data.length) {
|
|
len = self._cache.length
|
|
out = Buffer.concat([out, encryptStart(self, data.slice(0, len), decrypt)])
|
|
data = data.slice(len)
|
|
} else {
|
|
out = Buffer.concat([out, encryptStart(self, data, decrypt)])
|
|
break
|
|
}
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/modes/cfb1.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/browserify-aes/modes/cfb1.js ***!
|
|
\***************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
function encryptByte (self, byteParam, decrypt) {
|
|
var pad
|
|
var i = -1
|
|
var len = 8
|
|
var out = 0
|
|
var bit, value
|
|
while (++i < len) {
|
|
pad = self._cipher.encryptBlock(self._prev)
|
|
bit = (byteParam & (1 << (7 - i))) ? 0x80 : 0
|
|
value = pad[0] ^ bit
|
|
out += ((value & 0x80) >> (i % 8))
|
|
self._prev = shiftIn(self._prev, decrypt ? bit : value)
|
|
}
|
|
return out
|
|
}
|
|
|
|
function shiftIn (buffer, value) {
|
|
var len = buffer.length
|
|
var i = -1
|
|
var out = Buffer.allocUnsafe(buffer.length)
|
|
buffer = Buffer.concat([buffer, Buffer.from([value])])
|
|
|
|
while (++i < len) {
|
|
out[i] = buffer[i] << 1 | buffer[i + 1] >> (7)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
exports.encrypt = function (self, chunk, decrypt) {
|
|
var len = chunk.length
|
|
var out = Buffer.allocUnsafe(len)
|
|
var i = -1
|
|
|
|
while (++i < len) {
|
|
out[i] = encryptByte(self, chunk[i], decrypt)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/modes/cfb8.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/browserify-aes/modes/cfb8.js ***!
|
|
\***************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
function encryptByte (self, byteParam, decrypt) {
|
|
var pad = self._cipher.encryptBlock(self._prev)
|
|
var out = pad[0] ^ byteParam
|
|
|
|
self._prev = Buffer.concat([
|
|
self._prev.slice(1),
|
|
Buffer.from([decrypt ? byteParam : out])
|
|
])
|
|
|
|
return out
|
|
}
|
|
|
|
exports.encrypt = function (self, chunk, decrypt) {
|
|
var len = chunk.length
|
|
var out = Buffer.allocUnsafe(len)
|
|
var i = -1
|
|
|
|
while (++i < len) {
|
|
out[i] = encryptByte(self, chunk[i], decrypt)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/modes/ctr.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/browserify-aes/modes/ctr.js ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var xor = __webpack_require__(/*! buffer-xor */ "./node_modules/buffer-xor/index.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var incr32 = __webpack_require__(/*! ../incr32 */ "./node_modules/browserify-aes/incr32.js")
|
|
|
|
function getBlock (self) {
|
|
var out = self._cipher.encryptBlockRaw(self._prev)
|
|
incr32(self._prev)
|
|
return out
|
|
}
|
|
|
|
var blockSize = 16
|
|
exports.encrypt = function (self, chunk) {
|
|
var chunkNum = Math.ceil(chunk.length / blockSize)
|
|
var start = self._cache.length
|
|
self._cache = Buffer.concat([
|
|
self._cache,
|
|
Buffer.allocUnsafe(chunkNum * blockSize)
|
|
])
|
|
for (var i = 0; i < chunkNum; i++) {
|
|
var out = getBlock(self)
|
|
var offset = start + i * blockSize
|
|
self._cache.writeUInt32BE(out[0], offset + 0)
|
|
self._cache.writeUInt32BE(out[1], offset + 4)
|
|
self._cache.writeUInt32BE(out[2], offset + 8)
|
|
self._cache.writeUInt32BE(out[3], offset + 12)
|
|
}
|
|
var pad = self._cache.slice(0, chunk.length)
|
|
self._cache = self._cache.slice(chunk.length)
|
|
return xor(chunk, pad)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/modes/ecb.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/browserify-aes/modes/ecb.js ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
exports.encrypt = function (self, block) {
|
|
return self._cipher.encryptBlock(block)
|
|
}
|
|
|
|
exports.decrypt = function (self, block) {
|
|
return self._cipher.decryptBlock(block)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/modes/index.js":
|
|
/*!****************************************************!*\
|
|
!*** ./node_modules/browserify-aes/modes/index.js ***!
|
|
\****************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var modeModules = {
|
|
ECB: __webpack_require__(/*! ./ecb */ "./node_modules/browserify-aes/modes/ecb.js"),
|
|
CBC: __webpack_require__(/*! ./cbc */ "./node_modules/browserify-aes/modes/cbc.js"),
|
|
CFB: __webpack_require__(/*! ./cfb */ "./node_modules/browserify-aes/modes/cfb.js"),
|
|
CFB8: __webpack_require__(/*! ./cfb8 */ "./node_modules/browserify-aes/modes/cfb8.js"),
|
|
CFB1: __webpack_require__(/*! ./cfb1 */ "./node_modules/browserify-aes/modes/cfb1.js"),
|
|
OFB: __webpack_require__(/*! ./ofb */ "./node_modules/browserify-aes/modes/ofb.js"),
|
|
CTR: __webpack_require__(/*! ./ctr */ "./node_modules/browserify-aes/modes/ctr.js"),
|
|
GCM: __webpack_require__(/*! ./ctr */ "./node_modules/browserify-aes/modes/ctr.js")
|
|
}
|
|
|
|
var modes = __webpack_require__(/*! ./list.json */ "./node_modules/browserify-aes/modes/list.json")
|
|
|
|
for (var key in modes) {
|
|
modes[key].module = modeModules[modes[key].mode]
|
|
}
|
|
|
|
module.exports = modes
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/modes/list.json":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/browserify-aes/modes/list.json ***!
|
|
\*****************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = JSON.parse('{"aes-128-ecb":{"cipher":"AES","key":128,"iv":0,"mode":"ECB","type":"block"},"aes-192-ecb":{"cipher":"AES","key":192,"iv":0,"mode":"ECB","type":"block"},"aes-256-ecb":{"cipher":"AES","key":256,"iv":0,"mode":"ECB","type":"block"},"aes-128-cbc":{"cipher":"AES","key":128,"iv":16,"mode":"CBC","type":"block"},"aes-192-cbc":{"cipher":"AES","key":192,"iv":16,"mode":"CBC","type":"block"},"aes-256-cbc":{"cipher":"AES","key":256,"iv":16,"mode":"CBC","type":"block"},"aes128":{"cipher":"AES","key":128,"iv":16,"mode":"CBC","type":"block"},"aes192":{"cipher":"AES","key":192,"iv":16,"mode":"CBC","type":"block"},"aes256":{"cipher":"AES","key":256,"iv":16,"mode":"CBC","type":"block"},"aes-128-cfb":{"cipher":"AES","key":128,"iv":16,"mode":"CFB","type":"stream"},"aes-192-cfb":{"cipher":"AES","key":192,"iv":16,"mode":"CFB","type":"stream"},"aes-256-cfb":{"cipher":"AES","key":256,"iv":16,"mode":"CFB","type":"stream"},"aes-128-cfb8":{"cipher":"AES","key":128,"iv":16,"mode":"CFB8","type":"stream"},"aes-192-cfb8":{"cipher":"AES","key":192,"iv":16,"mode":"CFB8","type":"stream"},"aes-256-cfb8":{"cipher":"AES","key":256,"iv":16,"mode":"CFB8","type":"stream"},"aes-128-cfb1":{"cipher":"AES","key":128,"iv":16,"mode":"CFB1","type":"stream"},"aes-192-cfb1":{"cipher":"AES","key":192,"iv":16,"mode":"CFB1","type":"stream"},"aes-256-cfb1":{"cipher":"AES","key":256,"iv":16,"mode":"CFB1","type":"stream"},"aes-128-ofb":{"cipher":"AES","key":128,"iv":16,"mode":"OFB","type":"stream"},"aes-192-ofb":{"cipher":"AES","key":192,"iv":16,"mode":"OFB","type":"stream"},"aes-256-ofb":{"cipher":"AES","key":256,"iv":16,"mode":"OFB","type":"stream"},"aes-128-ctr":{"cipher":"AES","key":128,"iv":16,"mode":"CTR","type":"stream"},"aes-192-ctr":{"cipher":"AES","key":192,"iv":16,"mode":"CTR","type":"stream"},"aes-256-ctr":{"cipher":"AES","key":256,"iv":16,"mode":"CTR","type":"stream"},"aes-128-gcm":{"cipher":"AES","key":128,"iv":12,"mode":"GCM","type":"auth"},"aes-192-gcm":{"cipher":"AES","key":192,"iv":12,"mode":"GCM","type":"auth"},"aes-256-gcm":{"cipher":"AES","key":256,"iv":12,"mode":"GCM","type":"auth"}}');
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/modes/ofb.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/browserify-aes/modes/ofb.js ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
var xor = __webpack_require__(/*! buffer-xor */ "./node_modules/buffer-xor/index.js")
|
|
|
|
function getBlock (self) {
|
|
self._prev = self._cipher.encryptBlock(self._prev)
|
|
return self._prev
|
|
}
|
|
|
|
exports.encrypt = function (self, chunk) {
|
|
while (self._cache.length < chunk.length) {
|
|
self._cache = Buffer.concat([self._cache, getBlock(self)])
|
|
}
|
|
|
|
var pad = self._cache.slice(0, chunk.length)
|
|
self._cache = self._cache.slice(chunk.length)
|
|
return xor(chunk, pad)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-aes/streamCipher.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/browserify-aes/streamCipher.js ***!
|
|
\*****************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var aes = __webpack_require__(/*! ./aes */ "./node_modules/browserify-aes/aes.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var Transform = __webpack_require__(/*! cipher-base */ "./node_modules/cipher-base/index.js")
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
|
|
function StreamCipher (mode, key, iv, decrypt) {
|
|
Transform.call(this)
|
|
|
|
this._cipher = new aes.AES(key)
|
|
this._prev = Buffer.from(iv)
|
|
this._cache = Buffer.allocUnsafe(0)
|
|
this._secCache = Buffer.allocUnsafe(0)
|
|
this._decrypt = decrypt
|
|
this._mode = mode
|
|
}
|
|
|
|
inherits(StreamCipher, Transform)
|
|
|
|
StreamCipher.prototype._update = function (chunk) {
|
|
return this._mode.encrypt(this, chunk, this._decrypt)
|
|
}
|
|
|
|
StreamCipher.prototype._final = function () {
|
|
this._cipher.scrub()
|
|
}
|
|
|
|
module.exports = StreamCipher
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-cipher/browser.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/browserify-cipher/browser.js ***!
|
|
\***************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var DES = __webpack_require__(/*! browserify-des */ "./node_modules/browserify-des/index.js")
|
|
var aes = __webpack_require__(/*! browserify-aes/browser */ "./node_modules/browserify-aes/browser.js")
|
|
var aesModes = __webpack_require__(/*! browserify-aes/modes */ "./node_modules/browserify-aes/modes/index.js")
|
|
var desModes = __webpack_require__(/*! browserify-des/modes */ "./node_modules/browserify-des/modes.js")
|
|
var ebtk = __webpack_require__(/*! evp_bytestokey */ "./node_modules/evp_bytestokey/index.js")
|
|
|
|
function createCipher (suite, password) {
|
|
suite = suite.toLowerCase()
|
|
|
|
var keyLen, ivLen
|
|
if (aesModes[suite]) {
|
|
keyLen = aesModes[suite].key
|
|
ivLen = aesModes[suite].iv
|
|
} else if (desModes[suite]) {
|
|
keyLen = desModes[suite].key * 8
|
|
ivLen = desModes[suite].iv
|
|
} else {
|
|
throw new TypeError('invalid suite type')
|
|
}
|
|
|
|
var keys = ebtk(password, false, keyLen, ivLen)
|
|
return createCipheriv(suite, keys.key, keys.iv)
|
|
}
|
|
|
|
function createDecipher (suite, password) {
|
|
suite = suite.toLowerCase()
|
|
|
|
var keyLen, ivLen
|
|
if (aesModes[suite]) {
|
|
keyLen = aesModes[suite].key
|
|
ivLen = aesModes[suite].iv
|
|
} else if (desModes[suite]) {
|
|
keyLen = desModes[suite].key * 8
|
|
ivLen = desModes[suite].iv
|
|
} else {
|
|
throw new TypeError('invalid suite type')
|
|
}
|
|
|
|
var keys = ebtk(password, false, keyLen, ivLen)
|
|
return createDecipheriv(suite, keys.key, keys.iv)
|
|
}
|
|
|
|
function createCipheriv (suite, key, iv) {
|
|
suite = suite.toLowerCase()
|
|
if (aesModes[suite]) return aes.createCipheriv(suite, key, iv)
|
|
if (desModes[suite]) return new DES({ key: key, iv: iv, mode: suite })
|
|
|
|
throw new TypeError('invalid suite type')
|
|
}
|
|
|
|
function createDecipheriv (suite, key, iv) {
|
|
suite = suite.toLowerCase()
|
|
if (aesModes[suite]) return aes.createDecipheriv(suite, key, iv)
|
|
if (desModes[suite]) return new DES({ key: key, iv: iv, mode: suite, decrypt: true })
|
|
|
|
throw new TypeError('invalid suite type')
|
|
}
|
|
|
|
function getCiphers () {
|
|
return Object.keys(desModes).concat(aes.getCiphers())
|
|
}
|
|
|
|
exports.createCipher = exports.Cipher = createCipher
|
|
exports.createCipheriv = exports.Cipheriv = createCipheriv
|
|
exports.createDecipher = exports.Decipher = createDecipher
|
|
exports.createDecipheriv = exports.Decipheriv = createDecipheriv
|
|
exports.listCiphers = exports.getCiphers = getCiphers
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-des/index.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/browserify-des/index.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var CipherBase = __webpack_require__(/*! cipher-base */ "./node_modules/cipher-base/index.js")
|
|
var des = __webpack_require__(/*! des.js */ "./node_modules/des.js/lib/des.js")
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var modes = {
|
|
'des-ede3-cbc': des.CBC.instantiate(des.EDE),
|
|
'des-ede3': des.EDE,
|
|
'des-ede-cbc': des.CBC.instantiate(des.EDE),
|
|
'des-ede': des.EDE,
|
|
'des-cbc': des.CBC.instantiate(des.DES),
|
|
'des-ecb': des.DES
|
|
}
|
|
modes.des = modes['des-cbc']
|
|
modes.des3 = modes['des-ede3-cbc']
|
|
module.exports = DES
|
|
inherits(DES, CipherBase)
|
|
function DES (opts) {
|
|
CipherBase.call(this)
|
|
var modeName = opts.mode.toLowerCase()
|
|
var mode = modes[modeName]
|
|
var type
|
|
if (opts.decrypt) {
|
|
type = 'decrypt'
|
|
} else {
|
|
type = 'encrypt'
|
|
}
|
|
var key = opts.key
|
|
if (!Buffer.isBuffer(key)) {
|
|
key = Buffer.from(key)
|
|
}
|
|
if (modeName === 'des-ede' || modeName === 'des-ede-cbc') {
|
|
key = Buffer.concat([key, key.slice(0, 8)])
|
|
}
|
|
var iv = opts.iv
|
|
if (!Buffer.isBuffer(iv)) {
|
|
iv = Buffer.from(iv)
|
|
}
|
|
this._des = mode.create({
|
|
key: key,
|
|
iv: iv,
|
|
type: type
|
|
})
|
|
}
|
|
DES.prototype._update = function (data) {
|
|
return Buffer.from(this._des.update(data))
|
|
}
|
|
DES.prototype._final = function () {
|
|
return Buffer.from(this._des.final())
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-des/modes.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/browserify-des/modes.js ***!
|
|
\**********************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
exports["des-ecb"] = {
|
|
key: 8,
|
|
iv: 0
|
|
}
|
|
exports["des-cbc"] = exports.des = {
|
|
key: 8,
|
|
iv: 8
|
|
}
|
|
exports["des-ede3-cbc"] = exports.des3 = {
|
|
key: 24,
|
|
iv: 8
|
|
}
|
|
exports["des-ede3"] = {
|
|
key: 24,
|
|
iv: 0
|
|
}
|
|
exports["des-ede-cbc"] = {
|
|
key: 16,
|
|
iv: 8
|
|
}
|
|
exports["des-ede"] = {
|
|
key: 16,
|
|
iv: 0
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-rsa/index.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/browserify-rsa/index.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/bn.js/lib/bn.js")
|
|
var randomBytes = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js")
|
|
|
|
function blind (priv) {
|
|
var r = getr(priv)
|
|
var blinder = r.toRed(BN.mont(priv.modulus)).redPow(new BN(priv.publicExponent)).fromRed()
|
|
return { blinder: blinder, unblinder: r.invm(priv.modulus) }
|
|
}
|
|
|
|
function getr (priv) {
|
|
var len = priv.modulus.byteLength()
|
|
var r
|
|
do {
|
|
r = new BN(randomBytes(len))
|
|
} while (r.cmp(priv.modulus) >= 0 || !r.umod(priv.prime1) || !r.umod(priv.prime2))
|
|
return r
|
|
}
|
|
|
|
function crt (msg, priv) {
|
|
var blinds = blind(priv)
|
|
var len = priv.modulus.byteLength()
|
|
var blinded = new BN(msg).mul(blinds.blinder).umod(priv.modulus)
|
|
var c1 = blinded.toRed(BN.mont(priv.prime1))
|
|
var c2 = blinded.toRed(BN.mont(priv.prime2))
|
|
var qinv = priv.coefficient
|
|
var p = priv.prime1
|
|
var q = priv.prime2
|
|
var m1 = c1.redPow(priv.exponent1).fromRed()
|
|
var m2 = c2.redPow(priv.exponent2).fromRed()
|
|
var h = m1.isub(m2).imul(qinv).umod(p).imul(q)
|
|
return m2.iadd(h).imul(blinds.unblinder).umod(priv.modulus).toArrayLike(Buffer, 'be', len)
|
|
}
|
|
crt.getr = getr
|
|
|
|
module.exports = crt
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-sign/algos.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/browserify-sign/algos.js ***!
|
|
\***********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
module.exports = __webpack_require__(/*! ./browser/algorithms.json */ "./node_modules/browserify-sign/browser/algorithms.json")
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-sign/browser/algorithms.json":
|
|
/*!**************************************************************!*\
|
|
!*** ./node_modules/browserify-sign/browser/algorithms.json ***!
|
|
\**************************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = JSON.parse('{"sha224WithRSAEncryption":{"sign":"rsa","hash":"sha224","id":"302d300d06096086480165030402040500041c"},"RSA-SHA224":{"sign":"ecdsa/rsa","hash":"sha224","id":"302d300d06096086480165030402040500041c"},"sha256WithRSAEncryption":{"sign":"rsa","hash":"sha256","id":"3031300d060960864801650304020105000420"},"RSA-SHA256":{"sign":"ecdsa/rsa","hash":"sha256","id":"3031300d060960864801650304020105000420"},"sha384WithRSAEncryption":{"sign":"rsa","hash":"sha384","id":"3041300d060960864801650304020205000430"},"RSA-SHA384":{"sign":"ecdsa/rsa","hash":"sha384","id":"3041300d060960864801650304020205000430"},"sha512WithRSAEncryption":{"sign":"rsa","hash":"sha512","id":"3051300d060960864801650304020305000440"},"RSA-SHA512":{"sign":"ecdsa/rsa","hash":"sha512","id":"3051300d060960864801650304020305000440"},"RSA-SHA1":{"sign":"rsa","hash":"sha1","id":"3021300906052b0e03021a05000414"},"ecdsa-with-SHA1":{"sign":"ecdsa","hash":"sha1","id":""},"sha256":{"sign":"ecdsa","hash":"sha256","id":""},"sha224":{"sign":"ecdsa","hash":"sha224","id":""},"sha384":{"sign":"ecdsa","hash":"sha384","id":""},"sha512":{"sign":"ecdsa","hash":"sha512","id":""},"DSA-SHA":{"sign":"dsa","hash":"sha1","id":""},"DSA-SHA1":{"sign":"dsa","hash":"sha1","id":""},"DSA":{"sign":"dsa","hash":"sha1","id":""},"DSA-WITH-SHA224":{"sign":"dsa","hash":"sha224","id":""},"DSA-SHA224":{"sign":"dsa","hash":"sha224","id":""},"DSA-WITH-SHA256":{"sign":"dsa","hash":"sha256","id":""},"DSA-SHA256":{"sign":"dsa","hash":"sha256","id":""},"DSA-WITH-SHA384":{"sign":"dsa","hash":"sha384","id":""},"DSA-SHA384":{"sign":"dsa","hash":"sha384","id":""},"DSA-WITH-SHA512":{"sign":"dsa","hash":"sha512","id":""},"DSA-SHA512":{"sign":"dsa","hash":"sha512","id":""},"DSA-RIPEMD160":{"sign":"dsa","hash":"rmd160","id":""},"ripemd160WithRSA":{"sign":"rsa","hash":"rmd160","id":"3021300906052b2403020105000414"},"RSA-RIPEMD160":{"sign":"rsa","hash":"rmd160","id":"3021300906052b2403020105000414"},"md5WithRSAEncryption":{"sign":"rsa","hash":"md5","id":"3020300c06082a864886f70d020505000410"},"RSA-MD5":{"sign":"rsa","hash":"md5","id":"3020300c06082a864886f70d020505000410"}}');
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-sign/browser/curves.json":
|
|
/*!**********************************************************!*\
|
|
!*** ./node_modules/browserify-sign/browser/curves.json ***!
|
|
\**********************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = JSON.parse('{"1.3.132.0.10":"secp256k1","1.3.132.0.33":"p224","1.2.840.10045.3.1.1":"p192","1.2.840.10045.3.1.7":"p256","1.3.132.0.34":"p384","1.3.132.0.35":"p521"}');
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-sign/browser/index.js":
|
|
/*!*******************************************************!*\
|
|
!*** ./node_modules/browserify-sign/browser/index.js ***!
|
|
\*******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var createHash = __webpack_require__(/*! create-hash */ "./node_modules/create-hash/browser.js")
|
|
var stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var sign = __webpack_require__(/*! ./sign */ "./node_modules/browserify-sign/browser/sign.js")
|
|
var verify = __webpack_require__(/*! ./verify */ "./node_modules/browserify-sign/browser/verify.js")
|
|
|
|
var algorithms = __webpack_require__(/*! ./algorithms.json */ "./node_modules/browserify-sign/browser/algorithms.json")
|
|
Object.keys(algorithms).forEach(function (key) {
|
|
algorithms[key].id = Buffer.from(algorithms[key].id, 'hex')
|
|
algorithms[key.toLowerCase()] = algorithms[key]
|
|
})
|
|
|
|
function Sign (algorithm) {
|
|
stream.Writable.call(this)
|
|
|
|
var data = algorithms[algorithm]
|
|
if (!data) throw new Error('Unknown message digest')
|
|
|
|
this._hashType = data.hash
|
|
this._hash = createHash(data.hash)
|
|
this._tag = data.id
|
|
this._signType = data.sign
|
|
}
|
|
inherits(Sign, stream.Writable)
|
|
|
|
Sign.prototype._write = function _write (data, _, done) {
|
|
this._hash.update(data)
|
|
done()
|
|
}
|
|
|
|
Sign.prototype.update = function update (data, enc) {
|
|
if (typeof data === 'string') data = Buffer.from(data, enc)
|
|
|
|
this._hash.update(data)
|
|
return this
|
|
}
|
|
|
|
Sign.prototype.sign = function signMethod (key, enc) {
|
|
this.end()
|
|
var hash = this._hash.digest()
|
|
var sig = sign(hash, key, this._hashType, this._signType, this._tag)
|
|
|
|
return enc ? sig.toString(enc) : sig
|
|
}
|
|
|
|
function Verify (algorithm) {
|
|
stream.Writable.call(this)
|
|
|
|
var data = algorithms[algorithm]
|
|
if (!data) throw new Error('Unknown message digest')
|
|
|
|
this._hash = createHash(data.hash)
|
|
this._tag = data.id
|
|
this._signType = data.sign
|
|
}
|
|
inherits(Verify, stream.Writable)
|
|
|
|
Verify.prototype._write = function _write (data, _, done) {
|
|
this._hash.update(data)
|
|
done()
|
|
}
|
|
|
|
Verify.prototype.update = function update (data, enc) {
|
|
if (typeof data === 'string') data = Buffer.from(data, enc)
|
|
|
|
this._hash.update(data)
|
|
return this
|
|
}
|
|
|
|
Verify.prototype.verify = function verifyMethod (key, sig, enc) {
|
|
if (typeof sig === 'string') sig = Buffer.from(sig, enc)
|
|
|
|
this.end()
|
|
var hash = this._hash.digest()
|
|
return verify(sig, hash, key, this._signType, this._tag)
|
|
}
|
|
|
|
function createSign (algorithm) {
|
|
return new Sign(algorithm)
|
|
}
|
|
|
|
function createVerify (algorithm) {
|
|
return new Verify(algorithm)
|
|
}
|
|
|
|
module.exports = {
|
|
Sign: createSign,
|
|
Verify: createVerify,
|
|
createSign: createSign,
|
|
createVerify: createVerify
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-sign/browser/sign.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/browserify-sign/browser/sign.js ***!
|
|
\******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var createHmac = __webpack_require__(/*! create-hmac */ "./node_modules/create-hmac/browser.js")
|
|
var crt = __webpack_require__(/*! browserify-rsa */ "./node_modules/browserify-rsa/index.js")
|
|
var EC = __webpack_require__(/*! elliptic */ "./node_modules/elliptic/lib/elliptic.js").ec
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/bn.js/lib/bn.js")
|
|
var parseKeys = __webpack_require__(/*! parse-asn1 */ "./node_modules/parse-asn1/index.js")
|
|
var curves = __webpack_require__(/*! ./curves.json */ "./node_modules/browserify-sign/browser/curves.json")
|
|
|
|
function sign (hash, key, hashType, signType, tag) {
|
|
var priv = parseKeys(key)
|
|
if (priv.curve) {
|
|
// rsa keys can be interpreted as ecdsa ones in openssl
|
|
if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type')
|
|
return ecSign(hash, priv)
|
|
} else if (priv.type === 'dsa') {
|
|
if (signType !== 'dsa') throw new Error('wrong private key type')
|
|
return dsaSign(hash, priv, hashType)
|
|
} else {
|
|
if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type')
|
|
}
|
|
hash = Buffer.concat([tag, hash])
|
|
var len = priv.modulus.byteLength()
|
|
var pad = [0, 1]
|
|
while (hash.length + pad.length + 1 < len) pad.push(0xff)
|
|
pad.push(0x00)
|
|
var i = -1
|
|
while (++i < hash.length) pad.push(hash[i])
|
|
|
|
var out = crt(pad, priv)
|
|
return out
|
|
}
|
|
|
|
function ecSign (hash, priv) {
|
|
var curveId = curves[priv.curve.join('.')]
|
|
if (!curveId) throw new Error('unknown curve ' + priv.curve.join('.'))
|
|
|
|
var curve = new EC(curveId)
|
|
var key = curve.keyFromPrivate(priv.privateKey)
|
|
var out = key.sign(hash)
|
|
|
|
return Buffer.from(out.toDER())
|
|
}
|
|
|
|
function dsaSign (hash, priv, algo) {
|
|
var x = priv.params.priv_key
|
|
var p = priv.params.p
|
|
var q = priv.params.q
|
|
var g = priv.params.g
|
|
var r = new BN(0)
|
|
var k
|
|
var H = bits2int(hash, q).mod(q)
|
|
var s = false
|
|
var kv = getKey(x, q, hash, algo)
|
|
while (s === false) {
|
|
k = makeKey(q, kv, algo)
|
|
r = makeR(g, k, p, q)
|
|
s = k.invm(q).imul(H.add(x.mul(r))).mod(q)
|
|
if (s.cmpn(0) === 0) {
|
|
s = false
|
|
r = new BN(0)
|
|
}
|
|
}
|
|
return toDER(r, s)
|
|
}
|
|
|
|
function toDER (r, s) {
|
|
r = r.toArray()
|
|
s = s.toArray()
|
|
|
|
// Pad values
|
|
if (r[0] & 0x80) r = [0].concat(r)
|
|
if (s[0] & 0x80) s = [0].concat(s)
|
|
|
|
var total = r.length + s.length + 4
|
|
var res = [0x30, total, 0x02, r.length]
|
|
res = res.concat(r, [0x02, s.length], s)
|
|
return Buffer.from(res)
|
|
}
|
|
|
|
function getKey (x, q, hash, algo) {
|
|
x = Buffer.from(x.toArray())
|
|
if (x.length < q.byteLength()) {
|
|
var zeros = Buffer.alloc(q.byteLength() - x.length)
|
|
x = Buffer.concat([zeros, x])
|
|
}
|
|
var hlen = hash.length
|
|
var hbits = bits2octets(hash, q)
|
|
var v = Buffer.alloc(hlen)
|
|
v.fill(1)
|
|
var k = Buffer.alloc(hlen)
|
|
k = createHmac(algo, k).update(v).update(Buffer.from([0])).update(x).update(hbits).digest()
|
|
v = createHmac(algo, k).update(v).digest()
|
|
k = createHmac(algo, k).update(v).update(Buffer.from([1])).update(x).update(hbits).digest()
|
|
v = createHmac(algo, k).update(v).digest()
|
|
return { k: k, v: v }
|
|
}
|
|
|
|
function bits2int (obits, q) {
|
|
var bits = new BN(obits)
|
|
var shift = (obits.length << 3) - q.bitLength()
|
|
if (shift > 0) bits.ishrn(shift)
|
|
return bits
|
|
}
|
|
|
|
function bits2octets (bits, q) {
|
|
bits = bits2int(bits, q)
|
|
bits = bits.mod(q)
|
|
var out = Buffer.from(bits.toArray())
|
|
if (out.length < q.byteLength()) {
|
|
var zeros = Buffer.alloc(q.byteLength() - out.length)
|
|
out = Buffer.concat([zeros, out])
|
|
}
|
|
return out
|
|
}
|
|
|
|
function makeKey (q, kv, algo) {
|
|
var t
|
|
var k
|
|
|
|
do {
|
|
t = Buffer.alloc(0)
|
|
|
|
while (t.length * 8 < q.bitLength()) {
|
|
kv.v = createHmac(algo, kv.k).update(kv.v).digest()
|
|
t = Buffer.concat([t, kv.v])
|
|
}
|
|
|
|
k = bits2int(t, q)
|
|
kv.k = createHmac(algo, kv.k).update(kv.v).update(Buffer.from([0])).digest()
|
|
kv.v = createHmac(algo, kv.k).update(kv.v).digest()
|
|
} while (k.cmp(q) !== -1)
|
|
|
|
return k
|
|
}
|
|
|
|
function makeR (g, k, p, q) {
|
|
return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q)
|
|
}
|
|
|
|
module.exports = sign
|
|
module.exports.getKey = getKey
|
|
module.exports.makeKey = makeKey
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-sign/browser/verify.js":
|
|
/*!********************************************************!*\
|
|
!*** ./node_modules/browserify-sign/browser/verify.js ***!
|
|
\********************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/bn.js/lib/bn.js")
|
|
var EC = __webpack_require__(/*! elliptic */ "./node_modules/elliptic/lib/elliptic.js").ec
|
|
var parseKeys = __webpack_require__(/*! parse-asn1 */ "./node_modules/parse-asn1/index.js")
|
|
var curves = __webpack_require__(/*! ./curves.json */ "./node_modules/browserify-sign/browser/curves.json")
|
|
|
|
function verify (sig, hash, key, signType, tag) {
|
|
var pub = parseKeys(key)
|
|
if (pub.type === 'ec') {
|
|
// rsa keys can be interpreted as ecdsa ones in openssl
|
|
if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type')
|
|
return ecVerify(sig, hash, pub)
|
|
} else if (pub.type === 'dsa') {
|
|
if (signType !== 'dsa') throw new Error('wrong public key type')
|
|
return dsaVerify(sig, hash, pub)
|
|
} else {
|
|
if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type')
|
|
}
|
|
hash = Buffer.concat([tag, hash])
|
|
var len = pub.modulus.byteLength()
|
|
var pad = [1]
|
|
var padNum = 0
|
|
while (hash.length + pad.length + 2 < len) {
|
|
pad.push(0xff)
|
|
padNum++
|
|
}
|
|
pad.push(0x00)
|
|
var i = -1
|
|
while (++i < hash.length) {
|
|
pad.push(hash[i])
|
|
}
|
|
pad = Buffer.from(pad)
|
|
var red = BN.mont(pub.modulus)
|
|
sig = new BN(sig).toRed(red)
|
|
|
|
sig = sig.redPow(new BN(pub.publicExponent))
|
|
sig = Buffer.from(sig.fromRed().toArray())
|
|
var out = padNum < 8 ? 1 : 0
|
|
len = Math.min(sig.length, pad.length)
|
|
if (sig.length !== pad.length) out = 1
|
|
|
|
i = -1
|
|
while (++i < len) out |= sig[i] ^ pad[i]
|
|
return out === 0
|
|
}
|
|
|
|
function ecVerify (sig, hash, pub) {
|
|
var curveId = curves[pub.data.algorithm.curve.join('.')]
|
|
if (!curveId) throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.'))
|
|
|
|
var curve = new EC(curveId)
|
|
var pubkey = pub.data.subjectPrivateKey.data
|
|
|
|
return curve.verify(hash, sig, pubkey)
|
|
}
|
|
|
|
function dsaVerify (sig, hash, pub) {
|
|
var p = pub.data.p
|
|
var q = pub.data.q
|
|
var g = pub.data.g
|
|
var y = pub.data.pub_key
|
|
var unpacked = parseKeys.signature.decode(sig, 'der')
|
|
var s = unpacked.s
|
|
var r = unpacked.r
|
|
checkValue(s, q)
|
|
checkValue(r, q)
|
|
var montp = BN.mont(p)
|
|
var w = s.invm(q)
|
|
var v = g.toRed(montp)
|
|
.redPow(new BN(hash).mul(w).mod(q))
|
|
.fromRed()
|
|
.mul(y.toRed(montp).redPow(r.mul(w).mod(q)).fromRed())
|
|
.mod(p)
|
|
.mod(q)
|
|
return v.cmp(r) === 0
|
|
}
|
|
|
|
function checkValue (b, q) {
|
|
if (b.cmpn(0) <= 0) throw new Error('invalid sig')
|
|
if (b.cmp(q) >= q) throw new Error('invalid sig')
|
|
}
|
|
|
|
module.exports = verify
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/lib/binding.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/lib/binding.js ***!
|
|
\*****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
|
|
/* eslint camelcase: "off" */
|
|
|
|
var assert = __webpack_require__(/*! assert */ "./node_modules/assert/build/assert.js");
|
|
|
|
var Zstream = __webpack_require__(/*! pako/lib/zlib/zstream */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/zstream.js");
|
|
var zlib_deflate = __webpack_require__(/*! pako/lib/zlib/deflate.js */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/deflate.js");
|
|
var zlib_inflate = __webpack_require__(/*! pako/lib/zlib/inflate.js */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/inflate.js");
|
|
var constants = __webpack_require__(/*! pako/lib/zlib/constants */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/constants.js");
|
|
|
|
for (var key in constants) {
|
|
exports[key] = constants[key];
|
|
}
|
|
|
|
// zlib modes
|
|
exports.NONE = 0;
|
|
exports.DEFLATE = 1;
|
|
exports.INFLATE = 2;
|
|
exports.GZIP = 3;
|
|
exports.GUNZIP = 4;
|
|
exports.DEFLATERAW = 5;
|
|
exports.INFLATERAW = 6;
|
|
exports.UNZIP = 7;
|
|
|
|
var GZIP_HEADER_ID1 = 0x1f;
|
|
var GZIP_HEADER_ID2 = 0x8b;
|
|
|
|
/**
|
|
* Emulate Node's zlib C++ layer for use by the JS layer in index.js
|
|
*/
|
|
function Zlib(mode) {
|
|
if (typeof mode !== 'number' || mode < exports.DEFLATE || mode > exports.UNZIP) {
|
|
throw new TypeError('Bad argument');
|
|
}
|
|
|
|
this.dictionary = null;
|
|
this.err = 0;
|
|
this.flush = 0;
|
|
this.init_done = false;
|
|
this.level = 0;
|
|
this.memLevel = 0;
|
|
this.mode = mode;
|
|
this.strategy = 0;
|
|
this.windowBits = 0;
|
|
this.write_in_progress = false;
|
|
this.pending_close = false;
|
|
this.gzip_id_bytes_read = 0;
|
|
}
|
|
|
|
Zlib.prototype.close = function () {
|
|
if (this.write_in_progress) {
|
|
this.pending_close = true;
|
|
return;
|
|
}
|
|
|
|
this.pending_close = false;
|
|
|
|
assert(this.init_done, 'close before init');
|
|
assert(this.mode <= exports.UNZIP);
|
|
|
|
if (this.mode === exports.DEFLATE || this.mode === exports.GZIP || this.mode === exports.DEFLATERAW) {
|
|
zlib_deflate.deflateEnd(this.strm);
|
|
} else if (this.mode === exports.INFLATE || this.mode === exports.GUNZIP || this.mode === exports.INFLATERAW || this.mode === exports.UNZIP) {
|
|
zlib_inflate.inflateEnd(this.strm);
|
|
}
|
|
|
|
this.mode = exports.NONE;
|
|
|
|
this.dictionary = null;
|
|
};
|
|
|
|
Zlib.prototype.write = function (flush, input, in_off, in_len, out, out_off, out_len) {
|
|
return this._write(true, flush, input, in_off, in_len, out, out_off, out_len);
|
|
};
|
|
|
|
Zlib.prototype.writeSync = function (flush, input, in_off, in_len, out, out_off, out_len) {
|
|
return this._write(false, flush, input, in_off, in_len, out, out_off, out_len);
|
|
};
|
|
|
|
Zlib.prototype._write = function (async, flush, input, in_off, in_len, out, out_off, out_len) {
|
|
assert.equal(arguments.length, 8);
|
|
|
|
assert(this.init_done, 'write before init');
|
|
assert(this.mode !== exports.NONE, 'already finalized');
|
|
assert.equal(false, this.write_in_progress, 'write already in progress');
|
|
assert.equal(false, this.pending_close, 'close is pending');
|
|
|
|
this.write_in_progress = true;
|
|
|
|
assert.equal(false, flush === undefined, 'must provide flush value');
|
|
|
|
this.write_in_progress = true;
|
|
|
|
if (flush !== exports.Z_NO_FLUSH && flush !== exports.Z_PARTIAL_FLUSH && flush !== exports.Z_SYNC_FLUSH && flush !== exports.Z_FULL_FLUSH && flush !== exports.Z_FINISH && flush !== exports.Z_BLOCK) {
|
|
throw new Error('Invalid flush value');
|
|
}
|
|
|
|
if (input == null) {
|
|
input = Buffer.alloc(0);
|
|
in_len = 0;
|
|
in_off = 0;
|
|
}
|
|
|
|
this.strm.avail_in = in_len;
|
|
this.strm.input = input;
|
|
this.strm.next_in = in_off;
|
|
this.strm.avail_out = out_len;
|
|
this.strm.output = out;
|
|
this.strm.next_out = out_off;
|
|
this.flush = flush;
|
|
|
|
if (!async) {
|
|
// sync version
|
|
this._process();
|
|
|
|
if (this._checkError()) {
|
|
return this._afterSync();
|
|
}
|
|
return;
|
|
}
|
|
|
|
// async version
|
|
var self = this;
|
|
process.nextTick(function () {
|
|
self._process();
|
|
self._after();
|
|
});
|
|
|
|
return this;
|
|
};
|
|
|
|
Zlib.prototype._afterSync = function () {
|
|
var avail_out = this.strm.avail_out;
|
|
var avail_in = this.strm.avail_in;
|
|
|
|
this.write_in_progress = false;
|
|
|
|
return [avail_in, avail_out];
|
|
};
|
|
|
|
Zlib.prototype._process = function () {
|
|
var next_expected_header_byte = null;
|
|
|
|
// If the avail_out is left at 0, then it means that it ran out
|
|
// of room. If there was avail_out left over, then it means
|
|
// that all of the input was consumed.
|
|
switch (this.mode) {
|
|
case exports.DEFLATE:
|
|
case exports.GZIP:
|
|
case exports.DEFLATERAW:
|
|
this.err = zlib_deflate.deflate(this.strm, this.flush);
|
|
break;
|
|
case exports.UNZIP:
|
|
if (this.strm.avail_in > 0) {
|
|
next_expected_header_byte = this.strm.next_in;
|
|
}
|
|
|
|
switch (this.gzip_id_bytes_read) {
|
|
case 0:
|
|
if (next_expected_header_byte === null) {
|
|
break;
|
|
}
|
|
|
|
if (this.strm.input[next_expected_header_byte] === GZIP_HEADER_ID1) {
|
|
this.gzip_id_bytes_read = 1;
|
|
next_expected_header_byte++;
|
|
|
|
if (this.strm.avail_in === 1) {
|
|
// The only available byte was already read.
|
|
break;
|
|
}
|
|
} else {
|
|
this.mode = exports.INFLATE;
|
|
break;
|
|
}
|
|
|
|
// fallthrough
|
|
case 1:
|
|
if (next_expected_header_byte === null) {
|
|
break;
|
|
}
|
|
|
|
if (this.strm.input[next_expected_header_byte] === GZIP_HEADER_ID2) {
|
|
this.gzip_id_bytes_read = 2;
|
|
this.mode = exports.GUNZIP;
|
|
} else {
|
|
// There is no actual difference between INFLATE and INFLATERAW
|
|
// (after initialization).
|
|
this.mode = exports.INFLATE;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
throw new Error('invalid number of gzip magic number bytes read');
|
|
}
|
|
|
|
// fallthrough
|
|
case exports.INFLATE:
|
|
case exports.GUNZIP:
|
|
case exports.INFLATERAW:
|
|
this.err = zlib_inflate.inflate(this.strm, this.flush
|
|
|
|
// If data was encoded with dictionary
|
|
);if (this.err === exports.Z_NEED_DICT && this.dictionary) {
|
|
// Load it
|
|
this.err = zlib_inflate.inflateSetDictionary(this.strm, this.dictionary);
|
|
if (this.err === exports.Z_OK) {
|
|
// And try to decode again
|
|
this.err = zlib_inflate.inflate(this.strm, this.flush);
|
|
} else if (this.err === exports.Z_DATA_ERROR) {
|
|
// Both inflateSetDictionary() and inflate() return Z_DATA_ERROR.
|
|
// Make it possible for After() to tell a bad dictionary from bad
|
|
// input.
|
|
this.err = exports.Z_NEED_DICT;
|
|
}
|
|
}
|
|
while (this.strm.avail_in > 0 && this.mode === exports.GUNZIP && this.err === exports.Z_STREAM_END && this.strm.next_in[0] !== 0x00) {
|
|
// Bytes remain in input buffer. Perhaps this is another compressed
|
|
// member in the same archive, or just trailing garbage.
|
|
// Trailing zero bytes are okay, though, since they are frequently
|
|
// used for padding.
|
|
|
|
this.reset();
|
|
this.err = zlib_inflate.inflate(this.strm, this.flush);
|
|
}
|
|
break;
|
|
default:
|
|
throw new Error('Unknown mode ' + this.mode);
|
|
}
|
|
};
|
|
|
|
Zlib.prototype._checkError = function () {
|
|
// Acceptable error states depend on the type of zlib stream.
|
|
switch (this.err) {
|
|
case exports.Z_OK:
|
|
case exports.Z_BUF_ERROR:
|
|
if (this.strm.avail_out !== 0 && this.flush === exports.Z_FINISH) {
|
|
this._error('unexpected end of file');
|
|
return false;
|
|
}
|
|
break;
|
|
case exports.Z_STREAM_END:
|
|
// normal statuses, not fatal
|
|
break;
|
|
case exports.Z_NEED_DICT:
|
|
if (this.dictionary == null) {
|
|
this._error('Missing dictionary');
|
|
} else {
|
|
this._error('Bad dictionary');
|
|
}
|
|
return false;
|
|
default:
|
|
// something else.
|
|
this._error('Zlib error');
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
Zlib.prototype._after = function () {
|
|
if (!this._checkError()) {
|
|
return;
|
|
}
|
|
|
|
var avail_out = this.strm.avail_out;
|
|
var avail_in = this.strm.avail_in;
|
|
|
|
this.write_in_progress = false;
|
|
|
|
// call the write() cb
|
|
this.callback(avail_in, avail_out);
|
|
|
|
if (this.pending_close) {
|
|
this.close();
|
|
}
|
|
};
|
|
|
|
Zlib.prototype._error = function (message) {
|
|
if (this.strm.msg) {
|
|
message = this.strm.msg;
|
|
}
|
|
this.onerror(message, this.err
|
|
|
|
// no hope of rescue.
|
|
);this.write_in_progress = false;
|
|
if (this.pending_close) {
|
|
this.close();
|
|
}
|
|
};
|
|
|
|
Zlib.prototype.init = function (windowBits, level, memLevel, strategy, dictionary) {
|
|
assert(arguments.length === 4 || arguments.length === 5, 'init(windowBits, level, memLevel, strategy, [dictionary])');
|
|
|
|
assert(windowBits >= 8 && windowBits <= 15, 'invalid windowBits');
|
|
assert(level >= -1 && level <= 9, 'invalid compression level');
|
|
|
|
assert(memLevel >= 1 && memLevel <= 9, 'invalid memlevel');
|
|
|
|
assert(strategy === exports.Z_FILTERED || strategy === exports.Z_HUFFMAN_ONLY || strategy === exports.Z_RLE || strategy === exports.Z_FIXED || strategy === exports.Z_DEFAULT_STRATEGY, 'invalid strategy');
|
|
|
|
this._init(level, windowBits, memLevel, strategy, dictionary);
|
|
this._setDictionary();
|
|
};
|
|
|
|
Zlib.prototype.params = function () {
|
|
throw new Error('deflateParams Not supported');
|
|
};
|
|
|
|
Zlib.prototype.reset = function () {
|
|
this._reset();
|
|
this._setDictionary();
|
|
};
|
|
|
|
Zlib.prototype._init = function (level, windowBits, memLevel, strategy, dictionary) {
|
|
this.level = level;
|
|
this.windowBits = windowBits;
|
|
this.memLevel = memLevel;
|
|
this.strategy = strategy;
|
|
|
|
this.flush = exports.Z_NO_FLUSH;
|
|
|
|
this.err = exports.Z_OK;
|
|
|
|
if (this.mode === exports.GZIP || this.mode === exports.GUNZIP) {
|
|
this.windowBits += 16;
|
|
}
|
|
|
|
if (this.mode === exports.UNZIP) {
|
|
this.windowBits += 32;
|
|
}
|
|
|
|
if (this.mode === exports.DEFLATERAW || this.mode === exports.INFLATERAW) {
|
|
this.windowBits = -1 * this.windowBits;
|
|
}
|
|
|
|
this.strm = new Zstream();
|
|
|
|
switch (this.mode) {
|
|
case exports.DEFLATE:
|
|
case exports.GZIP:
|
|
case exports.DEFLATERAW:
|
|
this.err = zlib_deflate.deflateInit2(this.strm, this.level, exports.Z_DEFLATED, this.windowBits, this.memLevel, this.strategy);
|
|
break;
|
|
case exports.INFLATE:
|
|
case exports.GUNZIP:
|
|
case exports.INFLATERAW:
|
|
case exports.UNZIP:
|
|
this.err = zlib_inflate.inflateInit2(this.strm, this.windowBits);
|
|
break;
|
|
default:
|
|
throw new Error('Unknown mode ' + this.mode);
|
|
}
|
|
|
|
if (this.err !== exports.Z_OK) {
|
|
this._error('Init error');
|
|
}
|
|
|
|
this.dictionary = dictionary;
|
|
|
|
this.write_in_progress = false;
|
|
this.init_done = true;
|
|
};
|
|
|
|
Zlib.prototype._setDictionary = function () {
|
|
if (this.dictionary == null) {
|
|
return;
|
|
}
|
|
|
|
this.err = exports.Z_OK;
|
|
|
|
switch (this.mode) {
|
|
case exports.DEFLATE:
|
|
case exports.DEFLATERAW:
|
|
this.err = zlib_deflate.deflateSetDictionary(this.strm, this.dictionary);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (this.err !== exports.Z_OK) {
|
|
this._error('Failed to set dictionary');
|
|
}
|
|
};
|
|
|
|
Zlib.prototype._reset = function () {
|
|
this.err = exports.Z_OK;
|
|
|
|
switch (this.mode) {
|
|
case exports.DEFLATE:
|
|
case exports.DEFLATERAW:
|
|
case exports.GZIP:
|
|
this.err = zlib_deflate.deflateReset(this.strm);
|
|
break;
|
|
case exports.INFLATE:
|
|
case exports.INFLATERAW:
|
|
case exports.GUNZIP:
|
|
this.err = zlib_inflate.inflateReset(this.strm);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (this.err !== exports.Z_OK) {
|
|
this._error('Failed to reset stream');
|
|
}
|
|
};
|
|
|
|
exports.Zlib = Zlib;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/lib/index.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/lib/index.js ***!
|
|
\***************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
|
|
|
|
var Buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js").Buffer;
|
|
var Transform = __webpack_require__(/*! stream */ "./node_modules/stream-browserify/index.js").Transform;
|
|
var binding = __webpack_require__(/*! ./binding */ "./node_modules/browserify-zlib/lib/binding.js");
|
|
var util = __webpack_require__(/*! util */ "./node_modules/util/util.js");
|
|
var assert = __webpack_require__(/*! assert */ "./node_modules/assert/build/assert.js").ok;
|
|
var kMaxLength = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js").kMaxLength;
|
|
var kRangeErrorMessage = 'Cannot create final Buffer. It would be larger ' + 'than 0x' + kMaxLength.toString(16) + ' bytes';
|
|
|
|
// zlib doesn't provide these, so kludge them in following the same
|
|
// const naming scheme zlib uses.
|
|
binding.Z_MIN_WINDOWBITS = 8;
|
|
binding.Z_MAX_WINDOWBITS = 15;
|
|
binding.Z_DEFAULT_WINDOWBITS = 15;
|
|
|
|
// fewer than 64 bytes per chunk is stupid.
|
|
// technically it could work with as few as 8, but even 64 bytes
|
|
// is absurdly low. Usually a MB or more is best.
|
|
binding.Z_MIN_CHUNK = 64;
|
|
binding.Z_MAX_CHUNK = Infinity;
|
|
binding.Z_DEFAULT_CHUNK = 16 * 1024;
|
|
|
|
binding.Z_MIN_MEMLEVEL = 1;
|
|
binding.Z_MAX_MEMLEVEL = 9;
|
|
binding.Z_DEFAULT_MEMLEVEL = 8;
|
|
|
|
binding.Z_MIN_LEVEL = -1;
|
|
binding.Z_MAX_LEVEL = 9;
|
|
binding.Z_DEFAULT_LEVEL = binding.Z_DEFAULT_COMPRESSION;
|
|
|
|
// expose all the zlib constants
|
|
var bkeys = Object.keys(binding);
|
|
for (var bk = 0; bk < bkeys.length; bk++) {
|
|
var bkey = bkeys[bk];
|
|
if (bkey.match(/^Z/)) {
|
|
Object.defineProperty(exports, bkey, {
|
|
enumerable: true, value: binding[bkey], writable: false
|
|
});
|
|
}
|
|
}
|
|
|
|
// translation table for return codes.
|
|
var codes = {
|
|
Z_OK: binding.Z_OK,
|
|
Z_STREAM_END: binding.Z_STREAM_END,
|
|
Z_NEED_DICT: binding.Z_NEED_DICT,
|
|
Z_ERRNO: binding.Z_ERRNO,
|
|
Z_STREAM_ERROR: binding.Z_STREAM_ERROR,
|
|
Z_DATA_ERROR: binding.Z_DATA_ERROR,
|
|
Z_MEM_ERROR: binding.Z_MEM_ERROR,
|
|
Z_BUF_ERROR: binding.Z_BUF_ERROR,
|
|
Z_VERSION_ERROR: binding.Z_VERSION_ERROR
|
|
};
|
|
|
|
var ckeys = Object.keys(codes);
|
|
for (var ck = 0; ck < ckeys.length; ck++) {
|
|
var ckey = ckeys[ck];
|
|
codes[codes[ckey]] = ckey;
|
|
}
|
|
|
|
Object.defineProperty(exports, "codes", ({
|
|
enumerable: true, value: Object.freeze(codes), writable: false
|
|
}));
|
|
|
|
exports.Deflate = Deflate;
|
|
exports.Inflate = Inflate;
|
|
exports.Gzip = Gzip;
|
|
exports.Gunzip = Gunzip;
|
|
exports.DeflateRaw = DeflateRaw;
|
|
exports.InflateRaw = InflateRaw;
|
|
exports.Unzip = Unzip;
|
|
|
|
exports.createDeflate = function (o) {
|
|
return new Deflate(o);
|
|
};
|
|
|
|
exports.createInflate = function (o) {
|
|
return new Inflate(o);
|
|
};
|
|
|
|
exports.createDeflateRaw = function (o) {
|
|
return new DeflateRaw(o);
|
|
};
|
|
|
|
exports.createInflateRaw = function (o) {
|
|
return new InflateRaw(o);
|
|
};
|
|
|
|
exports.createGzip = function (o) {
|
|
return new Gzip(o);
|
|
};
|
|
|
|
exports.createGunzip = function (o) {
|
|
return new Gunzip(o);
|
|
};
|
|
|
|
exports.createUnzip = function (o) {
|
|
return new Unzip(o);
|
|
};
|
|
|
|
// Convenience methods.
|
|
// compress/decompress a string or buffer in one step.
|
|
exports.deflate = function (buffer, opts, callback) {
|
|
if (typeof opts === 'function') {
|
|
callback = opts;
|
|
opts = {};
|
|
}
|
|
return zlibBuffer(new Deflate(opts), buffer, callback);
|
|
};
|
|
|
|
exports.deflateSync = function (buffer, opts) {
|
|
return zlibBufferSync(new Deflate(opts), buffer);
|
|
};
|
|
|
|
exports.gzip = function (buffer, opts, callback) {
|
|
if (typeof opts === 'function') {
|
|
callback = opts;
|
|
opts = {};
|
|
}
|
|
return zlibBuffer(new Gzip(opts), buffer, callback);
|
|
};
|
|
|
|
exports.gzipSync = function (buffer, opts) {
|
|
return zlibBufferSync(new Gzip(opts), buffer);
|
|
};
|
|
|
|
exports.deflateRaw = function (buffer, opts, callback) {
|
|
if (typeof opts === 'function') {
|
|
callback = opts;
|
|
opts = {};
|
|
}
|
|
return zlibBuffer(new DeflateRaw(opts), buffer, callback);
|
|
};
|
|
|
|
exports.deflateRawSync = function (buffer, opts) {
|
|
return zlibBufferSync(new DeflateRaw(opts), buffer);
|
|
};
|
|
|
|
exports.unzip = function (buffer, opts, callback) {
|
|
if (typeof opts === 'function') {
|
|
callback = opts;
|
|
opts = {};
|
|
}
|
|
return zlibBuffer(new Unzip(opts), buffer, callback);
|
|
};
|
|
|
|
exports.unzipSync = function (buffer, opts) {
|
|
return zlibBufferSync(new Unzip(opts), buffer);
|
|
};
|
|
|
|
exports.inflate = function (buffer, opts, callback) {
|
|
if (typeof opts === 'function') {
|
|
callback = opts;
|
|
opts = {};
|
|
}
|
|
return zlibBuffer(new Inflate(opts), buffer, callback);
|
|
};
|
|
|
|
exports.inflateSync = function (buffer, opts) {
|
|
return zlibBufferSync(new Inflate(opts), buffer);
|
|
};
|
|
|
|
exports.gunzip = function (buffer, opts, callback) {
|
|
if (typeof opts === 'function') {
|
|
callback = opts;
|
|
opts = {};
|
|
}
|
|
return zlibBuffer(new Gunzip(opts), buffer, callback);
|
|
};
|
|
|
|
exports.gunzipSync = function (buffer, opts) {
|
|
return zlibBufferSync(new Gunzip(opts), buffer);
|
|
};
|
|
|
|
exports.inflateRaw = function (buffer, opts, callback) {
|
|
if (typeof opts === 'function') {
|
|
callback = opts;
|
|
opts = {};
|
|
}
|
|
return zlibBuffer(new InflateRaw(opts), buffer, callback);
|
|
};
|
|
|
|
exports.inflateRawSync = function (buffer, opts) {
|
|
return zlibBufferSync(new InflateRaw(opts), buffer);
|
|
};
|
|
|
|
function zlibBuffer(engine, buffer, callback) {
|
|
var buffers = [];
|
|
var nread = 0;
|
|
|
|
engine.on('error', onError);
|
|
engine.on('end', onEnd);
|
|
|
|
engine.end(buffer);
|
|
flow();
|
|
|
|
function flow() {
|
|
var chunk;
|
|
while (null !== (chunk = engine.read())) {
|
|
buffers.push(chunk);
|
|
nread += chunk.length;
|
|
}
|
|
engine.once('readable', flow);
|
|
}
|
|
|
|
function onError(err) {
|
|
engine.removeListener('end', onEnd);
|
|
engine.removeListener('readable', flow);
|
|
callback(err);
|
|
}
|
|
|
|
function onEnd() {
|
|
var buf;
|
|
var err = null;
|
|
|
|
if (nread >= kMaxLength) {
|
|
err = new RangeError(kRangeErrorMessage);
|
|
} else {
|
|
buf = Buffer.concat(buffers, nread);
|
|
}
|
|
|
|
buffers = [];
|
|
engine.close();
|
|
callback(err, buf);
|
|
}
|
|
}
|
|
|
|
function zlibBufferSync(engine, buffer) {
|
|
if (typeof buffer === 'string') buffer = Buffer.from(buffer);
|
|
|
|
if (!Buffer.isBuffer(buffer)) throw new TypeError('Not a string or buffer');
|
|
|
|
var flushFlag = engine._finishFlushFlag;
|
|
|
|
return engine._processChunk(buffer, flushFlag);
|
|
}
|
|
|
|
// generic zlib
|
|
// minimal 2-byte header
|
|
function Deflate(opts) {
|
|
if (!(this instanceof Deflate)) return new Deflate(opts);
|
|
Zlib.call(this, opts, binding.DEFLATE);
|
|
}
|
|
|
|
function Inflate(opts) {
|
|
if (!(this instanceof Inflate)) return new Inflate(opts);
|
|
Zlib.call(this, opts, binding.INFLATE);
|
|
}
|
|
|
|
// gzip - bigger header, same deflate compression
|
|
function Gzip(opts) {
|
|
if (!(this instanceof Gzip)) return new Gzip(opts);
|
|
Zlib.call(this, opts, binding.GZIP);
|
|
}
|
|
|
|
function Gunzip(opts) {
|
|
if (!(this instanceof Gunzip)) return new Gunzip(opts);
|
|
Zlib.call(this, opts, binding.GUNZIP);
|
|
}
|
|
|
|
// raw - no header
|
|
function DeflateRaw(opts) {
|
|
if (!(this instanceof DeflateRaw)) return new DeflateRaw(opts);
|
|
Zlib.call(this, opts, binding.DEFLATERAW);
|
|
}
|
|
|
|
function InflateRaw(opts) {
|
|
if (!(this instanceof InflateRaw)) return new InflateRaw(opts);
|
|
Zlib.call(this, opts, binding.INFLATERAW);
|
|
}
|
|
|
|
// auto-detect header.
|
|
function Unzip(opts) {
|
|
if (!(this instanceof Unzip)) return new Unzip(opts);
|
|
Zlib.call(this, opts, binding.UNZIP);
|
|
}
|
|
|
|
function isValidFlushFlag(flag) {
|
|
return flag === binding.Z_NO_FLUSH || flag === binding.Z_PARTIAL_FLUSH || flag === binding.Z_SYNC_FLUSH || flag === binding.Z_FULL_FLUSH || flag === binding.Z_FINISH || flag === binding.Z_BLOCK;
|
|
}
|
|
|
|
// the Zlib class they all inherit from
|
|
// This thing manages the queue of requests, and returns
|
|
// true or false if there is anything in the queue when
|
|
// you call the .write() method.
|
|
|
|
function Zlib(opts, mode) {
|
|
var _this = this;
|
|
|
|
this._opts = opts = opts || {};
|
|
this._chunkSize = opts.chunkSize || exports.Z_DEFAULT_CHUNK;
|
|
|
|
Transform.call(this, opts);
|
|
|
|
if (opts.flush && !isValidFlushFlag(opts.flush)) {
|
|
throw new Error('Invalid flush flag: ' + opts.flush);
|
|
}
|
|
if (opts.finishFlush && !isValidFlushFlag(opts.finishFlush)) {
|
|
throw new Error('Invalid flush flag: ' + opts.finishFlush);
|
|
}
|
|
|
|
this._flushFlag = opts.flush || binding.Z_NO_FLUSH;
|
|
this._finishFlushFlag = typeof opts.finishFlush !== 'undefined' ? opts.finishFlush : binding.Z_FINISH;
|
|
|
|
if (opts.chunkSize) {
|
|
if (opts.chunkSize < exports.Z_MIN_CHUNK || opts.chunkSize > exports.Z_MAX_CHUNK) {
|
|
throw new Error('Invalid chunk size: ' + opts.chunkSize);
|
|
}
|
|
}
|
|
|
|
if (opts.windowBits) {
|
|
if (opts.windowBits < exports.Z_MIN_WINDOWBITS || opts.windowBits > exports.Z_MAX_WINDOWBITS) {
|
|
throw new Error('Invalid windowBits: ' + opts.windowBits);
|
|
}
|
|
}
|
|
|
|
if (opts.level) {
|
|
if (opts.level < exports.Z_MIN_LEVEL || opts.level > exports.Z_MAX_LEVEL) {
|
|
throw new Error('Invalid compression level: ' + opts.level);
|
|
}
|
|
}
|
|
|
|
if (opts.memLevel) {
|
|
if (opts.memLevel < exports.Z_MIN_MEMLEVEL || opts.memLevel > exports.Z_MAX_MEMLEVEL) {
|
|
throw new Error('Invalid memLevel: ' + opts.memLevel);
|
|
}
|
|
}
|
|
|
|
if (opts.strategy) {
|
|
if (opts.strategy != exports.Z_FILTERED && opts.strategy != exports.Z_HUFFMAN_ONLY && opts.strategy != exports.Z_RLE && opts.strategy != exports.Z_FIXED && opts.strategy != exports.Z_DEFAULT_STRATEGY) {
|
|
throw new Error('Invalid strategy: ' + opts.strategy);
|
|
}
|
|
}
|
|
|
|
if (opts.dictionary) {
|
|
if (!Buffer.isBuffer(opts.dictionary)) {
|
|
throw new Error('Invalid dictionary: it should be a Buffer instance');
|
|
}
|
|
}
|
|
|
|
this._handle = new binding.Zlib(mode);
|
|
|
|
var self = this;
|
|
this._hadError = false;
|
|
this._handle.onerror = function (message, errno) {
|
|
// there is no way to cleanly recover.
|
|
// continuing only obscures problems.
|
|
_close(self);
|
|
self._hadError = true;
|
|
|
|
var error = new Error(message);
|
|
error.errno = errno;
|
|
error.code = exports.codes[errno];
|
|
self.emit('error', error);
|
|
};
|
|
|
|
var level = exports.Z_DEFAULT_COMPRESSION;
|
|
if (typeof opts.level === 'number') level = opts.level;
|
|
|
|
var strategy = exports.Z_DEFAULT_STRATEGY;
|
|
if (typeof opts.strategy === 'number') strategy = opts.strategy;
|
|
|
|
this._handle.init(opts.windowBits || exports.Z_DEFAULT_WINDOWBITS, level, opts.memLevel || exports.Z_DEFAULT_MEMLEVEL, strategy, opts.dictionary);
|
|
|
|
this._buffer = Buffer.allocUnsafe(this._chunkSize);
|
|
this._offset = 0;
|
|
this._level = level;
|
|
this._strategy = strategy;
|
|
|
|
this.once('end', this.close);
|
|
|
|
Object.defineProperty(this, '_closed', {
|
|
get: function () {
|
|
return !_this._handle;
|
|
},
|
|
configurable: true,
|
|
enumerable: true
|
|
});
|
|
}
|
|
|
|
util.inherits(Zlib, Transform);
|
|
|
|
Zlib.prototype.params = function (level, strategy, callback) {
|
|
if (level < exports.Z_MIN_LEVEL || level > exports.Z_MAX_LEVEL) {
|
|
throw new RangeError('Invalid compression level: ' + level);
|
|
}
|
|
if (strategy != exports.Z_FILTERED && strategy != exports.Z_HUFFMAN_ONLY && strategy != exports.Z_RLE && strategy != exports.Z_FIXED && strategy != exports.Z_DEFAULT_STRATEGY) {
|
|
throw new TypeError('Invalid strategy: ' + strategy);
|
|
}
|
|
|
|
if (this._level !== level || this._strategy !== strategy) {
|
|
var self = this;
|
|
this.flush(binding.Z_SYNC_FLUSH, function () {
|
|
assert(self._handle, 'zlib binding closed');
|
|
self._handle.params(level, strategy);
|
|
if (!self._hadError) {
|
|
self._level = level;
|
|
self._strategy = strategy;
|
|
if (callback) callback();
|
|
}
|
|
});
|
|
} else {
|
|
process.nextTick(callback);
|
|
}
|
|
};
|
|
|
|
Zlib.prototype.reset = function () {
|
|
assert(this._handle, 'zlib binding closed');
|
|
return this._handle.reset();
|
|
};
|
|
|
|
// This is the _flush function called by the transform class,
|
|
// internally, when the last chunk has been written.
|
|
Zlib.prototype._flush = function (callback) {
|
|
this._transform(Buffer.alloc(0), '', callback);
|
|
};
|
|
|
|
Zlib.prototype.flush = function (kind, callback) {
|
|
var _this2 = this;
|
|
|
|
var ws = this._writableState;
|
|
|
|
if (typeof kind === 'function' || kind === undefined && !callback) {
|
|
callback = kind;
|
|
kind = binding.Z_FULL_FLUSH;
|
|
}
|
|
|
|
if (ws.ended) {
|
|
if (callback) process.nextTick(callback);
|
|
} else if (ws.ending) {
|
|
if (callback) this.once('end', callback);
|
|
} else if (ws.needDrain) {
|
|
if (callback) {
|
|
this.once('drain', function () {
|
|
return _this2.flush(kind, callback);
|
|
});
|
|
}
|
|
} else {
|
|
this._flushFlag = kind;
|
|
this.write(Buffer.alloc(0), '', callback);
|
|
}
|
|
};
|
|
|
|
Zlib.prototype.close = function (callback) {
|
|
_close(this, callback);
|
|
process.nextTick(emitCloseNT, this);
|
|
};
|
|
|
|
function _close(engine, callback) {
|
|
if (callback) process.nextTick(callback);
|
|
|
|
// Caller may invoke .close after a zlib error (which will null _handle).
|
|
if (!engine._handle) return;
|
|
|
|
engine._handle.close();
|
|
engine._handle = null;
|
|
}
|
|
|
|
function emitCloseNT(self) {
|
|
self.emit('close');
|
|
}
|
|
|
|
Zlib.prototype._transform = function (chunk, encoding, cb) {
|
|
var flushFlag;
|
|
var ws = this._writableState;
|
|
var ending = ws.ending || ws.ended;
|
|
var last = ending && (!chunk || ws.length === chunk.length);
|
|
|
|
if (chunk !== null && !Buffer.isBuffer(chunk)) return cb(new Error('invalid input'));
|
|
|
|
if (!this._handle) return cb(new Error('zlib binding closed'));
|
|
|
|
// If it's the last chunk, or a final flush, we use the Z_FINISH flush flag
|
|
// (or whatever flag was provided using opts.finishFlush).
|
|
// If it's explicitly flushing at some other time, then we use
|
|
// Z_FULL_FLUSH. Otherwise, use Z_NO_FLUSH for maximum compression
|
|
// goodness.
|
|
if (last) flushFlag = this._finishFlushFlag;else {
|
|
flushFlag = this._flushFlag;
|
|
// once we've flushed the last of the queue, stop flushing and
|
|
// go back to the normal behavior.
|
|
if (chunk.length >= ws.length) {
|
|
this._flushFlag = this._opts.flush || binding.Z_NO_FLUSH;
|
|
}
|
|
}
|
|
|
|
this._processChunk(chunk, flushFlag, cb);
|
|
};
|
|
|
|
Zlib.prototype._processChunk = function (chunk, flushFlag, cb) {
|
|
var availInBefore = chunk && chunk.length;
|
|
var availOutBefore = this._chunkSize - this._offset;
|
|
var inOff = 0;
|
|
|
|
var self = this;
|
|
|
|
var async = typeof cb === 'function';
|
|
|
|
if (!async) {
|
|
var buffers = [];
|
|
var nread = 0;
|
|
|
|
var error;
|
|
this.on('error', function (er) {
|
|
error = er;
|
|
});
|
|
|
|
assert(this._handle, 'zlib binding closed');
|
|
do {
|
|
var res = this._handle.writeSync(flushFlag, chunk, // in
|
|
inOff, // in_off
|
|
availInBefore, // in_len
|
|
this._buffer, // out
|
|
this._offset, //out_off
|
|
availOutBefore); // out_len
|
|
} while (!this._hadError && callback(res[0], res[1]));
|
|
|
|
if (this._hadError) {
|
|
throw error;
|
|
}
|
|
|
|
if (nread >= kMaxLength) {
|
|
_close(this);
|
|
throw new RangeError(kRangeErrorMessage);
|
|
}
|
|
|
|
var buf = Buffer.concat(buffers, nread);
|
|
_close(this);
|
|
|
|
return buf;
|
|
}
|
|
|
|
assert(this._handle, 'zlib binding closed');
|
|
var req = this._handle.write(flushFlag, chunk, // in
|
|
inOff, // in_off
|
|
availInBefore, // in_len
|
|
this._buffer, // out
|
|
this._offset, //out_off
|
|
availOutBefore); // out_len
|
|
|
|
req.buffer = chunk;
|
|
req.callback = callback;
|
|
|
|
function callback(availInAfter, availOutAfter) {
|
|
// When the callback is used in an async write, the callback's
|
|
// context is the `req` object that was created. The req object
|
|
// is === this._handle, and that's why it's important to null
|
|
// out the values after they are done being used. `this._handle`
|
|
// can stay in memory longer than the callback and buffer are needed.
|
|
if (this) {
|
|
this.buffer = null;
|
|
this.callback = null;
|
|
}
|
|
|
|
if (self._hadError) return;
|
|
|
|
var have = availOutBefore - availOutAfter;
|
|
assert(have >= 0, 'have should not go down');
|
|
|
|
if (have > 0) {
|
|
var out = self._buffer.slice(self._offset, self._offset + have);
|
|
self._offset += have;
|
|
// serve some output to the consumer.
|
|
if (async) {
|
|
self.push(out);
|
|
} else {
|
|
buffers.push(out);
|
|
nread += out.length;
|
|
}
|
|
}
|
|
|
|
// exhausted the output buffer, or used all the input create a new one.
|
|
if (availOutAfter === 0 || self._offset >= self._chunkSize) {
|
|
availOutBefore = self._chunkSize;
|
|
self._offset = 0;
|
|
self._buffer = Buffer.allocUnsafe(self._chunkSize);
|
|
}
|
|
|
|
if (availOutAfter === 0) {
|
|
// Not actually done. Need to reprocess.
|
|
// Also, update the availInBefore to the availInAfter value,
|
|
// so that if we have to hit it a third (fourth, etc.) time,
|
|
// it'll have the correct byte counts.
|
|
inOff += availInBefore - availInAfter;
|
|
availInBefore = availInAfter;
|
|
|
|
if (!async) return true;
|
|
|
|
var newReq = self._handle.write(flushFlag, chunk, inOff, availInBefore, self._buffer, self._offset, self._chunkSize);
|
|
newReq.callback = callback; // this same function
|
|
newReq.buffer = chunk;
|
|
return;
|
|
}
|
|
|
|
if (!async) return false;
|
|
|
|
// finished with the chunk.
|
|
cb();
|
|
}
|
|
};
|
|
|
|
util.inherits(Deflate, Zlib);
|
|
util.inherits(Inflate, Zlib);
|
|
util.inherits(Gzip, Zlib);
|
|
util.inherits(Gunzip, Zlib);
|
|
util.inherits(DeflateRaw, Zlib);
|
|
util.inherits(InflateRaw, Zlib);
|
|
util.inherits(Unzip, Zlib);
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/utils/common.js":
|
|
/*!****************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/utils/common.js ***!
|
|
\****************************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
var TYPED_OK = (typeof Uint8Array !== 'undefined') &&
|
|
(typeof Uint16Array !== 'undefined') &&
|
|
(typeof Int32Array !== 'undefined');
|
|
|
|
function _has(obj, key) {
|
|
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
}
|
|
|
|
exports.assign = function (obj /*from1, from2, from3, ...*/) {
|
|
var sources = Array.prototype.slice.call(arguments, 1);
|
|
while (sources.length) {
|
|
var source = sources.shift();
|
|
if (!source) { continue; }
|
|
|
|
if (typeof source !== 'object') {
|
|
throw new TypeError(source + 'must be non-object');
|
|
}
|
|
|
|
for (var p in source) {
|
|
if (_has(source, p)) {
|
|
obj[p] = source[p];
|
|
}
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
};
|
|
|
|
|
|
// reduce buffer size, avoiding mem copy
|
|
exports.shrinkBuf = function (buf, size) {
|
|
if (buf.length === size) { return buf; }
|
|
if (buf.subarray) { return buf.subarray(0, size); }
|
|
buf.length = size;
|
|
return buf;
|
|
};
|
|
|
|
|
|
var fnTyped = {
|
|
arraySet: function (dest, src, src_offs, len, dest_offs) {
|
|
if (src.subarray && dest.subarray) {
|
|
dest.set(src.subarray(src_offs, src_offs + len), dest_offs);
|
|
return;
|
|
}
|
|
// Fallback to ordinary array
|
|
for (var i = 0; i < len; i++) {
|
|
dest[dest_offs + i] = src[src_offs + i];
|
|
}
|
|
},
|
|
// Join array of chunks to single array.
|
|
flattenChunks: function (chunks) {
|
|
var i, l, len, pos, chunk, result;
|
|
|
|
// calculate data length
|
|
len = 0;
|
|
for (i = 0, l = chunks.length; i < l; i++) {
|
|
len += chunks[i].length;
|
|
}
|
|
|
|
// join chunks
|
|
result = new Uint8Array(len);
|
|
pos = 0;
|
|
for (i = 0, l = chunks.length; i < l; i++) {
|
|
chunk = chunks[i];
|
|
result.set(chunk, pos);
|
|
pos += chunk.length;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
};
|
|
|
|
var fnUntyped = {
|
|
arraySet: function (dest, src, src_offs, len, dest_offs) {
|
|
for (var i = 0; i < len; i++) {
|
|
dest[dest_offs + i] = src[src_offs + i];
|
|
}
|
|
},
|
|
// Join array of chunks to single array.
|
|
flattenChunks: function (chunks) {
|
|
return [].concat.apply([], chunks);
|
|
}
|
|
};
|
|
|
|
|
|
// Enable/Disable typed arrays use, for testing
|
|
//
|
|
exports.setTyped = function (on) {
|
|
if (on) {
|
|
exports.Buf8 = Uint8Array;
|
|
exports.Buf16 = Uint16Array;
|
|
exports.Buf32 = Int32Array;
|
|
exports.assign(exports, fnTyped);
|
|
} else {
|
|
exports.Buf8 = Array;
|
|
exports.Buf16 = Array;
|
|
exports.Buf32 = Array;
|
|
exports.assign(exports, fnUntyped);
|
|
}
|
|
};
|
|
|
|
exports.setTyped(TYPED_OK);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/adler32.js":
|
|
/*!****************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/zlib/adler32.js ***!
|
|
\****************************************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// Note: adler32 takes 12% for level 0 and 2% for level 6.
|
|
// It isn't worth it to make additional optimizations as in original.
|
|
// Small size is preferable.
|
|
|
|
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
function adler32(adler, buf, len, pos) {
|
|
var s1 = (adler & 0xffff) |0,
|
|
s2 = ((adler >>> 16) & 0xffff) |0,
|
|
n = 0;
|
|
|
|
while (len !== 0) {
|
|
// Set limit ~ twice less than 5552, to keep
|
|
// s2 in 31-bits, because we force signed ints.
|
|
// in other case %= will fail.
|
|
n = len > 2000 ? 2000 : len;
|
|
len -= n;
|
|
|
|
do {
|
|
s1 = (s1 + buf[pos++]) |0;
|
|
s2 = (s2 + s1) |0;
|
|
} while (--n);
|
|
|
|
s1 %= 65521;
|
|
s2 %= 65521;
|
|
}
|
|
|
|
return (s1 | (s2 << 16)) |0;
|
|
}
|
|
|
|
|
|
module.exports = adler32;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/constants.js":
|
|
/*!******************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/zlib/constants.js ***!
|
|
\******************************************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
module.exports = {
|
|
|
|
/* Allowed flush values; see deflate() and inflate() below for details */
|
|
Z_NO_FLUSH: 0,
|
|
Z_PARTIAL_FLUSH: 1,
|
|
Z_SYNC_FLUSH: 2,
|
|
Z_FULL_FLUSH: 3,
|
|
Z_FINISH: 4,
|
|
Z_BLOCK: 5,
|
|
Z_TREES: 6,
|
|
|
|
/* Return codes for the compression/decompression functions. Negative values
|
|
* are errors, positive values are used for special but normal events.
|
|
*/
|
|
Z_OK: 0,
|
|
Z_STREAM_END: 1,
|
|
Z_NEED_DICT: 2,
|
|
Z_ERRNO: -1,
|
|
Z_STREAM_ERROR: -2,
|
|
Z_DATA_ERROR: -3,
|
|
//Z_MEM_ERROR: -4,
|
|
Z_BUF_ERROR: -5,
|
|
//Z_VERSION_ERROR: -6,
|
|
|
|
/* compression levels */
|
|
Z_NO_COMPRESSION: 0,
|
|
Z_BEST_SPEED: 1,
|
|
Z_BEST_COMPRESSION: 9,
|
|
Z_DEFAULT_COMPRESSION: -1,
|
|
|
|
|
|
Z_FILTERED: 1,
|
|
Z_HUFFMAN_ONLY: 2,
|
|
Z_RLE: 3,
|
|
Z_FIXED: 4,
|
|
Z_DEFAULT_STRATEGY: 0,
|
|
|
|
/* Possible values of the data_type field (though see inflate()) */
|
|
Z_BINARY: 0,
|
|
Z_TEXT: 1,
|
|
//Z_ASCII: 1, // = Z_TEXT (deprecated)
|
|
Z_UNKNOWN: 2,
|
|
|
|
/* The deflate compression method */
|
|
Z_DEFLATED: 8
|
|
//Z_NULL: null // Use -1 or null inline, depending on var type
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/crc32.js":
|
|
/*!**************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/zlib/crc32.js ***!
|
|
\**************************************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// Note: we can't get significant speed boost here.
|
|
// So write code to minimize size - no pregenerated tables
|
|
// and array tools dependencies.
|
|
|
|
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
// Use ordinary array, since untyped makes no boost here
|
|
function makeTable() {
|
|
var c, table = [];
|
|
|
|
for (var n = 0; n < 256; n++) {
|
|
c = n;
|
|
for (var k = 0; k < 8; k++) {
|
|
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
|
|
}
|
|
table[n] = c;
|
|
}
|
|
|
|
return table;
|
|
}
|
|
|
|
// Create table on load. Just 255 signed longs. Not a problem.
|
|
var crcTable = makeTable();
|
|
|
|
|
|
function crc32(crc, buf, len, pos) {
|
|
var t = crcTable,
|
|
end = pos + len;
|
|
|
|
crc ^= -1;
|
|
|
|
for (var i = pos; i < end; i++) {
|
|
crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
|
|
}
|
|
|
|
return (crc ^ (-1)); // >>> 0;
|
|
}
|
|
|
|
|
|
module.exports = crc32;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/deflate.js":
|
|
/*!****************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/zlib/deflate.js ***!
|
|
\****************************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
var utils = __webpack_require__(/*! ../utils/common */ "./node_modules/browserify-zlib/node_modules/pako/lib/utils/common.js");
|
|
var trees = __webpack_require__(/*! ./trees */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/trees.js");
|
|
var adler32 = __webpack_require__(/*! ./adler32 */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/adler32.js");
|
|
var crc32 = __webpack_require__(/*! ./crc32 */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/crc32.js");
|
|
var msg = __webpack_require__(/*! ./messages */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/messages.js");
|
|
|
|
/* Public constants ==========================================================*/
|
|
/* ===========================================================================*/
|
|
|
|
|
|
/* Allowed flush values; see deflate() and inflate() below for details */
|
|
var Z_NO_FLUSH = 0;
|
|
var Z_PARTIAL_FLUSH = 1;
|
|
//var Z_SYNC_FLUSH = 2;
|
|
var Z_FULL_FLUSH = 3;
|
|
var Z_FINISH = 4;
|
|
var Z_BLOCK = 5;
|
|
//var Z_TREES = 6;
|
|
|
|
|
|
/* Return codes for the compression/decompression functions. Negative values
|
|
* are errors, positive values are used for special but normal events.
|
|
*/
|
|
var Z_OK = 0;
|
|
var Z_STREAM_END = 1;
|
|
//var Z_NEED_DICT = 2;
|
|
//var Z_ERRNO = -1;
|
|
var Z_STREAM_ERROR = -2;
|
|
var Z_DATA_ERROR = -3;
|
|
//var Z_MEM_ERROR = -4;
|
|
var Z_BUF_ERROR = -5;
|
|
//var Z_VERSION_ERROR = -6;
|
|
|
|
|
|
/* compression levels */
|
|
//var Z_NO_COMPRESSION = 0;
|
|
//var Z_BEST_SPEED = 1;
|
|
//var Z_BEST_COMPRESSION = 9;
|
|
var Z_DEFAULT_COMPRESSION = -1;
|
|
|
|
|
|
var Z_FILTERED = 1;
|
|
var Z_HUFFMAN_ONLY = 2;
|
|
var Z_RLE = 3;
|
|
var Z_FIXED = 4;
|
|
var Z_DEFAULT_STRATEGY = 0;
|
|
|
|
/* Possible values of the data_type field (though see inflate()) */
|
|
//var Z_BINARY = 0;
|
|
//var Z_TEXT = 1;
|
|
//var Z_ASCII = 1; // = Z_TEXT
|
|
var Z_UNKNOWN = 2;
|
|
|
|
|
|
/* The deflate compression method */
|
|
var Z_DEFLATED = 8;
|
|
|
|
/*============================================================================*/
|
|
|
|
|
|
var MAX_MEM_LEVEL = 9;
|
|
/* Maximum value for memLevel in deflateInit2 */
|
|
var MAX_WBITS = 15;
|
|
/* 32K LZ77 window */
|
|
var DEF_MEM_LEVEL = 8;
|
|
|
|
|
|
var LENGTH_CODES = 29;
|
|
/* number of length codes, not counting the special END_BLOCK code */
|
|
var LITERALS = 256;
|
|
/* number of literal bytes 0..255 */
|
|
var L_CODES = LITERALS + 1 + LENGTH_CODES;
|
|
/* number of Literal or Length codes, including the END_BLOCK code */
|
|
var D_CODES = 30;
|
|
/* number of distance codes */
|
|
var BL_CODES = 19;
|
|
/* number of codes used to transfer the bit lengths */
|
|
var HEAP_SIZE = 2 * L_CODES + 1;
|
|
/* maximum heap size */
|
|
var MAX_BITS = 15;
|
|
/* All codes must not exceed MAX_BITS bits */
|
|
|
|
var MIN_MATCH = 3;
|
|
var MAX_MATCH = 258;
|
|
var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
|
|
|
|
var PRESET_DICT = 0x20;
|
|
|
|
var INIT_STATE = 42;
|
|
var EXTRA_STATE = 69;
|
|
var NAME_STATE = 73;
|
|
var COMMENT_STATE = 91;
|
|
var HCRC_STATE = 103;
|
|
var BUSY_STATE = 113;
|
|
var FINISH_STATE = 666;
|
|
|
|
var BS_NEED_MORE = 1; /* block not completed, need more input or more output */
|
|
var BS_BLOCK_DONE = 2; /* block flush performed */
|
|
var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */
|
|
var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */
|
|
|
|
var OS_CODE = 0x03; // Unix :) . Don't detect, use this default.
|
|
|
|
function err(strm, errorCode) {
|
|
strm.msg = msg[errorCode];
|
|
return errorCode;
|
|
}
|
|
|
|
function rank(f) {
|
|
return ((f) << 1) - ((f) > 4 ? 9 : 0);
|
|
}
|
|
|
|
function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }
|
|
|
|
|
|
/* =========================================================================
|
|
* Flush as much pending output as possible. All deflate() output goes
|
|
* through this function so some applications may wish to modify it
|
|
* to avoid allocating a large strm->output buffer and copying into it.
|
|
* (See also read_buf()).
|
|
*/
|
|
function flush_pending(strm) {
|
|
var s = strm.state;
|
|
|
|
//_tr_flush_bits(s);
|
|
var len = s.pending;
|
|
if (len > strm.avail_out) {
|
|
len = strm.avail_out;
|
|
}
|
|
if (len === 0) { return; }
|
|
|
|
utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out);
|
|
strm.next_out += len;
|
|
s.pending_out += len;
|
|
strm.total_out += len;
|
|
strm.avail_out -= len;
|
|
s.pending -= len;
|
|
if (s.pending === 0) {
|
|
s.pending_out = 0;
|
|
}
|
|
}
|
|
|
|
|
|
function flush_block_only(s, last) {
|
|
trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);
|
|
s.block_start = s.strstart;
|
|
flush_pending(s.strm);
|
|
}
|
|
|
|
|
|
function put_byte(s, b) {
|
|
s.pending_buf[s.pending++] = b;
|
|
}
|
|
|
|
|
|
/* =========================================================================
|
|
* Put a short in the pending buffer. The 16-bit value is put in MSB order.
|
|
* IN assertion: the stream state is correct and there is enough room in
|
|
* pending_buf.
|
|
*/
|
|
function putShortMSB(s, b) {
|
|
// put_byte(s, (Byte)(b >> 8));
|
|
// put_byte(s, (Byte)(b & 0xff));
|
|
s.pending_buf[s.pending++] = (b >>> 8) & 0xff;
|
|
s.pending_buf[s.pending++] = b & 0xff;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Read a new buffer from the current input stream, update the adler32
|
|
* and total number of bytes read. All deflate() input goes through
|
|
* this function so some applications may wish to modify it to avoid
|
|
* allocating a large strm->input buffer and copying from it.
|
|
* (See also flush_pending()).
|
|
*/
|
|
function read_buf(strm, buf, start, size) {
|
|
var len = strm.avail_in;
|
|
|
|
if (len > size) { len = size; }
|
|
if (len === 0) { return 0; }
|
|
|
|
strm.avail_in -= len;
|
|
|
|
// zmemcpy(buf, strm->next_in, len);
|
|
utils.arraySet(buf, strm.input, strm.next_in, len, start);
|
|
if (strm.state.wrap === 1) {
|
|
strm.adler = adler32(strm.adler, buf, len, start);
|
|
}
|
|
|
|
else if (strm.state.wrap === 2) {
|
|
strm.adler = crc32(strm.adler, buf, len, start);
|
|
}
|
|
|
|
strm.next_in += len;
|
|
strm.total_in += len;
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Set match_start to the longest match starting at the given string and
|
|
* return its length. Matches shorter or equal to prev_length are discarded,
|
|
* in which case the result is equal to prev_length and match_start is
|
|
* garbage.
|
|
* IN assertions: cur_match is the head of the hash chain for the current
|
|
* string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
|
|
* OUT assertion: the match length is not greater than s->lookahead.
|
|
*/
|
|
function longest_match(s, cur_match) {
|
|
var chain_length = s.max_chain_length; /* max hash chain length */
|
|
var scan = s.strstart; /* current string */
|
|
var match; /* matched string */
|
|
var len; /* length of current match */
|
|
var best_len = s.prev_length; /* best match length so far */
|
|
var nice_match = s.nice_match; /* stop if match long enough */
|
|
var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?
|
|
s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;
|
|
|
|
var _win = s.window; // shortcut
|
|
|
|
var wmask = s.w_mask;
|
|
var prev = s.prev;
|
|
|
|
/* Stop when cur_match becomes <= limit. To simplify the code,
|
|
* we prevent matches with the string of window index 0.
|
|
*/
|
|
|
|
var strend = s.strstart + MAX_MATCH;
|
|
var scan_end1 = _win[scan + best_len - 1];
|
|
var scan_end = _win[scan + best_len];
|
|
|
|
/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
|
|
* It is easy to get rid of this optimization if necessary.
|
|
*/
|
|
// Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
|
|
|
|
/* Do not waste too much time if we already have a good match: */
|
|
if (s.prev_length >= s.good_match) {
|
|
chain_length >>= 2;
|
|
}
|
|
/* Do not look for matches beyond the end of the input. This is necessary
|
|
* to make deflate deterministic.
|
|
*/
|
|
if (nice_match > s.lookahead) { nice_match = s.lookahead; }
|
|
|
|
// Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
|
|
|
|
do {
|
|
// Assert(cur_match < s->strstart, "no future");
|
|
match = cur_match;
|
|
|
|
/* Skip to next match if the match length cannot increase
|
|
* or if the match length is less than 2. Note that the checks below
|
|
* for insufficient lookahead only occur occasionally for performance
|
|
* reasons. Therefore uninitialized memory will be accessed, and
|
|
* conditional jumps will be made that depend on those values.
|
|
* However the length of the match is limited to the lookahead, so
|
|
* the output of deflate is not affected by the uninitialized values.
|
|
*/
|
|
|
|
if (_win[match + best_len] !== scan_end ||
|
|
_win[match + best_len - 1] !== scan_end1 ||
|
|
_win[match] !== _win[scan] ||
|
|
_win[++match] !== _win[scan + 1]) {
|
|
continue;
|
|
}
|
|
|
|
/* The check at best_len-1 can be removed because it will be made
|
|
* again later. (This heuristic is not always a win.)
|
|
* It is not necessary to compare scan[2] and match[2] since they
|
|
* are always equal when the other bytes match, given that
|
|
* the hash keys are equal and that HASH_BITS >= 8.
|
|
*/
|
|
scan += 2;
|
|
match++;
|
|
// Assert(*scan == *match, "match[2]?");
|
|
|
|
/* We check for insufficient lookahead only every 8th comparison;
|
|
* the 256th check will be made at strstart+258.
|
|
*/
|
|
do {
|
|
/*jshint noempty:false*/
|
|
} while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
|
|
_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
|
|
_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
|
|
_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
|
|
scan < strend);
|
|
|
|
// Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
|
|
|
|
len = MAX_MATCH - (strend - scan);
|
|
scan = strend - MAX_MATCH;
|
|
|
|
if (len > best_len) {
|
|
s.match_start = cur_match;
|
|
best_len = len;
|
|
if (len >= nice_match) {
|
|
break;
|
|
}
|
|
scan_end1 = _win[scan + best_len - 1];
|
|
scan_end = _win[scan + best_len];
|
|
}
|
|
} while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);
|
|
|
|
if (best_len <= s.lookahead) {
|
|
return best_len;
|
|
}
|
|
return s.lookahead;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Fill the window when the lookahead becomes insufficient.
|
|
* Updates strstart and lookahead.
|
|
*
|
|
* IN assertion: lookahead < MIN_LOOKAHEAD
|
|
* OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
|
|
* At least one byte has been read, or avail_in == 0; reads are
|
|
* performed for at least two bytes (required for the zip translate_eol
|
|
* option -- not supported here).
|
|
*/
|
|
function fill_window(s) {
|
|
var _w_size = s.w_size;
|
|
var p, n, m, more, str;
|
|
|
|
//Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
|
|
|
|
do {
|
|
more = s.window_size - s.lookahead - s.strstart;
|
|
|
|
// JS ints have 32 bit, block below not needed
|
|
/* Deal with !@#$% 64K limit: */
|
|
//if (sizeof(int) <= 2) {
|
|
// if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
|
|
// more = wsize;
|
|
//
|
|
// } else if (more == (unsigned)(-1)) {
|
|
// /* Very unlikely, but possible on 16 bit machine if
|
|
// * strstart == 0 && lookahead == 1 (input done a byte at time)
|
|
// */
|
|
// more--;
|
|
// }
|
|
//}
|
|
|
|
|
|
/* If the window is almost full and there is insufficient lookahead,
|
|
* move the upper half to the lower one to make room in the upper half.
|
|
*/
|
|
if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {
|
|
|
|
utils.arraySet(s.window, s.window, _w_size, _w_size, 0);
|
|
s.match_start -= _w_size;
|
|
s.strstart -= _w_size;
|
|
/* we now have strstart >= MAX_DIST */
|
|
s.block_start -= _w_size;
|
|
|
|
/* Slide the hash table (could be avoided with 32 bit values
|
|
at the expense of memory usage). We slide even when level == 0
|
|
to keep the hash table consistent if we switch back to level > 0
|
|
later. (Using level 0 permanently is not an optimal usage of
|
|
zlib, so we don't care about this pathological case.)
|
|
*/
|
|
|
|
n = s.hash_size;
|
|
p = n;
|
|
do {
|
|
m = s.head[--p];
|
|
s.head[p] = (m >= _w_size ? m - _w_size : 0);
|
|
} while (--n);
|
|
|
|
n = _w_size;
|
|
p = n;
|
|
do {
|
|
m = s.prev[--p];
|
|
s.prev[p] = (m >= _w_size ? m - _w_size : 0);
|
|
/* If n is not on any hash chain, prev[n] is garbage but
|
|
* its value will never be used.
|
|
*/
|
|
} while (--n);
|
|
|
|
more += _w_size;
|
|
}
|
|
if (s.strm.avail_in === 0) {
|
|
break;
|
|
}
|
|
|
|
/* If there was no sliding:
|
|
* strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
|
|
* more == window_size - lookahead - strstart
|
|
* => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
|
|
* => more >= window_size - 2*WSIZE + 2
|
|
* In the BIG_MEM or MMAP case (not yet supported),
|
|
* window_size == input_size + MIN_LOOKAHEAD &&
|
|
* strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
|
|
* Otherwise, window_size == 2*WSIZE so more >= 2.
|
|
* If there was sliding, more >= WSIZE. So in all cases, more >= 2.
|
|
*/
|
|
//Assert(more >= 2, "more < 2");
|
|
n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);
|
|
s.lookahead += n;
|
|
|
|
/* Initialize the hash value now that we have some input: */
|
|
if (s.lookahead + s.insert >= MIN_MATCH) {
|
|
str = s.strstart - s.insert;
|
|
s.ins_h = s.window[str];
|
|
|
|
/* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */
|
|
s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask;
|
|
//#if MIN_MATCH != 3
|
|
// Call update_hash() MIN_MATCH-3 more times
|
|
//#endif
|
|
while (s.insert) {
|
|
/* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
|
|
s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask;
|
|
|
|
s.prev[str & s.w_mask] = s.head[s.ins_h];
|
|
s.head[s.ins_h] = str;
|
|
str++;
|
|
s.insert--;
|
|
if (s.lookahead + s.insert < MIN_MATCH) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
|
|
* but this is not important since only literal bytes will be emitted.
|
|
*/
|
|
|
|
} while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);
|
|
|
|
/* If the WIN_INIT bytes after the end of the current data have never been
|
|
* written, then zero those bytes in order to avoid memory check reports of
|
|
* the use of uninitialized (or uninitialised as Julian writes) bytes by
|
|
* the longest match routines. Update the high water mark for the next
|
|
* time through here. WIN_INIT is set to MAX_MATCH since the longest match
|
|
* routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
|
|
*/
|
|
// if (s.high_water < s.window_size) {
|
|
// var curr = s.strstart + s.lookahead;
|
|
// var init = 0;
|
|
//
|
|
// if (s.high_water < curr) {
|
|
// /* Previous high water mark below current data -- zero WIN_INIT
|
|
// * bytes or up to end of window, whichever is less.
|
|
// */
|
|
// init = s.window_size - curr;
|
|
// if (init > WIN_INIT)
|
|
// init = WIN_INIT;
|
|
// zmemzero(s->window + curr, (unsigned)init);
|
|
// s->high_water = curr + init;
|
|
// }
|
|
// else if (s->high_water < (ulg)curr + WIN_INIT) {
|
|
// /* High water mark at or above current data, but below current data
|
|
// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
|
|
// * to end of window, whichever is less.
|
|
// */
|
|
// init = (ulg)curr + WIN_INIT - s->high_water;
|
|
// if (init > s->window_size - s->high_water)
|
|
// init = s->window_size - s->high_water;
|
|
// zmemzero(s->window + s->high_water, (unsigned)init);
|
|
// s->high_water += init;
|
|
// }
|
|
// }
|
|
//
|
|
// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
|
|
// "not enough room for search");
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Copy without compression as much as possible from the input stream, return
|
|
* the current block state.
|
|
* This function does not insert new strings in the dictionary since
|
|
* uncompressible data is probably not useful. This function is used
|
|
* only for the level=0 compression option.
|
|
* NOTE: this function should be optimized to avoid extra copying from
|
|
* window to pending_buf.
|
|
*/
|
|
function deflate_stored(s, flush) {
|
|
/* Stored blocks are limited to 0xffff bytes, pending_buf is limited
|
|
* to pending_buf_size, and each stored block has a 5 byte header:
|
|
*/
|
|
var max_block_size = 0xffff;
|
|
|
|
if (max_block_size > s.pending_buf_size - 5) {
|
|
max_block_size = s.pending_buf_size - 5;
|
|
}
|
|
|
|
/* Copy as much as possible from input to output: */
|
|
for (;;) {
|
|
/* Fill the window as much as possible: */
|
|
if (s.lookahead <= 1) {
|
|
|
|
//Assert(s->strstart < s->w_size+MAX_DIST(s) ||
|
|
// s->block_start >= (long)s->w_size, "slide too late");
|
|
// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) ||
|
|
// s.block_start >= s.w_size)) {
|
|
// throw new Error("slide too late");
|
|
// }
|
|
|
|
fill_window(s);
|
|
if (s.lookahead === 0 && flush === Z_NO_FLUSH) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
|
|
if (s.lookahead === 0) {
|
|
break;
|
|
}
|
|
/* flush the current block */
|
|
}
|
|
//Assert(s->block_start >= 0L, "block gone");
|
|
// if (s.block_start < 0) throw new Error("block gone");
|
|
|
|
s.strstart += s.lookahead;
|
|
s.lookahead = 0;
|
|
|
|
/* Emit a stored block if pending_buf will be full: */
|
|
var max_start = s.block_start + max_block_size;
|
|
|
|
if (s.strstart === 0 || s.strstart >= max_start) {
|
|
/* strstart == 0 is possible when wraparound on 16-bit machine */
|
|
s.lookahead = s.strstart - max_start;
|
|
s.strstart = max_start;
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
|
|
|
|
}
|
|
/* Flush if we may have to slide, otherwise block_start may become
|
|
* negative and the data will be gone:
|
|
*/
|
|
if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) {
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
}
|
|
}
|
|
|
|
s.insert = 0;
|
|
|
|
if (flush === Z_FINISH) {
|
|
/*** FLUSH_BLOCK(s, 1); ***/
|
|
flush_block_only(s, true);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_FINISH_STARTED;
|
|
}
|
|
/***/
|
|
return BS_FINISH_DONE;
|
|
}
|
|
|
|
if (s.strstart > s.block_start) {
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
}
|
|
|
|
return BS_NEED_MORE;
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Compress as much as possible from the input stream, return the current
|
|
* block state.
|
|
* This function does not perform lazy evaluation of matches and inserts
|
|
* new strings in the dictionary only for unmatched strings or for short
|
|
* matches. It is used only for the fast compression options.
|
|
*/
|
|
function deflate_fast(s, flush) {
|
|
var hash_head; /* head of the hash chain */
|
|
var bflush; /* set if current block must be flushed */
|
|
|
|
for (;;) {
|
|
/* Make sure that we always have enough lookahead, except
|
|
* at the end of the input file. We need MAX_MATCH bytes
|
|
* for the next match, plus MIN_MATCH bytes to insert the
|
|
* string following the next match.
|
|
*/
|
|
if (s.lookahead < MIN_LOOKAHEAD) {
|
|
fill_window(s);
|
|
if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
if (s.lookahead === 0) {
|
|
break; /* flush the current block */
|
|
}
|
|
}
|
|
|
|
/* Insert the string window[strstart .. strstart+2] in the
|
|
* dictionary, and set hash_head to the head of the hash chain:
|
|
*/
|
|
hash_head = 0/*NIL*/;
|
|
if (s.lookahead >= MIN_MATCH) {
|
|
/*** INSERT_STRING(s, s.strstart, hash_head); ***/
|
|
s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
|
|
hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
|
|
s.head[s.ins_h] = s.strstart;
|
|
/***/
|
|
}
|
|
|
|
/* Find the longest match, discarding those <= prev_length.
|
|
* At this point we have always match_length < MIN_MATCH
|
|
*/
|
|
if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {
|
|
/* To simplify the code, we prevent matches with the string
|
|
* of window index 0 (in particular we have to avoid a match
|
|
* of the string with itself at the start of the input file).
|
|
*/
|
|
s.match_length = longest_match(s, hash_head);
|
|
/* longest_match() sets match_start */
|
|
}
|
|
if (s.match_length >= MIN_MATCH) {
|
|
// check_match(s, s.strstart, s.match_start, s.match_length); // for debug only
|
|
|
|
/*** _tr_tally_dist(s, s.strstart - s.match_start,
|
|
s.match_length - MIN_MATCH, bflush); ***/
|
|
bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH);
|
|
|
|
s.lookahead -= s.match_length;
|
|
|
|
/* Insert new strings in the hash table only if the match length
|
|
* is not too large. This saves time but degrades compression.
|
|
*/
|
|
if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) {
|
|
s.match_length--; /* string at strstart already in table */
|
|
do {
|
|
s.strstart++;
|
|
/*** INSERT_STRING(s, s.strstart, hash_head); ***/
|
|
s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
|
|
hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
|
|
s.head[s.ins_h] = s.strstart;
|
|
/***/
|
|
/* strstart never exceeds WSIZE-MAX_MATCH, so there are
|
|
* always MIN_MATCH bytes ahead.
|
|
*/
|
|
} while (--s.match_length !== 0);
|
|
s.strstart++;
|
|
} else
|
|
{
|
|
s.strstart += s.match_length;
|
|
s.match_length = 0;
|
|
s.ins_h = s.window[s.strstart];
|
|
/* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */
|
|
s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask;
|
|
|
|
//#if MIN_MATCH != 3
|
|
// Call UPDATE_HASH() MIN_MATCH-3 more times
|
|
//#endif
|
|
/* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
|
|
* matter since it will be recomputed at next deflate call.
|
|
*/
|
|
}
|
|
} else {
|
|
/* No match, output a literal byte */
|
|
//Tracevv((stderr,"%c", s.window[s.strstart]));
|
|
/*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
|
|
bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
|
|
|
|
s.lookahead--;
|
|
s.strstart++;
|
|
}
|
|
if (bflush) {
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
}
|
|
}
|
|
s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1);
|
|
if (flush === Z_FINISH) {
|
|
/*** FLUSH_BLOCK(s, 1); ***/
|
|
flush_block_only(s, true);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_FINISH_STARTED;
|
|
}
|
|
/***/
|
|
return BS_FINISH_DONE;
|
|
}
|
|
if (s.last_lit) {
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
}
|
|
return BS_BLOCK_DONE;
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Same as above, but achieves better compression. We use a lazy
|
|
* evaluation for matches: a match is finally adopted only if there is
|
|
* no better match at the next window position.
|
|
*/
|
|
function deflate_slow(s, flush) {
|
|
var hash_head; /* head of hash chain */
|
|
var bflush; /* set if current block must be flushed */
|
|
|
|
var max_insert;
|
|
|
|
/* Process the input block. */
|
|
for (;;) {
|
|
/* Make sure that we always have enough lookahead, except
|
|
* at the end of the input file. We need MAX_MATCH bytes
|
|
* for the next match, plus MIN_MATCH bytes to insert the
|
|
* string following the next match.
|
|
*/
|
|
if (s.lookahead < MIN_LOOKAHEAD) {
|
|
fill_window(s);
|
|
if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
if (s.lookahead === 0) { break; } /* flush the current block */
|
|
}
|
|
|
|
/* Insert the string window[strstart .. strstart+2] in the
|
|
* dictionary, and set hash_head to the head of the hash chain:
|
|
*/
|
|
hash_head = 0/*NIL*/;
|
|
if (s.lookahead >= MIN_MATCH) {
|
|
/*** INSERT_STRING(s, s.strstart, hash_head); ***/
|
|
s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
|
|
hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
|
|
s.head[s.ins_h] = s.strstart;
|
|
/***/
|
|
}
|
|
|
|
/* Find the longest match, discarding those <= prev_length.
|
|
*/
|
|
s.prev_length = s.match_length;
|
|
s.prev_match = s.match_start;
|
|
s.match_length = MIN_MATCH - 1;
|
|
|
|
if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&
|
|
s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {
|
|
/* To simplify the code, we prevent matches with the string
|
|
* of window index 0 (in particular we have to avoid a match
|
|
* of the string with itself at the start of the input file).
|
|
*/
|
|
s.match_length = longest_match(s, hash_head);
|
|
/* longest_match() sets match_start */
|
|
|
|
if (s.match_length <= 5 &&
|
|
(s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {
|
|
|
|
/* If prev_match is also MIN_MATCH, match_start is garbage
|
|
* but we will ignore the current match anyway.
|
|
*/
|
|
s.match_length = MIN_MATCH - 1;
|
|
}
|
|
}
|
|
/* If there was a match at the previous step and the current
|
|
* match is not better, output the previous match:
|
|
*/
|
|
if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) {
|
|
max_insert = s.strstart + s.lookahead - MIN_MATCH;
|
|
/* Do not insert strings in hash table beyond this. */
|
|
|
|
//check_match(s, s.strstart-1, s.prev_match, s.prev_length);
|
|
|
|
/***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,
|
|
s.prev_length - MIN_MATCH, bflush);***/
|
|
bflush = trees._tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH);
|
|
/* Insert in hash table all strings up to the end of the match.
|
|
* strstart-1 and strstart are already inserted. If there is not
|
|
* enough lookahead, the last two strings are not inserted in
|
|
* the hash table.
|
|
*/
|
|
s.lookahead -= s.prev_length - 1;
|
|
s.prev_length -= 2;
|
|
do {
|
|
if (++s.strstart <= max_insert) {
|
|
/*** INSERT_STRING(s, s.strstart, hash_head); ***/
|
|
s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
|
|
hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
|
|
s.head[s.ins_h] = s.strstart;
|
|
/***/
|
|
}
|
|
} while (--s.prev_length !== 0);
|
|
s.match_available = 0;
|
|
s.match_length = MIN_MATCH - 1;
|
|
s.strstart++;
|
|
|
|
if (bflush) {
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
}
|
|
|
|
} else if (s.match_available) {
|
|
/* If there was no match at the previous position, output a
|
|
* single literal. If there was a match but the current match
|
|
* is longer, truncate the previous match to a single literal.
|
|
*/
|
|
//Tracevv((stderr,"%c", s->window[s->strstart-1]));
|
|
/*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
|
|
bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]);
|
|
|
|
if (bflush) {
|
|
/*** FLUSH_BLOCK_ONLY(s, 0) ***/
|
|
flush_block_only(s, false);
|
|
/***/
|
|
}
|
|
s.strstart++;
|
|
s.lookahead--;
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
} else {
|
|
/* There is no previous match to compare with, wait for
|
|
* the next step to decide.
|
|
*/
|
|
s.match_available = 1;
|
|
s.strstart++;
|
|
s.lookahead--;
|
|
}
|
|
}
|
|
//Assert (flush != Z_NO_FLUSH, "no flush?");
|
|
if (s.match_available) {
|
|
//Tracevv((stderr,"%c", s->window[s->strstart-1]));
|
|
/*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
|
|
bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]);
|
|
|
|
s.match_available = 0;
|
|
}
|
|
s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1;
|
|
if (flush === Z_FINISH) {
|
|
/*** FLUSH_BLOCK(s, 1); ***/
|
|
flush_block_only(s, true);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_FINISH_STARTED;
|
|
}
|
|
/***/
|
|
return BS_FINISH_DONE;
|
|
}
|
|
if (s.last_lit) {
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
}
|
|
|
|
return BS_BLOCK_DONE;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* For Z_RLE, simply look for runs of bytes, generate matches only of distance
|
|
* one. Do not maintain a hash table. (It will be regenerated if this run of
|
|
* deflate switches away from Z_RLE.)
|
|
*/
|
|
function deflate_rle(s, flush) {
|
|
var bflush; /* set if current block must be flushed */
|
|
var prev; /* byte at distance one to match */
|
|
var scan, strend; /* scan goes up to strend for length of run */
|
|
|
|
var _win = s.window;
|
|
|
|
for (;;) {
|
|
/* Make sure that we always have enough lookahead, except
|
|
* at the end of the input file. We need MAX_MATCH bytes
|
|
* for the longest run, plus one for the unrolled loop.
|
|
*/
|
|
if (s.lookahead <= MAX_MATCH) {
|
|
fill_window(s);
|
|
if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
if (s.lookahead === 0) { break; } /* flush the current block */
|
|
}
|
|
|
|
/* See how many times the previous byte repeats */
|
|
s.match_length = 0;
|
|
if (s.lookahead >= MIN_MATCH && s.strstart > 0) {
|
|
scan = s.strstart - 1;
|
|
prev = _win[scan];
|
|
if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {
|
|
strend = s.strstart + MAX_MATCH;
|
|
do {
|
|
/*jshint noempty:false*/
|
|
} while (prev === _win[++scan] && prev === _win[++scan] &&
|
|
prev === _win[++scan] && prev === _win[++scan] &&
|
|
prev === _win[++scan] && prev === _win[++scan] &&
|
|
prev === _win[++scan] && prev === _win[++scan] &&
|
|
scan < strend);
|
|
s.match_length = MAX_MATCH - (strend - scan);
|
|
if (s.match_length > s.lookahead) {
|
|
s.match_length = s.lookahead;
|
|
}
|
|
}
|
|
//Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
|
|
}
|
|
|
|
/* Emit match if have run of MIN_MATCH or longer, else emit literal */
|
|
if (s.match_length >= MIN_MATCH) {
|
|
//check_match(s, s.strstart, s.strstart - 1, s.match_length);
|
|
|
|
/*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/
|
|
bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH);
|
|
|
|
s.lookahead -= s.match_length;
|
|
s.strstart += s.match_length;
|
|
s.match_length = 0;
|
|
} else {
|
|
/* No match, output a literal byte */
|
|
//Tracevv((stderr,"%c", s->window[s->strstart]));
|
|
/*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
|
|
bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
|
|
|
|
s.lookahead--;
|
|
s.strstart++;
|
|
}
|
|
if (bflush) {
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
}
|
|
}
|
|
s.insert = 0;
|
|
if (flush === Z_FINISH) {
|
|
/*** FLUSH_BLOCK(s, 1); ***/
|
|
flush_block_only(s, true);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_FINISH_STARTED;
|
|
}
|
|
/***/
|
|
return BS_FINISH_DONE;
|
|
}
|
|
if (s.last_lit) {
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
}
|
|
return BS_BLOCK_DONE;
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
|
|
* (It will be regenerated if this run of deflate switches away from Huffman.)
|
|
*/
|
|
function deflate_huff(s, flush) {
|
|
var bflush; /* set if current block must be flushed */
|
|
|
|
for (;;) {
|
|
/* Make sure that we have a literal to write. */
|
|
if (s.lookahead === 0) {
|
|
fill_window(s);
|
|
if (s.lookahead === 0) {
|
|
if (flush === Z_NO_FLUSH) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
break; /* flush the current block */
|
|
}
|
|
}
|
|
|
|
/* Output a literal byte */
|
|
s.match_length = 0;
|
|
//Tracevv((stderr,"%c", s->window[s->strstart]));
|
|
/*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
|
|
bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
|
|
s.lookahead--;
|
|
s.strstart++;
|
|
if (bflush) {
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
}
|
|
}
|
|
s.insert = 0;
|
|
if (flush === Z_FINISH) {
|
|
/*** FLUSH_BLOCK(s, 1); ***/
|
|
flush_block_only(s, true);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_FINISH_STARTED;
|
|
}
|
|
/***/
|
|
return BS_FINISH_DONE;
|
|
}
|
|
if (s.last_lit) {
|
|
/*** FLUSH_BLOCK(s, 0); ***/
|
|
flush_block_only(s, false);
|
|
if (s.strm.avail_out === 0) {
|
|
return BS_NEED_MORE;
|
|
}
|
|
/***/
|
|
}
|
|
return BS_BLOCK_DONE;
|
|
}
|
|
|
|
/* Values for max_lazy_match, good_match and max_chain_length, depending on
|
|
* the desired pack level (0..9). The values given below have been tuned to
|
|
* exclude worst case performance for pathological files. Better values may be
|
|
* found for specific files.
|
|
*/
|
|
function Config(good_length, max_lazy, nice_length, max_chain, func) {
|
|
this.good_length = good_length;
|
|
this.max_lazy = max_lazy;
|
|
this.nice_length = nice_length;
|
|
this.max_chain = max_chain;
|
|
this.func = func;
|
|
}
|
|
|
|
var configuration_table;
|
|
|
|
configuration_table = [
|
|
/* good lazy nice chain */
|
|
new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */
|
|
new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */
|
|
new Config(4, 5, 16, 8, deflate_fast), /* 2 */
|
|
new Config(4, 6, 32, 32, deflate_fast), /* 3 */
|
|
|
|
new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */
|
|
new Config(8, 16, 32, 32, deflate_slow), /* 5 */
|
|
new Config(8, 16, 128, 128, deflate_slow), /* 6 */
|
|
new Config(8, 32, 128, 256, deflate_slow), /* 7 */
|
|
new Config(32, 128, 258, 1024, deflate_slow), /* 8 */
|
|
new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */
|
|
];
|
|
|
|
|
|
/* ===========================================================================
|
|
* Initialize the "longest match" routines for a new zlib stream
|
|
*/
|
|
function lm_init(s) {
|
|
s.window_size = 2 * s.w_size;
|
|
|
|
/*** CLEAR_HASH(s); ***/
|
|
zero(s.head); // Fill with NIL (= 0);
|
|
|
|
/* Set the default configuration parameters:
|
|
*/
|
|
s.max_lazy_match = configuration_table[s.level].max_lazy;
|
|
s.good_match = configuration_table[s.level].good_length;
|
|
s.nice_match = configuration_table[s.level].nice_length;
|
|
s.max_chain_length = configuration_table[s.level].max_chain;
|
|
|
|
s.strstart = 0;
|
|
s.block_start = 0;
|
|
s.lookahead = 0;
|
|
s.insert = 0;
|
|
s.match_length = s.prev_length = MIN_MATCH - 1;
|
|
s.match_available = 0;
|
|
s.ins_h = 0;
|
|
}
|
|
|
|
|
|
function DeflateState() {
|
|
this.strm = null; /* pointer back to this zlib stream */
|
|
this.status = 0; /* as the name implies */
|
|
this.pending_buf = null; /* output still pending */
|
|
this.pending_buf_size = 0; /* size of pending_buf */
|
|
this.pending_out = 0; /* next pending byte to output to the stream */
|
|
this.pending = 0; /* nb of bytes in the pending buffer */
|
|
this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
|
|
this.gzhead = null; /* gzip header information to write */
|
|
this.gzindex = 0; /* where in extra, name, or comment */
|
|
this.method = Z_DEFLATED; /* can only be DEFLATED */
|
|
this.last_flush = -1; /* value of flush param for previous deflate call */
|
|
|
|
this.w_size = 0; /* LZ77 window size (32K by default) */
|
|
this.w_bits = 0; /* log2(w_size) (8..16) */
|
|
this.w_mask = 0; /* w_size - 1 */
|
|
|
|
this.window = null;
|
|
/* Sliding window. Input bytes are read into the second half of the window,
|
|
* and move to the first half later to keep a dictionary of at least wSize
|
|
* bytes. With this organization, matches are limited to a distance of
|
|
* wSize-MAX_MATCH bytes, but this ensures that IO is always
|
|
* performed with a length multiple of the block size.
|
|
*/
|
|
|
|
this.window_size = 0;
|
|
/* Actual size of window: 2*wSize, except when the user input buffer
|
|
* is directly used as sliding window.
|
|
*/
|
|
|
|
this.prev = null;
|
|
/* Link to older string with same hash index. To limit the size of this
|
|
* array to 64K, this link is maintained only for the last 32K strings.
|
|
* An index in this array is thus a window index modulo 32K.
|
|
*/
|
|
|
|
this.head = null; /* Heads of the hash chains or NIL. */
|
|
|
|
this.ins_h = 0; /* hash index of string to be inserted */
|
|
this.hash_size = 0; /* number of elements in hash table */
|
|
this.hash_bits = 0; /* log2(hash_size) */
|
|
this.hash_mask = 0; /* hash_size-1 */
|
|
|
|
this.hash_shift = 0;
|
|
/* Number of bits by which ins_h must be shifted at each input
|
|
* step. It must be such that after MIN_MATCH steps, the oldest
|
|
* byte no longer takes part in the hash key, that is:
|
|
* hash_shift * MIN_MATCH >= hash_bits
|
|
*/
|
|
|
|
this.block_start = 0;
|
|
/* Window position at the beginning of the current output block. Gets
|
|
* negative when the window is moved backwards.
|
|
*/
|
|
|
|
this.match_length = 0; /* length of best match */
|
|
this.prev_match = 0; /* previous match */
|
|
this.match_available = 0; /* set if previous match exists */
|
|
this.strstart = 0; /* start of string to insert */
|
|
this.match_start = 0; /* start of matching string */
|
|
this.lookahead = 0; /* number of valid bytes ahead in window */
|
|
|
|
this.prev_length = 0;
|
|
/* Length of the best match at previous step. Matches not greater than this
|
|
* are discarded. This is used in the lazy match evaluation.
|
|
*/
|
|
|
|
this.max_chain_length = 0;
|
|
/* To speed up deflation, hash chains are never searched beyond this
|
|
* length. A higher limit improves compression ratio but degrades the
|
|
* speed.
|
|
*/
|
|
|
|
this.max_lazy_match = 0;
|
|
/* Attempt to find a better match only when the current match is strictly
|
|
* smaller than this value. This mechanism is used only for compression
|
|
* levels >= 4.
|
|
*/
|
|
// That's alias to max_lazy_match, don't use directly
|
|
//this.max_insert_length = 0;
|
|
/* Insert new strings in the hash table only if the match length is not
|
|
* greater than this length. This saves time but degrades compression.
|
|
* max_insert_length is used only for compression levels <= 3.
|
|
*/
|
|
|
|
this.level = 0; /* compression level (1..9) */
|
|
this.strategy = 0; /* favor or force Huffman coding*/
|
|
|
|
this.good_match = 0;
|
|
/* Use a faster search when the previous match is longer than this */
|
|
|
|
this.nice_match = 0; /* Stop searching when current match exceeds this */
|
|
|
|
/* used by trees.c: */
|
|
|
|
/* Didn't use ct_data typedef below to suppress compiler warning */
|
|
|
|
// struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
|
// struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
|
// struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
|
|
|
// Use flat array of DOUBLE size, with interleaved fata,
|
|
// because JS does not support effective
|
|
this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2);
|
|
this.dyn_dtree = new utils.Buf16((2 * D_CODES + 1) * 2);
|
|
this.bl_tree = new utils.Buf16((2 * BL_CODES + 1) * 2);
|
|
zero(this.dyn_ltree);
|
|
zero(this.dyn_dtree);
|
|
zero(this.bl_tree);
|
|
|
|
this.l_desc = null; /* desc. for literal tree */
|
|
this.d_desc = null; /* desc. for distance tree */
|
|
this.bl_desc = null; /* desc. for bit length tree */
|
|
|
|
//ush bl_count[MAX_BITS+1];
|
|
this.bl_count = new utils.Buf16(MAX_BITS + 1);
|
|
/* number of codes at each bit length for an optimal tree */
|
|
|
|
//int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
|
|
this.heap = new utils.Buf16(2 * L_CODES + 1); /* heap used to build the Huffman trees */
|
|
zero(this.heap);
|
|
|
|
this.heap_len = 0; /* number of elements in the heap */
|
|
this.heap_max = 0; /* element of largest frequency */
|
|
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
|
|
* The same heap array is used to build all trees.
|
|
*/
|
|
|
|
this.depth = new utils.Buf16(2 * L_CODES + 1); //uch depth[2*L_CODES+1];
|
|
zero(this.depth);
|
|
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
|
*/
|
|
|
|
this.l_buf = 0; /* buffer index for literals or lengths */
|
|
|
|
this.lit_bufsize = 0;
|
|
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
|
* limiting lit_bufsize to 64K:
|
|
* - frequencies can be kept in 16 bit counters
|
|
* - if compression is not successful for the first block, all input
|
|
* data is still in the window so we can still emit a stored block even
|
|
* when input comes from standard input. (This can also be done for
|
|
* all blocks if lit_bufsize is not greater than 32K.)
|
|
* - if compression is not successful for a file smaller than 64K, we can
|
|
* even emit a stored file instead of a stored block (saving 5 bytes).
|
|
* This is applicable only for zip (not gzip or zlib).
|
|
* - creating new Huffman trees less frequently may not provide fast
|
|
* adaptation to changes in the input data statistics. (Take for
|
|
* example a binary file with poorly compressible code followed by
|
|
* a highly compressible string table.) Smaller buffer sizes give
|
|
* fast adaptation but have of course the overhead of transmitting
|
|
* trees more frequently.
|
|
* - I can't count above 4
|
|
*/
|
|
|
|
this.last_lit = 0; /* running index in l_buf */
|
|
|
|
this.d_buf = 0;
|
|
/* Buffer index for distances. To simplify the code, d_buf and l_buf have
|
|
* the same number of elements. To use different lengths, an extra flag
|
|
* array would be necessary.
|
|
*/
|
|
|
|
this.opt_len = 0; /* bit length of current block with optimal trees */
|
|
this.static_len = 0; /* bit length of current block with static trees */
|
|
this.matches = 0; /* number of string matches in current block */
|
|
this.insert = 0; /* bytes at end of window left to insert */
|
|
|
|
|
|
this.bi_buf = 0;
|
|
/* Output buffer. bits are inserted starting at the bottom (least
|
|
* significant bits).
|
|
*/
|
|
this.bi_valid = 0;
|
|
/* Number of valid bits in bi_buf. All bits above the last valid bit
|
|
* are always zero.
|
|
*/
|
|
|
|
// Used for window memory init. We safely ignore it for JS. That makes
|
|
// sense only for pointers and memory check tools.
|
|
//this.high_water = 0;
|
|
/* High water mark offset in window for initialized bytes -- bytes above
|
|
* this are set to zero in order to avoid memory check warnings when
|
|
* longest match routines access bytes past the input. This is then
|
|
* updated to the new high water mark.
|
|
*/
|
|
}
|
|
|
|
|
|
function deflateResetKeep(strm) {
|
|
var s;
|
|
|
|
if (!strm || !strm.state) {
|
|
return err(strm, Z_STREAM_ERROR);
|
|
}
|
|
|
|
strm.total_in = strm.total_out = 0;
|
|
strm.data_type = Z_UNKNOWN;
|
|
|
|
s = strm.state;
|
|
s.pending = 0;
|
|
s.pending_out = 0;
|
|
|
|
if (s.wrap < 0) {
|
|
s.wrap = -s.wrap;
|
|
/* was made negative by deflate(..., Z_FINISH); */
|
|
}
|
|
s.status = (s.wrap ? INIT_STATE : BUSY_STATE);
|
|
strm.adler = (s.wrap === 2) ?
|
|
0 // crc32(0, Z_NULL, 0)
|
|
:
|
|
1; // adler32(0, Z_NULL, 0)
|
|
s.last_flush = Z_NO_FLUSH;
|
|
trees._tr_init(s);
|
|
return Z_OK;
|
|
}
|
|
|
|
|
|
function deflateReset(strm) {
|
|
var ret = deflateResetKeep(strm);
|
|
if (ret === Z_OK) {
|
|
lm_init(strm.state);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
function deflateSetHeader(strm, head) {
|
|
if (!strm || !strm.state) { return Z_STREAM_ERROR; }
|
|
if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; }
|
|
strm.state.gzhead = head;
|
|
return Z_OK;
|
|
}
|
|
|
|
|
|
function deflateInit2(strm, level, method, windowBits, memLevel, strategy) {
|
|
if (!strm) { // === Z_NULL
|
|
return Z_STREAM_ERROR;
|
|
}
|
|
var wrap = 1;
|
|
|
|
if (level === Z_DEFAULT_COMPRESSION) {
|
|
level = 6;
|
|
}
|
|
|
|
if (windowBits < 0) { /* suppress zlib wrapper */
|
|
wrap = 0;
|
|
windowBits = -windowBits;
|
|
}
|
|
|
|
else if (windowBits > 15) {
|
|
wrap = 2; /* write gzip wrapper instead */
|
|
windowBits -= 16;
|
|
}
|
|
|
|
|
|
if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED ||
|
|
windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
|
|
strategy < 0 || strategy > Z_FIXED) {
|
|
return err(strm, Z_STREAM_ERROR);
|
|
}
|
|
|
|
|
|
if (windowBits === 8) {
|
|
windowBits = 9;
|
|
}
|
|
/* until 256-byte window bug fixed */
|
|
|
|
var s = new DeflateState();
|
|
|
|
strm.state = s;
|
|
s.strm = strm;
|
|
|
|
s.wrap = wrap;
|
|
s.gzhead = null;
|
|
s.w_bits = windowBits;
|
|
s.w_size = 1 << s.w_bits;
|
|
s.w_mask = s.w_size - 1;
|
|
|
|
s.hash_bits = memLevel + 7;
|
|
s.hash_size = 1 << s.hash_bits;
|
|
s.hash_mask = s.hash_size - 1;
|
|
s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH);
|
|
|
|
s.window = new utils.Buf8(s.w_size * 2);
|
|
s.head = new utils.Buf16(s.hash_size);
|
|
s.prev = new utils.Buf16(s.w_size);
|
|
|
|
// Don't need mem init magic for JS.
|
|
//s.high_water = 0; /* nothing written to s->window yet */
|
|
|
|
s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
|
|
|
|
s.pending_buf_size = s.lit_bufsize * 4;
|
|
|
|
//overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
|
|
//s->pending_buf = (uchf *) overlay;
|
|
s.pending_buf = new utils.Buf8(s.pending_buf_size);
|
|
|
|
// It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)
|
|
//s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
|
|
s.d_buf = 1 * s.lit_bufsize;
|
|
|
|
//s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
|
|
s.l_buf = (1 + 2) * s.lit_bufsize;
|
|
|
|
s.level = level;
|
|
s.strategy = strategy;
|
|
s.method = method;
|
|
|
|
return deflateReset(strm);
|
|
}
|
|
|
|
function deflateInit(strm, level) {
|
|
return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
|
}
|
|
|
|
|
|
function deflate(strm, flush) {
|
|
var old_flush, s;
|
|
var beg, val; // for gzip header write only
|
|
|
|
if (!strm || !strm.state ||
|
|
flush > Z_BLOCK || flush < 0) {
|
|
return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR;
|
|
}
|
|
|
|
s = strm.state;
|
|
|
|
if (!strm.output ||
|
|
(!strm.input && strm.avail_in !== 0) ||
|
|
(s.status === FINISH_STATE && flush !== Z_FINISH)) {
|
|
return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR);
|
|
}
|
|
|
|
s.strm = strm; /* just in case */
|
|
old_flush = s.last_flush;
|
|
s.last_flush = flush;
|
|
|
|
/* Write the header */
|
|
if (s.status === INIT_STATE) {
|
|
|
|
if (s.wrap === 2) { // GZIP header
|
|
strm.adler = 0; //crc32(0L, Z_NULL, 0);
|
|
put_byte(s, 31);
|
|
put_byte(s, 139);
|
|
put_byte(s, 8);
|
|
if (!s.gzhead) { // s->gzhead == Z_NULL
|
|
put_byte(s, 0);
|
|
put_byte(s, 0);
|
|
put_byte(s, 0);
|
|
put_byte(s, 0);
|
|
put_byte(s, 0);
|
|
put_byte(s, s.level === 9 ? 2 :
|
|
(s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
|
|
4 : 0));
|
|
put_byte(s, OS_CODE);
|
|
s.status = BUSY_STATE;
|
|
}
|
|
else {
|
|
put_byte(s, (s.gzhead.text ? 1 : 0) +
|
|
(s.gzhead.hcrc ? 2 : 0) +
|
|
(!s.gzhead.extra ? 0 : 4) +
|
|
(!s.gzhead.name ? 0 : 8) +
|
|
(!s.gzhead.comment ? 0 : 16)
|
|
);
|
|
put_byte(s, s.gzhead.time & 0xff);
|
|
put_byte(s, (s.gzhead.time >> 8) & 0xff);
|
|
put_byte(s, (s.gzhead.time >> 16) & 0xff);
|
|
put_byte(s, (s.gzhead.time >> 24) & 0xff);
|
|
put_byte(s, s.level === 9 ? 2 :
|
|
(s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
|
|
4 : 0));
|
|
put_byte(s, s.gzhead.os & 0xff);
|
|
if (s.gzhead.extra && s.gzhead.extra.length) {
|
|
put_byte(s, s.gzhead.extra.length & 0xff);
|
|
put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
|
|
}
|
|
if (s.gzhead.hcrc) {
|
|
strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0);
|
|
}
|
|
s.gzindex = 0;
|
|
s.status = EXTRA_STATE;
|
|
}
|
|
}
|
|
else // DEFLATE header
|
|
{
|
|
var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;
|
|
var level_flags = -1;
|
|
|
|
if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {
|
|
level_flags = 0;
|
|
} else if (s.level < 6) {
|
|
level_flags = 1;
|
|
} else if (s.level === 6) {
|
|
level_flags = 2;
|
|
} else {
|
|
level_flags = 3;
|
|
}
|
|
header |= (level_flags << 6);
|
|
if (s.strstart !== 0) { header |= PRESET_DICT; }
|
|
header += 31 - (header % 31);
|
|
|
|
s.status = BUSY_STATE;
|
|
putShortMSB(s, header);
|
|
|
|
/* Save the adler32 of the preset dictionary: */
|
|
if (s.strstart !== 0) {
|
|
putShortMSB(s, strm.adler >>> 16);
|
|
putShortMSB(s, strm.adler & 0xffff);
|
|
}
|
|
strm.adler = 1; // adler32(0L, Z_NULL, 0);
|
|
}
|
|
}
|
|
|
|
//#ifdef GZIP
|
|
if (s.status === EXTRA_STATE) {
|
|
if (s.gzhead.extra/* != Z_NULL*/) {
|
|
beg = s.pending; /* start of bytes to update crc */
|
|
|
|
while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {
|
|
if (s.pending === s.pending_buf_size) {
|
|
if (s.gzhead.hcrc && s.pending > beg) {
|
|
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
|
}
|
|
flush_pending(strm);
|
|
beg = s.pending;
|
|
if (s.pending === s.pending_buf_size) {
|
|
break;
|
|
}
|
|
}
|
|
put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
|
|
s.gzindex++;
|
|
}
|
|
if (s.gzhead.hcrc && s.pending > beg) {
|
|
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
|
}
|
|
if (s.gzindex === s.gzhead.extra.length) {
|
|
s.gzindex = 0;
|
|
s.status = NAME_STATE;
|
|
}
|
|
}
|
|
else {
|
|
s.status = NAME_STATE;
|
|
}
|
|
}
|
|
if (s.status === NAME_STATE) {
|
|
if (s.gzhead.name/* != Z_NULL*/) {
|
|
beg = s.pending; /* start of bytes to update crc */
|
|
//int val;
|
|
|
|
do {
|
|
if (s.pending === s.pending_buf_size) {
|
|
if (s.gzhead.hcrc && s.pending > beg) {
|
|
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
|
}
|
|
flush_pending(strm);
|
|
beg = s.pending;
|
|
if (s.pending === s.pending_buf_size) {
|
|
val = 1;
|
|
break;
|
|
}
|
|
}
|
|
// JS specific: little magic to add zero terminator to end of string
|
|
if (s.gzindex < s.gzhead.name.length) {
|
|
val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
|
|
} else {
|
|
val = 0;
|
|
}
|
|
put_byte(s, val);
|
|
} while (val !== 0);
|
|
|
|
if (s.gzhead.hcrc && s.pending > beg) {
|
|
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
|
}
|
|
if (val === 0) {
|
|
s.gzindex = 0;
|
|
s.status = COMMENT_STATE;
|
|
}
|
|
}
|
|
else {
|
|
s.status = COMMENT_STATE;
|
|
}
|
|
}
|
|
if (s.status === COMMENT_STATE) {
|
|
if (s.gzhead.comment/* != Z_NULL*/) {
|
|
beg = s.pending; /* start of bytes to update crc */
|
|
//int val;
|
|
|
|
do {
|
|
if (s.pending === s.pending_buf_size) {
|
|
if (s.gzhead.hcrc && s.pending > beg) {
|
|
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
|
}
|
|
flush_pending(strm);
|
|
beg = s.pending;
|
|
if (s.pending === s.pending_buf_size) {
|
|
val = 1;
|
|
break;
|
|
}
|
|
}
|
|
// JS specific: little magic to add zero terminator to end of string
|
|
if (s.gzindex < s.gzhead.comment.length) {
|
|
val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
|
|
} else {
|
|
val = 0;
|
|
}
|
|
put_byte(s, val);
|
|
} while (val !== 0);
|
|
|
|
if (s.gzhead.hcrc && s.pending > beg) {
|
|
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
|
}
|
|
if (val === 0) {
|
|
s.status = HCRC_STATE;
|
|
}
|
|
}
|
|
else {
|
|
s.status = HCRC_STATE;
|
|
}
|
|
}
|
|
if (s.status === HCRC_STATE) {
|
|
if (s.gzhead.hcrc) {
|
|
if (s.pending + 2 > s.pending_buf_size) {
|
|
flush_pending(strm);
|
|
}
|
|
if (s.pending + 2 <= s.pending_buf_size) {
|
|
put_byte(s, strm.adler & 0xff);
|
|
put_byte(s, (strm.adler >> 8) & 0xff);
|
|
strm.adler = 0; //crc32(0L, Z_NULL, 0);
|
|
s.status = BUSY_STATE;
|
|
}
|
|
}
|
|
else {
|
|
s.status = BUSY_STATE;
|
|
}
|
|
}
|
|
//#endif
|
|
|
|
/* Flush as much pending output as possible */
|
|
if (s.pending !== 0) {
|
|
flush_pending(strm);
|
|
if (strm.avail_out === 0) {
|
|
/* Since avail_out is 0, deflate will be called again with
|
|
* more output space, but possibly with both pending and
|
|
* avail_in equal to zero. There won't be anything to do,
|
|
* but this is not an error situation so make sure we
|
|
* return OK instead of BUF_ERROR at next call of deflate:
|
|
*/
|
|
s.last_flush = -1;
|
|
return Z_OK;
|
|
}
|
|
|
|
/* Make sure there is something to do and avoid duplicate consecutive
|
|
* flushes. For repeated and useless calls with Z_FINISH, we keep
|
|
* returning Z_STREAM_END instead of Z_BUF_ERROR.
|
|
*/
|
|
} else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&
|
|
flush !== Z_FINISH) {
|
|
return err(strm, Z_BUF_ERROR);
|
|
}
|
|
|
|
/* User must not provide more input after the first FINISH: */
|
|
if (s.status === FINISH_STATE && strm.avail_in !== 0) {
|
|
return err(strm, Z_BUF_ERROR);
|
|
}
|
|
|
|
/* Start a new block or continue the current one.
|
|
*/
|
|
if (strm.avail_in !== 0 || s.lookahead !== 0 ||
|
|
(flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) {
|
|
var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) :
|
|
(s.strategy === Z_RLE ? deflate_rle(s, flush) :
|
|
configuration_table[s.level].func(s, flush));
|
|
|
|
if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {
|
|
s.status = FINISH_STATE;
|
|
}
|
|
if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {
|
|
if (strm.avail_out === 0) {
|
|
s.last_flush = -1;
|
|
/* avoid BUF_ERROR next call, see above */
|
|
}
|
|
return Z_OK;
|
|
/* If flush != Z_NO_FLUSH && avail_out == 0, the next call
|
|
* of deflate should use the same flush parameter to make sure
|
|
* that the flush is complete. So we don't have to output an
|
|
* empty block here, this will be done at next call. This also
|
|
* ensures that for a very small output buffer, we emit at most
|
|
* one empty block.
|
|
*/
|
|
}
|
|
if (bstate === BS_BLOCK_DONE) {
|
|
if (flush === Z_PARTIAL_FLUSH) {
|
|
trees._tr_align(s);
|
|
}
|
|
else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
|
|
|
|
trees._tr_stored_block(s, 0, 0, false);
|
|
/* For a full flush, this empty block will be recognized
|
|
* as a special marker by inflate_sync().
|
|
*/
|
|
if (flush === Z_FULL_FLUSH) {
|
|
/*** CLEAR_HASH(s); ***/ /* forget history */
|
|
zero(s.head); // Fill with NIL (= 0);
|
|
|
|
if (s.lookahead === 0) {
|
|
s.strstart = 0;
|
|
s.block_start = 0;
|
|
s.insert = 0;
|
|
}
|
|
}
|
|
}
|
|
flush_pending(strm);
|
|
if (strm.avail_out === 0) {
|
|
s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */
|
|
return Z_OK;
|
|
}
|
|
}
|
|
}
|
|
//Assert(strm->avail_out > 0, "bug2");
|
|
//if (strm.avail_out <= 0) { throw new Error("bug2");}
|
|
|
|
if (flush !== Z_FINISH) { return Z_OK; }
|
|
if (s.wrap <= 0) { return Z_STREAM_END; }
|
|
|
|
/* Write the trailer */
|
|
if (s.wrap === 2) {
|
|
put_byte(s, strm.adler & 0xff);
|
|
put_byte(s, (strm.adler >> 8) & 0xff);
|
|
put_byte(s, (strm.adler >> 16) & 0xff);
|
|
put_byte(s, (strm.adler >> 24) & 0xff);
|
|
put_byte(s, strm.total_in & 0xff);
|
|
put_byte(s, (strm.total_in >> 8) & 0xff);
|
|
put_byte(s, (strm.total_in >> 16) & 0xff);
|
|
put_byte(s, (strm.total_in >> 24) & 0xff);
|
|
}
|
|
else
|
|
{
|
|
putShortMSB(s, strm.adler >>> 16);
|
|
putShortMSB(s, strm.adler & 0xffff);
|
|
}
|
|
|
|
flush_pending(strm);
|
|
/* If avail_out is zero, the application will call deflate again
|
|
* to flush the rest.
|
|
*/
|
|
if (s.wrap > 0) { s.wrap = -s.wrap; }
|
|
/* write the trailer only once! */
|
|
return s.pending !== 0 ? Z_OK : Z_STREAM_END;
|
|
}
|
|
|
|
function deflateEnd(strm) {
|
|
var status;
|
|
|
|
if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
|
|
return Z_STREAM_ERROR;
|
|
}
|
|
|
|
status = strm.state.status;
|
|
if (status !== INIT_STATE &&
|
|
status !== EXTRA_STATE &&
|
|
status !== NAME_STATE &&
|
|
status !== COMMENT_STATE &&
|
|
status !== HCRC_STATE &&
|
|
status !== BUSY_STATE &&
|
|
status !== FINISH_STATE
|
|
) {
|
|
return err(strm, Z_STREAM_ERROR);
|
|
}
|
|
|
|
strm.state = null;
|
|
|
|
return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK;
|
|
}
|
|
|
|
|
|
/* =========================================================================
|
|
* Initializes the compression dictionary from the given byte
|
|
* sequence without producing any compressed output.
|
|
*/
|
|
function deflateSetDictionary(strm, dictionary) {
|
|
var dictLength = dictionary.length;
|
|
|
|
var s;
|
|
var str, n;
|
|
var wrap;
|
|
var avail;
|
|
var next;
|
|
var input;
|
|
var tmpDict;
|
|
|
|
if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
|
|
return Z_STREAM_ERROR;
|
|
}
|
|
|
|
s = strm.state;
|
|
wrap = s.wrap;
|
|
|
|
if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {
|
|
return Z_STREAM_ERROR;
|
|
}
|
|
|
|
/* when using zlib wrappers, compute Adler-32 for provided dictionary */
|
|
if (wrap === 1) {
|
|
/* adler32(strm->adler, dictionary, dictLength); */
|
|
strm.adler = adler32(strm.adler, dictionary, dictLength, 0);
|
|
}
|
|
|
|
s.wrap = 0; /* avoid computing Adler-32 in read_buf */
|
|
|
|
/* if dictionary would fill window, just replace the history */
|
|
if (dictLength >= s.w_size) {
|
|
if (wrap === 0) { /* already empty otherwise */
|
|
/*** CLEAR_HASH(s); ***/
|
|
zero(s.head); // Fill with NIL (= 0);
|
|
s.strstart = 0;
|
|
s.block_start = 0;
|
|
s.insert = 0;
|
|
}
|
|
/* use the tail */
|
|
// dictionary = dictionary.slice(dictLength - s.w_size);
|
|
tmpDict = new utils.Buf8(s.w_size);
|
|
utils.arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0);
|
|
dictionary = tmpDict;
|
|
dictLength = s.w_size;
|
|
}
|
|
/* insert dictionary into window and hash */
|
|
avail = strm.avail_in;
|
|
next = strm.next_in;
|
|
input = strm.input;
|
|
strm.avail_in = dictLength;
|
|
strm.next_in = 0;
|
|
strm.input = dictionary;
|
|
fill_window(s);
|
|
while (s.lookahead >= MIN_MATCH) {
|
|
str = s.strstart;
|
|
n = s.lookahead - (MIN_MATCH - 1);
|
|
do {
|
|
/* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
|
|
s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask;
|
|
|
|
s.prev[str & s.w_mask] = s.head[s.ins_h];
|
|
|
|
s.head[s.ins_h] = str;
|
|
str++;
|
|
} while (--n);
|
|
s.strstart = str;
|
|
s.lookahead = MIN_MATCH - 1;
|
|
fill_window(s);
|
|
}
|
|
s.strstart += s.lookahead;
|
|
s.block_start = s.strstart;
|
|
s.insert = s.lookahead;
|
|
s.lookahead = 0;
|
|
s.match_length = s.prev_length = MIN_MATCH - 1;
|
|
s.match_available = 0;
|
|
strm.next_in = next;
|
|
strm.input = input;
|
|
strm.avail_in = avail;
|
|
s.wrap = wrap;
|
|
return Z_OK;
|
|
}
|
|
|
|
|
|
exports.deflateInit = deflateInit;
|
|
exports.deflateInit2 = deflateInit2;
|
|
exports.deflateReset = deflateReset;
|
|
exports.deflateResetKeep = deflateResetKeep;
|
|
exports.deflateSetHeader = deflateSetHeader;
|
|
exports.deflate = deflate;
|
|
exports.deflateEnd = deflateEnd;
|
|
exports.deflateSetDictionary = deflateSetDictionary;
|
|
exports.deflateInfo = 'pako deflate (from Nodeca project)';
|
|
|
|
/* Not implemented
|
|
exports.deflateBound = deflateBound;
|
|
exports.deflateCopy = deflateCopy;
|
|
exports.deflateParams = deflateParams;
|
|
exports.deflatePending = deflatePending;
|
|
exports.deflatePrime = deflatePrime;
|
|
exports.deflateTune = deflateTune;
|
|
*/
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/inffast.js":
|
|
/*!****************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/zlib/inffast.js ***!
|
|
\****************************************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
// See state defs from inflate.js
|
|
var BAD = 30; /* got a data error -- remain here until reset */
|
|
var TYPE = 12; /* i: waiting for type bits, including last-flag bit */
|
|
|
|
/*
|
|
Decode literal, length, and distance codes and write out the resulting
|
|
literal and match bytes until either not enough input or output is
|
|
available, an end-of-block is encountered, or a data error is encountered.
|
|
When large enough input and output buffers are supplied to inflate(), for
|
|
example, a 16K input buffer and a 64K output buffer, more than 95% of the
|
|
inflate execution time is spent in this routine.
|
|
|
|
Entry assumptions:
|
|
|
|
state.mode === LEN
|
|
strm.avail_in >= 6
|
|
strm.avail_out >= 258
|
|
start >= strm.avail_out
|
|
state.bits < 8
|
|
|
|
On return, state.mode is one of:
|
|
|
|
LEN -- ran out of enough output space or enough available input
|
|
TYPE -- reached end of block code, inflate() to interpret next block
|
|
BAD -- error in block data
|
|
|
|
Notes:
|
|
|
|
- The maximum input bits used by a length/distance pair is 15 bits for the
|
|
length code, 5 bits for the length extra, 15 bits for the distance code,
|
|
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
|
|
Therefore if strm.avail_in >= 6, then there is enough input to avoid
|
|
checking for available input while decoding.
|
|
|
|
- The maximum bytes that a single length/distance pair can output is 258
|
|
bytes, which is the maximum length that can be coded. inflate_fast()
|
|
requires strm.avail_out >= 258 for each loop to avoid checking for
|
|
output space.
|
|
*/
|
|
module.exports = function inflate_fast(strm, start) {
|
|
var state;
|
|
var _in; /* local strm.input */
|
|
var last; /* have enough input while in < last */
|
|
var _out; /* local strm.output */
|
|
var beg; /* inflate()'s initial strm.output */
|
|
var end; /* while out < end, enough space available */
|
|
//#ifdef INFLATE_STRICT
|
|
var dmax; /* maximum distance from zlib header */
|
|
//#endif
|
|
var wsize; /* window size or zero if not using window */
|
|
var whave; /* valid bytes in the window */
|
|
var wnext; /* window write index */
|
|
// Use `s_window` instead `window`, avoid conflict with instrumentation tools
|
|
var s_window; /* allocated sliding window, if wsize != 0 */
|
|
var hold; /* local strm.hold */
|
|
var bits; /* local strm.bits */
|
|
var lcode; /* local strm.lencode */
|
|
var dcode; /* local strm.distcode */
|
|
var lmask; /* mask for first level of length codes */
|
|
var dmask; /* mask for first level of distance codes */
|
|
var here; /* retrieved table entry */
|
|
var op; /* code bits, operation, extra bits, or */
|
|
/* window position, window bytes to copy */
|
|
var len; /* match length, unused bytes */
|
|
var dist; /* match distance */
|
|
var from; /* where to copy match from */
|
|
var from_source;
|
|
|
|
|
|
var input, output; // JS specific, because we have no pointers
|
|
|
|
/* copy state to local variables */
|
|
state = strm.state;
|
|
//here = state.here;
|
|
_in = strm.next_in;
|
|
input = strm.input;
|
|
last = _in + (strm.avail_in - 5);
|
|
_out = strm.next_out;
|
|
output = strm.output;
|
|
beg = _out - (start - strm.avail_out);
|
|
end = _out + (strm.avail_out - 257);
|
|
//#ifdef INFLATE_STRICT
|
|
dmax = state.dmax;
|
|
//#endif
|
|
wsize = state.wsize;
|
|
whave = state.whave;
|
|
wnext = state.wnext;
|
|
s_window = state.window;
|
|
hold = state.hold;
|
|
bits = state.bits;
|
|
lcode = state.lencode;
|
|
dcode = state.distcode;
|
|
lmask = (1 << state.lenbits) - 1;
|
|
dmask = (1 << state.distbits) - 1;
|
|
|
|
|
|
/* decode literals and length/distances until end-of-block or not enough
|
|
input data or output space */
|
|
|
|
top:
|
|
do {
|
|
if (bits < 15) {
|
|
hold += input[_in++] << bits;
|
|
bits += 8;
|
|
hold += input[_in++] << bits;
|
|
bits += 8;
|
|
}
|
|
|
|
here = lcode[hold & lmask];
|
|
|
|
dolen:
|
|
for (;;) { // Goto emulation
|
|
op = here >>> 24/*here.bits*/;
|
|
hold >>>= op;
|
|
bits -= op;
|
|
op = (here >>> 16) & 0xff/*here.op*/;
|
|
if (op === 0) { /* literal */
|
|
//Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
|
// "inflate: literal '%c'\n" :
|
|
// "inflate: literal 0x%02x\n", here.val));
|
|
output[_out++] = here & 0xffff/*here.val*/;
|
|
}
|
|
else if (op & 16) { /* length base */
|
|
len = here & 0xffff/*here.val*/;
|
|
op &= 15; /* number of extra bits */
|
|
if (op) {
|
|
if (bits < op) {
|
|
hold += input[_in++] << bits;
|
|
bits += 8;
|
|
}
|
|
len += hold & ((1 << op) - 1);
|
|
hold >>>= op;
|
|
bits -= op;
|
|
}
|
|
//Tracevv((stderr, "inflate: length %u\n", len));
|
|
if (bits < 15) {
|
|
hold += input[_in++] << bits;
|
|
bits += 8;
|
|
hold += input[_in++] << bits;
|
|
bits += 8;
|
|
}
|
|
here = dcode[hold & dmask];
|
|
|
|
dodist:
|
|
for (;;) { // goto emulation
|
|
op = here >>> 24/*here.bits*/;
|
|
hold >>>= op;
|
|
bits -= op;
|
|
op = (here >>> 16) & 0xff/*here.op*/;
|
|
|
|
if (op & 16) { /* distance base */
|
|
dist = here & 0xffff/*here.val*/;
|
|
op &= 15; /* number of extra bits */
|
|
if (bits < op) {
|
|
hold += input[_in++] << bits;
|
|
bits += 8;
|
|
if (bits < op) {
|
|
hold += input[_in++] << bits;
|
|
bits += 8;
|
|
}
|
|
}
|
|
dist += hold & ((1 << op) - 1);
|
|
//#ifdef INFLATE_STRICT
|
|
if (dist > dmax) {
|
|
strm.msg = 'invalid distance too far back';
|
|
state.mode = BAD;
|
|
break top;
|
|
}
|
|
//#endif
|
|
hold >>>= op;
|
|
bits -= op;
|
|
//Tracevv((stderr, "inflate: distance %u\n", dist));
|
|
op = _out - beg; /* max distance in output */
|
|
if (dist > op) { /* see if copy from window */
|
|
op = dist - op; /* distance back in window */
|
|
if (op > whave) {
|
|
if (state.sane) {
|
|
strm.msg = 'invalid distance too far back';
|
|
state.mode = BAD;
|
|
break top;
|
|
}
|
|
|
|
// (!) This block is disabled in zlib defaults,
|
|
// don't enable it for binary compatibility
|
|
//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
|
// if (len <= op - whave) {
|
|
// do {
|
|
// output[_out++] = 0;
|
|
// } while (--len);
|
|
// continue top;
|
|
// }
|
|
// len -= op - whave;
|
|
// do {
|
|
// output[_out++] = 0;
|
|
// } while (--op > whave);
|
|
// if (op === 0) {
|
|
// from = _out - dist;
|
|
// do {
|
|
// output[_out++] = output[from++];
|
|
// } while (--len);
|
|
// continue top;
|
|
// }
|
|
//#endif
|
|
}
|
|
from = 0; // window index
|
|
from_source = s_window;
|
|
if (wnext === 0) { /* very common case */
|
|
from += wsize - op;
|
|
if (op < len) { /* some from window */
|
|
len -= op;
|
|
do {
|
|
output[_out++] = s_window[from++];
|
|
} while (--op);
|
|
from = _out - dist; /* rest from output */
|
|
from_source = output;
|
|
}
|
|
}
|
|
else if (wnext < op) { /* wrap around window */
|
|
from += wsize + wnext - op;
|
|
op -= wnext;
|
|
if (op < len) { /* some from end of window */
|
|
len -= op;
|
|
do {
|
|
output[_out++] = s_window[from++];
|
|
} while (--op);
|
|
from = 0;
|
|
if (wnext < len) { /* some from start of window */
|
|
op = wnext;
|
|
len -= op;
|
|
do {
|
|
output[_out++] = s_window[from++];
|
|
} while (--op);
|
|
from = _out - dist; /* rest from output */
|
|
from_source = output;
|
|
}
|
|
}
|
|
}
|
|
else { /* contiguous in window */
|
|
from += wnext - op;
|
|
if (op < len) { /* some from window */
|
|
len -= op;
|
|
do {
|
|
output[_out++] = s_window[from++];
|
|
} while (--op);
|
|
from = _out - dist; /* rest from output */
|
|
from_source = output;
|
|
}
|
|
}
|
|
while (len > 2) {
|
|
output[_out++] = from_source[from++];
|
|
output[_out++] = from_source[from++];
|
|
output[_out++] = from_source[from++];
|
|
len -= 3;
|
|
}
|
|
if (len) {
|
|
output[_out++] = from_source[from++];
|
|
if (len > 1) {
|
|
output[_out++] = from_source[from++];
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
from = _out - dist; /* copy direct from output */
|
|
do { /* minimum length is three */
|
|
output[_out++] = output[from++];
|
|
output[_out++] = output[from++];
|
|
output[_out++] = output[from++];
|
|
len -= 3;
|
|
} while (len > 2);
|
|
if (len) {
|
|
output[_out++] = output[from++];
|
|
if (len > 1) {
|
|
output[_out++] = output[from++];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ((op & 64) === 0) { /* 2nd level distance code */
|
|
here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
|
|
continue dodist;
|
|
}
|
|
else {
|
|
strm.msg = 'invalid distance code';
|
|
state.mode = BAD;
|
|
break top;
|
|
}
|
|
|
|
break; // need to emulate goto via "continue"
|
|
}
|
|
}
|
|
else if ((op & 64) === 0) { /* 2nd level length code */
|
|
here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
|
|
continue dolen;
|
|
}
|
|
else if (op & 32) { /* end-of-block */
|
|
//Tracevv((stderr, "inflate: end of block\n"));
|
|
state.mode = TYPE;
|
|
break top;
|
|
}
|
|
else {
|
|
strm.msg = 'invalid literal/length code';
|
|
state.mode = BAD;
|
|
break top;
|
|
}
|
|
|
|
break; // need to emulate goto via "continue"
|
|
}
|
|
} while (_in < last && _out < end);
|
|
|
|
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
|
|
len = bits >> 3;
|
|
_in -= len;
|
|
bits -= len << 3;
|
|
hold &= (1 << bits) - 1;
|
|
|
|
/* update state and return */
|
|
strm.next_in = _in;
|
|
strm.next_out = _out;
|
|
strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
|
|
strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
|
|
state.hold = hold;
|
|
state.bits = bits;
|
|
return;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/inflate.js":
|
|
/*!****************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/zlib/inflate.js ***!
|
|
\****************************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
var utils = __webpack_require__(/*! ../utils/common */ "./node_modules/browserify-zlib/node_modules/pako/lib/utils/common.js");
|
|
var adler32 = __webpack_require__(/*! ./adler32 */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/adler32.js");
|
|
var crc32 = __webpack_require__(/*! ./crc32 */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/crc32.js");
|
|
var inflate_fast = __webpack_require__(/*! ./inffast */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/inffast.js");
|
|
var inflate_table = __webpack_require__(/*! ./inftrees */ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/inftrees.js");
|
|
|
|
var CODES = 0;
|
|
var LENS = 1;
|
|
var DISTS = 2;
|
|
|
|
/* Public constants ==========================================================*/
|
|
/* ===========================================================================*/
|
|
|
|
|
|
/* Allowed flush values; see deflate() and inflate() below for details */
|
|
//var Z_NO_FLUSH = 0;
|
|
//var Z_PARTIAL_FLUSH = 1;
|
|
//var Z_SYNC_FLUSH = 2;
|
|
//var Z_FULL_FLUSH = 3;
|
|
var Z_FINISH = 4;
|
|
var Z_BLOCK = 5;
|
|
var Z_TREES = 6;
|
|
|
|
|
|
/* Return codes for the compression/decompression functions. Negative values
|
|
* are errors, positive values are used for special but normal events.
|
|
*/
|
|
var Z_OK = 0;
|
|
var Z_STREAM_END = 1;
|
|
var Z_NEED_DICT = 2;
|
|
//var Z_ERRNO = -1;
|
|
var Z_STREAM_ERROR = -2;
|
|
var Z_DATA_ERROR = -3;
|
|
var Z_MEM_ERROR = -4;
|
|
var Z_BUF_ERROR = -5;
|
|
//var Z_VERSION_ERROR = -6;
|
|
|
|
/* The deflate compression method */
|
|
var Z_DEFLATED = 8;
|
|
|
|
|
|
/* STATES ====================================================================*/
|
|
/* ===========================================================================*/
|
|
|
|
|
|
var HEAD = 1; /* i: waiting for magic header */
|
|
var FLAGS = 2; /* i: waiting for method and flags (gzip) */
|
|
var TIME = 3; /* i: waiting for modification time (gzip) */
|
|
var OS = 4; /* i: waiting for extra flags and operating system (gzip) */
|
|
var EXLEN = 5; /* i: waiting for extra length (gzip) */
|
|
var EXTRA = 6; /* i: waiting for extra bytes (gzip) */
|
|
var NAME = 7; /* i: waiting for end of file name (gzip) */
|
|
var COMMENT = 8; /* i: waiting for end of comment (gzip) */
|
|
var HCRC = 9; /* i: waiting for header crc (gzip) */
|
|
var DICTID = 10; /* i: waiting for dictionary check value */
|
|
var DICT = 11; /* waiting for inflateSetDictionary() call */
|
|
var TYPE = 12; /* i: waiting for type bits, including last-flag bit */
|
|
var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */
|
|
var STORED = 14; /* i: waiting for stored size (length and complement) */
|
|
var COPY_ = 15; /* i/o: same as COPY below, but only first time in */
|
|
var COPY = 16; /* i/o: waiting for input or output to copy stored block */
|
|
var TABLE = 17; /* i: waiting for dynamic block table lengths */
|
|
var LENLENS = 18; /* i: waiting for code length code lengths */
|
|
var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */
|
|
var LEN_ = 20; /* i: same as LEN below, but only first time in */
|
|
var LEN = 21; /* i: waiting for length/lit/eob code */
|
|
var LENEXT = 22; /* i: waiting for length extra bits */
|
|
var DIST = 23; /* i: waiting for distance code */
|
|
var DISTEXT = 24; /* i: waiting for distance extra bits */
|
|
var MATCH = 25; /* o: waiting for output space to copy string */
|
|
var LIT = 26; /* o: waiting for output space to write literal */
|
|
var CHECK = 27; /* i: waiting for 32-bit check value */
|
|
var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */
|
|
var DONE = 29; /* finished check, done -- remain here until reset */
|
|
var BAD = 30; /* got a data error -- remain here until reset */
|
|
var MEM = 31; /* got an inflate() memory error -- remain here until reset */
|
|
var SYNC = 32; /* looking for synchronization bytes to restart inflate() */
|
|
|
|
/* ===========================================================================*/
|
|
|
|
|
|
|
|
var ENOUGH_LENS = 852;
|
|
var ENOUGH_DISTS = 592;
|
|
//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
|
|
|
|
var MAX_WBITS = 15;
|
|
/* 32K LZ77 window */
|
|
var DEF_WBITS = MAX_WBITS;
|
|
|
|
|
|
function zswap32(q) {
|
|
return (((q >>> 24) & 0xff) +
|
|
((q >>> 8) & 0xff00) +
|
|
((q & 0xff00) << 8) +
|
|
((q & 0xff) << 24));
|
|
}
|
|
|
|
|
|
function InflateState() {
|
|
this.mode = 0; /* current inflate mode */
|
|
this.last = false; /* true if processing last block */
|
|
this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
|
|
this.havedict = false; /* true if dictionary provided */
|
|
this.flags = 0; /* gzip header method and flags (0 if zlib) */
|
|
this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */
|
|
this.check = 0; /* protected copy of check value */
|
|
this.total = 0; /* protected copy of output count */
|
|
// TODO: may be {}
|
|
this.head = null; /* where to save gzip header information */
|
|
|
|
/* sliding window */
|
|
this.wbits = 0; /* log base 2 of requested window size */
|
|
this.wsize = 0; /* window size or zero if not using window */
|
|
this.whave = 0; /* valid bytes in the window */
|
|
this.wnext = 0; /* window write index */
|
|
this.window = null; /* allocated sliding window, if needed */
|
|
|
|
/* bit accumulator */
|
|
this.hold = 0; /* input bit accumulator */
|
|
this.bits = 0; /* number of bits in "in" */
|
|
|
|
/* for string and stored block copying */
|
|
this.length = 0; /* literal or length of data to copy */
|
|
this.offset = 0; /* distance back to copy string from */
|
|
|
|
/* for table and code decoding */
|
|
this.extra = 0; /* extra bits needed */
|
|
|
|
/* fixed and dynamic code tables */
|
|
this.lencode = null; /* starting table for length/literal codes */
|
|
this.distcode = null; /* starting table for distance codes */
|
|
this.lenbits = 0; /* index bits for lencode */
|
|
this.distbits = 0; /* index bits for distcode */
|
|
|
|
/* dynamic table building */
|
|
this.ncode = 0; /* number of code length code lengths */
|
|
this.nlen = 0; /* number of length code lengths */
|
|
this.ndist = 0; /* number of distance code lengths */
|
|
this.have = 0; /* number of code lengths in lens[] */
|
|
this.next = null; /* next available space in codes[] */
|
|
|
|
this.lens = new utils.Buf16(320); /* temporary storage for code lengths */
|
|
this.work = new utils.Buf16(288); /* work area for code table building */
|
|
|
|
/*
|
|
because we don't have pointers in js, we use lencode and distcode directly
|
|
as buffers so we don't need codes
|
|
*/
|
|
//this.codes = new utils.Buf32(ENOUGH); /* space for code tables */
|
|
this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */
|
|
this.distdyn = null; /* dynamic table for distance codes (JS specific) */
|
|
this.sane = 0; /* if false, allow invalid distance too far */
|
|
this.back = 0; /* bits back of last unprocessed length/lit */
|
|
this.was = 0; /* initial length of match */
|
|
}
|
|
|
|
function inflateResetKeep(strm) {
|
|
var state;
|
|
|
|
if (!strm || !strm.state) { return Z_STREAM_ERROR; }
|
|
state = strm.state;
|
|
strm.total_in = strm.total_out = state.total = 0;
|
|
strm.msg = ''; /*Z_NULL*/
|
|
if (state.wrap) { /* to support ill-conceived Java test suite */
|
|
strm.adler = state.wrap & 1;
|
|
}
|
|
state.mode = HEAD;
|
|
state.last = 0;
|
|
state.havedict = 0;
|
|
state.dmax = 32768;
|
|
state.head = null/*Z_NULL*/;
|
|
state.hold = 0;
|
|
state.bits = 0;
|
|
//state.lencode = state.distcode = state.next = state.codes;
|
|
state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS);
|
|
state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS);
|
|
|
|
state.sane = 1;
|
|
state.back = -1;
|
|
//Tracev((stderr, "inflate: reset\n"));
|
|
return Z_OK;
|
|
}
|
|
|
|
function inflateReset(strm) {
|
|
var state;
|
|
|
|
if (!strm || !strm.state) { return Z_STREAM_ERROR; }
|
|
state = strm.state;
|
|
state.wsize = 0;
|
|
state.whave = 0;
|
|
state.wnext = 0;
|
|
return inflateResetKeep(strm);
|
|
|
|
}
|
|
|
|
function inflateReset2(strm, windowBits) {
|
|
var wrap;
|
|
var state;
|
|
|
|
/* get the state */
|
|
if (!strm || !strm.state) { return Z_STREAM_ERROR; }
|
|
state = strm.state;
|
|
|
|
/* extract wrap request from windowBits parameter */
|
|
if (windowBits < 0) {
|
|
wrap = 0;
|
|
windowBits = -windowBits;
|
|
}
|
|
else {
|
|
wrap = (windowBits >> 4) + 1;
|
|
if (windowBits < 48) {
|
|
windowBits &= 15;
|
|
}
|
|
}
|
|
|
|
/* set number of window bits, free window if different */
|
|
if (windowBits && (windowBits < 8 || windowBits > 15)) {
|
|
return Z_STREAM_ERROR;
|
|
}
|
|
if (state.window !== null && state.wbits !== windowBits) {
|
|
state.window = null;
|
|
}
|
|
|
|
/* update state and reset the rest of it */
|
|
state.wrap = wrap;
|
|
state.wbits = windowBits;
|
|
return inflateReset(strm);
|
|
}
|
|
|
|
function inflateInit2(strm, windowBits) {
|
|
var ret;
|
|
var state;
|
|
|
|
if (!strm) { return Z_STREAM_ERROR; }
|
|
//strm.msg = Z_NULL; /* in case we return an error */
|
|
|
|
state = new InflateState();
|
|
|
|
//if (state === Z_NULL) return Z_MEM_ERROR;
|
|
//Tracev((stderr, "inflate: allocated\n"));
|
|
strm.state = state;
|
|
state.window = null/*Z_NULL*/;
|
|
ret = inflateReset2(strm, windowBits);
|
|
if (ret !== Z_OK) {
|
|
strm.state = null/*Z_NULL*/;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
function inflateInit(strm) {
|
|
return inflateInit2(strm, DEF_WBITS);
|
|
}
|
|
|
|
|
|
/*
|
|
Return state with length and distance decoding tables and index sizes set to
|
|
fixed code decoding. Normally this returns fixed tables from inffixed.h.
|
|
If BUILDFIXED is defined, then instead this routine builds the tables the
|
|
first time it's called, and returns those tables the first time and
|
|
thereafter. This reduces the size of the code by about 2K bytes, in
|
|
exchange for a little execution time. However, BUILDFIXED should not be
|
|
used for threaded applications, since the rewriting of the tables and virgin
|
|
may not be thread-safe.
|
|
*/
|
|
var virgin = true;
|
|
|
|
var lenfix, distfix; // We have no pointers in JS, so keep tables separate
|
|
|
|
function fixedtables(state) {
|
|
/* build fixed huffman tables if first call (may not be thread safe) */
|
|
if (virgin) {
|
|
var sym;
|
|
|
|
lenfix = new utils.Buf32(512);
|
|
distfix = new utils.Buf32(32);
|
|
|
|
/* literal/length table */
|
|
sym = 0;
|
|
while (sym < 144) { state.lens[sym++] = 8; }
|
|
while (sym < 256) { state.lens[sym++] = 9; }
|
|
while (sym < 280) { state.lens[sym++] = 7; }
|
|
while (sym < 288) { state.lens[sym++] = 8; }
|
|
|
|
inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 });
|
|
|
|
/* distance table */
|
|
sym = 0;
|
|
while (sym < 32) { state.lens[sym++] = 5; }
|
|
|
|
inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 });
|
|
|
|
/* do this just once */
|
|
virgin = false;
|
|
}
|
|
|
|
state.lencode = lenfix;
|
|
state.lenbits = 9;
|
|
state.distcode = distfix;
|
|
state.distbits = 5;
|
|
}
|
|
|
|
|
|
/*
|
|
Update the window with the last wsize (normally 32K) bytes written before
|
|
returning. If window does not exist yet, create it. This is only called
|
|
when a window is already in use, or when output has been written during this
|
|
inflate call, but the end of the deflate stream has not been reached yet.
|
|
It is also called to create a window for dictionary data when a dictionary
|
|
is loaded.
|
|
|
|
Providing output buffers larger than 32K to inflate() should provide a speed
|
|
advantage, since only the last 32K of output is copied to the sliding window
|
|
upon return from inflate(), and since all distances after the first 32K of
|
|
output will fall in the output data, making match copies simpler and faster.
|
|
The advantage may be dependent on the size of the processor's data caches.
|
|
*/
|
|
function updatewindow(strm, src, end, copy) {
|
|
var dist;
|
|
var state = strm.state;
|
|
|
|
/* if it hasn't been done already, allocate space for the window */
|
|
if (state.window === null) {
|
|
state.wsize = 1 << state.wbits;
|
|
state.wnext = 0;
|
|
state.whave = 0;
|
|
|
|
state.window = new utils.Buf8(state.wsize);
|
|
}
|
|
|
|
/* copy state->wsize or less output bytes into the circular window */
|
|
if (copy >= state.wsize) {
|
|
utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0);
|
|
state.wnext = 0;
|
|
state.whave = state.wsize;
|
|
}
|
|
else {
|
|
dist = state.wsize - state.wnext;
|
|
if (dist > copy) {
|
|
dist = copy;
|
|
}
|
|
//zmemcpy(state->window + state->wnext, end - copy, dist);
|
|
utils.arraySet(state.window, src, end - copy, dist, state.wnext);
|
|
copy -= dist;
|
|
if (copy) {
|
|
//zmemcpy(state->window, end - copy, copy);
|
|
utils.arraySet(state.window, src, end - copy, copy, 0);
|
|
state.wnext = copy;
|
|
state.whave = state.wsize;
|
|
}
|
|
else {
|
|
state.wnext += dist;
|
|
if (state.wnext === state.wsize) { state.wnext = 0; }
|
|
if (state.whave < state.wsize) { state.whave += dist; }
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
function inflate(strm, flush) {
|
|
var state;
|
|
var input, output; // input/output buffers
|
|
var next; /* next input INDEX */
|
|
var put; /* next output INDEX */
|
|
var have, left; /* available input and output */
|
|
var hold; /* bit buffer */
|
|
var bits; /* bits in bit buffer */
|
|
var _in, _out; /* save starting available input and output */
|
|
var copy; /* number of stored or match bytes to copy */
|
|
var from; /* where to copy match bytes from */
|
|
var from_source;
|
|
var here = 0; /* current decoding table entry */
|
|
var here_bits, here_op, here_val; // paked "here" denormalized (JS specific)
|
|
//var last; /* parent table entry */
|
|
var last_bits, last_op, last_val; // paked "last" denormalized (JS specific)
|
|
var len; /* length to copy for repeats, bits to drop */
|
|
var ret; /* return code */
|
|
var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */
|
|
var opts;
|
|
|
|
var n; // temporary var for NEED_BITS
|
|
|
|
var order = /* permutation of code lengths */
|
|
[ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
|
|
|
|
|
|
if (!strm || !strm.state || !strm.output ||
|
|
(!strm.input && strm.avail_in !== 0)) {
|
|
return Z_STREAM_ERROR;
|
|
}
|
|
|
|
state = strm.state;
|
|
if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */
|
|
|
|
|
|
//--- LOAD() ---
|
|
put = strm.next_out;
|
|
output = strm.output;
|
|
left = strm.avail_out;
|
|
next = strm.next_in;
|
|
input = strm.input;
|
|
have = strm.avail_in;
|
|
hold = state.hold;
|
|
bits = state.bits;
|
|
//---
|
|
|
|
_in = have;
|
|
_out = left;
|
|
ret = Z_OK;
|
|
|
|
inf_leave: // goto emulation
|
|
for (;;) {
|
|
switch (state.mode) {
|
|
case HEAD:
|
|
if (state.wrap === 0) {
|
|
state.mode = TYPEDO;
|
|
break;
|
|
}
|
|
//=== NEEDBITS(16);
|
|
while (bits < 16) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */
|
|
state.check = 0/*crc32(0L, Z_NULL, 0)*/;
|
|
//=== CRC2(state.check, hold);
|
|
hbuf[0] = hold & 0xff;
|
|
hbuf[1] = (hold >>> 8) & 0xff;
|
|
state.check = crc32(state.check, hbuf, 2, 0);
|
|
//===//
|
|
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
state.mode = FLAGS;
|
|
break;
|
|
}
|
|
state.flags = 0; /* expect zlib header */
|
|
if (state.head) {
|
|
state.head.done = false;
|
|
}
|
|
if (!(state.wrap & 1) || /* check if zlib header allowed */
|
|
(((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
|
|
strm.msg = 'incorrect header check';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {
|
|
strm.msg = 'unknown compression method';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
//--- DROPBITS(4) ---//
|
|
hold >>>= 4;
|
|
bits -= 4;
|
|
//---//
|
|
len = (hold & 0x0f)/*BITS(4)*/ + 8;
|
|
if (state.wbits === 0) {
|
|
state.wbits = len;
|
|
}
|
|
else if (len > state.wbits) {
|
|
strm.msg = 'invalid window size';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
state.dmax = 1 << len;
|
|
//Tracev((stderr, "inflate: zlib header ok\n"));
|
|
strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
|
|
state.mode = hold & 0x200 ? DICTID : TYPE;
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
break;
|
|
case FLAGS:
|
|
//=== NEEDBITS(16); */
|
|
while (bits < 16) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
state.flags = hold;
|
|
if ((state.flags & 0xff) !== Z_DEFLATED) {
|
|
strm.msg = 'unknown compression method';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
if (state.flags & 0xe000) {
|
|
strm.msg = 'unknown header flags set';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
if (state.head) {
|
|
state.head.text = ((hold >> 8) & 1);
|
|
}
|
|
if (state.flags & 0x0200) {
|
|
//=== CRC2(state.check, hold);
|
|
hbuf[0] = hold & 0xff;
|
|
hbuf[1] = (hold >>> 8) & 0xff;
|
|
state.check = crc32(state.check, hbuf, 2, 0);
|
|
//===//
|
|
}
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
state.mode = TIME;
|
|
/* falls through */
|
|
case TIME:
|
|
//=== NEEDBITS(32); */
|
|
while (bits < 32) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
if (state.head) {
|
|
state.head.time = hold;
|
|
}
|
|
if (state.flags & 0x0200) {
|
|
//=== CRC4(state.check, hold)
|
|
hbuf[0] = hold & 0xff;
|
|
hbuf[1] = (hold >>> 8) & 0xff;
|
|
hbuf[2] = (hold >>> 16) & 0xff;
|
|
hbuf[3] = (hold >>> 24) & 0xff;
|
|
state.check = crc32(state.check, hbuf, 4, 0);
|
|
//===
|
|
}
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
state.mode = OS;
|
|
/* falls through */
|
|
case OS:
|
|
//=== NEEDBITS(16); */
|
|
while (bits < 16) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
if (state.head) {
|
|
state.head.xflags = (hold & 0xff);
|
|
state.head.os = (hold >> 8);
|
|
}
|
|
if (state.flags & 0x0200) {
|
|
//=== CRC2(state.check, hold);
|
|
hbuf[0] = hold & 0xff;
|
|
hbuf[1] = (hold >>> 8) & 0xff;
|
|
state.check = crc32(state.check, hbuf, 2, 0);
|
|
//===//
|
|
}
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
state.mode = EXLEN;
|
|
/* falls through */
|
|
case EXLEN:
|
|
if (state.flags & 0x0400) {
|
|
//=== NEEDBITS(16); */
|
|
while (bits < 16) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
state.length = hold;
|
|
if (state.head) {
|
|
state.head.extra_len = hold;
|
|
}
|
|
if (state.flags & 0x0200) {
|
|
//=== CRC2(state.check, hold);
|
|
hbuf[0] = hold & 0xff;
|
|
hbuf[1] = (hold >>> 8) & 0xff;
|
|
state.check = crc32(state.check, hbuf, 2, 0);
|
|
//===//
|
|
}
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
}
|
|
else if (state.head) {
|
|
state.head.extra = null/*Z_NULL*/;
|
|
}
|
|
state.mode = EXTRA;
|
|
/* falls through */
|
|
case EXTRA:
|
|
if (state.flags & 0x0400) {
|
|
copy = state.length;
|
|
if (copy > have) { copy = have; }
|
|
if (copy) {
|
|
if (state.head) {
|
|
len = state.head.extra_len - state.length;
|
|
if (!state.head.extra) {
|
|
// Use untyped array for more convenient processing later
|
|
state.head.extra = new Array(state.head.extra_len);
|
|
}
|
|
utils.arraySet(
|
|
state.head.extra,
|
|
input,
|
|
next,
|
|
// extra field is limited to 65536 bytes
|
|
// - no need for additional size check
|
|
copy,
|
|
/*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
|
|
len
|
|
);
|
|
//zmemcpy(state.head.extra + len, next,
|
|
// len + copy > state.head.extra_max ?
|
|
// state.head.extra_max - len : copy);
|
|
}
|
|
if (state.flags & 0x0200) {
|
|
state.check = crc32(state.check, input, copy, next);
|
|
}
|
|
have -= copy;
|
|
next += copy;
|
|
state.length -= copy;
|
|
}
|
|
if (state.length) { break inf_leave; }
|
|
}
|
|
state.length = 0;
|
|
state.mode = NAME;
|
|
/* falls through */
|
|
case NAME:
|
|
if (state.flags & 0x0800) {
|
|
if (have === 0) { break inf_leave; }
|
|
copy = 0;
|
|
do {
|
|
// TODO: 2 or 1 bytes?
|
|
len = input[next + copy++];
|
|
/* use constant limit because in js we should not preallocate memory */
|
|
if (state.head && len &&
|
|
(state.length < 65536 /*state.head.name_max*/)) {
|
|
state.head.name += String.fromCharCode(len);
|
|
}
|
|
} while (len && copy < have);
|
|
|
|
if (state.flags & 0x0200) {
|
|
state.check = crc32(state.check, input, copy, next);
|
|
}
|
|
have -= copy;
|
|
next += copy;
|
|
if (len) { break inf_leave; }
|
|
}
|
|
else if (state.head) {
|
|
state.head.name = null;
|
|
}
|
|
state.length = 0;
|
|
state.mode = COMMENT;
|
|
/* falls through */
|
|
case COMMENT:
|
|
if (state.flags & 0x1000) {
|
|
if (have === 0) { break inf_leave; }
|
|
copy = 0;
|
|
do {
|
|
len = input[next + copy++];
|
|
/* use constant limit because in js we should not preallocate memory */
|
|
if (state.head && len &&
|
|
(state.length < 65536 /*state.head.comm_max*/)) {
|
|
state.head.comment += String.fromCharCode(len);
|
|
}
|
|
} while (len && copy < have);
|
|
if (state.flags & 0x0200) {
|
|
state.check = crc32(state.check, input, copy, next);
|
|
}
|
|
have -= copy;
|
|
next += copy;
|
|
if (len) { break inf_leave; }
|
|
}
|
|
else if (state.head) {
|
|
state.head.comment = null;
|
|
}
|
|
state.mode = HCRC;
|
|
/* falls through */
|
|
case HCRC:
|
|
if (state.flags & 0x0200) {
|
|
//=== NEEDBITS(16); */
|
|
while (bits < 16) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
if (hold !== (state.check & 0xffff)) {
|
|
strm.msg = 'header crc mismatch';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
}
|
|
if (state.head) {
|
|
state.head.hcrc = ((state.flags >> 9) & 1);
|
|
state.head.done = true;
|
|
}
|
|
strm.adler = state.check = 0;
|
|
state.mode = TYPE;
|
|
break;
|
|
case DICTID:
|
|
//=== NEEDBITS(32); */
|
|
while (bits < 32) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
strm.adler = state.check = zswap32(hold);
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
state.mode = DICT;
|
|
/* falls through */
|
|
case DICT:
|
|
if (state.havedict === 0) {
|
|
//--- RESTORE() ---
|
|
strm.next_out = put;
|
|
strm.avail_out = left;
|
|
strm.next_in = next;
|
|
strm.avail_in = have;
|
|
state.hold = hold;
|
|
state.bits = bits;
|
|
//---
|
|
return Z_NEED_DICT;
|
|
}
|
|
strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
|
|
state.mode = TYPE;
|
|
/* falls through */
|
|
case TYPE:
|
|
if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; }
|
|
/* falls through */
|
|
case TYPEDO:
|
|
if (state.last) {
|
|
//--- BYTEBITS() ---//
|
|
hold >>>= bits & 7;
|
|
bits -= bits & 7;
|
|
//---//
|
|
state.mode = CHECK;
|
|
break;
|
|
}
|
|
//=== NEEDBITS(3); */
|
|
while (bits < 3) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
state.last = (hold & 0x01)/*BITS(1)*/;
|
|
//--- DROPBITS(1) ---//
|
|
hold >>>= 1;
|
|
bits -= 1;
|
|
//---//
|
|
|
|
switch ((hold & 0x03)/*BITS(2)*/) {
|
|
case 0: /* stored block */
|
|
//Tracev((stderr, "inflate: stored block%s\n",
|
|
// state.last ? " (last)" : ""));
|
|
state.mode = STORED;
|
|
break;
|
|
case 1: /* fixed block */
|
|
fixedtables(state);
|
|
//Tracev((stderr, "inflate: fixed codes block%s\n",
|
|
// state.last ? " (last)" : ""));
|
|
state.mode = LEN_; /* decode codes */
|
|
if (flush === Z_TREES) {
|
|
//--- DROPBITS(2) ---//
|
|
hold >>>= 2;
|
|
bits -= 2;
|
|
//---//
|
|
break inf_leave;
|
|
}
|
|
break;
|
|
case 2: /* dynamic block */
|
|
//Tracev((stderr, "inflate: dynamic codes block%s\n",
|
|
// state.last ? " (last)" : ""));
|
|
state.mode = TABLE;
|
|
break;
|
|
case 3:
|
|
strm.msg = 'invalid block type';
|
|
state.mode = BAD;
|
|
}
|
|
//--- DROPBITS(2) ---//
|
|
hold >>>= 2;
|
|
bits -= 2;
|
|
//---//
|
|
break;
|
|
case STORED:
|
|
//--- BYTEBITS() ---// /* go to byte boundary */
|
|
hold >>>= bits & 7;
|
|
bits -= bits & 7;
|
|
//---//
|
|
//=== NEEDBITS(32); */
|
|
while (bits < 32) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {
|
|
strm.msg = 'invalid stored block lengths';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
state.length = hold & 0xffff;
|
|
//Tracev((stderr, "inflate: stored length %u\n",
|
|
// state.length));
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
state.mode = COPY_;
|
|
if (flush === Z_TREES) { break inf_leave; }
|
|
/* falls through */
|
|
case COPY_:
|
|
state.mode = COPY;
|
|
/* falls through */
|
|
case COPY:
|
|
copy = state.length;
|
|
if (copy) {
|
|
if (copy > have) { copy = have; }
|
|
if (copy > left) { copy = left; }
|
|
if (copy === 0) { break inf_leave; }
|
|
//--- zmemcpy(put, next, copy); ---
|
|
utils.arraySet(output, input, next, copy, put);
|
|
//---//
|
|
have -= copy;
|
|
next += copy;
|
|
left -= copy;
|
|
put += copy;
|
|
state.length -= copy;
|
|
break;
|
|
}
|
|
//Tracev((stderr, "inflate: stored end\n"));
|
|
state.mode = TYPE;
|
|
break;
|
|
case TABLE:
|
|
//=== NEEDBITS(14); */
|
|
while (bits < 14) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;
|
|
//--- DROPBITS(5) ---//
|
|
hold >>>= 5;
|
|
bits -= 5;
|
|
//---//
|
|
state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
|
|
//--- DROPBITS(5) ---//
|
|
hold >>>= 5;
|
|
bits -= 5;
|
|
//---//
|
|
state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
|
|
//--- DROPBITS(4) ---//
|
|
hold >>>= 4;
|
|
bits -= 4;
|
|
//---//
|
|
//#ifndef PKZIP_BUG_WORKAROUND
|
|
if (state.nlen > 286 || state.ndist > 30) {
|
|
strm.msg = 'too many length or distance symbols';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
//#endif
|
|
//Tracev((stderr, "inflate: table sizes ok\n"));
|
|
state.have = 0;
|
|
state.mode = LENLENS;
|
|
/* falls through */
|
|
case LENLENS:
|
|
while (state.have < state.ncode) {
|
|
//=== NEEDBITS(3);
|
|
while (bits < 3) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);
|
|
//--- DROPBITS(3) ---//
|
|
hold >>>= 3;
|
|
bits -= 3;
|
|
//---//
|
|
}
|
|
while (state.have < 19) {
|
|
state.lens[order[state.have++]] = 0;
|
|
}
|
|
// We have separate tables & no pointers. 2 commented lines below not needed.
|
|
//state.next = state.codes;
|
|
//state.lencode = state.next;
|
|
// Switch to use dynamic table
|
|
state.lencode = state.lendyn;
|
|
state.lenbits = 7;
|
|
|
|
opts = { bits: state.lenbits };
|
|
ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);
|
|
state.lenbits = opts.bits;
|
|
|
|
if (ret) {
|
|
strm.msg = 'invalid code lengths set';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
//Tracev((stderr, "inflate: code lengths ok\n"));
|
|
state.have = 0;
|
|
state.mode = CODELENS;
|
|
/* falls through */
|
|
case CODELENS:
|
|
while (state.have < state.nlen + state.ndist) {
|
|
for (;;) {
|
|
here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/
|
|
here_bits = here >>> 24;
|
|
here_op = (here >>> 16) & 0xff;
|
|
here_val = here & 0xffff;
|
|
|
|
if ((here_bits) <= bits) { break; }
|
|
//--- PULLBYTE() ---//
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
//---//
|
|
}
|
|
if (here_val < 16) {
|
|
//--- DROPBITS(here.bits) ---//
|
|
hold >>>= here_bits;
|
|
bits -= here_bits;
|
|
//---//
|
|
state.lens[state.have++] = here_val;
|
|
}
|
|
else {
|
|
if (here_val === 16) {
|
|
//=== NEEDBITS(here.bits + 2);
|
|
n = here_bits + 2;
|
|
while (bits < n) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
//--- DROPBITS(here.bits) ---//
|
|
hold >>>= here_bits;
|
|
bits -= here_bits;
|
|
//---//
|
|
if (state.have === 0) {
|
|
strm.msg = 'invalid bit length repeat';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
len = state.lens[state.have - 1];
|
|
copy = 3 + (hold & 0x03);//BITS(2);
|
|
//--- DROPBITS(2) ---//
|
|
hold >>>= 2;
|
|
bits -= 2;
|
|
//---//
|
|
}
|
|
else if (here_val === 17) {
|
|
//=== NEEDBITS(here.bits + 3);
|
|
n = here_bits + 3;
|
|
while (bits < n) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
//--- DROPBITS(here.bits) ---//
|
|
hold >>>= here_bits;
|
|
bits -= here_bits;
|
|
//---//
|
|
len = 0;
|
|
copy = 3 + (hold & 0x07);//BITS(3);
|
|
//--- DROPBITS(3) ---//
|
|
hold >>>= 3;
|
|
bits -= 3;
|
|
//---//
|
|
}
|
|
else {
|
|
//=== NEEDBITS(here.bits + 7);
|
|
n = here_bits + 7;
|
|
while (bits < n) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
//--- DROPBITS(here.bits) ---//
|
|
hold >>>= here_bits;
|
|
bits -= here_bits;
|
|
//---//
|
|
len = 0;
|
|
copy = 11 + (hold & 0x7f);//BITS(7);
|
|
//--- DROPBITS(7) ---//
|
|
hold >>>= 7;
|
|
bits -= 7;
|
|
//---//
|
|
}
|
|
if (state.have + copy > state.nlen + state.ndist) {
|
|
strm.msg = 'invalid bit length repeat';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
while (copy--) {
|
|
state.lens[state.have++] = len;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* handle error breaks in while */
|
|
if (state.mode === BAD) { break; }
|
|
|
|
/* check for end-of-block code (better have one) */
|
|
if (state.lens[256] === 0) {
|
|
strm.msg = 'invalid code -- missing end-of-block';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
|
|
/* build code tables -- note: do not change the lenbits or distbits
|
|
values here (9 and 6) without reading the comments in inftrees.h
|
|
concerning the ENOUGH constants, which depend on those values */
|
|
state.lenbits = 9;
|
|
|
|
opts = { bits: state.lenbits };
|
|
ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
|
|
// We have separate tables & no pointers. 2 commented lines below not needed.
|
|
// state.next_index = opts.table_index;
|
|
state.lenbits = opts.bits;
|
|
// state.lencode = state.next;
|
|
|
|
if (ret) {
|
|
strm.msg = 'invalid literal/lengths set';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
|
|
state.distbits = 6;
|
|
//state.distcode.copy(state.codes);
|
|
// Switch to use dynamic table
|
|
state.distcode = state.distdyn;
|
|
opts = { bits: state.distbits };
|
|
ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
|
|
// We have separate tables & no pointers. 2 commented lines below not needed.
|
|
// state.next_index = opts.table_index;
|
|
state.distbits = opts.bits;
|
|
// state.distcode = state.next;
|
|
|
|
if (ret) {
|
|
strm.msg = 'invalid distances set';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
//Tracev((stderr, 'inflate: codes ok\n'));
|
|
state.mode = LEN_;
|
|
if (flush === Z_TREES) { break inf_leave; }
|
|
/* falls through */
|
|
case LEN_:
|
|
state.mode = LEN;
|
|
/* falls through */
|
|
case LEN:
|
|
if (have >= 6 && left >= 258) {
|
|
//--- RESTORE() ---
|
|
strm.next_out = put;
|
|
strm.avail_out = left;
|
|
strm.next_in = next;
|
|
strm.avail_in = have;
|
|
state.hold = hold;
|
|
state.bits = bits;
|
|
//---
|
|
inflate_fast(strm, _out);
|
|
//--- LOAD() ---
|
|
put = strm.next_out;
|
|
output = strm.output;
|
|
left = strm.avail_out;
|
|
next = strm.next_in;
|
|
input = strm.input;
|
|
have = strm.avail_in;
|
|
hold = state.hold;
|
|
bits = state.bits;
|
|
//---
|
|
|
|
if (state.mode === TYPE) {
|
|
state.back = -1;
|
|
}
|
|
break;
|
|
}
|
|
state.back = 0;
|
|
for (;;) {
|
|
here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/
|
|
here_bits = here >>> 24;
|
|
here_op = (here >>> 16) & 0xff;
|
|
here_val = here & 0xffff;
|
|
|
|
if (here_bits <= bits) { break; }
|
|
//--- PULLBYTE() ---//
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
//---//
|
|
}
|
|
if (here_op && (here_op & 0xf0) === 0) {
|
|
last_bits = here_bits;
|
|
last_op = here_op;
|
|
last_val = here_val;
|
|
for (;;) {
|
|
here = state.lencode[last_val +
|
|
((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
|
|
here_bits = here >>> 24;
|
|
here_op = (here >>> 16) & 0xff;
|
|
here_val = here & 0xffff;
|
|
|
|
if ((last_bits + here_bits) <= bits) { break; }
|
|
//--- PULLBYTE() ---//
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
//---//
|
|
}
|
|
//--- DROPBITS(last.bits) ---//
|
|
hold >>>= last_bits;
|
|
bits -= last_bits;
|
|
//---//
|
|
state.back += last_bits;
|
|
}
|
|
//--- DROPBITS(here.bits) ---//
|
|
hold >>>= here_bits;
|
|
bits -= here_bits;
|
|
//---//
|
|
state.back += here_bits;
|
|
state.length = here_val;
|
|
if (here_op === 0) {
|
|
//Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
|
// "inflate: literal '%c'\n" :
|
|
// "inflate: literal 0x%02x\n", here.val));
|
|
state.mode = LIT;
|
|
break;
|
|
}
|
|
if (here_op & 32) {
|
|
//Tracevv((stderr, "inflate: end of block\n"));
|
|
state.back = -1;
|
|
state.mode = TYPE;
|
|
break;
|
|
}
|
|
if (here_op & 64) {
|
|
strm.msg = 'invalid literal/length code';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
state.extra = here_op & 15;
|
|
state.mode = LENEXT;
|
|
/* falls through */
|
|
case LENEXT:
|
|
if (state.extra) {
|
|
//=== NEEDBITS(state.extra);
|
|
n = state.extra;
|
|
while (bits < n) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
|
|
//--- DROPBITS(state.extra) ---//
|
|
hold >>>= state.extra;
|
|
bits -= state.extra;
|
|
//---//
|
|
state.back += state.extra;
|
|
}
|
|
//Tracevv((stderr, "inflate: length %u\n", state.length));
|
|
state.was = state.length;
|
|
state.mode = DIST;
|
|
/* falls through */
|
|
case DIST:
|
|
for (;;) {
|
|
here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/
|
|
here_bits = here >>> 24;
|
|
here_op = (here >>> 16) & 0xff;
|
|
here_val = here & 0xffff;
|
|
|
|
if ((here_bits) <= bits) { break; }
|
|
//--- PULLBYTE() ---//
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
//---//
|
|
}
|
|
if ((here_op & 0xf0) === 0) {
|
|
last_bits = here_bits;
|
|
last_op = here_op;
|
|
last_val = here_val;
|
|
for (;;) {
|
|
here = state.distcode[last_val +
|
|
((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
|
|
here_bits = here >>> 24;
|
|
here_op = (here >>> 16) & 0xff;
|
|
here_val = here & 0xffff;
|
|
|
|
if ((last_bits + here_bits) <= bits) { break; }
|
|
//--- PULLBYTE() ---//
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
//---//
|
|
}
|
|
//--- DROPBITS(last.bits) ---//
|
|
hold >>>= last_bits;
|
|
bits -= last_bits;
|
|
//---//
|
|
state.back += last_bits;
|
|
}
|
|
//--- DROPBITS(here.bits) ---//
|
|
hold >>>= here_bits;
|
|
bits -= here_bits;
|
|
//---//
|
|
state.back += here_bits;
|
|
if (here_op & 64) {
|
|
strm.msg = 'invalid distance code';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
state.offset = here_val;
|
|
state.extra = (here_op) & 15;
|
|
state.mode = DISTEXT;
|
|
/* falls through */
|
|
case DISTEXT:
|
|
if (state.extra) {
|
|
//=== NEEDBITS(state.extra);
|
|
n = state.extra;
|
|
while (bits < n) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
|
|
//--- DROPBITS(state.extra) ---//
|
|
hold >>>= state.extra;
|
|
bits -= state.extra;
|
|
//---//
|
|
state.back += state.extra;
|
|
}
|
|
//#ifdef INFLATE_STRICT
|
|
if (state.offset > state.dmax) {
|
|
strm.msg = 'invalid distance too far back';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
//#endif
|
|
//Tracevv((stderr, "inflate: distance %u\n", state.offset));
|
|
state.mode = MATCH;
|
|
/* falls through */
|
|
case MATCH:
|
|
if (left === 0) { break inf_leave; }
|
|
copy = _out - left;
|
|
if (state.offset > copy) { /* copy from window */
|
|
copy = state.offset - copy;
|
|
if (copy > state.whave) {
|
|
if (state.sane) {
|
|
strm.msg = 'invalid distance too far back';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
// (!) This block is disabled in zlib defaults,
|
|
// don't enable it for binary compatibility
|
|
//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
|
// Trace((stderr, "inflate.c too far\n"));
|
|
// copy -= state.whave;
|
|
// if (copy > state.length) { copy = state.length; }
|
|
// if (copy > left) { copy = left; }
|
|
// left -= copy;
|
|
// state.length -= copy;
|
|
// do {
|
|
// output[put++] = 0;
|
|
// } while (--copy);
|
|
// if (state.length === 0) { state.mode = LEN; }
|
|
// break;
|
|
//#endif
|
|
}
|
|
if (copy > state.wnext) {
|
|
copy -= state.wnext;
|
|
from = state.wsize - copy;
|
|
}
|
|
else {
|
|
from = state.wnext - copy;
|
|
}
|
|
if (copy > state.length) { copy = state.length; }
|
|
from_source = state.window;
|
|
}
|
|
else { /* copy from output */
|
|
from_source = output;
|
|
from = put - state.offset;
|
|
copy = state.length;
|
|
}
|
|
if (copy > left) { copy = left; }
|
|
left -= copy;
|
|
state.length -= copy;
|
|
do {
|
|
output[put++] = from_source[from++];
|
|
} while (--copy);
|
|
if (state.length === 0) { state.mode = LEN; }
|
|
break;
|
|
case LIT:
|
|
if (left === 0) { break inf_leave; }
|
|
output[put++] = state.length;
|
|
left--;
|
|
state.mode = LEN;
|
|
break;
|
|
case CHECK:
|
|
if (state.wrap) {
|
|
//=== NEEDBITS(32);
|
|
while (bits < 32) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
// Use '|' instead of '+' to make sure that result is signed
|
|
hold |= input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
_out -= left;
|
|
strm.total_out += _out;
|
|
state.total += _out;
|
|
if (_out) {
|
|
strm.adler = state.check =
|
|
/*UPDATE(state.check, put - _out, _out);*/
|
|
(state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out));
|
|
|
|
}
|
|
_out = left;
|
|
// NB: crc32 stored as signed 32-bit int, zswap32 returns signed too
|
|
if ((state.flags ? hold : zswap32(hold)) !== state.check) {
|
|
strm.msg = 'incorrect data check';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
//Tracev((stderr, "inflate: check matches trailer\n"));
|
|
}
|
|
state.mode = LENGTH;
|
|
/* falls through */
|
|
case LENGTH:
|
|
if (state.wrap && state.flags) {
|
|
//=== NEEDBITS(32);
|
|
while (bits < 32) {
|
|
if (have === 0) { break inf_leave; }
|
|
have--;
|
|
hold += input[next++] << bits;
|
|
bits += 8;
|
|
}
|
|
//===//
|
|
if (hold !== (state.total & 0xffffffff)) {
|
|
strm.msg = 'incorrect length check';
|
|
state.mode = BAD;
|
|
break;
|
|
}
|
|
//=== INITBITS();
|
|
hold = 0;
|
|
bits = 0;
|
|
//===//
|
|
//Tracev((stderr, "inflate: length matches trailer\n"));
|
|
}
|
|
state.mode = DONE;
|
|
/* falls through */
|
|
case DONE:
|
|
ret = Z_STREAM_END;
|
|
break inf_leave;
|
|
case BAD:
|
|
ret = Z_DATA_ERROR;
|
|
break inf_leave;
|
|
case MEM:
|
|
return Z_MEM_ERROR;
|
|
case SYNC:
|
|
/* falls through */
|
|
default:
|
|
return Z_STREAM_ERROR;
|
|
}
|
|
}
|
|
|
|
// inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave"
|
|
|
|
/*
|
|
Return from inflate(), updating the total counts and the check value.
|
|
If there was no progress during the inflate() call, return a buffer
|
|
error. Call updatewindow() to create and/or update the window state.
|
|
Note: a memory error from inflate() is non-recoverable.
|
|
*/
|
|
|
|
//--- RESTORE() ---
|
|
strm.next_out = put;
|
|
strm.avail_out = left;
|
|
strm.next_in = next;
|
|
strm.avail_in = have;
|
|
state.hold = hold;
|
|
state.bits = bits;
|
|
//---
|
|
|
|
if (state.wsize || (_out !== strm.avail_out && state.mode < BAD &&
|
|
(state.mode < CHECK || flush !== Z_FINISH))) {
|
|
if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) {
|
|
state.mode = MEM;
|
|
return Z_MEM_ERROR;
|
|
}
|
|
}
|
|
_in -= strm.avail_in;
|
|
_out -= strm.avail_out;
|
|
strm.total_in += _in;
|
|
strm.total_out += _out;
|
|
state.total += _out;
|
|
if (state.wrap && _out) {
|
|
strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/
|
|
(state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out));
|
|
}
|
|
strm.data_type = state.bits + (state.last ? 64 : 0) +
|
|
(state.mode === TYPE ? 128 : 0) +
|
|
(state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);
|
|
if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) {
|
|
ret = Z_BUF_ERROR;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
function inflateEnd(strm) {
|
|
|
|
if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) {
|
|
return Z_STREAM_ERROR;
|
|
}
|
|
|
|
var state = strm.state;
|
|
if (state.window) {
|
|
state.window = null;
|
|
}
|
|
strm.state = null;
|
|
return Z_OK;
|
|
}
|
|
|
|
function inflateGetHeader(strm, head) {
|
|
var state;
|
|
|
|
/* check state */
|
|
if (!strm || !strm.state) { return Z_STREAM_ERROR; }
|
|
state = strm.state;
|
|
if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; }
|
|
|
|
/* save header structure */
|
|
state.head = head;
|
|
head.done = false;
|
|
return Z_OK;
|
|
}
|
|
|
|
function inflateSetDictionary(strm, dictionary) {
|
|
var dictLength = dictionary.length;
|
|
|
|
var state;
|
|
var dictid;
|
|
var ret;
|
|
|
|
/* check state */
|
|
if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; }
|
|
state = strm.state;
|
|
|
|
if (state.wrap !== 0 && state.mode !== DICT) {
|
|
return Z_STREAM_ERROR;
|
|
}
|
|
|
|
/* check for correct dictionary identifier */
|
|
if (state.mode === DICT) {
|
|
dictid = 1; /* adler32(0, null, 0)*/
|
|
/* dictid = adler32(dictid, dictionary, dictLength); */
|
|
dictid = adler32(dictid, dictionary, dictLength, 0);
|
|
if (dictid !== state.check) {
|
|
return Z_DATA_ERROR;
|
|
}
|
|
}
|
|
/* copy dictionary to window using updatewindow(), which will amend the
|
|
existing dictionary if appropriate */
|
|
ret = updatewindow(strm, dictionary, dictLength, dictLength);
|
|
if (ret) {
|
|
state.mode = MEM;
|
|
return Z_MEM_ERROR;
|
|
}
|
|
state.havedict = 1;
|
|
// Tracev((stderr, "inflate: dictionary set\n"));
|
|
return Z_OK;
|
|
}
|
|
|
|
exports.inflateReset = inflateReset;
|
|
exports.inflateReset2 = inflateReset2;
|
|
exports.inflateResetKeep = inflateResetKeep;
|
|
exports.inflateInit = inflateInit;
|
|
exports.inflateInit2 = inflateInit2;
|
|
exports.inflate = inflate;
|
|
exports.inflateEnd = inflateEnd;
|
|
exports.inflateGetHeader = inflateGetHeader;
|
|
exports.inflateSetDictionary = inflateSetDictionary;
|
|
exports.inflateInfo = 'pako inflate (from Nodeca project)';
|
|
|
|
/* Not implemented
|
|
exports.inflateCopy = inflateCopy;
|
|
exports.inflateGetDictionary = inflateGetDictionary;
|
|
exports.inflateMark = inflateMark;
|
|
exports.inflatePrime = inflatePrime;
|
|
exports.inflateSync = inflateSync;
|
|
exports.inflateSyncPoint = inflateSyncPoint;
|
|
exports.inflateUndermine = inflateUndermine;
|
|
*/
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/inftrees.js":
|
|
/*!*****************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/zlib/inftrees.js ***!
|
|
\*****************************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
var utils = __webpack_require__(/*! ../utils/common */ "./node_modules/browserify-zlib/node_modules/pako/lib/utils/common.js");
|
|
|
|
var MAXBITS = 15;
|
|
var ENOUGH_LENS = 852;
|
|
var ENOUGH_DISTS = 592;
|
|
//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
|
|
|
|
var CODES = 0;
|
|
var LENS = 1;
|
|
var DISTS = 2;
|
|
|
|
var lbase = [ /* Length codes 257..285 base */
|
|
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
|
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
|
|
];
|
|
|
|
var lext = [ /* Length codes 257..285 extra */
|
|
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
|
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
|
|
];
|
|
|
|
var dbase = [ /* Distance codes 0..29 base */
|
|
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
|
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
|
8193, 12289, 16385, 24577, 0, 0
|
|
];
|
|
|
|
var dext = [ /* Distance codes 0..29 extra */
|
|
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
|
|
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
|
|
28, 28, 29, 29, 64, 64
|
|
];
|
|
|
|
module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts)
|
|
{
|
|
var bits = opts.bits;
|
|
//here = opts.here; /* table entry for duplication */
|
|
|
|
var len = 0; /* a code's length in bits */
|
|
var sym = 0; /* index of code symbols */
|
|
var min = 0, max = 0; /* minimum and maximum code lengths */
|
|
var root = 0; /* number of index bits for root table */
|
|
var curr = 0; /* number of index bits for current table */
|
|
var drop = 0; /* code bits to drop for sub-table */
|
|
var left = 0; /* number of prefix codes available */
|
|
var used = 0; /* code entries in table used */
|
|
var huff = 0; /* Huffman code */
|
|
var incr; /* for incrementing code, index */
|
|
var fill; /* index for replicating entries */
|
|
var low; /* low bits for current root entry */
|
|
var mask; /* mask for low root bits */
|
|
var next; /* next available space in table */
|
|
var base = null; /* base value table to use */
|
|
var base_index = 0;
|
|
// var shoextra; /* extra bits table to use */
|
|
var end; /* use base and extra for symbol > end */
|
|
var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */
|
|
var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */
|
|
var extra = null;
|
|
var extra_index = 0;
|
|
|
|
var here_bits, here_op, here_val;
|
|
|
|
/*
|
|
Process a set of code lengths to create a canonical Huffman code. The
|
|
code lengths are lens[0..codes-1]. Each length corresponds to the
|
|
symbols 0..codes-1. The Huffman code is generated by first sorting the
|
|
symbols by length from short to long, and retaining the symbol order
|
|
for codes with equal lengths. Then the code starts with all zero bits
|
|
for the first code of the shortest length, and the codes are integer
|
|
increments for the same length, and zeros are appended as the length
|
|
increases. For the deflate format, these bits are stored backwards
|
|
from their more natural integer increment ordering, and so when the
|
|
decoding tables are built in the large loop below, the integer codes
|
|
are incremented backwards.
|
|
|
|
This routine assumes, but does not check, that all of the entries in
|
|
lens[] are in the range 0..MAXBITS. The caller must assure this.
|
|
1..MAXBITS is interpreted as that code length. zero means that that
|
|
symbol does not occur in this code.
|
|
|
|
The codes are sorted by computing a count of codes for each length,
|
|
creating from that a table of starting indices for each length in the
|
|
sorted table, and then entering the symbols in order in the sorted
|
|
table. The sorted table is work[], with that space being provided by
|
|
the caller.
|
|
|
|
The length counts are used for other purposes as well, i.e. finding
|
|
the minimum and maximum length codes, determining if there are any
|
|
codes at all, checking for a valid set of lengths, and looking ahead
|
|
at length counts to determine sub-table sizes when building the
|
|
decoding tables.
|
|
*/
|
|
|
|
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
|
|
for (len = 0; len <= MAXBITS; len++) {
|
|
count[len] = 0;
|
|
}
|
|
for (sym = 0; sym < codes; sym++) {
|
|
count[lens[lens_index + sym]]++;
|
|
}
|
|
|
|
/* bound code lengths, force root to be within code lengths */
|
|
root = bits;
|
|
for (max = MAXBITS; max >= 1; max--) {
|
|
if (count[max] !== 0) { break; }
|
|
}
|
|
if (root > max) {
|
|
root = max;
|
|
}
|
|
if (max === 0) { /* no symbols to code at all */
|
|
//table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */
|
|
//table.bits[opts.table_index] = 1; //here.bits = (var char)1;
|
|
//table.val[opts.table_index++] = 0; //here.val = (var short)0;
|
|
table[table_index++] = (1 << 24) | (64 << 16) | 0;
|
|
|
|
|
|
//table.op[opts.table_index] = 64;
|
|
//table.bits[opts.table_index] = 1;
|
|
//table.val[opts.table_index++] = 0;
|
|
table[table_index++] = (1 << 24) | (64 << 16) | 0;
|
|
|
|
opts.bits = 1;
|
|
return 0; /* no symbols, but wait for decoding to report error */
|
|
}
|
|
for (min = 1; min < max; min++) {
|
|
if (count[min] !== 0) { break; }
|
|
}
|
|
if (root < min) {
|
|
root = min;
|
|
}
|
|
|
|
/* check for an over-subscribed or incomplete set of lengths */
|
|
left = 1;
|
|
for (len = 1; len <= MAXBITS; len++) {
|
|
left <<= 1;
|
|
left -= count[len];
|
|
if (left < 0) {
|
|
return -1;
|
|
} /* over-subscribed */
|
|
}
|
|
if (left > 0 && (type === CODES || max !== 1)) {
|
|
return -1; /* incomplete set */
|
|
}
|
|
|
|
/* generate offsets into symbol table for each length for sorting */
|
|
offs[1] = 0;
|
|
for (len = 1; len < MAXBITS; len++) {
|
|
offs[len + 1] = offs[len] + count[len];
|
|
}
|
|
|
|
/* sort symbols by length, by symbol order within each length */
|
|
for (sym = 0; sym < codes; sym++) {
|
|
if (lens[lens_index + sym] !== 0) {
|
|
work[offs[lens[lens_index + sym]]++] = sym;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Create and fill in decoding tables. In this loop, the table being
|
|
filled is at next and has curr index bits. The code being used is huff
|
|
with length len. That code is converted to an index by dropping drop
|
|
bits off of the bottom. For codes where len is less than drop + curr,
|
|
those top drop + curr - len bits are incremented through all values to
|
|
fill the table with replicated entries.
|
|
|
|
root is the number of index bits for the root table. When len exceeds
|
|
root, sub-tables are created pointed to by the root entry with an index
|
|
of the low root bits of huff. This is saved in low to check for when a
|
|
new sub-table should be started. drop is zero when the root table is
|
|
being filled, and drop is root when sub-tables are being filled.
|
|
|
|
When a new sub-table is needed, it is necessary to look ahead in the
|
|
code lengths to determine what size sub-table is needed. The length
|
|
counts are used for this, and so count[] is decremented as codes are
|
|
entered in the tables.
|
|
|
|
used keeps track of how many table entries have been allocated from the
|
|
provided *table space. It is checked for LENS and DIST tables against
|
|
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
|
|
the initial root table size constants. See the comments in inftrees.h
|
|
for more information.
|
|
|
|
sym increments through all symbols, and the loop terminates when
|
|
all codes of length max, i.e. all codes, have been processed. This
|
|
routine permits incomplete codes, so another loop after this one fills
|
|
in the rest of the decoding tables with invalid code markers.
|
|
*/
|
|
|
|
/* set up for code type */
|
|
// poor man optimization - use if-else instead of switch,
|
|
// to avoid deopts in old v8
|
|
if (type === CODES) {
|
|
base = extra = work; /* dummy value--not used */
|
|
end = 19;
|
|
|
|
} else if (type === LENS) {
|
|
base = lbase;
|
|
base_index -= 257;
|
|
extra = lext;
|
|
extra_index -= 257;
|
|
end = 256;
|
|
|
|
} else { /* DISTS */
|
|
base = dbase;
|
|
extra = dext;
|
|
end = -1;
|
|
}
|
|
|
|
/* initialize opts for loop */
|
|
huff = 0; /* starting code */
|
|
sym = 0; /* starting code symbol */
|
|
len = min; /* starting code length */
|
|
next = table_index; /* current table to fill in */
|
|
curr = root; /* current table index bits */
|
|
drop = 0; /* current bits to drop from code for index */
|
|
low = -1; /* trigger new sub-table when len > root */
|
|
used = 1 << root; /* use root table entries */
|
|
mask = used - 1; /* mask for comparing low */
|
|
|
|
/* check available table space */
|
|
if ((type === LENS && used > ENOUGH_LENS) ||
|
|
(type === DISTS && used > ENOUGH_DISTS)) {
|
|
return 1;
|
|
}
|
|
|
|
/* process all codes and make table entries */
|
|
for (;;) {
|
|
/* create table entry */
|
|
here_bits = len - drop;
|
|
if (work[sym] < end) {
|
|
here_op = 0;
|
|
here_val = work[sym];
|
|
}
|
|
else if (work[sym] > end) {
|
|
here_op = extra[extra_index + work[sym]];
|
|
here_val = base[base_index + work[sym]];
|
|
}
|
|
else {
|
|
here_op = 32 + 64; /* end of block */
|
|
here_val = 0;
|
|
}
|
|
|
|
/* replicate for those indices with low len bits equal to huff */
|
|
incr = 1 << (len - drop);
|
|
fill = 1 << curr;
|
|
min = fill; /* save offset to next table */
|
|
do {
|
|
fill -= incr;
|
|
table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;
|
|
} while (fill !== 0);
|
|
|
|
/* backwards increment the len-bit code huff */
|
|
incr = 1 << (len - 1);
|
|
while (huff & incr) {
|
|
incr >>= 1;
|
|
}
|
|
if (incr !== 0) {
|
|
huff &= incr - 1;
|
|
huff += incr;
|
|
} else {
|
|
huff = 0;
|
|
}
|
|
|
|
/* go to next symbol, update count, len */
|
|
sym++;
|
|
if (--count[len] === 0) {
|
|
if (len === max) { break; }
|
|
len = lens[lens_index + work[sym]];
|
|
}
|
|
|
|
/* create new sub-table if needed */
|
|
if (len > root && (huff & mask) !== low) {
|
|
/* if first time, transition to sub-tables */
|
|
if (drop === 0) {
|
|
drop = root;
|
|
}
|
|
|
|
/* increment past last table */
|
|
next += min; /* here min is 1 << curr */
|
|
|
|
/* determine length of next table */
|
|
curr = len - drop;
|
|
left = 1 << curr;
|
|
while (curr + drop < max) {
|
|
left -= count[curr + drop];
|
|
if (left <= 0) { break; }
|
|
curr++;
|
|
left <<= 1;
|
|
}
|
|
|
|
/* check for enough space */
|
|
used += 1 << curr;
|
|
if ((type === LENS && used > ENOUGH_LENS) ||
|
|
(type === DISTS && used > ENOUGH_DISTS)) {
|
|
return 1;
|
|
}
|
|
|
|
/* point entry in root table to sub-table */
|
|
low = huff & mask;
|
|
/*table.op[low] = curr;
|
|
table.bits[low] = root;
|
|
table.val[low] = next - opts.table_index;*/
|
|
table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;
|
|
}
|
|
}
|
|
|
|
/* fill in remaining table entry if code is incomplete (guaranteed to have
|
|
at most one remaining entry, since if the code is incomplete, the
|
|
maximum code length that was allowed to get this far is one bit) */
|
|
if (huff !== 0) {
|
|
//table.op[next + huff] = 64; /* invalid code marker */
|
|
//table.bits[next + huff] = len - drop;
|
|
//table.val[next + huff] = 0;
|
|
table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;
|
|
}
|
|
|
|
/* set return parameters */
|
|
//opts.table_index += used;
|
|
opts.bits = root;
|
|
return 0;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/messages.js":
|
|
/*!*****************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/zlib/messages.js ***!
|
|
\*****************************************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
module.exports = {
|
|
2: 'need dictionary', /* Z_NEED_DICT 2 */
|
|
1: 'stream end', /* Z_STREAM_END 1 */
|
|
0: '', /* Z_OK 0 */
|
|
'-1': 'file error', /* Z_ERRNO (-1) */
|
|
'-2': 'stream error', /* Z_STREAM_ERROR (-2) */
|
|
'-3': 'data error', /* Z_DATA_ERROR (-3) */
|
|
'-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */
|
|
'-5': 'buffer error', /* Z_BUF_ERROR (-5) */
|
|
'-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/trees.js":
|
|
/*!**************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/zlib/trees.js ***!
|
|
\**************************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
/* eslint-disable space-unary-ops */
|
|
|
|
var utils = __webpack_require__(/*! ../utils/common */ "./node_modules/browserify-zlib/node_modules/pako/lib/utils/common.js");
|
|
|
|
/* Public constants ==========================================================*/
|
|
/* ===========================================================================*/
|
|
|
|
|
|
//var Z_FILTERED = 1;
|
|
//var Z_HUFFMAN_ONLY = 2;
|
|
//var Z_RLE = 3;
|
|
var Z_FIXED = 4;
|
|
//var Z_DEFAULT_STRATEGY = 0;
|
|
|
|
/* Possible values of the data_type field (though see inflate()) */
|
|
var Z_BINARY = 0;
|
|
var Z_TEXT = 1;
|
|
//var Z_ASCII = 1; // = Z_TEXT
|
|
var Z_UNKNOWN = 2;
|
|
|
|
/*============================================================================*/
|
|
|
|
|
|
function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }
|
|
|
|
// From zutil.h
|
|
|
|
var STORED_BLOCK = 0;
|
|
var STATIC_TREES = 1;
|
|
var DYN_TREES = 2;
|
|
/* The three kinds of block type */
|
|
|
|
var MIN_MATCH = 3;
|
|
var MAX_MATCH = 258;
|
|
/* The minimum and maximum match lengths */
|
|
|
|
// From deflate.h
|
|
/* ===========================================================================
|
|
* Internal compression state.
|
|
*/
|
|
|
|
var LENGTH_CODES = 29;
|
|
/* number of length codes, not counting the special END_BLOCK code */
|
|
|
|
var LITERALS = 256;
|
|
/* number of literal bytes 0..255 */
|
|
|
|
var L_CODES = LITERALS + 1 + LENGTH_CODES;
|
|
/* number of Literal or Length codes, including the END_BLOCK code */
|
|
|
|
var D_CODES = 30;
|
|
/* number of distance codes */
|
|
|
|
var BL_CODES = 19;
|
|
/* number of codes used to transfer the bit lengths */
|
|
|
|
var HEAP_SIZE = 2 * L_CODES + 1;
|
|
/* maximum heap size */
|
|
|
|
var MAX_BITS = 15;
|
|
/* All codes must not exceed MAX_BITS bits */
|
|
|
|
var Buf_size = 16;
|
|
/* size of bit buffer in bi_buf */
|
|
|
|
|
|
/* ===========================================================================
|
|
* Constants
|
|
*/
|
|
|
|
var MAX_BL_BITS = 7;
|
|
/* Bit length codes must not exceed MAX_BL_BITS bits */
|
|
|
|
var END_BLOCK = 256;
|
|
/* end of block literal code */
|
|
|
|
var REP_3_6 = 16;
|
|
/* repeat previous bit length 3-6 times (2 bits of repeat count) */
|
|
|
|
var REPZ_3_10 = 17;
|
|
/* repeat a zero length 3-10 times (3 bits of repeat count) */
|
|
|
|
var REPZ_11_138 = 18;
|
|
/* repeat a zero length 11-138 times (7 bits of repeat count) */
|
|
|
|
/* eslint-disable comma-spacing,array-bracket-spacing */
|
|
var extra_lbits = /* extra bits for each length code */
|
|
[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0];
|
|
|
|
var extra_dbits = /* extra bits for each distance code */
|
|
[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];
|
|
|
|
var extra_blbits = /* extra bits for each bit length code */
|
|
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7];
|
|
|
|
var bl_order =
|
|
[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];
|
|
/* eslint-enable comma-spacing,array-bracket-spacing */
|
|
|
|
/* The lengths of the bit length codes are sent in order of decreasing
|
|
* probability, to avoid transmitting the lengths for unused bit length codes.
|
|
*/
|
|
|
|
/* ===========================================================================
|
|
* Local data. These are initialized only once.
|
|
*/
|
|
|
|
// We pre-fill arrays with 0 to avoid uninitialized gaps
|
|
|
|
var DIST_CODE_LEN = 512; /* see definition of array dist_code below */
|
|
|
|
// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1
|
|
var static_ltree = new Array((L_CODES + 2) * 2);
|
|
zero(static_ltree);
|
|
/* The static literal tree. Since the bit lengths are imposed, there is no
|
|
* need for the L_CODES extra codes used during heap construction. However
|
|
* The codes 286 and 287 are needed to build a canonical tree (see _tr_init
|
|
* below).
|
|
*/
|
|
|
|
var static_dtree = new Array(D_CODES * 2);
|
|
zero(static_dtree);
|
|
/* The static distance tree. (Actually a trivial tree since all codes use
|
|
* 5 bits.)
|
|
*/
|
|
|
|
var _dist_code = new Array(DIST_CODE_LEN);
|
|
zero(_dist_code);
|
|
/* Distance codes. The first 256 values correspond to the distances
|
|
* 3 .. 258, the last 256 values correspond to the top 8 bits of
|
|
* the 15 bit distances.
|
|
*/
|
|
|
|
var _length_code = new Array(MAX_MATCH - MIN_MATCH + 1);
|
|
zero(_length_code);
|
|
/* length code for each normalized match length (0 == MIN_MATCH) */
|
|
|
|
var base_length = new Array(LENGTH_CODES);
|
|
zero(base_length);
|
|
/* First normalized length for each code (0 = MIN_MATCH) */
|
|
|
|
var base_dist = new Array(D_CODES);
|
|
zero(base_dist);
|
|
/* First normalized distance for each code (0 = distance of 1) */
|
|
|
|
|
|
function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {
|
|
|
|
this.static_tree = static_tree; /* static tree or NULL */
|
|
this.extra_bits = extra_bits; /* extra bits for each code or NULL */
|
|
this.extra_base = extra_base; /* base index for extra_bits */
|
|
this.elems = elems; /* max number of elements in the tree */
|
|
this.max_length = max_length; /* max bit length for the codes */
|
|
|
|
// show if `static_tree` has data or dummy - needed for monomorphic objects
|
|
this.has_stree = static_tree && static_tree.length;
|
|
}
|
|
|
|
|
|
var static_l_desc;
|
|
var static_d_desc;
|
|
var static_bl_desc;
|
|
|
|
|
|
function TreeDesc(dyn_tree, stat_desc) {
|
|
this.dyn_tree = dyn_tree; /* the dynamic tree */
|
|
this.max_code = 0; /* largest code with non zero frequency */
|
|
this.stat_desc = stat_desc; /* the corresponding static tree */
|
|
}
|
|
|
|
|
|
|
|
function d_code(dist) {
|
|
return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Output a short LSB first on the stream.
|
|
* IN assertion: there is enough room in pendingBuf.
|
|
*/
|
|
function put_short(s, w) {
|
|
// put_byte(s, (uch)((w) & 0xff));
|
|
// put_byte(s, (uch)((ush)(w) >> 8));
|
|
s.pending_buf[s.pending++] = (w) & 0xff;
|
|
s.pending_buf[s.pending++] = (w >>> 8) & 0xff;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Send a value on a given number of bits.
|
|
* IN assertion: length <= 16 and value fits in length bits.
|
|
*/
|
|
function send_bits(s, value, length) {
|
|
if (s.bi_valid > (Buf_size - length)) {
|
|
s.bi_buf |= (value << s.bi_valid) & 0xffff;
|
|
put_short(s, s.bi_buf);
|
|
s.bi_buf = value >> (Buf_size - s.bi_valid);
|
|
s.bi_valid += length - Buf_size;
|
|
} else {
|
|
s.bi_buf |= (value << s.bi_valid) & 0xffff;
|
|
s.bi_valid += length;
|
|
}
|
|
}
|
|
|
|
|
|
function send_code(s, c, tree) {
|
|
send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/);
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Reverse the first len bits of a code, using straightforward code (a faster
|
|
* method would use a table)
|
|
* IN assertion: 1 <= len <= 15
|
|
*/
|
|
function bi_reverse(code, len) {
|
|
var res = 0;
|
|
do {
|
|
res |= code & 1;
|
|
code >>>= 1;
|
|
res <<= 1;
|
|
} while (--len > 0);
|
|
return res >>> 1;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Flush the bit buffer, keeping at most 7 bits in it.
|
|
*/
|
|
function bi_flush(s) {
|
|
if (s.bi_valid === 16) {
|
|
put_short(s, s.bi_buf);
|
|
s.bi_buf = 0;
|
|
s.bi_valid = 0;
|
|
|
|
} else if (s.bi_valid >= 8) {
|
|
s.pending_buf[s.pending++] = s.bi_buf & 0xff;
|
|
s.bi_buf >>= 8;
|
|
s.bi_valid -= 8;
|
|
}
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Compute the optimal bit lengths for a tree and update the total bit length
|
|
* for the current block.
|
|
* IN assertion: the fields freq and dad are set, heap[heap_max] and
|
|
* above are the tree nodes sorted by increasing frequency.
|
|
* OUT assertions: the field len is set to the optimal bit length, the
|
|
* array bl_count contains the frequencies for each bit length.
|
|
* The length opt_len is updated; static_len is also updated if stree is
|
|
* not null.
|
|
*/
|
|
function gen_bitlen(s, desc)
|
|
// deflate_state *s;
|
|
// tree_desc *desc; /* the tree descriptor */
|
|
{
|
|
var tree = desc.dyn_tree;
|
|
var max_code = desc.max_code;
|
|
var stree = desc.stat_desc.static_tree;
|
|
var has_stree = desc.stat_desc.has_stree;
|
|
var extra = desc.stat_desc.extra_bits;
|
|
var base = desc.stat_desc.extra_base;
|
|
var max_length = desc.stat_desc.max_length;
|
|
var h; /* heap index */
|
|
var n, m; /* iterate over the tree elements */
|
|
var bits; /* bit length */
|
|
var xbits; /* extra bits */
|
|
var f; /* frequency */
|
|
var overflow = 0; /* number of elements with bit length too large */
|
|
|
|
for (bits = 0; bits <= MAX_BITS; bits++) {
|
|
s.bl_count[bits] = 0;
|
|
}
|
|
|
|
/* In a first pass, compute the optimal bit lengths (which may
|
|
* overflow in the case of the bit length tree).
|
|
*/
|
|
tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */
|
|
|
|
for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
|
|
n = s.heap[h];
|
|
bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;
|
|
if (bits > max_length) {
|
|
bits = max_length;
|
|
overflow++;
|
|
}
|
|
tree[n * 2 + 1]/*.Len*/ = bits;
|
|
/* We overwrite tree[n].Dad which is no longer needed */
|
|
|
|
if (n > max_code) { continue; } /* not a leaf node */
|
|
|
|
s.bl_count[bits]++;
|
|
xbits = 0;
|
|
if (n >= base) {
|
|
xbits = extra[n - base];
|
|
}
|
|
f = tree[n * 2]/*.Freq*/;
|
|
s.opt_len += f * (bits + xbits);
|
|
if (has_stree) {
|
|
s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits);
|
|
}
|
|
}
|
|
if (overflow === 0) { return; }
|
|
|
|
// Trace((stderr,"\nbit length overflow\n"));
|
|
/* This happens for example on obj2 and pic of the Calgary corpus */
|
|
|
|
/* Find the first bit length which could increase: */
|
|
do {
|
|
bits = max_length - 1;
|
|
while (s.bl_count[bits] === 0) { bits--; }
|
|
s.bl_count[bits]--; /* move one leaf down the tree */
|
|
s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */
|
|
s.bl_count[max_length]--;
|
|
/* The brother of the overflow item also moves one step up,
|
|
* but this does not affect bl_count[max_length]
|
|
*/
|
|
overflow -= 2;
|
|
} while (overflow > 0);
|
|
|
|
/* Now recompute all bit lengths, scanning in increasing frequency.
|
|
* h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
|
|
* lengths instead of fixing only the wrong ones. This idea is taken
|
|
* from 'ar' written by Haruhiko Okumura.)
|
|
*/
|
|
for (bits = max_length; bits !== 0; bits--) {
|
|
n = s.bl_count[bits];
|
|
while (n !== 0) {
|
|
m = s.heap[--h];
|
|
if (m > max_code) { continue; }
|
|
if (tree[m * 2 + 1]/*.Len*/ !== bits) {
|
|
// Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
|
|
s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/;
|
|
tree[m * 2 + 1]/*.Len*/ = bits;
|
|
}
|
|
n--;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Generate the codes for a given tree and bit counts (which need not be
|
|
* optimal).
|
|
* IN assertion: the array bl_count contains the bit length statistics for
|
|
* the given tree and the field len is set for all tree elements.
|
|
* OUT assertion: the field code is set for all tree elements of non
|
|
* zero code length.
|
|
*/
|
|
function gen_codes(tree, max_code, bl_count)
|
|
// ct_data *tree; /* the tree to decorate */
|
|
// int max_code; /* largest code with non zero frequency */
|
|
// ushf *bl_count; /* number of codes at each bit length */
|
|
{
|
|
var next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */
|
|
var code = 0; /* running code value */
|
|
var bits; /* bit index */
|
|
var n; /* code index */
|
|
|
|
/* The distribution counts are first used to generate the code values
|
|
* without bit reversal.
|
|
*/
|
|
for (bits = 1; bits <= MAX_BITS; bits++) {
|
|
next_code[bits] = code = (code + bl_count[bits - 1]) << 1;
|
|
}
|
|
/* Check that the bit counts in bl_count are consistent. The last code
|
|
* must be all ones.
|
|
*/
|
|
//Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
|
|
// "inconsistent bit counts");
|
|
//Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
|
|
|
|
for (n = 0; n <= max_code; n++) {
|
|
var len = tree[n * 2 + 1]/*.Len*/;
|
|
if (len === 0) { continue; }
|
|
/* Now reverse the bits */
|
|
tree[n * 2]/*.Code*/ = bi_reverse(next_code[len]++, len);
|
|
|
|
//Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
|
|
// n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
|
|
}
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Initialize the various 'constant' tables.
|
|
*/
|
|
function tr_static_init() {
|
|
var n; /* iterates over tree elements */
|
|
var bits; /* bit counter */
|
|
var length; /* length value */
|
|
var code; /* code value */
|
|
var dist; /* distance index */
|
|
var bl_count = new Array(MAX_BITS + 1);
|
|
/* number of codes at each bit length for an optimal tree */
|
|
|
|
// do check in _tr_init()
|
|
//if (static_init_done) return;
|
|
|
|
/* For some embedded targets, global variables are not initialized: */
|
|
/*#ifdef NO_INIT_GLOBAL_POINTERS
|
|
static_l_desc.static_tree = static_ltree;
|
|
static_l_desc.extra_bits = extra_lbits;
|
|
static_d_desc.static_tree = static_dtree;
|
|
static_d_desc.extra_bits = extra_dbits;
|
|
static_bl_desc.extra_bits = extra_blbits;
|
|
#endif*/
|
|
|
|
/* Initialize the mapping length (0..255) -> length code (0..28) */
|
|
length = 0;
|
|
for (code = 0; code < LENGTH_CODES - 1; code++) {
|
|
base_length[code] = length;
|
|
for (n = 0; n < (1 << extra_lbits[code]); n++) {
|
|
_length_code[length++] = code;
|
|
}
|
|
}
|
|
//Assert (length == 256, "tr_static_init: length != 256");
|
|
/* Note that the length 255 (match length 258) can be represented
|
|
* in two different ways: code 284 + 5 bits or code 285, so we
|
|
* overwrite length_code[255] to use the best encoding:
|
|
*/
|
|
_length_code[length - 1] = code;
|
|
|
|
/* Initialize the mapping dist (0..32K) -> dist code (0..29) */
|
|
dist = 0;
|
|
for (code = 0; code < 16; code++) {
|
|
base_dist[code] = dist;
|
|
for (n = 0; n < (1 << extra_dbits[code]); n++) {
|
|
_dist_code[dist++] = code;
|
|
}
|
|
}
|
|
//Assert (dist == 256, "tr_static_init: dist != 256");
|
|
dist >>= 7; /* from now on, all distances are divided by 128 */
|
|
for (; code < D_CODES; code++) {
|
|
base_dist[code] = dist << 7;
|
|
for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
|
|
_dist_code[256 + dist++] = code;
|
|
}
|
|
}
|
|
//Assert (dist == 256, "tr_static_init: 256+dist != 512");
|
|
|
|
/* Construct the codes of the static literal tree */
|
|
for (bits = 0; bits <= MAX_BITS; bits++) {
|
|
bl_count[bits] = 0;
|
|
}
|
|
|
|
n = 0;
|
|
while (n <= 143) {
|
|
static_ltree[n * 2 + 1]/*.Len*/ = 8;
|
|
n++;
|
|
bl_count[8]++;
|
|
}
|
|
while (n <= 255) {
|
|
static_ltree[n * 2 + 1]/*.Len*/ = 9;
|
|
n++;
|
|
bl_count[9]++;
|
|
}
|
|
while (n <= 279) {
|
|
static_ltree[n * 2 + 1]/*.Len*/ = 7;
|
|
n++;
|
|
bl_count[7]++;
|
|
}
|
|
while (n <= 287) {
|
|
static_ltree[n * 2 + 1]/*.Len*/ = 8;
|
|
n++;
|
|
bl_count[8]++;
|
|
}
|
|
/* Codes 286 and 287 do not exist, but we must include them in the
|
|
* tree construction to get a canonical Huffman tree (longest code
|
|
* all ones)
|
|
*/
|
|
gen_codes(static_ltree, L_CODES + 1, bl_count);
|
|
|
|
/* The static distance tree is trivial: */
|
|
for (n = 0; n < D_CODES; n++) {
|
|
static_dtree[n * 2 + 1]/*.Len*/ = 5;
|
|
static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5);
|
|
}
|
|
|
|
// Now data ready and we can init static trees
|
|
static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
|
|
static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS);
|
|
static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS);
|
|
|
|
//static_init_done = true;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Initialize a new block.
|
|
*/
|
|
function init_block(s) {
|
|
var n; /* iterates over tree elements */
|
|
|
|
/* Initialize the trees. */
|
|
for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; }
|
|
for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; }
|
|
for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; }
|
|
|
|
s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1;
|
|
s.opt_len = s.static_len = 0;
|
|
s.last_lit = s.matches = 0;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Flush the bit buffer and align the output on a byte boundary
|
|
*/
|
|
function bi_windup(s)
|
|
{
|
|
if (s.bi_valid > 8) {
|
|
put_short(s, s.bi_buf);
|
|
} else if (s.bi_valid > 0) {
|
|
//put_byte(s, (Byte)s->bi_buf);
|
|
s.pending_buf[s.pending++] = s.bi_buf;
|
|
}
|
|
s.bi_buf = 0;
|
|
s.bi_valid = 0;
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Copy a stored block, storing first the length and its
|
|
* one's complement if requested.
|
|
*/
|
|
function copy_block(s, buf, len, header)
|
|
//DeflateState *s;
|
|
//charf *buf; /* the input data */
|
|
//unsigned len; /* its length */
|
|
//int header; /* true if block header must be written */
|
|
{
|
|
bi_windup(s); /* align on byte boundary */
|
|
|
|
if (header) {
|
|
put_short(s, len);
|
|
put_short(s, ~len);
|
|
}
|
|
// while (len--) {
|
|
// put_byte(s, *buf++);
|
|
// }
|
|
utils.arraySet(s.pending_buf, s.window, buf, len, s.pending);
|
|
s.pending += len;
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Compares to subtrees, using the tree depth as tie breaker when
|
|
* the subtrees have equal frequency. This minimizes the worst case length.
|
|
*/
|
|
function smaller(tree, n, m, depth) {
|
|
var _n2 = n * 2;
|
|
var _m2 = m * 2;
|
|
return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||
|
|
(tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Restore the heap property by moving down the tree starting at node k,
|
|
* exchanging a node with the smallest of its two sons if necessary, stopping
|
|
* when the heap property is re-established (each father smaller than its
|
|
* two sons).
|
|
*/
|
|
function pqdownheap(s, tree, k)
|
|
// deflate_state *s;
|
|
// ct_data *tree; /* the tree to restore */
|
|
// int k; /* node to move down */
|
|
{
|
|
var v = s.heap[k];
|
|
var j = k << 1; /* left son of k */
|
|
while (j <= s.heap_len) {
|
|
/* Set j to the smallest of the two sons: */
|
|
if (j < s.heap_len &&
|
|
smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) {
|
|
j++;
|
|
}
|
|
/* Exit if v is smaller than both sons */
|
|
if (smaller(tree, v, s.heap[j], s.depth)) { break; }
|
|
|
|
/* Exchange v with the smallest son */
|
|
s.heap[k] = s.heap[j];
|
|
k = j;
|
|
|
|
/* And continue down the tree, setting j to the left son of k */
|
|
j <<= 1;
|
|
}
|
|
s.heap[k] = v;
|
|
}
|
|
|
|
|
|
// inlined manually
|
|
// var SMALLEST = 1;
|
|
|
|
/* ===========================================================================
|
|
* Send the block data compressed using the given Huffman trees
|
|
*/
|
|
function compress_block(s, ltree, dtree)
|
|
// deflate_state *s;
|
|
// const ct_data *ltree; /* literal tree */
|
|
// const ct_data *dtree; /* distance tree */
|
|
{
|
|
var dist; /* distance of matched string */
|
|
var lc; /* match length or unmatched char (if dist == 0) */
|
|
var lx = 0; /* running index in l_buf */
|
|
var code; /* the code to send */
|
|
var extra; /* number of extra bits to send */
|
|
|
|
if (s.last_lit !== 0) {
|
|
do {
|
|
dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]);
|
|
lc = s.pending_buf[s.l_buf + lx];
|
|
lx++;
|
|
|
|
if (dist === 0) {
|
|
send_code(s, lc, ltree); /* send a literal byte */
|
|
//Tracecv(isgraph(lc), (stderr," '%c' ", lc));
|
|
} else {
|
|
/* Here, lc is the match length - MIN_MATCH */
|
|
code = _length_code[lc];
|
|
send_code(s, code + LITERALS + 1, ltree); /* send the length code */
|
|
extra = extra_lbits[code];
|
|
if (extra !== 0) {
|
|
lc -= base_length[code];
|
|
send_bits(s, lc, extra); /* send the extra length bits */
|
|
}
|
|
dist--; /* dist is now the match distance - 1 */
|
|
code = d_code(dist);
|
|
//Assert (code < D_CODES, "bad d_code");
|
|
|
|
send_code(s, code, dtree); /* send the distance code */
|
|
extra = extra_dbits[code];
|
|
if (extra !== 0) {
|
|
dist -= base_dist[code];
|
|
send_bits(s, dist, extra); /* send the extra distance bits */
|
|
}
|
|
} /* literal or match pair ? */
|
|
|
|
/* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
|
|
//Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
|
|
// "pendingBuf overflow");
|
|
|
|
} while (lx < s.last_lit);
|
|
}
|
|
|
|
send_code(s, END_BLOCK, ltree);
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Construct one Huffman tree and assigns the code bit strings and lengths.
|
|
* Update the total bit length for the current block.
|
|
* IN assertion: the field freq is set for all tree elements.
|
|
* OUT assertions: the fields len and code are set to the optimal bit length
|
|
* and corresponding code. The length opt_len is updated; static_len is
|
|
* also updated if stree is not null. The field max_code is set.
|
|
*/
|
|
function build_tree(s, desc)
|
|
// deflate_state *s;
|
|
// tree_desc *desc; /* the tree descriptor */
|
|
{
|
|
var tree = desc.dyn_tree;
|
|
var stree = desc.stat_desc.static_tree;
|
|
var has_stree = desc.stat_desc.has_stree;
|
|
var elems = desc.stat_desc.elems;
|
|
var n, m; /* iterate over heap elements */
|
|
var max_code = -1; /* largest code with non zero frequency */
|
|
var node; /* new node being created */
|
|
|
|
/* Construct the initial heap, with least frequent element in
|
|
* heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
|
|
* heap[0] is not used.
|
|
*/
|
|
s.heap_len = 0;
|
|
s.heap_max = HEAP_SIZE;
|
|
|
|
for (n = 0; n < elems; n++) {
|
|
if (tree[n * 2]/*.Freq*/ !== 0) {
|
|
s.heap[++s.heap_len] = max_code = n;
|
|
s.depth[n] = 0;
|
|
|
|
} else {
|
|
tree[n * 2 + 1]/*.Len*/ = 0;
|
|
}
|
|
}
|
|
|
|
/* The pkzip format requires that at least one distance code exists,
|
|
* and that at least one bit should be sent even if there is only one
|
|
* possible code. So to avoid special checks later on we force at least
|
|
* two codes of non zero frequency.
|
|
*/
|
|
while (s.heap_len < 2) {
|
|
node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
|
|
tree[node * 2]/*.Freq*/ = 1;
|
|
s.depth[node] = 0;
|
|
s.opt_len--;
|
|
|
|
if (has_stree) {
|
|
s.static_len -= stree[node * 2 + 1]/*.Len*/;
|
|
}
|
|
/* node is 0 or 1 so it does not have extra bits */
|
|
}
|
|
desc.max_code = max_code;
|
|
|
|
/* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
|
|
* establish sub-heaps of increasing lengths:
|
|
*/
|
|
for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }
|
|
|
|
/* Construct the Huffman tree by repeatedly combining the least two
|
|
* frequent nodes.
|
|
*/
|
|
node = elems; /* next internal node of the tree */
|
|
do {
|
|
//pqremove(s, tree, n); /* n = node of least frequency */
|
|
/*** pqremove ***/
|
|
n = s.heap[1/*SMALLEST*/];
|
|
s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];
|
|
pqdownheap(s, tree, 1/*SMALLEST*/);
|
|
/***/
|
|
|
|
m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */
|
|
|
|
s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */
|
|
s.heap[--s.heap_max] = m;
|
|
|
|
/* Create a new node father of n and m */
|
|
tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;
|
|
s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;
|
|
tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node;
|
|
|
|
/* and insert the new node in the heap */
|
|
s.heap[1/*SMALLEST*/] = node++;
|
|
pqdownheap(s, tree, 1/*SMALLEST*/);
|
|
|
|
} while (s.heap_len >= 2);
|
|
|
|
s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];
|
|
|
|
/* At this point, the fields freq and dad are set. We can now
|
|
* generate the bit lengths.
|
|
*/
|
|
gen_bitlen(s, desc);
|
|
|
|
/* The field len is now set, we can generate the bit codes */
|
|
gen_codes(tree, max_code, s.bl_count);
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Scan a literal or distance tree to determine the frequencies of the codes
|
|
* in the bit length tree.
|
|
*/
|
|
function scan_tree(s, tree, max_code)
|
|
// deflate_state *s;
|
|
// ct_data *tree; /* the tree to be scanned */
|
|
// int max_code; /* and its largest code of non zero frequency */
|
|
{
|
|
var n; /* iterates over all tree elements */
|
|
var prevlen = -1; /* last emitted length */
|
|
var curlen; /* length of current code */
|
|
|
|
var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
|
|
|
|
var count = 0; /* repeat count of the current code */
|
|
var max_count = 7; /* max repeat count */
|
|
var min_count = 4; /* min repeat count */
|
|
|
|
if (nextlen === 0) {
|
|
max_count = 138;
|
|
min_count = 3;
|
|
}
|
|
tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */
|
|
|
|
for (n = 0; n <= max_code; n++) {
|
|
curlen = nextlen;
|
|
nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;
|
|
|
|
if (++count < max_count && curlen === nextlen) {
|
|
continue;
|
|
|
|
} else if (count < min_count) {
|
|
s.bl_tree[curlen * 2]/*.Freq*/ += count;
|
|
|
|
} else if (curlen !== 0) {
|
|
|
|
if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }
|
|
s.bl_tree[REP_3_6 * 2]/*.Freq*/++;
|
|
|
|
} else if (count <= 10) {
|
|
s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++;
|
|
|
|
} else {
|
|
s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++;
|
|
}
|
|
|
|
count = 0;
|
|
prevlen = curlen;
|
|
|
|
if (nextlen === 0) {
|
|
max_count = 138;
|
|
min_count = 3;
|
|
|
|
} else if (curlen === nextlen) {
|
|
max_count = 6;
|
|
min_count = 3;
|
|
|
|
} else {
|
|
max_count = 7;
|
|
min_count = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Send a literal or distance tree in compressed form, using the codes in
|
|
* bl_tree.
|
|
*/
|
|
function send_tree(s, tree, max_code)
|
|
// deflate_state *s;
|
|
// ct_data *tree; /* the tree to be scanned */
|
|
// int max_code; /* and its largest code of non zero frequency */
|
|
{
|
|
var n; /* iterates over all tree elements */
|
|
var prevlen = -1; /* last emitted length */
|
|
var curlen; /* length of current code */
|
|
|
|
var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
|
|
|
|
var count = 0; /* repeat count of the current code */
|
|
var max_count = 7; /* max repeat count */
|
|
var min_count = 4; /* min repeat count */
|
|
|
|
/* tree[max_code+1].Len = -1; */ /* guard already set */
|
|
if (nextlen === 0) {
|
|
max_count = 138;
|
|
min_count = 3;
|
|
}
|
|
|
|
for (n = 0; n <= max_code; n++) {
|
|
curlen = nextlen;
|
|
nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;
|
|
|
|
if (++count < max_count && curlen === nextlen) {
|
|
continue;
|
|
|
|
} else if (count < min_count) {
|
|
do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);
|
|
|
|
} else if (curlen !== 0) {
|
|
if (curlen !== prevlen) {
|
|
send_code(s, curlen, s.bl_tree);
|
|
count--;
|
|
}
|
|
//Assert(count >= 3 && count <= 6, " 3_6?");
|
|
send_code(s, REP_3_6, s.bl_tree);
|
|
send_bits(s, count - 3, 2);
|
|
|
|
} else if (count <= 10) {
|
|
send_code(s, REPZ_3_10, s.bl_tree);
|
|
send_bits(s, count - 3, 3);
|
|
|
|
} else {
|
|
send_code(s, REPZ_11_138, s.bl_tree);
|
|
send_bits(s, count - 11, 7);
|
|
}
|
|
|
|
count = 0;
|
|
prevlen = curlen;
|
|
if (nextlen === 0) {
|
|
max_count = 138;
|
|
min_count = 3;
|
|
|
|
} else if (curlen === nextlen) {
|
|
max_count = 6;
|
|
min_count = 3;
|
|
|
|
} else {
|
|
max_count = 7;
|
|
min_count = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Construct the Huffman tree for the bit lengths and return the index in
|
|
* bl_order of the last bit length code to send.
|
|
*/
|
|
function build_bl_tree(s) {
|
|
var max_blindex; /* index of last bit length code of non zero freq */
|
|
|
|
/* Determine the bit length frequencies for literal and distance trees */
|
|
scan_tree(s, s.dyn_ltree, s.l_desc.max_code);
|
|
scan_tree(s, s.dyn_dtree, s.d_desc.max_code);
|
|
|
|
/* Build the bit length tree: */
|
|
build_tree(s, s.bl_desc);
|
|
/* opt_len now includes the length of the tree representations, except
|
|
* the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
|
|
*/
|
|
|
|
/* Determine the number of bit length codes to send. The pkzip format
|
|
* requires that at least 4 bit length codes be sent. (appnote.txt says
|
|
* 3 but the actual value used is 4.)
|
|
*/
|
|
for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
|
|
if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) {
|
|
break;
|
|
}
|
|
}
|
|
/* Update opt_len to include the bit length tree and counts */
|
|
s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
|
|
//Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
|
|
// s->opt_len, s->static_len));
|
|
|
|
return max_blindex;
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Send the header for a block using dynamic Huffman trees: the counts, the
|
|
* lengths of the bit length codes, the literal tree and the distance tree.
|
|
* IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
|
|
*/
|
|
function send_all_trees(s, lcodes, dcodes, blcodes)
|
|
// deflate_state *s;
|
|
// int lcodes, dcodes, blcodes; /* number of codes for each tree */
|
|
{
|
|
var rank; /* index in bl_order */
|
|
|
|
//Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
|
|
//Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
|
|
// "too many codes");
|
|
//Tracev((stderr, "\nbl counts: "));
|
|
send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
|
|
send_bits(s, dcodes - 1, 5);
|
|
send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */
|
|
for (rank = 0; rank < blcodes; rank++) {
|
|
//Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
|
|
send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3);
|
|
}
|
|
//Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
|
|
|
|
send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */
|
|
//Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
|
|
|
|
send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */
|
|
//Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Check if the data type is TEXT or BINARY, using the following algorithm:
|
|
* - TEXT if the two conditions below are satisfied:
|
|
* a) There are no non-portable control characters belonging to the
|
|
* "black list" (0..6, 14..25, 28..31).
|
|
* b) There is at least one printable character belonging to the
|
|
* "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
|
|
* - BINARY otherwise.
|
|
* - The following partially-portable control characters form a
|
|
* "gray list" that is ignored in this detection algorithm:
|
|
* (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
|
|
* IN assertion: the fields Freq of dyn_ltree are set.
|
|
*/
|
|
function detect_data_type(s) {
|
|
/* black_mask is the bit mask of black-listed bytes
|
|
* set bits 0..6, 14..25, and 28..31
|
|
* 0xf3ffc07f = binary 11110011111111111100000001111111
|
|
*/
|
|
var black_mask = 0xf3ffc07f;
|
|
var n;
|
|
|
|
/* Check for non-textual ("black-listed") bytes. */
|
|
for (n = 0; n <= 31; n++, black_mask >>>= 1) {
|
|
if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) {
|
|
return Z_BINARY;
|
|
}
|
|
}
|
|
|
|
/* Check for textual ("white-listed") bytes. */
|
|
if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||
|
|
s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {
|
|
return Z_TEXT;
|
|
}
|
|
for (n = 32; n < LITERALS; n++) {
|
|
if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {
|
|
return Z_TEXT;
|
|
}
|
|
}
|
|
|
|
/* There are no "black-listed" or "white-listed" bytes:
|
|
* this stream either is empty or has tolerated ("gray-listed") bytes only.
|
|
*/
|
|
return Z_BINARY;
|
|
}
|
|
|
|
|
|
var static_init_done = false;
|
|
|
|
/* ===========================================================================
|
|
* Initialize the tree data structures for a new zlib stream.
|
|
*/
|
|
function _tr_init(s)
|
|
{
|
|
|
|
if (!static_init_done) {
|
|
tr_static_init();
|
|
static_init_done = true;
|
|
}
|
|
|
|
s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc);
|
|
s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc);
|
|
s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);
|
|
|
|
s.bi_buf = 0;
|
|
s.bi_valid = 0;
|
|
|
|
/* Initialize the first block of the first file: */
|
|
init_block(s);
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Send a stored block
|
|
*/
|
|
function _tr_stored_block(s, buf, stored_len, last)
|
|
//DeflateState *s;
|
|
//charf *buf; /* input block */
|
|
//ulg stored_len; /* length of input block */
|
|
//int last; /* one if this is the last block for a file */
|
|
{
|
|
send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */
|
|
copy_block(s, buf, stored_len, true); /* with header */
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Send one empty static block to give enough lookahead for inflate.
|
|
* This takes 10 bits, of which 7 may remain in the bit buffer.
|
|
*/
|
|
function _tr_align(s) {
|
|
send_bits(s, STATIC_TREES << 1, 3);
|
|
send_code(s, END_BLOCK, static_ltree);
|
|
bi_flush(s);
|
|
}
|
|
|
|
|
|
/* ===========================================================================
|
|
* Determine the best encoding for the current block: dynamic trees, static
|
|
* trees or store, and output the encoded block to the zip file.
|
|
*/
|
|
function _tr_flush_block(s, buf, stored_len, last)
|
|
//DeflateState *s;
|
|
//charf *buf; /* input block, or NULL if too old */
|
|
//ulg stored_len; /* length of input block */
|
|
//int last; /* one if this is the last block for a file */
|
|
{
|
|
var opt_lenb, static_lenb; /* opt_len and static_len in bytes */
|
|
var max_blindex = 0; /* index of last bit length code of non zero freq */
|
|
|
|
/* Build the Huffman trees unless a stored block is forced */
|
|
if (s.level > 0) {
|
|
|
|
/* Check if the file is binary or text */
|
|
if (s.strm.data_type === Z_UNKNOWN) {
|
|
s.strm.data_type = detect_data_type(s);
|
|
}
|
|
|
|
/* Construct the literal and distance trees */
|
|
build_tree(s, s.l_desc);
|
|
// Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
|
|
// s->static_len));
|
|
|
|
build_tree(s, s.d_desc);
|
|
// Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
|
|
// s->static_len));
|
|
/* At this point, opt_len and static_len are the total bit lengths of
|
|
* the compressed block data, excluding the tree representations.
|
|
*/
|
|
|
|
/* Build the bit length tree for the above two trees, and get the index
|
|
* in bl_order of the last bit length code to send.
|
|
*/
|
|
max_blindex = build_bl_tree(s);
|
|
|
|
/* Determine the best encoding. Compute the block lengths in bytes. */
|
|
opt_lenb = (s.opt_len + 3 + 7) >>> 3;
|
|
static_lenb = (s.static_len + 3 + 7) >>> 3;
|
|
|
|
// Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
|
|
// opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
|
|
// s->last_lit));
|
|
|
|
if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }
|
|
|
|
} else {
|
|
// Assert(buf != (char*)0, "lost buf");
|
|
opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
|
|
}
|
|
|
|
if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) {
|
|
/* 4: two words for the lengths */
|
|
|
|
/* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
|
|
* Otherwise we can't have processed more than WSIZE input bytes since
|
|
* the last block flush, because compression would have been
|
|
* successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
|
|
* transform a block into a stored block.
|
|
*/
|
|
_tr_stored_block(s, buf, stored_len, last);
|
|
|
|
} else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) {
|
|
|
|
send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3);
|
|
compress_block(s, static_ltree, static_dtree);
|
|
|
|
} else {
|
|
send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3);
|
|
send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1);
|
|
compress_block(s, s.dyn_ltree, s.dyn_dtree);
|
|
}
|
|
// Assert (s->compressed_len == s->bits_sent, "bad compressed size");
|
|
/* The above check is made mod 2^32, for files larger than 512 MB
|
|
* and uLong implemented on 32 bits.
|
|
*/
|
|
init_block(s);
|
|
|
|
if (last) {
|
|
bi_windup(s);
|
|
}
|
|
// Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
|
|
// s->compressed_len-7*last));
|
|
}
|
|
|
|
/* ===========================================================================
|
|
* Save the match info and tally the frequency counts. Return true if
|
|
* the current block must be flushed.
|
|
*/
|
|
function _tr_tally(s, dist, lc)
|
|
// deflate_state *s;
|
|
// unsigned dist; /* distance of matched string */
|
|
// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
|
|
{
|
|
//var out_length, in_length, dcode;
|
|
|
|
s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff;
|
|
s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff;
|
|
|
|
s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff;
|
|
s.last_lit++;
|
|
|
|
if (dist === 0) {
|
|
/* lc is the unmatched char */
|
|
s.dyn_ltree[lc * 2]/*.Freq*/++;
|
|
} else {
|
|
s.matches++;
|
|
/* Here, lc is the match length - MIN_MATCH */
|
|
dist--; /* dist = match distance - 1 */
|
|
//Assert((ush)dist < (ush)MAX_DIST(s) &&
|
|
// (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
|
|
// (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
|
|
|
|
s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++;
|
|
s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;
|
|
}
|
|
|
|
// (!) This block is disabled in zlib defaults,
|
|
// don't enable it for binary compatibility
|
|
|
|
//#ifdef TRUNCATE_BLOCK
|
|
// /* Try to guess if it is profitable to stop the current block here */
|
|
// if ((s.last_lit & 0x1fff) === 0 && s.level > 2) {
|
|
// /* Compute an upper bound for the compressed length */
|
|
// out_length = s.last_lit*8;
|
|
// in_length = s.strstart - s.block_start;
|
|
//
|
|
// for (dcode = 0; dcode < D_CODES; dcode++) {
|
|
// out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]);
|
|
// }
|
|
// out_length >>>= 3;
|
|
// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
|
|
// // s->last_lit, in_length, out_length,
|
|
// // 100L - out_length*100L/in_length));
|
|
// if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) {
|
|
// return true;
|
|
// }
|
|
// }
|
|
//#endif
|
|
|
|
return (s.last_lit === s.lit_bufsize - 1);
|
|
/* We avoid equality with lit_bufsize because of wraparound at 64K
|
|
* on 16 bit machines and because stored blocks are restricted to
|
|
* 64K-1 bytes.
|
|
*/
|
|
}
|
|
|
|
exports._tr_init = _tr_init;
|
|
exports._tr_stored_block = _tr_stored_block;
|
|
exports._tr_flush_block = _tr_flush_block;
|
|
exports._tr_tally = _tr_tally;
|
|
exports._tr_align = _tr_align;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/browserify-zlib/node_modules/pako/lib/zlib/zstream.js":
|
|
/*!****************************************************************************!*\
|
|
!*** ./node_modules/browserify-zlib/node_modules/pako/lib/zlib/zstream.js ***!
|
|
\****************************************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
function ZStream() {
|
|
/* next input byte */
|
|
this.input = null; // JS specific, because we have no pointers
|
|
this.next_in = 0;
|
|
/* number of bytes available at input */
|
|
this.avail_in = 0;
|
|
/* total number of input bytes read so far */
|
|
this.total_in = 0;
|
|
/* next output byte should be put there */
|
|
this.output = null; // JS specific, because we have no pointers
|
|
this.next_out = 0;
|
|
/* remaining free space at output */
|
|
this.avail_out = 0;
|
|
/* total number of bytes output so far */
|
|
this.total_out = 0;
|
|
/* last error message, NULL if no error */
|
|
this.msg = ''/*Z_NULL*/;
|
|
/* not visible by applications */
|
|
this.state = null;
|
|
/* best guess about the data type: binary or text */
|
|
this.data_type = 2/*Z_UNKNOWN*/;
|
|
/* adler32 value of the uncompressed data */
|
|
this.adler = 0;
|
|
}
|
|
|
|
module.exports = ZStream;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/buffer-alloc-unsafe/index.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/buffer-alloc-unsafe/index.js ***!
|
|
\***************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
function allocUnsafe (size) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('"size" argument must be a number')
|
|
}
|
|
|
|
if (size < 0) {
|
|
throw new RangeError('"size" argument must not be negative')
|
|
}
|
|
|
|
if (Buffer.allocUnsafe) {
|
|
return Buffer.allocUnsafe(size)
|
|
} else {
|
|
return new Buffer(size)
|
|
}
|
|
}
|
|
|
|
module.exports = allocUnsafe
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/buffer-alloc/index.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/buffer-alloc/index.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
var bufferFill = __webpack_require__(/*! buffer-fill */ "./node_modules/buffer-fill/index.js")
|
|
var allocUnsafe = __webpack_require__(/*! buffer-alloc-unsafe */ "./node_modules/buffer-alloc-unsafe/index.js")
|
|
|
|
module.exports = function alloc (size, fill, encoding) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('"size" argument must be a number')
|
|
}
|
|
|
|
if (size < 0) {
|
|
throw new RangeError('"size" argument must not be negative')
|
|
}
|
|
|
|
if (Buffer.alloc) {
|
|
return Buffer.alloc(size, fill, encoding)
|
|
}
|
|
|
|
var buffer = allocUnsafe(size)
|
|
|
|
if (size === 0) {
|
|
return buffer
|
|
}
|
|
|
|
if (fill === undefined) {
|
|
return bufferFill(buffer, 0)
|
|
}
|
|
|
|
if (typeof encoding !== 'string') {
|
|
encoding = undefined
|
|
}
|
|
|
|
return bufferFill(buffer, fill, encoding)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/buffer-fill/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/buffer-fill/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/* Node.js 6.4.0 and up has full support */
|
|
var hasFullSupport = (function () {
|
|
try {
|
|
if (!Buffer.isEncoding('latin1')) {
|
|
return false
|
|
}
|
|
|
|
var buf = Buffer.alloc ? Buffer.alloc(4) : new Buffer(4)
|
|
|
|
buf.fill('ab', 'ucs2')
|
|
|
|
return (buf.toString('hex') === '61006200')
|
|
} catch (_) {
|
|
return false
|
|
}
|
|
}())
|
|
|
|
function isSingleByte (val) {
|
|
return (val.length === 1 && val.charCodeAt(0) < 256)
|
|
}
|
|
|
|
function fillWithNumber (buffer, val, start, end) {
|
|
if (start < 0 || end > buffer.length) {
|
|
throw new RangeError('Out of range index')
|
|
}
|
|
|
|
start = start >>> 0
|
|
end = end === undefined ? buffer.length : end >>> 0
|
|
|
|
if (end > start) {
|
|
buffer.fill(val, start, end)
|
|
}
|
|
|
|
return buffer
|
|
}
|
|
|
|
function fillWithBuffer (buffer, val, start, end) {
|
|
if (start < 0 || end > buffer.length) {
|
|
throw new RangeError('Out of range index')
|
|
}
|
|
|
|
if (end <= start) {
|
|
return buffer
|
|
}
|
|
|
|
start = start >>> 0
|
|
end = end === undefined ? buffer.length : end >>> 0
|
|
|
|
var pos = start
|
|
var len = val.length
|
|
while (pos <= (end - len)) {
|
|
val.copy(buffer, pos)
|
|
pos += len
|
|
}
|
|
|
|
if (pos !== end) {
|
|
val.copy(buffer, pos, 0, end - pos)
|
|
}
|
|
|
|
return buffer
|
|
}
|
|
|
|
function fill (buffer, val, start, end, encoding) {
|
|
if (hasFullSupport) {
|
|
return buffer.fill(val, start, end, encoding)
|
|
}
|
|
|
|
if (typeof val === 'number') {
|
|
return fillWithNumber(buffer, val, start, end)
|
|
}
|
|
|
|
if (typeof val === 'string') {
|
|
if (typeof start === 'string') {
|
|
encoding = start
|
|
start = 0
|
|
end = buffer.length
|
|
} else if (typeof end === 'string') {
|
|
encoding = end
|
|
end = buffer.length
|
|
}
|
|
|
|
if (encoding !== undefined && typeof encoding !== 'string') {
|
|
throw new TypeError('encoding must be a string')
|
|
}
|
|
|
|
if (encoding === 'latin1') {
|
|
encoding = 'binary'
|
|
}
|
|
|
|
if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
|
|
throw new TypeError('Unknown encoding: ' + encoding)
|
|
}
|
|
|
|
if (val === '') {
|
|
return fillWithNumber(buffer, 0, start, end)
|
|
}
|
|
|
|
if (isSingleByte(val)) {
|
|
return fillWithNumber(buffer, val.charCodeAt(0), start, end)
|
|
}
|
|
|
|
val = new Buffer(val, encoding)
|
|
}
|
|
|
|
if (Buffer.isBuffer(val)) {
|
|
return fillWithBuffer(buffer, val, start, end)
|
|
}
|
|
|
|
// Other values (e.g. undefined, boolean, object) results in zero-fill
|
|
return fillWithNumber(buffer, 0, start, end)
|
|
}
|
|
|
|
module.exports = fill
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/buffer-xor/index.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/buffer-xor/index.js ***!
|
|
\******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
module.exports = function xor (a, b) {
|
|
var length = Math.min(a.length, b.length)
|
|
var buffer = new Buffer(length)
|
|
|
|
for (var i = 0; i < length; ++i) {
|
|
buffer[i] = a[i] ^ b[i]
|
|
}
|
|
|
|
return buffer
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/buffer/index.js":
|
|
/*!**************************************!*\
|
|
!*** ./node_modules/buffer/index.js ***!
|
|
\**************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
/*!
|
|
* 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] = parsed
|
|
}
|
|
return i
|
|
}
|
|
|
|
function utf8Write (buf, string, offset, length) {
|
|
return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
|
|
}
|
|
|
|
function asciiWrite (buf, string, offset, length) {
|
|
return blitBuffer(asciiToBytes(string), buf, offset, length)
|
|
}
|
|
|
|
function base64Write (buf, string, offset, length) {
|
|
return blitBuffer(base64ToBytes(string), buf, offset, length)
|
|
}
|
|
|
|
function ucs2Write (buf, string, offset, length) {
|
|
return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
|
|
}
|
|
|
|
Buffer.prototype.write = function write (string, offset, length, encoding) {
|
|
// Buffer#write(string)
|
|
if (offset === undefined) {
|
|
encoding = 'utf8'
|
|
length = this.length
|
|
offset = 0
|
|
// Buffer#write(string, encoding)
|
|
} else if (length === undefined && typeof offset === 'string') {
|
|
encoding = offset
|
|
length = this.length
|
|
offset = 0
|
|
// Buffer#write(string, offset[, length][, encoding])
|
|
} else if (isFinite(offset)) {
|
|
offset = offset >>> 0
|
|
if (isFinite(length)) {
|
|
length = length >>> 0
|
|
if (encoding === undefined) encoding = 'utf8'
|
|
} else {
|
|
encoding = length
|
|
length = undefined
|
|
}
|
|
} else {
|
|
throw new Error(
|
|
'Buffer.write(string, encoding, offset[, length]) is no longer supported'
|
|
)
|
|
}
|
|
|
|
const remaining = this.length - offset
|
|
if (length === undefined || length > remaining) length = remaining
|
|
|
|
if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
|
|
throw new RangeError('Attempt to write outside buffer bounds')
|
|
}
|
|
|
|
if (!encoding) encoding = 'utf8'
|
|
|
|
let loweredCase = false
|
|
for (;;) {
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return hexWrite(this, string, offset, length)
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return utf8Write(this, string, offset, length)
|
|
|
|
case 'ascii':
|
|
case 'latin1':
|
|
case 'binary':
|
|
return asciiWrite(this, string, offset, length)
|
|
|
|
case 'base64':
|
|
// Warning: maxLength not taken into account in base64Write
|
|
return base64Write(this, string, offset, length)
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
case 'utf16le':
|
|
case 'utf-16le':
|
|
return ucs2Write(this, string, offset, length)
|
|
|
|
default:
|
|
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
|
|
encoding = ('' + encoding).toLowerCase()
|
|
loweredCase = true
|
|
}
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.toJSON = function toJSON () {
|
|
return {
|
|
type: 'Buffer',
|
|
data: Array.prototype.slice.call(this._arr || this, 0)
|
|
}
|
|
}
|
|
|
|
function base64Slice (buf, start, end) {
|
|
if (start === 0 && end === buf.length) {
|
|
return base64.fromByteArray(buf)
|
|
} else {
|
|
return base64.fromByteArray(buf.slice(start, end))
|
|
}
|
|
}
|
|
|
|
function utf8Slice (buf, start, end) {
|
|
end = Math.min(buf.length, end)
|
|
const res = []
|
|
|
|
let i = start
|
|
while (i < end) {
|
|
const firstByte = buf[i]
|
|
let codePoint = null
|
|
let bytesPerSequence = (firstByte > 0xEF)
|
|
? 4
|
|
: (firstByte > 0xDF)
|
|
? 3
|
|
: (firstByte > 0xBF)
|
|
? 2
|
|
: 1
|
|
|
|
if (i + bytesPerSequence <= end) {
|
|
let secondByte, thirdByte, fourthByte, tempCodePoint
|
|
|
|
switch (bytesPerSequence) {
|
|
case 1:
|
|
if (firstByte < 0x80) {
|
|
codePoint = firstByte
|
|
}
|
|
break
|
|
case 2:
|
|
secondByte = buf[i + 1]
|
|
if ((secondByte & 0xC0) === 0x80) {
|
|
tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
|
|
if (tempCodePoint > 0x7F) {
|
|
codePoint = tempCodePoint
|
|
}
|
|
}
|
|
break
|
|
case 3:
|
|
secondByte = buf[i + 1]
|
|
thirdByte = buf[i + 2]
|
|
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
|
|
tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
|
|
if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
|
|
codePoint = tempCodePoint
|
|
}
|
|
}
|
|
break
|
|
case 4:
|
|
secondByte = buf[i + 1]
|
|
thirdByte = buf[i + 2]
|
|
fourthByte = buf[i + 3]
|
|
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
|
|
tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
|
|
if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
|
|
codePoint = tempCodePoint
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (codePoint === null) {
|
|
// we did not generate a valid codePoint so insert a
|
|
// replacement char (U+FFFD) and advance only 1 byte
|
|
codePoint = 0xFFFD
|
|
bytesPerSequence = 1
|
|
} else if (codePoint > 0xFFFF) {
|
|
// encode to utf16 (surrogate pair dance)
|
|
codePoint -= 0x10000
|
|
res.push(codePoint >>> 10 & 0x3FF | 0xD800)
|
|
codePoint = 0xDC00 | codePoint & 0x3FF
|
|
}
|
|
|
|
res.push(codePoint)
|
|
i += bytesPerSequence
|
|
}
|
|
|
|
return decodeCodePointsArray(res)
|
|
}
|
|
|
|
// Based on http://stackoverflow.com/a/22747272/680742, the browser with
|
|
// the lowest limit is Chrome, with 0x10000 args.
|
|
// We go 1 magnitude less, for safety
|
|
const MAX_ARGUMENTS_LENGTH = 0x1000
|
|
|
|
function decodeCodePointsArray (codePoints) {
|
|
const len = codePoints.length
|
|
if (len <= MAX_ARGUMENTS_LENGTH) {
|
|
return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
|
|
}
|
|
|
|
// Decode in chunks to avoid "call stack size exceeded".
|
|
let res = ''
|
|
let i = 0
|
|
while (i < len) {
|
|
res += String.fromCharCode.apply(
|
|
String,
|
|
codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
|
|
)
|
|
}
|
|
return res
|
|
}
|
|
|
|
function asciiSlice (buf, start, end) {
|
|
let ret = ''
|
|
end = Math.min(buf.length, end)
|
|
|
|
for (let i = start; i < end; ++i) {
|
|
ret += String.fromCharCode(buf[i] & 0x7F)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
function latin1Slice (buf, start, end) {
|
|
let ret = ''
|
|
end = Math.min(buf.length, end)
|
|
|
|
for (let i = start; i < end; ++i) {
|
|
ret += String.fromCharCode(buf[i])
|
|
}
|
|
return ret
|
|
}
|
|
|
|
function hexSlice (buf, start, end) {
|
|
const len = buf.length
|
|
|
|
if (!start || start < 0) start = 0
|
|
if (!end || end < 0 || end > len) end = len
|
|
|
|
let out = ''
|
|
for (let i = start; i < end; ++i) {
|
|
out += hexSliceLookupTable[buf[i]]
|
|
}
|
|
return out
|
|
}
|
|
|
|
function utf16leSlice (buf, start, end) {
|
|
const bytes = buf.slice(start, end)
|
|
let res = ''
|
|
// If bytes.length is odd, the last 8 bits must be ignored (same as node.js)
|
|
for (let i = 0; i < bytes.length - 1; i += 2) {
|
|
res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))
|
|
}
|
|
return res
|
|
}
|
|
|
|
Buffer.prototype.slice = function slice (start, end) {
|
|
const len = this.length
|
|
start = ~~start
|
|
end = end === undefined ? len : ~~end
|
|
|
|
if (start < 0) {
|
|
start += len
|
|
if (start < 0) start = 0
|
|
} else if (start > len) {
|
|
start = len
|
|
}
|
|
|
|
if (end < 0) {
|
|
end += len
|
|
if (end < 0) end = 0
|
|
} else if (end > len) {
|
|
end = len
|
|
}
|
|
|
|
if (end < start) end = start
|
|
|
|
const newBuf = this.subarray(start, end)
|
|
// Return an augmented `Uint8Array` instance
|
|
Object.setPrototypeOf(newBuf, Buffer.prototype)
|
|
|
|
return newBuf
|
|
}
|
|
|
|
/*
|
|
* Need to make sure that buffer isn't trying to write out of bounds.
|
|
*/
|
|
function checkOffset (offset, ext, length) {
|
|
if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
|
|
if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
|
|
}
|
|
|
|
Buffer.prototype.readUintLE =
|
|
Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
|
|
offset = offset >>> 0
|
|
byteLength = byteLength >>> 0
|
|
if (!noAssert) checkOffset(offset, byteLength, this.length)
|
|
|
|
let val = this[offset]
|
|
let mul = 1
|
|
let i = 0
|
|
while (++i < byteLength && (mul *= 0x100)) {
|
|
val += this[offset + i] * mul
|
|
}
|
|
|
|
return val
|
|
}
|
|
|
|
Buffer.prototype.readUintBE =
|
|
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
|
|
offset = offset >>> 0
|
|
byteLength = byteLength >>> 0
|
|
if (!noAssert) {
|
|
checkOffset(offset, byteLength, this.length)
|
|
}
|
|
|
|
let val = this[offset + --byteLength]
|
|
let mul = 1
|
|
while (byteLength > 0 && (mul *= 0x100)) {
|
|
val += this[offset + --byteLength] * mul
|
|
}
|
|
|
|
return val
|
|
}
|
|
|
|
Buffer.prototype.readUint8 =
|
|
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 1, this.length)
|
|
return this[offset]
|
|
}
|
|
|
|
Buffer.prototype.readUint16LE =
|
|
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
return this[offset] | (this[offset + 1] << 8)
|
|
}
|
|
|
|
Buffer.prototype.readUint16BE =
|
|
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
return (this[offset] << 8) | this[offset + 1]
|
|
}
|
|
|
|
Buffer.prototype.readUint32LE =
|
|
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
|
|
return ((this[offset]) |
|
|
(this[offset + 1] << 8) |
|
|
(this[offset + 2] << 16)) +
|
|
(this[offset + 3] * 0x1000000)
|
|
}
|
|
|
|
Buffer.prototype.readUint32BE =
|
|
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
|
|
return (this[offset] * 0x1000000) +
|
|
((this[offset + 1] << 16) |
|
|
(this[offset + 2] << 8) |
|
|
this[offset + 3])
|
|
}
|
|
|
|
Buffer.prototype.readBigUInt64LE = defineBigIntMethod(function readBigUInt64LE (offset) {
|
|
offset = offset >>> 0
|
|
validateNumber(offset, 'offset')
|
|
const first = this[offset]
|
|
const last = this[offset + 7]
|
|
if (first === undefined || last === undefined) {
|
|
boundsError(offset, this.length - 8)
|
|
}
|
|
|
|
const lo = first +
|
|
this[++offset] * 2 ** 8 +
|
|
this[++offset] * 2 ** 16 +
|
|
this[++offset] * 2 ** 24
|
|
|
|
const hi = this[++offset] +
|
|
this[++offset] * 2 ** 8 +
|
|
this[++offset] * 2 ** 16 +
|
|
last * 2 ** 24
|
|
|
|
return BigInt(lo) + (BigInt(hi) << BigInt(32))
|
|
})
|
|
|
|
Buffer.prototype.readBigUInt64BE = defineBigIntMethod(function readBigUInt64BE (offset) {
|
|
offset = offset >>> 0
|
|
validateNumber(offset, 'offset')
|
|
const first = this[offset]
|
|
const last = this[offset + 7]
|
|
if (first === undefined || last === undefined) {
|
|
boundsError(offset, this.length - 8)
|
|
}
|
|
|
|
const hi = first * 2 ** 24 +
|
|
this[++offset] * 2 ** 16 +
|
|
this[++offset] * 2 ** 8 +
|
|
this[++offset]
|
|
|
|
const lo = this[++offset] * 2 ** 24 +
|
|
this[++offset] * 2 ** 16 +
|
|
this[++offset] * 2 ** 8 +
|
|
last
|
|
|
|
return (BigInt(hi) << BigInt(32)) + BigInt(lo)
|
|
})
|
|
|
|
Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
|
|
offset = offset >>> 0
|
|
byteLength = byteLength >>> 0
|
|
if (!noAssert) checkOffset(offset, byteLength, this.length)
|
|
|
|
let val = this[offset]
|
|
let mul = 1
|
|
let i = 0
|
|
while (++i < byteLength && (mul *= 0x100)) {
|
|
val += this[offset + i] * mul
|
|
}
|
|
mul *= 0x80
|
|
|
|
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
|
|
|
|
return val
|
|
}
|
|
|
|
Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
|
|
offset = offset >>> 0
|
|
byteLength = byteLength >>> 0
|
|
if (!noAssert) checkOffset(offset, byteLength, this.length)
|
|
|
|
let i = byteLength
|
|
let mul = 1
|
|
let val = this[offset + --i]
|
|
while (i > 0 && (mul *= 0x100)) {
|
|
val += this[offset + --i] * mul
|
|
}
|
|
mul *= 0x80
|
|
|
|
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
|
|
|
|
return val
|
|
}
|
|
|
|
Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 1, this.length)
|
|
if (!(this[offset] & 0x80)) return (this[offset])
|
|
return ((0xff - this[offset] + 1) * -1)
|
|
}
|
|
|
|
Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
const val = this[offset] | (this[offset + 1] << 8)
|
|
return (val & 0x8000) ? val | 0xFFFF0000 : val
|
|
}
|
|
|
|
Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
const val = this[offset + 1] | (this[offset] << 8)
|
|
return (val & 0x8000) ? val | 0xFFFF0000 : val
|
|
}
|
|
|
|
Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
|
|
return (this[offset]) |
|
|
(this[offset + 1] << 8) |
|
|
(this[offset + 2] << 16) |
|
|
(this[offset + 3] << 24)
|
|
}
|
|
|
|
Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
|
|
return (this[offset] << 24) |
|
|
(this[offset + 1] << 16) |
|
|
(this[offset + 2] << 8) |
|
|
(this[offset + 3])
|
|
}
|
|
|
|
Buffer.prototype.readBigInt64LE = defineBigIntMethod(function readBigInt64LE (offset) {
|
|
offset = offset >>> 0
|
|
validateNumber(offset, 'offset')
|
|
const first = this[offset]
|
|
const last = this[offset + 7]
|
|
if (first === undefined || last === undefined) {
|
|
boundsError(offset, this.length - 8)
|
|
}
|
|
|
|
const val = this[offset + 4] +
|
|
this[offset + 5] * 2 ** 8 +
|
|
this[offset + 6] * 2 ** 16 +
|
|
(last << 24) // Overflow
|
|
|
|
return (BigInt(val) << BigInt(32)) +
|
|
BigInt(first +
|
|
this[++offset] * 2 ** 8 +
|
|
this[++offset] * 2 ** 16 +
|
|
this[++offset] * 2 ** 24)
|
|
})
|
|
|
|
Buffer.prototype.readBigInt64BE = defineBigIntMethod(function readBigInt64BE (offset) {
|
|
offset = offset >>> 0
|
|
validateNumber(offset, 'offset')
|
|
const first = this[offset]
|
|
const last = this[offset + 7]
|
|
if (first === undefined || last === undefined) {
|
|
boundsError(offset, this.length - 8)
|
|
}
|
|
|
|
const val = (first << 24) + // Overflow
|
|
this[++offset] * 2 ** 16 +
|
|
this[++offset] * 2 ** 8 +
|
|
this[++offset]
|
|
|
|
return (BigInt(val) << BigInt(32)) +
|
|
BigInt(this[++offset] * 2 ** 24 +
|
|
this[++offset] * 2 ** 16 +
|
|
this[++offset] * 2 ** 8 +
|
|
last)
|
|
})
|
|
|
|
Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
return ieee754.read(this, offset, true, 23, 4)
|
|
}
|
|
|
|
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
return ieee754.read(this, offset, false, 23, 4)
|
|
}
|
|
|
|
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 8, this.length)
|
|
return ieee754.read(this, offset, true, 52, 8)
|
|
}
|
|
|
|
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 8, this.length)
|
|
return ieee754.read(this, offset, false, 52, 8)
|
|
}
|
|
|
|
function checkInt (buf, value, offset, ext, max, min) {
|
|
if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
|
|
if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
|
|
if (offset + ext > buf.length) throw new RangeError('Index out of range')
|
|
}
|
|
|
|
Buffer.prototype.writeUintLE =
|
|
Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
byteLength = byteLength >>> 0
|
|
if (!noAssert) {
|
|
const maxBytes = Math.pow(2, 8 * byteLength) - 1
|
|
checkInt(this, value, offset, byteLength, maxBytes, 0)
|
|
}
|
|
|
|
let mul = 1
|
|
let i = 0
|
|
this[offset] = value & 0xFF
|
|
while (++i < byteLength && (mul *= 0x100)) {
|
|
this[offset + i] = (value / mul) & 0xFF
|
|
}
|
|
|
|
return offset + byteLength
|
|
}
|
|
|
|
Buffer.prototype.writeUintBE =
|
|
Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
byteLength = byteLength >>> 0
|
|
if (!noAssert) {
|
|
const maxBytes = Math.pow(2, 8 * byteLength) - 1
|
|
checkInt(this, value, offset, byteLength, maxBytes, 0)
|
|
}
|
|
|
|
let i = byteLength - 1
|
|
let mul = 1
|
|
this[offset + i] = value & 0xFF
|
|
while (--i >= 0 && (mul *= 0x100)) {
|
|
this[offset + i] = (value / mul) & 0xFF
|
|
}
|
|
|
|
return offset + byteLength
|
|
}
|
|
|
|
Buffer.prototype.writeUint8 =
|
|
Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
|
|
this[offset] = (value & 0xff)
|
|
return offset + 1
|
|
}
|
|
|
|
Buffer.prototype.writeUint16LE =
|
|
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
return offset + 2
|
|
}
|
|
|
|
Buffer.prototype.writeUint16BE =
|
|
Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
|
|
this[offset] = (value >>> 8)
|
|
this[offset + 1] = (value & 0xff)
|
|
return offset + 2
|
|
}
|
|
|
|
Buffer.prototype.writeUint32LE =
|
|
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
|
|
this[offset + 3] = (value >>> 24)
|
|
this[offset + 2] = (value >>> 16)
|
|
this[offset + 1] = (value >>> 8)
|
|
this[offset] = (value & 0xff)
|
|
return offset + 4
|
|
}
|
|
|
|
Buffer.prototype.writeUint32BE =
|
|
Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
|
|
this[offset] = (value >>> 24)
|
|
this[offset + 1] = (value >>> 16)
|
|
this[offset + 2] = (value >>> 8)
|
|
this[offset + 3] = (value & 0xff)
|
|
return offset + 4
|
|
}
|
|
|
|
function wrtBigUInt64LE (buf, value, offset, min, max) {
|
|
checkIntBI(value, min, max, buf, offset, 7)
|
|
|
|
let lo = Number(value & BigInt(0xffffffff))
|
|
buf[offset++] = lo
|
|
lo = lo >> 8
|
|
buf[offset++] = lo
|
|
lo = lo >> 8
|
|
buf[offset++] = lo
|
|
lo = lo >> 8
|
|
buf[offset++] = lo
|
|
let hi = Number(value >> BigInt(32) & BigInt(0xffffffff))
|
|
buf[offset++] = hi
|
|
hi = hi >> 8
|
|
buf[offset++] = hi
|
|
hi = hi >> 8
|
|
buf[offset++] = hi
|
|
hi = hi >> 8
|
|
buf[offset++] = hi
|
|
return offset
|
|
}
|
|
|
|
function wrtBigUInt64BE (buf, value, offset, min, max) {
|
|
checkIntBI(value, min, max, buf, offset, 7)
|
|
|
|
let lo = Number(value & BigInt(0xffffffff))
|
|
buf[offset + 7] = lo
|
|
lo = lo >> 8
|
|
buf[offset + 6] = lo
|
|
lo = lo >> 8
|
|
buf[offset + 5] = lo
|
|
lo = lo >> 8
|
|
buf[offset + 4] = lo
|
|
let hi = Number(value >> BigInt(32) & BigInt(0xffffffff))
|
|
buf[offset + 3] = hi
|
|
hi = hi >> 8
|
|
buf[offset + 2] = hi
|
|
hi = hi >> 8
|
|
buf[offset + 1] = hi
|
|
hi = hi >> 8
|
|
buf[offset] = hi
|
|
return offset + 8
|
|
}
|
|
|
|
Buffer.prototype.writeBigUInt64LE = defineBigIntMethod(function writeBigUInt64LE (value, offset = 0) {
|
|
return wrtBigUInt64LE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff'))
|
|
})
|
|
|
|
Buffer.prototype.writeBigUInt64BE = defineBigIntMethod(function writeBigUInt64BE (value, offset = 0) {
|
|
return wrtBigUInt64BE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff'))
|
|
})
|
|
|
|
Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) {
|
|
const limit = Math.pow(2, (8 * byteLength) - 1)
|
|
|
|
checkInt(this, value, offset, byteLength, limit - 1, -limit)
|
|
}
|
|
|
|
let i = 0
|
|
let mul = 1
|
|
let sub = 0
|
|
this[offset] = value & 0xFF
|
|
while (++i < byteLength && (mul *= 0x100)) {
|
|
if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
|
|
sub = 1
|
|
}
|
|
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
|
|
}
|
|
|
|
return offset + byteLength
|
|
}
|
|
|
|
Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) {
|
|
const limit = Math.pow(2, (8 * byteLength) - 1)
|
|
|
|
checkInt(this, value, offset, byteLength, limit - 1, -limit)
|
|
}
|
|
|
|
let i = byteLength - 1
|
|
let mul = 1
|
|
let sub = 0
|
|
this[offset + i] = value & 0xFF
|
|
while (--i >= 0 && (mul *= 0x100)) {
|
|
if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
|
|
sub = 1
|
|
}
|
|
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
|
|
}
|
|
|
|
return offset + byteLength
|
|
}
|
|
|
|
Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
|
|
if (value < 0) value = 0xff + value + 1
|
|
this[offset] = (value & 0xff)
|
|
return offset + 1
|
|
}
|
|
|
|
Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
return offset + 2
|
|
}
|
|
|
|
Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
|
|
this[offset] = (value >>> 8)
|
|
this[offset + 1] = (value & 0xff)
|
|
return offset + 2
|
|
}
|
|
|
|
Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
this[offset + 2] = (value >>> 16)
|
|
this[offset + 3] = (value >>> 24)
|
|
return offset + 4
|
|
}
|
|
|
|
Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
|
|
if (value < 0) value = 0xffffffff + value + 1
|
|
this[offset] = (value >>> 24)
|
|
this[offset + 1] = (value >>> 16)
|
|
this[offset + 2] = (value >>> 8)
|
|
this[offset + 3] = (value & 0xff)
|
|
return offset + 4
|
|
}
|
|
|
|
Buffer.prototype.writeBigInt64LE = defineBigIntMethod(function writeBigInt64LE (value, offset = 0) {
|
|
return wrtBigUInt64LE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff'))
|
|
})
|
|
|
|
Buffer.prototype.writeBigInt64BE = defineBigIntMethod(function writeBigInt64BE (value, offset = 0) {
|
|
return wrtBigUInt64BE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff'))
|
|
})
|
|
|
|
function checkIEEE754 (buf, value, offset, ext, max, min) {
|
|
if (offset + ext > buf.length) throw new RangeError('Index out of range')
|
|
if (offset < 0) throw new RangeError('Index out of range')
|
|
}
|
|
|
|
function writeFloat (buf, value, offset, littleEndian, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) {
|
|
checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
|
|
}
|
|
ieee754.write(buf, value, offset, littleEndian, 23, 4)
|
|
return offset + 4
|
|
}
|
|
|
|
Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
|
|
return writeFloat(this, value, offset, true, noAssert)
|
|
}
|
|
|
|
Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
|
|
return writeFloat(this, value, offset, false, noAssert)
|
|
}
|
|
|
|
function writeDouble (buf, value, offset, littleEndian, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) {
|
|
checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
|
|
}
|
|
ieee754.write(buf, value, offset, littleEndian, 52, 8)
|
|
return offset + 8
|
|
}
|
|
|
|
Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
|
|
return writeDouble(this, value, offset, true, noAssert)
|
|
}
|
|
|
|
Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
|
|
return writeDouble(this, value, offset, false, noAssert)
|
|
}
|
|
|
|
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
|
|
Buffer.prototype.copy = function copy (target, targetStart, start, end) {
|
|
if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer')
|
|
if (!start) start = 0
|
|
if (!end && end !== 0) end = this.length
|
|
if (targetStart >= target.length) targetStart = target.length
|
|
if (!targetStart) targetStart = 0
|
|
if (end > 0 && end < start) end = start
|
|
|
|
// Copy 0 bytes; we're done
|
|
if (end === start) return 0
|
|
if (target.length === 0 || this.length === 0) return 0
|
|
|
|
// Fatal error conditions
|
|
if (targetStart < 0) {
|
|
throw new RangeError('targetStart out of bounds')
|
|
}
|
|
if (start < 0 || start >= this.length) throw new RangeError('Index out of range')
|
|
if (end < 0) throw new RangeError('sourceEnd out of bounds')
|
|
|
|
// Are we oob?
|
|
if (end > this.length) end = this.length
|
|
if (target.length - targetStart < end - start) {
|
|
end = target.length - targetStart + start
|
|
}
|
|
|
|
const len = end - start
|
|
|
|
if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') {
|
|
// Use built-in when available, missing from IE11
|
|
this.copyWithin(targetStart, start, end)
|
|
} else {
|
|
Uint8Array.prototype.set.call(
|
|
target,
|
|
this.subarray(start, end),
|
|
targetStart
|
|
)
|
|
}
|
|
|
|
return len
|
|
}
|
|
|
|
// Usage:
|
|
// buffer.fill(number[, offset[, end]])
|
|
// buffer.fill(buffer[, offset[, end]])
|
|
// buffer.fill(string[, offset[, end]][, encoding])
|
|
Buffer.prototype.fill = function fill (val, start, end, encoding) {
|
|
// Handle string cases:
|
|
if (typeof val === 'string') {
|
|
if (typeof start === 'string') {
|
|
encoding = start
|
|
start = 0
|
|
end = this.length
|
|
} else if (typeof end === 'string') {
|
|
encoding = end
|
|
end = this.length
|
|
}
|
|
if (encoding !== undefined && typeof encoding !== 'string') {
|
|
throw new TypeError('encoding must be a string')
|
|
}
|
|
if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
|
|
throw new TypeError('Unknown encoding: ' + encoding)
|
|
}
|
|
if (val.length === 1) {
|
|
const code = val.charCodeAt(0)
|
|
if ((encoding === 'utf8' && code < 128) ||
|
|
encoding === 'latin1') {
|
|
// Fast path: If `val` fits into a single byte, use that numeric value.
|
|
val = code
|
|
}
|
|
}
|
|
} else if (typeof val === 'number') {
|
|
val = val & 255
|
|
} else if (typeof val === 'boolean') {
|
|
val = Number(val)
|
|
}
|
|
|
|
// Invalid ranges are not set to a default, so can range check early.
|
|
if (start < 0 || this.length < start || this.length < end) {
|
|
throw new RangeError('Out of range index')
|
|
}
|
|
|
|
if (end <= start) {
|
|
return this
|
|
}
|
|
|
|
start = start >>> 0
|
|
end = end === undefined ? this.length : end >>> 0
|
|
|
|
if (!val) val = 0
|
|
|
|
let i
|
|
if (typeof val === 'number') {
|
|
for (i = start; i < end; ++i) {
|
|
this[i] = val
|
|
}
|
|
} else {
|
|
const bytes = Buffer.isBuffer(val)
|
|
? val
|
|
: Buffer.from(val, encoding)
|
|
const len = bytes.length
|
|
if (len === 0) {
|
|
throw new TypeError('The value "' + val +
|
|
'" is invalid for argument "value"')
|
|
}
|
|
for (i = 0; i < end - start; ++i) {
|
|
this[i + start] = bytes[i % len]
|
|
}
|
|
}
|
|
|
|
return this
|
|
}
|
|
|
|
// CUSTOM ERRORS
|
|
// =============
|
|
|
|
// Simplified versions from Node, changed for Buffer-only usage
|
|
const errors = {}
|
|
function E (sym, getMessage, Base) {
|
|
errors[sym] = class NodeError extends Base {
|
|
constructor () {
|
|
super()
|
|
|
|
Object.defineProperty(this, 'message', {
|
|
value: getMessage.apply(this, arguments),
|
|
writable: true,
|
|
configurable: true
|
|
})
|
|
|
|
// Add the error code to the name to include it in the stack trace.
|
|
this.name = `${this.name} [${sym}]`
|
|
// Access the stack to generate the error message including the error code
|
|
// from the name.
|
|
this.stack // eslint-disable-line no-unused-expressions
|
|
// Reset the name to the actual name.
|
|
delete this.name
|
|
}
|
|
|
|
get code () {
|
|
return sym
|
|
}
|
|
|
|
set code (value) {
|
|
Object.defineProperty(this, 'code', {
|
|
configurable: true,
|
|
enumerable: true,
|
|
value,
|
|
writable: true
|
|
})
|
|
}
|
|
|
|
toString () {
|
|
return `${this.name} [${sym}]: ${this.message}`
|
|
}
|
|
}
|
|
}
|
|
|
|
E('ERR_BUFFER_OUT_OF_BOUNDS',
|
|
function (name) {
|
|
if (name) {
|
|
return `${name} is outside of buffer bounds`
|
|
}
|
|
|
|
return 'Attempt to access memory outside buffer bounds'
|
|
}, RangeError)
|
|
E('ERR_INVALID_ARG_TYPE',
|
|
function (name, actual) {
|
|
return `The "${name}" argument must be of type number. Received type ${typeof actual}`
|
|
}, TypeError)
|
|
E('ERR_OUT_OF_RANGE',
|
|
function (str, range, input) {
|
|
let msg = `The value of "${str}" is out of range.`
|
|
let received = input
|
|
if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) {
|
|
received = addNumericalSeparator(String(input))
|
|
} else if (typeof input === 'bigint') {
|
|
received = String(input)
|
|
if (input > BigInt(2) ** BigInt(32) || input < -(BigInt(2) ** BigInt(32))) {
|
|
received = addNumericalSeparator(received)
|
|
}
|
|
received += 'n'
|
|
}
|
|
msg += ` It must be ${range}. Received ${received}`
|
|
return msg
|
|
}, RangeError)
|
|
|
|
function addNumericalSeparator (val) {
|
|
let res = ''
|
|
let i = val.length
|
|
const start = val[0] === '-' ? 1 : 0
|
|
for (; i >= start + 4; i -= 3) {
|
|
res = `_${val.slice(i - 3, i)}${res}`
|
|
}
|
|
return `${val.slice(0, i)}${res}`
|
|
}
|
|
|
|
// CHECK FUNCTIONS
|
|
// ===============
|
|
|
|
function checkBounds (buf, offset, byteLength) {
|
|
validateNumber(offset, 'offset')
|
|
if (buf[offset] === undefined || buf[offset + byteLength] === undefined) {
|
|
boundsError(offset, buf.length - (byteLength + 1))
|
|
}
|
|
}
|
|
|
|
function checkIntBI (value, min, max, buf, offset, byteLength) {
|
|
if (value > max || value < min) {
|
|
const n = typeof min === 'bigint' ? 'n' : ''
|
|
let range
|
|
if (byteLength > 3) {
|
|
if (min === 0 || min === BigInt(0)) {
|
|
range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`
|
|
} else {
|
|
range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and < 2 ** ` +
|
|
`${(byteLength + 1) * 8 - 1}${n}`
|
|
}
|
|
} else {
|
|
range = `>= ${min}${n} and <= ${max}${n}`
|
|
}
|
|
throw new errors.ERR_OUT_OF_RANGE('value', range, value)
|
|
}
|
|
checkBounds(buf, offset, byteLength)
|
|
}
|
|
|
|
function validateNumber (value, name) {
|
|
if (typeof value !== 'number') {
|
|
throw new errors.ERR_INVALID_ARG_TYPE(name, 'number', value)
|
|
}
|
|
}
|
|
|
|
function boundsError (value, length, type) {
|
|
if (Math.floor(value) !== value) {
|
|
validateNumber(value, type)
|
|
throw new errors.ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value)
|
|
}
|
|
|
|
if (length < 0) {
|
|
throw new errors.ERR_BUFFER_OUT_OF_BOUNDS()
|
|
}
|
|
|
|
throw new errors.ERR_OUT_OF_RANGE(type || 'offset',
|
|
`>= ${type ? 1 : 0} and <= ${length}`,
|
|
value)
|
|
}
|
|
|
|
// HELPER FUNCTIONS
|
|
// ================
|
|
|
|
const INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g
|
|
|
|
function base64clean (str) {
|
|
// Node takes equal signs as end of the Base64 encoding
|
|
str = str.split('=')[0]
|
|
// Node strips out invalid characters like \n and \t from the string, base64-js does not
|
|
str = str.trim().replace(INVALID_BASE64_RE, '')
|
|
// Node converts strings with length < 2 to ''
|
|
if (str.length < 2) return ''
|
|
// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
|
|
while (str.length % 4 !== 0) {
|
|
str = str + '='
|
|
}
|
|
return str
|
|
}
|
|
|
|
function utf8ToBytes (string, units) {
|
|
units = units || Infinity
|
|
let codePoint
|
|
const length = string.length
|
|
let leadSurrogate = null
|
|
const bytes = []
|
|
|
|
for (let i = 0; i < length; ++i) {
|
|
codePoint = string.charCodeAt(i)
|
|
|
|
// is surrogate component
|
|
if (codePoint > 0xD7FF && codePoint < 0xE000) {
|
|
// last char was a lead
|
|
if (!leadSurrogate) {
|
|
// no lead yet
|
|
if (codePoint > 0xDBFF) {
|
|
// unexpected trail
|
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
|
continue
|
|
} else if (i + 1 === length) {
|
|
// unpaired lead
|
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
|
continue
|
|
}
|
|
|
|
// valid lead
|
|
leadSurrogate = codePoint
|
|
|
|
continue
|
|
}
|
|
|
|
// 2 leads in a row
|
|
if (codePoint < 0xDC00) {
|
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
|
leadSurrogate = codePoint
|
|
continue
|
|
}
|
|
|
|
// valid surrogate pair
|
|
codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
|
|
} else if (leadSurrogate) {
|
|
// valid bmp char, but last char was a lead
|
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
|
}
|
|
|
|
leadSurrogate = null
|
|
|
|
// encode utf8
|
|
if (codePoint < 0x80) {
|
|
if ((units -= 1) < 0) break
|
|
bytes.push(codePoint)
|
|
} else if (codePoint < 0x800) {
|
|
if ((units -= 2) < 0) break
|
|
bytes.push(
|
|
codePoint >> 0x6 | 0xC0,
|
|
codePoint & 0x3F | 0x80
|
|
)
|
|
} else if (codePoint < 0x10000) {
|
|
if ((units -= 3) < 0) break
|
|
bytes.push(
|
|
codePoint >> 0xC | 0xE0,
|
|
codePoint >> 0x6 & 0x3F | 0x80,
|
|
codePoint & 0x3F | 0x80
|
|
)
|
|
} else if (codePoint < 0x110000) {
|
|
if ((units -= 4) < 0) break
|
|
bytes.push(
|
|
codePoint >> 0x12 | 0xF0,
|
|
codePoint >> 0xC & 0x3F | 0x80,
|
|
codePoint >> 0x6 & 0x3F | 0x80,
|
|
codePoint & 0x3F | 0x80
|
|
)
|
|
} else {
|
|
throw new Error('Invalid code point')
|
|
}
|
|
}
|
|
|
|
return bytes
|
|
}
|
|
|
|
function asciiToBytes (str) {
|
|
const byteArray = []
|
|
for (let i = 0; i < str.length; ++i) {
|
|
// Node's code seems to be doing this and not & 0x7F..
|
|
byteArray.push(str.charCodeAt(i) & 0xFF)
|
|
}
|
|
return byteArray
|
|
}
|
|
|
|
function utf16leToBytes (str, units) {
|
|
let c, hi, lo
|
|
const byteArray = []
|
|
for (let i = 0; i < str.length; ++i) {
|
|
if ((units -= 2) < 0) break
|
|
|
|
c = str.charCodeAt(i)
|
|
hi = c >> 8
|
|
lo = c % 256
|
|
byteArray.push(lo)
|
|
byteArray.push(hi)
|
|
}
|
|
|
|
return byteArray
|
|
}
|
|
|
|
function base64ToBytes (str) {
|
|
return base64.toByteArray(base64clean(str))
|
|
}
|
|
|
|
function blitBuffer (src, dst, offset, length) {
|
|
let i
|
|
for (i = 0; i < length; ++i) {
|
|
if ((i + offset >= dst.length) || (i >= src.length)) break
|
|
dst[i + offset] = src[i]
|
|
}
|
|
return i
|
|
}
|
|
|
|
// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass
|
|
// the `instanceof` check but they should be treated as of that type.
|
|
// See: https://github.com/feross/buffer/issues/166
|
|
function isInstance (obj, type) {
|
|
return obj instanceof type ||
|
|
(obj != null && obj.constructor != null && obj.constructor.name != null &&
|
|
obj.constructor.name === type.name)
|
|
}
|
|
function numberIsNaN (obj) {
|
|
// For IE11 support
|
|
return obj !== obj // eslint-disable-line no-self-compare
|
|
}
|
|
|
|
// Create lookup table for `toString('hex')`
|
|
// See: https://github.com/feross/buffer/issues/219
|
|
const hexSliceLookupTable = (function () {
|
|
const alphabet = '0123456789abcdef'
|
|
const table = new Array(256)
|
|
for (let i = 0; i < 16; ++i) {
|
|
const i16 = i * 16
|
|
for (let j = 0; j < 16; ++j) {
|
|
table[i16 + j] = alphabet[i] + alphabet[j]
|
|
}
|
|
}
|
|
return table
|
|
})()
|
|
|
|
// Return not function with Error if BigInt not supported
|
|
function defineBigIntMethod (fn) {
|
|
return typeof BigInt === 'undefined' ? BufferBigIntNotDefined : fn
|
|
}
|
|
|
|
function BufferBigIntNotDefined () {
|
|
throw new Error('BigInt not supported')
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/builtin-status-codes/browser.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/builtin-status-codes/browser.js ***!
|
|
\******************************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = {
|
|
"100": "Continue",
|
|
"101": "Switching Protocols",
|
|
"102": "Processing",
|
|
"200": "OK",
|
|
"201": "Created",
|
|
"202": "Accepted",
|
|
"203": "Non-Authoritative Information",
|
|
"204": "No Content",
|
|
"205": "Reset Content",
|
|
"206": "Partial Content",
|
|
"207": "Multi-Status",
|
|
"208": "Already Reported",
|
|
"226": "IM Used",
|
|
"300": "Multiple Choices",
|
|
"301": "Moved Permanently",
|
|
"302": "Found",
|
|
"303": "See Other",
|
|
"304": "Not Modified",
|
|
"305": "Use Proxy",
|
|
"307": "Temporary Redirect",
|
|
"308": "Permanent Redirect",
|
|
"400": "Bad Request",
|
|
"401": "Unauthorized",
|
|
"402": "Payment Required",
|
|
"403": "Forbidden",
|
|
"404": "Not Found",
|
|
"405": "Method Not Allowed",
|
|
"406": "Not Acceptable",
|
|
"407": "Proxy Authentication Required",
|
|
"408": "Request Timeout",
|
|
"409": "Conflict",
|
|
"410": "Gone",
|
|
"411": "Length Required",
|
|
"412": "Precondition Failed",
|
|
"413": "Payload Too Large",
|
|
"414": "URI Too Long",
|
|
"415": "Unsupported Media Type",
|
|
"416": "Range Not Satisfiable",
|
|
"417": "Expectation Failed",
|
|
"418": "I'm a teapot",
|
|
"421": "Misdirected Request",
|
|
"422": "Unprocessable Entity",
|
|
"423": "Locked",
|
|
"424": "Failed Dependency",
|
|
"425": "Unordered Collection",
|
|
"426": "Upgrade Required",
|
|
"428": "Precondition Required",
|
|
"429": "Too Many Requests",
|
|
"431": "Request Header Fields Too Large",
|
|
"451": "Unavailable For Legal Reasons",
|
|
"500": "Internal Server Error",
|
|
"501": "Not Implemented",
|
|
"502": "Bad Gateway",
|
|
"503": "Service Unavailable",
|
|
"504": "Gateway Timeout",
|
|
"505": "HTTP Version Not Supported",
|
|
"506": "Variant Also Negotiates",
|
|
"507": "Insufficient Storage",
|
|
"508": "Loop Detected",
|
|
"509": "Bandwidth Limit Exceeded",
|
|
"510": "Not Extended",
|
|
"511": "Network Authentication Required"
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/cache-chunk-store/index.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/cache-chunk-store/index.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*! cache-chunk-store. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
const LRU = __webpack_require__(/*! lru */ "./node_modules/lru/index.js")
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
|
|
class CacheStore {
|
|
constructor (store, opts) {
|
|
this.store = store
|
|
this.chunkLength = store.chunkLength
|
|
this.inProgressGets = new Map() // Map from chunk index to info on callbacks waiting for that chunk
|
|
|
|
if (!this.store || !this.store.get || !this.store.put) {
|
|
throw new Error('First argument must be abstract-chunk-store compliant')
|
|
}
|
|
|
|
this.cache = new LRU(opts)
|
|
}
|
|
|
|
put (index, buf, cb = () => {}) {
|
|
if (!this.cache) {
|
|
return queueMicrotask(() => cb(new Error('CacheStore closed')))
|
|
}
|
|
|
|
this.cache.remove(index)
|
|
this.store.put(index, buf, cb)
|
|
}
|
|
|
|
get (index, opts, cb = () => {}) {
|
|
if (typeof opts === 'function') return this.get(index, null, opts)
|
|
|
|
if (!this.cache) {
|
|
return queueMicrotask(() => cb(new Error('CacheStore closed')))
|
|
}
|
|
|
|
if (!opts) opts = {}
|
|
|
|
let buf = this.cache.get(index)
|
|
if (buf) {
|
|
const offset = opts.offset || 0
|
|
const len = opts.length || (buf.length - offset)
|
|
if (offset !== 0 || len !== buf.length) {
|
|
buf = buf.slice(offset, len + offset)
|
|
}
|
|
return queueMicrotask(() => cb(null, buf))
|
|
}
|
|
|
|
// See if a get for this index has already started
|
|
let waiters = this.inProgressGets.get(index)
|
|
const getAlreadyStarted = !!waiters
|
|
if (!waiters) {
|
|
waiters = []
|
|
this.inProgressGets.set(index, waiters)
|
|
}
|
|
|
|
waiters.push({
|
|
opts,
|
|
cb
|
|
})
|
|
|
|
if (!getAlreadyStarted) {
|
|
this.store.get(index, (err, buf) => {
|
|
if (!err && this.cache != null) this.cache.set(index, buf)
|
|
|
|
const inProgressEntry = this.inProgressGets.get(index)
|
|
this.inProgressGets.delete(index)
|
|
|
|
for (const { opts, cb } of inProgressEntry) {
|
|
if (err) {
|
|
cb(err)
|
|
} else {
|
|
const offset = opts.offset || 0
|
|
const len = opts.length || (buf.length - offset)
|
|
let slicedBuf = buf
|
|
if (offset !== 0 || len !== buf.length) {
|
|
slicedBuf = buf.slice(offset, len + offset)
|
|
}
|
|
cb(null, slicedBuf)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
close (cb = () => {}) {
|
|
if (!this.cache) {
|
|
return queueMicrotask(() => cb(new Error('CacheStore closed')))
|
|
}
|
|
|
|
this.cache = null
|
|
this.store.close(cb)
|
|
}
|
|
|
|
destroy (cb = () => {}) {
|
|
if (!this.cache) {
|
|
return queueMicrotask(() => cb(new Error('CacheStore closed')))
|
|
}
|
|
|
|
this.cache = null
|
|
this.store.destroy(cb)
|
|
}
|
|
}
|
|
|
|
module.exports = CacheStore
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/call-bind/callBound.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/call-bind/callBound.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var GetIntrinsic = __webpack_require__(/*! get-intrinsic */ "./node_modules/get-intrinsic/index.js");
|
|
|
|
var callBind = __webpack_require__(/*! ./ */ "./node_modules/call-bind/index.js");
|
|
|
|
var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf'));
|
|
|
|
module.exports = function callBoundIntrinsic(name, allowMissing) {
|
|
var intrinsic = GetIntrinsic(name, !!allowMissing);
|
|
if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {
|
|
return callBind(intrinsic);
|
|
}
|
|
return intrinsic;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/call-bind/index.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/call-bind/index.js ***!
|
|
\*****************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var bind = __webpack_require__(/*! function-bind */ "./node_modules/function-bind/index.js");
|
|
var GetIntrinsic = __webpack_require__(/*! get-intrinsic */ "./node_modules/get-intrinsic/index.js");
|
|
|
|
var $apply = GetIntrinsic('%Function.prototype.apply%');
|
|
var $call = GetIntrinsic('%Function.prototype.call%');
|
|
var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply);
|
|
|
|
var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true);
|
|
var $defineProperty = GetIntrinsic('%Object.defineProperty%', true);
|
|
var $max = GetIntrinsic('%Math.max%');
|
|
|
|
if ($defineProperty) {
|
|
try {
|
|
$defineProperty({}, 'a', { value: 1 });
|
|
} catch (e) {
|
|
// IE 8 has a broken defineProperty
|
|
$defineProperty = null;
|
|
}
|
|
}
|
|
|
|
module.exports = function callBind(originalFunction) {
|
|
var func = $reflectApply(bind, $call, arguments);
|
|
if ($gOPD && $defineProperty) {
|
|
var desc = $gOPD(func, 'length');
|
|
if (desc.configurable) {
|
|
// original length, plus the receiver, minus any additional arguments (after the receiver)
|
|
$defineProperty(
|
|
func,
|
|
'length',
|
|
{ value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) }
|
|
);
|
|
}
|
|
}
|
|
return func;
|
|
};
|
|
|
|
var applyBind = function applyBind() {
|
|
return $reflectApply(bind, $apply, arguments);
|
|
};
|
|
|
|
if ($defineProperty) {
|
|
$defineProperty(module.exports, 'apply', { value: applyBind });
|
|
} else {
|
|
module.exports.apply = applyBind;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/chunk-store-stream/write.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/chunk-store-stream/write.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const BlockStream = __webpack_require__(/*! block-stream2 */ "./node_modules/block-stream2/index.js")
|
|
const stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
|
|
class ChunkStoreWriteStream extends stream.Writable {
|
|
constructor (store, chunkLength, opts = {}) {
|
|
super(opts)
|
|
|
|
if (!store || !store.put || !store.get) {
|
|
throw new Error('First argument must be an abstract-chunk-store compliant store')
|
|
}
|
|
chunkLength = Number(chunkLength)
|
|
if (!chunkLength) throw new Error('Second argument must be a chunk length')
|
|
|
|
const zeroPadding = opts.zeroPadding === undefined ? false : opts.zeroPadding
|
|
this._blockstream = new BlockStream(chunkLength, { ...opts, zeroPadding })
|
|
this._outstandingPuts = 0
|
|
this._storeMaxOutstandingPuts = opts.storeMaxOutstandingPuts || 16
|
|
|
|
let index = 0
|
|
const onData = chunk => {
|
|
if (this.destroyed) return
|
|
|
|
this._outstandingPuts += 1
|
|
if (this._outstandingPuts >= this._storeMaxOutstandingPuts) {
|
|
this._blockstream.pause()
|
|
}
|
|
store.put(index, chunk, (err) => {
|
|
if (err) return this.destroy(err)
|
|
this._outstandingPuts -= 1
|
|
if (this._outstandingPuts < this._storeMaxOutstandingPuts) {
|
|
this._blockstream.resume()
|
|
}
|
|
if (this._outstandingPuts === 0 && typeof this._finalCb === 'function') {
|
|
this._finalCb(null)
|
|
this._finalCb = null
|
|
}
|
|
})
|
|
index += 1
|
|
}
|
|
|
|
this._blockstream
|
|
.on('data', onData)
|
|
.on('error', err => { this.destroy(err) })
|
|
}
|
|
|
|
_write (chunk, encoding, callback) {
|
|
this._blockstream.write(chunk, encoding, callback)
|
|
}
|
|
|
|
_final (cb) {
|
|
this._blockstream.end()
|
|
this._blockstream.once('end', () => {
|
|
if (this._outstandingPuts === 0) cb(null)
|
|
else this._finalCb = cb
|
|
})
|
|
}
|
|
|
|
destroy (err) {
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
|
|
if (err) this.emit('error', err)
|
|
this.emit('close')
|
|
}
|
|
}
|
|
|
|
module.exports = ChunkStoreWriteStream
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/cipher-base/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/cipher-base/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var Transform = __webpack_require__(/*! stream */ "./node_modules/stream-browserify/index.js").Transform
|
|
var StringDecoder = __webpack_require__(/*! string_decoder */ "./node_modules/string_decoder/lib/string_decoder.js").StringDecoder
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
|
|
function CipherBase (hashMode) {
|
|
Transform.call(this)
|
|
this.hashMode = typeof hashMode === 'string'
|
|
if (this.hashMode) {
|
|
this[hashMode] = this._finalOrDigest
|
|
} else {
|
|
this.final = this._finalOrDigest
|
|
}
|
|
if (this._final) {
|
|
this.__final = this._final
|
|
this._final = null
|
|
}
|
|
this._decoder = null
|
|
this._encoding = null
|
|
}
|
|
inherits(CipherBase, Transform)
|
|
|
|
CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
|
|
if (typeof data === 'string') {
|
|
data = Buffer.from(data, inputEnc)
|
|
}
|
|
|
|
var outData = this._update(data)
|
|
if (this.hashMode) return this
|
|
|
|
if (outputEnc) {
|
|
outData = this._toString(outData, outputEnc)
|
|
}
|
|
|
|
return outData
|
|
}
|
|
|
|
CipherBase.prototype.setAutoPadding = function () {}
|
|
CipherBase.prototype.getAuthTag = function () {
|
|
throw new Error('trying to get auth tag in unsupported state')
|
|
}
|
|
|
|
CipherBase.prototype.setAuthTag = function () {
|
|
throw new Error('trying to set auth tag in unsupported state')
|
|
}
|
|
|
|
CipherBase.prototype.setAAD = function () {
|
|
throw new Error('trying to set aad in unsupported state')
|
|
}
|
|
|
|
CipherBase.prototype._transform = function (data, _, next) {
|
|
var err
|
|
try {
|
|
if (this.hashMode) {
|
|
this._update(data)
|
|
} else {
|
|
this.push(this._update(data))
|
|
}
|
|
} catch (e) {
|
|
err = e
|
|
} finally {
|
|
next(err)
|
|
}
|
|
}
|
|
CipherBase.prototype._flush = function (done) {
|
|
var err
|
|
try {
|
|
this.push(this.__final())
|
|
} catch (e) {
|
|
err = e
|
|
}
|
|
|
|
done(err)
|
|
}
|
|
CipherBase.prototype._finalOrDigest = function (outputEnc) {
|
|
var outData = this.__final() || Buffer.alloc(0)
|
|
if (outputEnc) {
|
|
outData = this._toString(outData, outputEnc, true)
|
|
}
|
|
return outData
|
|
}
|
|
|
|
CipherBase.prototype._toString = function (value, enc, fin) {
|
|
if (!this._decoder) {
|
|
this._decoder = new StringDecoder(enc)
|
|
this._encoding = enc
|
|
}
|
|
|
|
if (this._encoding !== enc) throw new Error('can\'t switch encodings')
|
|
|
|
var out = this._decoder.write(value)
|
|
if (fin) {
|
|
out += this._decoder.end()
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
module.exports = CipherBase
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/console-browserify/index.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/console-browserify/index.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*global window, global*/
|
|
var util = __webpack_require__(/*! util */ "./node_modules/util/util.js")
|
|
var assert = __webpack_require__(/*! assert */ "./node_modules/assert/build/assert.js")
|
|
function now() { return new Date().getTime() }
|
|
|
|
var slice = Array.prototype.slice
|
|
var console
|
|
var times = {}
|
|
|
|
if (typeof __webpack_require__.g !== "undefined" && __webpack_require__.g.console) {
|
|
console = __webpack_require__.g.console
|
|
} else if (typeof window !== "undefined" && window.console) {
|
|
console = window.console
|
|
} else {
|
|
console = {}
|
|
}
|
|
|
|
var functions = [
|
|
[log, "log"],
|
|
[info, "info"],
|
|
[warn, "warn"],
|
|
[error, "error"],
|
|
[time, "time"],
|
|
[timeEnd, "timeEnd"],
|
|
[trace, "trace"],
|
|
[dir, "dir"],
|
|
[consoleAssert, "assert"]
|
|
]
|
|
|
|
for (var i = 0; i < functions.length; i++) {
|
|
var tuple = functions[i]
|
|
var f = tuple[0]
|
|
var name = tuple[1]
|
|
|
|
if (!console[name]) {
|
|
console[name] = f
|
|
}
|
|
}
|
|
|
|
module.exports = console
|
|
|
|
function log() {}
|
|
|
|
function info() {
|
|
console.log.apply(console, arguments)
|
|
}
|
|
|
|
function warn() {
|
|
console.log.apply(console, arguments)
|
|
}
|
|
|
|
function error() {
|
|
console.warn.apply(console, arguments)
|
|
}
|
|
|
|
function time(label) {
|
|
times[label] = now()
|
|
}
|
|
|
|
function timeEnd(label) {
|
|
var time = times[label]
|
|
if (!time) {
|
|
throw new Error("No such label: " + label)
|
|
}
|
|
|
|
delete times[label]
|
|
var duration = now() - time
|
|
console.log(label + ": " + duration + "ms")
|
|
}
|
|
|
|
function trace() {
|
|
var err = new Error()
|
|
err.name = "Trace"
|
|
err.message = util.format.apply(null, arguments)
|
|
console.error(err.stack)
|
|
}
|
|
|
|
function dir(object) {
|
|
console.log(util.inspect(object) + "\n")
|
|
}
|
|
|
|
function consoleAssert(expression) {
|
|
if (!expression) {
|
|
var arr = slice.call(arguments, 1)
|
|
assert.ok(false, util.format.apply(null, arr))
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/cpus/browser.js":
|
|
/*!**************************************!*\
|
|
!*** ./node_modules/cpus/browser.js ***!
|
|
\**************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = function cpus () {
|
|
var num = navigator.hardwareConcurrency || 1
|
|
var cpus = []
|
|
for (var i = 0; i < num; i++) {
|
|
cpus.push({
|
|
model: '',
|
|
speed: 0,
|
|
times: { user: 0, nice: 0, sys: 0, idle: 0, irq: 0 }
|
|
})
|
|
}
|
|
return cpus
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/create-ecdh/browser.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/create-ecdh/browser.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
var elliptic = __webpack_require__(/*! elliptic */ "./node_modules/elliptic/lib/elliptic.js")
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/create-ecdh/node_modules/bn.js/lib/bn.js")
|
|
|
|
module.exports = function createECDH (curve) {
|
|
return new ECDH(curve)
|
|
}
|
|
|
|
var aliases = {
|
|
secp256k1: {
|
|
name: 'secp256k1',
|
|
byteLength: 32
|
|
},
|
|
secp224r1: {
|
|
name: 'p224',
|
|
byteLength: 28
|
|
},
|
|
prime256v1: {
|
|
name: 'p256',
|
|
byteLength: 32
|
|
},
|
|
prime192v1: {
|
|
name: 'p192',
|
|
byteLength: 24
|
|
},
|
|
ed25519: {
|
|
name: 'ed25519',
|
|
byteLength: 32
|
|
},
|
|
secp384r1: {
|
|
name: 'p384',
|
|
byteLength: 48
|
|
},
|
|
secp521r1: {
|
|
name: 'p521',
|
|
byteLength: 66
|
|
}
|
|
}
|
|
|
|
aliases.p224 = aliases.secp224r1
|
|
aliases.p256 = aliases.secp256r1 = aliases.prime256v1
|
|
aliases.p192 = aliases.secp192r1 = aliases.prime192v1
|
|
aliases.p384 = aliases.secp384r1
|
|
aliases.p521 = aliases.secp521r1
|
|
|
|
function ECDH (curve) {
|
|
this.curveType = aliases[curve]
|
|
if (!this.curveType) {
|
|
this.curveType = {
|
|
name: curve
|
|
}
|
|
}
|
|
this.curve = new elliptic.ec(this.curveType.name) // eslint-disable-line new-cap
|
|
this.keys = void 0
|
|
}
|
|
|
|
ECDH.prototype.generateKeys = function (enc, format) {
|
|
this.keys = this.curve.genKeyPair()
|
|
return this.getPublicKey(enc, format)
|
|
}
|
|
|
|
ECDH.prototype.computeSecret = function (other, inenc, enc) {
|
|
inenc = inenc || 'utf8'
|
|
if (!Buffer.isBuffer(other)) {
|
|
other = new Buffer(other, inenc)
|
|
}
|
|
var otherPub = this.curve.keyFromPublic(other).getPublic()
|
|
var out = otherPub.mul(this.keys.getPrivate()).getX()
|
|
return formatReturnValue(out, enc, this.curveType.byteLength)
|
|
}
|
|
|
|
ECDH.prototype.getPublicKey = function (enc, format) {
|
|
var key = this.keys.getPublic(format === 'compressed', true)
|
|
if (format === 'hybrid') {
|
|
if (key[key.length - 1] % 2) {
|
|
key[0] = 7
|
|
} else {
|
|
key[0] = 6
|
|
}
|
|
}
|
|
return formatReturnValue(key, enc)
|
|
}
|
|
|
|
ECDH.prototype.getPrivateKey = function (enc) {
|
|
return formatReturnValue(this.keys.getPrivate(), enc)
|
|
}
|
|
|
|
ECDH.prototype.setPublicKey = function (pub, enc) {
|
|
enc = enc || 'utf8'
|
|
if (!Buffer.isBuffer(pub)) {
|
|
pub = new Buffer(pub, enc)
|
|
}
|
|
this.keys._importPublic(pub)
|
|
return this
|
|
}
|
|
|
|
ECDH.prototype.setPrivateKey = function (priv, enc) {
|
|
enc = enc || 'utf8'
|
|
if (!Buffer.isBuffer(priv)) {
|
|
priv = new Buffer(priv, enc)
|
|
}
|
|
|
|
var _priv = new BN(priv)
|
|
_priv = _priv.toString(16)
|
|
this.keys = this.curve.genKeyPair()
|
|
this.keys._importPrivate(_priv)
|
|
return this
|
|
}
|
|
|
|
function formatReturnValue (bn, enc, len) {
|
|
if (!Array.isArray(bn)) {
|
|
bn = bn.toArray()
|
|
}
|
|
var buf = new Buffer(bn)
|
|
if (len && buf.length < len) {
|
|
var zeros = new Buffer(len - buf.length)
|
|
zeros.fill(0)
|
|
buf = Buffer.concat([zeros, buf])
|
|
}
|
|
if (!enc) {
|
|
return buf
|
|
} else {
|
|
return buf.toString(enc)
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/create-ecdh/node_modules/bn.js/lib/bn.js":
|
|
/*!***************************************************************!*\
|
|
!*** ./node_modules/create-ecdh/node_modules/bn.js/lib/bn.js ***!
|
|
\***************************************************************/
|
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
/* module decorator */ module = __webpack_require__.nmd(module);
|
|
(function (module, exports) {
|
|
'use strict';
|
|
|
|
// Utils
|
|
function assert (val, msg) {
|
|
if (!val) throw new Error(msg || 'Assertion failed');
|
|
}
|
|
|
|
// Could use `inherits` module, but don't want to move from single file
|
|
// architecture yet.
|
|
function inherits (ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
var TempCtor = function () {};
|
|
TempCtor.prototype = superCtor.prototype;
|
|
ctor.prototype = new TempCtor();
|
|
ctor.prototype.constructor = ctor;
|
|
}
|
|
|
|
// BN
|
|
|
|
function BN (number, base, endian) {
|
|
if (BN.isBN(number)) {
|
|
return number;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.words = null;
|
|
this.length = 0;
|
|
|
|
// Reduction context
|
|
this.red = null;
|
|
|
|
if (number !== null) {
|
|
if (base === 'le' || base === 'be') {
|
|
endian = base;
|
|
base = 10;
|
|
}
|
|
|
|
this._init(number || 0, base || 10, endian || 'be');
|
|
}
|
|
}
|
|
if (typeof module === 'object') {
|
|
module.exports = BN;
|
|
} else {
|
|
exports.BN = BN;
|
|
}
|
|
|
|
BN.BN = BN;
|
|
BN.wordSize = 26;
|
|
|
|
var Buffer;
|
|
try {
|
|
if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') {
|
|
Buffer = window.Buffer;
|
|
} else {
|
|
Buffer = __webpack_require__(/*! buffer */ "?4068").Buffer;
|
|
}
|
|
} catch (e) {
|
|
}
|
|
|
|
BN.isBN = function isBN (num) {
|
|
if (num instanceof BN) {
|
|
return true;
|
|
}
|
|
|
|
return num !== null && typeof num === 'object' &&
|
|
num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
|
|
};
|
|
|
|
BN.max = function max (left, right) {
|
|
if (left.cmp(right) > 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.min = function min (left, right) {
|
|
if (left.cmp(right) < 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.prototype._init = function init (number, base, endian) {
|
|
if (typeof number === 'number') {
|
|
return this._initNumber(number, base, endian);
|
|
}
|
|
|
|
if (typeof number === 'object') {
|
|
return this._initArray(number, base, endian);
|
|
}
|
|
|
|
if (base === 'hex') {
|
|
base = 16;
|
|
}
|
|
assert(base === (base | 0) && base >= 2 && base <= 36);
|
|
|
|
number = number.toString().replace(/\s+/g, '');
|
|
var start = 0;
|
|
if (number[0] === '-') {
|
|
start++;
|
|
this.negative = 1;
|
|
}
|
|
|
|
if (start < number.length) {
|
|
if (base === 16) {
|
|
this._parseHex(number, start, endian);
|
|
} else {
|
|
this._parseBase(number, base, start);
|
|
if (endian === 'le') {
|
|
this._initArray(this.toArray(), base, endian);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
BN.prototype._initNumber = function _initNumber (number, base, endian) {
|
|
if (number < 0) {
|
|
this.negative = 1;
|
|
number = -number;
|
|
}
|
|
if (number < 0x4000000) {
|
|
this.words = [ number & 0x3ffffff ];
|
|
this.length = 1;
|
|
} else if (number < 0x10000000000000) {
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff
|
|
];
|
|
this.length = 2;
|
|
} else {
|
|
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff,
|
|
1
|
|
];
|
|
this.length = 3;
|
|
}
|
|
|
|
if (endian !== 'le') return;
|
|
|
|
// Reverse the bytes
|
|
this._initArray(this.toArray(), base, endian);
|
|
};
|
|
|
|
BN.prototype._initArray = function _initArray (number, base, endian) {
|
|
// Perhaps a Uint8Array
|
|
assert(typeof number.length === 'number');
|
|
if (number.length <= 0) {
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
return this;
|
|
}
|
|
|
|
this.length = Math.ceil(number.length / 3);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
var j, w;
|
|
var off = 0;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
|
|
w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
} else if (endian === 'le') {
|
|
for (i = 0, j = 0; i < number.length; i += 3) {
|
|
w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
return this.strip();
|
|
};
|
|
|
|
function parseHex4Bits (string, index) {
|
|
var c = string.charCodeAt(index);
|
|
// 'A' - 'F'
|
|
if (c >= 65 && c <= 70) {
|
|
return c - 55;
|
|
// 'a' - 'f'
|
|
} else if (c >= 97 && c <= 102) {
|
|
return c - 87;
|
|
// '0' - '9'
|
|
} else {
|
|
return (c - 48) & 0xf;
|
|
}
|
|
}
|
|
|
|
function parseHexByte (string, lowerBound, index) {
|
|
var r = parseHex4Bits(string, index);
|
|
if (index - 1 >= lowerBound) {
|
|
r |= parseHex4Bits(string, index - 1) << 4;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseHex = function _parseHex (number, start, endian) {
|
|
// Create possibly bigger array to ensure that it fits the number
|
|
this.length = Math.ceil((number.length - start) / 6);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
// 24-bits chunks
|
|
var off = 0;
|
|
var j = 0;
|
|
|
|
var w;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1; i >= start; i -= 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
} else {
|
|
var parseLength = number.length - start;
|
|
for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
function parseBase (str, start, end, mul) {
|
|
var r = 0;
|
|
var len = Math.min(str.length, end);
|
|
for (var i = start; i < len; i++) {
|
|
var c = str.charCodeAt(i) - 48;
|
|
|
|
r *= mul;
|
|
|
|
// 'a'
|
|
if (c >= 49) {
|
|
r += c - 49 + 0xa;
|
|
|
|
// 'A'
|
|
} else if (c >= 17) {
|
|
r += c - 17 + 0xa;
|
|
|
|
// '0' - '9'
|
|
} else {
|
|
r += c;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseBase = function _parseBase (number, base, start) {
|
|
// Initialize as zero
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
|
|
// Find length of limb in base
|
|
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
|
|
limbLen++;
|
|
}
|
|
limbLen--;
|
|
limbPow = (limbPow / base) | 0;
|
|
|
|
var total = number.length - start;
|
|
var mod = total % limbLen;
|
|
var end = Math.min(total, total - mod) + start;
|
|
|
|
var word = 0;
|
|
for (var i = start; i < end; i += limbLen) {
|
|
word = parseBase(number, i, i + limbLen, base);
|
|
|
|
this.imuln(limbPow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
if (mod !== 0) {
|
|
var pow = 1;
|
|
word = parseBase(number, i, number.length, base);
|
|
|
|
for (i = 0; i < mod; i++) {
|
|
pow *= base;
|
|
}
|
|
|
|
this.imuln(pow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
BN.prototype.copy = function copy (dest) {
|
|
dest.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
dest.words[i] = this.words[i];
|
|
}
|
|
dest.length = this.length;
|
|
dest.negative = this.negative;
|
|
dest.red = this.red;
|
|
};
|
|
|
|
BN.prototype.clone = function clone () {
|
|
var r = new BN(null);
|
|
this.copy(r);
|
|
return r;
|
|
};
|
|
|
|
BN.prototype._expand = function _expand (size) {
|
|
while (this.length < size) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
// Remove leading `0` from `this`
|
|
BN.prototype.strip = function strip () {
|
|
while (this.length > 1 && this.words[this.length - 1] === 0) {
|
|
this.length--;
|
|
}
|
|
return this._normSign();
|
|
};
|
|
|
|
BN.prototype._normSign = function _normSign () {
|
|
// -0 = 0
|
|
if (this.length === 1 && this.words[0] === 0) {
|
|
this.negative = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.inspect = function inspect () {
|
|
return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
|
|
};
|
|
|
|
/*
|
|
|
|
var zeros = [];
|
|
var groupSizes = [];
|
|
var groupBases = [];
|
|
|
|
var s = '';
|
|
var i = -1;
|
|
while (++i < BN.wordSize) {
|
|
zeros[i] = s;
|
|
s += '0';
|
|
}
|
|
groupSizes[0] = 0;
|
|
groupSizes[1] = 0;
|
|
groupBases[0] = 0;
|
|
groupBases[1] = 0;
|
|
var base = 2 - 1;
|
|
while (++base < 36 + 1) {
|
|
var groupSize = 0;
|
|
var groupBase = 1;
|
|
while (groupBase < (1 << BN.wordSize) / base) {
|
|
groupBase *= base;
|
|
groupSize += 1;
|
|
}
|
|
groupSizes[base] = groupSize;
|
|
groupBases[base] = groupBase;
|
|
}
|
|
|
|
*/
|
|
|
|
var zeros = [
|
|
'',
|
|
'0',
|
|
'00',
|
|
'000',
|
|
'0000',
|
|
'00000',
|
|
'000000',
|
|
'0000000',
|
|
'00000000',
|
|
'000000000',
|
|
'0000000000',
|
|
'00000000000',
|
|
'000000000000',
|
|
'0000000000000',
|
|
'00000000000000',
|
|
'000000000000000',
|
|
'0000000000000000',
|
|
'00000000000000000',
|
|
'000000000000000000',
|
|
'0000000000000000000',
|
|
'00000000000000000000',
|
|
'000000000000000000000',
|
|
'0000000000000000000000',
|
|
'00000000000000000000000',
|
|
'000000000000000000000000',
|
|
'0000000000000000000000000'
|
|
];
|
|
|
|
var groupSizes = [
|
|
0, 0,
|
|
25, 16, 12, 11, 10, 9, 8,
|
|
8, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5
|
|
];
|
|
|
|
var groupBases = [
|
|
0, 0,
|
|
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
|
|
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
|
|
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
|
|
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
|
|
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
|
|
];
|
|
|
|
BN.prototype.toString = function toString (base, padding) {
|
|
base = base || 10;
|
|
padding = padding | 0 || 1;
|
|
|
|
var out;
|
|
if (base === 16 || base === 'hex') {
|
|
out = '';
|
|
var off = 0;
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = this.words[i];
|
|
var word = (((w << off) | carry) & 0xffffff).toString(16);
|
|
carry = (w >>> (24 - off)) & 0xffffff;
|
|
if (carry !== 0 || i !== this.length - 1) {
|
|
out = zeros[6 - word.length] + word + out;
|
|
} else {
|
|
out = word + out;
|
|
}
|
|
off += 2;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
i--;
|
|
}
|
|
}
|
|
if (carry !== 0) {
|
|
out = carry.toString(16) + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
if (base === (base | 0) && base >= 2 && base <= 36) {
|
|
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
|
|
var groupSize = groupSizes[base];
|
|
// var groupBase = Math.pow(base, groupSize);
|
|
var groupBase = groupBases[base];
|
|
out = '';
|
|
var c = this.clone();
|
|
c.negative = 0;
|
|
while (!c.isZero()) {
|
|
var r = c.modn(groupBase).toString(base);
|
|
c = c.idivn(groupBase);
|
|
|
|
if (!c.isZero()) {
|
|
out = zeros[groupSize - r.length] + r + out;
|
|
} else {
|
|
out = r + out;
|
|
}
|
|
}
|
|
if (this.isZero()) {
|
|
out = '0' + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
assert(false, 'Base should be between 2 and 36');
|
|
};
|
|
|
|
BN.prototype.toNumber = function toNumber () {
|
|
var ret = this.words[0];
|
|
if (this.length === 2) {
|
|
ret += this.words[1] * 0x4000000;
|
|
} else if (this.length === 3 && this.words[2] === 0x01) {
|
|
// NOTE: at this stage it is known that the top bit is set
|
|
ret += 0x10000000000000 + (this.words[1] * 0x4000000);
|
|
} else if (this.length > 2) {
|
|
assert(false, 'Number can only safely store up to 53 bits');
|
|
}
|
|
return (this.negative !== 0) ? -ret : ret;
|
|
};
|
|
|
|
BN.prototype.toJSON = function toJSON () {
|
|
return this.toString(16);
|
|
};
|
|
|
|
BN.prototype.toBuffer = function toBuffer (endian, length) {
|
|
assert(typeof Buffer !== 'undefined');
|
|
return this.toArrayLike(Buffer, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArray = function toArray (endian, length) {
|
|
return this.toArrayLike(Array, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
|
|
var byteLength = this.byteLength();
|
|
var reqLength = length || Math.max(1, byteLength);
|
|
assert(byteLength <= reqLength, 'byte array longer than desired length');
|
|
assert(reqLength > 0, 'Requested array length <= 0');
|
|
|
|
this.strip();
|
|
var littleEndian = endian === 'le';
|
|
var res = new ArrayType(reqLength);
|
|
|
|
var b, i;
|
|
var q = this.clone();
|
|
if (!littleEndian) {
|
|
// Assume big-endian
|
|
for (i = 0; i < reqLength - byteLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[reqLength - i - 1] = b;
|
|
}
|
|
} else {
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[i] = b;
|
|
}
|
|
|
|
for (; i < reqLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
if (Math.clz32) {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
return 32 - Math.clz32(w);
|
|
};
|
|
} else {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
var t = w;
|
|
var r = 0;
|
|
if (t >= 0x1000) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if (t >= 0x40) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if (t >= 0x8) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if (t >= 0x02) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
return r + t;
|
|
};
|
|
}
|
|
|
|
BN.prototype._zeroBits = function _zeroBits (w) {
|
|
// Short-cut
|
|
if (w === 0) return 26;
|
|
|
|
var t = w;
|
|
var r = 0;
|
|
if ((t & 0x1fff) === 0) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if ((t & 0x7f) === 0) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if ((t & 0xf) === 0) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if ((t & 0x3) === 0) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
if ((t & 0x1) === 0) {
|
|
r++;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
// Return number of used bits in a BN
|
|
BN.prototype.bitLength = function bitLength () {
|
|
var w = this.words[this.length - 1];
|
|
var hi = this._countBits(w);
|
|
return (this.length - 1) * 26 + hi;
|
|
};
|
|
|
|
function toBitArray (num) {
|
|
var w = new Array(num.bitLength());
|
|
|
|
for (var bit = 0; bit < w.length; bit++) {
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
// Number of trailing zero bits
|
|
BN.prototype.zeroBits = function zeroBits () {
|
|
if (this.isZero()) return 0;
|
|
|
|
var r = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var b = this._zeroBits(this.words[i]);
|
|
r += b;
|
|
if (b !== 26) break;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
BN.prototype.byteLength = function byteLength () {
|
|
return Math.ceil(this.bitLength() / 8);
|
|
};
|
|
|
|
BN.prototype.toTwos = function toTwos (width) {
|
|
if (this.negative !== 0) {
|
|
return this.abs().inotn(width).iaddn(1);
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.fromTwos = function fromTwos (width) {
|
|
if (this.testn(width - 1)) {
|
|
return this.notn(width).iaddn(1).ineg();
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.isNeg = function isNeg () {
|
|
return this.negative !== 0;
|
|
};
|
|
|
|
// Return negative clone of `this`
|
|
BN.prototype.neg = function neg () {
|
|
return this.clone().ineg();
|
|
};
|
|
|
|
BN.prototype.ineg = function ineg () {
|
|
if (!this.isZero()) {
|
|
this.negative ^= 1;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Or `num` with `this` in-place
|
|
BN.prototype.iuor = function iuor (num) {
|
|
while (this.length < num.length) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
|
|
for (var i = 0; i < num.length; i++) {
|
|
this.words[i] = this.words[i] | num.words[i];
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ior = function ior (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuor(num);
|
|
};
|
|
|
|
// Or `num` with `this`
|
|
BN.prototype.or = function or (num) {
|
|
if (this.length > num.length) return this.clone().ior(num);
|
|
return num.clone().ior(this);
|
|
};
|
|
|
|
BN.prototype.uor = function uor (num) {
|
|
if (this.length > num.length) return this.clone().iuor(num);
|
|
return num.clone().iuor(this);
|
|
};
|
|
|
|
// And `num` with `this` in-place
|
|
BN.prototype.iuand = function iuand (num) {
|
|
// b = min-length(num, this)
|
|
var b;
|
|
if (this.length > num.length) {
|
|
b = num;
|
|
} else {
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = this.words[i] & num.words[i];
|
|
}
|
|
|
|
this.length = b.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.iand = function iand (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuand(num);
|
|
};
|
|
|
|
// And `num` with `this`
|
|
BN.prototype.and = function and (num) {
|
|
if (this.length > num.length) return this.clone().iand(num);
|
|
return num.clone().iand(this);
|
|
};
|
|
|
|
BN.prototype.uand = function uand (num) {
|
|
if (this.length > num.length) return this.clone().iuand(num);
|
|
return num.clone().iuand(this);
|
|
};
|
|
|
|
// Xor `num` with `this` in-place
|
|
BN.prototype.iuxor = function iuxor (num) {
|
|
// a.length > b.length
|
|
var a;
|
|
var b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = a.words[i] ^ b.words[i];
|
|
}
|
|
|
|
if (this !== a) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = a.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ixor = function ixor (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuxor(num);
|
|
};
|
|
|
|
// Xor `num` with `this`
|
|
BN.prototype.xor = function xor (num) {
|
|
if (this.length > num.length) return this.clone().ixor(num);
|
|
return num.clone().ixor(this);
|
|
};
|
|
|
|
BN.prototype.uxor = function uxor (num) {
|
|
if (this.length > num.length) return this.clone().iuxor(num);
|
|
return num.clone().iuxor(this);
|
|
};
|
|
|
|
// Not ``this`` with ``width`` bitwidth
|
|
BN.prototype.inotn = function inotn (width) {
|
|
assert(typeof width === 'number' && width >= 0);
|
|
|
|
var bytesNeeded = Math.ceil(width / 26) | 0;
|
|
var bitsLeft = width % 26;
|
|
|
|
// Extend the buffer with leading zeroes
|
|
this._expand(bytesNeeded);
|
|
|
|
if (bitsLeft > 0) {
|
|
bytesNeeded--;
|
|
}
|
|
|
|
// Handle complete words
|
|
for (var i = 0; i < bytesNeeded; i++) {
|
|
this.words[i] = ~this.words[i] & 0x3ffffff;
|
|
}
|
|
|
|
// Handle the residue
|
|
if (bitsLeft > 0) {
|
|
this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
|
|
}
|
|
|
|
// And remove leading zeroes
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.notn = function notn (width) {
|
|
return this.clone().inotn(width);
|
|
};
|
|
|
|
// Set `bit` of `this`
|
|
BN.prototype.setn = function setn (bit, val) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
this._expand(off + 1);
|
|
|
|
if (val) {
|
|
this.words[off] = this.words[off] | (1 << wbit);
|
|
} else {
|
|
this.words[off] = this.words[off] & ~(1 << wbit);
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Add `num` to `this` in-place
|
|
BN.prototype.iadd = function iadd (num) {
|
|
var r;
|
|
|
|
// negative + positive
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
this.negative = 0;
|
|
r = this.isub(num);
|
|
this.negative ^= 1;
|
|
return this._normSign();
|
|
|
|
// positive + negative
|
|
} else if (this.negative === 0 && num.negative !== 0) {
|
|
num.negative = 0;
|
|
r = this.isub(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
}
|
|
|
|
// a.length > b.length
|
|
var a, b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
|
|
this.length = a.length;
|
|
if (carry !== 0) {
|
|
this.words[this.length] = carry;
|
|
this.length++;
|
|
// Copy the rest of the words
|
|
} else if (a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Add `num` to `this`
|
|
BN.prototype.add = function add (num) {
|
|
var res;
|
|
if (num.negative !== 0 && this.negative === 0) {
|
|
num.negative = 0;
|
|
res = this.sub(num);
|
|
num.negative ^= 1;
|
|
return res;
|
|
} else if (num.negative === 0 && this.negative !== 0) {
|
|
this.negative = 0;
|
|
res = num.sub(this);
|
|
this.negative = 1;
|
|
return res;
|
|
}
|
|
|
|
if (this.length > num.length) return this.clone().iadd(num);
|
|
|
|
return num.clone().iadd(this);
|
|
};
|
|
|
|
// Subtract `num` from `this` in-place
|
|
BN.prototype.isub = function isub (num) {
|
|
// this - (-num) = this + num
|
|
if (num.negative !== 0) {
|
|
num.negative = 0;
|
|
var r = this.iadd(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
|
|
// -this - num = -(this + num)
|
|
} else if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iadd(num);
|
|
this.negative = 1;
|
|
return this._normSign();
|
|
}
|
|
|
|
// At this point both numbers are positive
|
|
var cmp = this.cmp(num);
|
|
|
|
// Optimization - zeroify
|
|
if (cmp === 0) {
|
|
this.negative = 0;
|
|
this.length = 1;
|
|
this.words[0] = 0;
|
|
return this;
|
|
}
|
|
|
|
// a > b
|
|
var a, b;
|
|
if (cmp > 0) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
|
|
// Copy rest of the words
|
|
if (carry === 0 && i < a.length && a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = Math.max(this.length, i);
|
|
|
|
if (a !== this) {
|
|
this.negative = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Subtract `num` from `this`
|
|
BN.prototype.sub = function sub (num) {
|
|
return this.clone().isub(num);
|
|
};
|
|
|
|
function smallMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
var len = (self.length + num.length) | 0;
|
|
out.length = len;
|
|
len = (len - 1) | 0;
|
|
|
|
// Peel one iteration (compiler can't do it, because of code complexity)
|
|
var a = self.words[0] | 0;
|
|
var b = num.words[0] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
var carry = (r / 0x4000000) | 0;
|
|
out.words[0] = lo;
|
|
|
|
for (var k = 1; k < len; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = carry >>> 26;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = (k - j) | 0;
|
|
a = self.words[i] | 0;
|
|
b = num.words[j] | 0;
|
|
r = a * b + rword;
|
|
ncarry += (r / 0x4000000) | 0;
|
|
rword = r & 0x3ffffff;
|
|
}
|
|
out.words[k] = rword | 0;
|
|
carry = ncarry | 0;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry | 0;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
// TODO(indutny): it may be reasonable to omit it for users who don't need
|
|
// to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
|
|
// multiplication (like elliptic secp256k1).
|
|
var comb10MulTo = function comb10MulTo (self, num, out) {
|
|
var a = self.words;
|
|
var b = num.words;
|
|
var o = out.words;
|
|
var c = 0;
|
|
var lo;
|
|
var mid;
|
|
var hi;
|
|
var a0 = a[0] | 0;
|
|
var al0 = a0 & 0x1fff;
|
|
var ah0 = a0 >>> 13;
|
|
var a1 = a[1] | 0;
|
|
var al1 = a1 & 0x1fff;
|
|
var ah1 = a1 >>> 13;
|
|
var a2 = a[2] | 0;
|
|
var al2 = a2 & 0x1fff;
|
|
var ah2 = a2 >>> 13;
|
|
var a3 = a[3] | 0;
|
|
var al3 = a3 & 0x1fff;
|
|
var ah3 = a3 >>> 13;
|
|
var a4 = a[4] | 0;
|
|
var al4 = a4 & 0x1fff;
|
|
var ah4 = a4 >>> 13;
|
|
var a5 = a[5] | 0;
|
|
var al5 = a5 & 0x1fff;
|
|
var ah5 = a5 >>> 13;
|
|
var a6 = a[6] | 0;
|
|
var al6 = a6 & 0x1fff;
|
|
var ah6 = a6 >>> 13;
|
|
var a7 = a[7] | 0;
|
|
var al7 = a7 & 0x1fff;
|
|
var ah7 = a7 >>> 13;
|
|
var a8 = a[8] | 0;
|
|
var al8 = a8 & 0x1fff;
|
|
var ah8 = a8 >>> 13;
|
|
var a9 = a[9] | 0;
|
|
var al9 = a9 & 0x1fff;
|
|
var ah9 = a9 >>> 13;
|
|
var b0 = b[0] | 0;
|
|
var bl0 = b0 & 0x1fff;
|
|
var bh0 = b0 >>> 13;
|
|
var b1 = b[1] | 0;
|
|
var bl1 = b1 & 0x1fff;
|
|
var bh1 = b1 >>> 13;
|
|
var b2 = b[2] | 0;
|
|
var bl2 = b2 & 0x1fff;
|
|
var bh2 = b2 >>> 13;
|
|
var b3 = b[3] | 0;
|
|
var bl3 = b3 & 0x1fff;
|
|
var bh3 = b3 >>> 13;
|
|
var b4 = b[4] | 0;
|
|
var bl4 = b4 & 0x1fff;
|
|
var bh4 = b4 >>> 13;
|
|
var b5 = b[5] | 0;
|
|
var bl5 = b5 & 0x1fff;
|
|
var bh5 = b5 >>> 13;
|
|
var b6 = b[6] | 0;
|
|
var bl6 = b6 & 0x1fff;
|
|
var bh6 = b6 >>> 13;
|
|
var b7 = b[7] | 0;
|
|
var bl7 = b7 & 0x1fff;
|
|
var bh7 = b7 >>> 13;
|
|
var b8 = b[8] | 0;
|
|
var bl8 = b8 & 0x1fff;
|
|
var bh8 = b8 >>> 13;
|
|
var b9 = b[9] | 0;
|
|
var bl9 = b9 & 0x1fff;
|
|
var bh9 = b9 >>> 13;
|
|
|
|
out.negative = self.negative ^ num.negative;
|
|
out.length = 19;
|
|
/* k = 0 */
|
|
lo = Math.imul(al0, bl0);
|
|
mid = Math.imul(al0, bh0);
|
|
mid = (mid + Math.imul(ah0, bl0)) | 0;
|
|
hi = Math.imul(ah0, bh0);
|
|
var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
|
|
w0 &= 0x3ffffff;
|
|
/* k = 1 */
|
|
lo = Math.imul(al1, bl0);
|
|
mid = Math.imul(al1, bh0);
|
|
mid = (mid + Math.imul(ah1, bl0)) | 0;
|
|
hi = Math.imul(ah1, bh0);
|
|
lo = (lo + Math.imul(al0, bl1)) | 0;
|
|
mid = (mid + Math.imul(al0, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh1)) | 0;
|
|
var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
|
|
w1 &= 0x3ffffff;
|
|
/* k = 2 */
|
|
lo = Math.imul(al2, bl0);
|
|
mid = Math.imul(al2, bh0);
|
|
mid = (mid + Math.imul(ah2, bl0)) | 0;
|
|
hi = Math.imul(ah2, bh0);
|
|
lo = (lo + Math.imul(al1, bl1)) | 0;
|
|
mid = (mid + Math.imul(al1, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh1)) | 0;
|
|
lo = (lo + Math.imul(al0, bl2)) | 0;
|
|
mid = (mid + Math.imul(al0, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh2)) | 0;
|
|
var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
|
|
w2 &= 0x3ffffff;
|
|
/* k = 3 */
|
|
lo = Math.imul(al3, bl0);
|
|
mid = Math.imul(al3, bh0);
|
|
mid = (mid + Math.imul(ah3, bl0)) | 0;
|
|
hi = Math.imul(ah3, bh0);
|
|
lo = (lo + Math.imul(al2, bl1)) | 0;
|
|
mid = (mid + Math.imul(al2, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh1)) | 0;
|
|
lo = (lo + Math.imul(al1, bl2)) | 0;
|
|
mid = (mid + Math.imul(al1, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh2)) | 0;
|
|
lo = (lo + Math.imul(al0, bl3)) | 0;
|
|
mid = (mid + Math.imul(al0, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh3)) | 0;
|
|
var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
|
|
w3 &= 0x3ffffff;
|
|
/* k = 4 */
|
|
lo = Math.imul(al4, bl0);
|
|
mid = Math.imul(al4, bh0);
|
|
mid = (mid + Math.imul(ah4, bl0)) | 0;
|
|
hi = Math.imul(ah4, bh0);
|
|
lo = (lo + Math.imul(al3, bl1)) | 0;
|
|
mid = (mid + Math.imul(al3, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh1)) | 0;
|
|
lo = (lo + Math.imul(al2, bl2)) | 0;
|
|
mid = (mid + Math.imul(al2, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh2)) | 0;
|
|
lo = (lo + Math.imul(al1, bl3)) | 0;
|
|
mid = (mid + Math.imul(al1, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh3)) | 0;
|
|
lo = (lo + Math.imul(al0, bl4)) | 0;
|
|
mid = (mid + Math.imul(al0, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh4)) | 0;
|
|
var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
|
|
w4 &= 0x3ffffff;
|
|
/* k = 5 */
|
|
lo = Math.imul(al5, bl0);
|
|
mid = Math.imul(al5, bh0);
|
|
mid = (mid + Math.imul(ah5, bl0)) | 0;
|
|
hi = Math.imul(ah5, bh0);
|
|
lo = (lo + Math.imul(al4, bl1)) | 0;
|
|
mid = (mid + Math.imul(al4, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh1)) | 0;
|
|
lo = (lo + Math.imul(al3, bl2)) | 0;
|
|
mid = (mid + Math.imul(al3, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh2)) | 0;
|
|
lo = (lo + Math.imul(al2, bl3)) | 0;
|
|
mid = (mid + Math.imul(al2, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh3)) | 0;
|
|
lo = (lo + Math.imul(al1, bl4)) | 0;
|
|
mid = (mid + Math.imul(al1, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh4)) | 0;
|
|
lo = (lo + Math.imul(al0, bl5)) | 0;
|
|
mid = (mid + Math.imul(al0, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh5)) | 0;
|
|
var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
|
|
w5 &= 0x3ffffff;
|
|
/* k = 6 */
|
|
lo = Math.imul(al6, bl0);
|
|
mid = Math.imul(al6, bh0);
|
|
mid = (mid + Math.imul(ah6, bl0)) | 0;
|
|
hi = Math.imul(ah6, bh0);
|
|
lo = (lo + Math.imul(al5, bl1)) | 0;
|
|
mid = (mid + Math.imul(al5, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh1)) | 0;
|
|
lo = (lo + Math.imul(al4, bl2)) | 0;
|
|
mid = (mid + Math.imul(al4, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh2)) | 0;
|
|
lo = (lo + Math.imul(al3, bl3)) | 0;
|
|
mid = (mid + Math.imul(al3, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh3)) | 0;
|
|
lo = (lo + Math.imul(al2, bl4)) | 0;
|
|
mid = (mid + Math.imul(al2, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh4)) | 0;
|
|
lo = (lo + Math.imul(al1, bl5)) | 0;
|
|
mid = (mid + Math.imul(al1, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh5)) | 0;
|
|
lo = (lo + Math.imul(al0, bl6)) | 0;
|
|
mid = (mid + Math.imul(al0, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh6)) | 0;
|
|
var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
|
|
w6 &= 0x3ffffff;
|
|
/* k = 7 */
|
|
lo = Math.imul(al7, bl0);
|
|
mid = Math.imul(al7, bh0);
|
|
mid = (mid + Math.imul(ah7, bl0)) | 0;
|
|
hi = Math.imul(ah7, bh0);
|
|
lo = (lo + Math.imul(al6, bl1)) | 0;
|
|
mid = (mid + Math.imul(al6, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh1)) | 0;
|
|
lo = (lo + Math.imul(al5, bl2)) | 0;
|
|
mid = (mid + Math.imul(al5, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh2)) | 0;
|
|
lo = (lo + Math.imul(al4, bl3)) | 0;
|
|
mid = (mid + Math.imul(al4, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh3)) | 0;
|
|
lo = (lo + Math.imul(al3, bl4)) | 0;
|
|
mid = (mid + Math.imul(al3, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh4)) | 0;
|
|
lo = (lo + Math.imul(al2, bl5)) | 0;
|
|
mid = (mid + Math.imul(al2, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh5)) | 0;
|
|
lo = (lo + Math.imul(al1, bl6)) | 0;
|
|
mid = (mid + Math.imul(al1, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh6)) | 0;
|
|
lo = (lo + Math.imul(al0, bl7)) | 0;
|
|
mid = (mid + Math.imul(al0, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh7)) | 0;
|
|
var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
|
|
w7 &= 0x3ffffff;
|
|
/* k = 8 */
|
|
lo = Math.imul(al8, bl0);
|
|
mid = Math.imul(al8, bh0);
|
|
mid = (mid + Math.imul(ah8, bl0)) | 0;
|
|
hi = Math.imul(ah8, bh0);
|
|
lo = (lo + Math.imul(al7, bl1)) | 0;
|
|
mid = (mid + Math.imul(al7, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh1)) | 0;
|
|
lo = (lo + Math.imul(al6, bl2)) | 0;
|
|
mid = (mid + Math.imul(al6, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh2)) | 0;
|
|
lo = (lo + Math.imul(al5, bl3)) | 0;
|
|
mid = (mid + Math.imul(al5, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh3)) | 0;
|
|
lo = (lo + Math.imul(al4, bl4)) | 0;
|
|
mid = (mid + Math.imul(al4, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh4)) | 0;
|
|
lo = (lo + Math.imul(al3, bl5)) | 0;
|
|
mid = (mid + Math.imul(al3, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh5)) | 0;
|
|
lo = (lo + Math.imul(al2, bl6)) | 0;
|
|
mid = (mid + Math.imul(al2, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh6)) | 0;
|
|
lo = (lo + Math.imul(al1, bl7)) | 0;
|
|
mid = (mid + Math.imul(al1, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh7)) | 0;
|
|
lo = (lo + Math.imul(al0, bl8)) | 0;
|
|
mid = (mid + Math.imul(al0, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh8)) | 0;
|
|
var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
|
|
w8 &= 0x3ffffff;
|
|
/* k = 9 */
|
|
lo = Math.imul(al9, bl0);
|
|
mid = Math.imul(al9, bh0);
|
|
mid = (mid + Math.imul(ah9, bl0)) | 0;
|
|
hi = Math.imul(ah9, bh0);
|
|
lo = (lo + Math.imul(al8, bl1)) | 0;
|
|
mid = (mid + Math.imul(al8, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh1)) | 0;
|
|
lo = (lo + Math.imul(al7, bl2)) | 0;
|
|
mid = (mid + Math.imul(al7, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh2)) | 0;
|
|
lo = (lo + Math.imul(al6, bl3)) | 0;
|
|
mid = (mid + Math.imul(al6, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh3)) | 0;
|
|
lo = (lo + Math.imul(al5, bl4)) | 0;
|
|
mid = (mid + Math.imul(al5, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh4)) | 0;
|
|
lo = (lo + Math.imul(al4, bl5)) | 0;
|
|
mid = (mid + Math.imul(al4, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh5)) | 0;
|
|
lo = (lo + Math.imul(al3, bl6)) | 0;
|
|
mid = (mid + Math.imul(al3, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh6)) | 0;
|
|
lo = (lo + Math.imul(al2, bl7)) | 0;
|
|
mid = (mid + Math.imul(al2, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh7)) | 0;
|
|
lo = (lo + Math.imul(al1, bl8)) | 0;
|
|
mid = (mid + Math.imul(al1, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh8)) | 0;
|
|
lo = (lo + Math.imul(al0, bl9)) | 0;
|
|
mid = (mid + Math.imul(al0, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh9)) | 0;
|
|
var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
|
|
w9 &= 0x3ffffff;
|
|
/* k = 10 */
|
|
lo = Math.imul(al9, bl1);
|
|
mid = Math.imul(al9, bh1);
|
|
mid = (mid + Math.imul(ah9, bl1)) | 0;
|
|
hi = Math.imul(ah9, bh1);
|
|
lo = (lo + Math.imul(al8, bl2)) | 0;
|
|
mid = (mid + Math.imul(al8, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh2)) | 0;
|
|
lo = (lo + Math.imul(al7, bl3)) | 0;
|
|
mid = (mid + Math.imul(al7, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh3)) | 0;
|
|
lo = (lo + Math.imul(al6, bl4)) | 0;
|
|
mid = (mid + Math.imul(al6, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh4)) | 0;
|
|
lo = (lo + Math.imul(al5, bl5)) | 0;
|
|
mid = (mid + Math.imul(al5, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh5)) | 0;
|
|
lo = (lo + Math.imul(al4, bl6)) | 0;
|
|
mid = (mid + Math.imul(al4, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh6)) | 0;
|
|
lo = (lo + Math.imul(al3, bl7)) | 0;
|
|
mid = (mid + Math.imul(al3, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh7)) | 0;
|
|
lo = (lo + Math.imul(al2, bl8)) | 0;
|
|
mid = (mid + Math.imul(al2, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh8)) | 0;
|
|
lo = (lo + Math.imul(al1, bl9)) | 0;
|
|
mid = (mid + Math.imul(al1, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh9)) | 0;
|
|
var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
|
|
w10 &= 0x3ffffff;
|
|
/* k = 11 */
|
|
lo = Math.imul(al9, bl2);
|
|
mid = Math.imul(al9, bh2);
|
|
mid = (mid + Math.imul(ah9, bl2)) | 0;
|
|
hi = Math.imul(ah9, bh2);
|
|
lo = (lo + Math.imul(al8, bl3)) | 0;
|
|
mid = (mid + Math.imul(al8, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh3)) | 0;
|
|
lo = (lo + Math.imul(al7, bl4)) | 0;
|
|
mid = (mid + Math.imul(al7, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh4)) | 0;
|
|
lo = (lo + Math.imul(al6, bl5)) | 0;
|
|
mid = (mid + Math.imul(al6, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh5)) | 0;
|
|
lo = (lo + Math.imul(al5, bl6)) | 0;
|
|
mid = (mid + Math.imul(al5, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh6)) | 0;
|
|
lo = (lo + Math.imul(al4, bl7)) | 0;
|
|
mid = (mid + Math.imul(al4, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh7)) | 0;
|
|
lo = (lo + Math.imul(al3, bl8)) | 0;
|
|
mid = (mid + Math.imul(al3, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh8)) | 0;
|
|
lo = (lo + Math.imul(al2, bl9)) | 0;
|
|
mid = (mid + Math.imul(al2, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh9)) | 0;
|
|
var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
|
|
w11 &= 0x3ffffff;
|
|
/* k = 12 */
|
|
lo = Math.imul(al9, bl3);
|
|
mid = Math.imul(al9, bh3);
|
|
mid = (mid + Math.imul(ah9, bl3)) | 0;
|
|
hi = Math.imul(ah9, bh3);
|
|
lo = (lo + Math.imul(al8, bl4)) | 0;
|
|
mid = (mid + Math.imul(al8, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh4)) | 0;
|
|
lo = (lo + Math.imul(al7, bl5)) | 0;
|
|
mid = (mid + Math.imul(al7, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh5)) | 0;
|
|
lo = (lo + Math.imul(al6, bl6)) | 0;
|
|
mid = (mid + Math.imul(al6, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh6)) | 0;
|
|
lo = (lo + Math.imul(al5, bl7)) | 0;
|
|
mid = (mid + Math.imul(al5, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh7)) | 0;
|
|
lo = (lo + Math.imul(al4, bl8)) | 0;
|
|
mid = (mid + Math.imul(al4, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh8)) | 0;
|
|
lo = (lo + Math.imul(al3, bl9)) | 0;
|
|
mid = (mid + Math.imul(al3, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh9)) | 0;
|
|
var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
|
|
w12 &= 0x3ffffff;
|
|
/* k = 13 */
|
|
lo = Math.imul(al9, bl4);
|
|
mid = Math.imul(al9, bh4);
|
|
mid = (mid + Math.imul(ah9, bl4)) | 0;
|
|
hi = Math.imul(ah9, bh4);
|
|
lo = (lo + Math.imul(al8, bl5)) | 0;
|
|
mid = (mid + Math.imul(al8, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh5)) | 0;
|
|
lo = (lo + Math.imul(al7, bl6)) | 0;
|
|
mid = (mid + Math.imul(al7, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh6)) | 0;
|
|
lo = (lo + Math.imul(al6, bl7)) | 0;
|
|
mid = (mid + Math.imul(al6, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh7)) | 0;
|
|
lo = (lo + Math.imul(al5, bl8)) | 0;
|
|
mid = (mid + Math.imul(al5, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh8)) | 0;
|
|
lo = (lo + Math.imul(al4, bl9)) | 0;
|
|
mid = (mid + Math.imul(al4, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh9)) | 0;
|
|
var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
|
|
w13 &= 0x3ffffff;
|
|
/* k = 14 */
|
|
lo = Math.imul(al9, bl5);
|
|
mid = Math.imul(al9, bh5);
|
|
mid = (mid + Math.imul(ah9, bl5)) | 0;
|
|
hi = Math.imul(ah9, bh5);
|
|
lo = (lo + Math.imul(al8, bl6)) | 0;
|
|
mid = (mid + Math.imul(al8, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh6)) | 0;
|
|
lo = (lo + Math.imul(al7, bl7)) | 0;
|
|
mid = (mid + Math.imul(al7, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh7)) | 0;
|
|
lo = (lo + Math.imul(al6, bl8)) | 0;
|
|
mid = (mid + Math.imul(al6, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh8)) | 0;
|
|
lo = (lo + Math.imul(al5, bl9)) | 0;
|
|
mid = (mid + Math.imul(al5, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh9)) | 0;
|
|
var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
|
|
w14 &= 0x3ffffff;
|
|
/* k = 15 */
|
|
lo = Math.imul(al9, bl6);
|
|
mid = Math.imul(al9, bh6);
|
|
mid = (mid + Math.imul(ah9, bl6)) | 0;
|
|
hi = Math.imul(ah9, bh6);
|
|
lo = (lo + Math.imul(al8, bl7)) | 0;
|
|
mid = (mid + Math.imul(al8, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh7)) | 0;
|
|
lo = (lo + Math.imul(al7, bl8)) | 0;
|
|
mid = (mid + Math.imul(al7, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh8)) | 0;
|
|
lo = (lo + Math.imul(al6, bl9)) | 0;
|
|
mid = (mid + Math.imul(al6, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh9)) | 0;
|
|
var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
|
|
w15 &= 0x3ffffff;
|
|
/* k = 16 */
|
|
lo = Math.imul(al9, bl7);
|
|
mid = Math.imul(al9, bh7);
|
|
mid = (mid + Math.imul(ah9, bl7)) | 0;
|
|
hi = Math.imul(ah9, bh7);
|
|
lo = (lo + Math.imul(al8, bl8)) | 0;
|
|
mid = (mid + Math.imul(al8, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh8)) | 0;
|
|
lo = (lo + Math.imul(al7, bl9)) | 0;
|
|
mid = (mid + Math.imul(al7, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh9)) | 0;
|
|
var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
|
|
w16 &= 0x3ffffff;
|
|
/* k = 17 */
|
|
lo = Math.imul(al9, bl8);
|
|
mid = Math.imul(al9, bh8);
|
|
mid = (mid + Math.imul(ah9, bl8)) | 0;
|
|
hi = Math.imul(ah9, bh8);
|
|
lo = (lo + Math.imul(al8, bl9)) | 0;
|
|
mid = (mid + Math.imul(al8, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh9)) | 0;
|
|
var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
|
|
w17 &= 0x3ffffff;
|
|
/* k = 18 */
|
|
lo = Math.imul(al9, bl9);
|
|
mid = Math.imul(al9, bh9);
|
|
mid = (mid + Math.imul(ah9, bl9)) | 0;
|
|
hi = Math.imul(ah9, bh9);
|
|
var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
|
|
w18 &= 0x3ffffff;
|
|
o[0] = w0;
|
|
o[1] = w1;
|
|
o[2] = w2;
|
|
o[3] = w3;
|
|
o[4] = w4;
|
|
o[5] = w5;
|
|
o[6] = w6;
|
|
o[7] = w7;
|
|
o[8] = w8;
|
|
o[9] = w9;
|
|
o[10] = w10;
|
|
o[11] = w11;
|
|
o[12] = w12;
|
|
o[13] = w13;
|
|
o[14] = w14;
|
|
o[15] = w15;
|
|
o[16] = w16;
|
|
o[17] = w17;
|
|
o[18] = w18;
|
|
if (c !== 0) {
|
|
o[19] = c;
|
|
out.length++;
|
|
}
|
|
return out;
|
|
};
|
|
|
|
// Polyfill comb
|
|
if (!Math.imul) {
|
|
comb10MulTo = smallMulTo;
|
|
}
|
|
|
|
function bigMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
out.length = self.length + num.length;
|
|
|
|
var carry = 0;
|
|
var hncarry = 0;
|
|
for (var k = 0; k < out.length - 1; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = hncarry;
|
|
hncarry = 0;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = k - j;
|
|
var a = self.words[i] | 0;
|
|
var b = num.words[j] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
|
|
lo = (lo + rword) | 0;
|
|
rword = lo & 0x3ffffff;
|
|
ncarry = (ncarry + (lo >>> 26)) | 0;
|
|
|
|
hncarry += ncarry >>> 26;
|
|
ncarry &= 0x3ffffff;
|
|
}
|
|
out.words[k] = rword;
|
|
carry = ncarry;
|
|
ncarry = hncarry;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
function jumboMulTo (self, num, out) {
|
|
var fftm = new FFTM();
|
|
return fftm.mulp(self, num, out);
|
|
}
|
|
|
|
BN.prototype.mulTo = function mulTo (num, out) {
|
|
var res;
|
|
var len = this.length + num.length;
|
|
if (this.length === 10 && num.length === 10) {
|
|
res = comb10MulTo(this, num, out);
|
|
} else if (len < 63) {
|
|
res = smallMulTo(this, num, out);
|
|
} else if (len < 1024) {
|
|
res = bigMulTo(this, num, out);
|
|
} else {
|
|
res = jumboMulTo(this, num, out);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Cooley-Tukey algorithm for FFT
|
|
// slightly revisited to rely on looping instead of recursion
|
|
|
|
function FFTM (x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
FFTM.prototype.makeRBT = function makeRBT (N) {
|
|
var t = new Array(N);
|
|
var l = BN.prototype._countBits(N) - 1;
|
|
for (var i = 0; i < N; i++) {
|
|
t[i] = this.revBin(i, l, N);
|
|
}
|
|
|
|
return t;
|
|
};
|
|
|
|
// Returns binary-reversed representation of `x`
|
|
FFTM.prototype.revBin = function revBin (x, l, N) {
|
|
if (x === 0 || x === N - 1) return x;
|
|
|
|
var rb = 0;
|
|
for (var i = 0; i < l; i++) {
|
|
rb |= (x & 1) << (l - i - 1);
|
|
x >>= 1;
|
|
}
|
|
|
|
return rb;
|
|
};
|
|
|
|
// Performs "tweedling" phase, therefore 'emulating'
|
|
// behaviour of the recursive algorithm
|
|
FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
|
|
for (var i = 0; i < N; i++) {
|
|
rtws[i] = rws[rbt[i]];
|
|
itws[i] = iws[rbt[i]];
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
|
|
this.permute(rbt, rws, iws, rtws, itws, N);
|
|
|
|
for (var s = 1; s < N; s <<= 1) {
|
|
var l = s << 1;
|
|
|
|
var rtwdf = Math.cos(2 * Math.PI / l);
|
|
var itwdf = Math.sin(2 * Math.PI / l);
|
|
|
|
for (var p = 0; p < N; p += l) {
|
|
var rtwdf_ = rtwdf;
|
|
var itwdf_ = itwdf;
|
|
|
|
for (var j = 0; j < s; j++) {
|
|
var re = rtws[p + j];
|
|
var ie = itws[p + j];
|
|
|
|
var ro = rtws[p + j + s];
|
|
var io = itws[p + j + s];
|
|
|
|
var rx = rtwdf_ * ro - itwdf_ * io;
|
|
|
|
io = rtwdf_ * io + itwdf_ * ro;
|
|
ro = rx;
|
|
|
|
rtws[p + j] = re + ro;
|
|
itws[p + j] = ie + io;
|
|
|
|
rtws[p + j + s] = re - ro;
|
|
itws[p + j + s] = ie - io;
|
|
|
|
/* jshint maxdepth : false */
|
|
if (j !== l) {
|
|
rx = rtwdf * rtwdf_ - itwdf * itwdf_;
|
|
|
|
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
|
|
rtwdf_ = rx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
|
|
var N = Math.max(m, n) | 1;
|
|
var odd = N & 1;
|
|
var i = 0;
|
|
for (N = N / 2 | 0; N; N = N >>> 1) {
|
|
i++;
|
|
}
|
|
|
|
return 1 << i + 1 + odd;
|
|
};
|
|
|
|
FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
|
|
if (N <= 1) return;
|
|
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var t = rws[i];
|
|
|
|
rws[i] = rws[N - i - 1];
|
|
rws[N - i - 1] = t;
|
|
|
|
t = iws[i];
|
|
|
|
iws[i] = -iws[N - i - 1];
|
|
iws[N - i - 1] = -t;
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.normalize13b = function normalize13b (ws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
|
|
Math.round(ws[2 * i] / N) +
|
|
carry;
|
|
|
|
ws[i] = w & 0x3ffffff;
|
|
|
|
if (w < 0x4000000) {
|
|
carry = 0;
|
|
} else {
|
|
carry = w / 0x4000000 | 0;
|
|
}
|
|
}
|
|
|
|
return ws;
|
|
};
|
|
|
|
FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < len; i++) {
|
|
carry = carry + (ws[i] | 0);
|
|
|
|
rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
|
|
rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
|
|
}
|
|
|
|
// Pad with zeroes
|
|
for (i = 2 * len; i < N; ++i) {
|
|
rws[i] = 0;
|
|
}
|
|
|
|
assert(carry === 0);
|
|
assert((carry & ~0x1fff) === 0);
|
|
};
|
|
|
|
FFTM.prototype.stub = function stub (N) {
|
|
var ph = new Array(N);
|
|
for (var i = 0; i < N; i++) {
|
|
ph[i] = 0;
|
|
}
|
|
|
|
return ph;
|
|
};
|
|
|
|
FFTM.prototype.mulp = function mulp (x, y, out) {
|
|
var N = 2 * this.guessLen13b(x.length, y.length);
|
|
|
|
var rbt = this.makeRBT(N);
|
|
|
|
var _ = this.stub(N);
|
|
|
|
var rws = new Array(N);
|
|
var rwst = new Array(N);
|
|
var iwst = new Array(N);
|
|
|
|
var nrws = new Array(N);
|
|
var nrwst = new Array(N);
|
|
var niwst = new Array(N);
|
|
|
|
var rmws = out.words;
|
|
rmws.length = N;
|
|
|
|
this.convert13b(x.words, x.length, rws, N);
|
|
this.convert13b(y.words, y.length, nrws, N);
|
|
|
|
this.transform(rws, _, rwst, iwst, N, rbt);
|
|
this.transform(nrws, _, nrwst, niwst, N, rbt);
|
|
|
|
for (var i = 0; i < N; i++) {
|
|
var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
|
|
iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
|
|
rwst[i] = rx;
|
|
}
|
|
|
|
this.conjugate(rwst, iwst, N);
|
|
this.transform(rwst, iwst, rmws, _, N, rbt);
|
|
this.conjugate(rmws, _, N);
|
|
this.normalize13b(rmws, N);
|
|
|
|
out.negative = x.negative ^ y.negative;
|
|
out.length = x.length + y.length;
|
|
return out.strip();
|
|
};
|
|
|
|
// Multiply `this` by `num`
|
|
BN.prototype.mul = function mul (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return this.mulTo(num, out);
|
|
};
|
|
|
|
// Multiply employing FFT
|
|
BN.prototype.mulf = function mulf (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return jumboMulTo(this, num, out);
|
|
};
|
|
|
|
// In-place Multiplication
|
|
BN.prototype.imul = function imul (num) {
|
|
return this.clone().mulTo(num, this);
|
|
};
|
|
|
|
BN.prototype.imuln = function imuln (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
|
|
// Carry
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = (this.words[i] | 0) * num;
|
|
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
|
|
carry >>= 26;
|
|
carry += (w / 0x4000000) | 0;
|
|
// NOTE: lo is 27bit maximum
|
|
carry += lo >>> 26;
|
|
this.words[i] = lo & 0x3ffffff;
|
|
}
|
|
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.muln = function muln (num) {
|
|
return this.clone().imuln(num);
|
|
};
|
|
|
|
// `this` * `this`
|
|
BN.prototype.sqr = function sqr () {
|
|
return this.mul(this);
|
|
};
|
|
|
|
// `this` * `this` in-place
|
|
BN.prototype.isqr = function isqr () {
|
|
return this.imul(this.clone());
|
|
};
|
|
|
|
// Math.pow(`this`, `num`)
|
|
BN.prototype.pow = function pow (num) {
|
|
var w = toBitArray(num);
|
|
if (w.length === 0) return new BN(1);
|
|
|
|
// Skip leading zeroes
|
|
var res = this;
|
|
for (var i = 0; i < w.length; i++, res = res.sqr()) {
|
|
if (w[i] !== 0) break;
|
|
}
|
|
|
|
if (++i < w.length) {
|
|
for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
|
|
if (w[i] === 0) continue;
|
|
|
|
res = res.mul(q);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Shift-left in-place
|
|
BN.prototype.iushln = function iushln (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
|
|
var i;
|
|
|
|
if (r !== 0) {
|
|
var carry = 0;
|
|
|
|
for (i = 0; i < this.length; i++) {
|
|
var newCarry = this.words[i] & carryMask;
|
|
var c = ((this.words[i] | 0) - newCarry) << r;
|
|
this.words[i] = c | carry;
|
|
carry = newCarry >>> (26 - r);
|
|
}
|
|
|
|
if (carry) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
}
|
|
|
|
if (s !== 0) {
|
|
for (i = this.length - 1; i >= 0; i--) {
|
|
this.words[i + s] = this.words[i];
|
|
}
|
|
|
|
for (i = 0; i < s; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
this.length += s;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishln = function ishln (bits) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushln(bits);
|
|
};
|
|
|
|
// Shift-right in-place
|
|
// NOTE: `hint` is a lowest bit before trailing zeroes
|
|
// NOTE: if `extended` is present - it will be filled with destroyed bits
|
|
BN.prototype.iushrn = function iushrn (bits, hint, extended) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var h;
|
|
if (hint) {
|
|
h = (hint - (hint % 26)) / 26;
|
|
} else {
|
|
h = 0;
|
|
}
|
|
|
|
var r = bits % 26;
|
|
var s = Math.min((bits - r) / 26, this.length);
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
var maskedWords = extended;
|
|
|
|
h -= s;
|
|
h = Math.max(0, h);
|
|
|
|
// Extended mode, copy masked part
|
|
if (maskedWords) {
|
|
for (var i = 0; i < s; i++) {
|
|
maskedWords.words[i] = this.words[i];
|
|
}
|
|
maskedWords.length = s;
|
|
}
|
|
|
|
if (s === 0) {
|
|
// No-op, we should not move anything at all
|
|
} else if (this.length > s) {
|
|
this.length -= s;
|
|
for (i = 0; i < this.length; i++) {
|
|
this.words[i] = this.words[i + s];
|
|
}
|
|
} else {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
|
|
var word = this.words[i] | 0;
|
|
this.words[i] = (carry << (26 - r)) | (word >>> r);
|
|
carry = word & mask;
|
|
}
|
|
|
|
// Push carried bits as a mask
|
|
if (maskedWords && carry !== 0) {
|
|
maskedWords.words[maskedWords.length++] = carry;
|
|
}
|
|
|
|
if (this.length === 0) {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishrn = function ishrn (bits, hint, extended) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushrn(bits, hint, extended);
|
|
};
|
|
|
|
// Shift-left
|
|
BN.prototype.shln = function shln (bits) {
|
|
return this.clone().ishln(bits);
|
|
};
|
|
|
|
BN.prototype.ushln = function ushln (bits) {
|
|
return this.clone().iushln(bits);
|
|
};
|
|
|
|
// Shift-right
|
|
BN.prototype.shrn = function shrn (bits) {
|
|
return this.clone().ishrn(bits);
|
|
};
|
|
|
|
BN.prototype.ushrn = function ushrn (bits) {
|
|
return this.clone().iushrn(bits);
|
|
};
|
|
|
|
// Test if n bit is set
|
|
BN.prototype.testn = function testn (bit) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) return false;
|
|
|
|
// Check bit and return
|
|
var w = this.words[s];
|
|
|
|
return !!(w & q);
|
|
};
|
|
|
|
// Return only lowers bits of number (in-place)
|
|
BN.prototype.imaskn = function imaskn (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
|
|
assert(this.negative === 0, 'imaskn works only with positive numbers');
|
|
|
|
if (this.length <= s) {
|
|
return this;
|
|
}
|
|
|
|
if (r !== 0) {
|
|
s++;
|
|
}
|
|
this.length = Math.min(s, this.length);
|
|
|
|
if (r !== 0) {
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
this.words[this.length - 1] &= mask;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Return only lowers bits of number
|
|
BN.prototype.maskn = function maskn (bits) {
|
|
return this.clone().imaskn(bits);
|
|
};
|
|
|
|
// Add plain number `num` to `this`
|
|
BN.prototype.iaddn = function iaddn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.isubn(-num);
|
|
|
|
// Possible sign change
|
|
if (this.negative !== 0) {
|
|
if (this.length === 1 && (this.words[0] | 0) < num) {
|
|
this.words[0] = num - (this.words[0] | 0);
|
|
this.negative = 0;
|
|
return this;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.isubn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
// Add without checks
|
|
return this._iaddn(num);
|
|
};
|
|
|
|
BN.prototype._iaddn = function _iaddn (num) {
|
|
this.words[0] += num;
|
|
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
|
|
this.words[i] -= 0x4000000;
|
|
if (i === this.length - 1) {
|
|
this.words[i + 1] = 1;
|
|
} else {
|
|
this.words[i + 1]++;
|
|
}
|
|
}
|
|
this.length = Math.max(this.length, i + 1);
|
|
|
|
return this;
|
|
};
|
|
|
|
// Subtract plain number `num` from `this`
|
|
BN.prototype.isubn = function isubn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.iaddn(-num);
|
|
|
|
if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iaddn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
this.words[0] -= num;
|
|
|
|
if (this.length === 1 && this.words[0] < 0) {
|
|
this.words[0] = -this.words[0];
|
|
this.negative = 1;
|
|
} else {
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
|
|
this.words[i] += 0x4000000;
|
|
this.words[i + 1] -= 1;
|
|
}
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.addn = function addn (num) {
|
|
return this.clone().iaddn(num);
|
|
};
|
|
|
|
BN.prototype.subn = function subn (num) {
|
|
return this.clone().isubn(num);
|
|
};
|
|
|
|
BN.prototype.iabs = function iabs () {
|
|
this.negative = 0;
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.abs = function abs () {
|
|
return this.clone().iabs();
|
|
};
|
|
|
|
BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
|
|
var len = num.length + shift;
|
|
var i;
|
|
|
|
this._expand(len);
|
|
|
|
var w;
|
|
var carry = 0;
|
|
for (i = 0; i < num.length; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
var right = (num.words[i] | 0) * mul;
|
|
w -= right & 0x3ffffff;
|
|
carry = (w >> 26) - ((right / 0x4000000) | 0);
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
for (; i < this.length - shift; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
|
|
if (carry === 0) return this.strip();
|
|
|
|
// Subtraction overflow
|
|
assert(carry === -1);
|
|
carry = 0;
|
|
for (i = 0; i < this.length; i++) {
|
|
w = -(this.words[i] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i] = w & 0x3ffffff;
|
|
}
|
|
this.negative = 1;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype._wordDiv = function _wordDiv (num, mode) {
|
|
var shift = this.length - num.length;
|
|
|
|
var a = this.clone();
|
|
var b = num;
|
|
|
|
// Normalize
|
|
var bhi = b.words[b.length - 1] | 0;
|
|
var bhiBits = this._countBits(bhi);
|
|
shift = 26 - bhiBits;
|
|
if (shift !== 0) {
|
|
b = b.ushln(shift);
|
|
a.iushln(shift);
|
|
bhi = b.words[b.length - 1] | 0;
|
|
}
|
|
|
|
// Initialize quotient
|
|
var m = a.length - b.length;
|
|
var q;
|
|
|
|
if (mode !== 'mod') {
|
|
q = new BN(null);
|
|
q.length = m + 1;
|
|
q.words = new Array(q.length);
|
|
for (var i = 0; i < q.length; i++) {
|
|
q.words[i] = 0;
|
|
}
|
|
}
|
|
|
|
var diff = a.clone()._ishlnsubmul(b, 1, m);
|
|
if (diff.negative === 0) {
|
|
a = diff;
|
|
if (q) {
|
|
q.words[m] = 1;
|
|
}
|
|
}
|
|
|
|
for (var j = m - 1; j >= 0; j--) {
|
|
var qj = (a.words[b.length + j] | 0) * 0x4000000 +
|
|
(a.words[b.length + j - 1] | 0);
|
|
|
|
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
|
|
// (0x7ffffff)
|
|
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
|
|
|
|
a._ishlnsubmul(b, qj, j);
|
|
while (a.negative !== 0) {
|
|
qj--;
|
|
a.negative = 0;
|
|
a._ishlnsubmul(b, 1, j);
|
|
if (!a.isZero()) {
|
|
a.negative ^= 1;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.words[j] = qj;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.strip();
|
|
}
|
|
a.strip();
|
|
|
|
// Denormalize
|
|
if (mode !== 'div' && shift !== 0) {
|
|
a.iushrn(shift);
|
|
}
|
|
|
|
return {
|
|
div: q || null,
|
|
mod: a
|
|
};
|
|
};
|
|
|
|
// NOTE: 1) `mode` can be set to `mod` to request mod only,
|
|
// to `div` to request div only, or be absent to
|
|
// request both div & mod
|
|
// 2) `positive` is true if unsigned mod is requested
|
|
BN.prototype.divmod = function divmod (num, mode, positive) {
|
|
assert(!num.isZero());
|
|
|
|
if (this.isZero()) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: new BN(0)
|
|
};
|
|
}
|
|
|
|
var div, mod, res;
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
res = this.neg().divmod(num, mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.iadd(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
if (this.negative === 0 && num.negative !== 0) {
|
|
res = this.divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: res.mod
|
|
};
|
|
}
|
|
|
|
if ((this.negative & num.negative) !== 0) {
|
|
res = this.neg().divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.isub(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: res.div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
// Both numbers are positive at this point
|
|
|
|
// Strip both numbers to approximate shift value
|
|
if (num.length > this.length || this.cmp(num) < 0) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: this
|
|
};
|
|
}
|
|
|
|
// Very short reduction
|
|
if (num.length === 1) {
|
|
if (mode === 'div') {
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: null
|
|
};
|
|
}
|
|
|
|
if (mode === 'mod') {
|
|
return {
|
|
div: null,
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return this._wordDiv(num, mode);
|
|
};
|
|
|
|
// Find `this` / `num`
|
|
BN.prototype.div = function div (num) {
|
|
return this.divmod(num, 'div', false).div;
|
|
};
|
|
|
|
// Find `this` % `num`
|
|
BN.prototype.mod = function mod (num) {
|
|
return this.divmod(num, 'mod', false).mod;
|
|
};
|
|
|
|
BN.prototype.umod = function umod (num) {
|
|
return this.divmod(num, 'mod', true).mod;
|
|
};
|
|
|
|
// Find Round(`this` / `num`)
|
|
BN.prototype.divRound = function divRound (num) {
|
|
var dm = this.divmod(num);
|
|
|
|
// Fast case - exact division
|
|
if (dm.mod.isZero()) return dm.div;
|
|
|
|
var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
|
|
|
|
var half = num.ushrn(1);
|
|
var r2 = num.andln(1);
|
|
var cmp = mod.cmp(half);
|
|
|
|
// Round down
|
|
if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
|
|
|
|
// Round up
|
|
return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
|
|
};
|
|
|
|
BN.prototype.modn = function modn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
var p = (1 << 26) % num;
|
|
|
|
var acc = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
acc = (p * acc + (this.words[i] | 0)) % num;
|
|
}
|
|
|
|
return acc;
|
|
};
|
|
|
|
// In-place division by number
|
|
BN.prototype.idivn = function idivn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
|
|
var carry = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var w = (this.words[i] | 0) + carry * 0x4000000;
|
|
this.words[i] = (w / num) | 0;
|
|
carry = w % num;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.divn = function divn (num) {
|
|
return this.clone().idivn(num);
|
|
};
|
|
|
|
BN.prototype.egcd = function egcd (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var x = this;
|
|
var y = p.clone();
|
|
|
|
if (x.negative !== 0) {
|
|
x = x.umod(p);
|
|
} else {
|
|
x = x.clone();
|
|
}
|
|
|
|
// A * x + B * y = x
|
|
var A = new BN(1);
|
|
var B = new BN(0);
|
|
|
|
// C * x + D * y = y
|
|
var C = new BN(0);
|
|
var D = new BN(1);
|
|
|
|
var g = 0;
|
|
|
|
while (x.isEven() && y.isEven()) {
|
|
x.iushrn(1);
|
|
y.iushrn(1);
|
|
++g;
|
|
}
|
|
|
|
var yp = y.clone();
|
|
var xp = x.clone();
|
|
|
|
while (!x.isZero()) {
|
|
for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
x.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (A.isOdd() || B.isOdd()) {
|
|
A.iadd(yp);
|
|
B.isub(xp);
|
|
}
|
|
|
|
A.iushrn(1);
|
|
B.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
y.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (C.isOdd() || D.isOdd()) {
|
|
C.iadd(yp);
|
|
D.isub(xp);
|
|
}
|
|
|
|
C.iushrn(1);
|
|
D.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (x.cmp(y) >= 0) {
|
|
x.isub(y);
|
|
A.isub(C);
|
|
B.isub(D);
|
|
} else {
|
|
y.isub(x);
|
|
C.isub(A);
|
|
D.isub(B);
|
|
}
|
|
}
|
|
|
|
return {
|
|
a: C,
|
|
b: D,
|
|
gcd: y.iushln(g)
|
|
};
|
|
};
|
|
|
|
// This is reduced incarnation of the binary EEA
|
|
// above, designated to invert members of the
|
|
// _prime_ fields F(p) at a maximal speed
|
|
BN.prototype._invmp = function _invmp (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var a = this;
|
|
var b = p.clone();
|
|
|
|
if (a.negative !== 0) {
|
|
a = a.umod(p);
|
|
} else {
|
|
a = a.clone();
|
|
}
|
|
|
|
var x1 = new BN(1);
|
|
var x2 = new BN(0);
|
|
|
|
var delta = b.clone();
|
|
|
|
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
|
|
for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
a.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (x1.isOdd()) {
|
|
x1.iadd(delta);
|
|
}
|
|
|
|
x1.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
b.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (x2.isOdd()) {
|
|
x2.iadd(delta);
|
|
}
|
|
|
|
x2.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (a.cmp(b) >= 0) {
|
|
a.isub(b);
|
|
x1.isub(x2);
|
|
} else {
|
|
b.isub(a);
|
|
x2.isub(x1);
|
|
}
|
|
}
|
|
|
|
var res;
|
|
if (a.cmpn(1) === 0) {
|
|
res = x1;
|
|
} else {
|
|
res = x2;
|
|
}
|
|
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(p);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gcd = function gcd (num) {
|
|
if (this.isZero()) return num.abs();
|
|
if (num.isZero()) return this.abs();
|
|
|
|
var a = this.clone();
|
|
var b = num.clone();
|
|
a.negative = 0;
|
|
b.negative = 0;
|
|
|
|
// Remove common factor of two
|
|
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
|
|
a.iushrn(1);
|
|
b.iushrn(1);
|
|
}
|
|
|
|
do {
|
|
while (a.isEven()) {
|
|
a.iushrn(1);
|
|
}
|
|
while (b.isEven()) {
|
|
b.iushrn(1);
|
|
}
|
|
|
|
var r = a.cmp(b);
|
|
if (r < 0) {
|
|
// Swap `a` and `b` to make `a` always bigger than `b`
|
|
var t = a;
|
|
a = b;
|
|
b = t;
|
|
} else if (r === 0 || b.cmpn(1) === 0) {
|
|
break;
|
|
}
|
|
|
|
a.isub(b);
|
|
} while (true);
|
|
|
|
return b.iushln(shift);
|
|
};
|
|
|
|
// Invert number in the field F(num)
|
|
BN.prototype.invm = function invm (num) {
|
|
return this.egcd(num).a.umod(num);
|
|
};
|
|
|
|
BN.prototype.isEven = function isEven () {
|
|
return (this.words[0] & 1) === 0;
|
|
};
|
|
|
|
BN.prototype.isOdd = function isOdd () {
|
|
return (this.words[0] & 1) === 1;
|
|
};
|
|
|
|
// And first word and num
|
|
BN.prototype.andln = function andln (num) {
|
|
return this.words[0] & num;
|
|
};
|
|
|
|
// Increment at the bit position in-line
|
|
BN.prototype.bincn = function bincn (bit) {
|
|
assert(typeof bit === 'number');
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) {
|
|
this._expand(s + 1);
|
|
this.words[s] |= q;
|
|
return this;
|
|
}
|
|
|
|
// Add bit and propagate, if needed
|
|
var carry = q;
|
|
for (var i = s; carry !== 0 && i < this.length; i++) {
|
|
var w = this.words[i] | 0;
|
|
w += carry;
|
|
carry = w >>> 26;
|
|
w &= 0x3ffffff;
|
|
this.words[i] = w;
|
|
}
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.isZero = function isZero () {
|
|
return this.length === 1 && this.words[0] === 0;
|
|
};
|
|
|
|
BN.prototype.cmpn = function cmpn (num) {
|
|
var negative = num < 0;
|
|
|
|
if (this.negative !== 0 && !negative) return -1;
|
|
if (this.negative === 0 && negative) return 1;
|
|
|
|
this.strip();
|
|
|
|
var res;
|
|
if (this.length > 1) {
|
|
res = 1;
|
|
} else {
|
|
if (negative) {
|
|
num = -num;
|
|
}
|
|
|
|
assert(num <= 0x3ffffff, 'Number is too big');
|
|
|
|
var w = this.words[0] | 0;
|
|
res = w === num ? 0 : w < num ? -1 : 1;
|
|
}
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Compare two numbers and return:
|
|
// 1 - if `this` > `num`
|
|
// 0 - if `this` == `num`
|
|
// -1 - if `this` < `num`
|
|
BN.prototype.cmp = function cmp (num) {
|
|
if (this.negative !== 0 && num.negative === 0) return -1;
|
|
if (this.negative === 0 && num.negative !== 0) return 1;
|
|
|
|
var res = this.ucmp(num);
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Unsigned comparison
|
|
BN.prototype.ucmp = function ucmp (num) {
|
|
// At this point both numbers have the same sign
|
|
if (this.length > num.length) return 1;
|
|
if (this.length < num.length) return -1;
|
|
|
|
var res = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var a = this.words[i] | 0;
|
|
var b = num.words[i] | 0;
|
|
|
|
if (a === b) continue;
|
|
if (a < b) {
|
|
res = -1;
|
|
} else if (a > b) {
|
|
res = 1;
|
|
}
|
|
break;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gtn = function gtn (num) {
|
|
return this.cmpn(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gt = function gt (num) {
|
|
return this.cmp(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gten = function gten (num) {
|
|
return this.cmpn(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.gte = function gte (num) {
|
|
return this.cmp(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.ltn = function ltn (num) {
|
|
return this.cmpn(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lt = function lt (num) {
|
|
return this.cmp(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lten = function lten (num) {
|
|
return this.cmpn(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.lte = function lte (num) {
|
|
return this.cmp(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.eqn = function eqn (num) {
|
|
return this.cmpn(num) === 0;
|
|
};
|
|
|
|
BN.prototype.eq = function eq (num) {
|
|
return this.cmp(num) === 0;
|
|
};
|
|
|
|
//
|
|
// A reduce context, could be using montgomery or something better, depending
|
|
// on the `m` itself.
|
|
//
|
|
BN.red = function red (num) {
|
|
return new Red(num);
|
|
};
|
|
|
|
BN.prototype.toRed = function toRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
assert(this.negative === 0, 'red works only with positives');
|
|
return ctx.convertTo(this)._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.fromRed = function fromRed () {
|
|
assert(this.red, 'fromRed works only with numbers in reduction context');
|
|
return this.red.convertFrom(this);
|
|
};
|
|
|
|
BN.prototype._forceRed = function _forceRed (ctx) {
|
|
this.red = ctx;
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.forceRed = function forceRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
return this._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.redAdd = function redAdd (num) {
|
|
assert(this.red, 'redAdd works only with red numbers');
|
|
return this.red.add(this, num);
|
|
};
|
|
|
|
BN.prototype.redIAdd = function redIAdd (num) {
|
|
assert(this.red, 'redIAdd works only with red numbers');
|
|
return this.red.iadd(this, num);
|
|
};
|
|
|
|
BN.prototype.redSub = function redSub (num) {
|
|
assert(this.red, 'redSub works only with red numbers');
|
|
return this.red.sub(this, num);
|
|
};
|
|
|
|
BN.prototype.redISub = function redISub (num) {
|
|
assert(this.red, 'redISub works only with red numbers');
|
|
return this.red.isub(this, num);
|
|
};
|
|
|
|
BN.prototype.redShl = function redShl (num) {
|
|
assert(this.red, 'redShl works only with red numbers');
|
|
return this.red.shl(this, num);
|
|
};
|
|
|
|
BN.prototype.redMul = function redMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.mul(this, num);
|
|
};
|
|
|
|
BN.prototype.redIMul = function redIMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.imul(this, num);
|
|
};
|
|
|
|
BN.prototype.redSqr = function redSqr () {
|
|
assert(this.red, 'redSqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqr(this);
|
|
};
|
|
|
|
BN.prototype.redISqr = function redISqr () {
|
|
assert(this.red, 'redISqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.isqr(this);
|
|
};
|
|
|
|
// Square root over p
|
|
BN.prototype.redSqrt = function redSqrt () {
|
|
assert(this.red, 'redSqrt works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqrt(this);
|
|
};
|
|
|
|
BN.prototype.redInvm = function redInvm () {
|
|
assert(this.red, 'redInvm works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.invm(this);
|
|
};
|
|
|
|
// Return negative clone of `this` % `red modulo`
|
|
BN.prototype.redNeg = function redNeg () {
|
|
assert(this.red, 'redNeg works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.neg(this);
|
|
};
|
|
|
|
BN.prototype.redPow = function redPow (num) {
|
|
assert(this.red && !num.red, 'redPow(normalNum)');
|
|
this.red._verify1(this);
|
|
return this.red.pow(this, num);
|
|
};
|
|
|
|
// Prime numbers with efficient reduction
|
|
var primes = {
|
|
k256: null,
|
|
p224: null,
|
|
p192: null,
|
|
p25519: null
|
|
};
|
|
|
|
// Pseudo-Mersenne prime
|
|
function MPrime (name, p) {
|
|
// P = 2 ^ N - K
|
|
this.name = name;
|
|
this.p = new BN(p, 16);
|
|
this.n = this.p.bitLength();
|
|
this.k = new BN(1).iushln(this.n).isub(this.p);
|
|
|
|
this.tmp = this._tmp();
|
|
}
|
|
|
|
MPrime.prototype._tmp = function _tmp () {
|
|
var tmp = new BN(null);
|
|
tmp.words = new Array(Math.ceil(this.n / 13));
|
|
return tmp;
|
|
};
|
|
|
|
MPrime.prototype.ireduce = function ireduce (num) {
|
|
// Assumes that `num` is less than `P^2`
|
|
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
|
|
var r = num;
|
|
var rlen;
|
|
|
|
do {
|
|
this.split(r, this.tmp);
|
|
r = this.imulK(r);
|
|
r = r.iadd(this.tmp);
|
|
rlen = r.bitLength();
|
|
} while (rlen > this.n);
|
|
|
|
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
|
|
if (cmp === 0) {
|
|
r.words[0] = 0;
|
|
r.length = 1;
|
|
} else if (cmp > 0) {
|
|
r.isub(this.p);
|
|
} else {
|
|
if (r.strip !== undefined) {
|
|
// r is BN v4 instance
|
|
r.strip();
|
|
} else {
|
|
// r is BN v5 instance
|
|
r._strip();
|
|
}
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
MPrime.prototype.split = function split (input, out) {
|
|
input.iushrn(this.n, 0, out);
|
|
};
|
|
|
|
MPrime.prototype.imulK = function imulK (num) {
|
|
return num.imul(this.k);
|
|
};
|
|
|
|
function K256 () {
|
|
MPrime.call(
|
|
this,
|
|
'k256',
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
|
|
}
|
|
inherits(K256, MPrime);
|
|
|
|
K256.prototype.split = function split (input, output) {
|
|
// 256 = 9 * 26 + 22
|
|
var mask = 0x3fffff;
|
|
|
|
var outLen = Math.min(input.length, 9);
|
|
for (var i = 0; i < outLen; i++) {
|
|
output.words[i] = input.words[i];
|
|
}
|
|
output.length = outLen;
|
|
|
|
if (input.length <= 9) {
|
|
input.words[0] = 0;
|
|
input.length = 1;
|
|
return;
|
|
}
|
|
|
|
// Shift by 9 limbs
|
|
var prev = input.words[9];
|
|
output.words[output.length++] = prev & mask;
|
|
|
|
for (i = 10; i < input.length; i++) {
|
|
var next = input.words[i] | 0;
|
|
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
|
|
prev = next;
|
|
}
|
|
prev >>>= 22;
|
|
input.words[i - 10] = prev;
|
|
if (prev === 0 && input.length > 10) {
|
|
input.length -= 10;
|
|
} else {
|
|
input.length -= 9;
|
|
}
|
|
};
|
|
|
|
K256.prototype.imulK = function imulK (num) {
|
|
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
|
|
num.words[num.length] = 0;
|
|
num.words[num.length + 1] = 0;
|
|
num.length += 2;
|
|
|
|
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
|
|
var lo = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var w = num.words[i] | 0;
|
|
lo += w * 0x3d1;
|
|
num.words[i] = lo & 0x3ffffff;
|
|
lo = w * 0x40 + ((lo / 0x4000000) | 0);
|
|
}
|
|
|
|
// Fast length reduction
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
}
|
|
}
|
|
return num;
|
|
};
|
|
|
|
function P224 () {
|
|
MPrime.call(
|
|
this,
|
|
'p224',
|
|
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
|
|
}
|
|
inherits(P224, MPrime);
|
|
|
|
function P192 () {
|
|
MPrime.call(
|
|
this,
|
|
'p192',
|
|
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
|
|
}
|
|
inherits(P192, MPrime);
|
|
|
|
function P25519 () {
|
|
// 2 ^ 255 - 19
|
|
MPrime.call(
|
|
this,
|
|
'25519',
|
|
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
|
|
}
|
|
inherits(P25519, MPrime);
|
|
|
|
P25519.prototype.imulK = function imulK (num) {
|
|
// K = 0x13
|
|
var carry = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var hi = (num.words[i] | 0) * 0x13 + carry;
|
|
var lo = hi & 0x3ffffff;
|
|
hi >>>= 26;
|
|
|
|
num.words[i] = lo;
|
|
carry = hi;
|
|
}
|
|
if (carry !== 0) {
|
|
num.words[num.length++] = carry;
|
|
}
|
|
return num;
|
|
};
|
|
|
|
// Exported mostly for testing purposes, use plain name instead
|
|
BN._prime = function prime (name) {
|
|
// Cached version of prime
|
|
if (primes[name]) return primes[name];
|
|
|
|
var prime;
|
|
if (name === 'k256') {
|
|
prime = new K256();
|
|
} else if (name === 'p224') {
|
|
prime = new P224();
|
|
} else if (name === 'p192') {
|
|
prime = new P192();
|
|
} else if (name === 'p25519') {
|
|
prime = new P25519();
|
|
} else {
|
|
throw new Error('Unknown prime ' + name);
|
|
}
|
|
primes[name] = prime;
|
|
|
|
return prime;
|
|
};
|
|
|
|
//
|
|
// Base reduction engine
|
|
//
|
|
function Red (m) {
|
|
if (typeof m === 'string') {
|
|
var prime = BN._prime(m);
|
|
this.m = prime.p;
|
|
this.prime = prime;
|
|
} else {
|
|
assert(m.gtn(1), 'modulus must be greater than 1');
|
|
this.m = m;
|
|
this.prime = null;
|
|
}
|
|
}
|
|
|
|
Red.prototype._verify1 = function _verify1 (a) {
|
|
assert(a.negative === 0, 'red works only with positives');
|
|
assert(a.red, 'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype._verify2 = function _verify2 (a, b) {
|
|
assert((a.negative | b.negative) === 0, 'red works only with positives');
|
|
assert(a.red && a.red === b.red,
|
|
'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype.imod = function imod (a) {
|
|
if (this.prime) return this.prime.ireduce(a)._forceRed(this);
|
|
return a.umod(this.m)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.neg = function neg (a) {
|
|
if (a.isZero()) {
|
|
return a.clone();
|
|
}
|
|
|
|
return this.m.sub(a)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.add = function add (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.add(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.iadd = function iadd (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.iadd(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.sub = function sub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.sub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.isub = function isub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.isub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.shl = function shl (a, num) {
|
|
this._verify1(a);
|
|
return this.imod(a.ushln(num));
|
|
};
|
|
|
|
Red.prototype.imul = function imul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.imul(b));
|
|
};
|
|
|
|
Red.prototype.mul = function mul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.mul(b));
|
|
};
|
|
|
|
Red.prototype.isqr = function isqr (a) {
|
|
return this.imul(a, a.clone());
|
|
};
|
|
|
|
Red.prototype.sqr = function sqr (a) {
|
|
return this.mul(a, a);
|
|
};
|
|
|
|
Red.prototype.sqrt = function sqrt (a) {
|
|
if (a.isZero()) return a.clone();
|
|
|
|
var mod3 = this.m.andln(3);
|
|
assert(mod3 % 2 === 1);
|
|
|
|
// Fast case
|
|
if (mod3 === 3) {
|
|
var pow = this.m.add(new BN(1)).iushrn(2);
|
|
return this.pow(a, pow);
|
|
}
|
|
|
|
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
|
|
//
|
|
// Find Q and S, that Q * 2 ^ S = (P - 1)
|
|
var q = this.m.subn(1);
|
|
var s = 0;
|
|
while (!q.isZero() && q.andln(1) === 0) {
|
|
s++;
|
|
q.iushrn(1);
|
|
}
|
|
assert(!q.isZero());
|
|
|
|
var one = new BN(1).toRed(this);
|
|
var nOne = one.redNeg();
|
|
|
|
// Find quadratic non-residue
|
|
// NOTE: Max is such because of generalized Riemann hypothesis.
|
|
var lpow = this.m.subn(1).iushrn(1);
|
|
var z = this.m.bitLength();
|
|
z = new BN(2 * z * z).toRed(this);
|
|
|
|
while (this.pow(z, lpow).cmp(nOne) !== 0) {
|
|
z.redIAdd(nOne);
|
|
}
|
|
|
|
var c = this.pow(z, q);
|
|
var r = this.pow(a, q.addn(1).iushrn(1));
|
|
var t = this.pow(a, q);
|
|
var m = s;
|
|
while (t.cmp(one) !== 0) {
|
|
var tmp = t;
|
|
for (var i = 0; tmp.cmp(one) !== 0; i++) {
|
|
tmp = tmp.redSqr();
|
|
}
|
|
assert(i < m);
|
|
var b = this.pow(c, new BN(1).iushln(m - i - 1));
|
|
|
|
r = r.redMul(b);
|
|
c = b.redSqr();
|
|
t = t.redMul(c);
|
|
m = i;
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
Red.prototype.invm = function invm (a) {
|
|
var inv = a._invmp(this.m);
|
|
if (inv.negative !== 0) {
|
|
inv.negative = 0;
|
|
return this.imod(inv).redNeg();
|
|
} else {
|
|
return this.imod(inv);
|
|
}
|
|
};
|
|
|
|
Red.prototype.pow = function pow (a, num) {
|
|
if (num.isZero()) return new BN(1).toRed(this);
|
|
if (num.cmpn(1) === 0) return a.clone();
|
|
|
|
var windowSize = 4;
|
|
var wnd = new Array(1 << windowSize);
|
|
wnd[0] = new BN(1).toRed(this);
|
|
wnd[1] = a;
|
|
for (var i = 2; i < wnd.length; i++) {
|
|
wnd[i] = this.mul(wnd[i - 1], a);
|
|
}
|
|
|
|
var res = wnd[0];
|
|
var current = 0;
|
|
var currentLen = 0;
|
|
var start = num.bitLength() % 26;
|
|
if (start === 0) {
|
|
start = 26;
|
|
}
|
|
|
|
for (i = num.length - 1; i >= 0; i--) {
|
|
var word = num.words[i];
|
|
for (var j = start - 1; j >= 0; j--) {
|
|
var bit = (word >> j) & 1;
|
|
if (res !== wnd[0]) {
|
|
res = this.sqr(res);
|
|
}
|
|
|
|
if (bit === 0 && current === 0) {
|
|
currentLen = 0;
|
|
continue;
|
|
}
|
|
|
|
current <<= 1;
|
|
current |= bit;
|
|
currentLen++;
|
|
if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
|
|
|
|
res = this.mul(res, wnd[current]);
|
|
currentLen = 0;
|
|
current = 0;
|
|
}
|
|
start = 26;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.convertTo = function convertTo (num) {
|
|
var r = num.umod(this.m);
|
|
|
|
return r === num ? r.clone() : r;
|
|
};
|
|
|
|
Red.prototype.convertFrom = function convertFrom (num) {
|
|
var res = num.clone();
|
|
res.red = null;
|
|
return res;
|
|
};
|
|
|
|
//
|
|
// Montgomery method engine
|
|
//
|
|
|
|
BN.mont = function mont (num) {
|
|
return new Mont(num);
|
|
};
|
|
|
|
function Mont (m) {
|
|
Red.call(this, m);
|
|
|
|
this.shift = this.m.bitLength();
|
|
if (this.shift % 26 !== 0) {
|
|
this.shift += 26 - (this.shift % 26);
|
|
}
|
|
|
|
this.r = new BN(1).iushln(this.shift);
|
|
this.r2 = this.imod(this.r.sqr());
|
|
this.rinv = this.r._invmp(this.m);
|
|
|
|
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
|
|
this.minv = this.minv.umod(this.r);
|
|
this.minv = this.r.sub(this.minv);
|
|
}
|
|
inherits(Mont, Red);
|
|
|
|
Mont.prototype.convertTo = function convertTo (num) {
|
|
return this.imod(num.ushln(this.shift));
|
|
};
|
|
|
|
Mont.prototype.convertFrom = function convertFrom (num) {
|
|
var r = this.imod(num.mul(this.rinv));
|
|
r.red = null;
|
|
return r;
|
|
};
|
|
|
|
Mont.prototype.imul = function imul (a, b) {
|
|
if (a.isZero() || b.isZero()) {
|
|
a.words[0] = 0;
|
|
a.length = 1;
|
|
return a;
|
|
}
|
|
|
|
var t = a.imul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.mul = function mul (a, b) {
|
|
if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
|
|
|
|
var t = a.mul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.invm = function invm (a) {
|
|
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
|
|
var res = this.imod(a._invmp(this.m).mul(this.r2));
|
|
return res._forceRed(this);
|
|
};
|
|
})( false || module, this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/create-hash/browser.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/create-hash/browser.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var MD5 = __webpack_require__(/*! md5.js */ "./node_modules/md5.js/index.js")
|
|
var RIPEMD160 = __webpack_require__(/*! ripemd160 */ "./node_modules/ripemd160/index.js")
|
|
var sha = __webpack_require__(/*! sha.js */ "./node_modules/sha.js/index.js")
|
|
var Base = __webpack_require__(/*! cipher-base */ "./node_modules/cipher-base/index.js")
|
|
|
|
function Hash (hash) {
|
|
Base.call(this, 'digest')
|
|
|
|
this._hash = hash
|
|
}
|
|
|
|
inherits(Hash, Base)
|
|
|
|
Hash.prototype._update = function (data) {
|
|
this._hash.update(data)
|
|
}
|
|
|
|
Hash.prototype._final = function () {
|
|
return this._hash.digest()
|
|
}
|
|
|
|
module.exports = function createHash (alg) {
|
|
alg = alg.toLowerCase()
|
|
if (alg === 'md5') return new MD5()
|
|
if (alg === 'rmd160' || alg === 'ripemd160') return new RIPEMD160()
|
|
|
|
return new Hash(sha(alg))
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/create-hash/md5.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/create-hash/md5.js ***!
|
|
\*****************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var MD5 = __webpack_require__(/*! md5.js */ "./node_modules/md5.js/index.js")
|
|
|
|
module.exports = function (buffer) {
|
|
return new MD5().update(buffer).digest()
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/create-hmac/browser.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/create-hmac/browser.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var Legacy = __webpack_require__(/*! ./legacy */ "./node_modules/create-hmac/legacy.js")
|
|
var Base = __webpack_require__(/*! cipher-base */ "./node_modules/cipher-base/index.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var md5 = __webpack_require__(/*! create-hash/md5 */ "./node_modules/create-hash/md5.js")
|
|
var RIPEMD160 = __webpack_require__(/*! ripemd160 */ "./node_modules/ripemd160/index.js")
|
|
|
|
var sha = __webpack_require__(/*! sha.js */ "./node_modules/sha.js/index.js")
|
|
|
|
var ZEROS = Buffer.alloc(128)
|
|
|
|
function Hmac (alg, key) {
|
|
Base.call(this, 'digest')
|
|
if (typeof key === 'string') {
|
|
key = Buffer.from(key)
|
|
}
|
|
|
|
var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64
|
|
|
|
this._alg = alg
|
|
this._key = key
|
|
if (key.length > blocksize) {
|
|
var hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg)
|
|
key = hash.update(key).digest()
|
|
} else if (key.length < blocksize) {
|
|
key = Buffer.concat([key, ZEROS], blocksize)
|
|
}
|
|
|
|
var ipad = this._ipad = Buffer.allocUnsafe(blocksize)
|
|
var opad = this._opad = Buffer.allocUnsafe(blocksize)
|
|
|
|
for (var i = 0; i < blocksize; i++) {
|
|
ipad[i] = key[i] ^ 0x36
|
|
opad[i] = key[i] ^ 0x5C
|
|
}
|
|
this._hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg)
|
|
this._hash.update(ipad)
|
|
}
|
|
|
|
inherits(Hmac, Base)
|
|
|
|
Hmac.prototype._update = function (data) {
|
|
this._hash.update(data)
|
|
}
|
|
|
|
Hmac.prototype._final = function () {
|
|
var h = this._hash.digest()
|
|
var hash = this._alg === 'rmd160' ? new RIPEMD160() : sha(this._alg)
|
|
return hash.update(this._opad).update(h).digest()
|
|
}
|
|
|
|
module.exports = function createHmac (alg, key) {
|
|
alg = alg.toLowerCase()
|
|
if (alg === 'rmd160' || alg === 'ripemd160') {
|
|
return new Hmac('rmd160', key)
|
|
}
|
|
if (alg === 'md5') {
|
|
return new Legacy(md5, key)
|
|
}
|
|
return new Hmac(alg, key)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/create-hmac/legacy.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/create-hmac/legacy.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var Base = __webpack_require__(/*! cipher-base */ "./node_modules/cipher-base/index.js")
|
|
|
|
var ZEROS = Buffer.alloc(128)
|
|
var blocksize = 64
|
|
|
|
function Hmac (alg, key) {
|
|
Base.call(this, 'digest')
|
|
if (typeof key === 'string') {
|
|
key = Buffer.from(key)
|
|
}
|
|
|
|
this._alg = alg
|
|
this._key = key
|
|
|
|
if (key.length > blocksize) {
|
|
key = alg(key)
|
|
} else if (key.length < blocksize) {
|
|
key = Buffer.concat([key, ZEROS], blocksize)
|
|
}
|
|
|
|
var ipad = this._ipad = Buffer.allocUnsafe(blocksize)
|
|
var opad = this._opad = Buffer.allocUnsafe(blocksize)
|
|
|
|
for (var i = 0; i < blocksize; i++) {
|
|
ipad[i] = key[i] ^ 0x36
|
|
opad[i] = key[i] ^ 0x5C
|
|
}
|
|
|
|
this._hash = [ipad]
|
|
}
|
|
|
|
inherits(Hmac, Base)
|
|
|
|
Hmac.prototype._update = function (data) {
|
|
this._hash.push(data)
|
|
}
|
|
|
|
Hmac.prototype._final = function () {
|
|
var h = this._alg(Buffer.concat(this._hash))
|
|
return this._alg(Buffer.concat([this._opad, h]))
|
|
}
|
|
module.exports = Hmac
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/create-torrent/index.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/create-torrent/index.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! create-torrent. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */
|
|
const bencode = __webpack_require__(/*! bencode */ "./node_modules/bencode/lib/index.js")
|
|
const BlockStream = __webpack_require__(/*! block-stream2 */ "./node_modules/block-stream2/index.js")
|
|
const calcPieceLength = __webpack_require__(/*! piece-length */ "./node_modules/piece-length/index.js")
|
|
const corePath = __webpack_require__(/*! path */ "./node_modules/path-browserify/index.js")
|
|
const FileReadStream = __webpack_require__(/*! filestream/read */ "./node_modules/filestream/read.js")
|
|
const isFile = __webpack_require__(/*! is-file */ "?f12c")
|
|
const junk = __webpack_require__(/*! junk */ "./node_modules/junk/index.js")
|
|
const MultiStream = __webpack_require__(/*! multistream */ "./node_modules/multistream/index.js")
|
|
const once = __webpack_require__(/*! once */ "./node_modules/once/once.js")
|
|
const parallel = __webpack_require__(/*! run-parallel */ "./node_modules/run-parallel/index.js")
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
const sha1 = __webpack_require__(/*! simple-sha1 */ "./node_modules/simple-sha1/browser.js")
|
|
const stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
|
|
const getFiles = __webpack_require__(/*! ./get-files */ "?3b18") // browser exclude
|
|
|
|
// TODO: When Node 10 support is dropped, replace this with Array.prototype.flat
|
|
function flat (arr1) {
|
|
return arr1.reduce(
|
|
(acc, val) => Array.isArray(val)
|
|
? acc.concat(flat(val))
|
|
: acc.concat(val),
|
|
[]
|
|
)
|
|
}
|
|
|
|
const announceList = [
|
|
['udp://tracker.leechers-paradise.org:6969'],
|
|
['udp://tracker.coppersurfer.tk:6969'],
|
|
['udp://tracker.opentrackr.org:1337'],
|
|
['udp://explodie.org:6969'],
|
|
['udp://tracker.empire-js.us:1337'],
|
|
['wss://tracker.btorrent.xyz'],
|
|
['wss://tracker.openwebtorrent.com']
|
|
]
|
|
|
|
/**
|
|
* Create a torrent.
|
|
* @param {string|File|FileList|Buffer|Stream|Array.<string|File|Buffer|Stream>} input
|
|
* @param {Object} opts
|
|
* @param {string=} opts.name
|
|
* @param {Date=} opts.creationDate
|
|
* @param {string=} opts.comment
|
|
* @param {string=} opts.createdBy
|
|
* @param {boolean|number=} opts.private
|
|
* @param {number=} opts.pieceLength
|
|
* @param {Array.<Array.<string>>=} opts.announceList
|
|
* @param {Array.<string>=} opts.urlList
|
|
* @param {Object=} opts.info
|
|
* @param {Function} opts.onProgress
|
|
* @param {function} cb
|
|
* @return {Buffer} buffer of .torrent file data
|
|
*/
|
|
function createTorrent (input, opts, cb) {
|
|
if (typeof opts === 'function') [opts, cb] = [cb, opts]
|
|
opts = opts ? Object.assign({}, opts) : {}
|
|
|
|
_parseInput(input, opts, (err, files, singleFileTorrent) => {
|
|
if (err) return cb(err)
|
|
opts.singleFileTorrent = singleFileTorrent
|
|
onFiles(files, opts, cb)
|
|
})
|
|
}
|
|
|
|
function parseInput (input, opts, cb) {
|
|
if (typeof opts === 'function') [opts, cb] = [cb, opts]
|
|
opts = opts ? Object.assign({}, opts) : {}
|
|
_parseInput(input, opts, cb)
|
|
}
|
|
|
|
/**
|
|
* Parse input file and return file information.
|
|
*/
|
|
function _parseInput (input, opts, cb) {
|
|
if (isFileList(input)) input = Array.from(input)
|
|
if (!Array.isArray(input)) input = [input]
|
|
|
|
if (input.length === 0) throw new Error('invalid input type')
|
|
|
|
input.forEach(item => {
|
|
if (item == null) throw new Error(`invalid input type: ${item}`)
|
|
})
|
|
|
|
// In Electron, use the true file path
|
|
input = input.map(item => {
|
|
if (isBlob(item) && typeof item.path === 'string' && typeof getFiles === 'function') return item.path
|
|
return item
|
|
})
|
|
|
|
// If there's just one file, allow the name to be set by `opts.name`
|
|
if (input.length === 1 && typeof input[0] !== 'string' && !input[0].name) input[0].name = opts.name
|
|
|
|
let commonPrefix = null
|
|
input.forEach((item, i) => {
|
|
if (typeof item === 'string') {
|
|
return
|
|
}
|
|
|
|
let path = item.fullPath || item.name
|
|
if (!path) {
|
|
path = `Unknown File ${i + 1}`
|
|
item.unknownName = true
|
|
}
|
|
|
|
item.path = path.split('/')
|
|
|
|
// Remove initial slash
|
|
if (!item.path[0]) {
|
|
item.path.shift()
|
|
}
|
|
|
|
if (item.path.length < 2) { // No real prefix
|
|
commonPrefix = null
|
|
} else if (i === 0 && input.length > 1) { // The first file has a prefix
|
|
commonPrefix = item.path[0]
|
|
} else if (item.path[0] !== commonPrefix) { // The prefix doesn't match
|
|
commonPrefix = null
|
|
}
|
|
})
|
|
|
|
const filterJunkFiles = opts.filterJunkFiles === undefined ? true : opts.filterJunkFiles
|
|
if (filterJunkFiles) {
|
|
// Remove junk files
|
|
input = input.filter(item => {
|
|
if (typeof item === 'string') {
|
|
return true
|
|
}
|
|
return !isJunkPath(item.path)
|
|
})
|
|
}
|
|
|
|
if (commonPrefix) {
|
|
input.forEach(item => {
|
|
const pathless = (Buffer.isBuffer(item) || isReadable(item)) && !item.path
|
|
if (typeof item === 'string' || pathless) return
|
|
item.path.shift()
|
|
})
|
|
}
|
|
|
|
if (!opts.name && commonPrefix) {
|
|
opts.name = commonPrefix
|
|
}
|
|
|
|
if (!opts.name) {
|
|
// use first user-set file name
|
|
input.some(item => {
|
|
if (typeof item === 'string') {
|
|
opts.name = corePath.basename(item)
|
|
return true
|
|
} else if (!item.unknownName) {
|
|
opts.name = item.path[item.path.length - 1]
|
|
return true
|
|
}
|
|
return false
|
|
})
|
|
}
|
|
|
|
if (!opts.name) {
|
|
opts.name = `Unnamed Torrent ${Date.now()}`
|
|
}
|
|
|
|
const numPaths = input.reduce((sum, item) => sum + Number(typeof item === 'string'), 0)
|
|
|
|
let isSingleFileTorrent = (input.length === 1)
|
|
|
|
if (input.length === 1 && typeof input[0] === 'string') {
|
|
if (typeof getFiles !== 'function') {
|
|
throw new Error('filesystem paths do not work in the browser')
|
|
}
|
|
// If there's a single path, verify it's a file before deciding this is a single
|
|
// file torrent
|
|
isFile(input[0], (err, pathIsFile) => {
|
|
if (err) return cb(err)
|
|
isSingleFileTorrent = pathIsFile
|
|
processInput()
|
|
})
|
|
} else {
|
|
queueMicrotask(processInput)
|
|
}
|
|
|
|
function processInput () {
|
|
parallel(input.map(item => cb => {
|
|
const file = {}
|
|
|
|
if (isBlob(item)) {
|
|
file.getStream = getBlobStream(item)
|
|
file.length = item.size
|
|
} else if (Buffer.isBuffer(item)) {
|
|
file.getStream = getBufferStream(item)
|
|
file.length = item.length
|
|
} else if (isReadable(item)) {
|
|
file.getStream = getStreamStream(item, file)
|
|
file.length = 0
|
|
} else if (typeof item === 'string') {
|
|
if (typeof getFiles !== 'function') {
|
|
throw new Error('filesystem paths do not work in the browser')
|
|
}
|
|
const keepRoot = numPaths > 1 || isSingleFileTorrent
|
|
getFiles(item, keepRoot, cb)
|
|
return // early return!
|
|
} else {
|
|
throw new Error('invalid input type')
|
|
}
|
|
file.path = item.path
|
|
cb(null, file)
|
|
}), (err, files) => {
|
|
if (err) return cb(err)
|
|
files = flat(files)
|
|
cb(null, files, isSingleFileTorrent)
|
|
})
|
|
}
|
|
}
|
|
|
|
const MAX_OUTSTANDING_HASHES = 5
|
|
|
|
function getPieceList (files, pieceLength, estimatedTorrentLength, opts, cb) {
|
|
cb = once(cb)
|
|
const pieces = []
|
|
let length = 0
|
|
let hashedLength = 0
|
|
|
|
const streams = files.map(file => file.getStream)
|
|
|
|
let remainingHashes = 0
|
|
let pieceNum = 0
|
|
let ended = false
|
|
|
|
const multistream = new MultiStream(streams)
|
|
const blockstream = new BlockStream(pieceLength, { zeroPadding: false })
|
|
|
|
multistream.on('error', onError)
|
|
|
|
multistream
|
|
.pipe(blockstream)
|
|
.on('data', onData)
|
|
.on('end', onEnd)
|
|
.on('error', onError)
|
|
|
|
function onData (chunk) {
|
|
length += chunk.length
|
|
|
|
const i = pieceNum
|
|
sha1(chunk, hash => {
|
|
pieces[i] = hash
|
|
remainingHashes -= 1
|
|
if (remainingHashes < MAX_OUTSTANDING_HASHES) {
|
|
blockstream.resume()
|
|
}
|
|
hashedLength += chunk.length
|
|
if (opts.onProgress) opts.onProgress(hashedLength, estimatedTorrentLength)
|
|
maybeDone()
|
|
})
|
|
remainingHashes += 1
|
|
if (remainingHashes >= MAX_OUTSTANDING_HASHES) {
|
|
blockstream.pause()
|
|
}
|
|
pieceNum += 1
|
|
}
|
|
|
|
function onEnd () {
|
|
ended = true
|
|
maybeDone()
|
|
}
|
|
|
|
function onError (err) {
|
|
cleanup()
|
|
cb(err)
|
|
}
|
|
|
|
function cleanup () {
|
|
multistream.removeListener('error', onError)
|
|
blockstream.removeListener('data', onData)
|
|
blockstream.removeListener('end', onEnd)
|
|
blockstream.removeListener('error', onError)
|
|
}
|
|
|
|
function maybeDone () {
|
|
if (ended && remainingHashes === 0) {
|
|
cleanup()
|
|
cb(null, Buffer.from(pieces.join(''), 'hex'), length)
|
|
}
|
|
}
|
|
}
|
|
|
|
function onFiles (files, opts, cb) {
|
|
let announceList = opts.announceList
|
|
|
|
if (!announceList) {
|
|
if (typeof opts.announce === 'string') announceList = [[opts.announce]]
|
|
else if (Array.isArray(opts.announce)) {
|
|
announceList = opts.announce.map(u => [u])
|
|
}
|
|
}
|
|
|
|
if (!announceList) announceList = []
|
|
|
|
if (__webpack_require__.g.WEBTORRENT_ANNOUNCE) {
|
|
if (typeof __webpack_require__.g.WEBTORRENT_ANNOUNCE === 'string') {
|
|
announceList.push([[__webpack_require__.g.WEBTORRENT_ANNOUNCE]])
|
|
} else if (Array.isArray(__webpack_require__.g.WEBTORRENT_ANNOUNCE)) {
|
|
announceList = announceList.concat(__webpack_require__.g.WEBTORRENT_ANNOUNCE.map(u => [u]))
|
|
}
|
|
}
|
|
|
|
// When no trackers specified, use some reasonable defaults
|
|
if (opts.announce === undefined && opts.announceList === undefined) {
|
|
announceList = announceList.concat(module.exports.announceList)
|
|
}
|
|
|
|
if (typeof opts.urlList === 'string') opts.urlList = [opts.urlList]
|
|
|
|
const torrent = {
|
|
info: {
|
|
name: opts.name
|
|
},
|
|
'creation date': Math.ceil((Number(opts.creationDate) || Date.now()) / 1000),
|
|
encoding: 'UTF-8'
|
|
}
|
|
|
|
if (announceList.length !== 0) {
|
|
torrent.announce = announceList[0][0]
|
|
torrent['announce-list'] = announceList
|
|
}
|
|
|
|
if (opts.comment !== undefined) torrent.comment = opts.comment
|
|
|
|
if (opts.createdBy !== undefined) torrent['created by'] = opts.createdBy
|
|
|
|
if (opts.private !== undefined) torrent.info.private = Number(opts.private)
|
|
|
|
if (opts.info !== undefined) Object.assign(torrent.info, opts.info)
|
|
|
|
// "ssl-cert" key is for SSL torrents, see:
|
|
// - http://blog.libtorrent.org/2012/01/bittorrent-over-ssl/
|
|
// - http://www.libtorrent.org/manual-ref.html#ssl-torrents
|
|
// - http://www.libtorrent.org/reference-Create_Torrents.html
|
|
if (opts.sslCert !== undefined) torrent.info['ssl-cert'] = opts.sslCert
|
|
|
|
if (opts.urlList !== undefined) torrent['url-list'] = opts.urlList
|
|
|
|
const estimatedTorrentLength = files.reduce(sumLength, 0)
|
|
const pieceLength = opts.pieceLength || calcPieceLength(estimatedTorrentLength)
|
|
torrent.info['piece length'] = pieceLength
|
|
|
|
getPieceList(
|
|
files,
|
|
pieceLength,
|
|
estimatedTorrentLength,
|
|
opts,
|
|
(err, pieces, torrentLength) => {
|
|
if (err) return cb(err)
|
|
torrent.info.pieces = pieces
|
|
|
|
files.forEach(file => {
|
|
delete file.getStream
|
|
})
|
|
|
|
if (opts.singleFileTorrent) {
|
|
torrent.info.length = torrentLength
|
|
} else {
|
|
torrent.info.files = files
|
|
}
|
|
|
|
cb(null, bencode.encode(torrent))
|
|
}
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Determine if a a file is junk based on its path
|
|
* (defined as hidden OR recognized by the `junk` package)
|
|
*
|
|
* @param {string} path
|
|
* @return {boolean}
|
|
*/
|
|
function isJunkPath (path) {
|
|
const filename = path[path.length - 1]
|
|
return filename[0] === '.' && junk.is(filename)
|
|
}
|
|
|
|
/**
|
|
* Accumulator to sum file lengths
|
|
* @param {number} sum
|
|
* @param {Object} file
|
|
* @return {number}
|
|
*/
|
|
function sumLength (sum, file) {
|
|
return sum + file.length
|
|
}
|
|
|
|
/**
|
|
* Check if `obj` is a W3C `Blob` object (which `File` inherits from)
|
|
* @param {*} obj
|
|
* @return {boolean}
|
|
*/
|
|
function isBlob (obj) {
|
|
return typeof Blob !== 'undefined' && obj instanceof Blob
|
|
}
|
|
|
|
/**
|
|
* Check if `obj` is a W3C `FileList` object
|
|
* @param {*} obj
|
|
* @return {boolean}
|
|
*/
|
|
function isFileList (obj) {
|
|
return typeof FileList !== 'undefined' && obj instanceof FileList
|
|
}
|
|
|
|
/**
|
|
* Check if `obj` is a node Readable stream
|
|
* @param {*} obj
|
|
* @return {boolean}
|
|
*/
|
|
function isReadable (obj) {
|
|
return typeof obj === 'object' && obj != null && typeof obj.pipe === 'function'
|
|
}
|
|
|
|
/**
|
|
* Convert a `File` to a lazy readable stream.
|
|
* @param {File|Blob} file
|
|
* @return {function}
|
|
*/
|
|
function getBlobStream (file) {
|
|
return () => new FileReadStream(file)
|
|
}
|
|
|
|
/**
|
|
* Convert a `Buffer` to a lazy readable stream.
|
|
* @param {Buffer} buffer
|
|
* @return {function}
|
|
*/
|
|
function getBufferStream (buffer) {
|
|
return () => {
|
|
const s = new stream.PassThrough()
|
|
s.end(buffer)
|
|
return s
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert a readable stream to a lazy readable stream. Adds instrumentation to track
|
|
* the number of bytes in the stream and set `file.length`.
|
|
*
|
|
* @param {Stream} readable
|
|
* @param {Object} file
|
|
* @return {function}
|
|
*/
|
|
function getStreamStream (readable, file) {
|
|
return () => {
|
|
const counter = new stream.Transform()
|
|
counter._transform = function (buf, enc, done) {
|
|
file.length += buf.length
|
|
this.push(buf)
|
|
done()
|
|
}
|
|
readable.pipe(counter)
|
|
return counter
|
|
}
|
|
}
|
|
|
|
module.exports = createTorrent
|
|
module.exports.parseInput = parseInput
|
|
module.exports.announceList = announceList
|
|
module.exports.isJunkPath = isJunkPath
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/crypto-browserify/index.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/crypto-browserify/index.js ***!
|
|
\*************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js")
|
|
exports.createHash = exports.Hash = __webpack_require__(/*! create-hash */ "./node_modules/create-hash/browser.js")
|
|
exports.createHmac = exports.Hmac = __webpack_require__(/*! create-hmac */ "./node_modules/create-hmac/browser.js")
|
|
|
|
var algos = __webpack_require__(/*! browserify-sign/algos */ "./node_modules/browserify-sign/algos.js")
|
|
var algoKeys = Object.keys(algos)
|
|
var hashes = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'].concat(algoKeys)
|
|
exports.getHashes = function () {
|
|
return hashes
|
|
}
|
|
|
|
var p = __webpack_require__(/*! pbkdf2 */ "./node_modules/pbkdf2/browser.js")
|
|
exports.pbkdf2 = p.pbkdf2
|
|
exports.pbkdf2Sync = p.pbkdf2Sync
|
|
|
|
var aes = __webpack_require__(/*! browserify-cipher */ "./node_modules/browserify-cipher/browser.js")
|
|
|
|
exports.Cipher = aes.Cipher
|
|
exports.createCipher = aes.createCipher
|
|
exports.Cipheriv = aes.Cipheriv
|
|
exports.createCipheriv = aes.createCipheriv
|
|
exports.Decipher = aes.Decipher
|
|
exports.createDecipher = aes.createDecipher
|
|
exports.Decipheriv = aes.Decipheriv
|
|
exports.createDecipheriv = aes.createDecipheriv
|
|
exports.getCiphers = aes.getCiphers
|
|
exports.listCiphers = aes.listCiphers
|
|
|
|
var dh = __webpack_require__(/*! diffie-hellman */ "./node_modules/diffie-hellman/browser.js")
|
|
|
|
exports.DiffieHellmanGroup = dh.DiffieHellmanGroup
|
|
exports.createDiffieHellmanGroup = dh.createDiffieHellmanGroup
|
|
exports.getDiffieHellman = dh.getDiffieHellman
|
|
exports.createDiffieHellman = dh.createDiffieHellman
|
|
exports.DiffieHellman = dh.DiffieHellman
|
|
|
|
var sign = __webpack_require__(/*! browserify-sign */ "./node_modules/browserify-sign/browser/index.js")
|
|
|
|
exports.createSign = sign.createSign
|
|
exports.Sign = sign.Sign
|
|
exports.createVerify = sign.createVerify
|
|
exports.Verify = sign.Verify
|
|
|
|
exports.createECDH = __webpack_require__(/*! create-ecdh */ "./node_modules/create-ecdh/browser.js")
|
|
|
|
var publicEncrypt = __webpack_require__(/*! public-encrypt */ "./node_modules/public-encrypt/browser.js")
|
|
|
|
exports.publicEncrypt = publicEncrypt.publicEncrypt
|
|
exports.privateEncrypt = publicEncrypt.privateEncrypt
|
|
exports.publicDecrypt = publicEncrypt.publicDecrypt
|
|
exports.privateDecrypt = publicEncrypt.privateDecrypt
|
|
|
|
// the least I can do is make error messages for the rest of the node.js/crypto api.
|
|
// ;[
|
|
// 'createCredentials'
|
|
// ].forEach(function (name) {
|
|
// exports[name] = function () {
|
|
// throw new Error([
|
|
// 'sorry, ' + name + ' is not implemented yet',
|
|
// 'we accept pull requests',
|
|
// 'https://github.com/crypto-browserify/crypto-browserify'
|
|
// ].join('\n'))
|
|
// }
|
|
// })
|
|
|
|
var rf = __webpack_require__(/*! randomfill */ "./node_modules/randomfill/browser.js")
|
|
|
|
exports.randomFill = rf.randomFill
|
|
exports.randomFillSync = rf.randomFillSync
|
|
|
|
exports.createCredentials = function () {
|
|
throw new Error([
|
|
'sorry, createCredentials is not implemented yet',
|
|
'we accept pull requests',
|
|
'https://github.com/crypto-browserify/crypto-browserify'
|
|
].join('\n'))
|
|
}
|
|
|
|
exports.constants = {
|
|
'DH_CHECK_P_NOT_SAFE_PRIME': 2,
|
|
'DH_CHECK_P_NOT_PRIME': 1,
|
|
'DH_UNABLE_TO_CHECK_GENERATOR': 4,
|
|
'DH_NOT_SUITABLE_GENERATOR': 8,
|
|
'NPN_ENABLED': 1,
|
|
'ALPN_ENABLED': 1,
|
|
'RSA_PKCS1_PADDING': 1,
|
|
'RSA_SSLV23_PADDING': 2,
|
|
'RSA_NO_PADDING': 3,
|
|
'RSA_PKCS1_OAEP_PADDING': 4,
|
|
'RSA_X931_PADDING': 5,
|
|
'RSA_PKCS1_PSS_PADDING': 6,
|
|
'POINT_CONVERSION_COMPRESSED': 2,
|
|
'POINT_CONVERSION_UNCOMPRESSED': 4,
|
|
'POINT_CONVERSION_HYBRID': 6
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/debug/src/browser.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/debug/src/browser.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
/* eslint-env browser */
|
|
|
|
/**
|
|
* This is the web browser implementation of `debug()`.
|
|
*/
|
|
|
|
exports.formatArgs = formatArgs;
|
|
exports.save = save;
|
|
exports.load = load;
|
|
exports.useColors = useColors;
|
|
exports.storage = localstorage();
|
|
exports.destroy = (() => {
|
|
let warned = false;
|
|
|
|
return () => {
|
|
if (!warned) {
|
|
warned = true;
|
|
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
|
}
|
|
};
|
|
})();
|
|
|
|
/**
|
|
* Colors.
|
|
*/
|
|
|
|
exports.colors = [
|
|
'#0000CC',
|
|
'#0000FF',
|
|
'#0033CC',
|
|
'#0033FF',
|
|
'#0066CC',
|
|
'#0066FF',
|
|
'#0099CC',
|
|
'#0099FF',
|
|
'#00CC00',
|
|
'#00CC33',
|
|
'#00CC66',
|
|
'#00CC99',
|
|
'#00CCCC',
|
|
'#00CCFF',
|
|
'#3300CC',
|
|
'#3300FF',
|
|
'#3333CC',
|
|
'#3333FF',
|
|
'#3366CC',
|
|
'#3366FF',
|
|
'#3399CC',
|
|
'#3399FF',
|
|
'#33CC00',
|
|
'#33CC33',
|
|
'#33CC66',
|
|
'#33CC99',
|
|
'#33CCCC',
|
|
'#33CCFF',
|
|
'#6600CC',
|
|
'#6600FF',
|
|
'#6633CC',
|
|
'#6633FF',
|
|
'#66CC00',
|
|
'#66CC33',
|
|
'#9900CC',
|
|
'#9900FF',
|
|
'#9933CC',
|
|
'#9933FF',
|
|
'#99CC00',
|
|
'#99CC33',
|
|
'#CC0000',
|
|
'#CC0033',
|
|
'#CC0066',
|
|
'#CC0099',
|
|
'#CC00CC',
|
|
'#CC00FF',
|
|
'#CC3300',
|
|
'#CC3333',
|
|
'#CC3366',
|
|
'#CC3399',
|
|
'#CC33CC',
|
|
'#CC33FF',
|
|
'#CC6600',
|
|
'#CC6633',
|
|
'#CC9900',
|
|
'#CC9933',
|
|
'#CCCC00',
|
|
'#CCCC33',
|
|
'#FF0000',
|
|
'#FF0033',
|
|
'#FF0066',
|
|
'#FF0099',
|
|
'#FF00CC',
|
|
'#FF00FF',
|
|
'#FF3300',
|
|
'#FF3333',
|
|
'#FF3366',
|
|
'#FF3399',
|
|
'#FF33CC',
|
|
'#FF33FF',
|
|
'#FF6600',
|
|
'#FF6633',
|
|
'#FF9900',
|
|
'#FF9933',
|
|
'#FFCC00',
|
|
'#FFCC33'
|
|
];
|
|
|
|
/**
|
|
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
|
|
* and the Firebug extension (any Firefox version) are known
|
|
* to support "%c" CSS customizations.
|
|
*
|
|
* TODO: add a `localStorage` variable to explicitly enable/disable colors
|
|
*/
|
|
|
|
// eslint-disable-next-line complexity
|
|
function useColors() {
|
|
// NB: In an Electron preload script, document will be defined but not fully
|
|
// initialized. Since we know we're in Chrome, we'll just detect this case
|
|
// explicitly
|
|
if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
|
|
return true;
|
|
}
|
|
|
|
// Internet Explorer and Edge do not support colors.
|
|
if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
|
|
return false;
|
|
}
|
|
|
|
// Is webkit? http://stackoverflow.com/a/16459606/376773
|
|
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
|
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
|
|
// Is firebug? http://stackoverflow.com/a/398120/376773
|
|
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
|
|
// Is firefox >= v31?
|
|
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
|
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
|
|
// Double check webkit in userAgent just in case we are in a worker
|
|
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
|
|
}
|
|
|
|
/**
|
|
* Colorize log arguments if enabled.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
function formatArgs(args) {
|
|
args[0] = (this.useColors ? '%c' : '') +
|
|
this.namespace +
|
|
(this.useColors ? ' %c' : ' ') +
|
|
args[0] +
|
|
(this.useColors ? '%c ' : ' ') +
|
|
'+' + module.exports.humanize(this.diff);
|
|
|
|
if (!this.useColors) {
|
|
return;
|
|
}
|
|
|
|
const c = 'color: ' + this.color;
|
|
args.splice(1, 0, c, 'color: inherit');
|
|
|
|
// The final "%c" is somewhat tricky, because there could be other
|
|
// arguments passed either before or after the %c, so we need to
|
|
// figure out the correct index to insert the CSS into
|
|
let index = 0;
|
|
let lastC = 0;
|
|
args[0].replace(/%[a-zA-Z%]/g, match => {
|
|
if (match === '%%') {
|
|
return;
|
|
}
|
|
index++;
|
|
if (match === '%c') {
|
|
// We only are interested in the *last* %c
|
|
// (the user may have provided their own)
|
|
lastC = index;
|
|
}
|
|
});
|
|
|
|
args.splice(lastC, 0, c);
|
|
}
|
|
|
|
/**
|
|
* Invokes `console.debug()` when available.
|
|
* No-op when `console.debug` is not a "function".
|
|
* If `console.debug` is not available, falls back
|
|
* to `console.log`.
|
|
*
|
|
* @api public
|
|
*/
|
|
exports.log = console.debug || console.log || (() => {});
|
|
|
|
/**
|
|
* Save `namespaces`.
|
|
*
|
|
* @param {String} namespaces
|
|
* @api private
|
|
*/
|
|
function save(namespaces) {
|
|
try {
|
|
if (namespaces) {
|
|
exports.storage.setItem('debug', namespaces);
|
|
} else {
|
|
exports.storage.removeItem('debug');
|
|
}
|
|
} catch (error) {
|
|
// Swallow
|
|
// XXX (@Qix-) should we be logging these?
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load `namespaces`.
|
|
*
|
|
* @return {String} returns the previously persisted debug modes
|
|
* @api private
|
|
*/
|
|
function load() {
|
|
let r;
|
|
try {
|
|
r = exports.storage.getItem('debug');
|
|
} catch (error) {
|
|
// Swallow
|
|
// XXX (@Qix-) should we be logging these?
|
|
}
|
|
|
|
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
|
|
if (!r && typeof process !== 'undefined' && 'env' in process) {
|
|
r = process.env.DEBUG;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* Localstorage attempts to return the localstorage.
|
|
*
|
|
* This is necessary because safari throws
|
|
* when a user disables cookies/localstorage
|
|
* and you attempt to access it.
|
|
*
|
|
* @return {LocalStorage}
|
|
* @api private
|
|
*/
|
|
|
|
function localstorage() {
|
|
try {
|
|
// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
|
|
// The Browser also has localStorage in the global context.
|
|
return localStorage;
|
|
} catch (error) {
|
|
// Swallow
|
|
// XXX (@Qix-) should we be logging these?
|
|
}
|
|
}
|
|
|
|
module.exports = __webpack_require__(/*! ./common */ "./node_modules/debug/src/common.js")(exports);
|
|
|
|
const {formatters} = module.exports;
|
|
|
|
/**
|
|
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
|
*/
|
|
|
|
formatters.j = function (v) {
|
|
try {
|
|
return JSON.stringify(v);
|
|
} catch (error) {
|
|
return '[UnexpectedJSONParseError]: ' + error.message;
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/debug/src/common.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/debug/src/common.js ***!
|
|
\******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
|
|
/**
|
|
* This is the common logic for both the Node.js and web browser
|
|
* implementations of `debug()`.
|
|
*/
|
|
|
|
function setup(env) {
|
|
createDebug.debug = createDebug;
|
|
createDebug.default = createDebug;
|
|
createDebug.coerce = coerce;
|
|
createDebug.disable = disable;
|
|
createDebug.enable = enable;
|
|
createDebug.enabled = enabled;
|
|
createDebug.humanize = __webpack_require__(/*! ms */ "./node_modules/ms/index.js");
|
|
createDebug.destroy = destroy;
|
|
|
|
Object.keys(env).forEach(key => {
|
|
createDebug[key] = env[key];
|
|
});
|
|
|
|
/**
|
|
* The currently active debug mode names, and names to skip.
|
|
*/
|
|
|
|
createDebug.names = [];
|
|
createDebug.skips = [];
|
|
|
|
/**
|
|
* Map of special "%n" handling functions, for the debug "format" argument.
|
|
*
|
|
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
|
|
*/
|
|
createDebug.formatters = {};
|
|
|
|
/**
|
|
* Selects a color for a debug namespace
|
|
* @param {String} namespace The namespace string for the for the debug instance to be colored
|
|
* @return {Number|String} An ANSI color code for the given namespace
|
|
* @api private
|
|
*/
|
|
function selectColor(namespace) {
|
|
let hash = 0;
|
|
|
|
for (let i = 0; i < namespace.length; i++) {
|
|
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
|
|
hash |= 0; // Convert to 32bit integer
|
|
}
|
|
|
|
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
|
|
}
|
|
createDebug.selectColor = selectColor;
|
|
|
|
/**
|
|
* Create a debugger with the given `namespace`.
|
|
*
|
|
* @param {String} namespace
|
|
* @return {Function}
|
|
* @api public
|
|
*/
|
|
function createDebug(namespace) {
|
|
let prevTime;
|
|
let enableOverride = null;
|
|
let namespacesCache;
|
|
let enabledCache;
|
|
|
|
function debug(...args) {
|
|
// Disabled?
|
|
if (!debug.enabled) {
|
|
return;
|
|
}
|
|
|
|
const self = debug;
|
|
|
|
// Set `diff` timestamp
|
|
const curr = Number(new Date());
|
|
const ms = curr - (prevTime || curr);
|
|
self.diff = ms;
|
|
self.prev = prevTime;
|
|
self.curr = curr;
|
|
prevTime = curr;
|
|
|
|
args[0] = createDebug.coerce(args[0]);
|
|
|
|
if (typeof args[0] !== 'string') {
|
|
// Anything else let's inspect with %O
|
|
args.unshift('%O');
|
|
}
|
|
|
|
// Apply any `formatters` transformations
|
|
let index = 0;
|
|
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
|
// If we encounter an escaped % then don't increase the array index
|
|
if (match === '%%') {
|
|
return '%';
|
|
}
|
|
index++;
|
|
const formatter = createDebug.formatters[format];
|
|
if (typeof formatter === 'function') {
|
|
const val = args[index];
|
|
match = formatter.call(self, val);
|
|
|
|
// Now we need to remove `args[index]` since it's inlined in the `format`
|
|
args.splice(index, 1);
|
|
index--;
|
|
}
|
|
return match;
|
|
});
|
|
|
|
// Apply env-specific formatting (colors, etc.)
|
|
createDebug.formatArgs.call(self, args);
|
|
|
|
const logFn = self.log || createDebug.log;
|
|
logFn.apply(self, args);
|
|
}
|
|
|
|
debug.namespace = namespace;
|
|
debug.useColors = createDebug.useColors();
|
|
debug.color = createDebug.selectColor(namespace);
|
|
debug.extend = extend;
|
|
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
|
|
|
|
Object.defineProperty(debug, 'enabled', {
|
|
enumerable: true,
|
|
configurable: false,
|
|
get: () => {
|
|
if (enableOverride !== null) {
|
|
return enableOverride;
|
|
}
|
|
if (namespacesCache !== createDebug.namespaces) {
|
|
namespacesCache = createDebug.namespaces;
|
|
enabledCache = createDebug.enabled(namespace);
|
|
}
|
|
|
|
return enabledCache;
|
|
},
|
|
set: v => {
|
|
enableOverride = v;
|
|
}
|
|
});
|
|
|
|
// Env-specific initialization logic for debug instances
|
|
if (typeof createDebug.init === 'function') {
|
|
createDebug.init(debug);
|
|
}
|
|
|
|
return debug;
|
|
}
|
|
|
|
function extend(namespace, delimiter) {
|
|
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
|
|
newDebug.log = this.log;
|
|
return newDebug;
|
|
}
|
|
|
|
/**
|
|
* Enables a debug mode by namespaces. This can include modes
|
|
* separated by a colon and wildcards.
|
|
*
|
|
* @param {String} namespaces
|
|
* @api public
|
|
*/
|
|
function enable(namespaces) {
|
|
createDebug.save(namespaces);
|
|
createDebug.namespaces = namespaces;
|
|
|
|
createDebug.names = [];
|
|
createDebug.skips = [];
|
|
|
|
let i;
|
|
const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
|
|
const len = split.length;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (!split[i]) {
|
|
// ignore empty strings
|
|
continue;
|
|
}
|
|
|
|
namespaces = split[i].replace(/\*/g, '.*?');
|
|
|
|
if (namespaces[0] === '-') {
|
|
createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
|
|
} else {
|
|
createDebug.names.push(new RegExp('^' + namespaces + '$'));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable debug output.
|
|
*
|
|
* @return {String} namespaces
|
|
* @api public
|
|
*/
|
|
function disable() {
|
|
const namespaces = [
|
|
...createDebug.names.map(toNamespace),
|
|
...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
|
|
].join(',');
|
|
createDebug.enable('');
|
|
return namespaces;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given mode name is enabled, false otherwise.
|
|
*
|
|
* @param {String} name
|
|
* @return {Boolean}
|
|
* @api public
|
|
*/
|
|
function enabled(name) {
|
|
if (name[name.length - 1] === '*') {
|
|
return true;
|
|
}
|
|
|
|
let i;
|
|
let len;
|
|
|
|
for (i = 0, len = createDebug.skips.length; i < len; i++) {
|
|
if (createDebug.skips[i].test(name)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for (i = 0, len = createDebug.names.length; i < len; i++) {
|
|
if (createDebug.names[i].test(name)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Convert regexp to namespace
|
|
*
|
|
* @param {RegExp} regxep
|
|
* @return {String} namespace
|
|
* @api private
|
|
*/
|
|
function toNamespace(regexp) {
|
|
return regexp.toString()
|
|
.substring(2, regexp.toString().length - 2)
|
|
.replace(/\.\*\?$/, '*');
|
|
}
|
|
|
|
/**
|
|
* Coerce `val`.
|
|
*
|
|
* @param {Mixed} val
|
|
* @return {Mixed}
|
|
* @api private
|
|
*/
|
|
function coerce(val) {
|
|
if (val instanceof Error) {
|
|
return val.stack || val.message;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
/**
|
|
* XXX DO NOT USE. This is a temporary stub function.
|
|
* XXX It WILL be removed in the next major release.
|
|
*/
|
|
function destroy() {
|
|
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
|
}
|
|
|
|
createDebug.enable(createDebug.load());
|
|
|
|
return createDebug;
|
|
}
|
|
|
|
module.exports = setup;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/define-properties/index.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/define-properties/index.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var keys = __webpack_require__(/*! object-keys */ "./node_modules/object-keys/index.js");
|
|
var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol';
|
|
|
|
var toStr = Object.prototype.toString;
|
|
var concat = Array.prototype.concat;
|
|
var origDefineProperty = Object.defineProperty;
|
|
|
|
var isFunction = function (fn) {
|
|
return typeof fn === 'function' && toStr.call(fn) === '[object Function]';
|
|
};
|
|
|
|
var arePropertyDescriptorsSupported = function () {
|
|
var obj = {};
|
|
try {
|
|
origDefineProperty(obj, 'x', { enumerable: false, value: obj });
|
|
// eslint-disable-next-line no-unused-vars, no-restricted-syntax
|
|
for (var _ in obj) { // jscs:ignore disallowUnusedVariables
|
|
return false;
|
|
}
|
|
return obj.x === obj;
|
|
} catch (e) { /* this is IE 8. */
|
|
return false;
|
|
}
|
|
};
|
|
var supportsDescriptors = origDefineProperty && arePropertyDescriptorsSupported();
|
|
|
|
var defineProperty = function (object, name, value, predicate) {
|
|
if (name in object && (!isFunction(predicate) || !predicate())) {
|
|
return;
|
|
}
|
|
if (supportsDescriptors) {
|
|
origDefineProperty(object, name, {
|
|
configurable: true,
|
|
enumerable: false,
|
|
value: value,
|
|
writable: true
|
|
});
|
|
} else {
|
|
object[name] = value;
|
|
}
|
|
};
|
|
|
|
var defineProperties = function (object, map) {
|
|
var predicates = arguments.length > 2 ? arguments[2] : {};
|
|
var props = keys(map);
|
|
if (hasSymbols) {
|
|
props = concat.call(props, Object.getOwnPropertySymbols(map));
|
|
}
|
|
for (var i = 0; i < props.length; i += 1) {
|
|
defineProperty(object, props[i], map[props[i]], predicates[props[i]]);
|
|
}
|
|
};
|
|
|
|
defineProperties.supportsDescriptors = !!supportsDescriptors;
|
|
|
|
module.exports = defineProperties;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/des.js/lib/des.js":
|
|
/*!****************************************!*\
|
|
!*** ./node_modules/des.js/lib/des.js ***!
|
|
\****************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
exports.utils = __webpack_require__(/*! ./des/utils */ "./node_modules/des.js/lib/des/utils.js");
|
|
exports.Cipher = __webpack_require__(/*! ./des/cipher */ "./node_modules/des.js/lib/des/cipher.js");
|
|
exports.DES = __webpack_require__(/*! ./des/des */ "./node_modules/des.js/lib/des/des.js");
|
|
exports.CBC = __webpack_require__(/*! ./des/cbc */ "./node_modules/des.js/lib/des/cbc.js");
|
|
exports.EDE = __webpack_require__(/*! ./des/ede */ "./node_modules/des.js/lib/des/ede.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/des.js/lib/des/cbc.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/des.js/lib/des/cbc.js ***!
|
|
\********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
|
|
var proto = {};
|
|
|
|
function CBCState(iv) {
|
|
assert.equal(iv.length, 8, 'Invalid IV length');
|
|
|
|
this.iv = new Array(8);
|
|
for (var i = 0; i < this.iv.length; i++)
|
|
this.iv[i] = iv[i];
|
|
}
|
|
|
|
function instantiate(Base) {
|
|
function CBC(options) {
|
|
Base.call(this, options);
|
|
this._cbcInit();
|
|
}
|
|
inherits(CBC, Base);
|
|
|
|
var keys = Object.keys(proto);
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var key = keys[i];
|
|
CBC.prototype[key] = proto[key];
|
|
}
|
|
|
|
CBC.create = function create(options) {
|
|
return new CBC(options);
|
|
};
|
|
|
|
return CBC;
|
|
}
|
|
|
|
exports.instantiate = instantiate;
|
|
|
|
proto._cbcInit = function _cbcInit() {
|
|
var state = new CBCState(this.options.iv);
|
|
this._cbcState = state;
|
|
};
|
|
|
|
proto._update = function _update(inp, inOff, out, outOff) {
|
|
var state = this._cbcState;
|
|
var superProto = this.constructor.super_.prototype;
|
|
|
|
var iv = state.iv;
|
|
if (this.type === 'encrypt') {
|
|
for (var i = 0; i < this.blockSize; i++)
|
|
iv[i] ^= inp[inOff + i];
|
|
|
|
superProto._update.call(this, iv, 0, out, outOff);
|
|
|
|
for (var i = 0; i < this.blockSize; i++)
|
|
iv[i] = out[outOff + i];
|
|
} else {
|
|
superProto._update.call(this, inp, inOff, out, outOff);
|
|
|
|
for (var i = 0; i < this.blockSize; i++)
|
|
out[outOff + i] ^= iv[i];
|
|
|
|
for (var i = 0; i < this.blockSize; i++)
|
|
iv[i] = inp[inOff + i];
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/des.js/lib/des/cipher.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/des.js/lib/des/cipher.js ***!
|
|
\***********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
|
|
function Cipher(options) {
|
|
this.options = options;
|
|
|
|
this.type = this.options.type;
|
|
this.blockSize = 8;
|
|
this._init();
|
|
|
|
this.buffer = new Array(this.blockSize);
|
|
this.bufferOff = 0;
|
|
}
|
|
module.exports = Cipher;
|
|
|
|
Cipher.prototype._init = function _init() {
|
|
// Might be overrided
|
|
};
|
|
|
|
Cipher.prototype.update = function update(data) {
|
|
if (data.length === 0)
|
|
return [];
|
|
|
|
if (this.type === 'decrypt')
|
|
return this._updateDecrypt(data);
|
|
else
|
|
return this._updateEncrypt(data);
|
|
};
|
|
|
|
Cipher.prototype._buffer = function _buffer(data, off) {
|
|
// Append data to buffer
|
|
var min = Math.min(this.buffer.length - this.bufferOff, data.length - off);
|
|
for (var i = 0; i < min; i++)
|
|
this.buffer[this.bufferOff + i] = data[off + i];
|
|
this.bufferOff += min;
|
|
|
|
// Shift next
|
|
return min;
|
|
};
|
|
|
|
Cipher.prototype._flushBuffer = function _flushBuffer(out, off) {
|
|
this._update(this.buffer, 0, out, off);
|
|
this.bufferOff = 0;
|
|
return this.blockSize;
|
|
};
|
|
|
|
Cipher.prototype._updateEncrypt = function _updateEncrypt(data) {
|
|
var inputOff = 0;
|
|
var outputOff = 0;
|
|
|
|
var count = ((this.bufferOff + data.length) / this.blockSize) | 0;
|
|
var out = new Array(count * this.blockSize);
|
|
|
|
if (this.bufferOff !== 0) {
|
|
inputOff += this._buffer(data, inputOff);
|
|
|
|
if (this.bufferOff === this.buffer.length)
|
|
outputOff += this._flushBuffer(out, outputOff);
|
|
}
|
|
|
|
// Write blocks
|
|
var max = data.length - ((data.length - inputOff) % this.blockSize);
|
|
for (; inputOff < max; inputOff += this.blockSize) {
|
|
this._update(data, inputOff, out, outputOff);
|
|
outputOff += this.blockSize;
|
|
}
|
|
|
|
// Queue rest
|
|
for (; inputOff < data.length; inputOff++, this.bufferOff++)
|
|
this.buffer[this.bufferOff] = data[inputOff];
|
|
|
|
return out;
|
|
};
|
|
|
|
Cipher.prototype._updateDecrypt = function _updateDecrypt(data) {
|
|
var inputOff = 0;
|
|
var outputOff = 0;
|
|
|
|
var count = Math.ceil((this.bufferOff + data.length) / this.blockSize) - 1;
|
|
var out = new Array(count * this.blockSize);
|
|
|
|
// TODO(indutny): optimize it, this is far from optimal
|
|
for (; count > 0; count--) {
|
|
inputOff += this._buffer(data, inputOff);
|
|
outputOff += this._flushBuffer(out, outputOff);
|
|
}
|
|
|
|
// Buffer rest of the input
|
|
inputOff += this._buffer(data, inputOff);
|
|
|
|
return out;
|
|
};
|
|
|
|
Cipher.prototype.final = function final(buffer) {
|
|
var first;
|
|
if (buffer)
|
|
first = this.update(buffer);
|
|
|
|
var last;
|
|
if (this.type === 'encrypt')
|
|
last = this._finalEncrypt();
|
|
else
|
|
last = this._finalDecrypt();
|
|
|
|
if (first)
|
|
return first.concat(last);
|
|
else
|
|
return last;
|
|
};
|
|
|
|
Cipher.prototype._pad = function _pad(buffer, off) {
|
|
if (off === 0)
|
|
return false;
|
|
|
|
while (off < buffer.length)
|
|
buffer[off++] = 0;
|
|
|
|
return true;
|
|
};
|
|
|
|
Cipher.prototype._finalEncrypt = function _finalEncrypt() {
|
|
if (!this._pad(this.buffer, this.bufferOff))
|
|
return [];
|
|
|
|
var out = new Array(this.blockSize);
|
|
this._update(this.buffer, 0, out, 0);
|
|
return out;
|
|
};
|
|
|
|
Cipher.prototype._unpad = function _unpad(buffer) {
|
|
return buffer;
|
|
};
|
|
|
|
Cipher.prototype._finalDecrypt = function _finalDecrypt() {
|
|
assert.equal(this.bufferOff, this.blockSize, 'Not enough data to decrypt');
|
|
var out = new Array(this.blockSize);
|
|
this._flushBuffer(out, 0);
|
|
|
|
return this._unpad(out);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/des.js/lib/des/des.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/des.js/lib/des/des.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
|
|
var utils = __webpack_require__(/*! ./utils */ "./node_modules/des.js/lib/des/utils.js");
|
|
var Cipher = __webpack_require__(/*! ./cipher */ "./node_modules/des.js/lib/des/cipher.js");
|
|
|
|
function DESState() {
|
|
this.tmp = new Array(2);
|
|
this.keys = null;
|
|
}
|
|
|
|
function DES(options) {
|
|
Cipher.call(this, options);
|
|
|
|
var state = new DESState();
|
|
this._desState = state;
|
|
|
|
this.deriveKeys(state, options.key);
|
|
}
|
|
inherits(DES, Cipher);
|
|
module.exports = DES;
|
|
|
|
DES.create = function create(options) {
|
|
return new DES(options);
|
|
};
|
|
|
|
var shiftTable = [
|
|
1, 1, 2, 2, 2, 2, 2, 2,
|
|
1, 2, 2, 2, 2, 2, 2, 1
|
|
];
|
|
|
|
DES.prototype.deriveKeys = function deriveKeys(state, key) {
|
|
state.keys = new Array(16 * 2);
|
|
|
|
assert.equal(key.length, this.blockSize, 'Invalid key length');
|
|
|
|
var kL = utils.readUInt32BE(key, 0);
|
|
var kR = utils.readUInt32BE(key, 4);
|
|
|
|
utils.pc1(kL, kR, state.tmp, 0);
|
|
kL = state.tmp[0];
|
|
kR = state.tmp[1];
|
|
for (var i = 0; i < state.keys.length; i += 2) {
|
|
var shift = shiftTable[i >>> 1];
|
|
kL = utils.r28shl(kL, shift);
|
|
kR = utils.r28shl(kR, shift);
|
|
utils.pc2(kL, kR, state.keys, i);
|
|
}
|
|
};
|
|
|
|
DES.prototype._update = function _update(inp, inOff, out, outOff) {
|
|
var state = this._desState;
|
|
|
|
var l = utils.readUInt32BE(inp, inOff);
|
|
var r = utils.readUInt32BE(inp, inOff + 4);
|
|
|
|
// Initial Permutation
|
|
utils.ip(l, r, state.tmp, 0);
|
|
l = state.tmp[0];
|
|
r = state.tmp[1];
|
|
|
|
if (this.type === 'encrypt')
|
|
this._encrypt(state, l, r, state.tmp, 0);
|
|
else
|
|
this._decrypt(state, l, r, state.tmp, 0);
|
|
|
|
l = state.tmp[0];
|
|
r = state.tmp[1];
|
|
|
|
utils.writeUInt32BE(out, l, outOff);
|
|
utils.writeUInt32BE(out, r, outOff + 4);
|
|
};
|
|
|
|
DES.prototype._pad = function _pad(buffer, off) {
|
|
var value = buffer.length - off;
|
|
for (var i = off; i < buffer.length; i++)
|
|
buffer[i] = value;
|
|
|
|
return true;
|
|
};
|
|
|
|
DES.prototype._unpad = function _unpad(buffer) {
|
|
var pad = buffer[buffer.length - 1];
|
|
for (var i = buffer.length - pad; i < buffer.length; i++)
|
|
assert.equal(buffer[i], pad);
|
|
|
|
return buffer.slice(0, buffer.length - pad);
|
|
};
|
|
|
|
DES.prototype._encrypt = function _encrypt(state, lStart, rStart, out, off) {
|
|
var l = lStart;
|
|
var r = rStart;
|
|
|
|
// Apply f() x16 times
|
|
for (var i = 0; i < state.keys.length; i += 2) {
|
|
var keyL = state.keys[i];
|
|
var keyR = state.keys[i + 1];
|
|
|
|
// f(r, k)
|
|
utils.expand(r, state.tmp, 0);
|
|
|
|
keyL ^= state.tmp[0];
|
|
keyR ^= state.tmp[1];
|
|
var s = utils.substitute(keyL, keyR);
|
|
var f = utils.permute(s);
|
|
|
|
var t = r;
|
|
r = (l ^ f) >>> 0;
|
|
l = t;
|
|
}
|
|
|
|
// Reverse Initial Permutation
|
|
utils.rip(r, l, out, off);
|
|
};
|
|
|
|
DES.prototype._decrypt = function _decrypt(state, lStart, rStart, out, off) {
|
|
var l = rStart;
|
|
var r = lStart;
|
|
|
|
// Apply f() x16 times
|
|
for (var i = state.keys.length - 2; i >= 0; i -= 2) {
|
|
var keyL = state.keys[i];
|
|
var keyR = state.keys[i + 1];
|
|
|
|
// f(r, k)
|
|
utils.expand(l, state.tmp, 0);
|
|
|
|
keyL ^= state.tmp[0];
|
|
keyR ^= state.tmp[1];
|
|
var s = utils.substitute(keyL, keyR);
|
|
var f = utils.permute(s);
|
|
|
|
var t = l;
|
|
l = (r ^ f) >>> 0;
|
|
r = t;
|
|
}
|
|
|
|
// Reverse Initial Permutation
|
|
utils.rip(l, r, out, off);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/des.js/lib/des/ede.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/des.js/lib/des/ede.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
|
|
var Cipher = __webpack_require__(/*! ./cipher */ "./node_modules/des.js/lib/des/cipher.js");
|
|
var DES = __webpack_require__(/*! ./des */ "./node_modules/des.js/lib/des/des.js");
|
|
|
|
function EDEState(type, key) {
|
|
assert.equal(key.length, 24, 'Invalid key length');
|
|
|
|
var k1 = key.slice(0, 8);
|
|
var k2 = key.slice(8, 16);
|
|
var k3 = key.slice(16, 24);
|
|
|
|
if (type === 'encrypt') {
|
|
this.ciphers = [
|
|
DES.create({ type: 'encrypt', key: k1 }),
|
|
DES.create({ type: 'decrypt', key: k2 }),
|
|
DES.create({ type: 'encrypt', key: k3 })
|
|
];
|
|
} else {
|
|
this.ciphers = [
|
|
DES.create({ type: 'decrypt', key: k3 }),
|
|
DES.create({ type: 'encrypt', key: k2 }),
|
|
DES.create({ type: 'decrypt', key: k1 })
|
|
];
|
|
}
|
|
}
|
|
|
|
function EDE(options) {
|
|
Cipher.call(this, options);
|
|
|
|
var state = new EDEState(this.type, this.options.key);
|
|
this._edeState = state;
|
|
}
|
|
inherits(EDE, Cipher);
|
|
|
|
module.exports = EDE;
|
|
|
|
EDE.create = function create(options) {
|
|
return new EDE(options);
|
|
};
|
|
|
|
EDE.prototype._update = function _update(inp, inOff, out, outOff) {
|
|
var state = this._edeState;
|
|
|
|
state.ciphers[0]._update(inp, inOff, out, outOff);
|
|
state.ciphers[1]._update(out, outOff, out, outOff);
|
|
state.ciphers[2]._update(out, outOff, out, outOff);
|
|
};
|
|
|
|
EDE.prototype._pad = DES.prototype._pad;
|
|
EDE.prototype._unpad = DES.prototype._unpad;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/des.js/lib/des/utils.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/des.js/lib/des/utils.js ***!
|
|
\**********************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
exports.readUInt32BE = function readUInt32BE(bytes, off) {
|
|
var res = (bytes[0 + off] << 24) |
|
|
(bytes[1 + off] << 16) |
|
|
(bytes[2 + off] << 8) |
|
|
bytes[3 + off];
|
|
return res >>> 0;
|
|
};
|
|
|
|
exports.writeUInt32BE = function writeUInt32BE(bytes, value, off) {
|
|
bytes[0 + off] = value >>> 24;
|
|
bytes[1 + off] = (value >>> 16) & 0xff;
|
|
bytes[2 + off] = (value >>> 8) & 0xff;
|
|
bytes[3 + off] = value & 0xff;
|
|
};
|
|
|
|
exports.ip = function ip(inL, inR, out, off) {
|
|
var outL = 0;
|
|
var outR = 0;
|
|
|
|
for (var i = 6; i >= 0; i -= 2) {
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outL <<= 1;
|
|
outL |= (inR >>> (j + i)) & 1;
|
|
}
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outL <<= 1;
|
|
outL |= (inL >>> (j + i)) & 1;
|
|
}
|
|
}
|
|
|
|
for (var i = 6; i >= 0; i -= 2) {
|
|
for (var j = 1; j <= 25; j += 8) {
|
|
outR <<= 1;
|
|
outR |= (inR >>> (j + i)) & 1;
|
|
}
|
|
for (var j = 1; j <= 25; j += 8) {
|
|
outR <<= 1;
|
|
outR |= (inL >>> (j + i)) & 1;
|
|
}
|
|
}
|
|
|
|
out[off + 0] = outL >>> 0;
|
|
out[off + 1] = outR >>> 0;
|
|
};
|
|
|
|
exports.rip = function rip(inL, inR, out, off) {
|
|
var outL = 0;
|
|
var outR = 0;
|
|
|
|
for (var i = 0; i < 4; i++) {
|
|
for (var j = 24; j >= 0; j -= 8) {
|
|
outL <<= 1;
|
|
outL |= (inR >>> (j + i)) & 1;
|
|
outL <<= 1;
|
|
outL |= (inL >>> (j + i)) & 1;
|
|
}
|
|
}
|
|
for (var i = 4; i < 8; i++) {
|
|
for (var j = 24; j >= 0; j -= 8) {
|
|
outR <<= 1;
|
|
outR |= (inR >>> (j + i)) & 1;
|
|
outR <<= 1;
|
|
outR |= (inL >>> (j + i)) & 1;
|
|
}
|
|
}
|
|
|
|
out[off + 0] = outL >>> 0;
|
|
out[off + 1] = outR >>> 0;
|
|
};
|
|
|
|
exports.pc1 = function pc1(inL, inR, out, off) {
|
|
var outL = 0;
|
|
var outR = 0;
|
|
|
|
// 7, 15, 23, 31, 39, 47, 55, 63
|
|
// 6, 14, 22, 30, 39, 47, 55, 63
|
|
// 5, 13, 21, 29, 39, 47, 55, 63
|
|
// 4, 12, 20, 28
|
|
for (var i = 7; i >= 5; i--) {
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outL <<= 1;
|
|
outL |= (inR >> (j + i)) & 1;
|
|
}
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outL <<= 1;
|
|
outL |= (inL >> (j + i)) & 1;
|
|
}
|
|
}
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outL <<= 1;
|
|
outL |= (inR >> (j + i)) & 1;
|
|
}
|
|
|
|
// 1, 9, 17, 25, 33, 41, 49, 57
|
|
// 2, 10, 18, 26, 34, 42, 50, 58
|
|
// 3, 11, 19, 27, 35, 43, 51, 59
|
|
// 36, 44, 52, 60
|
|
for (var i = 1; i <= 3; i++) {
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outR <<= 1;
|
|
outR |= (inR >> (j + i)) & 1;
|
|
}
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outR <<= 1;
|
|
outR |= (inL >> (j + i)) & 1;
|
|
}
|
|
}
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outR <<= 1;
|
|
outR |= (inL >> (j + i)) & 1;
|
|
}
|
|
|
|
out[off + 0] = outL >>> 0;
|
|
out[off + 1] = outR >>> 0;
|
|
};
|
|
|
|
exports.r28shl = function r28shl(num, shift) {
|
|
return ((num << shift) & 0xfffffff) | (num >>> (28 - shift));
|
|
};
|
|
|
|
var pc2table = [
|
|
// inL => outL
|
|
14, 11, 17, 4, 27, 23, 25, 0,
|
|
13, 22, 7, 18, 5, 9, 16, 24,
|
|
2, 20, 12, 21, 1, 8, 15, 26,
|
|
|
|
// inR => outR
|
|
15, 4, 25, 19, 9, 1, 26, 16,
|
|
5, 11, 23, 8, 12, 7, 17, 0,
|
|
22, 3, 10, 14, 6, 20, 27, 24
|
|
];
|
|
|
|
exports.pc2 = function pc2(inL, inR, out, off) {
|
|
var outL = 0;
|
|
var outR = 0;
|
|
|
|
var len = pc2table.length >>> 1;
|
|
for (var i = 0; i < len; i++) {
|
|
outL <<= 1;
|
|
outL |= (inL >>> pc2table[i]) & 0x1;
|
|
}
|
|
for (var i = len; i < pc2table.length; i++) {
|
|
outR <<= 1;
|
|
outR |= (inR >>> pc2table[i]) & 0x1;
|
|
}
|
|
|
|
out[off + 0] = outL >>> 0;
|
|
out[off + 1] = outR >>> 0;
|
|
};
|
|
|
|
exports.expand = function expand(r, out, off) {
|
|
var outL = 0;
|
|
var outR = 0;
|
|
|
|
outL = ((r & 1) << 5) | (r >>> 27);
|
|
for (var i = 23; i >= 15; i -= 4) {
|
|
outL <<= 6;
|
|
outL |= (r >>> i) & 0x3f;
|
|
}
|
|
for (var i = 11; i >= 3; i -= 4) {
|
|
outR |= (r >>> i) & 0x3f;
|
|
outR <<= 6;
|
|
}
|
|
outR |= ((r & 0x1f) << 1) | (r >>> 31);
|
|
|
|
out[off + 0] = outL >>> 0;
|
|
out[off + 1] = outR >>> 0;
|
|
};
|
|
|
|
var sTable = [
|
|
14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
|
|
3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
|
|
4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
|
|
15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13,
|
|
|
|
15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
|
|
9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
|
|
0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
|
|
5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9,
|
|
|
|
10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
|
|
1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
|
|
13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
|
|
11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12,
|
|
|
|
7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
|
|
1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
|
|
10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
|
|
15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14,
|
|
|
|
2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
|
|
8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
|
|
4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
|
|
15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3,
|
|
|
|
12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
|
|
0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
|
|
9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
|
|
7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13,
|
|
|
|
4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
|
|
3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
|
|
1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
|
|
10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12,
|
|
|
|
13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
|
|
10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
|
|
7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
|
|
0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
|
|
];
|
|
|
|
exports.substitute = function substitute(inL, inR) {
|
|
var out = 0;
|
|
for (var i = 0; i < 4; i++) {
|
|
var b = (inL >>> (18 - i * 6)) & 0x3f;
|
|
var sb = sTable[i * 0x40 + b];
|
|
|
|
out <<= 4;
|
|
out |= sb;
|
|
}
|
|
for (var i = 0; i < 4; i++) {
|
|
var b = (inR >>> (18 - i * 6)) & 0x3f;
|
|
var sb = sTable[4 * 0x40 + i * 0x40 + b];
|
|
|
|
out <<= 4;
|
|
out |= sb;
|
|
}
|
|
return out >>> 0;
|
|
};
|
|
|
|
var permuteTable = [
|
|
16, 25, 12, 11, 3, 20, 4, 15, 31, 17, 9, 6, 27, 14, 1, 22,
|
|
30, 24, 8, 18, 0, 5, 29, 23, 13, 19, 2, 26, 10, 21, 28, 7
|
|
];
|
|
|
|
exports.permute = function permute(num) {
|
|
var out = 0;
|
|
for (var i = 0; i < permuteTable.length; i++) {
|
|
out <<= 1;
|
|
out |= (num >>> permuteTable[i]) & 0x1;
|
|
}
|
|
return out >>> 0;
|
|
};
|
|
|
|
exports.padSplit = function padSplit(num, size, group) {
|
|
var str = num.toString(2);
|
|
while (str.length < size)
|
|
str = '0' + str;
|
|
|
|
var out = [];
|
|
for (var i = 0; i < size; i += group)
|
|
out.push(str.slice(i, i + group));
|
|
return out.join(' ');
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/diffie-hellman/browser.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/diffie-hellman/browser.js ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
var generatePrime = __webpack_require__(/*! ./lib/generatePrime */ "./node_modules/diffie-hellman/lib/generatePrime.js")
|
|
var primes = __webpack_require__(/*! ./lib/primes.json */ "./node_modules/diffie-hellman/lib/primes.json")
|
|
|
|
var DH = __webpack_require__(/*! ./lib/dh */ "./node_modules/diffie-hellman/lib/dh.js")
|
|
|
|
function getDiffieHellman (mod) {
|
|
var prime = new Buffer(primes[mod].prime, 'hex')
|
|
var gen = new Buffer(primes[mod].gen, 'hex')
|
|
|
|
return new DH(prime, gen)
|
|
}
|
|
|
|
var ENCODINGS = {
|
|
'binary': true, 'hex': true, 'base64': true
|
|
}
|
|
|
|
function createDiffieHellman (prime, enc, generator, genc) {
|
|
if (Buffer.isBuffer(enc) || ENCODINGS[enc] === undefined) {
|
|
return createDiffieHellman(prime, 'binary', enc, generator)
|
|
}
|
|
|
|
enc = enc || 'binary'
|
|
genc = genc || 'binary'
|
|
generator = generator || new Buffer([2])
|
|
|
|
if (!Buffer.isBuffer(generator)) {
|
|
generator = new Buffer(generator, genc)
|
|
}
|
|
|
|
if (typeof prime === 'number') {
|
|
return new DH(generatePrime(prime, generator), generator, true)
|
|
}
|
|
|
|
if (!Buffer.isBuffer(prime)) {
|
|
prime = new Buffer(prime, enc)
|
|
}
|
|
|
|
return new DH(prime, generator, true)
|
|
}
|
|
|
|
exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = getDiffieHellman
|
|
exports.createDiffieHellman = exports.DiffieHellman = createDiffieHellman
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/diffie-hellman/lib/dh.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/diffie-hellman/lib/dh.js ***!
|
|
\***********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/diffie-hellman/node_modules/bn.js/lib/bn.js");
|
|
var MillerRabin = __webpack_require__(/*! miller-rabin */ "./node_modules/miller-rabin/lib/mr.js");
|
|
var millerRabin = new MillerRabin();
|
|
var TWENTYFOUR = new BN(24);
|
|
var ELEVEN = new BN(11);
|
|
var TEN = new BN(10);
|
|
var THREE = new BN(3);
|
|
var SEVEN = new BN(7);
|
|
var primes = __webpack_require__(/*! ./generatePrime */ "./node_modules/diffie-hellman/lib/generatePrime.js");
|
|
var randomBytes = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js");
|
|
module.exports = DH;
|
|
|
|
function setPublicKey(pub, enc) {
|
|
enc = enc || 'utf8';
|
|
if (!Buffer.isBuffer(pub)) {
|
|
pub = new Buffer(pub, enc);
|
|
}
|
|
this._pub = new BN(pub);
|
|
return this;
|
|
}
|
|
|
|
function setPrivateKey(priv, enc) {
|
|
enc = enc || 'utf8';
|
|
if (!Buffer.isBuffer(priv)) {
|
|
priv = new Buffer(priv, enc);
|
|
}
|
|
this._priv = new BN(priv);
|
|
return this;
|
|
}
|
|
|
|
var primeCache = {};
|
|
function checkPrime(prime, generator) {
|
|
var gen = generator.toString('hex');
|
|
var hex = [gen, prime.toString(16)].join('_');
|
|
if (hex in primeCache) {
|
|
return primeCache[hex];
|
|
}
|
|
var error = 0;
|
|
|
|
if (prime.isEven() ||
|
|
!primes.simpleSieve ||
|
|
!primes.fermatTest(prime) ||
|
|
!millerRabin.test(prime)) {
|
|
//not a prime so +1
|
|
error += 1;
|
|
|
|
if (gen === '02' || gen === '05') {
|
|
// we'd be able to check the generator
|
|
// it would fail so +8
|
|
error += 8;
|
|
} else {
|
|
//we wouldn't be able to test the generator
|
|
// so +4
|
|
error += 4;
|
|
}
|
|
primeCache[hex] = error;
|
|
return error;
|
|
}
|
|
if (!millerRabin.test(prime.shrn(1))) {
|
|
//not a safe prime
|
|
error += 2;
|
|
}
|
|
var rem;
|
|
switch (gen) {
|
|
case '02':
|
|
if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) {
|
|
// unsuidable generator
|
|
error += 8;
|
|
}
|
|
break;
|
|
case '05':
|
|
rem = prime.mod(TEN);
|
|
if (rem.cmp(THREE) && rem.cmp(SEVEN)) {
|
|
// prime mod 10 needs to equal 3 or 7
|
|
error += 8;
|
|
}
|
|
break;
|
|
default:
|
|
error += 4;
|
|
}
|
|
primeCache[hex] = error;
|
|
return error;
|
|
}
|
|
|
|
function DH(prime, generator, malleable) {
|
|
this.setGenerator(generator);
|
|
this.__prime = new BN(prime);
|
|
this._prime = BN.mont(this.__prime);
|
|
this._primeLen = prime.length;
|
|
this._pub = undefined;
|
|
this._priv = undefined;
|
|
this._primeCode = undefined;
|
|
if (malleable) {
|
|
this.setPublicKey = setPublicKey;
|
|
this.setPrivateKey = setPrivateKey;
|
|
} else {
|
|
this._primeCode = 8;
|
|
}
|
|
}
|
|
Object.defineProperty(DH.prototype, 'verifyError', {
|
|
enumerable: true,
|
|
get: function () {
|
|
if (typeof this._primeCode !== 'number') {
|
|
this._primeCode = checkPrime(this.__prime, this.__gen);
|
|
}
|
|
return this._primeCode;
|
|
}
|
|
});
|
|
DH.prototype.generateKeys = function () {
|
|
if (!this._priv) {
|
|
this._priv = new BN(randomBytes(this._primeLen));
|
|
}
|
|
this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed();
|
|
return this.getPublicKey();
|
|
};
|
|
|
|
DH.prototype.computeSecret = function (other) {
|
|
other = new BN(other);
|
|
other = other.toRed(this._prime);
|
|
var secret = other.redPow(this._priv).fromRed();
|
|
var out = new Buffer(secret.toArray());
|
|
var prime = this.getPrime();
|
|
if (out.length < prime.length) {
|
|
var front = new Buffer(prime.length - out.length);
|
|
front.fill(0);
|
|
out = Buffer.concat([front, out]);
|
|
}
|
|
return out;
|
|
};
|
|
|
|
DH.prototype.getPublicKey = function getPublicKey(enc) {
|
|
return formatReturnValue(this._pub, enc);
|
|
};
|
|
|
|
DH.prototype.getPrivateKey = function getPrivateKey(enc) {
|
|
return formatReturnValue(this._priv, enc);
|
|
};
|
|
|
|
DH.prototype.getPrime = function (enc) {
|
|
return formatReturnValue(this.__prime, enc);
|
|
};
|
|
|
|
DH.prototype.getGenerator = function (enc) {
|
|
return formatReturnValue(this._gen, enc);
|
|
};
|
|
|
|
DH.prototype.setGenerator = function (gen, enc) {
|
|
enc = enc || 'utf8';
|
|
if (!Buffer.isBuffer(gen)) {
|
|
gen = new Buffer(gen, enc);
|
|
}
|
|
this.__gen = gen;
|
|
this._gen = new BN(gen);
|
|
return this;
|
|
};
|
|
|
|
function formatReturnValue(bn, enc) {
|
|
var buf = new Buffer(bn.toArray());
|
|
if (!enc) {
|
|
return buf;
|
|
} else {
|
|
return buf.toString(enc);
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/diffie-hellman/lib/generatePrime.js":
|
|
/*!**********************************************************!*\
|
|
!*** ./node_modules/diffie-hellman/lib/generatePrime.js ***!
|
|
\**********************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var randomBytes = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js");
|
|
module.exports = findPrime;
|
|
findPrime.simpleSieve = simpleSieve;
|
|
findPrime.fermatTest = fermatTest;
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/diffie-hellman/node_modules/bn.js/lib/bn.js");
|
|
var TWENTYFOUR = new BN(24);
|
|
var MillerRabin = __webpack_require__(/*! miller-rabin */ "./node_modules/miller-rabin/lib/mr.js");
|
|
var millerRabin = new MillerRabin();
|
|
var ONE = new BN(1);
|
|
var TWO = new BN(2);
|
|
var FIVE = new BN(5);
|
|
var SIXTEEN = new BN(16);
|
|
var EIGHT = new BN(8);
|
|
var TEN = new BN(10);
|
|
var THREE = new BN(3);
|
|
var SEVEN = new BN(7);
|
|
var ELEVEN = new BN(11);
|
|
var FOUR = new BN(4);
|
|
var TWELVE = new BN(12);
|
|
var primes = null;
|
|
|
|
function _getPrimes() {
|
|
if (primes !== null)
|
|
return primes;
|
|
|
|
var limit = 0x100000;
|
|
var res = [];
|
|
res[0] = 2;
|
|
for (var i = 1, k = 3; k < limit; k += 2) {
|
|
var sqrt = Math.ceil(Math.sqrt(k));
|
|
for (var j = 0; j < i && res[j] <= sqrt; j++)
|
|
if (k % res[j] === 0)
|
|
break;
|
|
|
|
if (i !== j && res[j] <= sqrt)
|
|
continue;
|
|
|
|
res[i++] = k;
|
|
}
|
|
primes = res;
|
|
return res;
|
|
}
|
|
|
|
function simpleSieve(p) {
|
|
var primes = _getPrimes();
|
|
|
|
for (var i = 0; i < primes.length; i++)
|
|
if (p.modn(primes[i]) === 0) {
|
|
if (p.cmpn(primes[i]) === 0) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function fermatTest(p) {
|
|
var red = BN.mont(p);
|
|
return TWO.toRed(red).redPow(p.subn(1)).fromRed().cmpn(1) === 0;
|
|
}
|
|
|
|
function findPrime(bits, gen) {
|
|
if (bits < 16) {
|
|
// this is what openssl does
|
|
if (gen === 2 || gen === 5) {
|
|
return new BN([0x8c, 0x7b]);
|
|
} else {
|
|
return new BN([0x8c, 0x27]);
|
|
}
|
|
}
|
|
gen = new BN(gen);
|
|
|
|
var num, n2;
|
|
|
|
while (true) {
|
|
num = new BN(randomBytes(Math.ceil(bits / 8)));
|
|
while (num.bitLength() > bits) {
|
|
num.ishrn(1);
|
|
}
|
|
if (num.isEven()) {
|
|
num.iadd(ONE);
|
|
}
|
|
if (!num.testn(1)) {
|
|
num.iadd(TWO);
|
|
}
|
|
if (!gen.cmp(TWO)) {
|
|
while (num.mod(TWENTYFOUR).cmp(ELEVEN)) {
|
|
num.iadd(FOUR);
|
|
}
|
|
} else if (!gen.cmp(FIVE)) {
|
|
while (num.mod(TEN).cmp(THREE)) {
|
|
num.iadd(FOUR);
|
|
}
|
|
}
|
|
n2 = num.shrn(1);
|
|
if (simpleSieve(n2) && simpleSieve(num) &&
|
|
fermatTest(n2) && fermatTest(num) &&
|
|
millerRabin.test(n2) && millerRabin.test(num)) {
|
|
return num;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/diffie-hellman/lib/primes.json":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/diffie-hellman/lib/primes.json ***!
|
|
\*****************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = JSON.parse('{"modp1":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"},"modp2":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff"},"modp5":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff"},"modp14":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff"},"modp15":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff"},"modp16":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff"},"modp17":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff"},"modp18":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff"}}');
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/diffie-hellman/node_modules/bn.js/lib/bn.js":
|
|
/*!******************************************************************!*\
|
|
!*** ./node_modules/diffie-hellman/node_modules/bn.js/lib/bn.js ***!
|
|
\******************************************************************/
|
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
/* module decorator */ module = __webpack_require__.nmd(module);
|
|
(function (module, exports) {
|
|
'use strict';
|
|
|
|
// Utils
|
|
function assert (val, msg) {
|
|
if (!val) throw new Error(msg || 'Assertion failed');
|
|
}
|
|
|
|
// Could use `inherits` module, but don't want to move from single file
|
|
// architecture yet.
|
|
function inherits (ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
var TempCtor = function () {};
|
|
TempCtor.prototype = superCtor.prototype;
|
|
ctor.prototype = new TempCtor();
|
|
ctor.prototype.constructor = ctor;
|
|
}
|
|
|
|
// BN
|
|
|
|
function BN (number, base, endian) {
|
|
if (BN.isBN(number)) {
|
|
return number;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.words = null;
|
|
this.length = 0;
|
|
|
|
// Reduction context
|
|
this.red = null;
|
|
|
|
if (number !== null) {
|
|
if (base === 'le' || base === 'be') {
|
|
endian = base;
|
|
base = 10;
|
|
}
|
|
|
|
this._init(number || 0, base || 10, endian || 'be');
|
|
}
|
|
}
|
|
if (typeof module === 'object') {
|
|
module.exports = BN;
|
|
} else {
|
|
exports.BN = BN;
|
|
}
|
|
|
|
BN.BN = BN;
|
|
BN.wordSize = 26;
|
|
|
|
var Buffer;
|
|
try {
|
|
if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') {
|
|
Buffer = window.Buffer;
|
|
} else {
|
|
Buffer = __webpack_require__(/*! buffer */ "?e7e4").Buffer;
|
|
}
|
|
} catch (e) {
|
|
}
|
|
|
|
BN.isBN = function isBN (num) {
|
|
if (num instanceof BN) {
|
|
return true;
|
|
}
|
|
|
|
return num !== null && typeof num === 'object' &&
|
|
num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
|
|
};
|
|
|
|
BN.max = function max (left, right) {
|
|
if (left.cmp(right) > 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.min = function min (left, right) {
|
|
if (left.cmp(right) < 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.prototype._init = function init (number, base, endian) {
|
|
if (typeof number === 'number') {
|
|
return this._initNumber(number, base, endian);
|
|
}
|
|
|
|
if (typeof number === 'object') {
|
|
return this._initArray(number, base, endian);
|
|
}
|
|
|
|
if (base === 'hex') {
|
|
base = 16;
|
|
}
|
|
assert(base === (base | 0) && base >= 2 && base <= 36);
|
|
|
|
number = number.toString().replace(/\s+/g, '');
|
|
var start = 0;
|
|
if (number[0] === '-') {
|
|
start++;
|
|
this.negative = 1;
|
|
}
|
|
|
|
if (start < number.length) {
|
|
if (base === 16) {
|
|
this._parseHex(number, start, endian);
|
|
} else {
|
|
this._parseBase(number, base, start);
|
|
if (endian === 'le') {
|
|
this._initArray(this.toArray(), base, endian);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
BN.prototype._initNumber = function _initNumber (number, base, endian) {
|
|
if (number < 0) {
|
|
this.negative = 1;
|
|
number = -number;
|
|
}
|
|
if (number < 0x4000000) {
|
|
this.words = [ number & 0x3ffffff ];
|
|
this.length = 1;
|
|
} else if (number < 0x10000000000000) {
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff
|
|
];
|
|
this.length = 2;
|
|
} else {
|
|
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff,
|
|
1
|
|
];
|
|
this.length = 3;
|
|
}
|
|
|
|
if (endian !== 'le') return;
|
|
|
|
// Reverse the bytes
|
|
this._initArray(this.toArray(), base, endian);
|
|
};
|
|
|
|
BN.prototype._initArray = function _initArray (number, base, endian) {
|
|
// Perhaps a Uint8Array
|
|
assert(typeof number.length === 'number');
|
|
if (number.length <= 0) {
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
return this;
|
|
}
|
|
|
|
this.length = Math.ceil(number.length / 3);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
var j, w;
|
|
var off = 0;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
|
|
w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
} else if (endian === 'le') {
|
|
for (i = 0, j = 0; i < number.length; i += 3) {
|
|
w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
return this.strip();
|
|
};
|
|
|
|
function parseHex4Bits (string, index) {
|
|
var c = string.charCodeAt(index);
|
|
// 'A' - 'F'
|
|
if (c >= 65 && c <= 70) {
|
|
return c - 55;
|
|
// 'a' - 'f'
|
|
} else if (c >= 97 && c <= 102) {
|
|
return c - 87;
|
|
// '0' - '9'
|
|
} else {
|
|
return (c - 48) & 0xf;
|
|
}
|
|
}
|
|
|
|
function parseHexByte (string, lowerBound, index) {
|
|
var r = parseHex4Bits(string, index);
|
|
if (index - 1 >= lowerBound) {
|
|
r |= parseHex4Bits(string, index - 1) << 4;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseHex = function _parseHex (number, start, endian) {
|
|
// Create possibly bigger array to ensure that it fits the number
|
|
this.length = Math.ceil((number.length - start) / 6);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
// 24-bits chunks
|
|
var off = 0;
|
|
var j = 0;
|
|
|
|
var w;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1; i >= start; i -= 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
} else {
|
|
var parseLength = number.length - start;
|
|
for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
function parseBase (str, start, end, mul) {
|
|
var r = 0;
|
|
var len = Math.min(str.length, end);
|
|
for (var i = start; i < len; i++) {
|
|
var c = str.charCodeAt(i) - 48;
|
|
|
|
r *= mul;
|
|
|
|
// 'a'
|
|
if (c >= 49) {
|
|
r += c - 49 + 0xa;
|
|
|
|
// 'A'
|
|
} else if (c >= 17) {
|
|
r += c - 17 + 0xa;
|
|
|
|
// '0' - '9'
|
|
} else {
|
|
r += c;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseBase = function _parseBase (number, base, start) {
|
|
// Initialize as zero
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
|
|
// Find length of limb in base
|
|
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
|
|
limbLen++;
|
|
}
|
|
limbLen--;
|
|
limbPow = (limbPow / base) | 0;
|
|
|
|
var total = number.length - start;
|
|
var mod = total % limbLen;
|
|
var end = Math.min(total, total - mod) + start;
|
|
|
|
var word = 0;
|
|
for (var i = start; i < end; i += limbLen) {
|
|
word = parseBase(number, i, i + limbLen, base);
|
|
|
|
this.imuln(limbPow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
if (mod !== 0) {
|
|
var pow = 1;
|
|
word = parseBase(number, i, number.length, base);
|
|
|
|
for (i = 0; i < mod; i++) {
|
|
pow *= base;
|
|
}
|
|
|
|
this.imuln(pow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
BN.prototype.copy = function copy (dest) {
|
|
dest.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
dest.words[i] = this.words[i];
|
|
}
|
|
dest.length = this.length;
|
|
dest.negative = this.negative;
|
|
dest.red = this.red;
|
|
};
|
|
|
|
BN.prototype.clone = function clone () {
|
|
var r = new BN(null);
|
|
this.copy(r);
|
|
return r;
|
|
};
|
|
|
|
BN.prototype._expand = function _expand (size) {
|
|
while (this.length < size) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
// Remove leading `0` from `this`
|
|
BN.prototype.strip = function strip () {
|
|
while (this.length > 1 && this.words[this.length - 1] === 0) {
|
|
this.length--;
|
|
}
|
|
return this._normSign();
|
|
};
|
|
|
|
BN.prototype._normSign = function _normSign () {
|
|
// -0 = 0
|
|
if (this.length === 1 && this.words[0] === 0) {
|
|
this.negative = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.inspect = function inspect () {
|
|
return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
|
|
};
|
|
|
|
/*
|
|
|
|
var zeros = [];
|
|
var groupSizes = [];
|
|
var groupBases = [];
|
|
|
|
var s = '';
|
|
var i = -1;
|
|
while (++i < BN.wordSize) {
|
|
zeros[i] = s;
|
|
s += '0';
|
|
}
|
|
groupSizes[0] = 0;
|
|
groupSizes[1] = 0;
|
|
groupBases[0] = 0;
|
|
groupBases[1] = 0;
|
|
var base = 2 - 1;
|
|
while (++base < 36 + 1) {
|
|
var groupSize = 0;
|
|
var groupBase = 1;
|
|
while (groupBase < (1 << BN.wordSize) / base) {
|
|
groupBase *= base;
|
|
groupSize += 1;
|
|
}
|
|
groupSizes[base] = groupSize;
|
|
groupBases[base] = groupBase;
|
|
}
|
|
|
|
*/
|
|
|
|
var zeros = [
|
|
'',
|
|
'0',
|
|
'00',
|
|
'000',
|
|
'0000',
|
|
'00000',
|
|
'000000',
|
|
'0000000',
|
|
'00000000',
|
|
'000000000',
|
|
'0000000000',
|
|
'00000000000',
|
|
'000000000000',
|
|
'0000000000000',
|
|
'00000000000000',
|
|
'000000000000000',
|
|
'0000000000000000',
|
|
'00000000000000000',
|
|
'000000000000000000',
|
|
'0000000000000000000',
|
|
'00000000000000000000',
|
|
'000000000000000000000',
|
|
'0000000000000000000000',
|
|
'00000000000000000000000',
|
|
'000000000000000000000000',
|
|
'0000000000000000000000000'
|
|
];
|
|
|
|
var groupSizes = [
|
|
0, 0,
|
|
25, 16, 12, 11, 10, 9, 8,
|
|
8, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5
|
|
];
|
|
|
|
var groupBases = [
|
|
0, 0,
|
|
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
|
|
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
|
|
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
|
|
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
|
|
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
|
|
];
|
|
|
|
BN.prototype.toString = function toString (base, padding) {
|
|
base = base || 10;
|
|
padding = padding | 0 || 1;
|
|
|
|
var out;
|
|
if (base === 16 || base === 'hex') {
|
|
out = '';
|
|
var off = 0;
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = this.words[i];
|
|
var word = (((w << off) | carry) & 0xffffff).toString(16);
|
|
carry = (w >>> (24 - off)) & 0xffffff;
|
|
if (carry !== 0 || i !== this.length - 1) {
|
|
out = zeros[6 - word.length] + word + out;
|
|
} else {
|
|
out = word + out;
|
|
}
|
|
off += 2;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
i--;
|
|
}
|
|
}
|
|
if (carry !== 0) {
|
|
out = carry.toString(16) + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
if (base === (base | 0) && base >= 2 && base <= 36) {
|
|
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
|
|
var groupSize = groupSizes[base];
|
|
// var groupBase = Math.pow(base, groupSize);
|
|
var groupBase = groupBases[base];
|
|
out = '';
|
|
var c = this.clone();
|
|
c.negative = 0;
|
|
while (!c.isZero()) {
|
|
var r = c.modn(groupBase).toString(base);
|
|
c = c.idivn(groupBase);
|
|
|
|
if (!c.isZero()) {
|
|
out = zeros[groupSize - r.length] + r + out;
|
|
} else {
|
|
out = r + out;
|
|
}
|
|
}
|
|
if (this.isZero()) {
|
|
out = '0' + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
assert(false, 'Base should be between 2 and 36');
|
|
};
|
|
|
|
BN.prototype.toNumber = function toNumber () {
|
|
var ret = this.words[0];
|
|
if (this.length === 2) {
|
|
ret += this.words[1] * 0x4000000;
|
|
} else if (this.length === 3 && this.words[2] === 0x01) {
|
|
// NOTE: at this stage it is known that the top bit is set
|
|
ret += 0x10000000000000 + (this.words[1] * 0x4000000);
|
|
} else if (this.length > 2) {
|
|
assert(false, 'Number can only safely store up to 53 bits');
|
|
}
|
|
return (this.negative !== 0) ? -ret : ret;
|
|
};
|
|
|
|
BN.prototype.toJSON = function toJSON () {
|
|
return this.toString(16);
|
|
};
|
|
|
|
BN.prototype.toBuffer = function toBuffer (endian, length) {
|
|
assert(typeof Buffer !== 'undefined');
|
|
return this.toArrayLike(Buffer, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArray = function toArray (endian, length) {
|
|
return this.toArrayLike(Array, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
|
|
var byteLength = this.byteLength();
|
|
var reqLength = length || Math.max(1, byteLength);
|
|
assert(byteLength <= reqLength, 'byte array longer than desired length');
|
|
assert(reqLength > 0, 'Requested array length <= 0');
|
|
|
|
this.strip();
|
|
var littleEndian = endian === 'le';
|
|
var res = new ArrayType(reqLength);
|
|
|
|
var b, i;
|
|
var q = this.clone();
|
|
if (!littleEndian) {
|
|
// Assume big-endian
|
|
for (i = 0; i < reqLength - byteLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[reqLength - i - 1] = b;
|
|
}
|
|
} else {
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[i] = b;
|
|
}
|
|
|
|
for (; i < reqLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
if (Math.clz32) {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
return 32 - Math.clz32(w);
|
|
};
|
|
} else {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
var t = w;
|
|
var r = 0;
|
|
if (t >= 0x1000) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if (t >= 0x40) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if (t >= 0x8) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if (t >= 0x02) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
return r + t;
|
|
};
|
|
}
|
|
|
|
BN.prototype._zeroBits = function _zeroBits (w) {
|
|
// Short-cut
|
|
if (w === 0) return 26;
|
|
|
|
var t = w;
|
|
var r = 0;
|
|
if ((t & 0x1fff) === 0) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if ((t & 0x7f) === 0) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if ((t & 0xf) === 0) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if ((t & 0x3) === 0) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
if ((t & 0x1) === 0) {
|
|
r++;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
// Return number of used bits in a BN
|
|
BN.prototype.bitLength = function bitLength () {
|
|
var w = this.words[this.length - 1];
|
|
var hi = this._countBits(w);
|
|
return (this.length - 1) * 26 + hi;
|
|
};
|
|
|
|
function toBitArray (num) {
|
|
var w = new Array(num.bitLength());
|
|
|
|
for (var bit = 0; bit < w.length; bit++) {
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
// Number of trailing zero bits
|
|
BN.prototype.zeroBits = function zeroBits () {
|
|
if (this.isZero()) return 0;
|
|
|
|
var r = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var b = this._zeroBits(this.words[i]);
|
|
r += b;
|
|
if (b !== 26) break;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
BN.prototype.byteLength = function byteLength () {
|
|
return Math.ceil(this.bitLength() / 8);
|
|
};
|
|
|
|
BN.prototype.toTwos = function toTwos (width) {
|
|
if (this.negative !== 0) {
|
|
return this.abs().inotn(width).iaddn(1);
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.fromTwos = function fromTwos (width) {
|
|
if (this.testn(width - 1)) {
|
|
return this.notn(width).iaddn(1).ineg();
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.isNeg = function isNeg () {
|
|
return this.negative !== 0;
|
|
};
|
|
|
|
// Return negative clone of `this`
|
|
BN.prototype.neg = function neg () {
|
|
return this.clone().ineg();
|
|
};
|
|
|
|
BN.prototype.ineg = function ineg () {
|
|
if (!this.isZero()) {
|
|
this.negative ^= 1;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Or `num` with `this` in-place
|
|
BN.prototype.iuor = function iuor (num) {
|
|
while (this.length < num.length) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
|
|
for (var i = 0; i < num.length; i++) {
|
|
this.words[i] = this.words[i] | num.words[i];
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ior = function ior (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuor(num);
|
|
};
|
|
|
|
// Or `num` with `this`
|
|
BN.prototype.or = function or (num) {
|
|
if (this.length > num.length) return this.clone().ior(num);
|
|
return num.clone().ior(this);
|
|
};
|
|
|
|
BN.prototype.uor = function uor (num) {
|
|
if (this.length > num.length) return this.clone().iuor(num);
|
|
return num.clone().iuor(this);
|
|
};
|
|
|
|
// And `num` with `this` in-place
|
|
BN.prototype.iuand = function iuand (num) {
|
|
// b = min-length(num, this)
|
|
var b;
|
|
if (this.length > num.length) {
|
|
b = num;
|
|
} else {
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = this.words[i] & num.words[i];
|
|
}
|
|
|
|
this.length = b.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.iand = function iand (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuand(num);
|
|
};
|
|
|
|
// And `num` with `this`
|
|
BN.prototype.and = function and (num) {
|
|
if (this.length > num.length) return this.clone().iand(num);
|
|
return num.clone().iand(this);
|
|
};
|
|
|
|
BN.prototype.uand = function uand (num) {
|
|
if (this.length > num.length) return this.clone().iuand(num);
|
|
return num.clone().iuand(this);
|
|
};
|
|
|
|
// Xor `num` with `this` in-place
|
|
BN.prototype.iuxor = function iuxor (num) {
|
|
// a.length > b.length
|
|
var a;
|
|
var b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = a.words[i] ^ b.words[i];
|
|
}
|
|
|
|
if (this !== a) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = a.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ixor = function ixor (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuxor(num);
|
|
};
|
|
|
|
// Xor `num` with `this`
|
|
BN.prototype.xor = function xor (num) {
|
|
if (this.length > num.length) return this.clone().ixor(num);
|
|
return num.clone().ixor(this);
|
|
};
|
|
|
|
BN.prototype.uxor = function uxor (num) {
|
|
if (this.length > num.length) return this.clone().iuxor(num);
|
|
return num.clone().iuxor(this);
|
|
};
|
|
|
|
// Not ``this`` with ``width`` bitwidth
|
|
BN.prototype.inotn = function inotn (width) {
|
|
assert(typeof width === 'number' && width >= 0);
|
|
|
|
var bytesNeeded = Math.ceil(width / 26) | 0;
|
|
var bitsLeft = width % 26;
|
|
|
|
// Extend the buffer with leading zeroes
|
|
this._expand(bytesNeeded);
|
|
|
|
if (bitsLeft > 0) {
|
|
bytesNeeded--;
|
|
}
|
|
|
|
// Handle complete words
|
|
for (var i = 0; i < bytesNeeded; i++) {
|
|
this.words[i] = ~this.words[i] & 0x3ffffff;
|
|
}
|
|
|
|
// Handle the residue
|
|
if (bitsLeft > 0) {
|
|
this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
|
|
}
|
|
|
|
// And remove leading zeroes
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.notn = function notn (width) {
|
|
return this.clone().inotn(width);
|
|
};
|
|
|
|
// Set `bit` of `this`
|
|
BN.prototype.setn = function setn (bit, val) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
this._expand(off + 1);
|
|
|
|
if (val) {
|
|
this.words[off] = this.words[off] | (1 << wbit);
|
|
} else {
|
|
this.words[off] = this.words[off] & ~(1 << wbit);
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Add `num` to `this` in-place
|
|
BN.prototype.iadd = function iadd (num) {
|
|
var r;
|
|
|
|
// negative + positive
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
this.negative = 0;
|
|
r = this.isub(num);
|
|
this.negative ^= 1;
|
|
return this._normSign();
|
|
|
|
// positive + negative
|
|
} else if (this.negative === 0 && num.negative !== 0) {
|
|
num.negative = 0;
|
|
r = this.isub(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
}
|
|
|
|
// a.length > b.length
|
|
var a, b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
|
|
this.length = a.length;
|
|
if (carry !== 0) {
|
|
this.words[this.length] = carry;
|
|
this.length++;
|
|
// Copy the rest of the words
|
|
} else if (a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Add `num` to `this`
|
|
BN.prototype.add = function add (num) {
|
|
var res;
|
|
if (num.negative !== 0 && this.negative === 0) {
|
|
num.negative = 0;
|
|
res = this.sub(num);
|
|
num.negative ^= 1;
|
|
return res;
|
|
} else if (num.negative === 0 && this.negative !== 0) {
|
|
this.negative = 0;
|
|
res = num.sub(this);
|
|
this.negative = 1;
|
|
return res;
|
|
}
|
|
|
|
if (this.length > num.length) return this.clone().iadd(num);
|
|
|
|
return num.clone().iadd(this);
|
|
};
|
|
|
|
// Subtract `num` from `this` in-place
|
|
BN.prototype.isub = function isub (num) {
|
|
// this - (-num) = this + num
|
|
if (num.negative !== 0) {
|
|
num.negative = 0;
|
|
var r = this.iadd(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
|
|
// -this - num = -(this + num)
|
|
} else if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iadd(num);
|
|
this.negative = 1;
|
|
return this._normSign();
|
|
}
|
|
|
|
// At this point both numbers are positive
|
|
var cmp = this.cmp(num);
|
|
|
|
// Optimization - zeroify
|
|
if (cmp === 0) {
|
|
this.negative = 0;
|
|
this.length = 1;
|
|
this.words[0] = 0;
|
|
return this;
|
|
}
|
|
|
|
// a > b
|
|
var a, b;
|
|
if (cmp > 0) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
|
|
// Copy rest of the words
|
|
if (carry === 0 && i < a.length && a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = Math.max(this.length, i);
|
|
|
|
if (a !== this) {
|
|
this.negative = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Subtract `num` from `this`
|
|
BN.prototype.sub = function sub (num) {
|
|
return this.clone().isub(num);
|
|
};
|
|
|
|
function smallMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
var len = (self.length + num.length) | 0;
|
|
out.length = len;
|
|
len = (len - 1) | 0;
|
|
|
|
// Peel one iteration (compiler can't do it, because of code complexity)
|
|
var a = self.words[0] | 0;
|
|
var b = num.words[0] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
var carry = (r / 0x4000000) | 0;
|
|
out.words[0] = lo;
|
|
|
|
for (var k = 1; k < len; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = carry >>> 26;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = (k - j) | 0;
|
|
a = self.words[i] | 0;
|
|
b = num.words[j] | 0;
|
|
r = a * b + rword;
|
|
ncarry += (r / 0x4000000) | 0;
|
|
rword = r & 0x3ffffff;
|
|
}
|
|
out.words[k] = rword | 0;
|
|
carry = ncarry | 0;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry | 0;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
// TODO(indutny): it may be reasonable to omit it for users who don't need
|
|
// to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
|
|
// multiplication (like elliptic secp256k1).
|
|
var comb10MulTo = function comb10MulTo (self, num, out) {
|
|
var a = self.words;
|
|
var b = num.words;
|
|
var o = out.words;
|
|
var c = 0;
|
|
var lo;
|
|
var mid;
|
|
var hi;
|
|
var a0 = a[0] | 0;
|
|
var al0 = a0 & 0x1fff;
|
|
var ah0 = a0 >>> 13;
|
|
var a1 = a[1] | 0;
|
|
var al1 = a1 & 0x1fff;
|
|
var ah1 = a1 >>> 13;
|
|
var a2 = a[2] | 0;
|
|
var al2 = a2 & 0x1fff;
|
|
var ah2 = a2 >>> 13;
|
|
var a3 = a[3] | 0;
|
|
var al3 = a3 & 0x1fff;
|
|
var ah3 = a3 >>> 13;
|
|
var a4 = a[4] | 0;
|
|
var al4 = a4 & 0x1fff;
|
|
var ah4 = a4 >>> 13;
|
|
var a5 = a[5] | 0;
|
|
var al5 = a5 & 0x1fff;
|
|
var ah5 = a5 >>> 13;
|
|
var a6 = a[6] | 0;
|
|
var al6 = a6 & 0x1fff;
|
|
var ah6 = a6 >>> 13;
|
|
var a7 = a[7] | 0;
|
|
var al7 = a7 & 0x1fff;
|
|
var ah7 = a7 >>> 13;
|
|
var a8 = a[8] | 0;
|
|
var al8 = a8 & 0x1fff;
|
|
var ah8 = a8 >>> 13;
|
|
var a9 = a[9] | 0;
|
|
var al9 = a9 & 0x1fff;
|
|
var ah9 = a9 >>> 13;
|
|
var b0 = b[0] | 0;
|
|
var bl0 = b0 & 0x1fff;
|
|
var bh0 = b0 >>> 13;
|
|
var b1 = b[1] | 0;
|
|
var bl1 = b1 & 0x1fff;
|
|
var bh1 = b1 >>> 13;
|
|
var b2 = b[2] | 0;
|
|
var bl2 = b2 & 0x1fff;
|
|
var bh2 = b2 >>> 13;
|
|
var b3 = b[3] | 0;
|
|
var bl3 = b3 & 0x1fff;
|
|
var bh3 = b3 >>> 13;
|
|
var b4 = b[4] | 0;
|
|
var bl4 = b4 & 0x1fff;
|
|
var bh4 = b4 >>> 13;
|
|
var b5 = b[5] | 0;
|
|
var bl5 = b5 & 0x1fff;
|
|
var bh5 = b5 >>> 13;
|
|
var b6 = b[6] | 0;
|
|
var bl6 = b6 & 0x1fff;
|
|
var bh6 = b6 >>> 13;
|
|
var b7 = b[7] | 0;
|
|
var bl7 = b7 & 0x1fff;
|
|
var bh7 = b7 >>> 13;
|
|
var b8 = b[8] | 0;
|
|
var bl8 = b8 & 0x1fff;
|
|
var bh8 = b8 >>> 13;
|
|
var b9 = b[9] | 0;
|
|
var bl9 = b9 & 0x1fff;
|
|
var bh9 = b9 >>> 13;
|
|
|
|
out.negative = self.negative ^ num.negative;
|
|
out.length = 19;
|
|
/* k = 0 */
|
|
lo = Math.imul(al0, bl0);
|
|
mid = Math.imul(al0, bh0);
|
|
mid = (mid + Math.imul(ah0, bl0)) | 0;
|
|
hi = Math.imul(ah0, bh0);
|
|
var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
|
|
w0 &= 0x3ffffff;
|
|
/* k = 1 */
|
|
lo = Math.imul(al1, bl0);
|
|
mid = Math.imul(al1, bh0);
|
|
mid = (mid + Math.imul(ah1, bl0)) | 0;
|
|
hi = Math.imul(ah1, bh0);
|
|
lo = (lo + Math.imul(al0, bl1)) | 0;
|
|
mid = (mid + Math.imul(al0, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh1)) | 0;
|
|
var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
|
|
w1 &= 0x3ffffff;
|
|
/* k = 2 */
|
|
lo = Math.imul(al2, bl0);
|
|
mid = Math.imul(al2, bh0);
|
|
mid = (mid + Math.imul(ah2, bl0)) | 0;
|
|
hi = Math.imul(ah2, bh0);
|
|
lo = (lo + Math.imul(al1, bl1)) | 0;
|
|
mid = (mid + Math.imul(al1, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh1)) | 0;
|
|
lo = (lo + Math.imul(al0, bl2)) | 0;
|
|
mid = (mid + Math.imul(al0, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh2)) | 0;
|
|
var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
|
|
w2 &= 0x3ffffff;
|
|
/* k = 3 */
|
|
lo = Math.imul(al3, bl0);
|
|
mid = Math.imul(al3, bh0);
|
|
mid = (mid + Math.imul(ah3, bl0)) | 0;
|
|
hi = Math.imul(ah3, bh0);
|
|
lo = (lo + Math.imul(al2, bl1)) | 0;
|
|
mid = (mid + Math.imul(al2, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh1)) | 0;
|
|
lo = (lo + Math.imul(al1, bl2)) | 0;
|
|
mid = (mid + Math.imul(al1, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh2)) | 0;
|
|
lo = (lo + Math.imul(al0, bl3)) | 0;
|
|
mid = (mid + Math.imul(al0, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh3)) | 0;
|
|
var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
|
|
w3 &= 0x3ffffff;
|
|
/* k = 4 */
|
|
lo = Math.imul(al4, bl0);
|
|
mid = Math.imul(al4, bh0);
|
|
mid = (mid + Math.imul(ah4, bl0)) | 0;
|
|
hi = Math.imul(ah4, bh0);
|
|
lo = (lo + Math.imul(al3, bl1)) | 0;
|
|
mid = (mid + Math.imul(al3, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh1)) | 0;
|
|
lo = (lo + Math.imul(al2, bl2)) | 0;
|
|
mid = (mid + Math.imul(al2, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh2)) | 0;
|
|
lo = (lo + Math.imul(al1, bl3)) | 0;
|
|
mid = (mid + Math.imul(al1, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh3)) | 0;
|
|
lo = (lo + Math.imul(al0, bl4)) | 0;
|
|
mid = (mid + Math.imul(al0, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh4)) | 0;
|
|
var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
|
|
w4 &= 0x3ffffff;
|
|
/* k = 5 */
|
|
lo = Math.imul(al5, bl0);
|
|
mid = Math.imul(al5, bh0);
|
|
mid = (mid + Math.imul(ah5, bl0)) | 0;
|
|
hi = Math.imul(ah5, bh0);
|
|
lo = (lo + Math.imul(al4, bl1)) | 0;
|
|
mid = (mid + Math.imul(al4, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh1)) | 0;
|
|
lo = (lo + Math.imul(al3, bl2)) | 0;
|
|
mid = (mid + Math.imul(al3, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh2)) | 0;
|
|
lo = (lo + Math.imul(al2, bl3)) | 0;
|
|
mid = (mid + Math.imul(al2, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh3)) | 0;
|
|
lo = (lo + Math.imul(al1, bl4)) | 0;
|
|
mid = (mid + Math.imul(al1, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh4)) | 0;
|
|
lo = (lo + Math.imul(al0, bl5)) | 0;
|
|
mid = (mid + Math.imul(al0, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh5)) | 0;
|
|
var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
|
|
w5 &= 0x3ffffff;
|
|
/* k = 6 */
|
|
lo = Math.imul(al6, bl0);
|
|
mid = Math.imul(al6, bh0);
|
|
mid = (mid + Math.imul(ah6, bl0)) | 0;
|
|
hi = Math.imul(ah6, bh0);
|
|
lo = (lo + Math.imul(al5, bl1)) | 0;
|
|
mid = (mid + Math.imul(al5, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh1)) | 0;
|
|
lo = (lo + Math.imul(al4, bl2)) | 0;
|
|
mid = (mid + Math.imul(al4, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh2)) | 0;
|
|
lo = (lo + Math.imul(al3, bl3)) | 0;
|
|
mid = (mid + Math.imul(al3, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh3)) | 0;
|
|
lo = (lo + Math.imul(al2, bl4)) | 0;
|
|
mid = (mid + Math.imul(al2, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh4)) | 0;
|
|
lo = (lo + Math.imul(al1, bl5)) | 0;
|
|
mid = (mid + Math.imul(al1, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh5)) | 0;
|
|
lo = (lo + Math.imul(al0, bl6)) | 0;
|
|
mid = (mid + Math.imul(al0, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh6)) | 0;
|
|
var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
|
|
w6 &= 0x3ffffff;
|
|
/* k = 7 */
|
|
lo = Math.imul(al7, bl0);
|
|
mid = Math.imul(al7, bh0);
|
|
mid = (mid + Math.imul(ah7, bl0)) | 0;
|
|
hi = Math.imul(ah7, bh0);
|
|
lo = (lo + Math.imul(al6, bl1)) | 0;
|
|
mid = (mid + Math.imul(al6, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh1)) | 0;
|
|
lo = (lo + Math.imul(al5, bl2)) | 0;
|
|
mid = (mid + Math.imul(al5, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh2)) | 0;
|
|
lo = (lo + Math.imul(al4, bl3)) | 0;
|
|
mid = (mid + Math.imul(al4, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh3)) | 0;
|
|
lo = (lo + Math.imul(al3, bl4)) | 0;
|
|
mid = (mid + Math.imul(al3, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh4)) | 0;
|
|
lo = (lo + Math.imul(al2, bl5)) | 0;
|
|
mid = (mid + Math.imul(al2, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh5)) | 0;
|
|
lo = (lo + Math.imul(al1, bl6)) | 0;
|
|
mid = (mid + Math.imul(al1, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh6)) | 0;
|
|
lo = (lo + Math.imul(al0, bl7)) | 0;
|
|
mid = (mid + Math.imul(al0, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh7)) | 0;
|
|
var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
|
|
w7 &= 0x3ffffff;
|
|
/* k = 8 */
|
|
lo = Math.imul(al8, bl0);
|
|
mid = Math.imul(al8, bh0);
|
|
mid = (mid + Math.imul(ah8, bl0)) | 0;
|
|
hi = Math.imul(ah8, bh0);
|
|
lo = (lo + Math.imul(al7, bl1)) | 0;
|
|
mid = (mid + Math.imul(al7, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh1)) | 0;
|
|
lo = (lo + Math.imul(al6, bl2)) | 0;
|
|
mid = (mid + Math.imul(al6, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh2)) | 0;
|
|
lo = (lo + Math.imul(al5, bl3)) | 0;
|
|
mid = (mid + Math.imul(al5, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh3)) | 0;
|
|
lo = (lo + Math.imul(al4, bl4)) | 0;
|
|
mid = (mid + Math.imul(al4, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh4)) | 0;
|
|
lo = (lo + Math.imul(al3, bl5)) | 0;
|
|
mid = (mid + Math.imul(al3, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh5)) | 0;
|
|
lo = (lo + Math.imul(al2, bl6)) | 0;
|
|
mid = (mid + Math.imul(al2, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh6)) | 0;
|
|
lo = (lo + Math.imul(al1, bl7)) | 0;
|
|
mid = (mid + Math.imul(al1, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh7)) | 0;
|
|
lo = (lo + Math.imul(al0, bl8)) | 0;
|
|
mid = (mid + Math.imul(al0, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh8)) | 0;
|
|
var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
|
|
w8 &= 0x3ffffff;
|
|
/* k = 9 */
|
|
lo = Math.imul(al9, bl0);
|
|
mid = Math.imul(al9, bh0);
|
|
mid = (mid + Math.imul(ah9, bl0)) | 0;
|
|
hi = Math.imul(ah9, bh0);
|
|
lo = (lo + Math.imul(al8, bl1)) | 0;
|
|
mid = (mid + Math.imul(al8, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh1)) | 0;
|
|
lo = (lo + Math.imul(al7, bl2)) | 0;
|
|
mid = (mid + Math.imul(al7, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh2)) | 0;
|
|
lo = (lo + Math.imul(al6, bl3)) | 0;
|
|
mid = (mid + Math.imul(al6, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh3)) | 0;
|
|
lo = (lo + Math.imul(al5, bl4)) | 0;
|
|
mid = (mid + Math.imul(al5, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh4)) | 0;
|
|
lo = (lo + Math.imul(al4, bl5)) | 0;
|
|
mid = (mid + Math.imul(al4, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh5)) | 0;
|
|
lo = (lo + Math.imul(al3, bl6)) | 0;
|
|
mid = (mid + Math.imul(al3, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh6)) | 0;
|
|
lo = (lo + Math.imul(al2, bl7)) | 0;
|
|
mid = (mid + Math.imul(al2, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh7)) | 0;
|
|
lo = (lo + Math.imul(al1, bl8)) | 0;
|
|
mid = (mid + Math.imul(al1, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh8)) | 0;
|
|
lo = (lo + Math.imul(al0, bl9)) | 0;
|
|
mid = (mid + Math.imul(al0, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh9)) | 0;
|
|
var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
|
|
w9 &= 0x3ffffff;
|
|
/* k = 10 */
|
|
lo = Math.imul(al9, bl1);
|
|
mid = Math.imul(al9, bh1);
|
|
mid = (mid + Math.imul(ah9, bl1)) | 0;
|
|
hi = Math.imul(ah9, bh1);
|
|
lo = (lo + Math.imul(al8, bl2)) | 0;
|
|
mid = (mid + Math.imul(al8, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh2)) | 0;
|
|
lo = (lo + Math.imul(al7, bl3)) | 0;
|
|
mid = (mid + Math.imul(al7, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh3)) | 0;
|
|
lo = (lo + Math.imul(al6, bl4)) | 0;
|
|
mid = (mid + Math.imul(al6, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh4)) | 0;
|
|
lo = (lo + Math.imul(al5, bl5)) | 0;
|
|
mid = (mid + Math.imul(al5, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh5)) | 0;
|
|
lo = (lo + Math.imul(al4, bl6)) | 0;
|
|
mid = (mid + Math.imul(al4, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh6)) | 0;
|
|
lo = (lo + Math.imul(al3, bl7)) | 0;
|
|
mid = (mid + Math.imul(al3, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh7)) | 0;
|
|
lo = (lo + Math.imul(al2, bl8)) | 0;
|
|
mid = (mid + Math.imul(al2, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh8)) | 0;
|
|
lo = (lo + Math.imul(al1, bl9)) | 0;
|
|
mid = (mid + Math.imul(al1, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh9)) | 0;
|
|
var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
|
|
w10 &= 0x3ffffff;
|
|
/* k = 11 */
|
|
lo = Math.imul(al9, bl2);
|
|
mid = Math.imul(al9, bh2);
|
|
mid = (mid + Math.imul(ah9, bl2)) | 0;
|
|
hi = Math.imul(ah9, bh2);
|
|
lo = (lo + Math.imul(al8, bl3)) | 0;
|
|
mid = (mid + Math.imul(al8, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh3)) | 0;
|
|
lo = (lo + Math.imul(al7, bl4)) | 0;
|
|
mid = (mid + Math.imul(al7, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh4)) | 0;
|
|
lo = (lo + Math.imul(al6, bl5)) | 0;
|
|
mid = (mid + Math.imul(al6, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh5)) | 0;
|
|
lo = (lo + Math.imul(al5, bl6)) | 0;
|
|
mid = (mid + Math.imul(al5, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh6)) | 0;
|
|
lo = (lo + Math.imul(al4, bl7)) | 0;
|
|
mid = (mid + Math.imul(al4, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh7)) | 0;
|
|
lo = (lo + Math.imul(al3, bl8)) | 0;
|
|
mid = (mid + Math.imul(al3, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh8)) | 0;
|
|
lo = (lo + Math.imul(al2, bl9)) | 0;
|
|
mid = (mid + Math.imul(al2, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh9)) | 0;
|
|
var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
|
|
w11 &= 0x3ffffff;
|
|
/* k = 12 */
|
|
lo = Math.imul(al9, bl3);
|
|
mid = Math.imul(al9, bh3);
|
|
mid = (mid + Math.imul(ah9, bl3)) | 0;
|
|
hi = Math.imul(ah9, bh3);
|
|
lo = (lo + Math.imul(al8, bl4)) | 0;
|
|
mid = (mid + Math.imul(al8, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh4)) | 0;
|
|
lo = (lo + Math.imul(al7, bl5)) | 0;
|
|
mid = (mid + Math.imul(al7, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh5)) | 0;
|
|
lo = (lo + Math.imul(al6, bl6)) | 0;
|
|
mid = (mid + Math.imul(al6, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh6)) | 0;
|
|
lo = (lo + Math.imul(al5, bl7)) | 0;
|
|
mid = (mid + Math.imul(al5, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh7)) | 0;
|
|
lo = (lo + Math.imul(al4, bl8)) | 0;
|
|
mid = (mid + Math.imul(al4, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh8)) | 0;
|
|
lo = (lo + Math.imul(al3, bl9)) | 0;
|
|
mid = (mid + Math.imul(al3, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh9)) | 0;
|
|
var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
|
|
w12 &= 0x3ffffff;
|
|
/* k = 13 */
|
|
lo = Math.imul(al9, bl4);
|
|
mid = Math.imul(al9, bh4);
|
|
mid = (mid + Math.imul(ah9, bl4)) | 0;
|
|
hi = Math.imul(ah9, bh4);
|
|
lo = (lo + Math.imul(al8, bl5)) | 0;
|
|
mid = (mid + Math.imul(al8, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh5)) | 0;
|
|
lo = (lo + Math.imul(al7, bl6)) | 0;
|
|
mid = (mid + Math.imul(al7, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh6)) | 0;
|
|
lo = (lo + Math.imul(al6, bl7)) | 0;
|
|
mid = (mid + Math.imul(al6, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh7)) | 0;
|
|
lo = (lo + Math.imul(al5, bl8)) | 0;
|
|
mid = (mid + Math.imul(al5, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh8)) | 0;
|
|
lo = (lo + Math.imul(al4, bl9)) | 0;
|
|
mid = (mid + Math.imul(al4, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh9)) | 0;
|
|
var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
|
|
w13 &= 0x3ffffff;
|
|
/* k = 14 */
|
|
lo = Math.imul(al9, bl5);
|
|
mid = Math.imul(al9, bh5);
|
|
mid = (mid + Math.imul(ah9, bl5)) | 0;
|
|
hi = Math.imul(ah9, bh5);
|
|
lo = (lo + Math.imul(al8, bl6)) | 0;
|
|
mid = (mid + Math.imul(al8, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh6)) | 0;
|
|
lo = (lo + Math.imul(al7, bl7)) | 0;
|
|
mid = (mid + Math.imul(al7, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh7)) | 0;
|
|
lo = (lo + Math.imul(al6, bl8)) | 0;
|
|
mid = (mid + Math.imul(al6, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh8)) | 0;
|
|
lo = (lo + Math.imul(al5, bl9)) | 0;
|
|
mid = (mid + Math.imul(al5, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh9)) | 0;
|
|
var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
|
|
w14 &= 0x3ffffff;
|
|
/* k = 15 */
|
|
lo = Math.imul(al9, bl6);
|
|
mid = Math.imul(al9, bh6);
|
|
mid = (mid + Math.imul(ah9, bl6)) | 0;
|
|
hi = Math.imul(ah9, bh6);
|
|
lo = (lo + Math.imul(al8, bl7)) | 0;
|
|
mid = (mid + Math.imul(al8, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh7)) | 0;
|
|
lo = (lo + Math.imul(al7, bl8)) | 0;
|
|
mid = (mid + Math.imul(al7, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh8)) | 0;
|
|
lo = (lo + Math.imul(al6, bl9)) | 0;
|
|
mid = (mid + Math.imul(al6, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh9)) | 0;
|
|
var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
|
|
w15 &= 0x3ffffff;
|
|
/* k = 16 */
|
|
lo = Math.imul(al9, bl7);
|
|
mid = Math.imul(al9, bh7);
|
|
mid = (mid + Math.imul(ah9, bl7)) | 0;
|
|
hi = Math.imul(ah9, bh7);
|
|
lo = (lo + Math.imul(al8, bl8)) | 0;
|
|
mid = (mid + Math.imul(al8, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh8)) | 0;
|
|
lo = (lo + Math.imul(al7, bl9)) | 0;
|
|
mid = (mid + Math.imul(al7, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh9)) | 0;
|
|
var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
|
|
w16 &= 0x3ffffff;
|
|
/* k = 17 */
|
|
lo = Math.imul(al9, bl8);
|
|
mid = Math.imul(al9, bh8);
|
|
mid = (mid + Math.imul(ah9, bl8)) | 0;
|
|
hi = Math.imul(ah9, bh8);
|
|
lo = (lo + Math.imul(al8, bl9)) | 0;
|
|
mid = (mid + Math.imul(al8, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh9)) | 0;
|
|
var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
|
|
w17 &= 0x3ffffff;
|
|
/* k = 18 */
|
|
lo = Math.imul(al9, bl9);
|
|
mid = Math.imul(al9, bh9);
|
|
mid = (mid + Math.imul(ah9, bl9)) | 0;
|
|
hi = Math.imul(ah9, bh9);
|
|
var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
|
|
w18 &= 0x3ffffff;
|
|
o[0] = w0;
|
|
o[1] = w1;
|
|
o[2] = w2;
|
|
o[3] = w3;
|
|
o[4] = w4;
|
|
o[5] = w5;
|
|
o[6] = w6;
|
|
o[7] = w7;
|
|
o[8] = w8;
|
|
o[9] = w9;
|
|
o[10] = w10;
|
|
o[11] = w11;
|
|
o[12] = w12;
|
|
o[13] = w13;
|
|
o[14] = w14;
|
|
o[15] = w15;
|
|
o[16] = w16;
|
|
o[17] = w17;
|
|
o[18] = w18;
|
|
if (c !== 0) {
|
|
o[19] = c;
|
|
out.length++;
|
|
}
|
|
return out;
|
|
};
|
|
|
|
// Polyfill comb
|
|
if (!Math.imul) {
|
|
comb10MulTo = smallMulTo;
|
|
}
|
|
|
|
function bigMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
out.length = self.length + num.length;
|
|
|
|
var carry = 0;
|
|
var hncarry = 0;
|
|
for (var k = 0; k < out.length - 1; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = hncarry;
|
|
hncarry = 0;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = k - j;
|
|
var a = self.words[i] | 0;
|
|
var b = num.words[j] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
|
|
lo = (lo + rword) | 0;
|
|
rword = lo & 0x3ffffff;
|
|
ncarry = (ncarry + (lo >>> 26)) | 0;
|
|
|
|
hncarry += ncarry >>> 26;
|
|
ncarry &= 0x3ffffff;
|
|
}
|
|
out.words[k] = rword;
|
|
carry = ncarry;
|
|
ncarry = hncarry;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
function jumboMulTo (self, num, out) {
|
|
var fftm = new FFTM();
|
|
return fftm.mulp(self, num, out);
|
|
}
|
|
|
|
BN.prototype.mulTo = function mulTo (num, out) {
|
|
var res;
|
|
var len = this.length + num.length;
|
|
if (this.length === 10 && num.length === 10) {
|
|
res = comb10MulTo(this, num, out);
|
|
} else if (len < 63) {
|
|
res = smallMulTo(this, num, out);
|
|
} else if (len < 1024) {
|
|
res = bigMulTo(this, num, out);
|
|
} else {
|
|
res = jumboMulTo(this, num, out);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Cooley-Tukey algorithm for FFT
|
|
// slightly revisited to rely on looping instead of recursion
|
|
|
|
function FFTM (x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
FFTM.prototype.makeRBT = function makeRBT (N) {
|
|
var t = new Array(N);
|
|
var l = BN.prototype._countBits(N) - 1;
|
|
for (var i = 0; i < N; i++) {
|
|
t[i] = this.revBin(i, l, N);
|
|
}
|
|
|
|
return t;
|
|
};
|
|
|
|
// Returns binary-reversed representation of `x`
|
|
FFTM.prototype.revBin = function revBin (x, l, N) {
|
|
if (x === 0 || x === N - 1) return x;
|
|
|
|
var rb = 0;
|
|
for (var i = 0; i < l; i++) {
|
|
rb |= (x & 1) << (l - i - 1);
|
|
x >>= 1;
|
|
}
|
|
|
|
return rb;
|
|
};
|
|
|
|
// Performs "tweedling" phase, therefore 'emulating'
|
|
// behaviour of the recursive algorithm
|
|
FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
|
|
for (var i = 0; i < N; i++) {
|
|
rtws[i] = rws[rbt[i]];
|
|
itws[i] = iws[rbt[i]];
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
|
|
this.permute(rbt, rws, iws, rtws, itws, N);
|
|
|
|
for (var s = 1; s < N; s <<= 1) {
|
|
var l = s << 1;
|
|
|
|
var rtwdf = Math.cos(2 * Math.PI / l);
|
|
var itwdf = Math.sin(2 * Math.PI / l);
|
|
|
|
for (var p = 0; p < N; p += l) {
|
|
var rtwdf_ = rtwdf;
|
|
var itwdf_ = itwdf;
|
|
|
|
for (var j = 0; j < s; j++) {
|
|
var re = rtws[p + j];
|
|
var ie = itws[p + j];
|
|
|
|
var ro = rtws[p + j + s];
|
|
var io = itws[p + j + s];
|
|
|
|
var rx = rtwdf_ * ro - itwdf_ * io;
|
|
|
|
io = rtwdf_ * io + itwdf_ * ro;
|
|
ro = rx;
|
|
|
|
rtws[p + j] = re + ro;
|
|
itws[p + j] = ie + io;
|
|
|
|
rtws[p + j + s] = re - ro;
|
|
itws[p + j + s] = ie - io;
|
|
|
|
/* jshint maxdepth : false */
|
|
if (j !== l) {
|
|
rx = rtwdf * rtwdf_ - itwdf * itwdf_;
|
|
|
|
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
|
|
rtwdf_ = rx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
|
|
var N = Math.max(m, n) | 1;
|
|
var odd = N & 1;
|
|
var i = 0;
|
|
for (N = N / 2 | 0; N; N = N >>> 1) {
|
|
i++;
|
|
}
|
|
|
|
return 1 << i + 1 + odd;
|
|
};
|
|
|
|
FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
|
|
if (N <= 1) return;
|
|
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var t = rws[i];
|
|
|
|
rws[i] = rws[N - i - 1];
|
|
rws[N - i - 1] = t;
|
|
|
|
t = iws[i];
|
|
|
|
iws[i] = -iws[N - i - 1];
|
|
iws[N - i - 1] = -t;
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.normalize13b = function normalize13b (ws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
|
|
Math.round(ws[2 * i] / N) +
|
|
carry;
|
|
|
|
ws[i] = w & 0x3ffffff;
|
|
|
|
if (w < 0x4000000) {
|
|
carry = 0;
|
|
} else {
|
|
carry = w / 0x4000000 | 0;
|
|
}
|
|
}
|
|
|
|
return ws;
|
|
};
|
|
|
|
FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < len; i++) {
|
|
carry = carry + (ws[i] | 0);
|
|
|
|
rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
|
|
rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
|
|
}
|
|
|
|
// Pad with zeroes
|
|
for (i = 2 * len; i < N; ++i) {
|
|
rws[i] = 0;
|
|
}
|
|
|
|
assert(carry === 0);
|
|
assert((carry & ~0x1fff) === 0);
|
|
};
|
|
|
|
FFTM.prototype.stub = function stub (N) {
|
|
var ph = new Array(N);
|
|
for (var i = 0; i < N; i++) {
|
|
ph[i] = 0;
|
|
}
|
|
|
|
return ph;
|
|
};
|
|
|
|
FFTM.prototype.mulp = function mulp (x, y, out) {
|
|
var N = 2 * this.guessLen13b(x.length, y.length);
|
|
|
|
var rbt = this.makeRBT(N);
|
|
|
|
var _ = this.stub(N);
|
|
|
|
var rws = new Array(N);
|
|
var rwst = new Array(N);
|
|
var iwst = new Array(N);
|
|
|
|
var nrws = new Array(N);
|
|
var nrwst = new Array(N);
|
|
var niwst = new Array(N);
|
|
|
|
var rmws = out.words;
|
|
rmws.length = N;
|
|
|
|
this.convert13b(x.words, x.length, rws, N);
|
|
this.convert13b(y.words, y.length, nrws, N);
|
|
|
|
this.transform(rws, _, rwst, iwst, N, rbt);
|
|
this.transform(nrws, _, nrwst, niwst, N, rbt);
|
|
|
|
for (var i = 0; i < N; i++) {
|
|
var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
|
|
iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
|
|
rwst[i] = rx;
|
|
}
|
|
|
|
this.conjugate(rwst, iwst, N);
|
|
this.transform(rwst, iwst, rmws, _, N, rbt);
|
|
this.conjugate(rmws, _, N);
|
|
this.normalize13b(rmws, N);
|
|
|
|
out.negative = x.negative ^ y.negative;
|
|
out.length = x.length + y.length;
|
|
return out.strip();
|
|
};
|
|
|
|
// Multiply `this` by `num`
|
|
BN.prototype.mul = function mul (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return this.mulTo(num, out);
|
|
};
|
|
|
|
// Multiply employing FFT
|
|
BN.prototype.mulf = function mulf (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return jumboMulTo(this, num, out);
|
|
};
|
|
|
|
// In-place Multiplication
|
|
BN.prototype.imul = function imul (num) {
|
|
return this.clone().mulTo(num, this);
|
|
};
|
|
|
|
BN.prototype.imuln = function imuln (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
|
|
// Carry
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = (this.words[i] | 0) * num;
|
|
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
|
|
carry >>= 26;
|
|
carry += (w / 0x4000000) | 0;
|
|
// NOTE: lo is 27bit maximum
|
|
carry += lo >>> 26;
|
|
this.words[i] = lo & 0x3ffffff;
|
|
}
|
|
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.muln = function muln (num) {
|
|
return this.clone().imuln(num);
|
|
};
|
|
|
|
// `this` * `this`
|
|
BN.prototype.sqr = function sqr () {
|
|
return this.mul(this);
|
|
};
|
|
|
|
// `this` * `this` in-place
|
|
BN.prototype.isqr = function isqr () {
|
|
return this.imul(this.clone());
|
|
};
|
|
|
|
// Math.pow(`this`, `num`)
|
|
BN.prototype.pow = function pow (num) {
|
|
var w = toBitArray(num);
|
|
if (w.length === 0) return new BN(1);
|
|
|
|
// Skip leading zeroes
|
|
var res = this;
|
|
for (var i = 0; i < w.length; i++, res = res.sqr()) {
|
|
if (w[i] !== 0) break;
|
|
}
|
|
|
|
if (++i < w.length) {
|
|
for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
|
|
if (w[i] === 0) continue;
|
|
|
|
res = res.mul(q);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Shift-left in-place
|
|
BN.prototype.iushln = function iushln (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
|
|
var i;
|
|
|
|
if (r !== 0) {
|
|
var carry = 0;
|
|
|
|
for (i = 0; i < this.length; i++) {
|
|
var newCarry = this.words[i] & carryMask;
|
|
var c = ((this.words[i] | 0) - newCarry) << r;
|
|
this.words[i] = c | carry;
|
|
carry = newCarry >>> (26 - r);
|
|
}
|
|
|
|
if (carry) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
}
|
|
|
|
if (s !== 0) {
|
|
for (i = this.length - 1; i >= 0; i--) {
|
|
this.words[i + s] = this.words[i];
|
|
}
|
|
|
|
for (i = 0; i < s; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
this.length += s;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishln = function ishln (bits) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushln(bits);
|
|
};
|
|
|
|
// Shift-right in-place
|
|
// NOTE: `hint` is a lowest bit before trailing zeroes
|
|
// NOTE: if `extended` is present - it will be filled with destroyed bits
|
|
BN.prototype.iushrn = function iushrn (bits, hint, extended) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var h;
|
|
if (hint) {
|
|
h = (hint - (hint % 26)) / 26;
|
|
} else {
|
|
h = 0;
|
|
}
|
|
|
|
var r = bits % 26;
|
|
var s = Math.min((bits - r) / 26, this.length);
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
var maskedWords = extended;
|
|
|
|
h -= s;
|
|
h = Math.max(0, h);
|
|
|
|
// Extended mode, copy masked part
|
|
if (maskedWords) {
|
|
for (var i = 0; i < s; i++) {
|
|
maskedWords.words[i] = this.words[i];
|
|
}
|
|
maskedWords.length = s;
|
|
}
|
|
|
|
if (s === 0) {
|
|
// No-op, we should not move anything at all
|
|
} else if (this.length > s) {
|
|
this.length -= s;
|
|
for (i = 0; i < this.length; i++) {
|
|
this.words[i] = this.words[i + s];
|
|
}
|
|
} else {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
|
|
var word = this.words[i] | 0;
|
|
this.words[i] = (carry << (26 - r)) | (word >>> r);
|
|
carry = word & mask;
|
|
}
|
|
|
|
// Push carried bits as a mask
|
|
if (maskedWords && carry !== 0) {
|
|
maskedWords.words[maskedWords.length++] = carry;
|
|
}
|
|
|
|
if (this.length === 0) {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishrn = function ishrn (bits, hint, extended) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushrn(bits, hint, extended);
|
|
};
|
|
|
|
// Shift-left
|
|
BN.prototype.shln = function shln (bits) {
|
|
return this.clone().ishln(bits);
|
|
};
|
|
|
|
BN.prototype.ushln = function ushln (bits) {
|
|
return this.clone().iushln(bits);
|
|
};
|
|
|
|
// Shift-right
|
|
BN.prototype.shrn = function shrn (bits) {
|
|
return this.clone().ishrn(bits);
|
|
};
|
|
|
|
BN.prototype.ushrn = function ushrn (bits) {
|
|
return this.clone().iushrn(bits);
|
|
};
|
|
|
|
// Test if n bit is set
|
|
BN.prototype.testn = function testn (bit) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) return false;
|
|
|
|
// Check bit and return
|
|
var w = this.words[s];
|
|
|
|
return !!(w & q);
|
|
};
|
|
|
|
// Return only lowers bits of number (in-place)
|
|
BN.prototype.imaskn = function imaskn (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
|
|
assert(this.negative === 0, 'imaskn works only with positive numbers');
|
|
|
|
if (this.length <= s) {
|
|
return this;
|
|
}
|
|
|
|
if (r !== 0) {
|
|
s++;
|
|
}
|
|
this.length = Math.min(s, this.length);
|
|
|
|
if (r !== 0) {
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
this.words[this.length - 1] &= mask;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Return only lowers bits of number
|
|
BN.prototype.maskn = function maskn (bits) {
|
|
return this.clone().imaskn(bits);
|
|
};
|
|
|
|
// Add plain number `num` to `this`
|
|
BN.prototype.iaddn = function iaddn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.isubn(-num);
|
|
|
|
// Possible sign change
|
|
if (this.negative !== 0) {
|
|
if (this.length === 1 && (this.words[0] | 0) < num) {
|
|
this.words[0] = num - (this.words[0] | 0);
|
|
this.negative = 0;
|
|
return this;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.isubn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
// Add without checks
|
|
return this._iaddn(num);
|
|
};
|
|
|
|
BN.prototype._iaddn = function _iaddn (num) {
|
|
this.words[0] += num;
|
|
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
|
|
this.words[i] -= 0x4000000;
|
|
if (i === this.length - 1) {
|
|
this.words[i + 1] = 1;
|
|
} else {
|
|
this.words[i + 1]++;
|
|
}
|
|
}
|
|
this.length = Math.max(this.length, i + 1);
|
|
|
|
return this;
|
|
};
|
|
|
|
// Subtract plain number `num` from `this`
|
|
BN.prototype.isubn = function isubn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.iaddn(-num);
|
|
|
|
if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iaddn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
this.words[0] -= num;
|
|
|
|
if (this.length === 1 && this.words[0] < 0) {
|
|
this.words[0] = -this.words[0];
|
|
this.negative = 1;
|
|
} else {
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
|
|
this.words[i] += 0x4000000;
|
|
this.words[i + 1] -= 1;
|
|
}
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.addn = function addn (num) {
|
|
return this.clone().iaddn(num);
|
|
};
|
|
|
|
BN.prototype.subn = function subn (num) {
|
|
return this.clone().isubn(num);
|
|
};
|
|
|
|
BN.prototype.iabs = function iabs () {
|
|
this.negative = 0;
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.abs = function abs () {
|
|
return this.clone().iabs();
|
|
};
|
|
|
|
BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
|
|
var len = num.length + shift;
|
|
var i;
|
|
|
|
this._expand(len);
|
|
|
|
var w;
|
|
var carry = 0;
|
|
for (i = 0; i < num.length; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
var right = (num.words[i] | 0) * mul;
|
|
w -= right & 0x3ffffff;
|
|
carry = (w >> 26) - ((right / 0x4000000) | 0);
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
for (; i < this.length - shift; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
|
|
if (carry === 0) return this.strip();
|
|
|
|
// Subtraction overflow
|
|
assert(carry === -1);
|
|
carry = 0;
|
|
for (i = 0; i < this.length; i++) {
|
|
w = -(this.words[i] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i] = w & 0x3ffffff;
|
|
}
|
|
this.negative = 1;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype._wordDiv = function _wordDiv (num, mode) {
|
|
var shift = this.length - num.length;
|
|
|
|
var a = this.clone();
|
|
var b = num;
|
|
|
|
// Normalize
|
|
var bhi = b.words[b.length - 1] | 0;
|
|
var bhiBits = this._countBits(bhi);
|
|
shift = 26 - bhiBits;
|
|
if (shift !== 0) {
|
|
b = b.ushln(shift);
|
|
a.iushln(shift);
|
|
bhi = b.words[b.length - 1] | 0;
|
|
}
|
|
|
|
// Initialize quotient
|
|
var m = a.length - b.length;
|
|
var q;
|
|
|
|
if (mode !== 'mod') {
|
|
q = new BN(null);
|
|
q.length = m + 1;
|
|
q.words = new Array(q.length);
|
|
for (var i = 0; i < q.length; i++) {
|
|
q.words[i] = 0;
|
|
}
|
|
}
|
|
|
|
var diff = a.clone()._ishlnsubmul(b, 1, m);
|
|
if (diff.negative === 0) {
|
|
a = diff;
|
|
if (q) {
|
|
q.words[m] = 1;
|
|
}
|
|
}
|
|
|
|
for (var j = m - 1; j >= 0; j--) {
|
|
var qj = (a.words[b.length + j] | 0) * 0x4000000 +
|
|
(a.words[b.length + j - 1] | 0);
|
|
|
|
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
|
|
// (0x7ffffff)
|
|
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
|
|
|
|
a._ishlnsubmul(b, qj, j);
|
|
while (a.negative !== 0) {
|
|
qj--;
|
|
a.negative = 0;
|
|
a._ishlnsubmul(b, 1, j);
|
|
if (!a.isZero()) {
|
|
a.negative ^= 1;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.words[j] = qj;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.strip();
|
|
}
|
|
a.strip();
|
|
|
|
// Denormalize
|
|
if (mode !== 'div' && shift !== 0) {
|
|
a.iushrn(shift);
|
|
}
|
|
|
|
return {
|
|
div: q || null,
|
|
mod: a
|
|
};
|
|
};
|
|
|
|
// NOTE: 1) `mode` can be set to `mod` to request mod only,
|
|
// to `div` to request div only, or be absent to
|
|
// request both div & mod
|
|
// 2) `positive` is true if unsigned mod is requested
|
|
BN.prototype.divmod = function divmod (num, mode, positive) {
|
|
assert(!num.isZero());
|
|
|
|
if (this.isZero()) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: new BN(0)
|
|
};
|
|
}
|
|
|
|
var div, mod, res;
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
res = this.neg().divmod(num, mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.iadd(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
if (this.negative === 0 && num.negative !== 0) {
|
|
res = this.divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: res.mod
|
|
};
|
|
}
|
|
|
|
if ((this.negative & num.negative) !== 0) {
|
|
res = this.neg().divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.isub(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: res.div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
// Both numbers are positive at this point
|
|
|
|
// Strip both numbers to approximate shift value
|
|
if (num.length > this.length || this.cmp(num) < 0) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: this
|
|
};
|
|
}
|
|
|
|
// Very short reduction
|
|
if (num.length === 1) {
|
|
if (mode === 'div') {
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: null
|
|
};
|
|
}
|
|
|
|
if (mode === 'mod') {
|
|
return {
|
|
div: null,
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return this._wordDiv(num, mode);
|
|
};
|
|
|
|
// Find `this` / `num`
|
|
BN.prototype.div = function div (num) {
|
|
return this.divmod(num, 'div', false).div;
|
|
};
|
|
|
|
// Find `this` % `num`
|
|
BN.prototype.mod = function mod (num) {
|
|
return this.divmod(num, 'mod', false).mod;
|
|
};
|
|
|
|
BN.prototype.umod = function umod (num) {
|
|
return this.divmod(num, 'mod', true).mod;
|
|
};
|
|
|
|
// Find Round(`this` / `num`)
|
|
BN.prototype.divRound = function divRound (num) {
|
|
var dm = this.divmod(num);
|
|
|
|
// Fast case - exact division
|
|
if (dm.mod.isZero()) return dm.div;
|
|
|
|
var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
|
|
|
|
var half = num.ushrn(1);
|
|
var r2 = num.andln(1);
|
|
var cmp = mod.cmp(half);
|
|
|
|
// Round down
|
|
if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
|
|
|
|
// Round up
|
|
return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
|
|
};
|
|
|
|
BN.prototype.modn = function modn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
var p = (1 << 26) % num;
|
|
|
|
var acc = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
acc = (p * acc + (this.words[i] | 0)) % num;
|
|
}
|
|
|
|
return acc;
|
|
};
|
|
|
|
// In-place division by number
|
|
BN.prototype.idivn = function idivn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
|
|
var carry = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var w = (this.words[i] | 0) + carry * 0x4000000;
|
|
this.words[i] = (w / num) | 0;
|
|
carry = w % num;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.divn = function divn (num) {
|
|
return this.clone().idivn(num);
|
|
};
|
|
|
|
BN.prototype.egcd = function egcd (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var x = this;
|
|
var y = p.clone();
|
|
|
|
if (x.negative !== 0) {
|
|
x = x.umod(p);
|
|
} else {
|
|
x = x.clone();
|
|
}
|
|
|
|
// A * x + B * y = x
|
|
var A = new BN(1);
|
|
var B = new BN(0);
|
|
|
|
// C * x + D * y = y
|
|
var C = new BN(0);
|
|
var D = new BN(1);
|
|
|
|
var g = 0;
|
|
|
|
while (x.isEven() && y.isEven()) {
|
|
x.iushrn(1);
|
|
y.iushrn(1);
|
|
++g;
|
|
}
|
|
|
|
var yp = y.clone();
|
|
var xp = x.clone();
|
|
|
|
while (!x.isZero()) {
|
|
for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
x.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (A.isOdd() || B.isOdd()) {
|
|
A.iadd(yp);
|
|
B.isub(xp);
|
|
}
|
|
|
|
A.iushrn(1);
|
|
B.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
y.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (C.isOdd() || D.isOdd()) {
|
|
C.iadd(yp);
|
|
D.isub(xp);
|
|
}
|
|
|
|
C.iushrn(1);
|
|
D.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (x.cmp(y) >= 0) {
|
|
x.isub(y);
|
|
A.isub(C);
|
|
B.isub(D);
|
|
} else {
|
|
y.isub(x);
|
|
C.isub(A);
|
|
D.isub(B);
|
|
}
|
|
}
|
|
|
|
return {
|
|
a: C,
|
|
b: D,
|
|
gcd: y.iushln(g)
|
|
};
|
|
};
|
|
|
|
// This is reduced incarnation of the binary EEA
|
|
// above, designated to invert members of the
|
|
// _prime_ fields F(p) at a maximal speed
|
|
BN.prototype._invmp = function _invmp (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var a = this;
|
|
var b = p.clone();
|
|
|
|
if (a.negative !== 0) {
|
|
a = a.umod(p);
|
|
} else {
|
|
a = a.clone();
|
|
}
|
|
|
|
var x1 = new BN(1);
|
|
var x2 = new BN(0);
|
|
|
|
var delta = b.clone();
|
|
|
|
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
|
|
for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
a.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (x1.isOdd()) {
|
|
x1.iadd(delta);
|
|
}
|
|
|
|
x1.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
b.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (x2.isOdd()) {
|
|
x2.iadd(delta);
|
|
}
|
|
|
|
x2.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (a.cmp(b) >= 0) {
|
|
a.isub(b);
|
|
x1.isub(x2);
|
|
} else {
|
|
b.isub(a);
|
|
x2.isub(x1);
|
|
}
|
|
}
|
|
|
|
var res;
|
|
if (a.cmpn(1) === 0) {
|
|
res = x1;
|
|
} else {
|
|
res = x2;
|
|
}
|
|
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(p);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gcd = function gcd (num) {
|
|
if (this.isZero()) return num.abs();
|
|
if (num.isZero()) return this.abs();
|
|
|
|
var a = this.clone();
|
|
var b = num.clone();
|
|
a.negative = 0;
|
|
b.negative = 0;
|
|
|
|
// Remove common factor of two
|
|
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
|
|
a.iushrn(1);
|
|
b.iushrn(1);
|
|
}
|
|
|
|
do {
|
|
while (a.isEven()) {
|
|
a.iushrn(1);
|
|
}
|
|
while (b.isEven()) {
|
|
b.iushrn(1);
|
|
}
|
|
|
|
var r = a.cmp(b);
|
|
if (r < 0) {
|
|
// Swap `a` and `b` to make `a` always bigger than `b`
|
|
var t = a;
|
|
a = b;
|
|
b = t;
|
|
} else if (r === 0 || b.cmpn(1) === 0) {
|
|
break;
|
|
}
|
|
|
|
a.isub(b);
|
|
} while (true);
|
|
|
|
return b.iushln(shift);
|
|
};
|
|
|
|
// Invert number in the field F(num)
|
|
BN.prototype.invm = function invm (num) {
|
|
return this.egcd(num).a.umod(num);
|
|
};
|
|
|
|
BN.prototype.isEven = function isEven () {
|
|
return (this.words[0] & 1) === 0;
|
|
};
|
|
|
|
BN.prototype.isOdd = function isOdd () {
|
|
return (this.words[0] & 1) === 1;
|
|
};
|
|
|
|
// And first word and num
|
|
BN.prototype.andln = function andln (num) {
|
|
return this.words[0] & num;
|
|
};
|
|
|
|
// Increment at the bit position in-line
|
|
BN.prototype.bincn = function bincn (bit) {
|
|
assert(typeof bit === 'number');
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) {
|
|
this._expand(s + 1);
|
|
this.words[s] |= q;
|
|
return this;
|
|
}
|
|
|
|
// Add bit and propagate, if needed
|
|
var carry = q;
|
|
for (var i = s; carry !== 0 && i < this.length; i++) {
|
|
var w = this.words[i] | 0;
|
|
w += carry;
|
|
carry = w >>> 26;
|
|
w &= 0x3ffffff;
|
|
this.words[i] = w;
|
|
}
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.isZero = function isZero () {
|
|
return this.length === 1 && this.words[0] === 0;
|
|
};
|
|
|
|
BN.prototype.cmpn = function cmpn (num) {
|
|
var negative = num < 0;
|
|
|
|
if (this.negative !== 0 && !negative) return -1;
|
|
if (this.negative === 0 && negative) return 1;
|
|
|
|
this.strip();
|
|
|
|
var res;
|
|
if (this.length > 1) {
|
|
res = 1;
|
|
} else {
|
|
if (negative) {
|
|
num = -num;
|
|
}
|
|
|
|
assert(num <= 0x3ffffff, 'Number is too big');
|
|
|
|
var w = this.words[0] | 0;
|
|
res = w === num ? 0 : w < num ? -1 : 1;
|
|
}
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Compare two numbers and return:
|
|
// 1 - if `this` > `num`
|
|
// 0 - if `this` == `num`
|
|
// -1 - if `this` < `num`
|
|
BN.prototype.cmp = function cmp (num) {
|
|
if (this.negative !== 0 && num.negative === 0) return -1;
|
|
if (this.negative === 0 && num.negative !== 0) return 1;
|
|
|
|
var res = this.ucmp(num);
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Unsigned comparison
|
|
BN.prototype.ucmp = function ucmp (num) {
|
|
// At this point both numbers have the same sign
|
|
if (this.length > num.length) return 1;
|
|
if (this.length < num.length) return -1;
|
|
|
|
var res = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var a = this.words[i] | 0;
|
|
var b = num.words[i] | 0;
|
|
|
|
if (a === b) continue;
|
|
if (a < b) {
|
|
res = -1;
|
|
} else if (a > b) {
|
|
res = 1;
|
|
}
|
|
break;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gtn = function gtn (num) {
|
|
return this.cmpn(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gt = function gt (num) {
|
|
return this.cmp(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gten = function gten (num) {
|
|
return this.cmpn(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.gte = function gte (num) {
|
|
return this.cmp(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.ltn = function ltn (num) {
|
|
return this.cmpn(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lt = function lt (num) {
|
|
return this.cmp(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lten = function lten (num) {
|
|
return this.cmpn(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.lte = function lte (num) {
|
|
return this.cmp(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.eqn = function eqn (num) {
|
|
return this.cmpn(num) === 0;
|
|
};
|
|
|
|
BN.prototype.eq = function eq (num) {
|
|
return this.cmp(num) === 0;
|
|
};
|
|
|
|
//
|
|
// A reduce context, could be using montgomery or something better, depending
|
|
// on the `m` itself.
|
|
//
|
|
BN.red = function red (num) {
|
|
return new Red(num);
|
|
};
|
|
|
|
BN.prototype.toRed = function toRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
assert(this.negative === 0, 'red works only with positives');
|
|
return ctx.convertTo(this)._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.fromRed = function fromRed () {
|
|
assert(this.red, 'fromRed works only with numbers in reduction context');
|
|
return this.red.convertFrom(this);
|
|
};
|
|
|
|
BN.prototype._forceRed = function _forceRed (ctx) {
|
|
this.red = ctx;
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.forceRed = function forceRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
return this._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.redAdd = function redAdd (num) {
|
|
assert(this.red, 'redAdd works only with red numbers');
|
|
return this.red.add(this, num);
|
|
};
|
|
|
|
BN.prototype.redIAdd = function redIAdd (num) {
|
|
assert(this.red, 'redIAdd works only with red numbers');
|
|
return this.red.iadd(this, num);
|
|
};
|
|
|
|
BN.prototype.redSub = function redSub (num) {
|
|
assert(this.red, 'redSub works only with red numbers');
|
|
return this.red.sub(this, num);
|
|
};
|
|
|
|
BN.prototype.redISub = function redISub (num) {
|
|
assert(this.red, 'redISub works only with red numbers');
|
|
return this.red.isub(this, num);
|
|
};
|
|
|
|
BN.prototype.redShl = function redShl (num) {
|
|
assert(this.red, 'redShl works only with red numbers');
|
|
return this.red.shl(this, num);
|
|
};
|
|
|
|
BN.prototype.redMul = function redMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.mul(this, num);
|
|
};
|
|
|
|
BN.prototype.redIMul = function redIMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.imul(this, num);
|
|
};
|
|
|
|
BN.prototype.redSqr = function redSqr () {
|
|
assert(this.red, 'redSqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqr(this);
|
|
};
|
|
|
|
BN.prototype.redISqr = function redISqr () {
|
|
assert(this.red, 'redISqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.isqr(this);
|
|
};
|
|
|
|
// Square root over p
|
|
BN.prototype.redSqrt = function redSqrt () {
|
|
assert(this.red, 'redSqrt works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqrt(this);
|
|
};
|
|
|
|
BN.prototype.redInvm = function redInvm () {
|
|
assert(this.red, 'redInvm works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.invm(this);
|
|
};
|
|
|
|
// Return negative clone of `this` % `red modulo`
|
|
BN.prototype.redNeg = function redNeg () {
|
|
assert(this.red, 'redNeg works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.neg(this);
|
|
};
|
|
|
|
BN.prototype.redPow = function redPow (num) {
|
|
assert(this.red && !num.red, 'redPow(normalNum)');
|
|
this.red._verify1(this);
|
|
return this.red.pow(this, num);
|
|
};
|
|
|
|
// Prime numbers with efficient reduction
|
|
var primes = {
|
|
k256: null,
|
|
p224: null,
|
|
p192: null,
|
|
p25519: null
|
|
};
|
|
|
|
// Pseudo-Mersenne prime
|
|
function MPrime (name, p) {
|
|
// P = 2 ^ N - K
|
|
this.name = name;
|
|
this.p = new BN(p, 16);
|
|
this.n = this.p.bitLength();
|
|
this.k = new BN(1).iushln(this.n).isub(this.p);
|
|
|
|
this.tmp = this._tmp();
|
|
}
|
|
|
|
MPrime.prototype._tmp = function _tmp () {
|
|
var tmp = new BN(null);
|
|
tmp.words = new Array(Math.ceil(this.n / 13));
|
|
return tmp;
|
|
};
|
|
|
|
MPrime.prototype.ireduce = function ireduce (num) {
|
|
// Assumes that `num` is less than `P^2`
|
|
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
|
|
var r = num;
|
|
var rlen;
|
|
|
|
do {
|
|
this.split(r, this.tmp);
|
|
r = this.imulK(r);
|
|
r = r.iadd(this.tmp);
|
|
rlen = r.bitLength();
|
|
} while (rlen > this.n);
|
|
|
|
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
|
|
if (cmp === 0) {
|
|
r.words[0] = 0;
|
|
r.length = 1;
|
|
} else if (cmp > 0) {
|
|
r.isub(this.p);
|
|
} else {
|
|
if (r.strip !== undefined) {
|
|
// r is BN v4 instance
|
|
r.strip();
|
|
} else {
|
|
// r is BN v5 instance
|
|
r._strip();
|
|
}
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
MPrime.prototype.split = function split (input, out) {
|
|
input.iushrn(this.n, 0, out);
|
|
};
|
|
|
|
MPrime.prototype.imulK = function imulK (num) {
|
|
return num.imul(this.k);
|
|
};
|
|
|
|
function K256 () {
|
|
MPrime.call(
|
|
this,
|
|
'k256',
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
|
|
}
|
|
inherits(K256, MPrime);
|
|
|
|
K256.prototype.split = function split (input, output) {
|
|
// 256 = 9 * 26 + 22
|
|
var mask = 0x3fffff;
|
|
|
|
var outLen = Math.min(input.length, 9);
|
|
for (var i = 0; i < outLen; i++) {
|
|
output.words[i] = input.words[i];
|
|
}
|
|
output.length = outLen;
|
|
|
|
if (input.length <= 9) {
|
|
input.words[0] = 0;
|
|
input.length = 1;
|
|
return;
|
|
}
|
|
|
|
// Shift by 9 limbs
|
|
var prev = input.words[9];
|
|
output.words[output.length++] = prev & mask;
|
|
|
|
for (i = 10; i < input.length; i++) {
|
|
var next = input.words[i] | 0;
|
|
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
|
|
prev = next;
|
|
}
|
|
prev >>>= 22;
|
|
input.words[i - 10] = prev;
|
|
if (prev === 0 && input.length > 10) {
|
|
input.length -= 10;
|
|
} else {
|
|
input.length -= 9;
|
|
}
|
|
};
|
|
|
|
K256.prototype.imulK = function imulK (num) {
|
|
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
|
|
num.words[num.length] = 0;
|
|
num.words[num.length + 1] = 0;
|
|
num.length += 2;
|
|
|
|
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
|
|
var lo = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var w = num.words[i] | 0;
|
|
lo += w * 0x3d1;
|
|
num.words[i] = lo & 0x3ffffff;
|
|
lo = w * 0x40 + ((lo / 0x4000000) | 0);
|
|
}
|
|
|
|
// Fast length reduction
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
}
|
|
}
|
|
return num;
|
|
};
|
|
|
|
function P224 () {
|
|
MPrime.call(
|
|
this,
|
|
'p224',
|
|
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
|
|
}
|
|
inherits(P224, MPrime);
|
|
|
|
function P192 () {
|
|
MPrime.call(
|
|
this,
|
|
'p192',
|
|
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
|
|
}
|
|
inherits(P192, MPrime);
|
|
|
|
function P25519 () {
|
|
// 2 ^ 255 - 19
|
|
MPrime.call(
|
|
this,
|
|
'25519',
|
|
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
|
|
}
|
|
inherits(P25519, MPrime);
|
|
|
|
P25519.prototype.imulK = function imulK (num) {
|
|
// K = 0x13
|
|
var carry = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var hi = (num.words[i] | 0) * 0x13 + carry;
|
|
var lo = hi & 0x3ffffff;
|
|
hi >>>= 26;
|
|
|
|
num.words[i] = lo;
|
|
carry = hi;
|
|
}
|
|
if (carry !== 0) {
|
|
num.words[num.length++] = carry;
|
|
}
|
|
return num;
|
|
};
|
|
|
|
// Exported mostly for testing purposes, use plain name instead
|
|
BN._prime = function prime (name) {
|
|
// Cached version of prime
|
|
if (primes[name]) return primes[name];
|
|
|
|
var prime;
|
|
if (name === 'k256') {
|
|
prime = new K256();
|
|
} else if (name === 'p224') {
|
|
prime = new P224();
|
|
} else if (name === 'p192') {
|
|
prime = new P192();
|
|
} else if (name === 'p25519') {
|
|
prime = new P25519();
|
|
} else {
|
|
throw new Error('Unknown prime ' + name);
|
|
}
|
|
primes[name] = prime;
|
|
|
|
return prime;
|
|
};
|
|
|
|
//
|
|
// Base reduction engine
|
|
//
|
|
function Red (m) {
|
|
if (typeof m === 'string') {
|
|
var prime = BN._prime(m);
|
|
this.m = prime.p;
|
|
this.prime = prime;
|
|
} else {
|
|
assert(m.gtn(1), 'modulus must be greater than 1');
|
|
this.m = m;
|
|
this.prime = null;
|
|
}
|
|
}
|
|
|
|
Red.prototype._verify1 = function _verify1 (a) {
|
|
assert(a.negative === 0, 'red works only with positives');
|
|
assert(a.red, 'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype._verify2 = function _verify2 (a, b) {
|
|
assert((a.negative | b.negative) === 0, 'red works only with positives');
|
|
assert(a.red && a.red === b.red,
|
|
'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype.imod = function imod (a) {
|
|
if (this.prime) return this.prime.ireduce(a)._forceRed(this);
|
|
return a.umod(this.m)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.neg = function neg (a) {
|
|
if (a.isZero()) {
|
|
return a.clone();
|
|
}
|
|
|
|
return this.m.sub(a)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.add = function add (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.add(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.iadd = function iadd (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.iadd(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.sub = function sub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.sub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.isub = function isub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.isub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.shl = function shl (a, num) {
|
|
this._verify1(a);
|
|
return this.imod(a.ushln(num));
|
|
};
|
|
|
|
Red.prototype.imul = function imul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.imul(b));
|
|
};
|
|
|
|
Red.prototype.mul = function mul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.mul(b));
|
|
};
|
|
|
|
Red.prototype.isqr = function isqr (a) {
|
|
return this.imul(a, a.clone());
|
|
};
|
|
|
|
Red.prototype.sqr = function sqr (a) {
|
|
return this.mul(a, a);
|
|
};
|
|
|
|
Red.prototype.sqrt = function sqrt (a) {
|
|
if (a.isZero()) return a.clone();
|
|
|
|
var mod3 = this.m.andln(3);
|
|
assert(mod3 % 2 === 1);
|
|
|
|
// Fast case
|
|
if (mod3 === 3) {
|
|
var pow = this.m.add(new BN(1)).iushrn(2);
|
|
return this.pow(a, pow);
|
|
}
|
|
|
|
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
|
|
//
|
|
// Find Q and S, that Q * 2 ^ S = (P - 1)
|
|
var q = this.m.subn(1);
|
|
var s = 0;
|
|
while (!q.isZero() && q.andln(1) === 0) {
|
|
s++;
|
|
q.iushrn(1);
|
|
}
|
|
assert(!q.isZero());
|
|
|
|
var one = new BN(1).toRed(this);
|
|
var nOne = one.redNeg();
|
|
|
|
// Find quadratic non-residue
|
|
// NOTE: Max is such because of generalized Riemann hypothesis.
|
|
var lpow = this.m.subn(1).iushrn(1);
|
|
var z = this.m.bitLength();
|
|
z = new BN(2 * z * z).toRed(this);
|
|
|
|
while (this.pow(z, lpow).cmp(nOne) !== 0) {
|
|
z.redIAdd(nOne);
|
|
}
|
|
|
|
var c = this.pow(z, q);
|
|
var r = this.pow(a, q.addn(1).iushrn(1));
|
|
var t = this.pow(a, q);
|
|
var m = s;
|
|
while (t.cmp(one) !== 0) {
|
|
var tmp = t;
|
|
for (var i = 0; tmp.cmp(one) !== 0; i++) {
|
|
tmp = tmp.redSqr();
|
|
}
|
|
assert(i < m);
|
|
var b = this.pow(c, new BN(1).iushln(m - i - 1));
|
|
|
|
r = r.redMul(b);
|
|
c = b.redSqr();
|
|
t = t.redMul(c);
|
|
m = i;
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
Red.prototype.invm = function invm (a) {
|
|
var inv = a._invmp(this.m);
|
|
if (inv.negative !== 0) {
|
|
inv.negative = 0;
|
|
return this.imod(inv).redNeg();
|
|
} else {
|
|
return this.imod(inv);
|
|
}
|
|
};
|
|
|
|
Red.prototype.pow = function pow (a, num) {
|
|
if (num.isZero()) return new BN(1).toRed(this);
|
|
if (num.cmpn(1) === 0) return a.clone();
|
|
|
|
var windowSize = 4;
|
|
var wnd = new Array(1 << windowSize);
|
|
wnd[0] = new BN(1).toRed(this);
|
|
wnd[1] = a;
|
|
for (var i = 2; i < wnd.length; i++) {
|
|
wnd[i] = this.mul(wnd[i - 1], a);
|
|
}
|
|
|
|
var res = wnd[0];
|
|
var current = 0;
|
|
var currentLen = 0;
|
|
var start = num.bitLength() % 26;
|
|
if (start === 0) {
|
|
start = 26;
|
|
}
|
|
|
|
for (i = num.length - 1; i >= 0; i--) {
|
|
var word = num.words[i];
|
|
for (var j = start - 1; j >= 0; j--) {
|
|
var bit = (word >> j) & 1;
|
|
if (res !== wnd[0]) {
|
|
res = this.sqr(res);
|
|
}
|
|
|
|
if (bit === 0 && current === 0) {
|
|
currentLen = 0;
|
|
continue;
|
|
}
|
|
|
|
current <<= 1;
|
|
current |= bit;
|
|
currentLen++;
|
|
if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
|
|
|
|
res = this.mul(res, wnd[current]);
|
|
currentLen = 0;
|
|
current = 0;
|
|
}
|
|
start = 26;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.convertTo = function convertTo (num) {
|
|
var r = num.umod(this.m);
|
|
|
|
return r === num ? r.clone() : r;
|
|
};
|
|
|
|
Red.prototype.convertFrom = function convertFrom (num) {
|
|
var res = num.clone();
|
|
res.red = null;
|
|
return res;
|
|
};
|
|
|
|
//
|
|
// Montgomery method engine
|
|
//
|
|
|
|
BN.mont = function mont (num) {
|
|
return new Mont(num);
|
|
};
|
|
|
|
function Mont (m) {
|
|
Red.call(this, m);
|
|
|
|
this.shift = this.m.bitLength();
|
|
if (this.shift % 26 !== 0) {
|
|
this.shift += 26 - (this.shift % 26);
|
|
}
|
|
|
|
this.r = new BN(1).iushln(this.shift);
|
|
this.r2 = this.imod(this.r.sqr());
|
|
this.rinv = this.r._invmp(this.m);
|
|
|
|
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
|
|
this.minv = this.minv.umod(this.r);
|
|
this.minv = this.r.sub(this.minv);
|
|
}
|
|
inherits(Mont, Red);
|
|
|
|
Mont.prototype.convertTo = function convertTo (num) {
|
|
return this.imod(num.ushln(this.shift));
|
|
};
|
|
|
|
Mont.prototype.convertFrom = function convertFrom (num) {
|
|
var r = this.imod(num.mul(this.rinv));
|
|
r.red = null;
|
|
return r;
|
|
};
|
|
|
|
Mont.prototype.imul = function imul (a, b) {
|
|
if (a.isZero() || b.isZero()) {
|
|
a.words[0] = 0;
|
|
a.length = 1;
|
|
return a;
|
|
}
|
|
|
|
var t = a.imul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.mul = function mul (a, b) {
|
|
if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
|
|
|
|
var t = a.mul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.invm = function invm (a) {
|
|
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
|
|
var res = this.imod(a._invmp(this.m).mul(this.r2));
|
|
return res._forceRed(this);
|
|
};
|
|
})( false || module, this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/EbmlStreamDecoder.js":
|
|
/*!***********************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/EbmlStreamDecoder.js ***!
|
|
\***********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
const stream_1 = __webpack_require__(/*! stream */ "./node_modules/stream-browserify/index.js");
|
|
const tools_1 = __webpack_require__(/*! ./tools */ "./node_modules/ebml-stream/lib/tools.js");
|
|
const EbmlElementType_1 = __webpack_require__(/*! ./models/enums/EbmlElementType */ "./node_modules/ebml-stream/lib/models/enums/EbmlElementType.js");
|
|
const EbmlTagPosition_1 = __webpack_require__(/*! ./models/enums/EbmlTagPosition */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagPosition.js");
|
|
const EbmlTagFactory_1 = __webpack_require__(/*! ./models/EbmlTagFactory */ "./node_modules/ebml-stream/lib/models/EbmlTagFactory.js");
|
|
class EbmlStreamDecoderOptions {
|
|
constructor() {
|
|
this.bufferTagIds = [];
|
|
}
|
|
}
|
|
exports.EbmlStreamDecoderOptions = EbmlStreamDecoderOptions;
|
|
class EbmlStreamDecoder extends stream_1.Transform {
|
|
constructor(options = {}) {
|
|
super(Object.assign({}, options, { readableObjectMode: true }));
|
|
this._currentBufferOffset = 0;
|
|
this._tagStack = [];
|
|
this._buffer = Buffer.alloc(0);
|
|
this._bufferTagIds = [];
|
|
this._bufferTagIds = options.bufferTagIds || [];
|
|
}
|
|
get buffer() {
|
|
return this._buffer;
|
|
}
|
|
_transform(chunk, enc, done) {
|
|
this._buffer = Buffer.concat([this._buffer, Buffer.from(chunk)]);
|
|
while (this.parseTags())
|
|
;
|
|
done();
|
|
}
|
|
parseTags() {
|
|
const currentTag = this.readTagHeader(this._buffer);
|
|
if (!currentTag) {
|
|
return false;
|
|
}
|
|
if (currentTag.type === EbmlElementType_1.EbmlElementType.Master && !this._bufferTagIds.some(i => i === currentTag.id)) {
|
|
this._tagStack.push(currentTag);
|
|
this.emitTag(currentTag, EbmlTagPosition_1.EbmlTagPosition.Start);
|
|
this.advanceBuffer(currentTag.tagHeaderLength);
|
|
return true;
|
|
}
|
|
else {
|
|
if (this._buffer.length < currentTag.tagHeaderLength + currentTag.size) {
|
|
return false;
|
|
}
|
|
const data = this._buffer.slice(currentTag.tagHeaderLength, currentTag.tagHeaderLength + currentTag.size);
|
|
this.emitTag(currentTag, EbmlTagPosition_1.EbmlTagPosition.Content, data);
|
|
this.advanceBuffer(currentTag.tagHeaderLength + currentTag.size);
|
|
while (this._tagStack.length > 0) {
|
|
const nextTag = this._tagStack[this._tagStack.length - 1];
|
|
if (this._currentBufferOffset < (nextTag.absoluteStart + nextTag.tagHeaderLength + nextTag.size)) {
|
|
break;
|
|
}
|
|
this.emitTag(nextTag, EbmlTagPosition_1.EbmlTagPosition.End);
|
|
this._tagStack.pop();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
advanceBuffer(length) {
|
|
this._currentBufferOffset += length;
|
|
this._buffer = this._buffer.slice(length);
|
|
}
|
|
readTagHeader(buffer, offset = 0) {
|
|
if (buffer.length == 0) {
|
|
return null;
|
|
}
|
|
const tag = tools_1.Tools.readVint(buffer, offset);
|
|
if (tag == null) {
|
|
return null;
|
|
}
|
|
const size = tools_1.Tools.readVint(buffer, offset + tag.length);
|
|
if (size == null) {
|
|
return null;
|
|
}
|
|
const tagIdHex = tools_1.Tools.readHexString(buffer, offset, offset + tag.length);
|
|
const tagId = Number.parseInt(tagIdHex, 16);
|
|
let tagObject = EbmlTagFactory_1.EbmlTagFactory.create(tagId);
|
|
tagObject.size = size.value;
|
|
return Object.assign(tagObject, {
|
|
absoluteStart: this._currentBufferOffset + offset,
|
|
tagHeaderLength: tag.length + size.length
|
|
});
|
|
}
|
|
emitTag(tag, position, data) {
|
|
let emittedTag = EbmlTagFactory_1.EbmlTagFactory.create(tag.id);
|
|
emittedTag.size = tag.size;
|
|
emittedTag.position = position;
|
|
if (position === EbmlTagPosition_1.EbmlTagPosition.Content) {
|
|
emittedTag.parseContent(data);
|
|
}
|
|
this.push(emittedTag);
|
|
}
|
|
}
|
|
exports.EbmlStreamDecoder = EbmlStreamDecoder;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/EbmlStreamEncoder.js":
|
|
/*!***********************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/EbmlStreamEncoder.js ***!
|
|
\***********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
const stream_1 = __webpack_require__(/*! stream */ "./node_modules/stream-browserify/index.js");
|
|
const EbmlTagPosition_1 = __webpack_require__(/*! ./models/enums/EbmlTagPosition */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagPosition.js");
|
|
const EbmlTagId_1 = __webpack_require__(/*! ./models/enums/EbmlTagId */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagId.js");
|
|
class EbmlStreamEncoder extends stream_1.Transform {
|
|
constructor(options = {}) {
|
|
super(Object.assign({}, options, { writableObjectMode: true }));
|
|
this.dataBuffer = Buffer.alloc(0);
|
|
this.mCorked = false;
|
|
this.openTags = [];
|
|
}
|
|
_transform(chunk, enc, done) {
|
|
if (chunk) {
|
|
if (!chunk.id) {
|
|
throw new Error(`No id found for ${JSON.stringify(chunk)}`);
|
|
}
|
|
switch (chunk.position) {
|
|
case EbmlTagPosition_1.EbmlTagPosition.Start:
|
|
this.startTag(chunk);
|
|
break;
|
|
case EbmlTagPosition_1.EbmlTagPosition.Content:
|
|
this.writeTag(chunk);
|
|
break;
|
|
case EbmlTagPosition_1.EbmlTagPosition.End:
|
|
this.endTag(chunk);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
done();
|
|
}
|
|
bufferAndFlush(buffer) {
|
|
this.dataBuffer = Buffer.concat([this.dataBuffer, buffer]);
|
|
this._flush(() => { });
|
|
}
|
|
_flush(callback) {
|
|
let chunk = null;
|
|
if (this.dataBuffer.length > 0 && !this.mCorked) {
|
|
chunk = Buffer.from(this.dataBuffer);
|
|
this.dataBuffer = Buffer.alloc(0);
|
|
this.push(chunk);
|
|
}
|
|
callback();
|
|
}
|
|
_bufferAndFlush(buffer) {
|
|
this.bufferAndFlush(buffer);
|
|
}
|
|
flush() {
|
|
this._flush(() => { });
|
|
}
|
|
get buffer() {
|
|
return this.dataBuffer;
|
|
}
|
|
set buffer(val) {
|
|
this.dataBuffer = val;
|
|
}
|
|
get stack() {
|
|
return this.openTags;
|
|
}
|
|
cork() {
|
|
this.mCorked = true;
|
|
}
|
|
uncork() {
|
|
this.mCorked = false;
|
|
this._flush(() => { });
|
|
}
|
|
writeTag(tag) {
|
|
if (this.openTags.length > 0) {
|
|
this.openTags[this.openTags.length - 1].Children.push(tag);
|
|
}
|
|
else {
|
|
this.bufferAndFlush(tag.encode());
|
|
}
|
|
}
|
|
startTag(tag) {
|
|
if (this.openTags.length > 0) {
|
|
this.openTags[this.openTags.length - 1].Children.push(tag);
|
|
}
|
|
this.openTags.push(tag);
|
|
}
|
|
endTag(tag) {
|
|
const inMemoryTag = this.openTags.pop();
|
|
if (tag.id !== inMemoryTag.id) {
|
|
throw `Logic error - closing tag "${EbmlTagId_1.EbmlTagId[tag.id]}" is not expected tag "${EbmlTagId_1.EbmlTagId[inMemoryTag.id]}"`;
|
|
}
|
|
if (this.openTags.length < 1) {
|
|
this.bufferAndFlush(inMemoryTag.encode());
|
|
}
|
|
}
|
|
}
|
|
exports.EbmlStreamEncoder = EbmlStreamEncoder;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/index.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/index.js ***!
|
|
\***********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
var tools_1 = __webpack_require__(/*! ./tools */ "./node_modules/ebml-stream/lib/tools.js");
|
|
exports.Tools = tools_1.Tools;
|
|
var EbmlStreamDecoder_1 = __webpack_require__(/*! ./EbmlStreamDecoder */ "./node_modules/ebml-stream/lib/EbmlStreamDecoder.js");
|
|
exports.EbmlStreamDecoder = EbmlStreamDecoder_1.EbmlStreamDecoder;
|
|
var EbmlStreamEncoder_1 = __webpack_require__(/*! ./EbmlStreamEncoder */ "./node_modules/ebml-stream/lib/EbmlStreamEncoder.js");
|
|
exports.EbmlStreamEncoder = EbmlStreamEncoder_1.EbmlStreamEncoder;
|
|
var Block_1 = __webpack_require__(/*! ./models/tags/Block */ "./node_modules/ebml-stream/lib/models/tags/Block.js");
|
|
exports.Block = Block_1.Block;
|
|
var BlockLacing_1 = __webpack_require__(/*! ./models/enums/BlockLacing */ "./node_modules/ebml-stream/lib/models/enums/BlockLacing.js");
|
|
exports.BlockLacing = BlockLacing_1.BlockLacing;
|
|
var EbmlDataTag_1 = __webpack_require__(/*! ./models/tags/EbmlDataTag */ "./node_modules/ebml-stream/lib/models/tags/EbmlDataTag.js");
|
|
exports.EbmlDataTag = EbmlDataTag_1.EbmlDataTag;
|
|
var EbmlElementType_1 = __webpack_require__(/*! ./models/enums/EbmlElementType */ "./node_modules/ebml-stream/lib/models/enums/EbmlElementType.js");
|
|
exports.EbmlElementType = EbmlElementType_1.EbmlElementType;
|
|
var EbmlMasterTag_1 = __webpack_require__(/*! ./models/tags/EbmlMasterTag */ "./node_modules/ebml-stream/lib/models/tags/EbmlMasterTag.js");
|
|
exports.EbmlMasterTag = EbmlMasterTag_1.EbmlMasterTag;
|
|
var EbmlTag_1 = __webpack_require__(/*! ./models/EbmlTag */ "./node_modules/ebml-stream/lib/models/EbmlTag.js");
|
|
exports.EbmlTag = EbmlTag_1.EbmlTag;
|
|
var EbmlTagFactory_1 = __webpack_require__(/*! ./models/EbmlTagFactory */ "./node_modules/ebml-stream/lib/models/EbmlTagFactory.js");
|
|
exports.EbmlTagFactory = EbmlTagFactory_1.EbmlTagFactory;
|
|
var EbmlTagId_1 = __webpack_require__(/*! ./models/enums/EbmlTagId */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagId.js");
|
|
exports.EbmlTagId = EbmlTagId_1.EbmlTagId;
|
|
var EbmlTagPosition_1 = __webpack_require__(/*! ./models/enums/EbmlTagPosition */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagPosition.js");
|
|
exports.EbmlTagPosition = EbmlTagPosition_1.EbmlTagPosition;
|
|
var SimpleBlock_1 = __webpack_require__(/*! ./models/tags/SimpleBlock */ "./node_modules/ebml-stream/lib/models/tags/SimpleBlock.js");
|
|
exports.SimpleBlock = SimpleBlock_1.SimpleBlock;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/models/EbmlTag.js":
|
|
/*!********************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/models/EbmlTag.js ***!
|
|
\********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
const EbmlTagId_1 = __webpack_require__(/*! ./enums/EbmlTagId */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagId.js");
|
|
const tools_1 = __webpack_require__(/*! ../tools */ "./node_modules/ebml-stream/lib/tools.js");
|
|
class EbmlTag {
|
|
constructor(id, type, position) {
|
|
this.id = id;
|
|
this.type = type;
|
|
this.position = position;
|
|
}
|
|
getTagDeclaration() {
|
|
let tagHex = this.id.toString(16);
|
|
if (tagHex.length % 2 !== 0) {
|
|
tagHex = `0${tagHex}`;
|
|
}
|
|
return Buffer.from(tagHex, 'hex');
|
|
}
|
|
encode() {
|
|
let vintSize = null;
|
|
let content = this.encodeContent();
|
|
if (this.size === -1) {
|
|
vintSize = Buffer.from('01ffffffffffffff', 'hex');
|
|
}
|
|
else {
|
|
let specialLength = undefined;
|
|
if ([
|
|
EbmlTagId_1.EbmlTagId.Segment,
|
|
EbmlTagId_1.EbmlTagId.Cluster
|
|
].some(i => i === this.id)) {
|
|
specialLength = 8;
|
|
}
|
|
vintSize = tools_1.Tools.writeVint(content.length, specialLength);
|
|
}
|
|
return Buffer.concat([
|
|
this.getTagDeclaration(),
|
|
vintSize,
|
|
content
|
|
]);
|
|
}
|
|
}
|
|
exports.EbmlTag = EbmlTag;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/models/EbmlTagFactory.js":
|
|
/*!***************************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/models/EbmlTagFactory.js ***!
|
|
\***************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
const EbmlTagId_1 = __webpack_require__(/*! ./enums/EbmlTagId */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagId.js");
|
|
const EbmlMasterTag_1 = __webpack_require__(/*! ./tags/EbmlMasterTag */ "./node_modules/ebml-stream/lib/models/tags/EbmlMasterTag.js");
|
|
const EbmlDataTag_1 = __webpack_require__(/*! ./tags/EbmlDataTag */ "./node_modules/ebml-stream/lib/models/tags/EbmlDataTag.js");
|
|
const Block_1 = __webpack_require__(/*! ./tags/Block */ "./node_modules/ebml-stream/lib/models/tags/Block.js");
|
|
const SimpleBlock_1 = __webpack_require__(/*! ./tags/SimpleBlock */ "./node_modules/ebml-stream/lib/models/tags/SimpleBlock.js");
|
|
const EbmlElementType_1 = __webpack_require__(/*! ./enums/EbmlElementType */ "./node_modules/ebml-stream/lib/models/enums/EbmlElementType.js");
|
|
class EbmlTagFactory {
|
|
static create(id, type) {
|
|
if (EbmlTagId_1.EbmlTagId[id] !== undefined) {
|
|
let foundType;
|
|
switch (id) {
|
|
case EbmlTagId_1.EbmlTagId.Block:
|
|
return new Block_1.Block();
|
|
case EbmlTagId_1.EbmlTagId.SimpleBlock:
|
|
return new SimpleBlock_1.SimpleBlock();
|
|
case EbmlTagId_1.EbmlTagId.ChapterDisplay:
|
|
case EbmlTagId_1.EbmlTagId.ContentCompression:
|
|
case EbmlTagId_1.EbmlTagId.ContentEncryption:
|
|
case EbmlTagId_1.EbmlTagId.SilentTracks:
|
|
case EbmlTagId_1.EbmlTagId.ContentEncoding:
|
|
case EbmlTagId_1.EbmlTagId.TrackTranslate:
|
|
case EbmlTagId_1.EbmlTagId.ChapProcessCommand:
|
|
case EbmlTagId_1.EbmlTagId.ChapterTranslate:
|
|
case EbmlTagId_1.EbmlTagId.ChapProcess:
|
|
case EbmlTagId_1.EbmlTagId.Tag:
|
|
case EbmlTagId_1.EbmlTagId.Segment:
|
|
case EbmlTagId_1.EbmlTagId.SimpleTag:
|
|
case EbmlTagId_1.EbmlTagId.Targets:
|
|
case EbmlTagId_1.EbmlTagId.Tags:
|
|
case EbmlTagId_1.EbmlTagId.ChapterTrack:
|
|
case EbmlTagId_1.EbmlTagId.ChapterAtom:
|
|
case EbmlTagId_1.EbmlTagId.EditionEntry:
|
|
case EbmlTagId_1.EbmlTagId.Chapters:
|
|
case EbmlTagId_1.EbmlTagId.AttachedFile:
|
|
case EbmlTagId_1.EbmlTagId.Attachments:
|
|
case EbmlTagId_1.EbmlTagId.CueReference:
|
|
case EbmlTagId_1.EbmlTagId.CueTrackPositions:
|
|
case EbmlTagId_1.EbmlTagId.CuePoint:
|
|
case EbmlTagId_1.EbmlTagId.Cues:
|
|
case EbmlTagId_1.EbmlTagId.ContentEncAESSettings:
|
|
case EbmlTagId_1.EbmlTagId.ContentEncodings:
|
|
case EbmlTagId_1.EbmlTagId.TrackJoinBlocks:
|
|
case EbmlTagId_1.EbmlTagId.TrackPlane:
|
|
case EbmlTagId_1.EbmlTagId.TrackCombinePlanes:
|
|
case EbmlTagId_1.EbmlTagId.TrackOperation:
|
|
case EbmlTagId_1.EbmlTagId.Audio:
|
|
case EbmlTagId_1.EbmlTagId.Video:
|
|
case EbmlTagId_1.EbmlTagId.TrackEntry:
|
|
case EbmlTagId_1.EbmlTagId.Tracks:
|
|
case EbmlTagId_1.EbmlTagId.ReferenceFrame:
|
|
case EbmlTagId_1.EbmlTagId.TimeSlice:
|
|
case EbmlTagId_1.EbmlTagId.Slices:
|
|
case EbmlTagId_1.EbmlTagId.BlockMore:
|
|
case EbmlTagId_1.EbmlTagId.BlockAdditions:
|
|
case EbmlTagId_1.EbmlTagId.BlockGroup:
|
|
case EbmlTagId_1.EbmlTagId.Cluster:
|
|
case EbmlTagId_1.EbmlTagId.Info:
|
|
case EbmlTagId_1.EbmlTagId.Seek:
|
|
case EbmlTagId_1.EbmlTagId.SeekHead:
|
|
case EbmlTagId_1.EbmlTagId.SignatureElementList:
|
|
case EbmlTagId_1.EbmlTagId.SignatureElements:
|
|
case EbmlTagId_1.EbmlTagId.SignatureSlot:
|
|
case EbmlTagId_1.EbmlTagId.EBML:
|
|
foundType = EbmlElementType_1.EbmlElementType.Master;
|
|
break;
|
|
case EbmlTagId_1.EbmlTagId.TrackType:
|
|
case EbmlTagId_1.EbmlTagId.FlagDefault:
|
|
case EbmlTagId_1.EbmlTagId.ChapterTrackNumber:
|
|
case EbmlTagId_1.EbmlTagId.ChapterTimeStart:
|
|
case EbmlTagId_1.EbmlTagId.ChapterTimeEnd:
|
|
case EbmlTagId_1.EbmlTagId.CueRefTime:
|
|
case EbmlTagId_1.EbmlTagId.CueRefCluster:
|
|
case EbmlTagId_1.EbmlTagId.ChapterFlagHidden:
|
|
case EbmlTagId_1.EbmlTagId.ContentCompAlgo:
|
|
case EbmlTagId_1.EbmlTagId.DocTypeReadVersion:
|
|
case EbmlTagId_1.EbmlTagId.EBMLVersion:
|
|
case EbmlTagId_1.EbmlTagId.DocTypeVersion:
|
|
case EbmlTagId_1.EbmlTagId.TagDefault:
|
|
case EbmlTagId_1.EbmlTagId.ChapterFlagEnabled:
|
|
case EbmlTagId_1.EbmlTagId.FileUsedStartTime:
|
|
case EbmlTagId_1.EbmlTagId.FileUsedEndTime:
|
|
case EbmlTagId_1.EbmlTagId.ContentEncodingOrder:
|
|
case EbmlTagId_1.EbmlTagId.ContentEncodingScope:
|
|
case EbmlTagId_1.EbmlTagId.ContentEncodingType:
|
|
case EbmlTagId_1.EbmlTagId.CueBlockNumber:
|
|
case EbmlTagId_1.EbmlTagId.BitDepth:
|
|
case EbmlTagId_1.EbmlTagId.ChapProcessTime:
|
|
case EbmlTagId_1.EbmlTagId.ChapProcessCodecID:
|
|
case EbmlTagId_1.EbmlTagId.AttachmentLink:
|
|
case EbmlTagId_1.EbmlTagId.TagAttachmentUID:
|
|
case EbmlTagId_1.EbmlTagId.TagChapterUID:
|
|
case EbmlTagId_1.EbmlTagId.TagEditionUID:
|
|
case EbmlTagId_1.EbmlTagId.TagTrackUID:
|
|
case EbmlTagId_1.EbmlTagId.TargetTypeValue:
|
|
case EbmlTagId_1.EbmlTagId.ChapterPhysicalEquiv:
|
|
case EbmlTagId_1.EbmlTagId.ChapterSegmentEditionUID:
|
|
case EbmlTagId_1.EbmlTagId.ChapterUID:
|
|
case EbmlTagId_1.EbmlTagId.EditionFlagOrdered:
|
|
case EbmlTagId_1.EbmlTagId.EditionFlagDefault:
|
|
case EbmlTagId_1.EbmlTagId.EditionFlagHidden:
|
|
case EbmlTagId_1.EbmlTagId.EditionUID:
|
|
case EbmlTagId_1.EbmlTagId.FileUID:
|
|
case EbmlTagId_1.EbmlTagId.CueRefCodecState:
|
|
case EbmlTagId_1.EbmlTagId.CueRefNumber:
|
|
case EbmlTagId_1.EbmlTagId.CueCodecState:
|
|
case EbmlTagId_1.EbmlTagId.CueDuration:
|
|
case EbmlTagId_1.EbmlTagId.CueRelativePosition:
|
|
case EbmlTagId_1.EbmlTagId.CueClusterPosition:
|
|
case EbmlTagId_1.EbmlTagId.CueTrack:
|
|
case EbmlTagId_1.EbmlTagId.CueTime:
|
|
case EbmlTagId_1.EbmlTagId.AESSettingsCipherMode:
|
|
case EbmlTagId_1.EbmlTagId.ContentSigHashAlgo:
|
|
case EbmlTagId_1.EbmlTagId.ContentSigAlgo:
|
|
case EbmlTagId_1.EbmlTagId.ContentEncAlgo:
|
|
case EbmlTagId_1.EbmlTagId.TrickMasterTrackUID:
|
|
case EbmlTagId_1.EbmlTagId.TrickTrackFlag:
|
|
case EbmlTagId_1.EbmlTagId.TrickTrackUID:
|
|
case EbmlTagId_1.EbmlTagId.TrackJoinUID:
|
|
case EbmlTagId_1.EbmlTagId.TrackPlaneType:
|
|
case EbmlTagId_1.EbmlTagId.TrackPlaneUID:
|
|
case EbmlTagId_1.EbmlTagId.Channels:
|
|
case EbmlTagId_1.EbmlTagId.AspectRatioType:
|
|
case EbmlTagId_1.EbmlTagId.DisplayUnit:
|
|
case EbmlTagId_1.EbmlTagId.DisplayHeight:
|
|
case EbmlTagId_1.EbmlTagId.DisplayWidth:
|
|
case EbmlTagId_1.EbmlTagId.PixelCropRight:
|
|
case EbmlTagId_1.EbmlTagId.PixelCropLeft:
|
|
case EbmlTagId_1.EbmlTagId.PixelCropTop:
|
|
case EbmlTagId_1.EbmlTagId.PixelCropBottom:
|
|
case EbmlTagId_1.EbmlTagId.PixelHeight:
|
|
case EbmlTagId_1.EbmlTagId.PixelWidth:
|
|
case EbmlTagId_1.EbmlTagId.OldStereoMode:
|
|
case EbmlTagId_1.EbmlTagId.AlphaMode:
|
|
case EbmlTagId_1.EbmlTagId.StereoMode:
|
|
case EbmlTagId_1.EbmlTagId.FlagInterlaced:
|
|
case EbmlTagId_1.EbmlTagId.TrackTranslateCodec:
|
|
case EbmlTagId_1.EbmlTagId.TrackTranslateEditionUID:
|
|
case EbmlTagId_1.EbmlTagId.SeekPreRoll:
|
|
case EbmlTagId_1.EbmlTagId.CodecDelay:
|
|
case EbmlTagId_1.EbmlTagId.TrackOverlay:
|
|
case EbmlTagId_1.EbmlTagId.CodecDecodeAll:
|
|
case EbmlTagId_1.EbmlTagId.MaxBlockAdditionID:
|
|
case EbmlTagId_1.EbmlTagId.DefaultDecodedFieldDuration:
|
|
case EbmlTagId_1.EbmlTagId.DefaultDuration:
|
|
case EbmlTagId_1.EbmlTagId.MaxCache:
|
|
case EbmlTagId_1.EbmlTagId.MinCache:
|
|
case EbmlTagId_1.EbmlTagId.FlagLacing:
|
|
case EbmlTagId_1.EbmlTagId.FlagForced:
|
|
case EbmlTagId_1.EbmlTagId.FlagEnabled:
|
|
case EbmlTagId_1.EbmlTagId.TrackUID:
|
|
case EbmlTagId_1.EbmlTagId.TrackNumber:
|
|
case EbmlTagId_1.EbmlTagId.ReferenceTimeCode:
|
|
case EbmlTagId_1.EbmlTagId.ReferenceOffset:
|
|
case EbmlTagId_1.EbmlTagId.SliceDuration:
|
|
case EbmlTagId_1.EbmlTagId.Delay:
|
|
case EbmlTagId_1.EbmlTagId.BlockAdditionID:
|
|
case EbmlTagId_1.EbmlTagId.FrameNumber:
|
|
case EbmlTagId_1.EbmlTagId.LaceNumber:
|
|
case EbmlTagId_1.EbmlTagId.ReferencePriority:
|
|
case EbmlTagId_1.EbmlTagId.BlockDuration:
|
|
case EbmlTagId_1.EbmlTagId.BlockAddID:
|
|
case EbmlTagId_1.EbmlTagId.PrevSize:
|
|
case EbmlTagId_1.EbmlTagId.Position:
|
|
case EbmlTagId_1.EbmlTagId.SilentTrackNumber:
|
|
case EbmlTagId_1.EbmlTagId.Timecode:
|
|
case EbmlTagId_1.EbmlTagId.TimecodeScaleDenominator:
|
|
case EbmlTagId_1.EbmlTagId.TimecodeScale:
|
|
case EbmlTagId_1.EbmlTagId.ChapterTranslateCodec:
|
|
case EbmlTagId_1.EbmlTagId.ChapterTranslateEditionUID:
|
|
case EbmlTagId_1.EbmlTagId.SeekPosition:
|
|
case EbmlTagId_1.EbmlTagId.SignatureHash:
|
|
case EbmlTagId_1.EbmlTagId.SignatureAlgo:
|
|
case EbmlTagId_1.EbmlTagId.EBMLMaxSizeLength:
|
|
case EbmlTagId_1.EbmlTagId.EBMLMaxIDLength:
|
|
case EbmlTagId_1.EbmlTagId.EBMLReadVersion:
|
|
foundType = EbmlElementType_1.EbmlElementType.UnsignedInt;
|
|
break;
|
|
case EbmlTagId_1.EbmlTagId.TrackOffset:
|
|
case EbmlTagId_1.EbmlTagId.DiscardPadding:
|
|
case EbmlTagId_1.EbmlTagId.ReferenceVirtual:
|
|
case EbmlTagId_1.EbmlTagId.ReferenceBlock:
|
|
foundType = EbmlElementType_1.EbmlElementType.Integer;
|
|
break;
|
|
case EbmlTagId_1.EbmlTagId.CodecID:
|
|
case EbmlTagId_1.EbmlTagId.DocType:
|
|
case EbmlTagId_1.EbmlTagId.FileMimeType:
|
|
case EbmlTagId_1.EbmlTagId.TagLanguage:
|
|
case EbmlTagId_1.EbmlTagId.TargetType:
|
|
case EbmlTagId_1.EbmlTagId.ChapCountry:
|
|
case EbmlTagId_1.EbmlTagId.ChapLanguage:
|
|
case EbmlTagId_1.EbmlTagId.CodecDownloadURL:
|
|
case EbmlTagId_1.EbmlTagId.CodecInfoURL:
|
|
case EbmlTagId_1.EbmlTagId.Language:
|
|
foundType = EbmlElementType_1.EbmlElementType.String;
|
|
break;
|
|
case EbmlTagId_1.EbmlTagId.ChapString:
|
|
case EbmlTagId_1.EbmlTagId.TagString:
|
|
case EbmlTagId_1.EbmlTagId.ChapterStringUID:
|
|
case EbmlTagId_1.EbmlTagId.WritingApp:
|
|
case EbmlTagId_1.EbmlTagId.SegmentFilename:
|
|
case EbmlTagId_1.EbmlTagId.CodecName:
|
|
case EbmlTagId_1.EbmlTagId.TagName:
|
|
case EbmlTagId_1.EbmlTagId.FileName:
|
|
case EbmlTagId_1.EbmlTagId.FileDescription:
|
|
case EbmlTagId_1.EbmlTagId.CodecSettings:
|
|
case EbmlTagId_1.EbmlTagId.Name:
|
|
case EbmlTagId_1.EbmlTagId.MuxingApp:
|
|
case EbmlTagId_1.EbmlTagId.Title:
|
|
case EbmlTagId_1.EbmlTagId.NextFilename:
|
|
case EbmlTagId_1.EbmlTagId.PrevFilename:
|
|
foundType = EbmlElementType_1.EbmlElementType.UTF8;
|
|
break;
|
|
case EbmlTagId_1.EbmlTagId.ContentCompSettings:
|
|
case EbmlTagId_1.EbmlTagId.SegmentFamily:
|
|
case EbmlTagId_1.EbmlTagId.TagBinary:
|
|
case EbmlTagId_1.EbmlTagId.FileReferral:
|
|
case EbmlTagId_1.EbmlTagId.SignedElement:
|
|
case EbmlTagId_1.EbmlTagId.ChapProcessData:
|
|
case EbmlTagId_1.EbmlTagId.ChapProcessPrivate:
|
|
case EbmlTagId_1.EbmlTagId.ChapterSegmentUID:
|
|
case EbmlTagId_1.EbmlTagId.FileData:
|
|
case EbmlTagId_1.EbmlTagId.ContentSigKeyID:
|
|
case EbmlTagId_1.EbmlTagId.ContentSignature:
|
|
case EbmlTagId_1.EbmlTagId.ContentEncKeyID:
|
|
case EbmlTagId_1.EbmlTagId.TrickMasterTrackSegmentUID:
|
|
case EbmlTagId_1.EbmlTagId.TrickTrackSegmentUID:
|
|
case EbmlTagId_1.EbmlTagId.ChannelPositions:
|
|
case EbmlTagId_1.EbmlTagId.ColourSpace:
|
|
case EbmlTagId_1.EbmlTagId.TrackTranslateTrackID:
|
|
case EbmlTagId_1.EbmlTagId.CodecPrivate:
|
|
case EbmlTagId_1.EbmlTagId.EncryptedBlock:
|
|
case EbmlTagId_1.EbmlTagId.CodecState:
|
|
case EbmlTagId_1.EbmlTagId.BlockAdditional:
|
|
case EbmlTagId_1.EbmlTagId.BlockVirtual:
|
|
case EbmlTagId_1.EbmlTagId.ChapterTranslateID:
|
|
case EbmlTagId_1.EbmlTagId.NextUID:
|
|
case EbmlTagId_1.EbmlTagId.PrevUID:
|
|
case EbmlTagId_1.EbmlTagId.SegmentUID:
|
|
case EbmlTagId_1.EbmlTagId.SeekID:
|
|
case EbmlTagId_1.EbmlTagId.Signature:
|
|
case EbmlTagId_1.EbmlTagId.SignaturePublicKey:
|
|
case EbmlTagId_1.EbmlTagId.CRC32:
|
|
case EbmlTagId_1.EbmlTagId.Void:
|
|
foundType = EbmlElementType_1.EbmlElementType.Binary;
|
|
break;
|
|
case EbmlTagId_1.EbmlTagId.Duration:
|
|
case EbmlTagId_1.EbmlTagId.OutputSamplingFrequency:
|
|
case EbmlTagId_1.EbmlTagId.SamplingFrequency:
|
|
case EbmlTagId_1.EbmlTagId.FrameRate:
|
|
case EbmlTagId_1.EbmlTagId.GammaValue:
|
|
case EbmlTagId_1.EbmlTagId.TrackTimecodeScale:
|
|
foundType = EbmlElementType_1.EbmlElementType.Float;
|
|
break;
|
|
case EbmlTagId_1.EbmlTagId.DateUTC:
|
|
foundType = EbmlElementType_1.EbmlElementType.Date;
|
|
break;
|
|
}
|
|
if (type === undefined) {
|
|
type = foundType;
|
|
}
|
|
else {
|
|
if (type !== foundType) {
|
|
throw new Error(`Trying to create tag of well-known type "${EbmlTagId_1.EbmlTagId[id]}" using content type "${type}" (which is incorrect). Either pass the correct type or ignore the type parameter to EbmlTag.create()`);
|
|
}
|
|
}
|
|
}
|
|
switch (type) {
|
|
case EbmlElementType_1.EbmlElementType.Master:
|
|
return new EbmlMasterTag_1.EbmlMasterTag(id);
|
|
case EbmlElementType_1.EbmlElementType.UTF8:
|
|
case EbmlElementType_1.EbmlElementType.Binary:
|
|
case EbmlElementType_1.EbmlElementType.Date:
|
|
case EbmlElementType_1.EbmlElementType.Float:
|
|
case EbmlElementType_1.EbmlElementType.Integer:
|
|
case EbmlElementType_1.EbmlElementType.String:
|
|
case EbmlElementType_1.EbmlElementType.UnsignedInt:
|
|
default:
|
|
return new EbmlDataTag_1.EbmlDataTag(id, type);
|
|
}
|
|
}
|
|
}
|
|
exports.EbmlTagFactory = EbmlTagFactory;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/models/enums/BlockLacing.js":
|
|
/*!******************************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/models/enums/BlockLacing.js ***!
|
|
\******************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
var BlockLacing;
|
|
(function (BlockLacing) {
|
|
BlockLacing[BlockLacing["None"] = 0] = "None";
|
|
BlockLacing[BlockLacing["Xiph"] = 1] = "Xiph";
|
|
BlockLacing[BlockLacing["EBML"] = 2] = "EBML";
|
|
BlockLacing[BlockLacing["FixedSize"] = 3] = "FixedSize";
|
|
})(BlockLacing = exports.BlockLacing || (exports.BlockLacing = {}));
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/models/enums/EbmlElementType.js":
|
|
/*!**********************************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/models/enums/EbmlElementType.js ***!
|
|
\**********************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
var EbmlElementType;
|
|
(function (EbmlElementType) {
|
|
EbmlElementType["Master"] = "m";
|
|
EbmlElementType["UnsignedInt"] = "u";
|
|
EbmlElementType["Integer"] = "i";
|
|
EbmlElementType["String"] = "s";
|
|
EbmlElementType["UTF8"] = "8";
|
|
EbmlElementType["Binary"] = "b";
|
|
EbmlElementType["Float"] = "f";
|
|
EbmlElementType["Date"] = "d";
|
|
})(EbmlElementType = exports.EbmlElementType || (exports.EbmlElementType = {}));
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/models/enums/EbmlTagId.js":
|
|
/*!****************************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/models/enums/EbmlTagId.js ***!
|
|
\****************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
var EbmlTagId;
|
|
(function (EbmlTagId) {
|
|
EbmlTagId[EbmlTagId["ChapterDisplay"] = 128] = "ChapterDisplay";
|
|
EbmlTagId[EbmlTagId["TrackType"] = 131] = "TrackType";
|
|
EbmlTagId[EbmlTagId["ChapString"] = 133] = "ChapString";
|
|
EbmlTagId[EbmlTagId["CodecID"] = 134] = "CodecID";
|
|
EbmlTagId[EbmlTagId["FlagDefault"] = 136] = "FlagDefault";
|
|
EbmlTagId[EbmlTagId["ChapterTrackNumber"] = 137] = "ChapterTrackNumber";
|
|
EbmlTagId[EbmlTagId["ChapterTimeStart"] = 145] = "ChapterTimeStart";
|
|
EbmlTagId[EbmlTagId["ChapterTimeEnd"] = 146] = "ChapterTimeEnd";
|
|
EbmlTagId[EbmlTagId["CueRefTime"] = 150] = "CueRefTime";
|
|
EbmlTagId[EbmlTagId["CueRefCluster"] = 151] = "CueRefCluster";
|
|
EbmlTagId[EbmlTagId["ChapterFlagHidden"] = 152] = "ChapterFlagHidden";
|
|
EbmlTagId[EbmlTagId["ContentCompAlgo"] = 16980] = "ContentCompAlgo";
|
|
EbmlTagId[EbmlTagId["ContentCompSettings"] = 16981] = "ContentCompSettings";
|
|
EbmlTagId[EbmlTagId["DocType"] = 17026] = "DocType";
|
|
EbmlTagId[EbmlTagId["DocTypeReadVersion"] = 17029] = "DocTypeReadVersion";
|
|
EbmlTagId[EbmlTagId["EBMLVersion"] = 17030] = "EBMLVersion";
|
|
EbmlTagId[EbmlTagId["DocTypeVersion"] = 17031] = "DocTypeVersion";
|
|
EbmlTagId[EbmlTagId["SegmentFamily"] = 17476] = "SegmentFamily";
|
|
EbmlTagId[EbmlTagId["DateUTC"] = 17505] = "DateUTC";
|
|
EbmlTagId[EbmlTagId["TagDefault"] = 17540] = "TagDefault";
|
|
EbmlTagId[EbmlTagId["TagBinary"] = 17541] = "TagBinary";
|
|
EbmlTagId[EbmlTagId["TagString"] = 17543] = "TagString";
|
|
EbmlTagId[EbmlTagId["Duration"] = 17545] = "Duration";
|
|
EbmlTagId[EbmlTagId["ChapterFlagEnabled"] = 17816] = "ChapterFlagEnabled";
|
|
EbmlTagId[EbmlTagId["FileMimeType"] = 18016] = "FileMimeType";
|
|
EbmlTagId[EbmlTagId["FileUsedStartTime"] = 18017] = "FileUsedStartTime";
|
|
EbmlTagId[EbmlTagId["FileUsedEndTime"] = 18018] = "FileUsedEndTime";
|
|
EbmlTagId[EbmlTagId["FileReferral"] = 18037] = "FileReferral";
|
|
EbmlTagId[EbmlTagId["ContentEncodingOrder"] = 20529] = "ContentEncodingOrder";
|
|
EbmlTagId[EbmlTagId["ContentEncodingScope"] = 20530] = "ContentEncodingScope";
|
|
EbmlTagId[EbmlTagId["ContentEncodingType"] = 20531] = "ContentEncodingType";
|
|
EbmlTagId[EbmlTagId["ContentCompression"] = 20532] = "ContentCompression";
|
|
EbmlTagId[EbmlTagId["ContentEncryption"] = 20533] = "ContentEncryption";
|
|
EbmlTagId[EbmlTagId["CueBlockNumber"] = 21368] = "CueBlockNumber";
|
|
EbmlTagId[EbmlTagId["ChapterStringUID"] = 22100] = "ChapterStringUID";
|
|
EbmlTagId[EbmlTagId["WritingApp"] = 22337] = "WritingApp";
|
|
EbmlTagId[EbmlTagId["SilentTracks"] = 22612] = "SilentTracks";
|
|
EbmlTagId[EbmlTagId["ContentEncoding"] = 25152] = "ContentEncoding";
|
|
EbmlTagId[EbmlTagId["BitDepth"] = 25188] = "BitDepth";
|
|
EbmlTagId[EbmlTagId["SignedElement"] = 25906] = "SignedElement";
|
|
EbmlTagId[EbmlTagId["TrackTranslate"] = 26148] = "TrackTranslate";
|
|
EbmlTagId[EbmlTagId["ChapProcessCommand"] = 26897] = "ChapProcessCommand";
|
|
EbmlTagId[EbmlTagId["ChapProcessTime"] = 26914] = "ChapProcessTime";
|
|
EbmlTagId[EbmlTagId["ChapterTranslate"] = 26916] = "ChapterTranslate";
|
|
EbmlTagId[EbmlTagId["ChapProcessData"] = 26931] = "ChapProcessData";
|
|
EbmlTagId[EbmlTagId["ChapProcess"] = 26948] = "ChapProcess";
|
|
EbmlTagId[EbmlTagId["ChapProcessCodecID"] = 26965] = "ChapProcessCodecID";
|
|
EbmlTagId[EbmlTagId["Tag"] = 29555] = "Tag";
|
|
EbmlTagId[EbmlTagId["SegmentFilename"] = 29572] = "SegmentFilename";
|
|
EbmlTagId[EbmlTagId["AttachmentLink"] = 29766] = "AttachmentLink";
|
|
EbmlTagId[EbmlTagId["CodecName"] = 2459272] = "CodecName";
|
|
EbmlTagId[EbmlTagId["Segment"] = 408125543] = "Segment";
|
|
EbmlTagId[EbmlTagId["TagLanguage"] = 17530] = "TagLanguage";
|
|
EbmlTagId[EbmlTagId["TagName"] = 17827] = "TagName";
|
|
EbmlTagId[EbmlTagId["SimpleTag"] = 26568] = "SimpleTag";
|
|
EbmlTagId[EbmlTagId["TagAttachmentUID"] = 25542] = "TagAttachmentUID";
|
|
EbmlTagId[EbmlTagId["TagChapterUID"] = 25540] = "TagChapterUID";
|
|
EbmlTagId[EbmlTagId["TagEditionUID"] = 25545] = "TagEditionUID";
|
|
EbmlTagId[EbmlTagId["TagTrackUID"] = 25541] = "TagTrackUID";
|
|
EbmlTagId[EbmlTagId["TargetType"] = 25546] = "TargetType";
|
|
EbmlTagId[EbmlTagId["TargetTypeValue"] = 26826] = "TargetTypeValue";
|
|
EbmlTagId[EbmlTagId["Targets"] = 25536] = "Targets";
|
|
EbmlTagId[EbmlTagId["Tags"] = 307544935] = "Tags";
|
|
EbmlTagId[EbmlTagId["ChapProcessPrivate"] = 17677] = "ChapProcessPrivate";
|
|
EbmlTagId[EbmlTagId["ChapCountry"] = 17278] = "ChapCountry";
|
|
EbmlTagId[EbmlTagId["ChapLanguage"] = 17276] = "ChapLanguage";
|
|
EbmlTagId[EbmlTagId["ChapterTrack"] = 143] = "ChapterTrack";
|
|
EbmlTagId[EbmlTagId["ChapterPhysicalEquiv"] = 25539] = "ChapterPhysicalEquiv";
|
|
EbmlTagId[EbmlTagId["ChapterSegmentEditionUID"] = 28348] = "ChapterSegmentEditionUID";
|
|
EbmlTagId[EbmlTagId["ChapterSegmentUID"] = 28263] = "ChapterSegmentUID";
|
|
EbmlTagId[EbmlTagId["ChapterUID"] = 29636] = "ChapterUID";
|
|
EbmlTagId[EbmlTagId["ChapterAtom"] = 182] = "ChapterAtom";
|
|
EbmlTagId[EbmlTagId["EditionFlagOrdered"] = 17885] = "EditionFlagOrdered";
|
|
EbmlTagId[EbmlTagId["EditionFlagDefault"] = 17883] = "EditionFlagDefault";
|
|
EbmlTagId[EbmlTagId["EditionFlagHidden"] = 17853] = "EditionFlagHidden";
|
|
EbmlTagId[EbmlTagId["EditionUID"] = 17852] = "EditionUID";
|
|
EbmlTagId[EbmlTagId["EditionEntry"] = 17849] = "EditionEntry";
|
|
EbmlTagId[EbmlTagId["Chapters"] = 272869232] = "Chapters";
|
|
EbmlTagId[EbmlTagId["FileUID"] = 18094] = "FileUID";
|
|
EbmlTagId[EbmlTagId["FileData"] = 18012] = "FileData";
|
|
EbmlTagId[EbmlTagId["FileName"] = 18030] = "FileName";
|
|
EbmlTagId[EbmlTagId["FileDescription"] = 18046] = "FileDescription";
|
|
EbmlTagId[EbmlTagId["AttachedFile"] = 24999] = "AttachedFile";
|
|
EbmlTagId[EbmlTagId["Attachments"] = 423732329] = "Attachments";
|
|
EbmlTagId[EbmlTagId["CueRefCodecState"] = 235] = "CueRefCodecState";
|
|
EbmlTagId[EbmlTagId["CueRefNumber"] = 21343] = "CueRefNumber";
|
|
EbmlTagId[EbmlTagId["CueReference"] = 219] = "CueReference";
|
|
EbmlTagId[EbmlTagId["CueCodecState"] = 234] = "CueCodecState";
|
|
EbmlTagId[EbmlTagId["CueDuration"] = 178] = "CueDuration";
|
|
EbmlTagId[EbmlTagId["CueRelativePosition"] = 240] = "CueRelativePosition";
|
|
EbmlTagId[EbmlTagId["CueClusterPosition"] = 241] = "CueClusterPosition";
|
|
EbmlTagId[EbmlTagId["CueTrack"] = 247] = "CueTrack";
|
|
EbmlTagId[EbmlTagId["CueTrackPositions"] = 183] = "CueTrackPositions";
|
|
EbmlTagId[EbmlTagId["CueTime"] = 179] = "CueTime";
|
|
EbmlTagId[EbmlTagId["CuePoint"] = 187] = "CuePoint";
|
|
EbmlTagId[EbmlTagId["Cues"] = 475249515] = "Cues";
|
|
EbmlTagId[EbmlTagId["AESSettingsCipherMode"] = 18408] = "AESSettingsCipherMode";
|
|
EbmlTagId[EbmlTagId["ContentEncAESSettings"] = 18407] = "ContentEncAESSettings";
|
|
EbmlTagId[EbmlTagId["ContentSigHashAlgo"] = 18406] = "ContentSigHashAlgo";
|
|
EbmlTagId[EbmlTagId["ContentSigAlgo"] = 18405] = "ContentSigAlgo";
|
|
EbmlTagId[EbmlTagId["ContentSigKeyID"] = 18404] = "ContentSigKeyID";
|
|
EbmlTagId[EbmlTagId["ContentSignature"] = 18403] = "ContentSignature";
|
|
EbmlTagId[EbmlTagId["ContentEncKeyID"] = 18402] = "ContentEncKeyID";
|
|
EbmlTagId[EbmlTagId["ContentEncAlgo"] = 18401] = "ContentEncAlgo";
|
|
EbmlTagId[EbmlTagId["ContentEncodings"] = 28032] = "ContentEncodings";
|
|
EbmlTagId[EbmlTagId["TrickMasterTrackSegmentUID"] = 196] = "TrickMasterTrackSegmentUID";
|
|
EbmlTagId[EbmlTagId["TrickMasterTrackUID"] = 199] = "TrickMasterTrackUID";
|
|
EbmlTagId[EbmlTagId["TrickTrackFlag"] = 198] = "TrickTrackFlag";
|
|
EbmlTagId[EbmlTagId["TrickTrackSegmentUID"] = 193] = "TrickTrackSegmentUID";
|
|
EbmlTagId[EbmlTagId["TrickTrackUID"] = 192] = "TrickTrackUID";
|
|
EbmlTagId[EbmlTagId["TrackJoinUID"] = 237] = "TrackJoinUID";
|
|
EbmlTagId[EbmlTagId["TrackJoinBlocks"] = 233] = "TrackJoinBlocks";
|
|
EbmlTagId[EbmlTagId["TrackPlaneType"] = 230] = "TrackPlaneType";
|
|
EbmlTagId[EbmlTagId["TrackPlaneUID"] = 229] = "TrackPlaneUID";
|
|
EbmlTagId[EbmlTagId["TrackPlane"] = 228] = "TrackPlane";
|
|
EbmlTagId[EbmlTagId["TrackCombinePlanes"] = 227] = "TrackCombinePlanes";
|
|
EbmlTagId[EbmlTagId["TrackOperation"] = 226] = "TrackOperation";
|
|
EbmlTagId[EbmlTagId["ChannelPositions"] = 32123] = "ChannelPositions";
|
|
EbmlTagId[EbmlTagId["Channels"] = 159] = "Channels";
|
|
EbmlTagId[EbmlTagId["OutputSamplingFrequency"] = 30901] = "OutputSamplingFrequency";
|
|
EbmlTagId[EbmlTagId["SamplingFrequency"] = 181] = "SamplingFrequency";
|
|
EbmlTagId[EbmlTagId["Audio"] = 225] = "Audio";
|
|
EbmlTagId[EbmlTagId["FrameRate"] = 2327523] = "FrameRate";
|
|
EbmlTagId[EbmlTagId["GammaValue"] = 3126563] = "GammaValue";
|
|
EbmlTagId[EbmlTagId["ColourSpace"] = 3061028] = "ColourSpace";
|
|
EbmlTagId[EbmlTagId["AspectRatioType"] = 21683] = "AspectRatioType";
|
|
EbmlTagId[EbmlTagId["DisplayUnit"] = 21682] = "DisplayUnit";
|
|
EbmlTagId[EbmlTagId["DisplayHeight"] = 21690] = "DisplayHeight";
|
|
EbmlTagId[EbmlTagId["DisplayWidth"] = 21680] = "DisplayWidth";
|
|
EbmlTagId[EbmlTagId["PixelCropRight"] = 21725] = "PixelCropRight";
|
|
EbmlTagId[EbmlTagId["PixelCropLeft"] = 21708] = "PixelCropLeft";
|
|
EbmlTagId[EbmlTagId["PixelCropTop"] = 21691] = "PixelCropTop";
|
|
EbmlTagId[EbmlTagId["PixelCropBottom"] = 21674] = "PixelCropBottom";
|
|
EbmlTagId[EbmlTagId["PixelHeight"] = 186] = "PixelHeight";
|
|
EbmlTagId[EbmlTagId["PixelWidth"] = 176] = "PixelWidth";
|
|
EbmlTagId[EbmlTagId["OldStereoMode"] = 21433] = "OldStereoMode";
|
|
EbmlTagId[EbmlTagId["AlphaMode"] = 21440] = "AlphaMode";
|
|
EbmlTagId[EbmlTagId["StereoMode"] = 21432] = "StereoMode";
|
|
EbmlTagId[EbmlTagId["FlagInterlaced"] = 154] = "FlagInterlaced";
|
|
EbmlTagId[EbmlTagId["Video"] = 224] = "Video";
|
|
EbmlTagId[EbmlTagId["TrackTranslateTrackID"] = 26277] = "TrackTranslateTrackID";
|
|
EbmlTagId[EbmlTagId["TrackTranslateCodec"] = 26303] = "TrackTranslateCodec";
|
|
EbmlTagId[EbmlTagId["TrackTranslateEditionUID"] = 26364] = "TrackTranslateEditionUID";
|
|
EbmlTagId[EbmlTagId["SeekPreRoll"] = 22203] = "SeekPreRoll";
|
|
EbmlTagId[EbmlTagId["CodecDelay"] = 22186] = "CodecDelay";
|
|
EbmlTagId[EbmlTagId["TrackOverlay"] = 28587] = "TrackOverlay";
|
|
EbmlTagId[EbmlTagId["CodecDecodeAll"] = 170] = "CodecDecodeAll";
|
|
EbmlTagId[EbmlTagId["CodecDownloadURL"] = 2536000] = "CodecDownloadURL";
|
|
EbmlTagId[EbmlTagId["CodecInfoURL"] = 3883072] = "CodecInfoURL";
|
|
EbmlTagId[EbmlTagId["CodecSettings"] = 3839639] = "CodecSettings";
|
|
EbmlTagId[EbmlTagId["CodecPrivate"] = 25506] = "CodecPrivate";
|
|
EbmlTagId[EbmlTagId["Language"] = 2274716] = "Language";
|
|
EbmlTagId[EbmlTagId["Name"] = 21358] = "Name";
|
|
EbmlTagId[EbmlTagId["MaxBlockAdditionID"] = 21998] = "MaxBlockAdditionID";
|
|
EbmlTagId[EbmlTagId["TrackOffset"] = 21375] = "TrackOffset";
|
|
EbmlTagId[EbmlTagId["TrackTimecodeScale"] = 2306383] = "TrackTimecodeScale";
|
|
EbmlTagId[EbmlTagId["DefaultDecodedFieldDuration"] = 2313850] = "DefaultDecodedFieldDuration";
|
|
EbmlTagId[EbmlTagId["DefaultDuration"] = 2352003] = "DefaultDuration";
|
|
EbmlTagId[EbmlTagId["MaxCache"] = 28152] = "MaxCache";
|
|
EbmlTagId[EbmlTagId["MinCache"] = 28135] = "MinCache";
|
|
EbmlTagId[EbmlTagId["FlagLacing"] = 156] = "FlagLacing";
|
|
EbmlTagId[EbmlTagId["FlagForced"] = 21930] = "FlagForced";
|
|
EbmlTagId[EbmlTagId["FlagEnabled"] = 185] = "FlagEnabled";
|
|
EbmlTagId[EbmlTagId["TrackUID"] = 29637] = "TrackUID";
|
|
EbmlTagId[EbmlTagId["TrackNumber"] = 215] = "TrackNumber";
|
|
EbmlTagId[EbmlTagId["TrackEntry"] = 174] = "TrackEntry";
|
|
EbmlTagId[EbmlTagId["Tracks"] = 374648427] = "Tracks";
|
|
EbmlTagId[EbmlTagId["EncryptedBlock"] = 175] = "EncryptedBlock";
|
|
EbmlTagId[EbmlTagId["ReferenceTimeCode"] = 202] = "ReferenceTimeCode";
|
|
EbmlTagId[EbmlTagId["ReferenceOffset"] = 201] = "ReferenceOffset";
|
|
EbmlTagId[EbmlTagId["ReferenceFrame"] = 200] = "ReferenceFrame";
|
|
EbmlTagId[EbmlTagId["SliceDuration"] = 207] = "SliceDuration";
|
|
EbmlTagId[EbmlTagId["Delay"] = 206] = "Delay";
|
|
EbmlTagId[EbmlTagId["BlockAdditionID"] = 203] = "BlockAdditionID";
|
|
EbmlTagId[EbmlTagId["FrameNumber"] = 205] = "FrameNumber";
|
|
EbmlTagId[EbmlTagId["LaceNumber"] = 204] = "LaceNumber";
|
|
EbmlTagId[EbmlTagId["TimeSlice"] = 232] = "TimeSlice";
|
|
EbmlTagId[EbmlTagId["Slices"] = 142] = "Slices";
|
|
EbmlTagId[EbmlTagId["DiscardPadding"] = 30114] = "DiscardPadding";
|
|
EbmlTagId[EbmlTagId["CodecState"] = 164] = "CodecState";
|
|
EbmlTagId[EbmlTagId["ReferenceVirtual"] = 253] = "ReferenceVirtual";
|
|
EbmlTagId[EbmlTagId["ReferenceBlock"] = 251] = "ReferenceBlock";
|
|
EbmlTagId[EbmlTagId["ReferencePriority"] = 250] = "ReferencePriority";
|
|
EbmlTagId[EbmlTagId["BlockDuration"] = 155] = "BlockDuration";
|
|
EbmlTagId[EbmlTagId["BlockAdditional"] = 165] = "BlockAdditional";
|
|
EbmlTagId[EbmlTagId["BlockAddID"] = 238] = "BlockAddID";
|
|
EbmlTagId[EbmlTagId["BlockMore"] = 166] = "BlockMore";
|
|
EbmlTagId[EbmlTagId["BlockAdditions"] = 30113] = "BlockAdditions";
|
|
EbmlTagId[EbmlTagId["BlockVirtual"] = 162] = "BlockVirtual";
|
|
EbmlTagId[EbmlTagId["Block"] = 161] = "Block";
|
|
EbmlTagId[EbmlTagId["BlockGroup"] = 160] = "BlockGroup";
|
|
EbmlTagId[EbmlTagId["SimpleBlock"] = 163] = "SimpleBlock";
|
|
EbmlTagId[EbmlTagId["PrevSize"] = 171] = "PrevSize";
|
|
EbmlTagId[EbmlTagId["Position"] = 167] = "Position";
|
|
EbmlTagId[EbmlTagId["SilentTrackNumber"] = 22743] = "SilentTrackNumber";
|
|
EbmlTagId[EbmlTagId["Timecode"] = 231] = "Timecode";
|
|
EbmlTagId[EbmlTagId["Cluster"] = 524531317] = "Cluster";
|
|
EbmlTagId[EbmlTagId["MuxingApp"] = 19840] = "MuxingApp";
|
|
EbmlTagId[EbmlTagId["Title"] = 31657] = "Title";
|
|
EbmlTagId[EbmlTagId["TimecodeScaleDenominator"] = 2807730] = "TimecodeScaleDenominator";
|
|
EbmlTagId[EbmlTagId["TimecodeScale"] = 2807729] = "TimecodeScale";
|
|
EbmlTagId[EbmlTagId["ChapterTranslateID"] = 27045] = "ChapterTranslateID";
|
|
EbmlTagId[EbmlTagId["ChapterTranslateCodec"] = 27071] = "ChapterTranslateCodec";
|
|
EbmlTagId[EbmlTagId["ChapterTranslateEditionUID"] = 27132] = "ChapterTranslateEditionUID";
|
|
EbmlTagId[EbmlTagId["NextFilename"] = 4096955] = "NextFilename";
|
|
EbmlTagId[EbmlTagId["NextUID"] = 4110627] = "NextUID";
|
|
EbmlTagId[EbmlTagId["PrevFilename"] = 3965867] = "PrevFilename";
|
|
EbmlTagId[EbmlTagId["PrevUID"] = 3979555] = "PrevUID";
|
|
EbmlTagId[EbmlTagId["SegmentUID"] = 29604] = "SegmentUID";
|
|
EbmlTagId[EbmlTagId["Info"] = 357149030] = "Info";
|
|
EbmlTagId[EbmlTagId["SeekPosition"] = 21420] = "SeekPosition";
|
|
EbmlTagId[EbmlTagId["SeekID"] = 21419] = "SeekID";
|
|
EbmlTagId[EbmlTagId["Seek"] = 19899] = "Seek";
|
|
EbmlTagId[EbmlTagId["SeekHead"] = 290298740] = "SeekHead";
|
|
EbmlTagId[EbmlTagId["SignatureElementList"] = 32379] = "SignatureElementList";
|
|
EbmlTagId[EbmlTagId["SignatureElements"] = 32347] = "SignatureElements";
|
|
EbmlTagId[EbmlTagId["Signature"] = 32437] = "Signature";
|
|
EbmlTagId[EbmlTagId["SignaturePublicKey"] = 32421] = "SignaturePublicKey";
|
|
EbmlTagId[EbmlTagId["SignatureHash"] = 32410] = "SignatureHash";
|
|
EbmlTagId[EbmlTagId["SignatureAlgo"] = 32394] = "SignatureAlgo";
|
|
EbmlTagId[EbmlTagId["SignatureSlot"] = 458458727] = "SignatureSlot";
|
|
EbmlTagId[EbmlTagId["CRC32"] = 191] = "CRC32";
|
|
EbmlTagId[EbmlTagId["Void"] = 236] = "Void";
|
|
EbmlTagId[EbmlTagId["EBMLMaxSizeLength"] = 17139] = "EBMLMaxSizeLength";
|
|
EbmlTagId[EbmlTagId["EBMLMaxIDLength"] = 17138] = "EBMLMaxIDLength";
|
|
EbmlTagId[EbmlTagId["EBMLReadVersion"] = 17143] = "EBMLReadVersion";
|
|
EbmlTagId[EbmlTagId["EBML"] = 440786851] = "EBML";
|
|
})(EbmlTagId = exports.EbmlTagId || (exports.EbmlTagId = {}));
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/models/enums/EbmlTagPosition.js":
|
|
/*!**********************************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/models/enums/EbmlTagPosition.js ***!
|
|
\**********************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
var EbmlTagPosition;
|
|
(function (EbmlTagPosition) {
|
|
EbmlTagPosition[EbmlTagPosition["Start"] = 0] = "Start";
|
|
EbmlTagPosition[EbmlTagPosition["Content"] = 1] = "Content";
|
|
EbmlTagPosition[EbmlTagPosition["End"] = 2] = "End";
|
|
})(EbmlTagPosition = exports.EbmlTagPosition || (exports.EbmlTagPosition = {}));
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/models/tags/Block.js":
|
|
/*!***********************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/models/tags/Block.js ***!
|
|
\***********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
const EbmlDataTag_1 = __webpack_require__(/*! ./EbmlDataTag */ "./node_modules/ebml-stream/lib/models/tags/EbmlDataTag.js");
|
|
const BlockLacing_1 = __webpack_require__(/*! ../enums/BlockLacing */ "./node_modules/ebml-stream/lib/models/enums/BlockLacing.js");
|
|
const tools_1 = __webpack_require__(/*! ../../tools */ "./node_modules/ebml-stream/lib/tools.js");
|
|
const EbmlTagId_1 = __webpack_require__(/*! ../enums/EbmlTagId */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagId.js");
|
|
const EbmlElementType_1 = __webpack_require__(/*! ../enums/EbmlElementType */ "./node_modules/ebml-stream/lib/models/enums/EbmlElementType.js");
|
|
class Block extends EbmlDataTag_1.EbmlDataTag {
|
|
constructor(subTypeId) {
|
|
super(subTypeId || EbmlTagId_1.EbmlTagId.Block, EbmlElementType_1.EbmlElementType.Binary);
|
|
}
|
|
writeTrackBuffer() {
|
|
return tools_1.Tools.writeVint(this.track);
|
|
}
|
|
writeValueBuffer() {
|
|
let value = Buffer.alloc(2);
|
|
value.writeInt16BE(this.value, 0);
|
|
return value;
|
|
}
|
|
writeFlagsBuffer() {
|
|
let flags = 0x00;
|
|
if (this.invisible) {
|
|
flags |= 0x10;
|
|
}
|
|
switch (this.lacing) {
|
|
case BlockLacing_1.BlockLacing.None:
|
|
break;
|
|
case BlockLacing_1.BlockLacing.Xiph:
|
|
flags |= 0x04;
|
|
break;
|
|
case BlockLacing_1.BlockLacing.EBML:
|
|
flags |= 0x08;
|
|
break;
|
|
case BlockLacing_1.BlockLacing.FixedSize:
|
|
flags |= 0x0c;
|
|
break;
|
|
}
|
|
return Buffer.of(flags);
|
|
}
|
|
encodeContent() {
|
|
return Buffer.concat([
|
|
this.writeTrackBuffer(),
|
|
this.writeValueBuffer(),
|
|
this.writeFlagsBuffer(),
|
|
this.payload
|
|
]);
|
|
}
|
|
parseContent(data) {
|
|
const track = tools_1.Tools.readVint(data);
|
|
this.track = track.value;
|
|
this.value = tools_1.Tools.readSigned(data.subarray(track.length, track.length + 2));
|
|
let flags = data[track.length + 2];
|
|
this.invisible = Boolean(flags & 0x10);
|
|
switch (flags & 0x0c) {
|
|
case 0x00:
|
|
this.lacing = BlockLacing_1.BlockLacing.None;
|
|
break;
|
|
case 0x04:
|
|
this.lacing = BlockLacing_1.BlockLacing.Xiph;
|
|
break;
|
|
case 0x08:
|
|
this.lacing = BlockLacing_1.BlockLacing.EBML;
|
|
break;
|
|
case 0x0c:
|
|
this.lacing = BlockLacing_1.BlockLacing.FixedSize;
|
|
break;
|
|
}
|
|
this.payload = data.slice(track.length + 3);
|
|
}
|
|
}
|
|
exports.Block = Block;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/models/tags/EbmlDataTag.js":
|
|
/*!*****************************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/models/tags/EbmlDataTag.js ***!
|
|
\*****************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
const EbmlTag_1 = __webpack_require__(/*! ../EbmlTag */ "./node_modules/ebml-stream/lib/models/EbmlTag.js");
|
|
const EbmlElementType_1 = __webpack_require__(/*! ../enums/EbmlElementType */ "./node_modules/ebml-stream/lib/models/enums/EbmlElementType.js");
|
|
const tools_1 = __webpack_require__(/*! ../../tools */ "./node_modules/ebml-stream/lib/tools.js");
|
|
const EbmlTagPosition_1 = __webpack_require__(/*! ../enums/EbmlTagPosition */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagPosition.js");
|
|
class EbmlDataTag extends EbmlTag_1.EbmlTag {
|
|
constructor(id, type) {
|
|
super(id, type, EbmlTagPosition_1.EbmlTagPosition.Content);
|
|
}
|
|
parseContent(data) {
|
|
switch (this.type) {
|
|
case EbmlElementType_1.EbmlElementType.UnsignedInt:
|
|
this.data = tools_1.Tools.readUnsigned(data);
|
|
break;
|
|
case EbmlElementType_1.EbmlElementType.Float:
|
|
this.data = tools_1.Tools.readFloat(data);
|
|
break;
|
|
case EbmlElementType_1.EbmlElementType.Integer:
|
|
this.data = tools_1.Tools.readSigned(data);
|
|
break;
|
|
case EbmlElementType_1.EbmlElementType.String:
|
|
this.data = String.fromCharCode(...data);
|
|
break;
|
|
case EbmlElementType_1.EbmlElementType.UTF8:
|
|
this.data = tools_1.Tools.readUtf8(data);
|
|
break;
|
|
default:
|
|
this.data = data;
|
|
break;
|
|
}
|
|
}
|
|
encodeContent() {
|
|
switch (this.type) {
|
|
case EbmlElementType_1.EbmlElementType.UnsignedInt:
|
|
return tools_1.Tools.writeUnsigned(this.data);
|
|
case EbmlElementType_1.EbmlElementType.Float:
|
|
return tools_1.Tools.writeFloat(this.data);
|
|
case EbmlElementType_1.EbmlElementType.Integer:
|
|
return tools_1.Tools.writeSigned(this.data);
|
|
case EbmlElementType_1.EbmlElementType.String:
|
|
return Buffer.from(this.data, "ascii");
|
|
case EbmlElementType_1.EbmlElementType.UTF8:
|
|
return Buffer.from(this.data, "utf8");
|
|
case EbmlElementType_1.EbmlElementType.Binary:
|
|
default:
|
|
return this.data;
|
|
}
|
|
}
|
|
}
|
|
exports.EbmlDataTag = EbmlDataTag;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/models/tags/EbmlMasterTag.js":
|
|
/*!*******************************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/models/tags/EbmlMasterTag.js ***!
|
|
\*******************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
const EbmlTag_1 = __webpack_require__(/*! ../EbmlTag */ "./node_modules/ebml-stream/lib/models/EbmlTag.js");
|
|
const EbmlElementType_1 = __webpack_require__(/*! ../enums/EbmlElementType */ "./node_modules/ebml-stream/lib/models/enums/EbmlElementType.js");
|
|
const EbmlTagPosition_1 = __webpack_require__(/*! ../enums/EbmlTagPosition */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagPosition.js");
|
|
const tools_1 = __webpack_require__(/*! ../../tools */ "./node_modules/ebml-stream/lib/tools.js");
|
|
const EbmlTagFactory_1 = __webpack_require__(/*! ../EbmlTagFactory */ "./node_modules/ebml-stream/lib/models/EbmlTagFactory.js");
|
|
class EbmlMasterTag extends EbmlTag_1.EbmlTag {
|
|
constructor(id, position = EbmlTagPosition_1.EbmlTagPosition.Content) {
|
|
super(id, EbmlElementType_1.EbmlElementType.Master, position);
|
|
this._children = [];
|
|
}
|
|
get Children() {
|
|
return this._children;
|
|
}
|
|
set Children(value) {
|
|
this._children = value;
|
|
}
|
|
encodeContent() {
|
|
return Buffer.concat(this._children.map(child => child.encode()));
|
|
}
|
|
parseContent(content) {
|
|
while (content.length > 0) {
|
|
const tag = tools_1.Tools.readVint(content);
|
|
const size = tools_1.Tools.readVint(content, tag.length);
|
|
const tagIdHex = tools_1.Tools.readHexString(content, 0, tag.length);
|
|
const tagId = Number.parseInt(tagIdHex, 16);
|
|
let tagObject = EbmlTagFactory_1.EbmlTagFactory.create(tagId);
|
|
tagObject.size = size.value;
|
|
let totalTagLength = tag.length + size.length + size.value;
|
|
tagObject.parseContent(content.slice(tag.length + size.length, totalTagLength));
|
|
this._children.push(tagObject);
|
|
content = content.slice(totalTagLength);
|
|
}
|
|
}
|
|
}
|
|
exports.EbmlMasterTag = EbmlMasterTag;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/models/tags/SimpleBlock.js":
|
|
/*!*****************************************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/models/tags/SimpleBlock.js ***!
|
|
\*****************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
const tools_1 = __webpack_require__(/*! ../../tools */ "./node_modules/ebml-stream/lib/tools.js");
|
|
const Block_1 = __webpack_require__(/*! ./Block */ "./node_modules/ebml-stream/lib/models/tags/Block.js");
|
|
const EbmlTagId_1 = __webpack_require__(/*! ../enums/EbmlTagId */ "./node_modules/ebml-stream/lib/models/enums/EbmlTagId.js");
|
|
class SimpleBlock extends Block_1.Block {
|
|
constructor() {
|
|
super(EbmlTagId_1.EbmlTagId.SimpleBlock);
|
|
}
|
|
encodeContent() {
|
|
let flags = this.writeFlagsBuffer();
|
|
if (this.keyframe) {
|
|
flags[0] |= 0x80;
|
|
}
|
|
if (this.discardable) {
|
|
flags[0] |= 0x01;
|
|
}
|
|
return Buffer.concat([
|
|
this.writeTrackBuffer(),
|
|
this.writeValueBuffer(),
|
|
flags,
|
|
this.payload
|
|
]);
|
|
}
|
|
parseContent(data) {
|
|
super.parseContent(data);
|
|
const track = tools_1.Tools.readVint(data);
|
|
let flags = data[track.length + 2];
|
|
this.keyframe = Boolean(flags & 0x80);
|
|
this.discardable = Boolean(flags & 0x01);
|
|
}
|
|
}
|
|
exports.SimpleBlock = SimpleBlock;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ebml-stream/lib/tools.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/ebml-stream/lib/tools.js ***!
|
|
\***********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
class Tools {
|
|
static readVint(buffer, start = 0) {
|
|
const length = 8 - Math.floor(Math.log2(buffer[start]));
|
|
if (length > 8) {
|
|
const number = Tools.readHexString(buffer, start, start + length);
|
|
throw new Error(`Unrepresentable length: ${length} ${number}`);
|
|
}
|
|
if (isNaN(length) || start + length > buffer.length) {
|
|
return null;
|
|
}
|
|
if (length === 8 && buffer[start + 1] >= 0x20 && buffer.subarray(start + 2, start + 8).some(i => i > 0x00)) {
|
|
return {
|
|
length: 8,
|
|
value: -1
|
|
};
|
|
}
|
|
let value = buffer[start] & ((1 << (8 - length)) - 1);
|
|
for (let i = 1; i < length; i += 1) {
|
|
value *= Math.pow(2, 8);
|
|
value += buffer[start + i];
|
|
}
|
|
if (value === (Math.pow(2, (length * 7)) - 1)) {
|
|
value = -1;
|
|
}
|
|
return {
|
|
length,
|
|
value,
|
|
};
|
|
}
|
|
static writeVint(value, desiredLength) {
|
|
if (value < 0 || value > (Math.pow(2, 53))) {
|
|
throw new Error(`Unrepresentable value: ${value}`);
|
|
}
|
|
let length = desiredLength;
|
|
if (!length) {
|
|
for (length = 1; length <= 8; length += 1) {
|
|
if (value < Math.pow(2, (7 * length)) - 1) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
const buffer = Buffer.alloc(length);
|
|
let val = value;
|
|
for (let i = 1; i <= length; i += 1) {
|
|
const b = val & 0xff;
|
|
buffer[length - i] = b;
|
|
val -= b;
|
|
val /= Math.pow(2, 8);
|
|
}
|
|
buffer[0] |= 1 << (8 - length);
|
|
return buffer;
|
|
}
|
|
static padStart(val) {
|
|
if (val.length == 0) {
|
|
return '00';
|
|
}
|
|
if (val.length == 1) {
|
|
return '0' + val;
|
|
}
|
|
return val;
|
|
}
|
|
static readHexString(buff, start = 0, end = buff.byteLength) {
|
|
return Array.from(buff.subarray(start, end))
|
|
.map(q => Number(q).toString(16))
|
|
.reduce((acc, current) => `${acc}${this.padStart(current)}`, '');
|
|
}
|
|
static readUtf8(buff) {
|
|
try {
|
|
return Buffer.from(buff).toString('utf8');
|
|
}
|
|
catch (exception) {
|
|
return null;
|
|
}
|
|
}
|
|
static readUnsigned(buff) {
|
|
const b = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
|
|
switch (buff.byteLength) {
|
|
case 1:
|
|
return b.getUint8(0);
|
|
case 2:
|
|
return b.getUint16(0);
|
|
case 4:
|
|
return b.getUint32(0);
|
|
default:
|
|
break;
|
|
}
|
|
if (buff.byteLength <= 6) {
|
|
return buff.reduce((acc, current) => acc * 256 + current, 0);
|
|
}
|
|
var hex = Tools.readHexString(buff, 0, buff.byteLength);
|
|
var num = parseInt(hex, 16);
|
|
if (num <= Math.pow(256, 6)) {
|
|
return num;
|
|
}
|
|
return hex;
|
|
}
|
|
static writeUnsigned(num) {
|
|
if (typeof num === 'string') {
|
|
return Buffer.from(num, 'hex');
|
|
}
|
|
else {
|
|
var buf = Buffer.alloc(6);
|
|
buf.fill(0);
|
|
buf.writeUIntBE(num, 0, 6);
|
|
let firstValueIndex = buf.findIndex(b => b !== 0);
|
|
if (firstValueIndex === -1) {
|
|
firstValueIndex = buf.length - 1;
|
|
}
|
|
let ret = buf.slice(firstValueIndex);
|
|
return ret;
|
|
}
|
|
}
|
|
static readSigned(buff) {
|
|
const b = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
|
|
switch (buff.byteLength) {
|
|
case 1:
|
|
return b.getInt8(0);
|
|
case 2:
|
|
return b.getInt16(0);
|
|
case 4:
|
|
return b.getInt32(0);
|
|
default:
|
|
return NaN;
|
|
}
|
|
}
|
|
static writeSigned(num) {
|
|
var buf = Buffer.alloc(8);
|
|
buf.writeInt32BE(num, 0);
|
|
return buf;
|
|
}
|
|
static readFloat(buff) {
|
|
const b = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
|
|
switch (buff.byteLength) {
|
|
case 4:
|
|
return b.getFloat32(0);
|
|
case 8:
|
|
return b.getFloat64(0);
|
|
default:
|
|
return NaN;
|
|
}
|
|
}
|
|
static writeFloat(num) {
|
|
let buf = Buffer.alloc(8);
|
|
let written = buf.writeFloatBE(num, 0);
|
|
if (written <= 4) {
|
|
buf = buf.slice(0, 4);
|
|
}
|
|
return buf;
|
|
}
|
|
}
|
|
exports.Tools = Tools;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic.js ***!
|
|
\***********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var elliptic = exports;
|
|
|
|
elliptic.version = __webpack_require__(/*! ../package.json */ "./node_modules/elliptic/package.json").version;
|
|
elliptic.utils = __webpack_require__(/*! ./elliptic/utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
elliptic.rand = __webpack_require__(/*! brorand */ "./node_modules/brorand/index.js");
|
|
elliptic.curve = __webpack_require__(/*! ./elliptic/curve */ "./node_modules/elliptic/lib/elliptic/curve/index.js");
|
|
elliptic.curves = __webpack_require__(/*! ./elliptic/curves */ "./node_modules/elliptic/lib/elliptic/curves.js");
|
|
|
|
// Protocols
|
|
elliptic.ec = __webpack_require__(/*! ./elliptic/ec */ "./node_modules/elliptic/lib/elliptic/ec/index.js");
|
|
elliptic.eddsa = __webpack_require__(/*! ./elliptic/eddsa */ "./node_modules/elliptic/lib/elliptic/eddsa/index.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/curve/base.js":
|
|
/*!**********************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/curve/base.js ***!
|
|
\**********************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/elliptic/node_modules/bn.js/lib/bn.js");
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
var getNAF = utils.getNAF;
|
|
var getJSF = utils.getJSF;
|
|
var assert = utils.assert;
|
|
|
|
function BaseCurve(type, conf) {
|
|
this.type = type;
|
|
this.p = new BN(conf.p, 16);
|
|
|
|
// Use Montgomery, when there is no fast reduction for the prime
|
|
this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p);
|
|
|
|
// Useful for many curves
|
|
this.zero = new BN(0).toRed(this.red);
|
|
this.one = new BN(1).toRed(this.red);
|
|
this.two = new BN(2).toRed(this.red);
|
|
|
|
// Curve configuration, optional
|
|
this.n = conf.n && new BN(conf.n, 16);
|
|
this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed);
|
|
|
|
// Temporary arrays
|
|
this._wnafT1 = new Array(4);
|
|
this._wnafT2 = new Array(4);
|
|
this._wnafT3 = new Array(4);
|
|
this._wnafT4 = new Array(4);
|
|
|
|
this._bitLength = this.n ? this.n.bitLength() : 0;
|
|
|
|
// Generalized Greg Maxwell's trick
|
|
var adjustCount = this.n && this.p.div(this.n);
|
|
if (!adjustCount || adjustCount.cmpn(100) > 0) {
|
|
this.redN = null;
|
|
} else {
|
|
this._maxwellTrick = true;
|
|
this.redN = this.n.toRed(this.red);
|
|
}
|
|
}
|
|
module.exports = BaseCurve;
|
|
|
|
BaseCurve.prototype.point = function point() {
|
|
throw new Error('Not implemented');
|
|
};
|
|
|
|
BaseCurve.prototype.validate = function validate() {
|
|
throw new Error('Not implemented');
|
|
};
|
|
|
|
BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) {
|
|
assert(p.precomputed);
|
|
var doubles = p._getDoubles();
|
|
|
|
var naf = getNAF(k, 1, this._bitLength);
|
|
var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1);
|
|
I /= 3;
|
|
|
|
// Translate into more windowed form
|
|
var repr = [];
|
|
var j;
|
|
var nafW;
|
|
for (j = 0; j < naf.length; j += doubles.step) {
|
|
nafW = 0;
|
|
for (var l = j + doubles.step - 1; l >= j; l--)
|
|
nafW = (nafW << 1) + naf[l];
|
|
repr.push(nafW);
|
|
}
|
|
|
|
var a = this.jpoint(null, null, null);
|
|
var b = this.jpoint(null, null, null);
|
|
for (var i = I; i > 0; i--) {
|
|
for (j = 0; j < repr.length; j++) {
|
|
nafW = repr[j];
|
|
if (nafW === i)
|
|
b = b.mixedAdd(doubles.points[j]);
|
|
else if (nafW === -i)
|
|
b = b.mixedAdd(doubles.points[j].neg());
|
|
}
|
|
a = a.add(b);
|
|
}
|
|
return a.toP();
|
|
};
|
|
|
|
BaseCurve.prototype._wnafMul = function _wnafMul(p, k) {
|
|
var w = 4;
|
|
|
|
// Precompute window
|
|
var nafPoints = p._getNAFPoints(w);
|
|
w = nafPoints.wnd;
|
|
var wnd = nafPoints.points;
|
|
|
|
// Get NAF form
|
|
var naf = getNAF(k, w, this._bitLength);
|
|
|
|
// Add `this`*(N+1) for every w-NAF index
|
|
var acc = this.jpoint(null, null, null);
|
|
for (var i = naf.length - 1; i >= 0; i--) {
|
|
// Count zeroes
|
|
for (var l = 0; i >= 0 && naf[i] === 0; i--)
|
|
l++;
|
|
if (i >= 0)
|
|
l++;
|
|
acc = acc.dblp(l);
|
|
|
|
if (i < 0)
|
|
break;
|
|
var z = naf[i];
|
|
assert(z !== 0);
|
|
if (p.type === 'affine') {
|
|
// J +- P
|
|
if (z > 0)
|
|
acc = acc.mixedAdd(wnd[(z - 1) >> 1]);
|
|
else
|
|
acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg());
|
|
} else {
|
|
// J +- J
|
|
if (z > 0)
|
|
acc = acc.add(wnd[(z - 1) >> 1]);
|
|
else
|
|
acc = acc.add(wnd[(-z - 1) >> 1].neg());
|
|
}
|
|
}
|
|
return p.type === 'affine' ? acc.toP() : acc;
|
|
};
|
|
|
|
BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW,
|
|
points,
|
|
coeffs,
|
|
len,
|
|
jacobianResult) {
|
|
var wndWidth = this._wnafT1;
|
|
var wnd = this._wnafT2;
|
|
var naf = this._wnafT3;
|
|
|
|
// Fill all arrays
|
|
var max = 0;
|
|
var i;
|
|
var j;
|
|
var p;
|
|
for (i = 0; i < len; i++) {
|
|
p = points[i];
|
|
var nafPoints = p._getNAFPoints(defW);
|
|
wndWidth[i] = nafPoints.wnd;
|
|
wnd[i] = nafPoints.points;
|
|
}
|
|
|
|
// Comb small window NAFs
|
|
for (i = len - 1; i >= 1; i -= 2) {
|
|
var a = i - 1;
|
|
var b = i;
|
|
if (wndWidth[a] !== 1 || wndWidth[b] !== 1) {
|
|
naf[a] = getNAF(coeffs[a], wndWidth[a], this._bitLength);
|
|
naf[b] = getNAF(coeffs[b], wndWidth[b], this._bitLength);
|
|
max = Math.max(naf[a].length, max);
|
|
max = Math.max(naf[b].length, max);
|
|
continue;
|
|
}
|
|
|
|
var comb = [
|
|
points[a], /* 1 */
|
|
null, /* 3 */
|
|
null, /* 5 */
|
|
points[b], /* 7 */
|
|
];
|
|
|
|
// Try to avoid Projective points, if possible
|
|
if (points[a].y.cmp(points[b].y) === 0) {
|
|
comb[1] = points[a].add(points[b]);
|
|
comb[2] = points[a].toJ().mixedAdd(points[b].neg());
|
|
} else if (points[a].y.cmp(points[b].y.redNeg()) === 0) {
|
|
comb[1] = points[a].toJ().mixedAdd(points[b]);
|
|
comb[2] = points[a].add(points[b].neg());
|
|
} else {
|
|
comb[1] = points[a].toJ().mixedAdd(points[b]);
|
|
comb[2] = points[a].toJ().mixedAdd(points[b].neg());
|
|
}
|
|
|
|
var index = [
|
|
-3, /* -1 -1 */
|
|
-1, /* -1 0 */
|
|
-5, /* -1 1 */
|
|
-7, /* 0 -1 */
|
|
0, /* 0 0 */
|
|
7, /* 0 1 */
|
|
5, /* 1 -1 */
|
|
1, /* 1 0 */
|
|
3, /* 1 1 */
|
|
];
|
|
|
|
var jsf = getJSF(coeffs[a], coeffs[b]);
|
|
max = Math.max(jsf[0].length, max);
|
|
naf[a] = new Array(max);
|
|
naf[b] = new Array(max);
|
|
for (j = 0; j < max; j++) {
|
|
var ja = jsf[0][j] | 0;
|
|
var jb = jsf[1][j] | 0;
|
|
|
|
naf[a][j] = index[(ja + 1) * 3 + (jb + 1)];
|
|
naf[b][j] = 0;
|
|
wnd[a] = comb;
|
|
}
|
|
}
|
|
|
|
var acc = this.jpoint(null, null, null);
|
|
var tmp = this._wnafT4;
|
|
for (i = max; i >= 0; i--) {
|
|
var k = 0;
|
|
|
|
while (i >= 0) {
|
|
var zero = true;
|
|
for (j = 0; j < len; j++) {
|
|
tmp[j] = naf[j][i] | 0;
|
|
if (tmp[j] !== 0)
|
|
zero = false;
|
|
}
|
|
if (!zero)
|
|
break;
|
|
k++;
|
|
i--;
|
|
}
|
|
if (i >= 0)
|
|
k++;
|
|
acc = acc.dblp(k);
|
|
if (i < 0)
|
|
break;
|
|
|
|
for (j = 0; j < len; j++) {
|
|
var z = tmp[j];
|
|
p;
|
|
if (z === 0)
|
|
continue;
|
|
else if (z > 0)
|
|
p = wnd[j][(z - 1) >> 1];
|
|
else if (z < 0)
|
|
p = wnd[j][(-z - 1) >> 1].neg();
|
|
|
|
if (p.type === 'affine')
|
|
acc = acc.mixedAdd(p);
|
|
else
|
|
acc = acc.add(p);
|
|
}
|
|
}
|
|
// Zeroify references
|
|
for (i = 0; i < len; i++)
|
|
wnd[i] = null;
|
|
|
|
if (jacobianResult)
|
|
return acc;
|
|
else
|
|
return acc.toP();
|
|
};
|
|
|
|
function BasePoint(curve, type) {
|
|
this.curve = curve;
|
|
this.type = type;
|
|
this.precomputed = null;
|
|
}
|
|
BaseCurve.BasePoint = BasePoint;
|
|
|
|
BasePoint.prototype.eq = function eq(/*other*/) {
|
|
throw new Error('Not implemented');
|
|
};
|
|
|
|
BasePoint.prototype.validate = function validate() {
|
|
return this.curve.validate(this);
|
|
};
|
|
|
|
BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) {
|
|
bytes = utils.toArray(bytes, enc);
|
|
|
|
var len = this.p.byteLength();
|
|
|
|
// uncompressed, hybrid-odd, hybrid-even
|
|
if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) &&
|
|
bytes.length - 1 === 2 * len) {
|
|
if (bytes[0] === 0x06)
|
|
assert(bytes[bytes.length - 1] % 2 === 0);
|
|
else if (bytes[0] === 0x07)
|
|
assert(bytes[bytes.length - 1] % 2 === 1);
|
|
|
|
var res = this.point(bytes.slice(1, 1 + len),
|
|
bytes.slice(1 + len, 1 + 2 * len));
|
|
|
|
return res;
|
|
} else if ((bytes[0] === 0x02 || bytes[0] === 0x03) &&
|
|
bytes.length - 1 === len) {
|
|
return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03);
|
|
}
|
|
throw new Error('Unknown point format');
|
|
};
|
|
|
|
BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) {
|
|
return this.encode(enc, true);
|
|
};
|
|
|
|
BasePoint.prototype._encode = function _encode(compact) {
|
|
var len = this.curve.p.byteLength();
|
|
var x = this.getX().toArray('be', len);
|
|
|
|
if (compact)
|
|
return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x);
|
|
|
|
return [ 0x04 ].concat(x, this.getY().toArray('be', len));
|
|
};
|
|
|
|
BasePoint.prototype.encode = function encode(enc, compact) {
|
|
return utils.encode(this._encode(compact), enc);
|
|
};
|
|
|
|
BasePoint.prototype.precompute = function precompute(power) {
|
|
if (this.precomputed)
|
|
return this;
|
|
|
|
var precomputed = {
|
|
doubles: null,
|
|
naf: null,
|
|
beta: null,
|
|
};
|
|
precomputed.naf = this._getNAFPoints(8);
|
|
precomputed.doubles = this._getDoubles(4, power);
|
|
precomputed.beta = this._getBeta();
|
|
this.precomputed = precomputed;
|
|
|
|
return this;
|
|
};
|
|
|
|
BasePoint.prototype._hasDoubles = function _hasDoubles(k) {
|
|
if (!this.precomputed)
|
|
return false;
|
|
|
|
var doubles = this.precomputed.doubles;
|
|
if (!doubles)
|
|
return false;
|
|
|
|
return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step);
|
|
};
|
|
|
|
BasePoint.prototype._getDoubles = function _getDoubles(step, power) {
|
|
if (this.precomputed && this.precomputed.doubles)
|
|
return this.precomputed.doubles;
|
|
|
|
var doubles = [ this ];
|
|
var acc = this;
|
|
for (var i = 0; i < power; i += step) {
|
|
for (var j = 0; j < step; j++)
|
|
acc = acc.dbl();
|
|
doubles.push(acc);
|
|
}
|
|
return {
|
|
step: step,
|
|
points: doubles,
|
|
};
|
|
};
|
|
|
|
BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) {
|
|
if (this.precomputed && this.precomputed.naf)
|
|
return this.precomputed.naf;
|
|
|
|
var res = [ this ];
|
|
var max = (1 << wnd) - 1;
|
|
var dbl = max === 1 ? null : this.dbl();
|
|
for (var i = 1; i < max; i++)
|
|
res[i] = res[i - 1].add(dbl);
|
|
return {
|
|
wnd: wnd,
|
|
points: res,
|
|
};
|
|
};
|
|
|
|
BasePoint.prototype._getBeta = function _getBeta() {
|
|
return null;
|
|
};
|
|
|
|
BasePoint.prototype.dblp = function dblp(k) {
|
|
var r = this;
|
|
for (var i = 0; i < k; i++)
|
|
r = r.dbl();
|
|
return r;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/curve/edwards.js":
|
|
/*!*************************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/curve/edwards.js ***!
|
|
\*************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/elliptic/node_modules/bn.js/lib/bn.js");
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
var Base = __webpack_require__(/*! ./base */ "./node_modules/elliptic/lib/elliptic/curve/base.js");
|
|
|
|
var assert = utils.assert;
|
|
|
|
function EdwardsCurve(conf) {
|
|
// NOTE: Important as we are creating point in Base.call()
|
|
this.twisted = (conf.a | 0) !== 1;
|
|
this.mOneA = this.twisted && (conf.a | 0) === -1;
|
|
this.extended = this.mOneA;
|
|
|
|
Base.call(this, 'edwards', conf);
|
|
|
|
this.a = new BN(conf.a, 16).umod(this.red.m);
|
|
this.a = this.a.toRed(this.red);
|
|
this.c = new BN(conf.c, 16).toRed(this.red);
|
|
this.c2 = this.c.redSqr();
|
|
this.d = new BN(conf.d, 16).toRed(this.red);
|
|
this.dd = this.d.redAdd(this.d);
|
|
|
|
assert(!this.twisted || this.c.fromRed().cmpn(1) === 0);
|
|
this.oneC = (conf.c | 0) === 1;
|
|
}
|
|
inherits(EdwardsCurve, Base);
|
|
module.exports = EdwardsCurve;
|
|
|
|
EdwardsCurve.prototype._mulA = function _mulA(num) {
|
|
if (this.mOneA)
|
|
return num.redNeg();
|
|
else
|
|
return this.a.redMul(num);
|
|
};
|
|
|
|
EdwardsCurve.prototype._mulC = function _mulC(num) {
|
|
if (this.oneC)
|
|
return num;
|
|
else
|
|
return this.c.redMul(num);
|
|
};
|
|
|
|
// Just for compatibility with Short curve
|
|
EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) {
|
|
return this.point(x, y, z, t);
|
|
};
|
|
|
|
EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) {
|
|
x = new BN(x, 16);
|
|
if (!x.red)
|
|
x = x.toRed(this.red);
|
|
|
|
var x2 = x.redSqr();
|
|
var rhs = this.c2.redSub(this.a.redMul(x2));
|
|
var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2));
|
|
|
|
var y2 = rhs.redMul(lhs.redInvm());
|
|
var y = y2.redSqrt();
|
|
if (y.redSqr().redSub(y2).cmp(this.zero) !== 0)
|
|
throw new Error('invalid point');
|
|
|
|
var isOdd = y.fromRed().isOdd();
|
|
if (odd && !isOdd || !odd && isOdd)
|
|
y = y.redNeg();
|
|
|
|
return this.point(x, y);
|
|
};
|
|
|
|
EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) {
|
|
y = new BN(y, 16);
|
|
if (!y.red)
|
|
y = y.toRed(this.red);
|
|
|
|
// x^2 = (y^2 - c^2) / (c^2 d y^2 - a)
|
|
var y2 = y.redSqr();
|
|
var lhs = y2.redSub(this.c2);
|
|
var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a);
|
|
var x2 = lhs.redMul(rhs.redInvm());
|
|
|
|
if (x2.cmp(this.zero) === 0) {
|
|
if (odd)
|
|
throw new Error('invalid point');
|
|
else
|
|
return this.point(this.zero, y);
|
|
}
|
|
|
|
var x = x2.redSqrt();
|
|
if (x.redSqr().redSub(x2).cmp(this.zero) !== 0)
|
|
throw new Error('invalid point');
|
|
|
|
if (x.fromRed().isOdd() !== odd)
|
|
x = x.redNeg();
|
|
|
|
return this.point(x, y);
|
|
};
|
|
|
|
EdwardsCurve.prototype.validate = function validate(point) {
|
|
if (point.isInfinity())
|
|
return true;
|
|
|
|
// Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2)
|
|
point.normalize();
|
|
|
|
var x2 = point.x.redSqr();
|
|
var y2 = point.y.redSqr();
|
|
var lhs = x2.redMul(this.a).redAdd(y2);
|
|
var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2)));
|
|
|
|
return lhs.cmp(rhs) === 0;
|
|
};
|
|
|
|
function Point(curve, x, y, z, t) {
|
|
Base.BasePoint.call(this, curve, 'projective');
|
|
if (x === null && y === null && z === null) {
|
|
this.x = this.curve.zero;
|
|
this.y = this.curve.one;
|
|
this.z = this.curve.one;
|
|
this.t = this.curve.zero;
|
|
this.zOne = true;
|
|
} else {
|
|
this.x = new BN(x, 16);
|
|
this.y = new BN(y, 16);
|
|
this.z = z ? new BN(z, 16) : this.curve.one;
|
|
this.t = t && new BN(t, 16);
|
|
if (!this.x.red)
|
|
this.x = this.x.toRed(this.curve.red);
|
|
if (!this.y.red)
|
|
this.y = this.y.toRed(this.curve.red);
|
|
if (!this.z.red)
|
|
this.z = this.z.toRed(this.curve.red);
|
|
if (this.t && !this.t.red)
|
|
this.t = this.t.toRed(this.curve.red);
|
|
this.zOne = this.z === this.curve.one;
|
|
|
|
// Use extended coordinates
|
|
if (this.curve.extended && !this.t) {
|
|
this.t = this.x.redMul(this.y);
|
|
if (!this.zOne)
|
|
this.t = this.t.redMul(this.z.redInvm());
|
|
}
|
|
}
|
|
}
|
|
inherits(Point, Base.BasePoint);
|
|
|
|
EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) {
|
|
return Point.fromJSON(this, obj);
|
|
};
|
|
|
|
EdwardsCurve.prototype.point = function point(x, y, z, t) {
|
|
return new Point(this, x, y, z, t);
|
|
};
|
|
|
|
Point.fromJSON = function fromJSON(curve, obj) {
|
|
return new Point(curve, obj[0], obj[1], obj[2]);
|
|
};
|
|
|
|
Point.prototype.inspect = function inspect() {
|
|
if (this.isInfinity())
|
|
return '<EC Point Infinity>';
|
|
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
|
|
' y: ' + this.y.fromRed().toString(16, 2) +
|
|
' z: ' + this.z.fromRed().toString(16, 2) + '>';
|
|
};
|
|
|
|
Point.prototype.isInfinity = function isInfinity() {
|
|
// XXX This code assumes that zero is always zero in red
|
|
return this.x.cmpn(0) === 0 &&
|
|
(this.y.cmp(this.z) === 0 ||
|
|
(this.zOne && this.y.cmp(this.curve.c) === 0));
|
|
};
|
|
|
|
Point.prototype._extDbl = function _extDbl() {
|
|
// hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
|
|
// #doubling-dbl-2008-hwcd
|
|
// 4M + 4S
|
|
|
|
// A = X1^2
|
|
var a = this.x.redSqr();
|
|
// B = Y1^2
|
|
var b = this.y.redSqr();
|
|
// C = 2 * Z1^2
|
|
var c = this.z.redSqr();
|
|
c = c.redIAdd(c);
|
|
// D = a * A
|
|
var d = this.curve._mulA(a);
|
|
// E = (X1 + Y1)^2 - A - B
|
|
var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b);
|
|
// G = D + B
|
|
var g = d.redAdd(b);
|
|
// F = G - C
|
|
var f = g.redSub(c);
|
|
// H = D - B
|
|
var h = d.redSub(b);
|
|
// X3 = E * F
|
|
var nx = e.redMul(f);
|
|
// Y3 = G * H
|
|
var ny = g.redMul(h);
|
|
// T3 = E * H
|
|
var nt = e.redMul(h);
|
|
// Z3 = F * G
|
|
var nz = f.redMul(g);
|
|
return this.curve.point(nx, ny, nz, nt);
|
|
};
|
|
|
|
Point.prototype._projDbl = function _projDbl() {
|
|
// hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
|
|
// #doubling-dbl-2008-bbjlp
|
|
// #doubling-dbl-2007-bl
|
|
// and others
|
|
// Generally 3M + 4S or 2M + 4S
|
|
|
|
// B = (X1 + Y1)^2
|
|
var b = this.x.redAdd(this.y).redSqr();
|
|
// C = X1^2
|
|
var c = this.x.redSqr();
|
|
// D = Y1^2
|
|
var d = this.y.redSqr();
|
|
|
|
var nx;
|
|
var ny;
|
|
var nz;
|
|
var e;
|
|
var h;
|
|
var j;
|
|
if (this.curve.twisted) {
|
|
// E = a * C
|
|
e = this.curve._mulA(c);
|
|
// F = E + D
|
|
var f = e.redAdd(d);
|
|
if (this.zOne) {
|
|
// X3 = (B - C - D) * (F - 2)
|
|
nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two));
|
|
// Y3 = F * (E - D)
|
|
ny = f.redMul(e.redSub(d));
|
|
// Z3 = F^2 - 2 * F
|
|
nz = f.redSqr().redSub(f).redSub(f);
|
|
} else {
|
|
// H = Z1^2
|
|
h = this.z.redSqr();
|
|
// J = F - 2 * H
|
|
j = f.redSub(h).redISub(h);
|
|
// X3 = (B-C-D)*J
|
|
nx = b.redSub(c).redISub(d).redMul(j);
|
|
// Y3 = F * (E - D)
|
|
ny = f.redMul(e.redSub(d));
|
|
// Z3 = F * J
|
|
nz = f.redMul(j);
|
|
}
|
|
} else {
|
|
// E = C + D
|
|
e = c.redAdd(d);
|
|
// H = (c * Z1)^2
|
|
h = this.curve._mulC(this.z).redSqr();
|
|
// J = E - 2 * H
|
|
j = e.redSub(h).redSub(h);
|
|
// X3 = c * (B - E) * J
|
|
nx = this.curve._mulC(b.redISub(e)).redMul(j);
|
|
// Y3 = c * E * (C - D)
|
|
ny = this.curve._mulC(e).redMul(c.redISub(d));
|
|
// Z3 = E * J
|
|
nz = e.redMul(j);
|
|
}
|
|
return this.curve.point(nx, ny, nz);
|
|
};
|
|
|
|
Point.prototype.dbl = function dbl() {
|
|
if (this.isInfinity())
|
|
return this;
|
|
|
|
// Double in extended coordinates
|
|
if (this.curve.extended)
|
|
return this._extDbl();
|
|
else
|
|
return this._projDbl();
|
|
};
|
|
|
|
Point.prototype._extAdd = function _extAdd(p) {
|
|
// hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
|
|
// #addition-add-2008-hwcd-3
|
|
// 8M
|
|
|
|
// A = (Y1 - X1) * (Y2 - X2)
|
|
var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x));
|
|
// B = (Y1 + X1) * (Y2 + X2)
|
|
var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x));
|
|
// C = T1 * k * T2
|
|
var c = this.t.redMul(this.curve.dd).redMul(p.t);
|
|
// D = Z1 * 2 * Z2
|
|
var d = this.z.redMul(p.z.redAdd(p.z));
|
|
// E = B - A
|
|
var e = b.redSub(a);
|
|
// F = D - C
|
|
var f = d.redSub(c);
|
|
// G = D + C
|
|
var g = d.redAdd(c);
|
|
// H = B + A
|
|
var h = b.redAdd(a);
|
|
// X3 = E * F
|
|
var nx = e.redMul(f);
|
|
// Y3 = G * H
|
|
var ny = g.redMul(h);
|
|
// T3 = E * H
|
|
var nt = e.redMul(h);
|
|
// Z3 = F * G
|
|
var nz = f.redMul(g);
|
|
return this.curve.point(nx, ny, nz, nt);
|
|
};
|
|
|
|
Point.prototype._projAdd = function _projAdd(p) {
|
|
// hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
|
|
// #addition-add-2008-bbjlp
|
|
// #addition-add-2007-bl
|
|
// 10M + 1S
|
|
|
|
// A = Z1 * Z2
|
|
var a = this.z.redMul(p.z);
|
|
// B = A^2
|
|
var b = a.redSqr();
|
|
// C = X1 * X2
|
|
var c = this.x.redMul(p.x);
|
|
// D = Y1 * Y2
|
|
var d = this.y.redMul(p.y);
|
|
// E = d * C * D
|
|
var e = this.curve.d.redMul(c).redMul(d);
|
|
// F = B - E
|
|
var f = b.redSub(e);
|
|
// G = B + E
|
|
var g = b.redAdd(e);
|
|
// X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D)
|
|
var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d);
|
|
var nx = a.redMul(f).redMul(tmp);
|
|
var ny;
|
|
var nz;
|
|
if (this.curve.twisted) {
|
|
// Y3 = A * G * (D - a * C)
|
|
ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c)));
|
|
// Z3 = F * G
|
|
nz = f.redMul(g);
|
|
} else {
|
|
// Y3 = A * G * (D - C)
|
|
ny = a.redMul(g).redMul(d.redSub(c));
|
|
// Z3 = c * F * G
|
|
nz = this.curve._mulC(f).redMul(g);
|
|
}
|
|
return this.curve.point(nx, ny, nz);
|
|
};
|
|
|
|
Point.prototype.add = function add(p) {
|
|
if (this.isInfinity())
|
|
return p;
|
|
if (p.isInfinity())
|
|
return this;
|
|
|
|
if (this.curve.extended)
|
|
return this._extAdd(p);
|
|
else
|
|
return this._projAdd(p);
|
|
};
|
|
|
|
Point.prototype.mul = function mul(k) {
|
|
if (this._hasDoubles(k))
|
|
return this.curve._fixedNafMul(this, k);
|
|
else
|
|
return this.curve._wnafMul(this, k);
|
|
};
|
|
|
|
Point.prototype.mulAdd = function mulAdd(k1, p, k2) {
|
|
return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false);
|
|
};
|
|
|
|
Point.prototype.jmulAdd = function jmulAdd(k1, p, k2) {
|
|
return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true);
|
|
};
|
|
|
|
Point.prototype.normalize = function normalize() {
|
|
if (this.zOne)
|
|
return this;
|
|
|
|
// Normalize coordinates
|
|
var zi = this.z.redInvm();
|
|
this.x = this.x.redMul(zi);
|
|
this.y = this.y.redMul(zi);
|
|
if (this.t)
|
|
this.t = this.t.redMul(zi);
|
|
this.z = this.curve.one;
|
|
this.zOne = true;
|
|
return this;
|
|
};
|
|
|
|
Point.prototype.neg = function neg() {
|
|
return this.curve.point(this.x.redNeg(),
|
|
this.y,
|
|
this.z,
|
|
this.t && this.t.redNeg());
|
|
};
|
|
|
|
Point.prototype.getX = function getX() {
|
|
this.normalize();
|
|
return this.x.fromRed();
|
|
};
|
|
|
|
Point.prototype.getY = function getY() {
|
|
this.normalize();
|
|
return this.y.fromRed();
|
|
};
|
|
|
|
Point.prototype.eq = function eq(other) {
|
|
return this === other ||
|
|
this.getX().cmp(other.getX()) === 0 &&
|
|
this.getY().cmp(other.getY()) === 0;
|
|
};
|
|
|
|
Point.prototype.eqXToP = function eqXToP(x) {
|
|
var rx = x.toRed(this.curve.red).redMul(this.z);
|
|
if (this.x.cmp(rx) === 0)
|
|
return true;
|
|
|
|
var xc = x.clone();
|
|
var t = this.curve.redN.redMul(this.z);
|
|
for (;;) {
|
|
xc.iadd(this.curve.n);
|
|
if (xc.cmp(this.curve.p) >= 0)
|
|
return false;
|
|
|
|
rx.redIAdd(t);
|
|
if (this.x.cmp(rx) === 0)
|
|
return true;
|
|
}
|
|
};
|
|
|
|
// Compatibility with BaseCurve
|
|
Point.prototype.toP = Point.prototype.normalize;
|
|
Point.prototype.mixedAdd = Point.prototype.add;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/curve/index.js":
|
|
/*!***********************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/curve/index.js ***!
|
|
\***********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var curve = exports;
|
|
|
|
curve.base = __webpack_require__(/*! ./base */ "./node_modules/elliptic/lib/elliptic/curve/base.js");
|
|
curve.short = __webpack_require__(/*! ./short */ "./node_modules/elliptic/lib/elliptic/curve/short.js");
|
|
curve.mont = __webpack_require__(/*! ./mont */ "./node_modules/elliptic/lib/elliptic/curve/mont.js");
|
|
curve.edwards = __webpack_require__(/*! ./edwards */ "./node_modules/elliptic/lib/elliptic/curve/edwards.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/curve/mont.js":
|
|
/*!**********************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/curve/mont.js ***!
|
|
\**********************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/elliptic/node_modules/bn.js/lib/bn.js");
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
var Base = __webpack_require__(/*! ./base */ "./node_modules/elliptic/lib/elliptic/curve/base.js");
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
|
|
function MontCurve(conf) {
|
|
Base.call(this, 'mont', conf);
|
|
|
|
this.a = new BN(conf.a, 16).toRed(this.red);
|
|
this.b = new BN(conf.b, 16).toRed(this.red);
|
|
this.i4 = new BN(4).toRed(this.red).redInvm();
|
|
this.two = new BN(2).toRed(this.red);
|
|
this.a24 = this.i4.redMul(this.a.redAdd(this.two));
|
|
}
|
|
inherits(MontCurve, Base);
|
|
module.exports = MontCurve;
|
|
|
|
MontCurve.prototype.validate = function validate(point) {
|
|
var x = point.normalize().x;
|
|
var x2 = x.redSqr();
|
|
var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x);
|
|
var y = rhs.redSqrt();
|
|
|
|
return y.redSqr().cmp(rhs) === 0;
|
|
};
|
|
|
|
function Point(curve, x, z) {
|
|
Base.BasePoint.call(this, curve, 'projective');
|
|
if (x === null && z === null) {
|
|
this.x = this.curve.one;
|
|
this.z = this.curve.zero;
|
|
} else {
|
|
this.x = new BN(x, 16);
|
|
this.z = new BN(z, 16);
|
|
if (!this.x.red)
|
|
this.x = this.x.toRed(this.curve.red);
|
|
if (!this.z.red)
|
|
this.z = this.z.toRed(this.curve.red);
|
|
}
|
|
}
|
|
inherits(Point, Base.BasePoint);
|
|
|
|
MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) {
|
|
return this.point(utils.toArray(bytes, enc), 1);
|
|
};
|
|
|
|
MontCurve.prototype.point = function point(x, z) {
|
|
return new Point(this, x, z);
|
|
};
|
|
|
|
MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) {
|
|
return Point.fromJSON(this, obj);
|
|
};
|
|
|
|
Point.prototype.precompute = function precompute() {
|
|
// No-op
|
|
};
|
|
|
|
Point.prototype._encode = function _encode() {
|
|
return this.getX().toArray('be', this.curve.p.byteLength());
|
|
};
|
|
|
|
Point.fromJSON = function fromJSON(curve, obj) {
|
|
return new Point(curve, obj[0], obj[1] || curve.one);
|
|
};
|
|
|
|
Point.prototype.inspect = function inspect() {
|
|
if (this.isInfinity())
|
|
return '<EC Point Infinity>';
|
|
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
|
|
' z: ' + this.z.fromRed().toString(16, 2) + '>';
|
|
};
|
|
|
|
Point.prototype.isInfinity = function isInfinity() {
|
|
// XXX This code assumes that zero is always zero in red
|
|
return this.z.cmpn(0) === 0;
|
|
};
|
|
|
|
Point.prototype.dbl = function dbl() {
|
|
// http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3
|
|
// 2M + 2S + 4A
|
|
|
|
// A = X1 + Z1
|
|
var a = this.x.redAdd(this.z);
|
|
// AA = A^2
|
|
var aa = a.redSqr();
|
|
// B = X1 - Z1
|
|
var b = this.x.redSub(this.z);
|
|
// BB = B^2
|
|
var bb = b.redSqr();
|
|
// C = AA - BB
|
|
var c = aa.redSub(bb);
|
|
// X3 = AA * BB
|
|
var nx = aa.redMul(bb);
|
|
// Z3 = C * (BB + A24 * C)
|
|
var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c)));
|
|
return this.curve.point(nx, nz);
|
|
};
|
|
|
|
Point.prototype.add = function add() {
|
|
throw new Error('Not supported on Montgomery curve');
|
|
};
|
|
|
|
Point.prototype.diffAdd = function diffAdd(p, diff) {
|
|
// http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3
|
|
// 4M + 2S + 6A
|
|
|
|
// A = X2 + Z2
|
|
var a = this.x.redAdd(this.z);
|
|
// B = X2 - Z2
|
|
var b = this.x.redSub(this.z);
|
|
// C = X3 + Z3
|
|
var c = p.x.redAdd(p.z);
|
|
// D = X3 - Z3
|
|
var d = p.x.redSub(p.z);
|
|
// DA = D * A
|
|
var da = d.redMul(a);
|
|
// CB = C * B
|
|
var cb = c.redMul(b);
|
|
// X5 = Z1 * (DA + CB)^2
|
|
var nx = diff.z.redMul(da.redAdd(cb).redSqr());
|
|
// Z5 = X1 * (DA - CB)^2
|
|
var nz = diff.x.redMul(da.redISub(cb).redSqr());
|
|
return this.curve.point(nx, nz);
|
|
};
|
|
|
|
Point.prototype.mul = function mul(k) {
|
|
var t = k.clone();
|
|
var a = this; // (N / 2) * Q + Q
|
|
var b = this.curve.point(null, null); // (N / 2) * Q
|
|
var c = this; // Q
|
|
|
|
for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1))
|
|
bits.push(t.andln(1));
|
|
|
|
for (var i = bits.length - 1; i >= 0; i--) {
|
|
if (bits[i] === 0) {
|
|
// N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q
|
|
a = a.diffAdd(b, c);
|
|
// N * Q = 2 * ((N / 2) * Q + Q))
|
|
b = b.dbl();
|
|
} else {
|
|
// N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q)
|
|
b = a.diffAdd(b, c);
|
|
// N * Q + Q = 2 * ((N / 2) * Q + Q)
|
|
a = a.dbl();
|
|
}
|
|
}
|
|
return b;
|
|
};
|
|
|
|
Point.prototype.mulAdd = function mulAdd() {
|
|
throw new Error('Not supported on Montgomery curve');
|
|
};
|
|
|
|
Point.prototype.jumlAdd = function jumlAdd() {
|
|
throw new Error('Not supported on Montgomery curve');
|
|
};
|
|
|
|
Point.prototype.eq = function eq(other) {
|
|
return this.getX().cmp(other.getX()) === 0;
|
|
};
|
|
|
|
Point.prototype.normalize = function normalize() {
|
|
this.x = this.x.redMul(this.z.redInvm());
|
|
this.z = this.curve.one;
|
|
return this;
|
|
};
|
|
|
|
Point.prototype.getX = function getX() {
|
|
// Normalize coordinates
|
|
this.normalize();
|
|
|
|
return this.x.fromRed();
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/curve/short.js":
|
|
/*!***********************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/curve/short.js ***!
|
|
\***********************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/elliptic/node_modules/bn.js/lib/bn.js");
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
var Base = __webpack_require__(/*! ./base */ "./node_modules/elliptic/lib/elliptic/curve/base.js");
|
|
|
|
var assert = utils.assert;
|
|
|
|
function ShortCurve(conf) {
|
|
Base.call(this, 'short', conf);
|
|
|
|
this.a = new BN(conf.a, 16).toRed(this.red);
|
|
this.b = new BN(conf.b, 16).toRed(this.red);
|
|
this.tinv = this.two.redInvm();
|
|
|
|
this.zeroA = this.a.fromRed().cmpn(0) === 0;
|
|
this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0;
|
|
|
|
// If the curve is endomorphic, precalculate beta and lambda
|
|
this.endo = this._getEndomorphism(conf);
|
|
this._endoWnafT1 = new Array(4);
|
|
this._endoWnafT2 = new Array(4);
|
|
}
|
|
inherits(ShortCurve, Base);
|
|
module.exports = ShortCurve;
|
|
|
|
ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) {
|
|
// No efficient endomorphism
|
|
if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1)
|
|
return;
|
|
|
|
// Compute beta and lambda, that lambda * P = (beta * Px; Py)
|
|
var beta;
|
|
var lambda;
|
|
if (conf.beta) {
|
|
beta = new BN(conf.beta, 16).toRed(this.red);
|
|
} else {
|
|
var betas = this._getEndoRoots(this.p);
|
|
// Choose the smallest beta
|
|
beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1];
|
|
beta = beta.toRed(this.red);
|
|
}
|
|
if (conf.lambda) {
|
|
lambda = new BN(conf.lambda, 16);
|
|
} else {
|
|
// Choose the lambda that is matching selected beta
|
|
var lambdas = this._getEndoRoots(this.n);
|
|
if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) {
|
|
lambda = lambdas[0];
|
|
} else {
|
|
lambda = lambdas[1];
|
|
assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0);
|
|
}
|
|
}
|
|
|
|
// Get basis vectors, used for balanced length-two representation
|
|
var basis;
|
|
if (conf.basis) {
|
|
basis = conf.basis.map(function(vec) {
|
|
return {
|
|
a: new BN(vec.a, 16),
|
|
b: new BN(vec.b, 16),
|
|
};
|
|
});
|
|
} else {
|
|
basis = this._getEndoBasis(lambda);
|
|
}
|
|
|
|
return {
|
|
beta: beta,
|
|
lambda: lambda,
|
|
basis: basis,
|
|
};
|
|
};
|
|
|
|
ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) {
|
|
// Find roots of for x^2 + x + 1 in F
|
|
// Root = (-1 +- Sqrt(-3)) / 2
|
|
//
|
|
var red = num === this.p ? this.red : BN.mont(num);
|
|
var tinv = new BN(2).toRed(red).redInvm();
|
|
var ntinv = tinv.redNeg();
|
|
|
|
var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv);
|
|
|
|
var l1 = ntinv.redAdd(s).fromRed();
|
|
var l2 = ntinv.redSub(s).fromRed();
|
|
return [ l1, l2 ];
|
|
};
|
|
|
|
ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) {
|
|
// aprxSqrt >= sqrt(this.n)
|
|
var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2));
|
|
|
|
// 3.74
|
|
// Run EGCD, until r(L + 1) < aprxSqrt
|
|
var u = lambda;
|
|
var v = this.n.clone();
|
|
var x1 = new BN(1);
|
|
var y1 = new BN(0);
|
|
var x2 = new BN(0);
|
|
var y2 = new BN(1);
|
|
|
|
// NOTE: all vectors are roots of: a + b * lambda = 0 (mod n)
|
|
var a0;
|
|
var b0;
|
|
// First vector
|
|
var a1;
|
|
var b1;
|
|
// Second vector
|
|
var a2;
|
|
var b2;
|
|
|
|
var prevR;
|
|
var i = 0;
|
|
var r;
|
|
var x;
|
|
while (u.cmpn(0) !== 0) {
|
|
var q = v.div(u);
|
|
r = v.sub(q.mul(u));
|
|
x = x2.sub(q.mul(x1));
|
|
var y = y2.sub(q.mul(y1));
|
|
|
|
if (!a1 && r.cmp(aprxSqrt) < 0) {
|
|
a0 = prevR.neg();
|
|
b0 = x1;
|
|
a1 = r.neg();
|
|
b1 = x;
|
|
} else if (a1 && ++i === 2) {
|
|
break;
|
|
}
|
|
prevR = r;
|
|
|
|
v = u;
|
|
u = r;
|
|
x2 = x1;
|
|
x1 = x;
|
|
y2 = y1;
|
|
y1 = y;
|
|
}
|
|
a2 = r.neg();
|
|
b2 = x;
|
|
|
|
var len1 = a1.sqr().add(b1.sqr());
|
|
var len2 = a2.sqr().add(b2.sqr());
|
|
if (len2.cmp(len1) >= 0) {
|
|
a2 = a0;
|
|
b2 = b0;
|
|
}
|
|
|
|
// Normalize signs
|
|
if (a1.negative) {
|
|
a1 = a1.neg();
|
|
b1 = b1.neg();
|
|
}
|
|
if (a2.negative) {
|
|
a2 = a2.neg();
|
|
b2 = b2.neg();
|
|
}
|
|
|
|
return [
|
|
{ a: a1, b: b1 },
|
|
{ a: a2, b: b2 },
|
|
];
|
|
};
|
|
|
|
ShortCurve.prototype._endoSplit = function _endoSplit(k) {
|
|
var basis = this.endo.basis;
|
|
var v1 = basis[0];
|
|
var v2 = basis[1];
|
|
|
|
var c1 = v2.b.mul(k).divRound(this.n);
|
|
var c2 = v1.b.neg().mul(k).divRound(this.n);
|
|
|
|
var p1 = c1.mul(v1.a);
|
|
var p2 = c2.mul(v2.a);
|
|
var q1 = c1.mul(v1.b);
|
|
var q2 = c2.mul(v2.b);
|
|
|
|
// Calculate answer
|
|
var k1 = k.sub(p1).sub(p2);
|
|
var k2 = q1.add(q2).neg();
|
|
return { k1: k1, k2: k2 };
|
|
};
|
|
|
|
ShortCurve.prototype.pointFromX = function pointFromX(x, odd) {
|
|
x = new BN(x, 16);
|
|
if (!x.red)
|
|
x = x.toRed(this.red);
|
|
|
|
var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b);
|
|
var y = y2.redSqrt();
|
|
if (y.redSqr().redSub(y2).cmp(this.zero) !== 0)
|
|
throw new Error('invalid point');
|
|
|
|
// XXX Is there any way to tell if the number is odd without converting it
|
|
// to non-red form?
|
|
var isOdd = y.fromRed().isOdd();
|
|
if (odd && !isOdd || !odd && isOdd)
|
|
y = y.redNeg();
|
|
|
|
return this.point(x, y);
|
|
};
|
|
|
|
ShortCurve.prototype.validate = function validate(point) {
|
|
if (point.inf)
|
|
return true;
|
|
|
|
var x = point.x;
|
|
var y = point.y;
|
|
|
|
var ax = this.a.redMul(x);
|
|
var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b);
|
|
return y.redSqr().redISub(rhs).cmpn(0) === 0;
|
|
};
|
|
|
|
ShortCurve.prototype._endoWnafMulAdd =
|
|
function _endoWnafMulAdd(points, coeffs, jacobianResult) {
|
|
var npoints = this._endoWnafT1;
|
|
var ncoeffs = this._endoWnafT2;
|
|
for (var i = 0; i < points.length; i++) {
|
|
var split = this._endoSplit(coeffs[i]);
|
|
var p = points[i];
|
|
var beta = p._getBeta();
|
|
|
|
if (split.k1.negative) {
|
|
split.k1.ineg();
|
|
p = p.neg(true);
|
|
}
|
|
if (split.k2.negative) {
|
|
split.k2.ineg();
|
|
beta = beta.neg(true);
|
|
}
|
|
|
|
npoints[i * 2] = p;
|
|
npoints[i * 2 + 1] = beta;
|
|
ncoeffs[i * 2] = split.k1;
|
|
ncoeffs[i * 2 + 1] = split.k2;
|
|
}
|
|
var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult);
|
|
|
|
// Clean-up references to points and coefficients
|
|
for (var j = 0; j < i * 2; j++) {
|
|
npoints[j] = null;
|
|
ncoeffs[j] = null;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
function Point(curve, x, y, isRed) {
|
|
Base.BasePoint.call(this, curve, 'affine');
|
|
if (x === null && y === null) {
|
|
this.x = null;
|
|
this.y = null;
|
|
this.inf = true;
|
|
} else {
|
|
this.x = new BN(x, 16);
|
|
this.y = new BN(y, 16);
|
|
// Force redgomery representation when loading from JSON
|
|
if (isRed) {
|
|
this.x.forceRed(this.curve.red);
|
|
this.y.forceRed(this.curve.red);
|
|
}
|
|
if (!this.x.red)
|
|
this.x = this.x.toRed(this.curve.red);
|
|
if (!this.y.red)
|
|
this.y = this.y.toRed(this.curve.red);
|
|
this.inf = false;
|
|
}
|
|
}
|
|
inherits(Point, Base.BasePoint);
|
|
|
|
ShortCurve.prototype.point = function point(x, y, isRed) {
|
|
return new Point(this, x, y, isRed);
|
|
};
|
|
|
|
ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) {
|
|
return Point.fromJSON(this, obj, red);
|
|
};
|
|
|
|
Point.prototype._getBeta = function _getBeta() {
|
|
if (!this.curve.endo)
|
|
return;
|
|
|
|
var pre = this.precomputed;
|
|
if (pre && pre.beta)
|
|
return pre.beta;
|
|
|
|
var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y);
|
|
if (pre) {
|
|
var curve = this.curve;
|
|
var endoMul = function(p) {
|
|
return curve.point(p.x.redMul(curve.endo.beta), p.y);
|
|
};
|
|
pre.beta = beta;
|
|
beta.precomputed = {
|
|
beta: null,
|
|
naf: pre.naf && {
|
|
wnd: pre.naf.wnd,
|
|
points: pre.naf.points.map(endoMul),
|
|
},
|
|
doubles: pre.doubles && {
|
|
step: pre.doubles.step,
|
|
points: pre.doubles.points.map(endoMul),
|
|
},
|
|
};
|
|
}
|
|
return beta;
|
|
};
|
|
|
|
Point.prototype.toJSON = function toJSON() {
|
|
if (!this.precomputed)
|
|
return [ this.x, this.y ];
|
|
|
|
return [ this.x, this.y, this.precomputed && {
|
|
doubles: this.precomputed.doubles && {
|
|
step: this.precomputed.doubles.step,
|
|
points: this.precomputed.doubles.points.slice(1),
|
|
},
|
|
naf: this.precomputed.naf && {
|
|
wnd: this.precomputed.naf.wnd,
|
|
points: this.precomputed.naf.points.slice(1),
|
|
},
|
|
} ];
|
|
};
|
|
|
|
Point.fromJSON = function fromJSON(curve, obj, red) {
|
|
if (typeof obj === 'string')
|
|
obj = JSON.parse(obj);
|
|
var res = curve.point(obj[0], obj[1], red);
|
|
if (!obj[2])
|
|
return res;
|
|
|
|
function obj2point(obj) {
|
|
return curve.point(obj[0], obj[1], red);
|
|
}
|
|
|
|
var pre = obj[2];
|
|
res.precomputed = {
|
|
beta: null,
|
|
doubles: pre.doubles && {
|
|
step: pre.doubles.step,
|
|
points: [ res ].concat(pre.doubles.points.map(obj2point)),
|
|
},
|
|
naf: pre.naf && {
|
|
wnd: pre.naf.wnd,
|
|
points: [ res ].concat(pre.naf.points.map(obj2point)),
|
|
},
|
|
};
|
|
return res;
|
|
};
|
|
|
|
Point.prototype.inspect = function inspect() {
|
|
if (this.isInfinity())
|
|
return '<EC Point Infinity>';
|
|
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
|
|
' y: ' + this.y.fromRed().toString(16, 2) + '>';
|
|
};
|
|
|
|
Point.prototype.isInfinity = function isInfinity() {
|
|
return this.inf;
|
|
};
|
|
|
|
Point.prototype.add = function add(p) {
|
|
// O + P = P
|
|
if (this.inf)
|
|
return p;
|
|
|
|
// P + O = P
|
|
if (p.inf)
|
|
return this;
|
|
|
|
// P + P = 2P
|
|
if (this.eq(p))
|
|
return this.dbl();
|
|
|
|
// P + (-P) = O
|
|
if (this.neg().eq(p))
|
|
return this.curve.point(null, null);
|
|
|
|
// P + Q = O
|
|
if (this.x.cmp(p.x) === 0)
|
|
return this.curve.point(null, null);
|
|
|
|
var c = this.y.redSub(p.y);
|
|
if (c.cmpn(0) !== 0)
|
|
c = c.redMul(this.x.redSub(p.x).redInvm());
|
|
var nx = c.redSqr().redISub(this.x).redISub(p.x);
|
|
var ny = c.redMul(this.x.redSub(nx)).redISub(this.y);
|
|
return this.curve.point(nx, ny);
|
|
};
|
|
|
|
Point.prototype.dbl = function dbl() {
|
|
if (this.inf)
|
|
return this;
|
|
|
|
// 2P = O
|
|
var ys1 = this.y.redAdd(this.y);
|
|
if (ys1.cmpn(0) === 0)
|
|
return this.curve.point(null, null);
|
|
|
|
var a = this.curve.a;
|
|
|
|
var x2 = this.x.redSqr();
|
|
var dyinv = ys1.redInvm();
|
|
var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv);
|
|
|
|
var nx = c.redSqr().redISub(this.x.redAdd(this.x));
|
|
var ny = c.redMul(this.x.redSub(nx)).redISub(this.y);
|
|
return this.curve.point(nx, ny);
|
|
};
|
|
|
|
Point.prototype.getX = function getX() {
|
|
return this.x.fromRed();
|
|
};
|
|
|
|
Point.prototype.getY = function getY() {
|
|
return this.y.fromRed();
|
|
};
|
|
|
|
Point.prototype.mul = function mul(k) {
|
|
k = new BN(k, 16);
|
|
if (this.isInfinity())
|
|
return this;
|
|
else if (this._hasDoubles(k))
|
|
return this.curve._fixedNafMul(this, k);
|
|
else if (this.curve.endo)
|
|
return this.curve._endoWnafMulAdd([ this ], [ k ]);
|
|
else
|
|
return this.curve._wnafMul(this, k);
|
|
};
|
|
|
|
Point.prototype.mulAdd = function mulAdd(k1, p2, k2) {
|
|
var points = [ this, p2 ];
|
|
var coeffs = [ k1, k2 ];
|
|
if (this.curve.endo)
|
|
return this.curve._endoWnafMulAdd(points, coeffs);
|
|
else
|
|
return this.curve._wnafMulAdd(1, points, coeffs, 2);
|
|
};
|
|
|
|
Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) {
|
|
var points = [ this, p2 ];
|
|
var coeffs = [ k1, k2 ];
|
|
if (this.curve.endo)
|
|
return this.curve._endoWnafMulAdd(points, coeffs, true);
|
|
else
|
|
return this.curve._wnafMulAdd(1, points, coeffs, 2, true);
|
|
};
|
|
|
|
Point.prototype.eq = function eq(p) {
|
|
return this === p ||
|
|
this.inf === p.inf &&
|
|
(this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0);
|
|
};
|
|
|
|
Point.prototype.neg = function neg(_precompute) {
|
|
if (this.inf)
|
|
return this;
|
|
|
|
var res = this.curve.point(this.x, this.y.redNeg());
|
|
if (_precompute && this.precomputed) {
|
|
var pre = this.precomputed;
|
|
var negate = function(p) {
|
|
return p.neg();
|
|
};
|
|
res.precomputed = {
|
|
naf: pre.naf && {
|
|
wnd: pre.naf.wnd,
|
|
points: pre.naf.points.map(negate),
|
|
},
|
|
doubles: pre.doubles && {
|
|
step: pre.doubles.step,
|
|
points: pre.doubles.points.map(negate),
|
|
},
|
|
};
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Point.prototype.toJ = function toJ() {
|
|
if (this.inf)
|
|
return this.curve.jpoint(null, null, null);
|
|
|
|
var res = this.curve.jpoint(this.x, this.y, this.curve.one);
|
|
return res;
|
|
};
|
|
|
|
function JPoint(curve, x, y, z) {
|
|
Base.BasePoint.call(this, curve, 'jacobian');
|
|
if (x === null && y === null && z === null) {
|
|
this.x = this.curve.one;
|
|
this.y = this.curve.one;
|
|
this.z = new BN(0);
|
|
} else {
|
|
this.x = new BN(x, 16);
|
|
this.y = new BN(y, 16);
|
|
this.z = new BN(z, 16);
|
|
}
|
|
if (!this.x.red)
|
|
this.x = this.x.toRed(this.curve.red);
|
|
if (!this.y.red)
|
|
this.y = this.y.toRed(this.curve.red);
|
|
if (!this.z.red)
|
|
this.z = this.z.toRed(this.curve.red);
|
|
|
|
this.zOne = this.z === this.curve.one;
|
|
}
|
|
inherits(JPoint, Base.BasePoint);
|
|
|
|
ShortCurve.prototype.jpoint = function jpoint(x, y, z) {
|
|
return new JPoint(this, x, y, z);
|
|
};
|
|
|
|
JPoint.prototype.toP = function toP() {
|
|
if (this.isInfinity())
|
|
return this.curve.point(null, null);
|
|
|
|
var zinv = this.z.redInvm();
|
|
var zinv2 = zinv.redSqr();
|
|
var ax = this.x.redMul(zinv2);
|
|
var ay = this.y.redMul(zinv2).redMul(zinv);
|
|
|
|
return this.curve.point(ax, ay);
|
|
};
|
|
|
|
JPoint.prototype.neg = function neg() {
|
|
return this.curve.jpoint(this.x, this.y.redNeg(), this.z);
|
|
};
|
|
|
|
JPoint.prototype.add = function add(p) {
|
|
// O + P = P
|
|
if (this.isInfinity())
|
|
return p;
|
|
|
|
// P + O = P
|
|
if (p.isInfinity())
|
|
return this;
|
|
|
|
// 12M + 4S + 7A
|
|
var pz2 = p.z.redSqr();
|
|
var z2 = this.z.redSqr();
|
|
var u1 = this.x.redMul(pz2);
|
|
var u2 = p.x.redMul(z2);
|
|
var s1 = this.y.redMul(pz2.redMul(p.z));
|
|
var s2 = p.y.redMul(z2.redMul(this.z));
|
|
|
|
var h = u1.redSub(u2);
|
|
var r = s1.redSub(s2);
|
|
if (h.cmpn(0) === 0) {
|
|
if (r.cmpn(0) !== 0)
|
|
return this.curve.jpoint(null, null, null);
|
|
else
|
|
return this.dbl();
|
|
}
|
|
|
|
var h2 = h.redSqr();
|
|
var h3 = h2.redMul(h);
|
|
var v = u1.redMul(h2);
|
|
|
|
var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v);
|
|
var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3));
|
|
var nz = this.z.redMul(p.z).redMul(h);
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype.mixedAdd = function mixedAdd(p) {
|
|
// O + P = P
|
|
if (this.isInfinity())
|
|
return p.toJ();
|
|
|
|
// P + O = P
|
|
if (p.isInfinity())
|
|
return this;
|
|
|
|
// 8M + 3S + 7A
|
|
var z2 = this.z.redSqr();
|
|
var u1 = this.x;
|
|
var u2 = p.x.redMul(z2);
|
|
var s1 = this.y;
|
|
var s2 = p.y.redMul(z2).redMul(this.z);
|
|
|
|
var h = u1.redSub(u2);
|
|
var r = s1.redSub(s2);
|
|
if (h.cmpn(0) === 0) {
|
|
if (r.cmpn(0) !== 0)
|
|
return this.curve.jpoint(null, null, null);
|
|
else
|
|
return this.dbl();
|
|
}
|
|
|
|
var h2 = h.redSqr();
|
|
var h3 = h2.redMul(h);
|
|
var v = u1.redMul(h2);
|
|
|
|
var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v);
|
|
var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3));
|
|
var nz = this.z.redMul(h);
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype.dblp = function dblp(pow) {
|
|
if (pow === 0)
|
|
return this;
|
|
if (this.isInfinity())
|
|
return this;
|
|
if (!pow)
|
|
return this.dbl();
|
|
|
|
var i;
|
|
if (this.curve.zeroA || this.curve.threeA) {
|
|
var r = this;
|
|
for (i = 0; i < pow; i++)
|
|
r = r.dbl();
|
|
return r;
|
|
}
|
|
|
|
// 1M + 2S + 1A + N * (4S + 5M + 8A)
|
|
// N = 1 => 6M + 6S + 9A
|
|
var a = this.curve.a;
|
|
var tinv = this.curve.tinv;
|
|
|
|
var jx = this.x;
|
|
var jy = this.y;
|
|
var jz = this.z;
|
|
var jz4 = jz.redSqr().redSqr();
|
|
|
|
// Reuse results
|
|
var jyd = jy.redAdd(jy);
|
|
for (i = 0; i < pow; i++) {
|
|
var jx2 = jx.redSqr();
|
|
var jyd2 = jyd.redSqr();
|
|
var jyd4 = jyd2.redSqr();
|
|
var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4));
|
|
|
|
var t1 = jx.redMul(jyd2);
|
|
var nx = c.redSqr().redISub(t1.redAdd(t1));
|
|
var t2 = t1.redISub(nx);
|
|
var dny = c.redMul(t2);
|
|
dny = dny.redIAdd(dny).redISub(jyd4);
|
|
var nz = jyd.redMul(jz);
|
|
if (i + 1 < pow)
|
|
jz4 = jz4.redMul(jyd4);
|
|
|
|
jx = nx;
|
|
jz = nz;
|
|
jyd = dny;
|
|
}
|
|
|
|
return this.curve.jpoint(jx, jyd.redMul(tinv), jz);
|
|
};
|
|
|
|
JPoint.prototype.dbl = function dbl() {
|
|
if (this.isInfinity())
|
|
return this;
|
|
|
|
if (this.curve.zeroA)
|
|
return this._zeroDbl();
|
|
else if (this.curve.threeA)
|
|
return this._threeDbl();
|
|
else
|
|
return this._dbl();
|
|
};
|
|
|
|
JPoint.prototype._zeroDbl = function _zeroDbl() {
|
|
var nx;
|
|
var ny;
|
|
var nz;
|
|
// Z = 1
|
|
if (this.zOne) {
|
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
|
|
// #doubling-mdbl-2007-bl
|
|
// 1M + 5S + 14A
|
|
|
|
// XX = X1^2
|
|
var xx = this.x.redSqr();
|
|
// YY = Y1^2
|
|
var yy = this.y.redSqr();
|
|
// YYYY = YY^2
|
|
var yyyy = yy.redSqr();
|
|
// S = 2 * ((X1 + YY)^2 - XX - YYYY)
|
|
var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
|
|
s = s.redIAdd(s);
|
|
// M = 3 * XX + a; a = 0
|
|
var m = xx.redAdd(xx).redIAdd(xx);
|
|
// T = M ^ 2 - 2*S
|
|
var t = m.redSqr().redISub(s).redISub(s);
|
|
|
|
// 8 * YYYY
|
|
var yyyy8 = yyyy.redIAdd(yyyy);
|
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
|
|
|
// X3 = T
|
|
nx = t;
|
|
// Y3 = M * (S - T) - 8 * YYYY
|
|
ny = m.redMul(s.redISub(t)).redISub(yyyy8);
|
|
// Z3 = 2*Y1
|
|
nz = this.y.redAdd(this.y);
|
|
} else {
|
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
|
|
// #doubling-dbl-2009-l
|
|
// 2M + 5S + 13A
|
|
|
|
// A = X1^2
|
|
var a = this.x.redSqr();
|
|
// B = Y1^2
|
|
var b = this.y.redSqr();
|
|
// C = B^2
|
|
var c = b.redSqr();
|
|
// D = 2 * ((X1 + B)^2 - A - C)
|
|
var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c);
|
|
d = d.redIAdd(d);
|
|
// E = 3 * A
|
|
var e = a.redAdd(a).redIAdd(a);
|
|
// F = E^2
|
|
var f = e.redSqr();
|
|
|
|
// 8 * C
|
|
var c8 = c.redIAdd(c);
|
|
c8 = c8.redIAdd(c8);
|
|
c8 = c8.redIAdd(c8);
|
|
|
|
// X3 = F - 2 * D
|
|
nx = f.redISub(d).redISub(d);
|
|
// Y3 = E * (D - X3) - 8 * C
|
|
ny = e.redMul(d.redISub(nx)).redISub(c8);
|
|
// Z3 = 2 * Y1 * Z1
|
|
nz = this.y.redMul(this.z);
|
|
nz = nz.redIAdd(nz);
|
|
}
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype._threeDbl = function _threeDbl() {
|
|
var nx;
|
|
var ny;
|
|
var nz;
|
|
// Z = 1
|
|
if (this.zOne) {
|
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html
|
|
// #doubling-mdbl-2007-bl
|
|
// 1M + 5S + 15A
|
|
|
|
// XX = X1^2
|
|
var xx = this.x.redSqr();
|
|
// YY = Y1^2
|
|
var yy = this.y.redSqr();
|
|
// YYYY = YY^2
|
|
var yyyy = yy.redSqr();
|
|
// S = 2 * ((X1 + YY)^2 - XX - YYYY)
|
|
var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
|
|
s = s.redIAdd(s);
|
|
// M = 3 * XX + a
|
|
var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a);
|
|
// T = M^2 - 2 * S
|
|
var t = m.redSqr().redISub(s).redISub(s);
|
|
// X3 = T
|
|
nx = t;
|
|
// Y3 = M * (S - T) - 8 * YYYY
|
|
var yyyy8 = yyyy.redIAdd(yyyy);
|
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
|
ny = m.redMul(s.redISub(t)).redISub(yyyy8);
|
|
// Z3 = 2 * Y1
|
|
nz = this.y.redAdd(this.y);
|
|
} else {
|
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
|
|
// 3M + 5S
|
|
|
|
// delta = Z1^2
|
|
var delta = this.z.redSqr();
|
|
// gamma = Y1^2
|
|
var gamma = this.y.redSqr();
|
|
// beta = X1 * gamma
|
|
var beta = this.x.redMul(gamma);
|
|
// alpha = 3 * (X1 - delta) * (X1 + delta)
|
|
var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta));
|
|
alpha = alpha.redAdd(alpha).redIAdd(alpha);
|
|
// X3 = alpha^2 - 8 * beta
|
|
var beta4 = beta.redIAdd(beta);
|
|
beta4 = beta4.redIAdd(beta4);
|
|
var beta8 = beta4.redAdd(beta4);
|
|
nx = alpha.redSqr().redISub(beta8);
|
|
// Z3 = (Y1 + Z1)^2 - gamma - delta
|
|
nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta);
|
|
// Y3 = alpha * (4 * beta - X3) - 8 * gamma^2
|
|
var ggamma8 = gamma.redSqr();
|
|
ggamma8 = ggamma8.redIAdd(ggamma8);
|
|
ggamma8 = ggamma8.redIAdd(ggamma8);
|
|
ggamma8 = ggamma8.redIAdd(ggamma8);
|
|
ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8);
|
|
}
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype._dbl = function _dbl() {
|
|
var a = this.curve.a;
|
|
|
|
// 4M + 6S + 10A
|
|
var jx = this.x;
|
|
var jy = this.y;
|
|
var jz = this.z;
|
|
var jz4 = jz.redSqr().redSqr();
|
|
|
|
var jx2 = jx.redSqr();
|
|
var jy2 = jy.redSqr();
|
|
|
|
var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4));
|
|
|
|
var jxd4 = jx.redAdd(jx);
|
|
jxd4 = jxd4.redIAdd(jxd4);
|
|
var t1 = jxd4.redMul(jy2);
|
|
var nx = c.redSqr().redISub(t1.redAdd(t1));
|
|
var t2 = t1.redISub(nx);
|
|
|
|
var jyd8 = jy2.redSqr();
|
|
jyd8 = jyd8.redIAdd(jyd8);
|
|
jyd8 = jyd8.redIAdd(jyd8);
|
|
jyd8 = jyd8.redIAdd(jyd8);
|
|
var ny = c.redMul(t2).redISub(jyd8);
|
|
var nz = jy.redAdd(jy).redMul(jz);
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype.trpl = function trpl() {
|
|
if (!this.curve.zeroA)
|
|
return this.dbl().add(this);
|
|
|
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl
|
|
// 5M + 10S + ...
|
|
|
|
// XX = X1^2
|
|
var xx = this.x.redSqr();
|
|
// YY = Y1^2
|
|
var yy = this.y.redSqr();
|
|
// ZZ = Z1^2
|
|
var zz = this.z.redSqr();
|
|
// YYYY = YY^2
|
|
var yyyy = yy.redSqr();
|
|
// M = 3 * XX + a * ZZ2; a = 0
|
|
var m = xx.redAdd(xx).redIAdd(xx);
|
|
// MM = M^2
|
|
var mm = m.redSqr();
|
|
// E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM
|
|
var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
|
|
e = e.redIAdd(e);
|
|
e = e.redAdd(e).redIAdd(e);
|
|
e = e.redISub(mm);
|
|
// EE = E^2
|
|
var ee = e.redSqr();
|
|
// T = 16*YYYY
|
|
var t = yyyy.redIAdd(yyyy);
|
|
t = t.redIAdd(t);
|
|
t = t.redIAdd(t);
|
|
t = t.redIAdd(t);
|
|
// U = (M + E)^2 - MM - EE - T
|
|
var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t);
|
|
// X3 = 4 * (X1 * EE - 4 * YY * U)
|
|
var yyu4 = yy.redMul(u);
|
|
yyu4 = yyu4.redIAdd(yyu4);
|
|
yyu4 = yyu4.redIAdd(yyu4);
|
|
var nx = this.x.redMul(ee).redISub(yyu4);
|
|
nx = nx.redIAdd(nx);
|
|
nx = nx.redIAdd(nx);
|
|
// Y3 = 8 * Y1 * (U * (T - U) - E * EE)
|
|
var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee)));
|
|
ny = ny.redIAdd(ny);
|
|
ny = ny.redIAdd(ny);
|
|
ny = ny.redIAdd(ny);
|
|
// Z3 = (Z1 + E)^2 - ZZ - EE
|
|
var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee);
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype.mul = function mul(k, kbase) {
|
|
k = new BN(k, kbase);
|
|
|
|
return this.curve._wnafMul(this, k);
|
|
};
|
|
|
|
JPoint.prototype.eq = function eq(p) {
|
|
if (p.type === 'affine')
|
|
return this.eq(p.toJ());
|
|
|
|
if (this === p)
|
|
return true;
|
|
|
|
// x1 * z2^2 == x2 * z1^2
|
|
var z2 = this.z.redSqr();
|
|
var pz2 = p.z.redSqr();
|
|
if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0)
|
|
return false;
|
|
|
|
// y1 * z2^3 == y2 * z1^3
|
|
var z3 = z2.redMul(this.z);
|
|
var pz3 = pz2.redMul(p.z);
|
|
return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0;
|
|
};
|
|
|
|
JPoint.prototype.eqXToP = function eqXToP(x) {
|
|
var zs = this.z.redSqr();
|
|
var rx = x.toRed(this.curve.red).redMul(zs);
|
|
if (this.x.cmp(rx) === 0)
|
|
return true;
|
|
|
|
var xc = x.clone();
|
|
var t = this.curve.redN.redMul(zs);
|
|
for (;;) {
|
|
xc.iadd(this.curve.n);
|
|
if (xc.cmp(this.curve.p) >= 0)
|
|
return false;
|
|
|
|
rx.redIAdd(t);
|
|
if (this.x.cmp(rx) === 0)
|
|
return true;
|
|
}
|
|
};
|
|
|
|
JPoint.prototype.inspect = function inspect() {
|
|
if (this.isInfinity())
|
|
return '<EC JPoint Infinity>';
|
|
return '<EC JPoint x: ' + this.x.toString(16, 2) +
|
|
' y: ' + this.y.toString(16, 2) +
|
|
' z: ' + this.z.toString(16, 2) + '>';
|
|
};
|
|
|
|
JPoint.prototype.isInfinity = function isInfinity() {
|
|
// XXX This code assumes that zero is always zero in red
|
|
return this.z.cmpn(0) === 0;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/curves.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/curves.js ***!
|
|
\******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var curves = exports;
|
|
|
|
var hash = __webpack_require__(/*! hash.js */ "./node_modules/hash.js/lib/hash.js");
|
|
var curve = __webpack_require__(/*! ./curve */ "./node_modules/elliptic/lib/elliptic/curve/index.js");
|
|
var utils = __webpack_require__(/*! ./utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
|
|
var assert = utils.assert;
|
|
|
|
function PresetCurve(options) {
|
|
if (options.type === 'short')
|
|
this.curve = new curve.short(options);
|
|
else if (options.type === 'edwards')
|
|
this.curve = new curve.edwards(options);
|
|
else
|
|
this.curve = new curve.mont(options);
|
|
this.g = this.curve.g;
|
|
this.n = this.curve.n;
|
|
this.hash = options.hash;
|
|
|
|
assert(this.g.validate(), 'Invalid curve');
|
|
assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, G*N != O');
|
|
}
|
|
curves.PresetCurve = PresetCurve;
|
|
|
|
function defineCurve(name, options) {
|
|
Object.defineProperty(curves, name, {
|
|
configurable: true,
|
|
enumerable: true,
|
|
get: function() {
|
|
var curve = new PresetCurve(options);
|
|
Object.defineProperty(curves, name, {
|
|
configurable: true,
|
|
enumerable: true,
|
|
value: curve,
|
|
});
|
|
return curve;
|
|
},
|
|
});
|
|
}
|
|
|
|
defineCurve('p192', {
|
|
type: 'short',
|
|
prime: 'p192',
|
|
p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff',
|
|
a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc',
|
|
b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1',
|
|
n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831',
|
|
hash: hash.sha256,
|
|
gRed: false,
|
|
g: [
|
|
'188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012',
|
|
'07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811',
|
|
],
|
|
});
|
|
|
|
defineCurve('p224', {
|
|
type: 'short',
|
|
prime: 'p224',
|
|
p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001',
|
|
a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe',
|
|
b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4',
|
|
n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d',
|
|
hash: hash.sha256,
|
|
gRed: false,
|
|
g: [
|
|
'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21',
|
|
'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34',
|
|
],
|
|
});
|
|
|
|
defineCurve('p256', {
|
|
type: 'short',
|
|
prime: null,
|
|
p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff',
|
|
a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc',
|
|
b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b',
|
|
n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551',
|
|
hash: hash.sha256,
|
|
gRed: false,
|
|
g: [
|
|
'6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296',
|
|
'4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5',
|
|
],
|
|
});
|
|
|
|
defineCurve('p384', {
|
|
type: 'short',
|
|
prime: null,
|
|
p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'fffffffe ffffffff 00000000 00000000 ffffffff',
|
|
a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'fffffffe ffffffff 00000000 00000000 fffffffc',
|
|
b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' +
|
|
'5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef',
|
|
n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' +
|
|
'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973',
|
|
hash: hash.sha384,
|
|
gRed: false,
|
|
g: [
|
|
'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' +
|
|
'5502f25d bf55296c 3a545e38 72760ab7',
|
|
'3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' +
|
|
'0a60b1ce 1d7e819d 7a431d7c 90ea0e5f',
|
|
],
|
|
});
|
|
|
|
defineCurve('p521', {
|
|
type: 'short',
|
|
prime: null,
|
|
p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff',
|
|
a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'ffffffff ffffffff ffffffff ffffffff fffffffc',
|
|
b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' +
|
|
'99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' +
|
|
'3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00',
|
|
n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' +
|
|
'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409',
|
|
hash: hash.sha512,
|
|
gRed: false,
|
|
g: [
|
|
'000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' +
|
|
'053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' +
|
|
'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66',
|
|
'00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' +
|
|
'579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' +
|
|
'3fad0761 353c7086 a272c240 88be9476 9fd16650',
|
|
],
|
|
});
|
|
|
|
defineCurve('curve25519', {
|
|
type: 'mont',
|
|
prime: 'p25519',
|
|
p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed',
|
|
a: '76d06',
|
|
b: '1',
|
|
n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed',
|
|
hash: hash.sha256,
|
|
gRed: false,
|
|
g: [
|
|
'9',
|
|
],
|
|
});
|
|
|
|
defineCurve('ed25519', {
|
|
type: 'edwards',
|
|
prime: 'p25519',
|
|
p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed',
|
|
a: '-1',
|
|
c: '1',
|
|
// -121665 * (121666^(-1)) (mod P)
|
|
d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3',
|
|
n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed',
|
|
hash: hash.sha256,
|
|
gRed: false,
|
|
g: [
|
|
'216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a',
|
|
|
|
// 4/5
|
|
'6666666666666666666666666666666666666666666666666666666666666658',
|
|
],
|
|
});
|
|
|
|
var pre;
|
|
try {
|
|
pre = __webpack_require__(/*! ./precomputed/secp256k1 */ "./node_modules/elliptic/lib/elliptic/precomputed/secp256k1.js");
|
|
} catch (e) {
|
|
pre = undefined;
|
|
}
|
|
|
|
defineCurve('secp256k1', {
|
|
type: 'short',
|
|
prime: 'k256',
|
|
p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f',
|
|
a: '0',
|
|
b: '7',
|
|
n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141',
|
|
h: '1',
|
|
hash: hash.sha256,
|
|
|
|
// Precomputed endomorphism
|
|
beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee',
|
|
lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72',
|
|
basis: [
|
|
{
|
|
a: '3086d221a7d46bcde86c90e49284eb15',
|
|
b: '-e4437ed6010e88286f547fa90abfe4c3',
|
|
},
|
|
{
|
|
a: '114ca50f7a8e2f3f657c1108d9d44cfd8',
|
|
b: '3086d221a7d46bcde86c90e49284eb15',
|
|
},
|
|
],
|
|
|
|
gRed: false,
|
|
g: [
|
|
'79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
|
|
'483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8',
|
|
pre,
|
|
],
|
|
});
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/ec/index.js":
|
|
/*!********************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/ec/index.js ***!
|
|
\********************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/elliptic/node_modules/bn.js/lib/bn.js");
|
|
var HmacDRBG = __webpack_require__(/*! hmac-drbg */ "./node_modules/hmac-drbg/lib/hmac-drbg.js");
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
var curves = __webpack_require__(/*! ../curves */ "./node_modules/elliptic/lib/elliptic/curves.js");
|
|
var rand = __webpack_require__(/*! brorand */ "./node_modules/brorand/index.js");
|
|
var assert = utils.assert;
|
|
|
|
var KeyPair = __webpack_require__(/*! ./key */ "./node_modules/elliptic/lib/elliptic/ec/key.js");
|
|
var Signature = __webpack_require__(/*! ./signature */ "./node_modules/elliptic/lib/elliptic/ec/signature.js");
|
|
|
|
function EC(options) {
|
|
if (!(this instanceof EC))
|
|
return new EC(options);
|
|
|
|
// Shortcut `elliptic.ec(curve-name)`
|
|
if (typeof options === 'string') {
|
|
assert(Object.prototype.hasOwnProperty.call(curves, options),
|
|
'Unknown curve ' + options);
|
|
|
|
options = curves[options];
|
|
}
|
|
|
|
// Shortcut for `elliptic.ec(elliptic.curves.curveName)`
|
|
if (options instanceof curves.PresetCurve)
|
|
options = { curve: options };
|
|
|
|
this.curve = options.curve.curve;
|
|
this.n = this.curve.n;
|
|
this.nh = this.n.ushrn(1);
|
|
this.g = this.curve.g;
|
|
|
|
// Point on curve
|
|
this.g = options.curve.g;
|
|
this.g.precompute(options.curve.n.bitLength() + 1);
|
|
|
|
// Hash for function for DRBG
|
|
this.hash = options.hash || options.curve.hash;
|
|
}
|
|
module.exports = EC;
|
|
|
|
EC.prototype.keyPair = function keyPair(options) {
|
|
return new KeyPair(this, options);
|
|
};
|
|
|
|
EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) {
|
|
return KeyPair.fromPrivate(this, priv, enc);
|
|
};
|
|
|
|
EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) {
|
|
return KeyPair.fromPublic(this, pub, enc);
|
|
};
|
|
|
|
EC.prototype.genKeyPair = function genKeyPair(options) {
|
|
if (!options)
|
|
options = {};
|
|
|
|
// Instantiate Hmac_DRBG
|
|
var drbg = new HmacDRBG({
|
|
hash: this.hash,
|
|
pers: options.pers,
|
|
persEnc: options.persEnc || 'utf8',
|
|
entropy: options.entropy || rand(this.hash.hmacStrength),
|
|
entropyEnc: options.entropy && options.entropyEnc || 'utf8',
|
|
nonce: this.n.toArray(),
|
|
});
|
|
|
|
var bytes = this.n.byteLength();
|
|
var ns2 = this.n.sub(new BN(2));
|
|
for (;;) {
|
|
var priv = new BN(drbg.generate(bytes));
|
|
if (priv.cmp(ns2) > 0)
|
|
continue;
|
|
|
|
priv.iaddn(1);
|
|
return this.keyFromPrivate(priv);
|
|
}
|
|
};
|
|
|
|
EC.prototype._truncateToN = function _truncateToN(msg, truncOnly) {
|
|
var delta = msg.byteLength() * 8 - this.n.bitLength();
|
|
if (delta > 0)
|
|
msg = msg.ushrn(delta);
|
|
if (!truncOnly && msg.cmp(this.n) >= 0)
|
|
return msg.sub(this.n);
|
|
else
|
|
return msg;
|
|
};
|
|
|
|
EC.prototype.sign = function sign(msg, key, enc, options) {
|
|
if (typeof enc === 'object') {
|
|
options = enc;
|
|
enc = null;
|
|
}
|
|
if (!options)
|
|
options = {};
|
|
|
|
key = this.keyFromPrivate(key, enc);
|
|
msg = this._truncateToN(new BN(msg, 16));
|
|
|
|
// Zero-extend key to provide enough entropy
|
|
var bytes = this.n.byteLength();
|
|
var bkey = key.getPrivate().toArray('be', bytes);
|
|
|
|
// Zero-extend nonce to have the same byte size as N
|
|
var nonce = msg.toArray('be', bytes);
|
|
|
|
// Instantiate Hmac_DRBG
|
|
var drbg = new HmacDRBG({
|
|
hash: this.hash,
|
|
entropy: bkey,
|
|
nonce: nonce,
|
|
pers: options.pers,
|
|
persEnc: options.persEnc || 'utf8',
|
|
});
|
|
|
|
// Number of bytes to generate
|
|
var ns1 = this.n.sub(new BN(1));
|
|
|
|
for (var iter = 0; ; iter++) {
|
|
var k = options.k ?
|
|
options.k(iter) :
|
|
new BN(drbg.generate(this.n.byteLength()));
|
|
k = this._truncateToN(k, true);
|
|
if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0)
|
|
continue;
|
|
|
|
var kp = this.g.mul(k);
|
|
if (kp.isInfinity())
|
|
continue;
|
|
|
|
var kpX = kp.getX();
|
|
var r = kpX.umod(this.n);
|
|
if (r.cmpn(0) === 0)
|
|
continue;
|
|
|
|
var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg));
|
|
s = s.umod(this.n);
|
|
if (s.cmpn(0) === 0)
|
|
continue;
|
|
|
|
var recoveryParam = (kp.getY().isOdd() ? 1 : 0) |
|
|
(kpX.cmp(r) !== 0 ? 2 : 0);
|
|
|
|
// Use complement of `s`, if it is > `n / 2`
|
|
if (options.canonical && s.cmp(this.nh) > 0) {
|
|
s = this.n.sub(s);
|
|
recoveryParam ^= 1;
|
|
}
|
|
|
|
return new Signature({ r: r, s: s, recoveryParam: recoveryParam });
|
|
}
|
|
};
|
|
|
|
EC.prototype.verify = function verify(msg, signature, key, enc) {
|
|
msg = this._truncateToN(new BN(msg, 16));
|
|
key = this.keyFromPublic(key, enc);
|
|
signature = new Signature(signature, 'hex');
|
|
|
|
// Perform primitive values validation
|
|
var r = signature.r;
|
|
var s = signature.s;
|
|
if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0)
|
|
return false;
|
|
if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0)
|
|
return false;
|
|
|
|
// Validate signature
|
|
var sinv = s.invm(this.n);
|
|
var u1 = sinv.mul(msg).umod(this.n);
|
|
var u2 = sinv.mul(r).umod(this.n);
|
|
var p;
|
|
|
|
if (!this.curve._maxwellTrick) {
|
|
p = this.g.mulAdd(u1, key.getPublic(), u2);
|
|
if (p.isInfinity())
|
|
return false;
|
|
|
|
return p.getX().umod(this.n).cmp(r) === 0;
|
|
}
|
|
|
|
// NOTE: Greg Maxwell's trick, inspired by:
|
|
// https://git.io/vad3K
|
|
|
|
p = this.g.jmulAdd(u1, key.getPublic(), u2);
|
|
if (p.isInfinity())
|
|
return false;
|
|
|
|
// Compare `p.x` of Jacobian point with `r`,
|
|
// this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the
|
|
// inverse of `p.z^2`
|
|
return p.eqXToP(r);
|
|
};
|
|
|
|
EC.prototype.recoverPubKey = function(msg, signature, j, enc) {
|
|
assert((3 & j) === j, 'The recovery param is more than two bits');
|
|
signature = new Signature(signature, enc);
|
|
|
|
var n = this.n;
|
|
var e = new BN(msg);
|
|
var r = signature.r;
|
|
var s = signature.s;
|
|
|
|
// A set LSB signifies that the y-coordinate is odd
|
|
var isYOdd = j & 1;
|
|
var isSecondKey = j >> 1;
|
|
if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey)
|
|
throw new Error('Unable to find sencond key candinate');
|
|
|
|
// 1.1. Let x = r + jn.
|
|
if (isSecondKey)
|
|
r = this.curve.pointFromX(r.add(this.curve.n), isYOdd);
|
|
else
|
|
r = this.curve.pointFromX(r, isYOdd);
|
|
|
|
var rInv = signature.r.invm(n);
|
|
var s1 = n.sub(e).mul(rInv).umod(n);
|
|
var s2 = s.mul(rInv).umod(n);
|
|
|
|
// 1.6.1 Compute Q = r^-1 (sR - eG)
|
|
// Q = r^-1 (sR + -eG)
|
|
return this.g.mulAdd(s1, r, s2);
|
|
};
|
|
|
|
EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) {
|
|
signature = new Signature(signature, enc);
|
|
if (signature.recoveryParam !== null)
|
|
return signature.recoveryParam;
|
|
|
|
for (var i = 0; i < 4; i++) {
|
|
var Qprime;
|
|
try {
|
|
Qprime = this.recoverPubKey(e, signature, i);
|
|
} catch (e) {
|
|
continue;
|
|
}
|
|
|
|
if (Qprime.eq(Q))
|
|
return i;
|
|
}
|
|
throw new Error('Unable to find valid recovery factor');
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/ec/key.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/ec/key.js ***!
|
|
\******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/elliptic/node_modules/bn.js/lib/bn.js");
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
var assert = utils.assert;
|
|
|
|
function KeyPair(ec, options) {
|
|
this.ec = ec;
|
|
this.priv = null;
|
|
this.pub = null;
|
|
|
|
// KeyPair(ec, { priv: ..., pub: ... })
|
|
if (options.priv)
|
|
this._importPrivate(options.priv, options.privEnc);
|
|
if (options.pub)
|
|
this._importPublic(options.pub, options.pubEnc);
|
|
}
|
|
module.exports = KeyPair;
|
|
|
|
KeyPair.fromPublic = function fromPublic(ec, pub, enc) {
|
|
if (pub instanceof KeyPair)
|
|
return pub;
|
|
|
|
return new KeyPair(ec, {
|
|
pub: pub,
|
|
pubEnc: enc,
|
|
});
|
|
};
|
|
|
|
KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) {
|
|
if (priv instanceof KeyPair)
|
|
return priv;
|
|
|
|
return new KeyPair(ec, {
|
|
priv: priv,
|
|
privEnc: enc,
|
|
});
|
|
};
|
|
|
|
KeyPair.prototype.validate = function validate() {
|
|
var pub = this.getPublic();
|
|
|
|
if (pub.isInfinity())
|
|
return { result: false, reason: 'Invalid public key' };
|
|
if (!pub.validate())
|
|
return { result: false, reason: 'Public key is not a point' };
|
|
if (!pub.mul(this.ec.curve.n).isInfinity())
|
|
return { result: false, reason: 'Public key * N != O' };
|
|
|
|
return { result: true, reason: null };
|
|
};
|
|
|
|
KeyPair.prototype.getPublic = function getPublic(compact, enc) {
|
|
// compact is optional argument
|
|
if (typeof compact === 'string') {
|
|
enc = compact;
|
|
compact = null;
|
|
}
|
|
|
|
if (!this.pub)
|
|
this.pub = this.ec.g.mul(this.priv);
|
|
|
|
if (!enc)
|
|
return this.pub;
|
|
|
|
return this.pub.encode(enc, compact);
|
|
};
|
|
|
|
KeyPair.prototype.getPrivate = function getPrivate(enc) {
|
|
if (enc === 'hex')
|
|
return this.priv.toString(16, 2);
|
|
else
|
|
return this.priv;
|
|
};
|
|
|
|
KeyPair.prototype._importPrivate = function _importPrivate(key, enc) {
|
|
this.priv = new BN(key, enc || 16);
|
|
|
|
// Ensure that the priv won't be bigger than n, otherwise we may fail
|
|
// in fixed multiplication method
|
|
this.priv = this.priv.umod(this.ec.curve.n);
|
|
};
|
|
|
|
KeyPair.prototype._importPublic = function _importPublic(key, enc) {
|
|
if (key.x || key.y) {
|
|
// Montgomery points only have an `x` coordinate.
|
|
// Weierstrass/Edwards points on the other hand have both `x` and
|
|
// `y` coordinates.
|
|
if (this.ec.curve.type === 'mont') {
|
|
assert(key.x, 'Need x coordinate');
|
|
} else if (this.ec.curve.type === 'short' ||
|
|
this.ec.curve.type === 'edwards') {
|
|
assert(key.x && key.y, 'Need both x and y coordinate');
|
|
}
|
|
this.pub = this.ec.curve.point(key.x, key.y);
|
|
return;
|
|
}
|
|
this.pub = this.ec.curve.decodePoint(key, enc);
|
|
};
|
|
|
|
// ECDH
|
|
KeyPair.prototype.derive = function derive(pub) {
|
|
if(!pub.validate()) {
|
|
assert(pub.validate(), 'public point not validated');
|
|
}
|
|
return pub.mul(this.priv).getX();
|
|
};
|
|
|
|
// ECDSA
|
|
KeyPair.prototype.sign = function sign(msg, enc, options) {
|
|
return this.ec.sign(msg, this, enc, options);
|
|
};
|
|
|
|
KeyPair.prototype.verify = function verify(msg, signature) {
|
|
return this.ec.verify(msg, signature, this);
|
|
};
|
|
|
|
KeyPair.prototype.inspect = function inspect() {
|
|
return '<Key priv: ' + (this.priv && this.priv.toString(16, 2)) +
|
|
' pub: ' + (this.pub && this.pub.inspect()) + ' >';
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/ec/signature.js":
|
|
/*!************************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/ec/signature.js ***!
|
|
\************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/elliptic/node_modules/bn.js/lib/bn.js");
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
var assert = utils.assert;
|
|
|
|
function Signature(options, enc) {
|
|
if (options instanceof Signature)
|
|
return options;
|
|
|
|
if (this._importDER(options, enc))
|
|
return;
|
|
|
|
assert(options.r && options.s, 'Signature without r or s');
|
|
this.r = new BN(options.r, 16);
|
|
this.s = new BN(options.s, 16);
|
|
if (options.recoveryParam === undefined)
|
|
this.recoveryParam = null;
|
|
else
|
|
this.recoveryParam = options.recoveryParam;
|
|
}
|
|
module.exports = Signature;
|
|
|
|
function Position() {
|
|
this.place = 0;
|
|
}
|
|
|
|
function getLength(buf, p) {
|
|
var initial = buf[p.place++];
|
|
if (!(initial & 0x80)) {
|
|
return initial;
|
|
}
|
|
var octetLen = initial & 0xf;
|
|
|
|
// Indefinite length or overflow
|
|
if (octetLen === 0 || octetLen > 4) {
|
|
return false;
|
|
}
|
|
|
|
var val = 0;
|
|
for (var i = 0, off = p.place; i < octetLen; i++, off++) {
|
|
val <<= 8;
|
|
val |= buf[off];
|
|
val >>>= 0;
|
|
}
|
|
|
|
// Leading zeroes
|
|
if (val <= 0x7f) {
|
|
return false;
|
|
}
|
|
|
|
p.place = off;
|
|
return val;
|
|
}
|
|
|
|
function rmPadding(buf) {
|
|
var i = 0;
|
|
var len = buf.length - 1;
|
|
while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) {
|
|
i++;
|
|
}
|
|
if (i === 0) {
|
|
return buf;
|
|
}
|
|
return buf.slice(i);
|
|
}
|
|
|
|
Signature.prototype._importDER = function _importDER(data, enc) {
|
|
data = utils.toArray(data, enc);
|
|
var p = new Position();
|
|
if (data[p.place++] !== 0x30) {
|
|
return false;
|
|
}
|
|
var len = getLength(data, p);
|
|
if (len === false) {
|
|
return false;
|
|
}
|
|
if ((len + p.place) !== data.length) {
|
|
return false;
|
|
}
|
|
if (data[p.place++] !== 0x02) {
|
|
return false;
|
|
}
|
|
var rlen = getLength(data, p);
|
|
if (rlen === false) {
|
|
return false;
|
|
}
|
|
var r = data.slice(p.place, rlen + p.place);
|
|
p.place += rlen;
|
|
if (data[p.place++] !== 0x02) {
|
|
return false;
|
|
}
|
|
var slen = getLength(data, p);
|
|
if (slen === false) {
|
|
return false;
|
|
}
|
|
if (data.length !== slen + p.place) {
|
|
return false;
|
|
}
|
|
var s = data.slice(p.place, slen + p.place);
|
|
if (r[0] === 0) {
|
|
if (r[1] & 0x80) {
|
|
r = r.slice(1);
|
|
} else {
|
|
// Leading zeroes
|
|
return false;
|
|
}
|
|
}
|
|
if (s[0] === 0) {
|
|
if (s[1] & 0x80) {
|
|
s = s.slice(1);
|
|
} else {
|
|
// Leading zeroes
|
|
return false;
|
|
}
|
|
}
|
|
|
|
this.r = new BN(r);
|
|
this.s = new BN(s);
|
|
this.recoveryParam = null;
|
|
|
|
return true;
|
|
};
|
|
|
|
function constructLength(arr, len) {
|
|
if (len < 0x80) {
|
|
arr.push(len);
|
|
return;
|
|
}
|
|
var octets = 1 + (Math.log(len) / Math.LN2 >>> 3);
|
|
arr.push(octets | 0x80);
|
|
while (--octets) {
|
|
arr.push((len >>> (octets << 3)) & 0xff);
|
|
}
|
|
arr.push(len);
|
|
}
|
|
|
|
Signature.prototype.toDER = function toDER(enc) {
|
|
var r = this.r.toArray();
|
|
var s = this.s.toArray();
|
|
|
|
// Pad values
|
|
if (r[0] & 0x80)
|
|
r = [ 0 ].concat(r);
|
|
// Pad values
|
|
if (s[0] & 0x80)
|
|
s = [ 0 ].concat(s);
|
|
|
|
r = rmPadding(r);
|
|
s = rmPadding(s);
|
|
|
|
while (!s[0] && !(s[1] & 0x80)) {
|
|
s = s.slice(1);
|
|
}
|
|
var arr = [ 0x02 ];
|
|
constructLength(arr, r.length);
|
|
arr = arr.concat(r);
|
|
arr.push(0x02);
|
|
constructLength(arr, s.length);
|
|
var backHalf = arr.concat(s);
|
|
var res = [ 0x30 ];
|
|
constructLength(res, backHalf.length);
|
|
res = res.concat(backHalf);
|
|
return utils.encode(res, enc);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/eddsa/index.js":
|
|
/*!***********************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/eddsa/index.js ***!
|
|
\***********************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var hash = __webpack_require__(/*! hash.js */ "./node_modules/hash.js/lib/hash.js");
|
|
var curves = __webpack_require__(/*! ../curves */ "./node_modules/elliptic/lib/elliptic/curves.js");
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
var assert = utils.assert;
|
|
var parseBytes = utils.parseBytes;
|
|
var KeyPair = __webpack_require__(/*! ./key */ "./node_modules/elliptic/lib/elliptic/eddsa/key.js");
|
|
var Signature = __webpack_require__(/*! ./signature */ "./node_modules/elliptic/lib/elliptic/eddsa/signature.js");
|
|
|
|
function EDDSA(curve) {
|
|
assert(curve === 'ed25519', 'only tested with ed25519 so far');
|
|
|
|
if (!(this instanceof EDDSA))
|
|
return new EDDSA(curve);
|
|
|
|
curve = curves[curve].curve;
|
|
this.curve = curve;
|
|
this.g = curve.g;
|
|
this.g.precompute(curve.n.bitLength() + 1);
|
|
|
|
this.pointClass = curve.point().constructor;
|
|
this.encodingLength = Math.ceil(curve.n.bitLength() / 8);
|
|
this.hash = hash.sha512;
|
|
}
|
|
|
|
module.exports = EDDSA;
|
|
|
|
/**
|
|
* @param {Array|String} message - message bytes
|
|
* @param {Array|String|KeyPair} secret - secret bytes or a keypair
|
|
* @returns {Signature} - signature
|
|
*/
|
|
EDDSA.prototype.sign = function sign(message, secret) {
|
|
message = parseBytes(message);
|
|
var key = this.keyFromSecret(secret);
|
|
var r = this.hashInt(key.messagePrefix(), message);
|
|
var R = this.g.mul(r);
|
|
var Rencoded = this.encodePoint(R);
|
|
var s_ = this.hashInt(Rencoded, key.pubBytes(), message)
|
|
.mul(key.priv());
|
|
var S = r.add(s_).umod(this.curve.n);
|
|
return this.makeSignature({ R: R, S: S, Rencoded: Rencoded });
|
|
};
|
|
|
|
/**
|
|
* @param {Array} message - message bytes
|
|
* @param {Array|String|Signature} sig - sig bytes
|
|
* @param {Array|String|Point|KeyPair} pub - public key
|
|
* @returns {Boolean} - true if public key matches sig of message
|
|
*/
|
|
EDDSA.prototype.verify = function verify(message, sig, pub) {
|
|
message = parseBytes(message);
|
|
sig = this.makeSignature(sig);
|
|
var key = this.keyFromPublic(pub);
|
|
var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message);
|
|
var SG = this.g.mul(sig.S());
|
|
var RplusAh = sig.R().add(key.pub().mul(h));
|
|
return RplusAh.eq(SG);
|
|
};
|
|
|
|
EDDSA.prototype.hashInt = function hashInt() {
|
|
var hash = this.hash();
|
|
for (var i = 0; i < arguments.length; i++)
|
|
hash.update(arguments[i]);
|
|
return utils.intFromLE(hash.digest()).umod(this.curve.n);
|
|
};
|
|
|
|
EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) {
|
|
return KeyPair.fromPublic(this, pub);
|
|
};
|
|
|
|
EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) {
|
|
return KeyPair.fromSecret(this, secret);
|
|
};
|
|
|
|
EDDSA.prototype.makeSignature = function makeSignature(sig) {
|
|
if (sig instanceof Signature)
|
|
return sig;
|
|
return new Signature(this, sig);
|
|
};
|
|
|
|
/**
|
|
* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2
|
|
*
|
|
* EDDSA defines methods for encoding and decoding points and integers. These are
|
|
* helper convenience methods, that pass along to utility functions implied
|
|
* parameters.
|
|
*
|
|
*/
|
|
EDDSA.prototype.encodePoint = function encodePoint(point) {
|
|
var enc = point.getY().toArray('le', this.encodingLength);
|
|
enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0;
|
|
return enc;
|
|
};
|
|
|
|
EDDSA.prototype.decodePoint = function decodePoint(bytes) {
|
|
bytes = utils.parseBytes(bytes);
|
|
|
|
var lastIx = bytes.length - 1;
|
|
var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80);
|
|
var xIsOdd = (bytes[lastIx] & 0x80) !== 0;
|
|
|
|
var y = utils.intFromLE(normed);
|
|
return this.curve.pointFromY(y, xIsOdd);
|
|
};
|
|
|
|
EDDSA.prototype.encodeInt = function encodeInt(num) {
|
|
return num.toArray('le', this.encodingLength);
|
|
};
|
|
|
|
EDDSA.prototype.decodeInt = function decodeInt(bytes) {
|
|
return utils.intFromLE(bytes);
|
|
};
|
|
|
|
EDDSA.prototype.isPoint = function isPoint(val) {
|
|
return val instanceof this.pointClass;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/eddsa/key.js":
|
|
/*!*********************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/eddsa/key.js ***!
|
|
\*********************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
var assert = utils.assert;
|
|
var parseBytes = utils.parseBytes;
|
|
var cachedProperty = utils.cachedProperty;
|
|
|
|
/**
|
|
* @param {EDDSA} eddsa - instance
|
|
* @param {Object} params - public/private key parameters
|
|
*
|
|
* @param {Array<Byte>} [params.secret] - secret seed bytes
|
|
* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms)
|
|
* @param {Array<Byte>} [params.pub] - public key point encoded as bytes
|
|
*
|
|
*/
|
|
function KeyPair(eddsa, params) {
|
|
this.eddsa = eddsa;
|
|
this._secret = parseBytes(params.secret);
|
|
if (eddsa.isPoint(params.pub))
|
|
this._pub = params.pub;
|
|
else
|
|
this._pubBytes = parseBytes(params.pub);
|
|
}
|
|
|
|
KeyPair.fromPublic = function fromPublic(eddsa, pub) {
|
|
if (pub instanceof KeyPair)
|
|
return pub;
|
|
return new KeyPair(eddsa, { pub: pub });
|
|
};
|
|
|
|
KeyPair.fromSecret = function fromSecret(eddsa, secret) {
|
|
if (secret instanceof KeyPair)
|
|
return secret;
|
|
return new KeyPair(eddsa, { secret: secret });
|
|
};
|
|
|
|
KeyPair.prototype.secret = function secret() {
|
|
return this._secret;
|
|
};
|
|
|
|
cachedProperty(KeyPair, 'pubBytes', function pubBytes() {
|
|
return this.eddsa.encodePoint(this.pub());
|
|
});
|
|
|
|
cachedProperty(KeyPair, 'pub', function pub() {
|
|
if (this._pubBytes)
|
|
return this.eddsa.decodePoint(this._pubBytes);
|
|
return this.eddsa.g.mul(this.priv());
|
|
});
|
|
|
|
cachedProperty(KeyPair, 'privBytes', function privBytes() {
|
|
var eddsa = this.eddsa;
|
|
var hash = this.hash();
|
|
var lastIx = eddsa.encodingLength - 1;
|
|
|
|
var a = hash.slice(0, eddsa.encodingLength);
|
|
a[0] &= 248;
|
|
a[lastIx] &= 127;
|
|
a[lastIx] |= 64;
|
|
|
|
return a;
|
|
});
|
|
|
|
cachedProperty(KeyPair, 'priv', function priv() {
|
|
return this.eddsa.decodeInt(this.privBytes());
|
|
});
|
|
|
|
cachedProperty(KeyPair, 'hash', function hash() {
|
|
return this.eddsa.hash().update(this.secret()).digest();
|
|
});
|
|
|
|
cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() {
|
|
return this.hash().slice(this.eddsa.encodingLength);
|
|
});
|
|
|
|
KeyPair.prototype.sign = function sign(message) {
|
|
assert(this._secret, 'KeyPair can only verify');
|
|
return this.eddsa.sign(message, this);
|
|
};
|
|
|
|
KeyPair.prototype.verify = function verify(message, sig) {
|
|
return this.eddsa.verify(message, sig, this);
|
|
};
|
|
|
|
KeyPair.prototype.getSecret = function getSecret(enc) {
|
|
assert(this._secret, 'KeyPair is public only');
|
|
return utils.encode(this.secret(), enc);
|
|
};
|
|
|
|
KeyPair.prototype.getPublic = function getPublic(enc) {
|
|
return utils.encode(this.pubBytes(), enc);
|
|
};
|
|
|
|
module.exports = KeyPair;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/eddsa/signature.js":
|
|
/*!***************************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/eddsa/signature.js ***!
|
|
\***************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/elliptic/node_modules/bn.js/lib/bn.js");
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/elliptic/lib/elliptic/utils.js");
|
|
var assert = utils.assert;
|
|
var cachedProperty = utils.cachedProperty;
|
|
var parseBytes = utils.parseBytes;
|
|
|
|
/**
|
|
* @param {EDDSA} eddsa - eddsa instance
|
|
* @param {Array<Bytes>|Object} sig -
|
|
* @param {Array<Bytes>|Point} [sig.R] - R point as Point or bytes
|
|
* @param {Array<Bytes>|bn} [sig.S] - S scalar as bn or bytes
|
|
* @param {Array<Bytes>} [sig.Rencoded] - R point encoded
|
|
* @param {Array<Bytes>} [sig.Sencoded] - S scalar encoded
|
|
*/
|
|
function Signature(eddsa, sig) {
|
|
this.eddsa = eddsa;
|
|
|
|
if (typeof sig !== 'object')
|
|
sig = parseBytes(sig);
|
|
|
|
if (Array.isArray(sig)) {
|
|
sig = {
|
|
R: sig.slice(0, eddsa.encodingLength),
|
|
S: sig.slice(eddsa.encodingLength),
|
|
};
|
|
}
|
|
|
|
assert(sig.R && sig.S, 'Signature without R or S');
|
|
|
|
if (eddsa.isPoint(sig.R))
|
|
this._R = sig.R;
|
|
if (sig.S instanceof BN)
|
|
this._S = sig.S;
|
|
|
|
this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded;
|
|
this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded;
|
|
}
|
|
|
|
cachedProperty(Signature, 'S', function S() {
|
|
return this.eddsa.decodeInt(this.Sencoded());
|
|
});
|
|
|
|
cachedProperty(Signature, 'R', function R() {
|
|
return this.eddsa.decodePoint(this.Rencoded());
|
|
});
|
|
|
|
cachedProperty(Signature, 'Rencoded', function Rencoded() {
|
|
return this.eddsa.encodePoint(this.R());
|
|
});
|
|
|
|
cachedProperty(Signature, 'Sencoded', function Sencoded() {
|
|
return this.eddsa.encodeInt(this.S());
|
|
});
|
|
|
|
Signature.prototype.toBytes = function toBytes() {
|
|
return this.Rencoded().concat(this.Sencoded());
|
|
};
|
|
|
|
Signature.prototype.toHex = function toHex() {
|
|
return utils.encode(this.toBytes(), 'hex').toUpperCase();
|
|
};
|
|
|
|
module.exports = Signature;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/precomputed/secp256k1.js":
|
|
/*!*********************************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/precomputed/secp256k1.js ***!
|
|
\*********************************************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = {
|
|
doubles: {
|
|
step: 4,
|
|
points: [
|
|
[
|
|
'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a',
|
|
'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821',
|
|
],
|
|
[
|
|
'8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508',
|
|
'11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf',
|
|
],
|
|
[
|
|
'175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739',
|
|
'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695',
|
|
],
|
|
[
|
|
'363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640',
|
|
'4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9',
|
|
],
|
|
[
|
|
'8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c',
|
|
'4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36',
|
|
],
|
|
[
|
|
'723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda',
|
|
'96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f',
|
|
],
|
|
[
|
|
'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa',
|
|
'5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999',
|
|
],
|
|
[
|
|
'100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0',
|
|
'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09',
|
|
],
|
|
[
|
|
'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d',
|
|
'9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d',
|
|
],
|
|
[
|
|
'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d',
|
|
'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088',
|
|
],
|
|
[
|
|
'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1',
|
|
'9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d',
|
|
],
|
|
[
|
|
'53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0',
|
|
'5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8',
|
|
],
|
|
[
|
|
'8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047',
|
|
'10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a',
|
|
],
|
|
[
|
|
'385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862',
|
|
'283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453',
|
|
],
|
|
[
|
|
'6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7',
|
|
'7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160',
|
|
],
|
|
[
|
|
'3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd',
|
|
'56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0',
|
|
],
|
|
[
|
|
'85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83',
|
|
'7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6',
|
|
],
|
|
[
|
|
'948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a',
|
|
'53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589',
|
|
],
|
|
[
|
|
'6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8',
|
|
'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17',
|
|
],
|
|
[
|
|
'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d',
|
|
'4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda',
|
|
],
|
|
[
|
|
'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725',
|
|
'7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd',
|
|
],
|
|
[
|
|
'213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754',
|
|
'4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2',
|
|
],
|
|
[
|
|
'4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c',
|
|
'17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6',
|
|
],
|
|
[
|
|
'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6',
|
|
'6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f',
|
|
],
|
|
[
|
|
'76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39',
|
|
'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01',
|
|
],
|
|
[
|
|
'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891',
|
|
'893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3',
|
|
],
|
|
[
|
|
'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b',
|
|
'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f',
|
|
],
|
|
[
|
|
'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03',
|
|
'2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7',
|
|
],
|
|
[
|
|
'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d',
|
|
'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78',
|
|
],
|
|
[
|
|
'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070',
|
|
'7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1',
|
|
],
|
|
[
|
|
'90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4',
|
|
'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150',
|
|
],
|
|
[
|
|
'8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da',
|
|
'662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82',
|
|
],
|
|
[
|
|
'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11',
|
|
'1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc',
|
|
],
|
|
[
|
|
'8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e',
|
|
'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b',
|
|
],
|
|
[
|
|
'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41',
|
|
'2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51',
|
|
],
|
|
[
|
|
'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef',
|
|
'67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45',
|
|
],
|
|
[
|
|
'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8',
|
|
'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120',
|
|
],
|
|
[
|
|
'324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d',
|
|
'648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84',
|
|
],
|
|
[
|
|
'4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96',
|
|
'35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d',
|
|
],
|
|
[
|
|
'9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd',
|
|
'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d',
|
|
],
|
|
[
|
|
'6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5',
|
|
'9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8',
|
|
],
|
|
[
|
|
'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266',
|
|
'40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8',
|
|
],
|
|
[
|
|
'7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71',
|
|
'34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac',
|
|
],
|
|
[
|
|
'928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac',
|
|
'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f',
|
|
],
|
|
[
|
|
'85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751',
|
|
'1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962',
|
|
],
|
|
[
|
|
'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e',
|
|
'493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907',
|
|
],
|
|
[
|
|
'827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241',
|
|
'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec',
|
|
],
|
|
[
|
|
'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3',
|
|
'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d',
|
|
],
|
|
[
|
|
'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f',
|
|
'4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414',
|
|
],
|
|
[
|
|
'1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19',
|
|
'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd',
|
|
],
|
|
[
|
|
'146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be',
|
|
'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0',
|
|
],
|
|
[
|
|
'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9',
|
|
'6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811',
|
|
],
|
|
[
|
|
'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2',
|
|
'8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1',
|
|
],
|
|
[
|
|
'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13',
|
|
'7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c',
|
|
],
|
|
[
|
|
'174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c',
|
|
'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73',
|
|
],
|
|
[
|
|
'959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba',
|
|
'2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd',
|
|
],
|
|
[
|
|
'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151',
|
|
'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405',
|
|
],
|
|
[
|
|
'64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073',
|
|
'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589',
|
|
],
|
|
[
|
|
'8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458',
|
|
'38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e',
|
|
],
|
|
[
|
|
'13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b',
|
|
'69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27',
|
|
],
|
|
[
|
|
'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366',
|
|
'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1',
|
|
],
|
|
[
|
|
'8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa',
|
|
'40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482',
|
|
],
|
|
[
|
|
'8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0',
|
|
'620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945',
|
|
],
|
|
[
|
|
'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787',
|
|
'7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573',
|
|
],
|
|
[
|
|
'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e',
|
|
'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82',
|
|
],
|
|
],
|
|
},
|
|
naf: {
|
|
wnd: 7,
|
|
points: [
|
|
[
|
|
'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9',
|
|
'388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672',
|
|
],
|
|
[
|
|
'2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4',
|
|
'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6',
|
|
],
|
|
[
|
|
'5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc',
|
|
'6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da',
|
|
],
|
|
[
|
|
'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe',
|
|
'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37',
|
|
],
|
|
[
|
|
'774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb',
|
|
'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b',
|
|
],
|
|
[
|
|
'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8',
|
|
'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81',
|
|
],
|
|
[
|
|
'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e',
|
|
'581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58',
|
|
],
|
|
[
|
|
'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34',
|
|
'4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77',
|
|
],
|
|
[
|
|
'2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c',
|
|
'85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a',
|
|
],
|
|
[
|
|
'352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5',
|
|
'321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c',
|
|
],
|
|
[
|
|
'2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f',
|
|
'2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67',
|
|
],
|
|
[
|
|
'9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714',
|
|
'73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402',
|
|
],
|
|
[
|
|
'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729',
|
|
'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55',
|
|
],
|
|
[
|
|
'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db',
|
|
'2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482',
|
|
],
|
|
[
|
|
'6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4',
|
|
'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82',
|
|
],
|
|
[
|
|
'1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5',
|
|
'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396',
|
|
],
|
|
[
|
|
'605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479',
|
|
'2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49',
|
|
],
|
|
[
|
|
'62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d',
|
|
'80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf',
|
|
],
|
|
[
|
|
'80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f',
|
|
'1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a',
|
|
],
|
|
[
|
|
'7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb',
|
|
'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7',
|
|
],
|
|
[
|
|
'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9',
|
|
'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933',
|
|
],
|
|
[
|
|
'49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963',
|
|
'758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a',
|
|
],
|
|
[
|
|
'77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74',
|
|
'958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6',
|
|
],
|
|
[
|
|
'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530',
|
|
'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37',
|
|
],
|
|
[
|
|
'463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b',
|
|
'5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e',
|
|
],
|
|
[
|
|
'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247',
|
|
'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6',
|
|
],
|
|
[
|
|
'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1',
|
|
'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476',
|
|
],
|
|
[
|
|
'2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120',
|
|
'4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40',
|
|
],
|
|
[
|
|
'7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435',
|
|
'91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61',
|
|
],
|
|
[
|
|
'754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18',
|
|
'673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683',
|
|
],
|
|
[
|
|
'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8',
|
|
'59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5',
|
|
],
|
|
[
|
|
'186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb',
|
|
'3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b',
|
|
],
|
|
[
|
|
'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f',
|
|
'55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417',
|
|
],
|
|
[
|
|
'5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143',
|
|
'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868',
|
|
],
|
|
[
|
|
'290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba',
|
|
'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a',
|
|
],
|
|
[
|
|
'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45',
|
|
'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6',
|
|
],
|
|
[
|
|
'766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a',
|
|
'744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996',
|
|
],
|
|
[
|
|
'59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e',
|
|
'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e',
|
|
],
|
|
[
|
|
'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8',
|
|
'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d',
|
|
],
|
|
[
|
|
'7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c',
|
|
'30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2',
|
|
],
|
|
[
|
|
'948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519',
|
|
'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e',
|
|
],
|
|
[
|
|
'7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab',
|
|
'100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437',
|
|
],
|
|
[
|
|
'3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca',
|
|
'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311',
|
|
],
|
|
[
|
|
'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf',
|
|
'8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4',
|
|
],
|
|
[
|
|
'1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610',
|
|
'68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575',
|
|
],
|
|
[
|
|
'733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4',
|
|
'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d',
|
|
],
|
|
[
|
|
'15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c',
|
|
'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d',
|
|
],
|
|
[
|
|
'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940',
|
|
'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629',
|
|
],
|
|
[
|
|
'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980',
|
|
'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06',
|
|
],
|
|
[
|
|
'311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3',
|
|
'66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374',
|
|
],
|
|
[
|
|
'34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf',
|
|
'9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee',
|
|
],
|
|
[
|
|
'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63',
|
|
'4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1',
|
|
],
|
|
[
|
|
'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448',
|
|
'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b',
|
|
],
|
|
[
|
|
'32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf',
|
|
'5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661',
|
|
],
|
|
[
|
|
'7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5',
|
|
'8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6',
|
|
],
|
|
[
|
|
'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6',
|
|
'8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e',
|
|
],
|
|
[
|
|
'16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5',
|
|
'5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d',
|
|
],
|
|
[
|
|
'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99',
|
|
'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc',
|
|
],
|
|
[
|
|
'78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51',
|
|
'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4',
|
|
],
|
|
[
|
|
'494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5',
|
|
'42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c',
|
|
],
|
|
[
|
|
'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5',
|
|
'204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b',
|
|
],
|
|
[
|
|
'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997',
|
|
'4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913',
|
|
],
|
|
[
|
|
'841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881',
|
|
'73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154',
|
|
],
|
|
[
|
|
'5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5',
|
|
'39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865',
|
|
],
|
|
[
|
|
'36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66',
|
|
'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc',
|
|
],
|
|
[
|
|
'336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726',
|
|
'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224',
|
|
],
|
|
[
|
|
'8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede',
|
|
'6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e',
|
|
],
|
|
[
|
|
'1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94',
|
|
'60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6',
|
|
],
|
|
[
|
|
'85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31',
|
|
'3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511',
|
|
],
|
|
[
|
|
'29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51',
|
|
'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b',
|
|
],
|
|
[
|
|
'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252',
|
|
'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2',
|
|
],
|
|
[
|
|
'4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5',
|
|
'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c',
|
|
],
|
|
[
|
|
'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b',
|
|
'6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3',
|
|
],
|
|
[
|
|
'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4',
|
|
'322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d',
|
|
],
|
|
[
|
|
'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f',
|
|
'6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700',
|
|
],
|
|
[
|
|
'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889',
|
|
'2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4',
|
|
],
|
|
[
|
|
'591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246',
|
|
'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196',
|
|
],
|
|
[
|
|
'11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984',
|
|
'998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4',
|
|
],
|
|
[
|
|
'3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a',
|
|
'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257',
|
|
],
|
|
[
|
|
'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030',
|
|
'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13',
|
|
],
|
|
[
|
|
'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197',
|
|
'6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096',
|
|
],
|
|
[
|
|
'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593',
|
|
'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38',
|
|
],
|
|
[
|
|
'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef',
|
|
'21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f',
|
|
],
|
|
[
|
|
'347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38',
|
|
'60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448',
|
|
],
|
|
[
|
|
'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a',
|
|
'49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a',
|
|
],
|
|
[
|
|
'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111',
|
|
'5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4',
|
|
],
|
|
[
|
|
'4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502',
|
|
'7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437',
|
|
],
|
|
[
|
|
'3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea',
|
|
'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7',
|
|
],
|
|
[
|
|
'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26',
|
|
'8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d',
|
|
],
|
|
[
|
|
'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986',
|
|
'39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a',
|
|
],
|
|
[
|
|
'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e',
|
|
'62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54',
|
|
],
|
|
[
|
|
'48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4',
|
|
'25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77',
|
|
],
|
|
[
|
|
'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda',
|
|
'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517',
|
|
],
|
|
[
|
|
'6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859',
|
|
'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10',
|
|
],
|
|
[
|
|
'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f',
|
|
'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125',
|
|
],
|
|
[
|
|
'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c',
|
|
'6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e',
|
|
],
|
|
[
|
|
'13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942',
|
|
'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1',
|
|
],
|
|
[
|
|
'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a',
|
|
'1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2',
|
|
],
|
|
[
|
|
'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80',
|
|
'5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423',
|
|
],
|
|
[
|
|
'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d',
|
|
'438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8',
|
|
],
|
|
[
|
|
'8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1',
|
|
'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758',
|
|
],
|
|
[
|
|
'52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63',
|
|
'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375',
|
|
],
|
|
[
|
|
'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352',
|
|
'6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d',
|
|
],
|
|
[
|
|
'7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193',
|
|
'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec',
|
|
],
|
|
[
|
|
'5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00',
|
|
'9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0',
|
|
],
|
|
[
|
|
'32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58',
|
|
'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c',
|
|
],
|
|
[
|
|
'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7',
|
|
'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4',
|
|
],
|
|
[
|
|
'8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8',
|
|
'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f',
|
|
],
|
|
[
|
|
'4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e',
|
|
'67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649',
|
|
],
|
|
[
|
|
'3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d',
|
|
'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826',
|
|
],
|
|
[
|
|
'674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b',
|
|
'299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5',
|
|
],
|
|
[
|
|
'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f',
|
|
'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87',
|
|
],
|
|
[
|
|
'30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6',
|
|
'462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b',
|
|
],
|
|
[
|
|
'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297',
|
|
'62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc',
|
|
],
|
|
[
|
|
'93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a',
|
|
'7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c',
|
|
],
|
|
[
|
|
'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c',
|
|
'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f',
|
|
],
|
|
[
|
|
'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52',
|
|
'4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a',
|
|
],
|
|
[
|
|
'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb',
|
|
'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46',
|
|
],
|
|
[
|
|
'463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065',
|
|
'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f',
|
|
],
|
|
[
|
|
'7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917',
|
|
'603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03',
|
|
],
|
|
[
|
|
'74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9',
|
|
'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08',
|
|
],
|
|
[
|
|
'30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3',
|
|
'553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8',
|
|
],
|
|
[
|
|
'9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57',
|
|
'712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373',
|
|
],
|
|
[
|
|
'176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66',
|
|
'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3',
|
|
],
|
|
[
|
|
'75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8',
|
|
'9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8',
|
|
],
|
|
[
|
|
'809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721',
|
|
'9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1',
|
|
],
|
|
[
|
|
'1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180',
|
|
'4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9',
|
|
],
|
|
],
|
|
},
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/lib/elliptic/utils.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/elliptic/lib/elliptic/utils.js ***!
|
|
\*****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = exports;
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/elliptic/node_modules/bn.js/lib/bn.js");
|
|
var minAssert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
var minUtils = __webpack_require__(/*! minimalistic-crypto-utils */ "./node_modules/minimalistic-crypto-utils/lib/utils.js");
|
|
|
|
utils.assert = minAssert;
|
|
utils.toArray = minUtils.toArray;
|
|
utils.zero2 = minUtils.zero2;
|
|
utils.toHex = minUtils.toHex;
|
|
utils.encode = minUtils.encode;
|
|
|
|
// Represent num in a w-NAF form
|
|
function getNAF(num, w, bits) {
|
|
var naf = new Array(Math.max(num.bitLength(), bits) + 1);
|
|
naf.fill(0);
|
|
|
|
var ws = 1 << (w + 1);
|
|
var k = num.clone();
|
|
|
|
for (var i = 0; i < naf.length; i++) {
|
|
var z;
|
|
var mod = k.andln(ws - 1);
|
|
if (k.isOdd()) {
|
|
if (mod > (ws >> 1) - 1)
|
|
z = (ws >> 1) - mod;
|
|
else
|
|
z = mod;
|
|
k.isubn(z);
|
|
} else {
|
|
z = 0;
|
|
}
|
|
|
|
naf[i] = z;
|
|
k.iushrn(1);
|
|
}
|
|
|
|
return naf;
|
|
}
|
|
utils.getNAF = getNAF;
|
|
|
|
// Represent k1, k2 in a Joint Sparse Form
|
|
function getJSF(k1, k2) {
|
|
var jsf = [
|
|
[],
|
|
[],
|
|
];
|
|
|
|
k1 = k1.clone();
|
|
k2 = k2.clone();
|
|
var d1 = 0;
|
|
var d2 = 0;
|
|
var m8;
|
|
while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) {
|
|
// First phase
|
|
var m14 = (k1.andln(3) + d1) & 3;
|
|
var m24 = (k2.andln(3) + d2) & 3;
|
|
if (m14 === 3)
|
|
m14 = -1;
|
|
if (m24 === 3)
|
|
m24 = -1;
|
|
var u1;
|
|
if ((m14 & 1) === 0) {
|
|
u1 = 0;
|
|
} else {
|
|
m8 = (k1.andln(7) + d1) & 7;
|
|
if ((m8 === 3 || m8 === 5) && m24 === 2)
|
|
u1 = -m14;
|
|
else
|
|
u1 = m14;
|
|
}
|
|
jsf[0].push(u1);
|
|
|
|
var u2;
|
|
if ((m24 & 1) === 0) {
|
|
u2 = 0;
|
|
} else {
|
|
m8 = (k2.andln(7) + d2) & 7;
|
|
if ((m8 === 3 || m8 === 5) && m14 === 2)
|
|
u2 = -m24;
|
|
else
|
|
u2 = m24;
|
|
}
|
|
jsf[1].push(u2);
|
|
|
|
// Second phase
|
|
if (2 * d1 === u1 + 1)
|
|
d1 = 1 - d1;
|
|
if (2 * d2 === u2 + 1)
|
|
d2 = 1 - d2;
|
|
k1.iushrn(1);
|
|
k2.iushrn(1);
|
|
}
|
|
|
|
return jsf;
|
|
}
|
|
utils.getJSF = getJSF;
|
|
|
|
function cachedProperty(obj, name, computer) {
|
|
var key = '_' + name;
|
|
obj.prototype[name] = function cachedProperty() {
|
|
return this[key] !== undefined ? this[key] :
|
|
this[key] = computer.call(this);
|
|
};
|
|
}
|
|
utils.cachedProperty = cachedProperty;
|
|
|
|
function parseBytes(bytes) {
|
|
return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') :
|
|
bytes;
|
|
}
|
|
utils.parseBytes = parseBytes;
|
|
|
|
function intFromLE(bytes) {
|
|
return new BN(bytes, 'hex', 'le');
|
|
}
|
|
utils.intFromLE = intFromLE;
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/node_modules/bn.js/lib/bn.js":
|
|
/*!************************************************************!*\
|
|
!*** ./node_modules/elliptic/node_modules/bn.js/lib/bn.js ***!
|
|
\************************************************************/
|
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
/* module decorator */ module = __webpack_require__.nmd(module);
|
|
(function (module, exports) {
|
|
'use strict';
|
|
|
|
// Utils
|
|
function assert (val, msg) {
|
|
if (!val) throw new Error(msg || 'Assertion failed');
|
|
}
|
|
|
|
// Could use `inherits` module, but don't want to move from single file
|
|
// architecture yet.
|
|
function inherits (ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
var TempCtor = function () {};
|
|
TempCtor.prototype = superCtor.prototype;
|
|
ctor.prototype = new TempCtor();
|
|
ctor.prototype.constructor = ctor;
|
|
}
|
|
|
|
// BN
|
|
|
|
function BN (number, base, endian) {
|
|
if (BN.isBN(number)) {
|
|
return number;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.words = null;
|
|
this.length = 0;
|
|
|
|
// Reduction context
|
|
this.red = null;
|
|
|
|
if (number !== null) {
|
|
if (base === 'le' || base === 'be') {
|
|
endian = base;
|
|
base = 10;
|
|
}
|
|
|
|
this._init(number || 0, base || 10, endian || 'be');
|
|
}
|
|
}
|
|
if (typeof module === 'object') {
|
|
module.exports = BN;
|
|
} else {
|
|
exports.BN = BN;
|
|
}
|
|
|
|
BN.BN = BN;
|
|
BN.wordSize = 26;
|
|
|
|
var Buffer;
|
|
try {
|
|
if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') {
|
|
Buffer = window.Buffer;
|
|
} else {
|
|
Buffer = __webpack_require__(/*! buffer */ "?7bec").Buffer;
|
|
}
|
|
} catch (e) {
|
|
}
|
|
|
|
BN.isBN = function isBN (num) {
|
|
if (num instanceof BN) {
|
|
return true;
|
|
}
|
|
|
|
return num !== null && typeof num === 'object' &&
|
|
num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
|
|
};
|
|
|
|
BN.max = function max (left, right) {
|
|
if (left.cmp(right) > 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.min = function min (left, right) {
|
|
if (left.cmp(right) < 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.prototype._init = function init (number, base, endian) {
|
|
if (typeof number === 'number') {
|
|
return this._initNumber(number, base, endian);
|
|
}
|
|
|
|
if (typeof number === 'object') {
|
|
return this._initArray(number, base, endian);
|
|
}
|
|
|
|
if (base === 'hex') {
|
|
base = 16;
|
|
}
|
|
assert(base === (base | 0) && base >= 2 && base <= 36);
|
|
|
|
number = number.toString().replace(/\s+/g, '');
|
|
var start = 0;
|
|
if (number[0] === '-') {
|
|
start++;
|
|
this.negative = 1;
|
|
}
|
|
|
|
if (start < number.length) {
|
|
if (base === 16) {
|
|
this._parseHex(number, start, endian);
|
|
} else {
|
|
this._parseBase(number, base, start);
|
|
if (endian === 'le') {
|
|
this._initArray(this.toArray(), base, endian);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
BN.prototype._initNumber = function _initNumber (number, base, endian) {
|
|
if (number < 0) {
|
|
this.negative = 1;
|
|
number = -number;
|
|
}
|
|
if (number < 0x4000000) {
|
|
this.words = [ number & 0x3ffffff ];
|
|
this.length = 1;
|
|
} else if (number < 0x10000000000000) {
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff
|
|
];
|
|
this.length = 2;
|
|
} else {
|
|
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff,
|
|
1
|
|
];
|
|
this.length = 3;
|
|
}
|
|
|
|
if (endian !== 'le') return;
|
|
|
|
// Reverse the bytes
|
|
this._initArray(this.toArray(), base, endian);
|
|
};
|
|
|
|
BN.prototype._initArray = function _initArray (number, base, endian) {
|
|
// Perhaps a Uint8Array
|
|
assert(typeof number.length === 'number');
|
|
if (number.length <= 0) {
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
return this;
|
|
}
|
|
|
|
this.length = Math.ceil(number.length / 3);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
var j, w;
|
|
var off = 0;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
|
|
w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
} else if (endian === 'le') {
|
|
for (i = 0, j = 0; i < number.length; i += 3) {
|
|
w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
return this.strip();
|
|
};
|
|
|
|
function parseHex4Bits (string, index) {
|
|
var c = string.charCodeAt(index);
|
|
// 'A' - 'F'
|
|
if (c >= 65 && c <= 70) {
|
|
return c - 55;
|
|
// 'a' - 'f'
|
|
} else if (c >= 97 && c <= 102) {
|
|
return c - 87;
|
|
// '0' - '9'
|
|
} else {
|
|
return (c - 48) & 0xf;
|
|
}
|
|
}
|
|
|
|
function parseHexByte (string, lowerBound, index) {
|
|
var r = parseHex4Bits(string, index);
|
|
if (index - 1 >= lowerBound) {
|
|
r |= parseHex4Bits(string, index - 1) << 4;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseHex = function _parseHex (number, start, endian) {
|
|
// Create possibly bigger array to ensure that it fits the number
|
|
this.length = Math.ceil((number.length - start) / 6);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
// 24-bits chunks
|
|
var off = 0;
|
|
var j = 0;
|
|
|
|
var w;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1; i >= start; i -= 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
} else {
|
|
var parseLength = number.length - start;
|
|
for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
function parseBase (str, start, end, mul) {
|
|
var r = 0;
|
|
var len = Math.min(str.length, end);
|
|
for (var i = start; i < len; i++) {
|
|
var c = str.charCodeAt(i) - 48;
|
|
|
|
r *= mul;
|
|
|
|
// 'a'
|
|
if (c >= 49) {
|
|
r += c - 49 + 0xa;
|
|
|
|
// 'A'
|
|
} else if (c >= 17) {
|
|
r += c - 17 + 0xa;
|
|
|
|
// '0' - '9'
|
|
} else {
|
|
r += c;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseBase = function _parseBase (number, base, start) {
|
|
// Initialize as zero
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
|
|
// Find length of limb in base
|
|
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
|
|
limbLen++;
|
|
}
|
|
limbLen--;
|
|
limbPow = (limbPow / base) | 0;
|
|
|
|
var total = number.length - start;
|
|
var mod = total % limbLen;
|
|
var end = Math.min(total, total - mod) + start;
|
|
|
|
var word = 0;
|
|
for (var i = start; i < end; i += limbLen) {
|
|
word = parseBase(number, i, i + limbLen, base);
|
|
|
|
this.imuln(limbPow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
if (mod !== 0) {
|
|
var pow = 1;
|
|
word = parseBase(number, i, number.length, base);
|
|
|
|
for (i = 0; i < mod; i++) {
|
|
pow *= base;
|
|
}
|
|
|
|
this.imuln(pow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
BN.prototype.copy = function copy (dest) {
|
|
dest.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
dest.words[i] = this.words[i];
|
|
}
|
|
dest.length = this.length;
|
|
dest.negative = this.negative;
|
|
dest.red = this.red;
|
|
};
|
|
|
|
BN.prototype.clone = function clone () {
|
|
var r = new BN(null);
|
|
this.copy(r);
|
|
return r;
|
|
};
|
|
|
|
BN.prototype._expand = function _expand (size) {
|
|
while (this.length < size) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
// Remove leading `0` from `this`
|
|
BN.prototype.strip = function strip () {
|
|
while (this.length > 1 && this.words[this.length - 1] === 0) {
|
|
this.length--;
|
|
}
|
|
return this._normSign();
|
|
};
|
|
|
|
BN.prototype._normSign = function _normSign () {
|
|
// -0 = 0
|
|
if (this.length === 1 && this.words[0] === 0) {
|
|
this.negative = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.inspect = function inspect () {
|
|
return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
|
|
};
|
|
|
|
/*
|
|
|
|
var zeros = [];
|
|
var groupSizes = [];
|
|
var groupBases = [];
|
|
|
|
var s = '';
|
|
var i = -1;
|
|
while (++i < BN.wordSize) {
|
|
zeros[i] = s;
|
|
s += '0';
|
|
}
|
|
groupSizes[0] = 0;
|
|
groupSizes[1] = 0;
|
|
groupBases[0] = 0;
|
|
groupBases[1] = 0;
|
|
var base = 2 - 1;
|
|
while (++base < 36 + 1) {
|
|
var groupSize = 0;
|
|
var groupBase = 1;
|
|
while (groupBase < (1 << BN.wordSize) / base) {
|
|
groupBase *= base;
|
|
groupSize += 1;
|
|
}
|
|
groupSizes[base] = groupSize;
|
|
groupBases[base] = groupBase;
|
|
}
|
|
|
|
*/
|
|
|
|
var zeros = [
|
|
'',
|
|
'0',
|
|
'00',
|
|
'000',
|
|
'0000',
|
|
'00000',
|
|
'000000',
|
|
'0000000',
|
|
'00000000',
|
|
'000000000',
|
|
'0000000000',
|
|
'00000000000',
|
|
'000000000000',
|
|
'0000000000000',
|
|
'00000000000000',
|
|
'000000000000000',
|
|
'0000000000000000',
|
|
'00000000000000000',
|
|
'000000000000000000',
|
|
'0000000000000000000',
|
|
'00000000000000000000',
|
|
'000000000000000000000',
|
|
'0000000000000000000000',
|
|
'00000000000000000000000',
|
|
'000000000000000000000000',
|
|
'0000000000000000000000000'
|
|
];
|
|
|
|
var groupSizes = [
|
|
0, 0,
|
|
25, 16, 12, 11, 10, 9, 8,
|
|
8, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5
|
|
];
|
|
|
|
var groupBases = [
|
|
0, 0,
|
|
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
|
|
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
|
|
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
|
|
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
|
|
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
|
|
];
|
|
|
|
BN.prototype.toString = function toString (base, padding) {
|
|
base = base || 10;
|
|
padding = padding | 0 || 1;
|
|
|
|
var out;
|
|
if (base === 16 || base === 'hex') {
|
|
out = '';
|
|
var off = 0;
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = this.words[i];
|
|
var word = (((w << off) | carry) & 0xffffff).toString(16);
|
|
carry = (w >>> (24 - off)) & 0xffffff;
|
|
if (carry !== 0 || i !== this.length - 1) {
|
|
out = zeros[6 - word.length] + word + out;
|
|
} else {
|
|
out = word + out;
|
|
}
|
|
off += 2;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
i--;
|
|
}
|
|
}
|
|
if (carry !== 0) {
|
|
out = carry.toString(16) + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
if (base === (base | 0) && base >= 2 && base <= 36) {
|
|
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
|
|
var groupSize = groupSizes[base];
|
|
// var groupBase = Math.pow(base, groupSize);
|
|
var groupBase = groupBases[base];
|
|
out = '';
|
|
var c = this.clone();
|
|
c.negative = 0;
|
|
while (!c.isZero()) {
|
|
var r = c.modn(groupBase).toString(base);
|
|
c = c.idivn(groupBase);
|
|
|
|
if (!c.isZero()) {
|
|
out = zeros[groupSize - r.length] + r + out;
|
|
} else {
|
|
out = r + out;
|
|
}
|
|
}
|
|
if (this.isZero()) {
|
|
out = '0' + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
assert(false, 'Base should be between 2 and 36');
|
|
};
|
|
|
|
BN.prototype.toNumber = function toNumber () {
|
|
var ret = this.words[0];
|
|
if (this.length === 2) {
|
|
ret += this.words[1] * 0x4000000;
|
|
} else if (this.length === 3 && this.words[2] === 0x01) {
|
|
// NOTE: at this stage it is known that the top bit is set
|
|
ret += 0x10000000000000 + (this.words[1] * 0x4000000);
|
|
} else if (this.length > 2) {
|
|
assert(false, 'Number can only safely store up to 53 bits');
|
|
}
|
|
return (this.negative !== 0) ? -ret : ret;
|
|
};
|
|
|
|
BN.prototype.toJSON = function toJSON () {
|
|
return this.toString(16);
|
|
};
|
|
|
|
BN.prototype.toBuffer = function toBuffer (endian, length) {
|
|
assert(typeof Buffer !== 'undefined');
|
|
return this.toArrayLike(Buffer, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArray = function toArray (endian, length) {
|
|
return this.toArrayLike(Array, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
|
|
var byteLength = this.byteLength();
|
|
var reqLength = length || Math.max(1, byteLength);
|
|
assert(byteLength <= reqLength, 'byte array longer than desired length');
|
|
assert(reqLength > 0, 'Requested array length <= 0');
|
|
|
|
this.strip();
|
|
var littleEndian = endian === 'le';
|
|
var res = new ArrayType(reqLength);
|
|
|
|
var b, i;
|
|
var q = this.clone();
|
|
if (!littleEndian) {
|
|
// Assume big-endian
|
|
for (i = 0; i < reqLength - byteLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[reqLength - i - 1] = b;
|
|
}
|
|
} else {
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[i] = b;
|
|
}
|
|
|
|
for (; i < reqLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
if (Math.clz32) {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
return 32 - Math.clz32(w);
|
|
};
|
|
} else {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
var t = w;
|
|
var r = 0;
|
|
if (t >= 0x1000) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if (t >= 0x40) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if (t >= 0x8) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if (t >= 0x02) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
return r + t;
|
|
};
|
|
}
|
|
|
|
BN.prototype._zeroBits = function _zeroBits (w) {
|
|
// Short-cut
|
|
if (w === 0) return 26;
|
|
|
|
var t = w;
|
|
var r = 0;
|
|
if ((t & 0x1fff) === 0) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if ((t & 0x7f) === 0) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if ((t & 0xf) === 0) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if ((t & 0x3) === 0) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
if ((t & 0x1) === 0) {
|
|
r++;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
// Return number of used bits in a BN
|
|
BN.prototype.bitLength = function bitLength () {
|
|
var w = this.words[this.length - 1];
|
|
var hi = this._countBits(w);
|
|
return (this.length - 1) * 26 + hi;
|
|
};
|
|
|
|
function toBitArray (num) {
|
|
var w = new Array(num.bitLength());
|
|
|
|
for (var bit = 0; bit < w.length; bit++) {
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
// Number of trailing zero bits
|
|
BN.prototype.zeroBits = function zeroBits () {
|
|
if (this.isZero()) return 0;
|
|
|
|
var r = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var b = this._zeroBits(this.words[i]);
|
|
r += b;
|
|
if (b !== 26) break;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
BN.prototype.byteLength = function byteLength () {
|
|
return Math.ceil(this.bitLength() / 8);
|
|
};
|
|
|
|
BN.prototype.toTwos = function toTwos (width) {
|
|
if (this.negative !== 0) {
|
|
return this.abs().inotn(width).iaddn(1);
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.fromTwos = function fromTwos (width) {
|
|
if (this.testn(width - 1)) {
|
|
return this.notn(width).iaddn(1).ineg();
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.isNeg = function isNeg () {
|
|
return this.negative !== 0;
|
|
};
|
|
|
|
// Return negative clone of `this`
|
|
BN.prototype.neg = function neg () {
|
|
return this.clone().ineg();
|
|
};
|
|
|
|
BN.prototype.ineg = function ineg () {
|
|
if (!this.isZero()) {
|
|
this.negative ^= 1;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Or `num` with `this` in-place
|
|
BN.prototype.iuor = function iuor (num) {
|
|
while (this.length < num.length) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
|
|
for (var i = 0; i < num.length; i++) {
|
|
this.words[i] = this.words[i] | num.words[i];
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ior = function ior (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuor(num);
|
|
};
|
|
|
|
// Or `num` with `this`
|
|
BN.prototype.or = function or (num) {
|
|
if (this.length > num.length) return this.clone().ior(num);
|
|
return num.clone().ior(this);
|
|
};
|
|
|
|
BN.prototype.uor = function uor (num) {
|
|
if (this.length > num.length) return this.clone().iuor(num);
|
|
return num.clone().iuor(this);
|
|
};
|
|
|
|
// And `num` with `this` in-place
|
|
BN.prototype.iuand = function iuand (num) {
|
|
// b = min-length(num, this)
|
|
var b;
|
|
if (this.length > num.length) {
|
|
b = num;
|
|
} else {
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = this.words[i] & num.words[i];
|
|
}
|
|
|
|
this.length = b.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.iand = function iand (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuand(num);
|
|
};
|
|
|
|
// And `num` with `this`
|
|
BN.prototype.and = function and (num) {
|
|
if (this.length > num.length) return this.clone().iand(num);
|
|
return num.clone().iand(this);
|
|
};
|
|
|
|
BN.prototype.uand = function uand (num) {
|
|
if (this.length > num.length) return this.clone().iuand(num);
|
|
return num.clone().iuand(this);
|
|
};
|
|
|
|
// Xor `num` with `this` in-place
|
|
BN.prototype.iuxor = function iuxor (num) {
|
|
// a.length > b.length
|
|
var a;
|
|
var b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = a.words[i] ^ b.words[i];
|
|
}
|
|
|
|
if (this !== a) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = a.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ixor = function ixor (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuxor(num);
|
|
};
|
|
|
|
// Xor `num` with `this`
|
|
BN.prototype.xor = function xor (num) {
|
|
if (this.length > num.length) return this.clone().ixor(num);
|
|
return num.clone().ixor(this);
|
|
};
|
|
|
|
BN.prototype.uxor = function uxor (num) {
|
|
if (this.length > num.length) return this.clone().iuxor(num);
|
|
return num.clone().iuxor(this);
|
|
};
|
|
|
|
// Not ``this`` with ``width`` bitwidth
|
|
BN.prototype.inotn = function inotn (width) {
|
|
assert(typeof width === 'number' && width >= 0);
|
|
|
|
var bytesNeeded = Math.ceil(width / 26) | 0;
|
|
var bitsLeft = width % 26;
|
|
|
|
// Extend the buffer with leading zeroes
|
|
this._expand(bytesNeeded);
|
|
|
|
if (bitsLeft > 0) {
|
|
bytesNeeded--;
|
|
}
|
|
|
|
// Handle complete words
|
|
for (var i = 0; i < bytesNeeded; i++) {
|
|
this.words[i] = ~this.words[i] & 0x3ffffff;
|
|
}
|
|
|
|
// Handle the residue
|
|
if (bitsLeft > 0) {
|
|
this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
|
|
}
|
|
|
|
// And remove leading zeroes
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.notn = function notn (width) {
|
|
return this.clone().inotn(width);
|
|
};
|
|
|
|
// Set `bit` of `this`
|
|
BN.prototype.setn = function setn (bit, val) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
this._expand(off + 1);
|
|
|
|
if (val) {
|
|
this.words[off] = this.words[off] | (1 << wbit);
|
|
} else {
|
|
this.words[off] = this.words[off] & ~(1 << wbit);
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Add `num` to `this` in-place
|
|
BN.prototype.iadd = function iadd (num) {
|
|
var r;
|
|
|
|
// negative + positive
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
this.negative = 0;
|
|
r = this.isub(num);
|
|
this.negative ^= 1;
|
|
return this._normSign();
|
|
|
|
// positive + negative
|
|
} else if (this.negative === 0 && num.negative !== 0) {
|
|
num.negative = 0;
|
|
r = this.isub(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
}
|
|
|
|
// a.length > b.length
|
|
var a, b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
|
|
this.length = a.length;
|
|
if (carry !== 0) {
|
|
this.words[this.length] = carry;
|
|
this.length++;
|
|
// Copy the rest of the words
|
|
} else if (a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Add `num` to `this`
|
|
BN.prototype.add = function add (num) {
|
|
var res;
|
|
if (num.negative !== 0 && this.negative === 0) {
|
|
num.negative = 0;
|
|
res = this.sub(num);
|
|
num.negative ^= 1;
|
|
return res;
|
|
} else if (num.negative === 0 && this.negative !== 0) {
|
|
this.negative = 0;
|
|
res = num.sub(this);
|
|
this.negative = 1;
|
|
return res;
|
|
}
|
|
|
|
if (this.length > num.length) return this.clone().iadd(num);
|
|
|
|
return num.clone().iadd(this);
|
|
};
|
|
|
|
// Subtract `num` from `this` in-place
|
|
BN.prototype.isub = function isub (num) {
|
|
// this - (-num) = this + num
|
|
if (num.negative !== 0) {
|
|
num.negative = 0;
|
|
var r = this.iadd(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
|
|
// -this - num = -(this + num)
|
|
} else if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iadd(num);
|
|
this.negative = 1;
|
|
return this._normSign();
|
|
}
|
|
|
|
// At this point both numbers are positive
|
|
var cmp = this.cmp(num);
|
|
|
|
// Optimization - zeroify
|
|
if (cmp === 0) {
|
|
this.negative = 0;
|
|
this.length = 1;
|
|
this.words[0] = 0;
|
|
return this;
|
|
}
|
|
|
|
// a > b
|
|
var a, b;
|
|
if (cmp > 0) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
|
|
// Copy rest of the words
|
|
if (carry === 0 && i < a.length && a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = Math.max(this.length, i);
|
|
|
|
if (a !== this) {
|
|
this.negative = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Subtract `num` from `this`
|
|
BN.prototype.sub = function sub (num) {
|
|
return this.clone().isub(num);
|
|
};
|
|
|
|
function smallMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
var len = (self.length + num.length) | 0;
|
|
out.length = len;
|
|
len = (len - 1) | 0;
|
|
|
|
// Peel one iteration (compiler can't do it, because of code complexity)
|
|
var a = self.words[0] | 0;
|
|
var b = num.words[0] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
var carry = (r / 0x4000000) | 0;
|
|
out.words[0] = lo;
|
|
|
|
for (var k = 1; k < len; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = carry >>> 26;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = (k - j) | 0;
|
|
a = self.words[i] | 0;
|
|
b = num.words[j] | 0;
|
|
r = a * b + rword;
|
|
ncarry += (r / 0x4000000) | 0;
|
|
rword = r & 0x3ffffff;
|
|
}
|
|
out.words[k] = rword | 0;
|
|
carry = ncarry | 0;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry | 0;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
// TODO(indutny): it may be reasonable to omit it for users who don't need
|
|
// to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
|
|
// multiplication (like elliptic secp256k1).
|
|
var comb10MulTo = function comb10MulTo (self, num, out) {
|
|
var a = self.words;
|
|
var b = num.words;
|
|
var o = out.words;
|
|
var c = 0;
|
|
var lo;
|
|
var mid;
|
|
var hi;
|
|
var a0 = a[0] | 0;
|
|
var al0 = a0 & 0x1fff;
|
|
var ah0 = a0 >>> 13;
|
|
var a1 = a[1] | 0;
|
|
var al1 = a1 & 0x1fff;
|
|
var ah1 = a1 >>> 13;
|
|
var a2 = a[2] | 0;
|
|
var al2 = a2 & 0x1fff;
|
|
var ah2 = a2 >>> 13;
|
|
var a3 = a[3] | 0;
|
|
var al3 = a3 & 0x1fff;
|
|
var ah3 = a3 >>> 13;
|
|
var a4 = a[4] | 0;
|
|
var al4 = a4 & 0x1fff;
|
|
var ah4 = a4 >>> 13;
|
|
var a5 = a[5] | 0;
|
|
var al5 = a5 & 0x1fff;
|
|
var ah5 = a5 >>> 13;
|
|
var a6 = a[6] | 0;
|
|
var al6 = a6 & 0x1fff;
|
|
var ah6 = a6 >>> 13;
|
|
var a7 = a[7] | 0;
|
|
var al7 = a7 & 0x1fff;
|
|
var ah7 = a7 >>> 13;
|
|
var a8 = a[8] | 0;
|
|
var al8 = a8 & 0x1fff;
|
|
var ah8 = a8 >>> 13;
|
|
var a9 = a[9] | 0;
|
|
var al9 = a9 & 0x1fff;
|
|
var ah9 = a9 >>> 13;
|
|
var b0 = b[0] | 0;
|
|
var bl0 = b0 & 0x1fff;
|
|
var bh0 = b0 >>> 13;
|
|
var b1 = b[1] | 0;
|
|
var bl1 = b1 & 0x1fff;
|
|
var bh1 = b1 >>> 13;
|
|
var b2 = b[2] | 0;
|
|
var bl2 = b2 & 0x1fff;
|
|
var bh2 = b2 >>> 13;
|
|
var b3 = b[3] | 0;
|
|
var bl3 = b3 & 0x1fff;
|
|
var bh3 = b3 >>> 13;
|
|
var b4 = b[4] | 0;
|
|
var bl4 = b4 & 0x1fff;
|
|
var bh4 = b4 >>> 13;
|
|
var b5 = b[5] | 0;
|
|
var bl5 = b5 & 0x1fff;
|
|
var bh5 = b5 >>> 13;
|
|
var b6 = b[6] | 0;
|
|
var bl6 = b6 & 0x1fff;
|
|
var bh6 = b6 >>> 13;
|
|
var b7 = b[7] | 0;
|
|
var bl7 = b7 & 0x1fff;
|
|
var bh7 = b7 >>> 13;
|
|
var b8 = b[8] | 0;
|
|
var bl8 = b8 & 0x1fff;
|
|
var bh8 = b8 >>> 13;
|
|
var b9 = b[9] | 0;
|
|
var bl9 = b9 & 0x1fff;
|
|
var bh9 = b9 >>> 13;
|
|
|
|
out.negative = self.negative ^ num.negative;
|
|
out.length = 19;
|
|
/* k = 0 */
|
|
lo = Math.imul(al0, bl0);
|
|
mid = Math.imul(al0, bh0);
|
|
mid = (mid + Math.imul(ah0, bl0)) | 0;
|
|
hi = Math.imul(ah0, bh0);
|
|
var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
|
|
w0 &= 0x3ffffff;
|
|
/* k = 1 */
|
|
lo = Math.imul(al1, bl0);
|
|
mid = Math.imul(al1, bh0);
|
|
mid = (mid + Math.imul(ah1, bl0)) | 0;
|
|
hi = Math.imul(ah1, bh0);
|
|
lo = (lo + Math.imul(al0, bl1)) | 0;
|
|
mid = (mid + Math.imul(al0, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh1)) | 0;
|
|
var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
|
|
w1 &= 0x3ffffff;
|
|
/* k = 2 */
|
|
lo = Math.imul(al2, bl0);
|
|
mid = Math.imul(al2, bh0);
|
|
mid = (mid + Math.imul(ah2, bl0)) | 0;
|
|
hi = Math.imul(ah2, bh0);
|
|
lo = (lo + Math.imul(al1, bl1)) | 0;
|
|
mid = (mid + Math.imul(al1, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh1)) | 0;
|
|
lo = (lo + Math.imul(al0, bl2)) | 0;
|
|
mid = (mid + Math.imul(al0, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh2)) | 0;
|
|
var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
|
|
w2 &= 0x3ffffff;
|
|
/* k = 3 */
|
|
lo = Math.imul(al3, bl0);
|
|
mid = Math.imul(al3, bh0);
|
|
mid = (mid + Math.imul(ah3, bl0)) | 0;
|
|
hi = Math.imul(ah3, bh0);
|
|
lo = (lo + Math.imul(al2, bl1)) | 0;
|
|
mid = (mid + Math.imul(al2, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh1)) | 0;
|
|
lo = (lo + Math.imul(al1, bl2)) | 0;
|
|
mid = (mid + Math.imul(al1, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh2)) | 0;
|
|
lo = (lo + Math.imul(al0, bl3)) | 0;
|
|
mid = (mid + Math.imul(al0, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh3)) | 0;
|
|
var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
|
|
w3 &= 0x3ffffff;
|
|
/* k = 4 */
|
|
lo = Math.imul(al4, bl0);
|
|
mid = Math.imul(al4, bh0);
|
|
mid = (mid + Math.imul(ah4, bl0)) | 0;
|
|
hi = Math.imul(ah4, bh0);
|
|
lo = (lo + Math.imul(al3, bl1)) | 0;
|
|
mid = (mid + Math.imul(al3, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh1)) | 0;
|
|
lo = (lo + Math.imul(al2, bl2)) | 0;
|
|
mid = (mid + Math.imul(al2, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh2)) | 0;
|
|
lo = (lo + Math.imul(al1, bl3)) | 0;
|
|
mid = (mid + Math.imul(al1, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh3)) | 0;
|
|
lo = (lo + Math.imul(al0, bl4)) | 0;
|
|
mid = (mid + Math.imul(al0, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh4)) | 0;
|
|
var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
|
|
w4 &= 0x3ffffff;
|
|
/* k = 5 */
|
|
lo = Math.imul(al5, bl0);
|
|
mid = Math.imul(al5, bh0);
|
|
mid = (mid + Math.imul(ah5, bl0)) | 0;
|
|
hi = Math.imul(ah5, bh0);
|
|
lo = (lo + Math.imul(al4, bl1)) | 0;
|
|
mid = (mid + Math.imul(al4, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh1)) | 0;
|
|
lo = (lo + Math.imul(al3, bl2)) | 0;
|
|
mid = (mid + Math.imul(al3, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh2)) | 0;
|
|
lo = (lo + Math.imul(al2, bl3)) | 0;
|
|
mid = (mid + Math.imul(al2, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh3)) | 0;
|
|
lo = (lo + Math.imul(al1, bl4)) | 0;
|
|
mid = (mid + Math.imul(al1, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh4)) | 0;
|
|
lo = (lo + Math.imul(al0, bl5)) | 0;
|
|
mid = (mid + Math.imul(al0, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh5)) | 0;
|
|
var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
|
|
w5 &= 0x3ffffff;
|
|
/* k = 6 */
|
|
lo = Math.imul(al6, bl0);
|
|
mid = Math.imul(al6, bh0);
|
|
mid = (mid + Math.imul(ah6, bl0)) | 0;
|
|
hi = Math.imul(ah6, bh0);
|
|
lo = (lo + Math.imul(al5, bl1)) | 0;
|
|
mid = (mid + Math.imul(al5, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh1)) | 0;
|
|
lo = (lo + Math.imul(al4, bl2)) | 0;
|
|
mid = (mid + Math.imul(al4, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh2)) | 0;
|
|
lo = (lo + Math.imul(al3, bl3)) | 0;
|
|
mid = (mid + Math.imul(al3, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh3)) | 0;
|
|
lo = (lo + Math.imul(al2, bl4)) | 0;
|
|
mid = (mid + Math.imul(al2, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh4)) | 0;
|
|
lo = (lo + Math.imul(al1, bl5)) | 0;
|
|
mid = (mid + Math.imul(al1, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh5)) | 0;
|
|
lo = (lo + Math.imul(al0, bl6)) | 0;
|
|
mid = (mid + Math.imul(al0, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh6)) | 0;
|
|
var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
|
|
w6 &= 0x3ffffff;
|
|
/* k = 7 */
|
|
lo = Math.imul(al7, bl0);
|
|
mid = Math.imul(al7, bh0);
|
|
mid = (mid + Math.imul(ah7, bl0)) | 0;
|
|
hi = Math.imul(ah7, bh0);
|
|
lo = (lo + Math.imul(al6, bl1)) | 0;
|
|
mid = (mid + Math.imul(al6, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh1)) | 0;
|
|
lo = (lo + Math.imul(al5, bl2)) | 0;
|
|
mid = (mid + Math.imul(al5, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh2)) | 0;
|
|
lo = (lo + Math.imul(al4, bl3)) | 0;
|
|
mid = (mid + Math.imul(al4, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh3)) | 0;
|
|
lo = (lo + Math.imul(al3, bl4)) | 0;
|
|
mid = (mid + Math.imul(al3, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh4)) | 0;
|
|
lo = (lo + Math.imul(al2, bl5)) | 0;
|
|
mid = (mid + Math.imul(al2, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh5)) | 0;
|
|
lo = (lo + Math.imul(al1, bl6)) | 0;
|
|
mid = (mid + Math.imul(al1, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh6)) | 0;
|
|
lo = (lo + Math.imul(al0, bl7)) | 0;
|
|
mid = (mid + Math.imul(al0, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh7)) | 0;
|
|
var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
|
|
w7 &= 0x3ffffff;
|
|
/* k = 8 */
|
|
lo = Math.imul(al8, bl0);
|
|
mid = Math.imul(al8, bh0);
|
|
mid = (mid + Math.imul(ah8, bl0)) | 0;
|
|
hi = Math.imul(ah8, bh0);
|
|
lo = (lo + Math.imul(al7, bl1)) | 0;
|
|
mid = (mid + Math.imul(al7, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh1)) | 0;
|
|
lo = (lo + Math.imul(al6, bl2)) | 0;
|
|
mid = (mid + Math.imul(al6, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh2)) | 0;
|
|
lo = (lo + Math.imul(al5, bl3)) | 0;
|
|
mid = (mid + Math.imul(al5, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh3)) | 0;
|
|
lo = (lo + Math.imul(al4, bl4)) | 0;
|
|
mid = (mid + Math.imul(al4, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh4)) | 0;
|
|
lo = (lo + Math.imul(al3, bl5)) | 0;
|
|
mid = (mid + Math.imul(al3, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh5)) | 0;
|
|
lo = (lo + Math.imul(al2, bl6)) | 0;
|
|
mid = (mid + Math.imul(al2, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh6)) | 0;
|
|
lo = (lo + Math.imul(al1, bl7)) | 0;
|
|
mid = (mid + Math.imul(al1, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh7)) | 0;
|
|
lo = (lo + Math.imul(al0, bl8)) | 0;
|
|
mid = (mid + Math.imul(al0, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh8)) | 0;
|
|
var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
|
|
w8 &= 0x3ffffff;
|
|
/* k = 9 */
|
|
lo = Math.imul(al9, bl0);
|
|
mid = Math.imul(al9, bh0);
|
|
mid = (mid + Math.imul(ah9, bl0)) | 0;
|
|
hi = Math.imul(ah9, bh0);
|
|
lo = (lo + Math.imul(al8, bl1)) | 0;
|
|
mid = (mid + Math.imul(al8, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh1)) | 0;
|
|
lo = (lo + Math.imul(al7, bl2)) | 0;
|
|
mid = (mid + Math.imul(al7, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh2)) | 0;
|
|
lo = (lo + Math.imul(al6, bl3)) | 0;
|
|
mid = (mid + Math.imul(al6, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh3)) | 0;
|
|
lo = (lo + Math.imul(al5, bl4)) | 0;
|
|
mid = (mid + Math.imul(al5, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh4)) | 0;
|
|
lo = (lo + Math.imul(al4, bl5)) | 0;
|
|
mid = (mid + Math.imul(al4, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh5)) | 0;
|
|
lo = (lo + Math.imul(al3, bl6)) | 0;
|
|
mid = (mid + Math.imul(al3, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh6)) | 0;
|
|
lo = (lo + Math.imul(al2, bl7)) | 0;
|
|
mid = (mid + Math.imul(al2, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh7)) | 0;
|
|
lo = (lo + Math.imul(al1, bl8)) | 0;
|
|
mid = (mid + Math.imul(al1, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh8)) | 0;
|
|
lo = (lo + Math.imul(al0, bl9)) | 0;
|
|
mid = (mid + Math.imul(al0, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh9)) | 0;
|
|
var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
|
|
w9 &= 0x3ffffff;
|
|
/* k = 10 */
|
|
lo = Math.imul(al9, bl1);
|
|
mid = Math.imul(al9, bh1);
|
|
mid = (mid + Math.imul(ah9, bl1)) | 0;
|
|
hi = Math.imul(ah9, bh1);
|
|
lo = (lo + Math.imul(al8, bl2)) | 0;
|
|
mid = (mid + Math.imul(al8, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh2)) | 0;
|
|
lo = (lo + Math.imul(al7, bl3)) | 0;
|
|
mid = (mid + Math.imul(al7, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh3)) | 0;
|
|
lo = (lo + Math.imul(al6, bl4)) | 0;
|
|
mid = (mid + Math.imul(al6, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh4)) | 0;
|
|
lo = (lo + Math.imul(al5, bl5)) | 0;
|
|
mid = (mid + Math.imul(al5, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh5)) | 0;
|
|
lo = (lo + Math.imul(al4, bl6)) | 0;
|
|
mid = (mid + Math.imul(al4, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh6)) | 0;
|
|
lo = (lo + Math.imul(al3, bl7)) | 0;
|
|
mid = (mid + Math.imul(al3, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh7)) | 0;
|
|
lo = (lo + Math.imul(al2, bl8)) | 0;
|
|
mid = (mid + Math.imul(al2, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh8)) | 0;
|
|
lo = (lo + Math.imul(al1, bl9)) | 0;
|
|
mid = (mid + Math.imul(al1, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh9)) | 0;
|
|
var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
|
|
w10 &= 0x3ffffff;
|
|
/* k = 11 */
|
|
lo = Math.imul(al9, bl2);
|
|
mid = Math.imul(al9, bh2);
|
|
mid = (mid + Math.imul(ah9, bl2)) | 0;
|
|
hi = Math.imul(ah9, bh2);
|
|
lo = (lo + Math.imul(al8, bl3)) | 0;
|
|
mid = (mid + Math.imul(al8, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh3)) | 0;
|
|
lo = (lo + Math.imul(al7, bl4)) | 0;
|
|
mid = (mid + Math.imul(al7, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh4)) | 0;
|
|
lo = (lo + Math.imul(al6, bl5)) | 0;
|
|
mid = (mid + Math.imul(al6, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh5)) | 0;
|
|
lo = (lo + Math.imul(al5, bl6)) | 0;
|
|
mid = (mid + Math.imul(al5, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh6)) | 0;
|
|
lo = (lo + Math.imul(al4, bl7)) | 0;
|
|
mid = (mid + Math.imul(al4, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh7)) | 0;
|
|
lo = (lo + Math.imul(al3, bl8)) | 0;
|
|
mid = (mid + Math.imul(al3, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh8)) | 0;
|
|
lo = (lo + Math.imul(al2, bl9)) | 0;
|
|
mid = (mid + Math.imul(al2, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh9)) | 0;
|
|
var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
|
|
w11 &= 0x3ffffff;
|
|
/* k = 12 */
|
|
lo = Math.imul(al9, bl3);
|
|
mid = Math.imul(al9, bh3);
|
|
mid = (mid + Math.imul(ah9, bl3)) | 0;
|
|
hi = Math.imul(ah9, bh3);
|
|
lo = (lo + Math.imul(al8, bl4)) | 0;
|
|
mid = (mid + Math.imul(al8, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh4)) | 0;
|
|
lo = (lo + Math.imul(al7, bl5)) | 0;
|
|
mid = (mid + Math.imul(al7, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh5)) | 0;
|
|
lo = (lo + Math.imul(al6, bl6)) | 0;
|
|
mid = (mid + Math.imul(al6, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh6)) | 0;
|
|
lo = (lo + Math.imul(al5, bl7)) | 0;
|
|
mid = (mid + Math.imul(al5, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh7)) | 0;
|
|
lo = (lo + Math.imul(al4, bl8)) | 0;
|
|
mid = (mid + Math.imul(al4, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh8)) | 0;
|
|
lo = (lo + Math.imul(al3, bl9)) | 0;
|
|
mid = (mid + Math.imul(al3, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh9)) | 0;
|
|
var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
|
|
w12 &= 0x3ffffff;
|
|
/* k = 13 */
|
|
lo = Math.imul(al9, bl4);
|
|
mid = Math.imul(al9, bh4);
|
|
mid = (mid + Math.imul(ah9, bl4)) | 0;
|
|
hi = Math.imul(ah9, bh4);
|
|
lo = (lo + Math.imul(al8, bl5)) | 0;
|
|
mid = (mid + Math.imul(al8, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh5)) | 0;
|
|
lo = (lo + Math.imul(al7, bl6)) | 0;
|
|
mid = (mid + Math.imul(al7, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh6)) | 0;
|
|
lo = (lo + Math.imul(al6, bl7)) | 0;
|
|
mid = (mid + Math.imul(al6, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh7)) | 0;
|
|
lo = (lo + Math.imul(al5, bl8)) | 0;
|
|
mid = (mid + Math.imul(al5, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh8)) | 0;
|
|
lo = (lo + Math.imul(al4, bl9)) | 0;
|
|
mid = (mid + Math.imul(al4, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh9)) | 0;
|
|
var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
|
|
w13 &= 0x3ffffff;
|
|
/* k = 14 */
|
|
lo = Math.imul(al9, bl5);
|
|
mid = Math.imul(al9, bh5);
|
|
mid = (mid + Math.imul(ah9, bl5)) | 0;
|
|
hi = Math.imul(ah9, bh5);
|
|
lo = (lo + Math.imul(al8, bl6)) | 0;
|
|
mid = (mid + Math.imul(al8, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh6)) | 0;
|
|
lo = (lo + Math.imul(al7, bl7)) | 0;
|
|
mid = (mid + Math.imul(al7, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh7)) | 0;
|
|
lo = (lo + Math.imul(al6, bl8)) | 0;
|
|
mid = (mid + Math.imul(al6, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh8)) | 0;
|
|
lo = (lo + Math.imul(al5, bl9)) | 0;
|
|
mid = (mid + Math.imul(al5, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh9)) | 0;
|
|
var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
|
|
w14 &= 0x3ffffff;
|
|
/* k = 15 */
|
|
lo = Math.imul(al9, bl6);
|
|
mid = Math.imul(al9, bh6);
|
|
mid = (mid + Math.imul(ah9, bl6)) | 0;
|
|
hi = Math.imul(ah9, bh6);
|
|
lo = (lo + Math.imul(al8, bl7)) | 0;
|
|
mid = (mid + Math.imul(al8, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh7)) | 0;
|
|
lo = (lo + Math.imul(al7, bl8)) | 0;
|
|
mid = (mid + Math.imul(al7, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh8)) | 0;
|
|
lo = (lo + Math.imul(al6, bl9)) | 0;
|
|
mid = (mid + Math.imul(al6, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh9)) | 0;
|
|
var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
|
|
w15 &= 0x3ffffff;
|
|
/* k = 16 */
|
|
lo = Math.imul(al9, bl7);
|
|
mid = Math.imul(al9, bh7);
|
|
mid = (mid + Math.imul(ah9, bl7)) | 0;
|
|
hi = Math.imul(ah9, bh7);
|
|
lo = (lo + Math.imul(al8, bl8)) | 0;
|
|
mid = (mid + Math.imul(al8, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh8)) | 0;
|
|
lo = (lo + Math.imul(al7, bl9)) | 0;
|
|
mid = (mid + Math.imul(al7, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh9)) | 0;
|
|
var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
|
|
w16 &= 0x3ffffff;
|
|
/* k = 17 */
|
|
lo = Math.imul(al9, bl8);
|
|
mid = Math.imul(al9, bh8);
|
|
mid = (mid + Math.imul(ah9, bl8)) | 0;
|
|
hi = Math.imul(ah9, bh8);
|
|
lo = (lo + Math.imul(al8, bl9)) | 0;
|
|
mid = (mid + Math.imul(al8, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh9)) | 0;
|
|
var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
|
|
w17 &= 0x3ffffff;
|
|
/* k = 18 */
|
|
lo = Math.imul(al9, bl9);
|
|
mid = Math.imul(al9, bh9);
|
|
mid = (mid + Math.imul(ah9, bl9)) | 0;
|
|
hi = Math.imul(ah9, bh9);
|
|
var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
|
|
w18 &= 0x3ffffff;
|
|
o[0] = w0;
|
|
o[1] = w1;
|
|
o[2] = w2;
|
|
o[3] = w3;
|
|
o[4] = w4;
|
|
o[5] = w5;
|
|
o[6] = w6;
|
|
o[7] = w7;
|
|
o[8] = w8;
|
|
o[9] = w9;
|
|
o[10] = w10;
|
|
o[11] = w11;
|
|
o[12] = w12;
|
|
o[13] = w13;
|
|
o[14] = w14;
|
|
o[15] = w15;
|
|
o[16] = w16;
|
|
o[17] = w17;
|
|
o[18] = w18;
|
|
if (c !== 0) {
|
|
o[19] = c;
|
|
out.length++;
|
|
}
|
|
return out;
|
|
};
|
|
|
|
// Polyfill comb
|
|
if (!Math.imul) {
|
|
comb10MulTo = smallMulTo;
|
|
}
|
|
|
|
function bigMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
out.length = self.length + num.length;
|
|
|
|
var carry = 0;
|
|
var hncarry = 0;
|
|
for (var k = 0; k < out.length - 1; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = hncarry;
|
|
hncarry = 0;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = k - j;
|
|
var a = self.words[i] | 0;
|
|
var b = num.words[j] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
|
|
lo = (lo + rword) | 0;
|
|
rword = lo & 0x3ffffff;
|
|
ncarry = (ncarry + (lo >>> 26)) | 0;
|
|
|
|
hncarry += ncarry >>> 26;
|
|
ncarry &= 0x3ffffff;
|
|
}
|
|
out.words[k] = rword;
|
|
carry = ncarry;
|
|
ncarry = hncarry;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
function jumboMulTo (self, num, out) {
|
|
var fftm = new FFTM();
|
|
return fftm.mulp(self, num, out);
|
|
}
|
|
|
|
BN.prototype.mulTo = function mulTo (num, out) {
|
|
var res;
|
|
var len = this.length + num.length;
|
|
if (this.length === 10 && num.length === 10) {
|
|
res = comb10MulTo(this, num, out);
|
|
} else if (len < 63) {
|
|
res = smallMulTo(this, num, out);
|
|
} else if (len < 1024) {
|
|
res = bigMulTo(this, num, out);
|
|
} else {
|
|
res = jumboMulTo(this, num, out);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Cooley-Tukey algorithm for FFT
|
|
// slightly revisited to rely on looping instead of recursion
|
|
|
|
function FFTM (x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
FFTM.prototype.makeRBT = function makeRBT (N) {
|
|
var t = new Array(N);
|
|
var l = BN.prototype._countBits(N) - 1;
|
|
for (var i = 0; i < N; i++) {
|
|
t[i] = this.revBin(i, l, N);
|
|
}
|
|
|
|
return t;
|
|
};
|
|
|
|
// Returns binary-reversed representation of `x`
|
|
FFTM.prototype.revBin = function revBin (x, l, N) {
|
|
if (x === 0 || x === N - 1) return x;
|
|
|
|
var rb = 0;
|
|
for (var i = 0; i < l; i++) {
|
|
rb |= (x & 1) << (l - i - 1);
|
|
x >>= 1;
|
|
}
|
|
|
|
return rb;
|
|
};
|
|
|
|
// Performs "tweedling" phase, therefore 'emulating'
|
|
// behaviour of the recursive algorithm
|
|
FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
|
|
for (var i = 0; i < N; i++) {
|
|
rtws[i] = rws[rbt[i]];
|
|
itws[i] = iws[rbt[i]];
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
|
|
this.permute(rbt, rws, iws, rtws, itws, N);
|
|
|
|
for (var s = 1; s < N; s <<= 1) {
|
|
var l = s << 1;
|
|
|
|
var rtwdf = Math.cos(2 * Math.PI / l);
|
|
var itwdf = Math.sin(2 * Math.PI / l);
|
|
|
|
for (var p = 0; p < N; p += l) {
|
|
var rtwdf_ = rtwdf;
|
|
var itwdf_ = itwdf;
|
|
|
|
for (var j = 0; j < s; j++) {
|
|
var re = rtws[p + j];
|
|
var ie = itws[p + j];
|
|
|
|
var ro = rtws[p + j + s];
|
|
var io = itws[p + j + s];
|
|
|
|
var rx = rtwdf_ * ro - itwdf_ * io;
|
|
|
|
io = rtwdf_ * io + itwdf_ * ro;
|
|
ro = rx;
|
|
|
|
rtws[p + j] = re + ro;
|
|
itws[p + j] = ie + io;
|
|
|
|
rtws[p + j + s] = re - ro;
|
|
itws[p + j + s] = ie - io;
|
|
|
|
/* jshint maxdepth : false */
|
|
if (j !== l) {
|
|
rx = rtwdf * rtwdf_ - itwdf * itwdf_;
|
|
|
|
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
|
|
rtwdf_ = rx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
|
|
var N = Math.max(m, n) | 1;
|
|
var odd = N & 1;
|
|
var i = 0;
|
|
for (N = N / 2 | 0; N; N = N >>> 1) {
|
|
i++;
|
|
}
|
|
|
|
return 1 << i + 1 + odd;
|
|
};
|
|
|
|
FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
|
|
if (N <= 1) return;
|
|
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var t = rws[i];
|
|
|
|
rws[i] = rws[N - i - 1];
|
|
rws[N - i - 1] = t;
|
|
|
|
t = iws[i];
|
|
|
|
iws[i] = -iws[N - i - 1];
|
|
iws[N - i - 1] = -t;
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.normalize13b = function normalize13b (ws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
|
|
Math.round(ws[2 * i] / N) +
|
|
carry;
|
|
|
|
ws[i] = w & 0x3ffffff;
|
|
|
|
if (w < 0x4000000) {
|
|
carry = 0;
|
|
} else {
|
|
carry = w / 0x4000000 | 0;
|
|
}
|
|
}
|
|
|
|
return ws;
|
|
};
|
|
|
|
FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < len; i++) {
|
|
carry = carry + (ws[i] | 0);
|
|
|
|
rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
|
|
rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
|
|
}
|
|
|
|
// Pad with zeroes
|
|
for (i = 2 * len; i < N; ++i) {
|
|
rws[i] = 0;
|
|
}
|
|
|
|
assert(carry === 0);
|
|
assert((carry & ~0x1fff) === 0);
|
|
};
|
|
|
|
FFTM.prototype.stub = function stub (N) {
|
|
var ph = new Array(N);
|
|
for (var i = 0; i < N; i++) {
|
|
ph[i] = 0;
|
|
}
|
|
|
|
return ph;
|
|
};
|
|
|
|
FFTM.prototype.mulp = function mulp (x, y, out) {
|
|
var N = 2 * this.guessLen13b(x.length, y.length);
|
|
|
|
var rbt = this.makeRBT(N);
|
|
|
|
var _ = this.stub(N);
|
|
|
|
var rws = new Array(N);
|
|
var rwst = new Array(N);
|
|
var iwst = new Array(N);
|
|
|
|
var nrws = new Array(N);
|
|
var nrwst = new Array(N);
|
|
var niwst = new Array(N);
|
|
|
|
var rmws = out.words;
|
|
rmws.length = N;
|
|
|
|
this.convert13b(x.words, x.length, rws, N);
|
|
this.convert13b(y.words, y.length, nrws, N);
|
|
|
|
this.transform(rws, _, rwst, iwst, N, rbt);
|
|
this.transform(nrws, _, nrwst, niwst, N, rbt);
|
|
|
|
for (var i = 0; i < N; i++) {
|
|
var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
|
|
iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
|
|
rwst[i] = rx;
|
|
}
|
|
|
|
this.conjugate(rwst, iwst, N);
|
|
this.transform(rwst, iwst, rmws, _, N, rbt);
|
|
this.conjugate(rmws, _, N);
|
|
this.normalize13b(rmws, N);
|
|
|
|
out.negative = x.negative ^ y.negative;
|
|
out.length = x.length + y.length;
|
|
return out.strip();
|
|
};
|
|
|
|
// Multiply `this` by `num`
|
|
BN.prototype.mul = function mul (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return this.mulTo(num, out);
|
|
};
|
|
|
|
// Multiply employing FFT
|
|
BN.prototype.mulf = function mulf (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return jumboMulTo(this, num, out);
|
|
};
|
|
|
|
// In-place Multiplication
|
|
BN.prototype.imul = function imul (num) {
|
|
return this.clone().mulTo(num, this);
|
|
};
|
|
|
|
BN.prototype.imuln = function imuln (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
|
|
// Carry
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = (this.words[i] | 0) * num;
|
|
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
|
|
carry >>= 26;
|
|
carry += (w / 0x4000000) | 0;
|
|
// NOTE: lo is 27bit maximum
|
|
carry += lo >>> 26;
|
|
this.words[i] = lo & 0x3ffffff;
|
|
}
|
|
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.muln = function muln (num) {
|
|
return this.clone().imuln(num);
|
|
};
|
|
|
|
// `this` * `this`
|
|
BN.prototype.sqr = function sqr () {
|
|
return this.mul(this);
|
|
};
|
|
|
|
// `this` * `this` in-place
|
|
BN.prototype.isqr = function isqr () {
|
|
return this.imul(this.clone());
|
|
};
|
|
|
|
// Math.pow(`this`, `num`)
|
|
BN.prototype.pow = function pow (num) {
|
|
var w = toBitArray(num);
|
|
if (w.length === 0) return new BN(1);
|
|
|
|
// Skip leading zeroes
|
|
var res = this;
|
|
for (var i = 0; i < w.length; i++, res = res.sqr()) {
|
|
if (w[i] !== 0) break;
|
|
}
|
|
|
|
if (++i < w.length) {
|
|
for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
|
|
if (w[i] === 0) continue;
|
|
|
|
res = res.mul(q);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Shift-left in-place
|
|
BN.prototype.iushln = function iushln (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
|
|
var i;
|
|
|
|
if (r !== 0) {
|
|
var carry = 0;
|
|
|
|
for (i = 0; i < this.length; i++) {
|
|
var newCarry = this.words[i] & carryMask;
|
|
var c = ((this.words[i] | 0) - newCarry) << r;
|
|
this.words[i] = c | carry;
|
|
carry = newCarry >>> (26 - r);
|
|
}
|
|
|
|
if (carry) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
}
|
|
|
|
if (s !== 0) {
|
|
for (i = this.length - 1; i >= 0; i--) {
|
|
this.words[i + s] = this.words[i];
|
|
}
|
|
|
|
for (i = 0; i < s; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
this.length += s;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishln = function ishln (bits) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushln(bits);
|
|
};
|
|
|
|
// Shift-right in-place
|
|
// NOTE: `hint` is a lowest bit before trailing zeroes
|
|
// NOTE: if `extended` is present - it will be filled with destroyed bits
|
|
BN.prototype.iushrn = function iushrn (bits, hint, extended) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var h;
|
|
if (hint) {
|
|
h = (hint - (hint % 26)) / 26;
|
|
} else {
|
|
h = 0;
|
|
}
|
|
|
|
var r = bits % 26;
|
|
var s = Math.min((bits - r) / 26, this.length);
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
var maskedWords = extended;
|
|
|
|
h -= s;
|
|
h = Math.max(0, h);
|
|
|
|
// Extended mode, copy masked part
|
|
if (maskedWords) {
|
|
for (var i = 0; i < s; i++) {
|
|
maskedWords.words[i] = this.words[i];
|
|
}
|
|
maskedWords.length = s;
|
|
}
|
|
|
|
if (s === 0) {
|
|
// No-op, we should not move anything at all
|
|
} else if (this.length > s) {
|
|
this.length -= s;
|
|
for (i = 0; i < this.length; i++) {
|
|
this.words[i] = this.words[i + s];
|
|
}
|
|
} else {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
|
|
var word = this.words[i] | 0;
|
|
this.words[i] = (carry << (26 - r)) | (word >>> r);
|
|
carry = word & mask;
|
|
}
|
|
|
|
// Push carried bits as a mask
|
|
if (maskedWords && carry !== 0) {
|
|
maskedWords.words[maskedWords.length++] = carry;
|
|
}
|
|
|
|
if (this.length === 0) {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishrn = function ishrn (bits, hint, extended) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushrn(bits, hint, extended);
|
|
};
|
|
|
|
// Shift-left
|
|
BN.prototype.shln = function shln (bits) {
|
|
return this.clone().ishln(bits);
|
|
};
|
|
|
|
BN.prototype.ushln = function ushln (bits) {
|
|
return this.clone().iushln(bits);
|
|
};
|
|
|
|
// Shift-right
|
|
BN.prototype.shrn = function shrn (bits) {
|
|
return this.clone().ishrn(bits);
|
|
};
|
|
|
|
BN.prototype.ushrn = function ushrn (bits) {
|
|
return this.clone().iushrn(bits);
|
|
};
|
|
|
|
// Test if n bit is set
|
|
BN.prototype.testn = function testn (bit) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) return false;
|
|
|
|
// Check bit and return
|
|
var w = this.words[s];
|
|
|
|
return !!(w & q);
|
|
};
|
|
|
|
// Return only lowers bits of number (in-place)
|
|
BN.prototype.imaskn = function imaskn (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
|
|
assert(this.negative === 0, 'imaskn works only with positive numbers');
|
|
|
|
if (this.length <= s) {
|
|
return this;
|
|
}
|
|
|
|
if (r !== 0) {
|
|
s++;
|
|
}
|
|
this.length = Math.min(s, this.length);
|
|
|
|
if (r !== 0) {
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
this.words[this.length - 1] &= mask;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Return only lowers bits of number
|
|
BN.prototype.maskn = function maskn (bits) {
|
|
return this.clone().imaskn(bits);
|
|
};
|
|
|
|
// Add plain number `num` to `this`
|
|
BN.prototype.iaddn = function iaddn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.isubn(-num);
|
|
|
|
// Possible sign change
|
|
if (this.negative !== 0) {
|
|
if (this.length === 1 && (this.words[0] | 0) < num) {
|
|
this.words[0] = num - (this.words[0] | 0);
|
|
this.negative = 0;
|
|
return this;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.isubn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
// Add without checks
|
|
return this._iaddn(num);
|
|
};
|
|
|
|
BN.prototype._iaddn = function _iaddn (num) {
|
|
this.words[0] += num;
|
|
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
|
|
this.words[i] -= 0x4000000;
|
|
if (i === this.length - 1) {
|
|
this.words[i + 1] = 1;
|
|
} else {
|
|
this.words[i + 1]++;
|
|
}
|
|
}
|
|
this.length = Math.max(this.length, i + 1);
|
|
|
|
return this;
|
|
};
|
|
|
|
// Subtract plain number `num` from `this`
|
|
BN.prototype.isubn = function isubn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.iaddn(-num);
|
|
|
|
if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iaddn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
this.words[0] -= num;
|
|
|
|
if (this.length === 1 && this.words[0] < 0) {
|
|
this.words[0] = -this.words[0];
|
|
this.negative = 1;
|
|
} else {
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
|
|
this.words[i] += 0x4000000;
|
|
this.words[i + 1] -= 1;
|
|
}
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.addn = function addn (num) {
|
|
return this.clone().iaddn(num);
|
|
};
|
|
|
|
BN.prototype.subn = function subn (num) {
|
|
return this.clone().isubn(num);
|
|
};
|
|
|
|
BN.prototype.iabs = function iabs () {
|
|
this.negative = 0;
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.abs = function abs () {
|
|
return this.clone().iabs();
|
|
};
|
|
|
|
BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
|
|
var len = num.length + shift;
|
|
var i;
|
|
|
|
this._expand(len);
|
|
|
|
var w;
|
|
var carry = 0;
|
|
for (i = 0; i < num.length; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
var right = (num.words[i] | 0) * mul;
|
|
w -= right & 0x3ffffff;
|
|
carry = (w >> 26) - ((right / 0x4000000) | 0);
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
for (; i < this.length - shift; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
|
|
if (carry === 0) return this.strip();
|
|
|
|
// Subtraction overflow
|
|
assert(carry === -1);
|
|
carry = 0;
|
|
for (i = 0; i < this.length; i++) {
|
|
w = -(this.words[i] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i] = w & 0x3ffffff;
|
|
}
|
|
this.negative = 1;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype._wordDiv = function _wordDiv (num, mode) {
|
|
var shift = this.length - num.length;
|
|
|
|
var a = this.clone();
|
|
var b = num;
|
|
|
|
// Normalize
|
|
var bhi = b.words[b.length - 1] | 0;
|
|
var bhiBits = this._countBits(bhi);
|
|
shift = 26 - bhiBits;
|
|
if (shift !== 0) {
|
|
b = b.ushln(shift);
|
|
a.iushln(shift);
|
|
bhi = b.words[b.length - 1] | 0;
|
|
}
|
|
|
|
// Initialize quotient
|
|
var m = a.length - b.length;
|
|
var q;
|
|
|
|
if (mode !== 'mod') {
|
|
q = new BN(null);
|
|
q.length = m + 1;
|
|
q.words = new Array(q.length);
|
|
for (var i = 0; i < q.length; i++) {
|
|
q.words[i] = 0;
|
|
}
|
|
}
|
|
|
|
var diff = a.clone()._ishlnsubmul(b, 1, m);
|
|
if (diff.negative === 0) {
|
|
a = diff;
|
|
if (q) {
|
|
q.words[m] = 1;
|
|
}
|
|
}
|
|
|
|
for (var j = m - 1; j >= 0; j--) {
|
|
var qj = (a.words[b.length + j] | 0) * 0x4000000 +
|
|
(a.words[b.length + j - 1] | 0);
|
|
|
|
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
|
|
// (0x7ffffff)
|
|
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
|
|
|
|
a._ishlnsubmul(b, qj, j);
|
|
while (a.negative !== 0) {
|
|
qj--;
|
|
a.negative = 0;
|
|
a._ishlnsubmul(b, 1, j);
|
|
if (!a.isZero()) {
|
|
a.negative ^= 1;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.words[j] = qj;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.strip();
|
|
}
|
|
a.strip();
|
|
|
|
// Denormalize
|
|
if (mode !== 'div' && shift !== 0) {
|
|
a.iushrn(shift);
|
|
}
|
|
|
|
return {
|
|
div: q || null,
|
|
mod: a
|
|
};
|
|
};
|
|
|
|
// NOTE: 1) `mode` can be set to `mod` to request mod only,
|
|
// to `div` to request div only, or be absent to
|
|
// request both div & mod
|
|
// 2) `positive` is true if unsigned mod is requested
|
|
BN.prototype.divmod = function divmod (num, mode, positive) {
|
|
assert(!num.isZero());
|
|
|
|
if (this.isZero()) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: new BN(0)
|
|
};
|
|
}
|
|
|
|
var div, mod, res;
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
res = this.neg().divmod(num, mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.iadd(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
if (this.negative === 0 && num.negative !== 0) {
|
|
res = this.divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: res.mod
|
|
};
|
|
}
|
|
|
|
if ((this.negative & num.negative) !== 0) {
|
|
res = this.neg().divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.isub(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: res.div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
// Both numbers are positive at this point
|
|
|
|
// Strip both numbers to approximate shift value
|
|
if (num.length > this.length || this.cmp(num) < 0) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: this
|
|
};
|
|
}
|
|
|
|
// Very short reduction
|
|
if (num.length === 1) {
|
|
if (mode === 'div') {
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: null
|
|
};
|
|
}
|
|
|
|
if (mode === 'mod') {
|
|
return {
|
|
div: null,
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return this._wordDiv(num, mode);
|
|
};
|
|
|
|
// Find `this` / `num`
|
|
BN.prototype.div = function div (num) {
|
|
return this.divmod(num, 'div', false).div;
|
|
};
|
|
|
|
// Find `this` % `num`
|
|
BN.prototype.mod = function mod (num) {
|
|
return this.divmod(num, 'mod', false).mod;
|
|
};
|
|
|
|
BN.prototype.umod = function umod (num) {
|
|
return this.divmod(num, 'mod', true).mod;
|
|
};
|
|
|
|
// Find Round(`this` / `num`)
|
|
BN.prototype.divRound = function divRound (num) {
|
|
var dm = this.divmod(num);
|
|
|
|
// Fast case - exact division
|
|
if (dm.mod.isZero()) return dm.div;
|
|
|
|
var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
|
|
|
|
var half = num.ushrn(1);
|
|
var r2 = num.andln(1);
|
|
var cmp = mod.cmp(half);
|
|
|
|
// Round down
|
|
if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
|
|
|
|
// Round up
|
|
return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
|
|
};
|
|
|
|
BN.prototype.modn = function modn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
var p = (1 << 26) % num;
|
|
|
|
var acc = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
acc = (p * acc + (this.words[i] | 0)) % num;
|
|
}
|
|
|
|
return acc;
|
|
};
|
|
|
|
// In-place division by number
|
|
BN.prototype.idivn = function idivn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
|
|
var carry = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var w = (this.words[i] | 0) + carry * 0x4000000;
|
|
this.words[i] = (w / num) | 0;
|
|
carry = w % num;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.divn = function divn (num) {
|
|
return this.clone().idivn(num);
|
|
};
|
|
|
|
BN.prototype.egcd = function egcd (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var x = this;
|
|
var y = p.clone();
|
|
|
|
if (x.negative !== 0) {
|
|
x = x.umod(p);
|
|
} else {
|
|
x = x.clone();
|
|
}
|
|
|
|
// A * x + B * y = x
|
|
var A = new BN(1);
|
|
var B = new BN(0);
|
|
|
|
// C * x + D * y = y
|
|
var C = new BN(0);
|
|
var D = new BN(1);
|
|
|
|
var g = 0;
|
|
|
|
while (x.isEven() && y.isEven()) {
|
|
x.iushrn(1);
|
|
y.iushrn(1);
|
|
++g;
|
|
}
|
|
|
|
var yp = y.clone();
|
|
var xp = x.clone();
|
|
|
|
while (!x.isZero()) {
|
|
for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
x.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (A.isOdd() || B.isOdd()) {
|
|
A.iadd(yp);
|
|
B.isub(xp);
|
|
}
|
|
|
|
A.iushrn(1);
|
|
B.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
y.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (C.isOdd() || D.isOdd()) {
|
|
C.iadd(yp);
|
|
D.isub(xp);
|
|
}
|
|
|
|
C.iushrn(1);
|
|
D.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (x.cmp(y) >= 0) {
|
|
x.isub(y);
|
|
A.isub(C);
|
|
B.isub(D);
|
|
} else {
|
|
y.isub(x);
|
|
C.isub(A);
|
|
D.isub(B);
|
|
}
|
|
}
|
|
|
|
return {
|
|
a: C,
|
|
b: D,
|
|
gcd: y.iushln(g)
|
|
};
|
|
};
|
|
|
|
// This is reduced incarnation of the binary EEA
|
|
// above, designated to invert members of the
|
|
// _prime_ fields F(p) at a maximal speed
|
|
BN.prototype._invmp = function _invmp (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var a = this;
|
|
var b = p.clone();
|
|
|
|
if (a.negative !== 0) {
|
|
a = a.umod(p);
|
|
} else {
|
|
a = a.clone();
|
|
}
|
|
|
|
var x1 = new BN(1);
|
|
var x2 = new BN(0);
|
|
|
|
var delta = b.clone();
|
|
|
|
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
|
|
for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
a.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (x1.isOdd()) {
|
|
x1.iadd(delta);
|
|
}
|
|
|
|
x1.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
b.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (x2.isOdd()) {
|
|
x2.iadd(delta);
|
|
}
|
|
|
|
x2.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (a.cmp(b) >= 0) {
|
|
a.isub(b);
|
|
x1.isub(x2);
|
|
} else {
|
|
b.isub(a);
|
|
x2.isub(x1);
|
|
}
|
|
}
|
|
|
|
var res;
|
|
if (a.cmpn(1) === 0) {
|
|
res = x1;
|
|
} else {
|
|
res = x2;
|
|
}
|
|
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(p);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gcd = function gcd (num) {
|
|
if (this.isZero()) return num.abs();
|
|
if (num.isZero()) return this.abs();
|
|
|
|
var a = this.clone();
|
|
var b = num.clone();
|
|
a.negative = 0;
|
|
b.negative = 0;
|
|
|
|
// Remove common factor of two
|
|
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
|
|
a.iushrn(1);
|
|
b.iushrn(1);
|
|
}
|
|
|
|
do {
|
|
while (a.isEven()) {
|
|
a.iushrn(1);
|
|
}
|
|
while (b.isEven()) {
|
|
b.iushrn(1);
|
|
}
|
|
|
|
var r = a.cmp(b);
|
|
if (r < 0) {
|
|
// Swap `a` and `b` to make `a` always bigger than `b`
|
|
var t = a;
|
|
a = b;
|
|
b = t;
|
|
} else if (r === 0 || b.cmpn(1) === 0) {
|
|
break;
|
|
}
|
|
|
|
a.isub(b);
|
|
} while (true);
|
|
|
|
return b.iushln(shift);
|
|
};
|
|
|
|
// Invert number in the field F(num)
|
|
BN.prototype.invm = function invm (num) {
|
|
return this.egcd(num).a.umod(num);
|
|
};
|
|
|
|
BN.prototype.isEven = function isEven () {
|
|
return (this.words[0] & 1) === 0;
|
|
};
|
|
|
|
BN.prototype.isOdd = function isOdd () {
|
|
return (this.words[0] & 1) === 1;
|
|
};
|
|
|
|
// And first word and num
|
|
BN.prototype.andln = function andln (num) {
|
|
return this.words[0] & num;
|
|
};
|
|
|
|
// Increment at the bit position in-line
|
|
BN.prototype.bincn = function bincn (bit) {
|
|
assert(typeof bit === 'number');
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) {
|
|
this._expand(s + 1);
|
|
this.words[s] |= q;
|
|
return this;
|
|
}
|
|
|
|
// Add bit and propagate, if needed
|
|
var carry = q;
|
|
for (var i = s; carry !== 0 && i < this.length; i++) {
|
|
var w = this.words[i] | 0;
|
|
w += carry;
|
|
carry = w >>> 26;
|
|
w &= 0x3ffffff;
|
|
this.words[i] = w;
|
|
}
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.isZero = function isZero () {
|
|
return this.length === 1 && this.words[0] === 0;
|
|
};
|
|
|
|
BN.prototype.cmpn = function cmpn (num) {
|
|
var negative = num < 0;
|
|
|
|
if (this.negative !== 0 && !negative) return -1;
|
|
if (this.negative === 0 && negative) return 1;
|
|
|
|
this.strip();
|
|
|
|
var res;
|
|
if (this.length > 1) {
|
|
res = 1;
|
|
} else {
|
|
if (negative) {
|
|
num = -num;
|
|
}
|
|
|
|
assert(num <= 0x3ffffff, 'Number is too big');
|
|
|
|
var w = this.words[0] | 0;
|
|
res = w === num ? 0 : w < num ? -1 : 1;
|
|
}
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Compare two numbers and return:
|
|
// 1 - if `this` > `num`
|
|
// 0 - if `this` == `num`
|
|
// -1 - if `this` < `num`
|
|
BN.prototype.cmp = function cmp (num) {
|
|
if (this.negative !== 0 && num.negative === 0) return -1;
|
|
if (this.negative === 0 && num.negative !== 0) return 1;
|
|
|
|
var res = this.ucmp(num);
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Unsigned comparison
|
|
BN.prototype.ucmp = function ucmp (num) {
|
|
// At this point both numbers have the same sign
|
|
if (this.length > num.length) return 1;
|
|
if (this.length < num.length) return -1;
|
|
|
|
var res = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var a = this.words[i] | 0;
|
|
var b = num.words[i] | 0;
|
|
|
|
if (a === b) continue;
|
|
if (a < b) {
|
|
res = -1;
|
|
} else if (a > b) {
|
|
res = 1;
|
|
}
|
|
break;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gtn = function gtn (num) {
|
|
return this.cmpn(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gt = function gt (num) {
|
|
return this.cmp(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gten = function gten (num) {
|
|
return this.cmpn(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.gte = function gte (num) {
|
|
return this.cmp(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.ltn = function ltn (num) {
|
|
return this.cmpn(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lt = function lt (num) {
|
|
return this.cmp(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lten = function lten (num) {
|
|
return this.cmpn(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.lte = function lte (num) {
|
|
return this.cmp(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.eqn = function eqn (num) {
|
|
return this.cmpn(num) === 0;
|
|
};
|
|
|
|
BN.prototype.eq = function eq (num) {
|
|
return this.cmp(num) === 0;
|
|
};
|
|
|
|
//
|
|
// A reduce context, could be using montgomery or something better, depending
|
|
// on the `m` itself.
|
|
//
|
|
BN.red = function red (num) {
|
|
return new Red(num);
|
|
};
|
|
|
|
BN.prototype.toRed = function toRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
assert(this.negative === 0, 'red works only with positives');
|
|
return ctx.convertTo(this)._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.fromRed = function fromRed () {
|
|
assert(this.red, 'fromRed works only with numbers in reduction context');
|
|
return this.red.convertFrom(this);
|
|
};
|
|
|
|
BN.prototype._forceRed = function _forceRed (ctx) {
|
|
this.red = ctx;
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.forceRed = function forceRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
return this._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.redAdd = function redAdd (num) {
|
|
assert(this.red, 'redAdd works only with red numbers');
|
|
return this.red.add(this, num);
|
|
};
|
|
|
|
BN.prototype.redIAdd = function redIAdd (num) {
|
|
assert(this.red, 'redIAdd works only with red numbers');
|
|
return this.red.iadd(this, num);
|
|
};
|
|
|
|
BN.prototype.redSub = function redSub (num) {
|
|
assert(this.red, 'redSub works only with red numbers');
|
|
return this.red.sub(this, num);
|
|
};
|
|
|
|
BN.prototype.redISub = function redISub (num) {
|
|
assert(this.red, 'redISub works only with red numbers');
|
|
return this.red.isub(this, num);
|
|
};
|
|
|
|
BN.prototype.redShl = function redShl (num) {
|
|
assert(this.red, 'redShl works only with red numbers');
|
|
return this.red.shl(this, num);
|
|
};
|
|
|
|
BN.prototype.redMul = function redMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.mul(this, num);
|
|
};
|
|
|
|
BN.prototype.redIMul = function redIMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.imul(this, num);
|
|
};
|
|
|
|
BN.prototype.redSqr = function redSqr () {
|
|
assert(this.red, 'redSqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqr(this);
|
|
};
|
|
|
|
BN.prototype.redISqr = function redISqr () {
|
|
assert(this.red, 'redISqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.isqr(this);
|
|
};
|
|
|
|
// Square root over p
|
|
BN.prototype.redSqrt = function redSqrt () {
|
|
assert(this.red, 'redSqrt works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqrt(this);
|
|
};
|
|
|
|
BN.prototype.redInvm = function redInvm () {
|
|
assert(this.red, 'redInvm works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.invm(this);
|
|
};
|
|
|
|
// Return negative clone of `this` % `red modulo`
|
|
BN.prototype.redNeg = function redNeg () {
|
|
assert(this.red, 'redNeg works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.neg(this);
|
|
};
|
|
|
|
BN.prototype.redPow = function redPow (num) {
|
|
assert(this.red && !num.red, 'redPow(normalNum)');
|
|
this.red._verify1(this);
|
|
return this.red.pow(this, num);
|
|
};
|
|
|
|
// Prime numbers with efficient reduction
|
|
var primes = {
|
|
k256: null,
|
|
p224: null,
|
|
p192: null,
|
|
p25519: null
|
|
};
|
|
|
|
// Pseudo-Mersenne prime
|
|
function MPrime (name, p) {
|
|
// P = 2 ^ N - K
|
|
this.name = name;
|
|
this.p = new BN(p, 16);
|
|
this.n = this.p.bitLength();
|
|
this.k = new BN(1).iushln(this.n).isub(this.p);
|
|
|
|
this.tmp = this._tmp();
|
|
}
|
|
|
|
MPrime.prototype._tmp = function _tmp () {
|
|
var tmp = new BN(null);
|
|
tmp.words = new Array(Math.ceil(this.n / 13));
|
|
return tmp;
|
|
};
|
|
|
|
MPrime.prototype.ireduce = function ireduce (num) {
|
|
// Assumes that `num` is less than `P^2`
|
|
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
|
|
var r = num;
|
|
var rlen;
|
|
|
|
do {
|
|
this.split(r, this.tmp);
|
|
r = this.imulK(r);
|
|
r = r.iadd(this.tmp);
|
|
rlen = r.bitLength();
|
|
} while (rlen > this.n);
|
|
|
|
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
|
|
if (cmp === 0) {
|
|
r.words[0] = 0;
|
|
r.length = 1;
|
|
} else if (cmp > 0) {
|
|
r.isub(this.p);
|
|
} else {
|
|
if (r.strip !== undefined) {
|
|
// r is BN v4 instance
|
|
r.strip();
|
|
} else {
|
|
// r is BN v5 instance
|
|
r._strip();
|
|
}
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
MPrime.prototype.split = function split (input, out) {
|
|
input.iushrn(this.n, 0, out);
|
|
};
|
|
|
|
MPrime.prototype.imulK = function imulK (num) {
|
|
return num.imul(this.k);
|
|
};
|
|
|
|
function K256 () {
|
|
MPrime.call(
|
|
this,
|
|
'k256',
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
|
|
}
|
|
inherits(K256, MPrime);
|
|
|
|
K256.prototype.split = function split (input, output) {
|
|
// 256 = 9 * 26 + 22
|
|
var mask = 0x3fffff;
|
|
|
|
var outLen = Math.min(input.length, 9);
|
|
for (var i = 0; i < outLen; i++) {
|
|
output.words[i] = input.words[i];
|
|
}
|
|
output.length = outLen;
|
|
|
|
if (input.length <= 9) {
|
|
input.words[0] = 0;
|
|
input.length = 1;
|
|
return;
|
|
}
|
|
|
|
// Shift by 9 limbs
|
|
var prev = input.words[9];
|
|
output.words[output.length++] = prev & mask;
|
|
|
|
for (i = 10; i < input.length; i++) {
|
|
var next = input.words[i] | 0;
|
|
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
|
|
prev = next;
|
|
}
|
|
prev >>>= 22;
|
|
input.words[i - 10] = prev;
|
|
if (prev === 0 && input.length > 10) {
|
|
input.length -= 10;
|
|
} else {
|
|
input.length -= 9;
|
|
}
|
|
};
|
|
|
|
K256.prototype.imulK = function imulK (num) {
|
|
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
|
|
num.words[num.length] = 0;
|
|
num.words[num.length + 1] = 0;
|
|
num.length += 2;
|
|
|
|
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
|
|
var lo = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var w = num.words[i] | 0;
|
|
lo += w * 0x3d1;
|
|
num.words[i] = lo & 0x3ffffff;
|
|
lo = w * 0x40 + ((lo / 0x4000000) | 0);
|
|
}
|
|
|
|
// Fast length reduction
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
}
|
|
}
|
|
return num;
|
|
};
|
|
|
|
function P224 () {
|
|
MPrime.call(
|
|
this,
|
|
'p224',
|
|
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
|
|
}
|
|
inherits(P224, MPrime);
|
|
|
|
function P192 () {
|
|
MPrime.call(
|
|
this,
|
|
'p192',
|
|
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
|
|
}
|
|
inherits(P192, MPrime);
|
|
|
|
function P25519 () {
|
|
// 2 ^ 255 - 19
|
|
MPrime.call(
|
|
this,
|
|
'25519',
|
|
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
|
|
}
|
|
inherits(P25519, MPrime);
|
|
|
|
P25519.prototype.imulK = function imulK (num) {
|
|
// K = 0x13
|
|
var carry = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var hi = (num.words[i] | 0) * 0x13 + carry;
|
|
var lo = hi & 0x3ffffff;
|
|
hi >>>= 26;
|
|
|
|
num.words[i] = lo;
|
|
carry = hi;
|
|
}
|
|
if (carry !== 0) {
|
|
num.words[num.length++] = carry;
|
|
}
|
|
return num;
|
|
};
|
|
|
|
// Exported mostly for testing purposes, use plain name instead
|
|
BN._prime = function prime (name) {
|
|
// Cached version of prime
|
|
if (primes[name]) return primes[name];
|
|
|
|
var prime;
|
|
if (name === 'k256') {
|
|
prime = new K256();
|
|
} else if (name === 'p224') {
|
|
prime = new P224();
|
|
} else if (name === 'p192') {
|
|
prime = new P192();
|
|
} else if (name === 'p25519') {
|
|
prime = new P25519();
|
|
} else {
|
|
throw new Error('Unknown prime ' + name);
|
|
}
|
|
primes[name] = prime;
|
|
|
|
return prime;
|
|
};
|
|
|
|
//
|
|
// Base reduction engine
|
|
//
|
|
function Red (m) {
|
|
if (typeof m === 'string') {
|
|
var prime = BN._prime(m);
|
|
this.m = prime.p;
|
|
this.prime = prime;
|
|
} else {
|
|
assert(m.gtn(1), 'modulus must be greater than 1');
|
|
this.m = m;
|
|
this.prime = null;
|
|
}
|
|
}
|
|
|
|
Red.prototype._verify1 = function _verify1 (a) {
|
|
assert(a.negative === 0, 'red works only with positives');
|
|
assert(a.red, 'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype._verify2 = function _verify2 (a, b) {
|
|
assert((a.negative | b.negative) === 0, 'red works only with positives');
|
|
assert(a.red && a.red === b.red,
|
|
'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype.imod = function imod (a) {
|
|
if (this.prime) return this.prime.ireduce(a)._forceRed(this);
|
|
return a.umod(this.m)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.neg = function neg (a) {
|
|
if (a.isZero()) {
|
|
return a.clone();
|
|
}
|
|
|
|
return this.m.sub(a)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.add = function add (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.add(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.iadd = function iadd (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.iadd(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.sub = function sub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.sub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.isub = function isub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.isub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.shl = function shl (a, num) {
|
|
this._verify1(a);
|
|
return this.imod(a.ushln(num));
|
|
};
|
|
|
|
Red.prototype.imul = function imul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.imul(b));
|
|
};
|
|
|
|
Red.prototype.mul = function mul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.mul(b));
|
|
};
|
|
|
|
Red.prototype.isqr = function isqr (a) {
|
|
return this.imul(a, a.clone());
|
|
};
|
|
|
|
Red.prototype.sqr = function sqr (a) {
|
|
return this.mul(a, a);
|
|
};
|
|
|
|
Red.prototype.sqrt = function sqrt (a) {
|
|
if (a.isZero()) return a.clone();
|
|
|
|
var mod3 = this.m.andln(3);
|
|
assert(mod3 % 2 === 1);
|
|
|
|
// Fast case
|
|
if (mod3 === 3) {
|
|
var pow = this.m.add(new BN(1)).iushrn(2);
|
|
return this.pow(a, pow);
|
|
}
|
|
|
|
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
|
|
//
|
|
// Find Q and S, that Q * 2 ^ S = (P - 1)
|
|
var q = this.m.subn(1);
|
|
var s = 0;
|
|
while (!q.isZero() && q.andln(1) === 0) {
|
|
s++;
|
|
q.iushrn(1);
|
|
}
|
|
assert(!q.isZero());
|
|
|
|
var one = new BN(1).toRed(this);
|
|
var nOne = one.redNeg();
|
|
|
|
// Find quadratic non-residue
|
|
// NOTE: Max is such because of generalized Riemann hypothesis.
|
|
var lpow = this.m.subn(1).iushrn(1);
|
|
var z = this.m.bitLength();
|
|
z = new BN(2 * z * z).toRed(this);
|
|
|
|
while (this.pow(z, lpow).cmp(nOne) !== 0) {
|
|
z.redIAdd(nOne);
|
|
}
|
|
|
|
var c = this.pow(z, q);
|
|
var r = this.pow(a, q.addn(1).iushrn(1));
|
|
var t = this.pow(a, q);
|
|
var m = s;
|
|
while (t.cmp(one) !== 0) {
|
|
var tmp = t;
|
|
for (var i = 0; tmp.cmp(one) !== 0; i++) {
|
|
tmp = tmp.redSqr();
|
|
}
|
|
assert(i < m);
|
|
var b = this.pow(c, new BN(1).iushln(m - i - 1));
|
|
|
|
r = r.redMul(b);
|
|
c = b.redSqr();
|
|
t = t.redMul(c);
|
|
m = i;
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
Red.prototype.invm = function invm (a) {
|
|
var inv = a._invmp(this.m);
|
|
if (inv.negative !== 0) {
|
|
inv.negative = 0;
|
|
return this.imod(inv).redNeg();
|
|
} else {
|
|
return this.imod(inv);
|
|
}
|
|
};
|
|
|
|
Red.prototype.pow = function pow (a, num) {
|
|
if (num.isZero()) return new BN(1).toRed(this);
|
|
if (num.cmpn(1) === 0) return a.clone();
|
|
|
|
var windowSize = 4;
|
|
var wnd = new Array(1 << windowSize);
|
|
wnd[0] = new BN(1).toRed(this);
|
|
wnd[1] = a;
|
|
for (var i = 2; i < wnd.length; i++) {
|
|
wnd[i] = this.mul(wnd[i - 1], a);
|
|
}
|
|
|
|
var res = wnd[0];
|
|
var current = 0;
|
|
var currentLen = 0;
|
|
var start = num.bitLength() % 26;
|
|
if (start === 0) {
|
|
start = 26;
|
|
}
|
|
|
|
for (i = num.length - 1; i >= 0; i--) {
|
|
var word = num.words[i];
|
|
for (var j = start - 1; j >= 0; j--) {
|
|
var bit = (word >> j) & 1;
|
|
if (res !== wnd[0]) {
|
|
res = this.sqr(res);
|
|
}
|
|
|
|
if (bit === 0 && current === 0) {
|
|
currentLen = 0;
|
|
continue;
|
|
}
|
|
|
|
current <<= 1;
|
|
current |= bit;
|
|
currentLen++;
|
|
if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
|
|
|
|
res = this.mul(res, wnd[current]);
|
|
currentLen = 0;
|
|
current = 0;
|
|
}
|
|
start = 26;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.convertTo = function convertTo (num) {
|
|
var r = num.umod(this.m);
|
|
|
|
return r === num ? r.clone() : r;
|
|
};
|
|
|
|
Red.prototype.convertFrom = function convertFrom (num) {
|
|
var res = num.clone();
|
|
res.red = null;
|
|
return res;
|
|
};
|
|
|
|
//
|
|
// Montgomery method engine
|
|
//
|
|
|
|
BN.mont = function mont (num) {
|
|
return new Mont(num);
|
|
};
|
|
|
|
function Mont (m) {
|
|
Red.call(this, m);
|
|
|
|
this.shift = this.m.bitLength();
|
|
if (this.shift % 26 !== 0) {
|
|
this.shift += 26 - (this.shift % 26);
|
|
}
|
|
|
|
this.r = new BN(1).iushln(this.shift);
|
|
this.r2 = this.imod(this.r.sqr());
|
|
this.rinv = this.r._invmp(this.m);
|
|
|
|
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
|
|
this.minv = this.minv.umod(this.r);
|
|
this.minv = this.r.sub(this.minv);
|
|
}
|
|
inherits(Mont, Red);
|
|
|
|
Mont.prototype.convertTo = function convertTo (num) {
|
|
return this.imod(num.ushln(this.shift));
|
|
};
|
|
|
|
Mont.prototype.convertFrom = function convertFrom (num) {
|
|
var r = this.imod(num.mul(this.rinv));
|
|
r.red = null;
|
|
return r;
|
|
};
|
|
|
|
Mont.prototype.imul = function imul (a, b) {
|
|
if (a.isZero() || b.isZero()) {
|
|
a.words[0] = 0;
|
|
a.length = 1;
|
|
return a;
|
|
}
|
|
|
|
var t = a.imul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.mul = function mul (a, b) {
|
|
if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
|
|
|
|
var t = a.mul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.invm = function invm (a) {
|
|
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
|
|
var res = this.imod(a._invmp(this.m).mul(this.r2));
|
|
return res._forceRed(this);
|
|
};
|
|
})( false || module, this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/elliptic/package.json":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/elliptic/package.json ***!
|
|
\********************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = JSON.parse('{"name":"elliptic","version":"6.5.4","description":"EC cryptography","main":"lib/elliptic.js","files":["lib"],"scripts":{"lint":"eslint lib test","lint:fix":"npm run lint -- --fix","unit":"istanbul test _mocha --reporter=spec test/index.js","test":"npm run lint && npm run unit","version":"grunt dist && git add dist/"},"repository":{"type":"git","url":"git@github.com:indutny/elliptic"},"keywords":["EC","Elliptic","curve","Cryptography"],"author":"Fedor Indutny <fedor@indutny.com>","license":"MIT","bugs":{"url":"https://github.com/indutny/elliptic/issues"},"homepage":"https://github.com/indutny/elliptic","devDependencies":{"brfs":"^2.0.2","coveralls":"^3.1.0","eslint":"^7.6.0","grunt":"^1.2.1","grunt-browserify":"^5.3.0","grunt-cli":"^1.3.2","grunt-contrib-connect":"^3.0.0","grunt-contrib-copy":"^1.0.0","grunt-contrib-uglify":"^5.0.0","grunt-mocha-istanbul":"^5.0.2","grunt-saucelabs":"^9.0.1","istanbul":"^0.4.5","mocha":"^8.0.1"},"dependencies":{"bn.js":"^4.11.9","brorand":"^1.1.0","hash.js":"^1.0.0","hmac-drbg":"^1.0.1","inherits":"^2.0.4","minimalistic-assert":"^1.0.1","minimalistic-crypto-utils":"^1.0.1"}}');
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/end-of-stream/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/end-of-stream/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
var once = __webpack_require__(/*! once */ "./node_modules/once/once.js");
|
|
|
|
var noop = function() {};
|
|
|
|
var isRequest = function(stream) {
|
|
return stream.setHeader && typeof stream.abort === 'function';
|
|
};
|
|
|
|
var isChildProcess = function(stream) {
|
|
return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3
|
|
};
|
|
|
|
var eos = function(stream, opts, callback) {
|
|
if (typeof opts === 'function') return eos(stream, null, opts);
|
|
if (!opts) opts = {};
|
|
|
|
callback = once(callback || noop);
|
|
|
|
var ws = stream._writableState;
|
|
var rs = stream._readableState;
|
|
var readable = opts.readable || (opts.readable !== false && stream.readable);
|
|
var writable = opts.writable || (opts.writable !== false && stream.writable);
|
|
var cancelled = false;
|
|
|
|
var onlegacyfinish = function() {
|
|
if (!stream.writable) onfinish();
|
|
};
|
|
|
|
var onfinish = function() {
|
|
writable = false;
|
|
if (!readable) callback.call(stream);
|
|
};
|
|
|
|
var onend = function() {
|
|
readable = false;
|
|
if (!writable) callback.call(stream);
|
|
};
|
|
|
|
var onexit = function(exitCode) {
|
|
callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null);
|
|
};
|
|
|
|
var onerror = function(err) {
|
|
callback.call(stream, err);
|
|
};
|
|
|
|
var onclose = function() {
|
|
process.nextTick(onclosenexttick);
|
|
};
|
|
|
|
var onclosenexttick = function() {
|
|
if (cancelled) return;
|
|
if (readable && !(rs && (rs.ended && !rs.destroyed))) return callback.call(stream, new Error('premature close'));
|
|
if (writable && !(ws && (ws.ended && !ws.destroyed))) return callback.call(stream, new Error('premature close'));
|
|
};
|
|
|
|
var onrequest = function() {
|
|
stream.req.on('finish', onfinish);
|
|
};
|
|
|
|
if (isRequest(stream)) {
|
|
stream.on('complete', onfinish);
|
|
stream.on('abort', onclose);
|
|
if (stream.req) onrequest();
|
|
else stream.on('request', onrequest);
|
|
} else if (writable && !ws) { // legacy streams
|
|
stream.on('end', onlegacyfinish);
|
|
stream.on('close', onlegacyfinish);
|
|
}
|
|
|
|
if (isChildProcess(stream)) stream.on('exit', onexit);
|
|
|
|
stream.on('end', onend);
|
|
stream.on('finish', onfinish);
|
|
if (opts.error !== false) stream.on('error', onerror);
|
|
stream.on('close', onclose);
|
|
|
|
return function() {
|
|
cancelled = true;
|
|
stream.removeListener('complete', onfinish);
|
|
stream.removeListener('abort', onclose);
|
|
stream.removeListener('request', onrequest);
|
|
if (stream.req) stream.req.removeListener('finish', onfinish);
|
|
stream.removeListener('end', onlegacyfinish);
|
|
stream.removeListener('close', onlegacyfinish);
|
|
stream.removeListener('finish', onfinish);
|
|
stream.removeListener('exit', onexit);
|
|
stream.removeListener('end', onend);
|
|
stream.removeListener('error', onerror);
|
|
stream.removeListener('close', onclose);
|
|
};
|
|
};
|
|
|
|
module.exports = eos;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/err-code/index.js":
|
|
/*!****************************************!*\
|
|
!*** ./node_modules/err-code/index.js ***!
|
|
\****************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
/**
|
|
* @typedef {{ [key: string]: any }} Extensions
|
|
* @typedef {Error} Err
|
|
* @property {string} message
|
|
*/
|
|
|
|
/**
|
|
*
|
|
* @param {Error} obj
|
|
* @param {Extensions} props
|
|
* @returns {Error & Extensions}
|
|
*/
|
|
function assign(obj, props) {
|
|
for (const key in props) {
|
|
Object.defineProperty(obj, key, {
|
|
value: props[key],
|
|
enumerable: true,
|
|
configurable: true,
|
|
});
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {any} err - An Error
|
|
* @param {string|Extensions} code - A string code or props to set on the error
|
|
* @param {Extensions} [props] - Props to set on the error
|
|
* @returns {Error & Extensions}
|
|
*/
|
|
function createError(err, code, props) {
|
|
if (!err || typeof err === 'string') {
|
|
throw new TypeError('Please pass an Error to err-code');
|
|
}
|
|
|
|
if (!props) {
|
|
props = {};
|
|
}
|
|
|
|
if (typeof code === 'object') {
|
|
props = code;
|
|
code = '';
|
|
}
|
|
|
|
if (code) {
|
|
props.code = code;
|
|
}
|
|
|
|
try {
|
|
return assign(err, props);
|
|
} catch (_) {
|
|
props.message = err.message;
|
|
props.stack = err.stack;
|
|
|
|
const ErrClass = function () {};
|
|
|
|
ErrClass.prototype = Object.create(Object.getPrototypeOf(err));
|
|
|
|
// @ts-ignore
|
|
const output = assign(new ErrClass(), props);
|
|
|
|
return output;
|
|
}
|
|
}
|
|
|
|
module.exports = createError;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/es-abstract/helpers/getOwnPropertyDescriptor.js":
|
|
/*!**********************************************************************!*\
|
|
!*** ./node_modules/es-abstract/helpers/getOwnPropertyDescriptor.js ***!
|
|
\**********************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var GetIntrinsic = __webpack_require__(/*! get-intrinsic */ "./node_modules/get-intrinsic/index.js");
|
|
|
|
var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%');
|
|
if ($gOPD) {
|
|
try {
|
|
$gOPD([], 'length');
|
|
} catch (e) {
|
|
// IE 8 has a broken gOPD
|
|
$gOPD = null;
|
|
}
|
|
}
|
|
|
|
module.exports = $gOPD;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/es6-object-assign/index.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/es6-object-assign/index.js ***!
|
|
\*************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
/**
|
|
* Code refactored from Mozilla Developer Network:
|
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
|
|
*/
|
|
|
|
|
|
|
|
function assign(target, firstSource) {
|
|
if (target === undefined || target === null) {
|
|
throw new TypeError('Cannot convert first argument to object');
|
|
}
|
|
|
|
var to = Object(target);
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var nextSource = arguments[i];
|
|
if (nextSource === undefined || nextSource === null) {
|
|
continue;
|
|
}
|
|
|
|
var keysArray = Object.keys(Object(nextSource));
|
|
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
|
|
var nextKey = keysArray[nextIndex];
|
|
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
|
|
if (desc !== undefined && desc.enumerable) {
|
|
to[nextKey] = nextSource[nextKey];
|
|
}
|
|
}
|
|
}
|
|
return to;
|
|
}
|
|
|
|
function polyfill() {
|
|
if (!Object.assign) {
|
|
Object.defineProperty(Object, 'assign', {
|
|
enumerable: false,
|
|
configurable: true,
|
|
writable: true,
|
|
value: assign
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
assign: assign,
|
|
polyfill: polyfill
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/events/events.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/events/events.js ***!
|
|
\***************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
var R = typeof Reflect === 'object' ? Reflect : null
|
|
var ReflectApply = R && typeof R.apply === 'function'
|
|
? R.apply
|
|
: function ReflectApply(target, receiver, args) {
|
|
return Function.prototype.apply.call(target, receiver, args);
|
|
}
|
|
|
|
var ReflectOwnKeys
|
|
if (R && typeof R.ownKeys === 'function') {
|
|
ReflectOwnKeys = R.ownKeys
|
|
} else if (Object.getOwnPropertySymbols) {
|
|
ReflectOwnKeys = function ReflectOwnKeys(target) {
|
|
return Object.getOwnPropertyNames(target)
|
|
.concat(Object.getOwnPropertySymbols(target));
|
|
};
|
|
} else {
|
|
ReflectOwnKeys = function ReflectOwnKeys(target) {
|
|
return Object.getOwnPropertyNames(target);
|
|
};
|
|
}
|
|
|
|
function ProcessEmitWarning(warning) {
|
|
if (console && console.warn) console.warn(warning);
|
|
}
|
|
|
|
var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
|
|
return value !== value;
|
|
}
|
|
|
|
function EventEmitter() {
|
|
EventEmitter.init.call(this);
|
|
}
|
|
module.exports = EventEmitter;
|
|
module.exports.once = once;
|
|
|
|
// Backwards-compat with node 0.10.x
|
|
EventEmitter.EventEmitter = EventEmitter;
|
|
|
|
EventEmitter.prototype._events = undefined;
|
|
EventEmitter.prototype._eventsCount = 0;
|
|
EventEmitter.prototype._maxListeners = undefined;
|
|
|
|
// By default EventEmitters will print a warning if more than 10 listeners are
|
|
// added to it. This is a useful default which helps finding memory leaks.
|
|
var defaultMaxListeners = 10;
|
|
|
|
function checkListener(listener) {
|
|
if (typeof listener !== 'function') {
|
|
throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
|
|
enumerable: true,
|
|
get: function() {
|
|
return defaultMaxListeners;
|
|
},
|
|
set: function(arg) {
|
|
if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
|
|
throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
|
|
}
|
|
defaultMaxListeners = arg;
|
|
}
|
|
});
|
|
|
|
EventEmitter.init = function() {
|
|
|
|
if (this._events === undefined ||
|
|
this._events === Object.getPrototypeOf(this)._events) {
|
|
this._events = Object.create(null);
|
|
this._eventsCount = 0;
|
|
}
|
|
|
|
this._maxListeners = this._maxListeners || undefined;
|
|
};
|
|
|
|
// Obviously not all Emitters should be limited to 10. This function allows
|
|
// that to be increased. Set to zero for unlimited.
|
|
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
|
|
if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
|
|
throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
|
|
}
|
|
this._maxListeners = n;
|
|
return this;
|
|
};
|
|
|
|
function _getMaxListeners(that) {
|
|
if (that._maxListeners === undefined)
|
|
return EventEmitter.defaultMaxListeners;
|
|
return that._maxListeners;
|
|
}
|
|
|
|
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
|
|
return _getMaxListeners(this);
|
|
};
|
|
|
|
EventEmitter.prototype.emit = function emit(type) {
|
|
var args = [];
|
|
for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
|
|
var doError = (type === 'error');
|
|
|
|
var events = this._events;
|
|
if (events !== undefined)
|
|
doError = (doError && events.error === undefined);
|
|
else if (!doError)
|
|
return false;
|
|
|
|
// If there is no 'error' event listener then throw.
|
|
if (doError) {
|
|
var er;
|
|
if (args.length > 0)
|
|
er = args[0];
|
|
if (er instanceof Error) {
|
|
// Note: The comments on the `throw` lines are intentional, they show
|
|
// up in Node's output if this results in an unhandled exception.
|
|
throw er; // Unhandled 'error' event
|
|
}
|
|
// At least give some kind of context to the user
|
|
var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
|
|
err.context = er;
|
|
throw err; // Unhandled 'error' event
|
|
}
|
|
|
|
var handler = events[type];
|
|
|
|
if (handler === undefined)
|
|
return false;
|
|
|
|
if (typeof handler === 'function') {
|
|
ReflectApply(handler, this, args);
|
|
} else {
|
|
var len = handler.length;
|
|
var listeners = arrayClone(handler, len);
|
|
for (var i = 0; i < len; ++i)
|
|
ReflectApply(listeners[i], this, args);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
function _addListener(target, type, listener, prepend) {
|
|
var m;
|
|
var events;
|
|
var existing;
|
|
|
|
checkListener(listener);
|
|
|
|
events = target._events;
|
|
if (events === undefined) {
|
|
events = target._events = Object.create(null);
|
|
target._eventsCount = 0;
|
|
} else {
|
|
// To avoid recursion in the case that type === "newListener"! Before
|
|
// adding it to the listeners, first emit "newListener".
|
|
if (events.newListener !== undefined) {
|
|
target.emit('newListener', type,
|
|
listener.listener ? listener.listener : listener);
|
|
|
|
// Re-assign `events` because a newListener handler could have caused the
|
|
// this._events to be assigned to a new object
|
|
events = target._events;
|
|
}
|
|
existing = events[type];
|
|
}
|
|
|
|
if (existing === undefined) {
|
|
// Optimize the case of one listener. Don't need the extra array object.
|
|
existing = events[type] = listener;
|
|
++target._eventsCount;
|
|
} else {
|
|
if (typeof existing === 'function') {
|
|
// Adding the second element, need to change to array.
|
|
existing = events[type] =
|
|
prepend ? [listener, existing] : [existing, listener];
|
|
// If we've already got an array, just append.
|
|
} else if (prepend) {
|
|
existing.unshift(listener);
|
|
} else {
|
|
existing.push(listener);
|
|
}
|
|
|
|
// Check for listener leak
|
|
m = _getMaxListeners(target);
|
|
if (m > 0 && existing.length > m && !existing.warned) {
|
|
existing.warned = true;
|
|
// No error code for this since it is a Warning
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
var w = new Error('Possible EventEmitter memory leak detected. ' +
|
|
existing.length + ' ' + String(type) + ' listeners ' +
|
|
'added. Use emitter.setMaxListeners() to ' +
|
|
'increase limit');
|
|
w.name = 'MaxListenersExceededWarning';
|
|
w.emitter = target;
|
|
w.type = type;
|
|
w.count = existing.length;
|
|
ProcessEmitWarning(w);
|
|
}
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
EventEmitter.prototype.addListener = function addListener(type, listener) {
|
|
return _addListener(this, type, listener, false);
|
|
};
|
|
|
|
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|
|
|
EventEmitter.prototype.prependListener =
|
|
function prependListener(type, listener) {
|
|
return _addListener(this, type, listener, true);
|
|
};
|
|
|
|
function onceWrapper() {
|
|
if (!this.fired) {
|
|
this.target.removeListener(this.type, this.wrapFn);
|
|
this.fired = true;
|
|
if (arguments.length === 0)
|
|
return this.listener.call(this.target);
|
|
return this.listener.apply(this.target, arguments);
|
|
}
|
|
}
|
|
|
|
function _onceWrap(target, type, listener) {
|
|
var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
|
|
var wrapped = onceWrapper.bind(state);
|
|
wrapped.listener = listener;
|
|
state.wrapFn = wrapped;
|
|
return wrapped;
|
|
}
|
|
|
|
EventEmitter.prototype.once = function once(type, listener) {
|
|
checkListener(listener);
|
|
this.on(type, _onceWrap(this, type, listener));
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.prependOnceListener =
|
|
function prependOnceListener(type, listener) {
|
|
checkListener(listener);
|
|
this.prependListener(type, _onceWrap(this, type, listener));
|
|
return this;
|
|
};
|
|
|
|
// Emits a 'removeListener' event if and only if the listener was removed.
|
|
EventEmitter.prototype.removeListener =
|
|
function removeListener(type, listener) {
|
|
var list, events, position, i, originalListener;
|
|
|
|
checkListener(listener);
|
|
|
|
events = this._events;
|
|
if (events === undefined)
|
|
return this;
|
|
|
|
list = events[type];
|
|
if (list === undefined)
|
|
return this;
|
|
|
|
if (list === listener || list.listener === listener) {
|
|
if (--this._eventsCount === 0)
|
|
this._events = Object.create(null);
|
|
else {
|
|
delete events[type];
|
|
if (events.removeListener)
|
|
this.emit('removeListener', type, list.listener || listener);
|
|
}
|
|
} else if (typeof list !== 'function') {
|
|
position = -1;
|
|
|
|
for (i = list.length - 1; i >= 0; i--) {
|
|
if (list[i] === listener || list[i].listener === listener) {
|
|
originalListener = list[i].listener;
|
|
position = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (position < 0)
|
|
return this;
|
|
|
|
if (position === 0)
|
|
list.shift();
|
|
else {
|
|
spliceOne(list, position);
|
|
}
|
|
|
|
if (list.length === 1)
|
|
events[type] = list[0];
|
|
|
|
if (events.removeListener !== undefined)
|
|
this.emit('removeListener', type, originalListener || listener);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
|
|
|
EventEmitter.prototype.removeAllListeners =
|
|
function removeAllListeners(type) {
|
|
var listeners, events, i;
|
|
|
|
events = this._events;
|
|
if (events === undefined)
|
|
return this;
|
|
|
|
// not listening for removeListener, no need to emit
|
|
if (events.removeListener === undefined) {
|
|
if (arguments.length === 0) {
|
|
this._events = Object.create(null);
|
|
this._eventsCount = 0;
|
|
} else if (events[type] !== undefined) {
|
|
if (--this._eventsCount === 0)
|
|
this._events = Object.create(null);
|
|
else
|
|
delete events[type];
|
|
}
|
|
return this;
|
|
}
|
|
|
|
// emit removeListener for all listeners on all events
|
|
if (arguments.length === 0) {
|
|
var keys = Object.keys(events);
|
|
var key;
|
|
for (i = 0; i < keys.length; ++i) {
|
|
key = keys[i];
|
|
if (key === 'removeListener') continue;
|
|
this.removeAllListeners(key);
|
|
}
|
|
this.removeAllListeners('removeListener');
|
|
this._events = Object.create(null);
|
|
this._eventsCount = 0;
|
|
return this;
|
|
}
|
|
|
|
listeners = events[type];
|
|
|
|
if (typeof listeners === 'function') {
|
|
this.removeListener(type, listeners);
|
|
} else if (listeners !== undefined) {
|
|
// LIFO order
|
|
for (i = listeners.length - 1; i >= 0; i--) {
|
|
this.removeListener(type, listeners[i]);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
function _listeners(target, type, unwrap) {
|
|
var events = target._events;
|
|
|
|
if (events === undefined)
|
|
return [];
|
|
|
|
var evlistener = events[type];
|
|
if (evlistener === undefined)
|
|
return [];
|
|
|
|
if (typeof evlistener === 'function')
|
|
return unwrap ? [evlistener.listener || evlistener] : [evlistener];
|
|
|
|
return unwrap ?
|
|
unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
|
|
}
|
|
|
|
EventEmitter.prototype.listeners = function listeners(type) {
|
|
return _listeners(this, type, true);
|
|
};
|
|
|
|
EventEmitter.prototype.rawListeners = function rawListeners(type) {
|
|
return _listeners(this, type, false);
|
|
};
|
|
|
|
EventEmitter.listenerCount = function(emitter, type) {
|
|
if (typeof emitter.listenerCount === 'function') {
|
|
return emitter.listenerCount(type);
|
|
} else {
|
|
return listenerCount.call(emitter, type);
|
|
}
|
|
};
|
|
|
|
EventEmitter.prototype.listenerCount = listenerCount;
|
|
function listenerCount(type) {
|
|
var events = this._events;
|
|
|
|
if (events !== undefined) {
|
|
var evlistener = events[type];
|
|
|
|
if (typeof evlistener === 'function') {
|
|
return 1;
|
|
} else if (evlistener !== undefined) {
|
|
return evlistener.length;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EventEmitter.prototype.eventNames = function eventNames() {
|
|
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
|
|
};
|
|
|
|
function arrayClone(arr, n) {
|
|
var copy = new Array(n);
|
|
for (var i = 0; i < n; ++i)
|
|
copy[i] = arr[i];
|
|
return copy;
|
|
}
|
|
|
|
function spliceOne(list, index) {
|
|
for (; index + 1 < list.length; index++)
|
|
list[index] = list[index + 1];
|
|
list.pop();
|
|
}
|
|
|
|
function unwrapListeners(arr) {
|
|
var ret = new Array(arr.length);
|
|
for (var i = 0; i < ret.length; ++i) {
|
|
ret[i] = arr[i].listener || arr[i];
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
function once(emitter, name) {
|
|
return new Promise(function (resolve, reject) {
|
|
function errorListener(err) {
|
|
emitter.removeListener(name, resolver);
|
|
reject(err);
|
|
}
|
|
|
|
function resolver() {
|
|
if (typeof emitter.removeListener === 'function') {
|
|
emitter.removeListener('error', errorListener);
|
|
}
|
|
resolve([].slice.call(arguments));
|
|
};
|
|
|
|
eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
|
|
if (name !== 'error') {
|
|
addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
|
|
}
|
|
});
|
|
}
|
|
|
|
function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
|
|
if (typeof emitter.on === 'function') {
|
|
eventTargetAgnosticAddListener(emitter, 'error', handler, flags);
|
|
}
|
|
}
|
|
|
|
function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
|
|
if (typeof emitter.on === 'function') {
|
|
if (flags.once) {
|
|
emitter.once(name, listener);
|
|
} else {
|
|
emitter.on(name, listener);
|
|
}
|
|
} else if (typeof emitter.addEventListener === 'function') {
|
|
// EventTarget does not have `error` event semantics like Node
|
|
// EventEmitters, we do not listen for `error` events here.
|
|
emitter.addEventListener(name, function wrapListener(arg) {
|
|
// IE does not have builtin `{ once: true }` support so we
|
|
// have to do it manually.
|
|
if (flags.once) {
|
|
emitter.removeEventListener(name, wrapListener);
|
|
}
|
|
listener(arg);
|
|
});
|
|
} else {
|
|
throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/evp_bytestokey/index.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/evp_bytestokey/index.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var MD5 = __webpack_require__(/*! md5.js */ "./node_modules/md5.js/index.js")
|
|
|
|
/* eslint-disable camelcase */
|
|
function EVP_BytesToKey (password, salt, keyBits, ivLen) {
|
|
if (!Buffer.isBuffer(password)) password = Buffer.from(password, 'binary')
|
|
if (salt) {
|
|
if (!Buffer.isBuffer(salt)) salt = Buffer.from(salt, 'binary')
|
|
if (salt.length !== 8) throw new RangeError('salt should be Buffer with 8 byte length')
|
|
}
|
|
|
|
var keyLen = keyBits / 8
|
|
var key = Buffer.alloc(keyLen)
|
|
var iv = Buffer.alloc(ivLen || 0)
|
|
var tmp = Buffer.alloc(0)
|
|
|
|
while (keyLen > 0 || ivLen > 0) {
|
|
var hash = new MD5()
|
|
hash.update(tmp)
|
|
hash.update(password)
|
|
if (salt) hash.update(salt)
|
|
tmp = hash.digest()
|
|
|
|
var used = 0
|
|
|
|
if (keyLen > 0) {
|
|
var keyStart = key.length - keyLen
|
|
used = Math.min(keyLen, tmp.length)
|
|
tmp.copy(key, keyStart, 0, used)
|
|
keyLen -= used
|
|
}
|
|
|
|
if (used < tmp.length && ivLen > 0) {
|
|
var ivStart = iv.length - ivLen
|
|
var length = Math.min(ivLen, tmp.length - used)
|
|
tmp.copy(iv, ivStart, used, used + length)
|
|
ivLen -= length
|
|
}
|
|
}
|
|
|
|
tmp.fill(0)
|
|
return { key: key, iv: iv }
|
|
}
|
|
|
|
module.exports = EVP_BytesToKey
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/fast-fifo/fixed-size.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/fast-fifo/fixed-size.js ***!
|
|
\**********************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = class FixedFIFO {
|
|
constructor (hwm) {
|
|
if (!(hwm > 0) || ((hwm - 1) & hwm) !== 0) throw new Error('Max size for a FixedFIFO should be a power of two')
|
|
this.buffer = new Array(hwm)
|
|
this.mask = hwm - 1
|
|
this.top = 0
|
|
this.btm = 0
|
|
this.next = null
|
|
}
|
|
|
|
push (data) {
|
|
if (this.buffer[this.top] !== undefined) return false
|
|
this.buffer[this.top] = data
|
|
this.top = (this.top + 1) & this.mask
|
|
return true
|
|
}
|
|
|
|
shift () {
|
|
const last = this.buffer[this.btm]
|
|
if (last === undefined) return undefined
|
|
this.buffer[this.btm] = undefined
|
|
this.btm = (this.btm + 1) & this.mask
|
|
return last
|
|
}
|
|
|
|
isEmpty () {
|
|
return this.buffer[this.btm] === undefined
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/fast-fifo/index.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/fast-fifo/index.js ***!
|
|
\*****************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const FixedFIFO = __webpack_require__(/*! ./fixed-size */ "./node_modules/fast-fifo/fixed-size.js")
|
|
|
|
module.exports = class FastFIFO {
|
|
constructor (hwm) {
|
|
this.hwm = hwm || 16
|
|
this.head = new FixedFIFO(this.hwm)
|
|
this.tail = this.head
|
|
}
|
|
|
|
push (val) {
|
|
if (!this.head.push(val)) {
|
|
const prev = this.head
|
|
this.head = prev.next = new FixedFIFO(2 * this.head.buffer.length)
|
|
this.head.push(val)
|
|
}
|
|
}
|
|
|
|
shift () {
|
|
const val = this.tail.shift()
|
|
if (val === undefined && this.tail.next) {
|
|
const next = this.tail.next
|
|
this.tail.next = null
|
|
this.tail = next
|
|
return this.tail.shift()
|
|
}
|
|
return val
|
|
}
|
|
|
|
isEmpty () {
|
|
return this.head.isEmpty()
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/filestream/read.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/filestream/read.js ***!
|
|
\*****************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* global FileReader */
|
|
|
|
const { Readable } = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
const toBuffer = __webpack_require__(/*! typedarray-to-buffer */ "./node_modules/typedarray-to-buffer/index.js")
|
|
|
|
class FileReadStream extends Readable {
|
|
constructor (file, opts = {}) {
|
|
super(opts)
|
|
|
|
// save the read offset
|
|
this._offset = 0
|
|
this._ready = false
|
|
this._file = file
|
|
this._size = file.size
|
|
this._chunkSize = opts.chunkSize || Math.max(this._size / 1000, 200 * 1024)
|
|
|
|
// create the reader
|
|
const reader = new FileReader()
|
|
|
|
reader.onload = () => {
|
|
// get the data chunk
|
|
this.push(toBuffer(reader.result))
|
|
}
|
|
reader.onerror = () => {
|
|
this.emit('error', reader.error)
|
|
}
|
|
|
|
this.reader = reader
|
|
|
|
// generate the header blocks that we will send as part of the initial payload
|
|
this._generateHeaderBlocks(file, opts, (err, blocks) => {
|
|
// if we encountered an error, emit it
|
|
if (err) {
|
|
return this.emit('error', err)
|
|
}
|
|
|
|
// push the header blocks out to the stream
|
|
if (Array.isArray(blocks)) {
|
|
blocks.forEach(block => this.push(block))
|
|
}
|
|
|
|
this._ready = true
|
|
this.emit('_ready')
|
|
})
|
|
}
|
|
|
|
_generateHeaderBlocks (file, opts, callback) {
|
|
callback(null, [])
|
|
}
|
|
|
|
_read () {
|
|
if (!this._ready) {
|
|
this.once('_ready', this._read.bind(this))
|
|
return
|
|
}
|
|
|
|
const startOffset = this._offset
|
|
let endOffset = this._offset + this._chunkSize
|
|
if (endOffset > this._size) endOffset = this._size
|
|
|
|
if (startOffset === this._size) {
|
|
this.destroy()
|
|
this.push(null)
|
|
return
|
|
}
|
|
|
|
this.reader.readAsArrayBuffer(this._file.slice(startOffset, endOffset))
|
|
|
|
// update the stream offset
|
|
this._offset = endOffset
|
|
}
|
|
|
|
destroy () {
|
|
this._file = null
|
|
if (this.reader) {
|
|
this.reader.onload = null
|
|
this.reader.onerror = null
|
|
try { this.reader.abort() } catch (e) {};
|
|
}
|
|
this.reader = null
|
|
}
|
|
}
|
|
|
|
module.exports = FileReadStream
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/foreach/index.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/foreach/index.js ***!
|
|
\***************************************/
|
|
/***/ ((module) => {
|
|
|
|
|
|
var hasOwn = Object.prototype.hasOwnProperty;
|
|
var toString = Object.prototype.toString;
|
|
|
|
module.exports = function forEach (obj, fn, ctx) {
|
|
if (toString.call(fn) !== '[object Function]') {
|
|
throw new TypeError('iterator must be a function');
|
|
}
|
|
var l = obj.length;
|
|
if (l === +l) {
|
|
for (var i = 0; i < l; i++) {
|
|
fn.call(ctx, obj[i], i, obj);
|
|
}
|
|
} else {
|
|
for (var k in obj) {
|
|
if (hasOwn.call(obj, k)) {
|
|
fn.call(ctx, obj[k], k, obj);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/fs-access-chunk-store/index.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/fs-access-chunk-store/index.js ***!
|
|
\*****************************************************/
|
|
/***/ ((module) => {
|
|
|
|
/* eslint-env browser */
|
|
class WebFsChunkStore {
|
|
constructor (chunkLength, opts = {}) {
|
|
this.chunkLength = Number(chunkLength)
|
|
|
|
if (!this.chunkLength) {
|
|
throw new Error('First argument must be a chunk length')
|
|
}
|
|
|
|
this.closed = false
|
|
|
|
this.name = opts.name || 'default'
|
|
|
|
this.rootDirPromise = opts.rootDir || navigator.storage.getDirectory()
|
|
this.storageDirPromise = this._getStorageDirectoryHandle()
|
|
this.chunksDirPromise = ((opts.files && opts.rootDir) && this._getChunksDirHandle()) || this.storageDirPromise
|
|
|
|
this.chunks = [] // individual chunks, required for reads :/
|
|
this.chunkMap = [] // full files
|
|
this.directoryMap = {}
|
|
|
|
if (opts.files && opts.rootDir) {
|
|
this.files = opts.files.slice(0).map((file, i, files) => {
|
|
if (file.path == null) throw new Error('File is missing `path` property')
|
|
if (file.length == null) throw new Error('File is missing `length` property')
|
|
if (file.offset == null) {
|
|
if (i === 0) {
|
|
file.offset = 0
|
|
} else {
|
|
const prevFile = files[i - 1]
|
|
file.offset = prevFile.offset + prevFile.length
|
|
}
|
|
}
|
|
|
|
// file handles
|
|
if (file.handle == null) {
|
|
file.handle = this._createFileHandle({ path: file.path })
|
|
}
|
|
|
|
// file chunkMap
|
|
const fileStart = file.offset
|
|
const fileEnd = file.offset + file.length
|
|
|
|
const firstChunk = Math.floor(fileStart / this.chunkLength)
|
|
const lastChunk = Math.floor((fileEnd - 1) / this.chunkLength)
|
|
|
|
for (let p = firstChunk; p <= lastChunk; ++p) {
|
|
const chunkStart = p * this.chunkLength
|
|
const chunkEnd = chunkStart + this.chunkLength
|
|
|
|
const from = (fileStart < chunkStart) ? 0 : fileStart - chunkStart
|
|
const to = (fileEnd > chunkEnd) ? this.chunkLength : fileEnd - chunkStart
|
|
const offset = (fileStart > chunkStart) ? 0 : chunkStart - fileStart
|
|
|
|
if (!this.chunkMap[p]) this.chunkMap[p] = []
|
|
|
|
this.chunkMap[p].push({ from, to, offset, file })
|
|
}
|
|
|
|
return file
|
|
})
|
|
|
|
// close streams is page is frozen/unloaded, they will re-open if the user returns via BFC
|
|
window.addEventListener('pagehide', this.cleanup)
|
|
|
|
this.length = this.files.reduce((sum, file) => sum + file.length, 0)
|
|
if (opts.length != null && opts.length !== this.length) {
|
|
throw new Error('total `files` length is not equal to explicit `length` option')
|
|
}
|
|
} else {
|
|
this.length = Number(opts.length) || Infinity
|
|
}
|
|
|
|
if (this.length !== Infinity) {
|
|
this.lastChunkLength = this.length % this.chunkLength || this.chunkLength
|
|
this.lastChunkIndex = Math.ceil(this.length / this.chunkLength) - 1
|
|
}
|
|
}
|
|
|
|
async _getChunksDirHandle () {
|
|
const storageDir = await this.storageDirPromise
|
|
return await storageDir.getDirectoryHandle('chunks', { create: true })
|
|
}
|
|
|
|
async _getStorageDirectoryHandle () {
|
|
const rootDir = await this.rootDirPromise
|
|
return await rootDir.getDirectoryHandle(this.name, { create: true })
|
|
}
|
|
|
|
async _getChunk (index) {
|
|
let chunk = this.chunks[index]
|
|
|
|
if (!chunk) {
|
|
const fileName = index.toString()
|
|
const storageDir = await this.chunksDirPromise
|
|
|
|
chunk = this.chunks[index] = { fileHandlePromise: storageDir.getFileHandle(fileName, { create: true }) }
|
|
}
|
|
|
|
return chunk
|
|
}
|
|
|
|
async _createFileHandle (opts) {
|
|
const fileName = opts.path.slice(opts.path.lastIndexOf('/') + 1)
|
|
return (await this._getDirectoryHandle(opts)).getFileHandle(fileName, { create: true })
|
|
}
|
|
|
|
// recursive, equiv of cd and mkdirp
|
|
async _getDirectoryHandle (opts) {
|
|
const lastIndex = opts.path.lastIndexOf('/')
|
|
if (lastIndex === -1 || lastIndex === 0) return this.storageDirPromise
|
|
const path = opts.path = opts.path.slice(0, lastIndex)
|
|
if (!this.directoryMap[path]) {
|
|
const parent = this._getDirectoryHandle(opts)
|
|
this.directoryMap[path] = (await parent).getDirectoryHandle(path.slice(path.lastIndexOf('/') + 1), { create: true })
|
|
}
|
|
return this.directoryMap[path]
|
|
}
|
|
|
|
put (index, buf, cb = () => {}) {
|
|
if (this.closed) {
|
|
queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
return
|
|
}
|
|
|
|
const isLastChunk = index === this.lastChunkIndex
|
|
if (isLastChunk && buf.length !== this.lastChunkLength) {
|
|
queueMicrotask(() => {
|
|
cb(new Error(`Last chunk length must be ${this.lastChunkLength}`))
|
|
})
|
|
return
|
|
}
|
|
if (!isLastChunk && buf.length !== this.chunkLength) {
|
|
queueMicrotask(() => {
|
|
cb(new Error(`Chunk length must be ${this.chunkLength}`))
|
|
})
|
|
return
|
|
}
|
|
|
|
;(async () => {
|
|
try {
|
|
const chunk = await this._getChunk(index)
|
|
const fileHandle = await chunk.fileHandlePromise
|
|
const stream = await fileHandle.createWritable({
|
|
keepExistingData: false
|
|
})
|
|
await stream.write(buf)
|
|
await stream.close()
|
|
} catch (err) {
|
|
cb(err)
|
|
return
|
|
}
|
|
|
|
if (!this.files) cb(null)
|
|
})()
|
|
|
|
if (this.files) {
|
|
const targets = this.chunkMap[index]
|
|
if (!targets) {
|
|
queueMicrotask(() => cb(new Error('No files matching the request range')))
|
|
}
|
|
const promises = targets.map(target => {
|
|
return (async () => {
|
|
try {
|
|
const { file } = target
|
|
if (!file.stream) {
|
|
file.stream = (await file.handle).createWritable({
|
|
keepExistingData: true
|
|
})
|
|
}
|
|
const stream = await file.stream
|
|
await stream.write({ type: 'write', position: target.offset, data: buf.slice(target.from, target.to) })
|
|
return null
|
|
} catch (err) {
|
|
return cb(err)
|
|
}
|
|
})()
|
|
})
|
|
Promise.all(promises).then(() => cb(null))
|
|
}
|
|
}
|
|
|
|
get (index, opts, cb = () => {}) {
|
|
if (typeof opts === 'function') {
|
|
return this.get(index, null, opts)
|
|
}
|
|
if (this.closed) {
|
|
queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
return
|
|
}
|
|
|
|
const isLastChunk = index === this.lastChunkIndex
|
|
const chunkLength = isLastChunk ? this.lastChunkLength : this.chunkLength
|
|
|
|
if (!opts) opts = {}
|
|
|
|
const rangeFrom = opts.offset || 0
|
|
const rangeTo = opts.length ? rangeFrom + opts.length : chunkLength
|
|
const len = opts.length || chunkLength - rangeFrom
|
|
|
|
if (!this.files || this.chunks[index]) {
|
|
;(async () => {
|
|
let buf
|
|
try {
|
|
const chunk = await this._getChunk(index)
|
|
const fileHandle = await chunk.fileHandlePromise
|
|
let file = await fileHandle.getFile()
|
|
if (rangeFrom !== 0 || len !== chunkLength) {
|
|
file = file.slice(rangeFrom, len + rangeFrom)
|
|
}
|
|
buf = await file.arrayBuffer()
|
|
} catch (err) {
|
|
cb(err)
|
|
return
|
|
}
|
|
|
|
if (buf.byteLength === 0) {
|
|
const err = new Error(`Index ${index} does not exist`)
|
|
err.notFound = true
|
|
cb(err)
|
|
return
|
|
}
|
|
|
|
cb(null, new Uint8Array(buf))
|
|
})()
|
|
} else {
|
|
let targets = this.chunkMap[index]
|
|
if (!targets) {
|
|
queueMicrotask(() => cb(new Error('No files matching the request range')))
|
|
}
|
|
if (opts) {
|
|
targets = targets.filter(target => {
|
|
return target.to > rangeFrom && target.from < rangeTo
|
|
})
|
|
if (targets.length === 0) {
|
|
queueMicrotask(() => cb(new Error('No files matching the request range')))
|
|
}
|
|
}
|
|
if (rangeFrom === rangeTo) return queueMicrotask(() => cb(null, new Uint8Array(0)))
|
|
|
|
const promises = targets.map(target => {
|
|
return (async () => {
|
|
let from = target.from
|
|
let to = target.to
|
|
let offset = target.offset
|
|
|
|
if (opts) {
|
|
if (to > rangeTo) to = rangeTo
|
|
if (from < rangeFrom) {
|
|
offset += (rangeFrom - from)
|
|
from = rangeFrom
|
|
}
|
|
}
|
|
try {
|
|
const handle = await target.file.handle
|
|
const file = (await handle.getFile()).slice(offset, offset + to - from)
|
|
return await file.arrayBuffer()
|
|
} catch (err) {
|
|
return err
|
|
}
|
|
})()
|
|
})
|
|
Promise.all(promises).then(values => {
|
|
if (values.length === 1) {
|
|
cb(null, new Uint8Array(values[0]))
|
|
} else {
|
|
new Blob(values).arrayBuffer().then(buf => {
|
|
cb(null, new Uint8Array(buf))
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
close (cb = () => {}) {
|
|
if (this.closed) {
|
|
queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
return
|
|
}
|
|
|
|
this.closed = true
|
|
this.chunkMap = []
|
|
this.directoryMap = {}
|
|
|
|
this.cleanup()
|
|
|
|
queueMicrotask(() => {
|
|
cb(null)
|
|
})
|
|
}
|
|
|
|
async cleanup () {
|
|
if (this.files) {
|
|
for (const file of this.files) {
|
|
if (file.stream) {
|
|
await (await file.stream).close()
|
|
file.stream = null
|
|
}
|
|
}
|
|
const storageDir = await this.storageDirPromise
|
|
await storageDir.removeEntry('chunks', { recursive: true })
|
|
}
|
|
this.chunks = []
|
|
}
|
|
|
|
destroy (cb = () => {}) {
|
|
if (this.closed) {
|
|
queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
return
|
|
}
|
|
|
|
const handleClose = async err => {
|
|
if (err) {
|
|
cb(err)
|
|
return
|
|
}
|
|
|
|
try {
|
|
const rootDir = await this.rootDirPromise
|
|
await rootDir.removeEntry(this.name, { recursive: true })
|
|
} catch (err) {
|
|
cb(err)
|
|
return
|
|
}
|
|
cb(null)
|
|
}
|
|
|
|
this.close(handleClose)
|
|
}
|
|
}
|
|
|
|
module.exports = WebFsChunkStore
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/function-bind/implementation.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/function-bind/implementation.js ***!
|
|
\******************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
/* eslint no-invalid-this: 1 */
|
|
|
|
var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
|
|
var slice = Array.prototype.slice;
|
|
var toStr = Object.prototype.toString;
|
|
var funcType = '[object Function]';
|
|
|
|
module.exports = function bind(that) {
|
|
var target = this;
|
|
if (typeof target !== 'function' || toStr.call(target) !== funcType) {
|
|
throw new TypeError(ERROR_MESSAGE + target);
|
|
}
|
|
var args = slice.call(arguments, 1);
|
|
|
|
var bound;
|
|
var binder = function () {
|
|
if (this instanceof bound) {
|
|
var result = target.apply(
|
|
this,
|
|
args.concat(slice.call(arguments))
|
|
);
|
|
if (Object(result) === result) {
|
|
return result;
|
|
}
|
|
return this;
|
|
} else {
|
|
return target.apply(
|
|
that,
|
|
args.concat(slice.call(arguments))
|
|
);
|
|
}
|
|
};
|
|
|
|
var boundLength = Math.max(0, target.length - args.length);
|
|
var boundArgs = [];
|
|
for (var i = 0; i < boundLength; i++) {
|
|
boundArgs.push('$' + i);
|
|
}
|
|
|
|
bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
|
|
|
|
if (target.prototype) {
|
|
var Empty = function Empty() {};
|
|
Empty.prototype = target.prototype;
|
|
bound.prototype = new Empty();
|
|
Empty.prototype = null;
|
|
}
|
|
|
|
return bound;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/function-bind/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/function-bind/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var implementation = __webpack_require__(/*! ./implementation */ "./node_modules/function-bind/implementation.js");
|
|
|
|
module.exports = Function.prototype.bind || implementation;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/get-browser-rtc/index.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/get-browser-rtc/index.js ***!
|
|
\***********************************************/
|
|
/***/ ((module) => {
|
|
|
|
// originally pulled out of simple-peer
|
|
|
|
module.exports = function getBrowserRTC () {
|
|
if (typeof globalThis === 'undefined') return null
|
|
var wrtc = {
|
|
RTCPeerConnection: globalThis.RTCPeerConnection || globalThis.mozRTCPeerConnection ||
|
|
globalThis.webkitRTCPeerConnection,
|
|
RTCSessionDescription: globalThis.RTCSessionDescription ||
|
|
globalThis.mozRTCSessionDescription || globalThis.webkitRTCSessionDescription,
|
|
RTCIceCandidate: globalThis.RTCIceCandidate || globalThis.mozRTCIceCandidate ||
|
|
globalThis.webkitRTCIceCandidate
|
|
}
|
|
if (!wrtc.RTCPeerConnection) return null
|
|
return wrtc
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/get-intrinsic/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/get-intrinsic/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var undefined;
|
|
|
|
var $SyntaxError = SyntaxError;
|
|
var $Function = Function;
|
|
var $TypeError = TypeError;
|
|
|
|
// eslint-disable-next-line consistent-return
|
|
var getEvalledConstructor = function (expressionSyntax) {
|
|
try {
|
|
return $Function('"use strict"; return (' + expressionSyntax + ').constructor;')();
|
|
} catch (e) {}
|
|
};
|
|
|
|
var $gOPD = Object.getOwnPropertyDescriptor;
|
|
if ($gOPD) {
|
|
try {
|
|
$gOPD({}, '');
|
|
} catch (e) {
|
|
$gOPD = null; // this is IE 8, which has a broken gOPD
|
|
}
|
|
}
|
|
|
|
var throwTypeError = function () {
|
|
throw new $TypeError();
|
|
};
|
|
var ThrowTypeError = $gOPD
|
|
? (function () {
|
|
try {
|
|
// eslint-disable-next-line no-unused-expressions, no-caller, no-restricted-properties
|
|
arguments.callee; // IE 8 does not throw here
|
|
return throwTypeError;
|
|
} catch (calleeThrows) {
|
|
try {
|
|
// IE 8 throws on Object.getOwnPropertyDescriptor(arguments, '')
|
|
return $gOPD(arguments, 'callee').get;
|
|
} catch (gOPDthrows) {
|
|
return throwTypeError;
|
|
}
|
|
}
|
|
}())
|
|
: throwTypeError;
|
|
|
|
var hasSymbols = __webpack_require__(/*! has-symbols */ "./node_modules/has-symbols/index.js")();
|
|
|
|
var getProto = Object.getPrototypeOf || function (x) { return x.__proto__; }; // eslint-disable-line no-proto
|
|
|
|
var needsEval = {};
|
|
|
|
var TypedArray = typeof Uint8Array === 'undefined' ? undefined : getProto(Uint8Array);
|
|
|
|
var INTRINSICS = {
|
|
'%AggregateError%': typeof AggregateError === 'undefined' ? undefined : AggregateError,
|
|
'%Array%': Array,
|
|
'%ArrayBuffer%': typeof ArrayBuffer === 'undefined' ? undefined : ArrayBuffer,
|
|
'%ArrayIteratorPrototype%': hasSymbols ? getProto([][Symbol.iterator]()) : undefined,
|
|
'%AsyncFromSyncIteratorPrototype%': undefined,
|
|
'%AsyncFunction%': needsEval,
|
|
'%AsyncGenerator%': needsEval,
|
|
'%AsyncGeneratorFunction%': needsEval,
|
|
'%AsyncIteratorPrototype%': needsEval,
|
|
'%Atomics%': typeof Atomics === 'undefined' ? undefined : Atomics,
|
|
'%BigInt%': typeof BigInt === 'undefined' ? undefined : BigInt,
|
|
'%Boolean%': Boolean,
|
|
'%DataView%': typeof DataView === 'undefined' ? undefined : DataView,
|
|
'%Date%': Date,
|
|
'%decodeURI%': decodeURI,
|
|
'%decodeURIComponent%': decodeURIComponent,
|
|
'%encodeURI%': encodeURI,
|
|
'%encodeURIComponent%': encodeURIComponent,
|
|
'%Error%': Error,
|
|
'%eval%': eval, // eslint-disable-line no-eval
|
|
'%EvalError%': EvalError,
|
|
'%Float32Array%': typeof Float32Array === 'undefined' ? undefined : Float32Array,
|
|
'%Float64Array%': typeof Float64Array === 'undefined' ? undefined : Float64Array,
|
|
'%FinalizationRegistry%': typeof FinalizationRegistry === 'undefined' ? undefined : FinalizationRegistry,
|
|
'%Function%': $Function,
|
|
'%GeneratorFunction%': needsEval,
|
|
'%Int8Array%': typeof Int8Array === 'undefined' ? undefined : Int8Array,
|
|
'%Int16Array%': typeof Int16Array === 'undefined' ? undefined : Int16Array,
|
|
'%Int32Array%': typeof Int32Array === 'undefined' ? undefined : Int32Array,
|
|
'%isFinite%': isFinite,
|
|
'%isNaN%': isNaN,
|
|
'%IteratorPrototype%': hasSymbols ? getProto(getProto([][Symbol.iterator]())) : undefined,
|
|
'%JSON%': typeof JSON === 'object' ? JSON : undefined,
|
|
'%Map%': typeof Map === 'undefined' ? undefined : Map,
|
|
'%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols ? undefined : getProto(new Map()[Symbol.iterator]()),
|
|
'%Math%': Math,
|
|
'%Number%': Number,
|
|
'%Object%': Object,
|
|
'%parseFloat%': parseFloat,
|
|
'%parseInt%': parseInt,
|
|
'%Promise%': typeof Promise === 'undefined' ? undefined : Promise,
|
|
'%Proxy%': typeof Proxy === 'undefined' ? undefined : Proxy,
|
|
'%RangeError%': RangeError,
|
|
'%ReferenceError%': ReferenceError,
|
|
'%Reflect%': typeof Reflect === 'undefined' ? undefined : Reflect,
|
|
'%RegExp%': RegExp,
|
|
'%Set%': typeof Set === 'undefined' ? undefined : Set,
|
|
'%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols ? undefined : getProto(new Set()[Symbol.iterator]()),
|
|
'%SharedArrayBuffer%': typeof SharedArrayBuffer === 'undefined' ? undefined : SharedArrayBuffer,
|
|
'%String%': String,
|
|
'%StringIteratorPrototype%': hasSymbols ? getProto(''[Symbol.iterator]()) : undefined,
|
|
'%Symbol%': hasSymbols ? Symbol : undefined,
|
|
'%SyntaxError%': $SyntaxError,
|
|
'%ThrowTypeError%': ThrowTypeError,
|
|
'%TypedArray%': TypedArray,
|
|
'%TypeError%': $TypeError,
|
|
'%Uint8Array%': typeof Uint8Array === 'undefined' ? undefined : Uint8Array,
|
|
'%Uint8ClampedArray%': typeof Uint8ClampedArray === 'undefined' ? undefined : Uint8ClampedArray,
|
|
'%Uint16Array%': typeof Uint16Array === 'undefined' ? undefined : Uint16Array,
|
|
'%Uint32Array%': typeof Uint32Array === 'undefined' ? undefined : Uint32Array,
|
|
'%URIError%': URIError,
|
|
'%WeakMap%': typeof WeakMap === 'undefined' ? undefined : WeakMap,
|
|
'%WeakRef%': typeof WeakRef === 'undefined' ? undefined : WeakRef,
|
|
'%WeakSet%': typeof WeakSet === 'undefined' ? undefined : WeakSet
|
|
};
|
|
|
|
var doEval = function doEval(name) {
|
|
var value;
|
|
if (name === '%AsyncFunction%') {
|
|
value = getEvalledConstructor('async function () {}');
|
|
} else if (name === '%GeneratorFunction%') {
|
|
value = getEvalledConstructor('function* () {}');
|
|
} else if (name === '%AsyncGeneratorFunction%') {
|
|
value = getEvalledConstructor('async function* () {}');
|
|
} else if (name === '%AsyncGenerator%') {
|
|
var fn = doEval('%AsyncGeneratorFunction%');
|
|
if (fn) {
|
|
value = fn.prototype;
|
|
}
|
|
} else if (name === '%AsyncIteratorPrototype%') {
|
|
var gen = doEval('%AsyncGenerator%');
|
|
if (gen) {
|
|
value = getProto(gen.prototype);
|
|
}
|
|
}
|
|
|
|
INTRINSICS[name] = value;
|
|
|
|
return value;
|
|
};
|
|
|
|
var LEGACY_ALIASES = {
|
|
'%ArrayBufferPrototype%': ['ArrayBuffer', 'prototype'],
|
|
'%ArrayPrototype%': ['Array', 'prototype'],
|
|
'%ArrayProto_entries%': ['Array', 'prototype', 'entries'],
|
|
'%ArrayProto_forEach%': ['Array', 'prototype', 'forEach'],
|
|
'%ArrayProto_keys%': ['Array', 'prototype', 'keys'],
|
|
'%ArrayProto_values%': ['Array', 'prototype', 'values'],
|
|
'%AsyncFunctionPrototype%': ['AsyncFunction', 'prototype'],
|
|
'%AsyncGenerator%': ['AsyncGeneratorFunction', 'prototype'],
|
|
'%AsyncGeneratorPrototype%': ['AsyncGeneratorFunction', 'prototype', 'prototype'],
|
|
'%BooleanPrototype%': ['Boolean', 'prototype'],
|
|
'%DataViewPrototype%': ['DataView', 'prototype'],
|
|
'%DatePrototype%': ['Date', 'prototype'],
|
|
'%ErrorPrototype%': ['Error', 'prototype'],
|
|
'%EvalErrorPrototype%': ['EvalError', 'prototype'],
|
|
'%Float32ArrayPrototype%': ['Float32Array', 'prototype'],
|
|
'%Float64ArrayPrototype%': ['Float64Array', 'prototype'],
|
|
'%FunctionPrototype%': ['Function', 'prototype'],
|
|
'%Generator%': ['GeneratorFunction', 'prototype'],
|
|
'%GeneratorPrototype%': ['GeneratorFunction', 'prototype', 'prototype'],
|
|
'%Int8ArrayPrototype%': ['Int8Array', 'prototype'],
|
|
'%Int16ArrayPrototype%': ['Int16Array', 'prototype'],
|
|
'%Int32ArrayPrototype%': ['Int32Array', 'prototype'],
|
|
'%JSONParse%': ['JSON', 'parse'],
|
|
'%JSONStringify%': ['JSON', 'stringify'],
|
|
'%MapPrototype%': ['Map', 'prototype'],
|
|
'%NumberPrototype%': ['Number', 'prototype'],
|
|
'%ObjectPrototype%': ['Object', 'prototype'],
|
|
'%ObjProto_toString%': ['Object', 'prototype', 'toString'],
|
|
'%ObjProto_valueOf%': ['Object', 'prototype', 'valueOf'],
|
|
'%PromisePrototype%': ['Promise', 'prototype'],
|
|
'%PromiseProto_then%': ['Promise', 'prototype', 'then'],
|
|
'%Promise_all%': ['Promise', 'all'],
|
|
'%Promise_reject%': ['Promise', 'reject'],
|
|
'%Promise_resolve%': ['Promise', 'resolve'],
|
|
'%RangeErrorPrototype%': ['RangeError', 'prototype'],
|
|
'%ReferenceErrorPrototype%': ['ReferenceError', 'prototype'],
|
|
'%RegExpPrototype%': ['RegExp', 'prototype'],
|
|
'%SetPrototype%': ['Set', 'prototype'],
|
|
'%SharedArrayBufferPrototype%': ['SharedArrayBuffer', 'prototype'],
|
|
'%StringPrototype%': ['String', 'prototype'],
|
|
'%SymbolPrototype%': ['Symbol', 'prototype'],
|
|
'%SyntaxErrorPrototype%': ['SyntaxError', 'prototype'],
|
|
'%TypedArrayPrototype%': ['TypedArray', 'prototype'],
|
|
'%TypeErrorPrototype%': ['TypeError', 'prototype'],
|
|
'%Uint8ArrayPrototype%': ['Uint8Array', 'prototype'],
|
|
'%Uint8ClampedArrayPrototype%': ['Uint8ClampedArray', 'prototype'],
|
|
'%Uint16ArrayPrototype%': ['Uint16Array', 'prototype'],
|
|
'%Uint32ArrayPrototype%': ['Uint32Array', 'prototype'],
|
|
'%URIErrorPrototype%': ['URIError', 'prototype'],
|
|
'%WeakMapPrototype%': ['WeakMap', 'prototype'],
|
|
'%WeakSetPrototype%': ['WeakSet', 'prototype']
|
|
};
|
|
|
|
var bind = __webpack_require__(/*! function-bind */ "./node_modules/function-bind/index.js");
|
|
var hasOwn = __webpack_require__(/*! has */ "./node_modules/has/src/index.js");
|
|
var $concat = bind.call(Function.call, Array.prototype.concat);
|
|
var $spliceApply = bind.call(Function.apply, Array.prototype.splice);
|
|
var $replace = bind.call(Function.call, String.prototype.replace);
|
|
var $strSlice = bind.call(Function.call, String.prototype.slice);
|
|
|
|
/* adapted from https://github.com/lodash/lodash/blob/4.17.15/dist/lodash.js#L6735-L6744 */
|
|
var rePropName = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g;
|
|
var reEscapeChar = /\\(\\)?/g; /** Used to match backslashes in property paths. */
|
|
var stringToPath = function stringToPath(string) {
|
|
var first = $strSlice(string, 0, 1);
|
|
var last = $strSlice(string, -1);
|
|
if (first === '%' && last !== '%') {
|
|
throw new $SyntaxError('invalid intrinsic syntax, expected closing `%`');
|
|
} else if (last === '%' && first !== '%') {
|
|
throw new $SyntaxError('invalid intrinsic syntax, expected opening `%`');
|
|
}
|
|
var result = [];
|
|
$replace(string, rePropName, function (match, number, quote, subString) {
|
|
result[result.length] = quote ? $replace(subString, reEscapeChar, '$1') : number || match;
|
|
});
|
|
return result;
|
|
};
|
|
/* end adaptation */
|
|
|
|
var getBaseIntrinsic = function getBaseIntrinsic(name, allowMissing) {
|
|
var intrinsicName = name;
|
|
var alias;
|
|
if (hasOwn(LEGACY_ALIASES, intrinsicName)) {
|
|
alias = LEGACY_ALIASES[intrinsicName];
|
|
intrinsicName = '%' + alias[0] + '%';
|
|
}
|
|
|
|
if (hasOwn(INTRINSICS, intrinsicName)) {
|
|
var value = INTRINSICS[intrinsicName];
|
|
if (value === needsEval) {
|
|
value = doEval(intrinsicName);
|
|
}
|
|
if (typeof value === 'undefined' && !allowMissing) {
|
|
throw new $TypeError('intrinsic ' + name + ' exists, but is not available. Please file an issue!');
|
|
}
|
|
|
|
return {
|
|
alias: alias,
|
|
name: intrinsicName,
|
|
value: value
|
|
};
|
|
}
|
|
|
|
throw new $SyntaxError('intrinsic ' + name + ' does not exist!');
|
|
};
|
|
|
|
module.exports = function GetIntrinsic(name, allowMissing) {
|
|
if (typeof name !== 'string' || name.length === 0) {
|
|
throw new $TypeError('intrinsic name must be a non-empty string');
|
|
}
|
|
if (arguments.length > 1 && typeof allowMissing !== 'boolean') {
|
|
throw new $TypeError('"allowMissing" argument must be a boolean');
|
|
}
|
|
|
|
var parts = stringToPath(name);
|
|
var intrinsicBaseName = parts.length > 0 ? parts[0] : '';
|
|
|
|
var intrinsic = getBaseIntrinsic('%' + intrinsicBaseName + '%', allowMissing);
|
|
var intrinsicRealName = intrinsic.name;
|
|
var value = intrinsic.value;
|
|
var skipFurtherCaching = false;
|
|
|
|
var alias = intrinsic.alias;
|
|
if (alias) {
|
|
intrinsicBaseName = alias[0];
|
|
$spliceApply(parts, $concat([0, 1], alias));
|
|
}
|
|
|
|
for (var i = 1, isOwn = true; i < parts.length; i += 1) {
|
|
var part = parts[i];
|
|
var first = $strSlice(part, 0, 1);
|
|
var last = $strSlice(part, -1);
|
|
if (
|
|
(
|
|
(first === '"' || first === "'" || first === '`')
|
|
|| (last === '"' || last === "'" || last === '`')
|
|
)
|
|
&& first !== last
|
|
) {
|
|
throw new $SyntaxError('property names with quotes must have matching quotes');
|
|
}
|
|
if (part === 'constructor' || !isOwn) {
|
|
skipFurtherCaching = true;
|
|
}
|
|
|
|
intrinsicBaseName += '.' + part;
|
|
intrinsicRealName = '%' + intrinsicBaseName + '%';
|
|
|
|
if (hasOwn(INTRINSICS, intrinsicRealName)) {
|
|
value = INTRINSICS[intrinsicRealName];
|
|
} else if (value != null) {
|
|
if (!(part in value)) {
|
|
if (!allowMissing) {
|
|
throw new $TypeError('base intrinsic for ' + name + ' exists, but the property is not available.');
|
|
}
|
|
return void undefined;
|
|
}
|
|
if ($gOPD && (i + 1) >= parts.length) {
|
|
var desc = $gOPD(value, part);
|
|
isOwn = !!desc;
|
|
|
|
// By convention, when a data property is converted to an accessor
|
|
// property to emulate a data property that does not suffer from
|
|
// the override mistake, that accessor's getter is marked with
|
|
// an `originalValue` property. Here, when we detect this, we
|
|
// uphold the illusion by pretending to see that original data
|
|
// property, i.e., returning the value rather than the getter
|
|
// itself.
|
|
if (isOwn && 'get' in desc && !('originalValue' in desc.get)) {
|
|
value = desc.get;
|
|
} else {
|
|
value = value[part];
|
|
}
|
|
} else {
|
|
isOwn = hasOwn(value, part);
|
|
value = value[part];
|
|
}
|
|
|
|
if (isOwn && !skipFurtherCaching) {
|
|
INTRINSICS[intrinsicRealName] = value;
|
|
}
|
|
}
|
|
}
|
|
return value;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/has-symbols/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/has-symbols/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var origSymbol = typeof Symbol !== 'undefined' && Symbol;
|
|
var hasSymbolSham = __webpack_require__(/*! ./shams */ "./node_modules/has-symbols/shams.js");
|
|
|
|
module.exports = function hasNativeSymbols() {
|
|
if (typeof origSymbol !== 'function') { return false; }
|
|
if (typeof Symbol !== 'function') { return false; }
|
|
if (typeof origSymbol('foo') !== 'symbol') { return false; }
|
|
if (typeof Symbol('bar') !== 'symbol') { return false; }
|
|
|
|
return hasSymbolSham();
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/has-symbols/shams.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/has-symbols/shams.js ***!
|
|
\*******************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
/* eslint complexity: [2, 18], max-statements: [2, 33] */
|
|
module.exports = function hasSymbols() {
|
|
if (typeof Symbol !== 'function' || typeof Object.getOwnPropertySymbols !== 'function') { return false; }
|
|
if (typeof Symbol.iterator === 'symbol') { return true; }
|
|
|
|
var obj = {};
|
|
var sym = Symbol('test');
|
|
var symObj = Object(sym);
|
|
if (typeof sym === 'string') { return false; }
|
|
|
|
if (Object.prototype.toString.call(sym) !== '[object Symbol]') { return false; }
|
|
if (Object.prototype.toString.call(symObj) !== '[object Symbol]') { return false; }
|
|
|
|
// temp disabled per https://github.com/ljharb/object.assign/issues/17
|
|
// if (sym instanceof Symbol) { return false; }
|
|
// temp disabled per https://github.com/WebReflection/get-own-property-symbols/issues/4
|
|
// if (!(symObj instanceof Symbol)) { return false; }
|
|
|
|
// if (typeof Symbol.prototype.toString !== 'function') { return false; }
|
|
// if (String(sym) !== Symbol.prototype.toString.call(sym)) { return false; }
|
|
|
|
var symVal = 42;
|
|
obj[sym] = symVal;
|
|
for (sym in obj) { return false; } // eslint-disable-line no-restricted-syntax, no-unreachable-loop
|
|
if (typeof Object.keys === 'function' && Object.keys(obj).length !== 0) { return false; }
|
|
|
|
if (typeof Object.getOwnPropertyNames === 'function' && Object.getOwnPropertyNames(obj).length !== 0) { return false; }
|
|
|
|
var syms = Object.getOwnPropertySymbols(obj);
|
|
if (syms.length !== 1 || syms[0] !== sym) { return false; }
|
|
|
|
if (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { return false; }
|
|
|
|
if (typeof Object.getOwnPropertyDescriptor === 'function') {
|
|
var descriptor = Object.getOwnPropertyDescriptor(obj, sym);
|
|
if (descriptor.value !== symVal || descriptor.enumerable !== true) { return false; }
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/has/src/index.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/has/src/index.js ***!
|
|
\***************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var bind = __webpack_require__(/*! function-bind */ "./node_modules/function-bind/index.js");
|
|
|
|
module.exports = bind.call(Function.call, Object.prototype.hasOwnProperty);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash-base/index.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/hash-base/index.js ***!
|
|
\*****************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var Transform = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js").Transform
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
|
|
function throwIfNotStringOrBuffer (val, prefix) {
|
|
if (!Buffer.isBuffer(val) && typeof val !== 'string') {
|
|
throw new TypeError(prefix + ' must be a string or a buffer')
|
|
}
|
|
}
|
|
|
|
function HashBase (blockSize) {
|
|
Transform.call(this)
|
|
|
|
this._block = Buffer.allocUnsafe(blockSize)
|
|
this._blockSize = blockSize
|
|
this._blockOffset = 0
|
|
this._length = [0, 0, 0, 0]
|
|
|
|
this._finalized = false
|
|
}
|
|
|
|
inherits(HashBase, Transform)
|
|
|
|
HashBase.prototype._transform = function (chunk, encoding, callback) {
|
|
var error = null
|
|
try {
|
|
this.update(chunk, encoding)
|
|
} catch (err) {
|
|
error = err
|
|
}
|
|
|
|
callback(error)
|
|
}
|
|
|
|
HashBase.prototype._flush = function (callback) {
|
|
var error = null
|
|
try {
|
|
this.push(this.digest())
|
|
} catch (err) {
|
|
error = err
|
|
}
|
|
|
|
callback(error)
|
|
}
|
|
|
|
HashBase.prototype.update = function (data, encoding) {
|
|
throwIfNotStringOrBuffer(data, 'Data')
|
|
if (this._finalized) throw new Error('Digest already called')
|
|
if (!Buffer.isBuffer(data)) data = Buffer.from(data, encoding)
|
|
|
|
// consume data
|
|
var block = this._block
|
|
var offset = 0
|
|
while (this._blockOffset + data.length - offset >= this._blockSize) {
|
|
for (var i = this._blockOffset; i < this._blockSize;) block[i++] = data[offset++]
|
|
this._update()
|
|
this._blockOffset = 0
|
|
}
|
|
while (offset < data.length) block[this._blockOffset++] = data[offset++]
|
|
|
|
// update length
|
|
for (var j = 0, carry = data.length * 8; carry > 0; ++j) {
|
|
this._length[j] += carry
|
|
carry = (this._length[j] / 0x0100000000) | 0
|
|
if (carry > 0) this._length[j] -= 0x0100000000 * carry
|
|
}
|
|
|
|
return this
|
|
}
|
|
|
|
HashBase.prototype._update = function () {
|
|
throw new Error('_update is not implemented')
|
|
}
|
|
|
|
HashBase.prototype.digest = function (encoding) {
|
|
if (this._finalized) throw new Error('Digest already called')
|
|
this._finalized = true
|
|
|
|
var digest = this._digest()
|
|
if (encoding !== undefined) digest = digest.toString(encoding)
|
|
|
|
// reset state
|
|
this._block.fill(0)
|
|
this._blockOffset = 0
|
|
for (var i = 0; i < 4; ++i) this._length[i] = 0
|
|
|
|
return digest
|
|
}
|
|
|
|
HashBase.prototype._digest = function () {
|
|
throw new Error('_digest is not implemented')
|
|
}
|
|
|
|
module.exports = HashBase
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash.js ***!
|
|
\******************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var hash = exports;
|
|
|
|
hash.utils = __webpack_require__(/*! ./hash/utils */ "./node_modules/hash.js/lib/hash/utils.js");
|
|
hash.common = __webpack_require__(/*! ./hash/common */ "./node_modules/hash.js/lib/hash/common.js");
|
|
hash.sha = __webpack_require__(/*! ./hash/sha */ "./node_modules/hash.js/lib/hash/sha.js");
|
|
hash.ripemd = __webpack_require__(/*! ./hash/ripemd */ "./node_modules/hash.js/lib/hash/ripemd.js");
|
|
hash.hmac = __webpack_require__(/*! ./hash/hmac */ "./node_modules/hash.js/lib/hash/hmac.js");
|
|
|
|
// Proxy hash functions to the main object
|
|
hash.sha1 = hash.sha.sha1;
|
|
hash.sha256 = hash.sha.sha256;
|
|
hash.sha224 = hash.sha.sha224;
|
|
hash.sha384 = hash.sha.sha384;
|
|
hash.sha512 = hash.sha.sha512;
|
|
hash.ripemd160 = hash.ripemd.ripemd160;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/common.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/common.js ***!
|
|
\*************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ./utils */ "./node_modules/hash.js/lib/hash/utils.js");
|
|
var assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
|
|
function BlockHash() {
|
|
this.pending = null;
|
|
this.pendingTotal = 0;
|
|
this.blockSize = this.constructor.blockSize;
|
|
this.outSize = this.constructor.outSize;
|
|
this.hmacStrength = this.constructor.hmacStrength;
|
|
this.padLength = this.constructor.padLength / 8;
|
|
this.endian = 'big';
|
|
|
|
this._delta8 = this.blockSize / 8;
|
|
this._delta32 = this.blockSize / 32;
|
|
}
|
|
exports.BlockHash = BlockHash;
|
|
|
|
BlockHash.prototype.update = function update(msg, enc) {
|
|
// Convert message to array, pad it, and join into 32bit blocks
|
|
msg = utils.toArray(msg, enc);
|
|
if (!this.pending)
|
|
this.pending = msg;
|
|
else
|
|
this.pending = this.pending.concat(msg);
|
|
this.pendingTotal += msg.length;
|
|
|
|
// Enough data, try updating
|
|
if (this.pending.length >= this._delta8) {
|
|
msg = this.pending;
|
|
|
|
// Process pending data in blocks
|
|
var r = msg.length % this._delta8;
|
|
this.pending = msg.slice(msg.length - r, msg.length);
|
|
if (this.pending.length === 0)
|
|
this.pending = null;
|
|
|
|
msg = utils.join32(msg, 0, msg.length - r, this.endian);
|
|
for (var i = 0; i < msg.length; i += this._delta32)
|
|
this._update(msg, i, i + this._delta32);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
BlockHash.prototype.digest = function digest(enc) {
|
|
this.update(this._pad());
|
|
assert(this.pending === null);
|
|
|
|
return this._digest(enc);
|
|
};
|
|
|
|
BlockHash.prototype._pad = function pad() {
|
|
var len = this.pendingTotal;
|
|
var bytes = this._delta8;
|
|
var k = bytes - ((len + this.padLength) % bytes);
|
|
var res = new Array(k + this.padLength);
|
|
res[0] = 0x80;
|
|
for (var i = 1; i < k; i++)
|
|
res[i] = 0;
|
|
|
|
// Append length
|
|
len <<= 3;
|
|
if (this.endian === 'big') {
|
|
for (var t = 8; t < this.padLength; t++)
|
|
res[i++] = 0;
|
|
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
res[i++] = (len >>> 24) & 0xff;
|
|
res[i++] = (len >>> 16) & 0xff;
|
|
res[i++] = (len >>> 8) & 0xff;
|
|
res[i++] = len & 0xff;
|
|
} else {
|
|
res[i++] = len & 0xff;
|
|
res[i++] = (len >>> 8) & 0xff;
|
|
res[i++] = (len >>> 16) & 0xff;
|
|
res[i++] = (len >>> 24) & 0xff;
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
|
|
for (t = 8; t < this.padLength; t++)
|
|
res[i++] = 0;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/hmac.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/hmac.js ***!
|
|
\***********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ./utils */ "./node_modules/hash.js/lib/hash/utils.js");
|
|
var assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
|
|
function Hmac(hash, key, enc) {
|
|
if (!(this instanceof Hmac))
|
|
return new Hmac(hash, key, enc);
|
|
this.Hash = hash;
|
|
this.blockSize = hash.blockSize / 8;
|
|
this.outSize = hash.outSize / 8;
|
|
this.inner = null;
|
|
this.outer = null;
|
|
|
|
this._init(utils.toArray(key, enc));
|
|
}
|
|
module.exports = Hmac;
|
|
|
|
Hmac.prototype._init = function init(key) {
|
|
// Shorten key, if needed
|
|
if (key.length > this.blockSize)
|
|
key = new this.Hash().update(key).digest();
|
|
assert(key.length <= this.blockSize);
|
|
|
|
// Add padding to key
|
|
for (var i = key.length; i < this.blockSize; i++)
|
|
key.push(0);
|
|
|
|
for (i = 0; i < key.length; i++)
|
|
key[i] ^= 0x36;
|
|
this.inner = new this.Hash().update(key);
|
|
|
|
// 0x36 ^ 0x5c = 0x6a
|
|
for (i = 0; i < key.length; i++)
|
|
key[i] ^= 0x6a;
|
|
this.outer = new this.Hash().update(key);
|
|
};
|
|
|
|
Hmac.prototype.update = function update(msg, enc) {
|
|
this.inner.update(msg, enc);
|
|
return this;
|
|
};
|
|
|
|
Hmac.prototype.digest = function digest(enc) {
|
|
this.outer.update(this.inner.digest());
|
|
return this.outer.digest(enc);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/ripemd.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/ripemd.js ***!
|
|
\*************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ./utils */ "./node_modules/hash.js/lib/hash/utils.js");
|
|
var common = __webpack_require__(/*! ./common */ "./node_modules/hash.js/lib/hash/common.js");
|
|
|
|
var rotl32 = utils.rotl32;
|
|
var sum32 = utils.sum32;
|
|
var sum32_3 = utils.sum32_3;
|
|
var sum32_4 = utils.sum32_4;
|
|
var BlockHash = common.BlockHash;
|
|
|
|
function RIPEMD160() {
|
|
if (!(this instanceof RIPEMD160))
|
|
return new RIPEMD160();
|
|
|
|
BlockHash.call(this);
|
|
|
|
this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ];
|
|
this.endian = 'little';
|
|
}
|
|
utils.inherits(RIPEMD160, BlockHash);
|
|
exports.ripemd160 = RIPEMD160;
|
|
|
|
RIPEMD160.blockSize = 512;
|
|
RIPEMD160.outSize = 160;
|
|
RIPEMD160.hmacStrength = 192;
|
|
RIPEMD160.padLength = 64;
|
|
|
|
RIPEMD160.prototype._update = function update(msg, start) {
|
|
var A = this.h[0];
|
|
var B = this.h[1];
|
|
var C = this.h[2];
|
|
var D = this.h[3];
|
|
var E = this.h[4];
|
|
var Ah = A;
|
|
var Bh = B;
|
|
var Ch = C;
|
|
var Dh = D;
|
|
var Eh = E;
|
|
for (var j = 0; j < 80; j++) {
|
|
var T = sum32(
|
|
rotl32(
|
|
sum32_4(A, f(j, B, C, D), msg[r[j] + start], K(j)),
|
|
s[j]),
|
|
E);
|
|
A = E;
|
|
E = D;
|
|
D = rotl32(C, 10);
|
|
C = B;
|
|
B = T;
|
|
T = sum32(
|
|
rotl32(
|
|
sum32_4(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)),
|
|
sh[j]),
|
|
Eh);
|
|
Ah = Eh;
|
|
Eh = Dh;
|
|
Dh = rotl32(Ch, 10);
|
|
Ch = Bh;
|
|
Bh = T;
|
|
}
|
|
T = sum32_3(this.h[1], C, Dh);
|
|
this.h[1] = sum32_3(this.h[2], D, Eh);
|
|
this.h[2] = sum32_3(this.h[3], E, Ah);
|
|
this.h[3] = sum32_3(this.h[4], A, Bh);
|
|
this.h[4] = sum32_3(this.h[0], B, Ch);
|
|
this.h[0] = T;
|
|
};
|
|
|
|
RIPEMD160.prototype._digest = function digest(enc) {
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h, 'little');
|
|
else
|
|
return utils.split32(this.h, 'little');
|
|
};
|
|
|
|
function f(j, x, y, z) {
|
|
if (j <= 15)
|
|
return x ^ y ^ z;
|
|
else if (j <= 31)
|
|
return (x & y) | ((~x) & z);
|
|
else if (j <= 47)
|
|
return (x | (~y)) ^ z;
|
|
else if (j <= 63)
|
|
return (x & z) | (y & (~z));
|
|
else
|
|
return x ^ (y | (~z));
|
|
}
|
|
|
|
function K(j) {
|
|
if (j <= 15)
|
|
return 0x00000000;
|
|
else if (j <= 31)
|
|
return 0x5a827999;
|
|
else if (j <= 47)
|
|
return 0x6ed9eba1;
|
|
else if (j <= 63)
|
|
return 0x8f1bbcdc;
|
|
else
|
|
return 0xa953fd4e;
|
|
}
|
|
|
|
function Kh(j) {
|
|
if (j <= 15)
|
|
return 0x50a28be6;
|
|
else if (j <= 31)
|
|
return 0x5c4dd124;
|
|
else if (j <= 47)
|
|
return 0x6d703ef3;
|
|
else if (j <= 63)
|
|
return 0x7a6d76e9;
|
|
else
|
|
return 0x00000000;
|
|
}
|
|
|
|
var r = [
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
|
|
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
|
|
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
|
|
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
|
|
];
|
|
|
|
var rh = [
|
|
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
|
|
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
|
|
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
|
|
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
|
|
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
|
|
];
|
|
|
|
var s = [
|
|
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
|
|
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
|
|
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
|
|
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
|
|
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
|
|
];
|
|
|
|
var sh = [
|
|
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
|
|
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
|
|
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
|
|
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
|
|
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
|
|
];
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/sha.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/sha.js ***!
|
|
\**********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
exports.sha1 = __webpack_require__(/*! ./sha/1 */ "./node_modules/hash.js/lib/hash/sha/1.js");
|
|
exports.sha224 = __webpack_require__(/*! ./sha/224 */ "./node_modules/hash.js/lib/hash/sha/224.js");
|
|
exports.sha256 = __webpack_require__(/*! ./sha/256 */ "./node_modules/hash.js/lib/hash/sha/256.js");
|
|
exports.sha384 = __webpack_require__(/*! ./sha/384 */ "./node_modules/hash.js/lib/hash/sha/384.js");
|
|
exports.sha512 = __webpack_require__(/*! ./sha/512 */ "./node_modules/hash.js/lib/hash/sha/512.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/sha/1.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/sha/1.js ***!
|
|
\************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/hash.js/lib/hash/utils.js");
|
|
var common = __webpack_require__(/*! ../common */ "./node_modules/hash.js/lib/hash/common.js");
|
|
var shaCommon = __webpack_require__(/*! ./common */ "./node_modules/hash.js/lib/hash/sha/common.js");
|
|
|
|
var rotl32 = utils.rotl32;
|
|
var sum32 = utils.sum32;
|
|
var sum32_5 = utils.sum32_5;
|
|
var ft_1 = shaCommon.ft_1;
|
|
var BlockHash = common.BlockHash;
|
|
|
|
var sha1_K = [
|
|
0x5A827999, 0x6ED9EBA1,
|
|
0x8F1BBCDC, 0xCA62C1D6
|
|
];
|
|
|
|
function SHA1() {
|
|
if (!(this instanceof SHA1))
|
|
return new SHA1();
|
|
|
|
BlockHash.call(this);
|
|
this.h = [
|
|
0x67452301, 0xefcdab89, 0x98badcfe,
|
|
0x10325476, 0xc3d2e1f0 ];
|
|
this.W = new Array(80);
|
|
}
|
|
|
|
utils.inherits(SHA1, BlockHash);
|
|
module.exports = SHA1;
|
|
|
|
SHA1.blockSize = 512;
|
|
SHA1.outSize = 160;
|
|
SHA1.hmacStrength = 80;
|
|
SHA1.padLength = 64;
|
|
|
|
SHA1.prototype._update = function _update(msg, start) {
|
|
var W = this.W;
|
|
|
|
for (var i = 0; i < 16; i++)
|
|
W[i] = msg[start + i];
|
|
|
|
for(; i < W.length; i++)
|
|
W[i] = rotl32(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
|
|
|
|
var a = this.h[0];
|
|
var b = this.h[1];
|
|
var c = this.h[2];
|
|
var d = this.h[3];
|
|
var e = this.h[4];
|
|
|
|
for (i = 0; i < W.length; i++) {
|
|
var s = ~~(i / 20);
|
|
var t = sum32_5(rotl32(a, 5), ft_1(s, b, c, d), e, W[i], sha1_K[s]);
|
|
e = d;
|
|
d = c;
|
|
c = rotl32(b, 30);
|
|
b = a;
|
|
a = t;
|
|
}
|
|
|
|
this.h[0] = sum32(this.h[0], a);
|
|
this.h[1] = sum32(this.h[1], b);
|
|
this.h[2] = sum32(this.h[2], c);
|
|
this.h[3] = sum32(this.h[3], d);
|
|
this.h[4] = sum32(this.h[4], e);
|
|
};
|
|
|
|
SHA1.prototype._digest = function digest(enc) {
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h, 'big');
|
|
else
|
|
return utils.split32(this.h, 'big');
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/sha/224.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/sha/224.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/hash.js/lib/hash/utils.js");
|
|
var SHA256 = __webpack_require__(/*! ./256 */ "./node_modules/hash.js/lib/hash/sha/256.js");
|
|
|
|
function SHA224() {
|
|
if (!(this instanceof SHA224))
|
|
return new SHA224();
|
|
|
|
SHA256.call(this);
|
|
this.h = [
|
|
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
|
|
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ];
|
|
}
|
|
utils.inherits(SHA224, SHA256);
|
|
module.exports = SHA224;
|
|
|
|
SHA224.blockSize = 512;
|
|
SHA224.outSize = 224;
|
|
SHA224.hmacStrength = 192;
|
|
SHA224.padLength = 64;
|
|
|
|
SHA224.prototype._digest = function digest(enc) {
|
|
// Just truncate output
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h.slice(0, 7), 'big');
|
|
else
|
|
return utils.split32(this.h.slice(0, 7), 'big');
|
|
};
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/sha/256.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/sha/256.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/hash.js/lib/hash/utils.js");
|
|
var common = __webpack_require__(/*! ../common */ "./node_modules/hash.js/lib/hash/common.js");
|
|
var shaCommon = __webpack_require__(/*! ./common */ "./node_modules/hash.js/lib/hash/sha/common.js");
|
|
var assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
|
|
var sum32 = utils.sum32;
|
|
var sum32_4 = utils.sum32_4;
|
|
var sum32_5 = utils.sum32_5;
|
|
var ch32 = shaCommon.ch32;
|
|
var maj32 = shaCommon.maj32;
|
|
var s0_256 = shaCommon.s0_256;
|
|
var s1_256 = shaCommon.s1_256;
|
|
var g0_256 = shaCommon.g0_256;
|
|
var g1_256 = shaCommon.g1_256;
|
|
|
|
var BlockHash = common.BlockHash;
|
|
|
|
var sha256_K = [
|
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
|
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
|
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
|
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
|
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
|
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
];
|
|
|
|
function SHA256() {
|
|
if (!(this instanceof SHA256))
|
|
return new SHA256();
|
|
|
|
BlockHash.call(this);
|
|
this.h = [
|
|
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
|
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
|
];
|
|
this.k = sha256_K;
|
|
this.W = new Array(64);
|
|
}
|
|
utils.inherits(SHA256, BlockHash);
|
|
module.exports = SHA256;
|
|
|
|
SHA256.blockSize = 512;
|
|
SHA256.outSize = 256;
|
|
SHA256.hmacStrength = 192;
|
|
SHA256.padLength = 64;
|
|
|
|
SHA256.prototype._update = function _update(msg, start) {
|
|
var W = this.W;
|
|
|
|
for (var i = 0; i < 16; i++)
|
|
W[i] = msg[start + i];
|
|
for (; i < W.length; i++)
|
|
W[i] = sum32_4(g1_256(W[i - 2]), W[i - 7], g0_256(W[i - 15]), W[i - 16]);
|
|
|
|
var a = this.h[0];
|
|
var b = this.h[1];
|
|
var c = this.h[2];
|
|
var d = this.h[3];
|
|
var e = this.h[4];
|
|
var f = this.h[5];
|
|
var g = this.h[6];
|
|
var h = this.h[7];
|
|
|
|
assert(this.k.length === W.length);
|
|
for (i = 0; i < W.length; i++) {
|
|
var T1 = sum32_5(h, s1_256(e), ch32(e, f, g), this.k[i], W[i]);
|
|
var T2 = sum32(s0_256(a), maj32(a, b, c));
|
|
h = g;
|
|
g = f;
|
|
f = e;
|
|
e = sum32(d, T1);
|
|
d = c;
|
|
c = b;
|
|
b = a;
|
|
a = sum32(T1, T2);
|
|
}
|
|
|
|
this.h[0] = sum32(this.h[0], a);
|
|
this.h[1] = sum32(this.h[1], b);
|
|
this.h[2] = sum32(this.h[2], c);
|
|
this.h[3] = sum32(this.h[3], d);
|
|
this.h[4] = sum32(this.h[4], e);
|
|
this.h[5] = sum32(this.h[5], f);
|
|
this.h[6] = sum32(this.h[6], g);
|
|
this.h[7] = sum32(this.h[7], h);
|
|
};
|
|
|
|
SHA256.prototype._digest = function digest(enc) {
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h, 'big');
|
|
else
|
|
return utils.split32(this.h, 'big');
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/sha/384.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/sha/384.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/hash.js/lib/hash/utils.js");
|
|
|
|
var SHA512 = __webpack_require__(/*! ./512 */ "./node_modules/hash.js/lib/hash/sha/512.js");
|
|
|
|
function SHA384() {
|
|
if (!(this instanceof SHA384))
|
|
return new SHA384();
|
|
|
|
SHA512.call(this);
|
|
this.h = [
|
|
0xcbbb9d5d, 0xc1059ed8,
|
|
0x629a292a, 0x367cd507,
|
|
0x9159015a, 0x3070dd17,
|
|
0x152fecd8, 0xf70e5939,
|
|
0x67332667, 0xffc00b31,
|
|
0x8eb44a87, 0x68581511,
|
|
0xdb0c2e0d, 0x64f98fa7,
|
|
0x47b5481d, 0xbefa4fa4 ];
|
|
}
|
|
utils.inherits(SHA384, SHA512);
|
|
module.exports = SHA384;
|
|
|
|
SHA384.blockSize = 1024;
|
|
SHA384.outSize = 384;
|
|
SHA384.hmacStrength = 192;
|
|
SHA384.padLength = 128;
|
|
|
|
SHA384.prototype._digest = function digest(enc) {
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h.slice(0, 12), 'big');
|
|
else
|
|
return utils.split32(this.h.slice(0, 12), 'big');
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/sha/512.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/sha/512.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/hash.js/lib/hash/utils.js");
|
|
var common = __webpack_require__(/*! ../common */ "./node_modules/hash.js/lib/hash/common.js");
|
|
var assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
|
|
var rotr64_hi = utils.rotr64_hi;
|
|
var rotr64_lo = utils.rotr64_lo;
|
|
var shr64_hi = utils.shr64_hi;
|
|
var shr64_lo = utils.shr64_lo;
|
|
var sum64 = utils.sum64;
|
|
var sum64_hi = utils.sum64_hi;
|
|
var sum64_lo = utils.sum64_lo;
|
|
var sum64_4_hi = utils.sum64_4_hi;
|
|
var sum64_4_lo = utils.sum64_4_lo;
|
|
var sum64_5_hi = utils.sum64_5_hi;
|
|
var sum64_5_lo = utils.sum64_5_lo;
|
|
|
|
var BlockHash = common.BlockHash;
|
|
|
|
var sha512_K = [
|
|
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
|
|
0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
|
|
0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
|
|
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
|
|
0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
|
|
0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
|
|
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
|
|
0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
|
|
0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
|
|
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
|
|
0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
|
|
0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
|
|
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
|
|
0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
|
|
0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
|
|
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
|
|
0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
|
|
0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
|
|
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
|
|
0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
|
|
0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
|
|
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
|
|
0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
|
|
0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
|
|
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
|
|
0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
|
|
0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
|
|
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
|
|
0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
|
|
0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
|
|
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
|
|
0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
|
|
0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
|
|
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
|
|
0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
|
|
0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
|
|
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
|
|
0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
|
|
0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
|
|
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
|
|
];
|
|
|
|
function SHA512() {
|
|
if (!(this instanceof SHA512))
|
|
return new SHA512();
|
|
|
|
BlockHash.call(this);
|
|
this.h = [
|
|
0x6a09e667, 0xf3bcc908,
|
|
0xbb67ae85, 0x84caa73b,
|
|
0x3c6ef372, 0xfe94f82b,
|
|
0xa54ff53a, 0x5f1d36f1,
|
|
0x510e527f, 0xade682d1,
|
|
0x9b05688c, 0x2b3e6c1f,
|
|
0x1f83d9ab, 0xfb41bd6b,
|
|
0x5be0cd19, 0x137e2179 ];
|
|
this.k = sha512_K;
|
|
this.W = new Array(160);
|
|
}
|
|
utils.inherits(SHA512, BlockHash);
|
|
module.exports = SHA512;
|
|
|
|
SHA512.blockSize = 1024;
|
|
SHA512.outSize = 512;
|
|
SHA512.hmacStrength = 192;
|
|
SHA512.padLength = 128;
|
|
|
|
SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) {
|
|
var W = this.W;
|
|
|
|
// 32 x 32bit words
|
|
for (var i = 0; i < 32; i++)
|
|
W[i] = msg[start + i];
|
|
for (; i < W.length; i += 2) {
|
|
var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2
|
|
var c0_lo = g1_512_lo(W[i - 4], W[i - 3]);
|
|
var c1_hi = W[i - 14]; // i - 7
|
|
var c1_lo = W[i - 13];
|
|
var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15
|
|
var c2_lo = g0_512_lo(W[i - 30], W[i - 29]);
|
|
var c3_hi = W[i - 32]; // i - 16
|
|
var c3_lo = W[i - 31];
|
|
|
|
W[i] = sum64_4_hi(
|
|
c0_hi, c0_lo,
|
|
c1_hi, c1_lo,
|
|
c2_hi, c2_lo,
|
|
c3_hi, c3_lo);
|
|
W[i + 1] = sum64_4_lo(
|
|
c0_hi, c0_lo,
|
|
c1_hi, c1_lo,
|
|
c2_hi, c2_lo,
|
|
c3_hi, c3_lo);
|
|
}
|
|
};
|
|
|
|
SHA512.prototype._update = function _update(msg, start) {
|
|
this._prepareBlock(msg, start);
|
|
|
|
var W = this.W;
|
|
|
|
var ah = this.h[0];
|
|
var al = this.h[1];
|
|
var bh = this.h[2];
|
|
var bl = this.h[3];
|
|
var ch = this.h[4];
|
|
var cl = this.h[5];
|
|
var dh = this.h[6];
|
|
var dl = this.h[7];
|
|
var eh = this.h[8];
|
|
var el = this.h[9];
|
|
var fh = this.h[10];
|
|
var fl = this.h[11];
|
|
var gh = this.h[12];
|
|
var gl = this.h[13];
|
|
var hh = this.h[14];
|
|
var hl = this.h[15];
|
|
|
|
assert(this.k.length === W.length);
|
|
for (var i = 0; i < W.length; i += 2) {
|
|
var c0_hi = hh;
|
|
var c0_lo = hl;
|
|
var c1_hi = s1_512_hi(eh, el);
|
|
var c1_lo = s1_512_lo(eh, el);
|
|
var c2_hi = ch64_hi(eh, el, fh, fl, gh, gl);
|
|
var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl);
|
|
var c3_hi = this.k[i];
|
|
var c3_lo = this.k[i + 1];
|
|
var c4_hi = W[i];
|
|
var c4_lo = W[i + 1];
|
|
|
|
var T1_hi = sum64_5_hi(
|
|
c0_hi, c0_lo,
|
|
c1_hi, c1_lo,
|
|
c2_hi, c2_lo,
|
|
c3_hi, c3_lo,
|
|
c4_hi, c4_lo);
|
|
var T1_lo = sum64_5_lo(
|
|
c0_hi, c0_lo,
|
|
c1_hi, c1_lo,
|
|
c2_hi, c2_lo,
|
|
c3_hi, c3_lo,
|
|
c4_hi, c4_lo);
|
|
|
|
c0_hi = s0_512_hi(ah, al);
|
|
c0_lo = s0_512_lo(ah, al);
|
|
c1_hi = maj64_hi(ah, al, bh, bl, ch, cl);
|
|
c1_lo = maj64_lo(ah, al, bh, bl, ch, cl);
|
|
|
|
var T2_hi = sum64_hi(c0_hi, c0_lo, c1_hi, c1_lo);
|
|
var T2_lo = sum64_lo(c0_hi, c0_lo, c1_hi, c1_lo);
|
|
|
|
hh = gh;
|
|
hl = gl;
|
|
|
|
gh = fh;
|
|
gl = fl;
|
|
|
|
fh = eh;
|
|
fl = el;
|
|
|
|
eh = sum64_hi(dh, dl, T1_hi, T1_lo);
|
|
el = sum64_lo(dl, dl, T1_hi, T1_lo);
|
|
|
|
dh = ch;
|
|
dl = cl;
|
|
|
|
ch = bh;
|
|
cl = bl;
|
|
|
|
bh = ah;
|
|
bl = al;
|
|
|
|
ah = sum64_hi(T1_hi, T1_lo, T2_hi, T2_lo);
|
|
al = sum64_lo(T1_hi, T1_lo, T2_hi, T2_lo);
|
|
}
|
|
|
|
sum64(this.h, 0, ah, al);
|
|
sum64(this.h, 2, bh, bl);
|
|
sum64(this.h, 4, ch, cl);
|
|
sum64(this.h, 6, dh, dl);
|
|
sum64(this.h, 8, eh, el);
|
|
sum64(this.h, 10, fh, fl);
|
|
sum64(this.h, 12, gh, gl);
|
|
sum64(this.h, 14, hh, hl);
|
|
};
|
|
|
|
SHA512.prototype._digest = function digest(enc) {
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h, 'big');
|
|
else
|
|
return utils.split32(this.h, 'big');
|
|
};
|
|
|
|
function ch64_hi(xh, xl, yh, yl, zh) {
|
|
var r = (xh & yh) ^ ((~xh) & zh);
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function ch64_lo(xh, xl, yh, yl, zh, zl) {
|
|
var r = (xl & yl) ^ ((~xl) & zl);
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function maj64_hi(xh, xl, yh, yl, zh) {
|
|
var r = (xh & yh) ^ (xh & zh) ^ (yh & zh);
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function maj64_lo(xh, xl, yh, yl, zh, zl) {
|
|
var r = (xl & yl) ^ (xl & zl) ^ (yl & zl);
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function s0_512_hi(xh, xl) {
|
|
var c0_hi = rotr64_hi(xh, xl, 28);
|
|
var c1_hi = rotr64_hi(xl, xh, 2); // 34
|
|
var c2_hi = rotr64_hi(xl, xh, 7); // 39
|
|
|
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function s0_512_lo(xh, xl) {
|
|
var c0_lo = rotr64_lo(xh, xl, 28);
|
|
var c1_lo = rotr64_lo(xl, xh, 2); // 34
|
|
var c2_lo = rotr64_lo(xl, xh, 7); // 39
|
|
|
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function s1_512_hi(xh, xl) {
|
|
var c0_hi = rotr64_hi(xh, xl, 14);
|
|
var c1_hi = rotr64_hi(xh, xl, 18);
|
|
var c2_hi = rotr64_hi(xl, xh, 9); // 41
|
|
|
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function s1_512_lo(xh, xl) {
|
|
var c0_lo = rotr64_lo(xh, xl, 14);
|
|
var c1_lo = rotr64_lo(xh, xl, 18);
|
|
var c2_lo = rotr64_lo(xl, xh, 9); // 41
|
|
|
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function g0_512_hi(xh, xl) {
|
|
var c0_hi = rotr64_hi(xh, xl, 1);
|
|
var c1_hi = rotr64_hi(xh, xl, 8);
|
|
var c2_hi = shr64_hi(xh, xl, 7);
|
|
|
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function g0_512_lo(xh, xl) {
|
|
var c0_lo = rotr64_lo(xh, xl, 1);
|
|
var c1_lo = rotr64_lo(xh, xl, 8);
|
|
var c2_lo = shr64_lo(xh, xl, 7);
|
|
|
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function g1_512_hi(xh, xl) {
|
|
var c0_hi = rotr64_hi(xh, xl, 19);
|
|
var c1_hi = rotr64_hi(xl, xh, 29); // 61
|
|
var c2_hi = shr64_hi(xh, xl, 6);
|
|
|
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function g1_512_lo(xh, xl) {
|
|
var c0_lo = rotr64_lo(xh, xl, 19);
|
|
var c1_lo = rotr64_lo(xl, xh, 29); // 61
|
|
var c2_lo = shr64_lo(xh, xl, 6);
|
|
|
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/sha/common.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/sha/common.js ***!
|
|
\*****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = __webpack_require__(/*! ../utils */ "./node_modules/hash.js/lib/hash/utils.js");
|
|
var rotr32 = utils.rotr32;
|
|
|
|
function ft_1(s, x, y, z) {
|
|
if (s === 0)
|
|
return ch32(x, y, z);
|
|
if (s === 1 || s === 3)
|
|
return p32(x, y, z);
|
|
if (s === 2)
|
|
return maj32(x, y, z);
|
|
}
|
|
exports.ft_1 = ft_1;
|
|
|
|
function ch32(x, y, z) {
|
|
return (x & y) ^ ((~x) & z);
|
|
}
|
|
exports.ch32 = ch32;
|
|
|
|
function maj32(x, y, z) {
|
|
return (x & y) ^ (x & z) ^ (y & z);
|
|
}
|
|
exports.maj32 = maj32;
|
|
|
|
function p32(x, y, z) {
|
|
return x ^ y ^ z;
|
|
}
|
|
exports.p32 = p32;
|
|
|
|
function s0_256(x) {
|
|
return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22);
|
|
}
|
|
exports.s0_256 = s0_256;
|
|
|
|
function s1_256(x) {
|
|
return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25);
|
|
}
|
|
exports.s1_256 = s1_256;
|
|
|
|
function g0_256(x) {
|
|
return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >>> 3);
|
|
}
|
|
exports.g0_256 = g0_256;
|
|
|
|
function g1_256(x) {
|
|
return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >>> 10);
|
|
}
|
|
exports.g1_256 = g1_256;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hash.js/lib/hash/utils.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/hash.js/lib/hash/utils.js ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
|
|
exports.inherits = inherits;
|
|
|
|
function isSurrogatePair(msg, i) {
|
|
if ((msg.charCodeAt(i) & 0xFC00) !== 0xD800) {
|
|
return false;
|
|
}
|
|
if (i < 0 || i + 1 >= msg.length) {
|
|
return false;
|
|
}
|
|
return (msg.charCodeAt(i + 1) & 0xFC00) === 0xDC00;
|
|
}
|
|
|
|
function toArray(msg, enc) {
|
|
if (Array.isArray(msg))
|
|
return msg.slice();
|
|
if (!msg)
|
|
return [];
|
|
var res = [];
|
|
if (typeof msg === 'string') {
|
|
if (!enc) {
|
|
// Inspired by stringToUtf8ByteArray() in closure-library by Google
|
|
// https://github.com/google/closure-library/blob/8598d87242af59aac233270742c8984e2b2bdbe0/closure/goog/crypt/crypt.js#L117-L143
|
|
// Apache License 2.0
|
|
// https://github.com/google/closure-library/blob/master/LICENSE
|
|
var p = 0;
|
|
for (var i = 0; i < msg.length; i++) {
|
|
var c = msg.charCodeAt(i);
|
|
if (c < 128) {
|
|
res[p++] = c;
|
|
} else if (c < 2048) {
|
|
res[p++] = (c >> 6) | 192;
|
|
res[p++] = (c & 63) | 128;
|
|
} else if (isSurrogatePair(msg, i)) {
|
|
c = 0x10000 + ((c & 0x03FF) << 10) + (msg.charCodeAt(++i) & 0x03FF);
|
|
res[p++] = (c >> 18) | 240;
|
|
res[p++] = ((c >> 12) & 63) | 128;
|
|
res[p++] = ((c >> 6) & 63) | 128;
|
|
res[p++] = (c & 63) | 128;
|
|
} else {
|
|
res[p++] = (c >> 12) | 224;
|
|
res[p++] = ((c >> 6) & 63) | 128;
|
|
res[p++] = (c & 63) | 128;
|
|
}
|
|
}
|
|
} else if (enc === 'hex') {
|
|
msg = msg.replace(/[^a-z0-9]+/ig, '');
|
|
if (msg.length % 2 !== 0)
|
|
msg = '0' + msg;
|
|
for (i = 0; i < msg.length; i += 2)
|
|
res.push(parseInt(msg[i] + msg[i + 1], 16));
|
|
}
|
|
} else {
|
|
for (i = 0; i < msg.length; i++)
|
|
res[i] = msg[i] | 0;
|
|
}
|
|
return res;
|
|
}
|
|
exports.toArray = toArray;
|
|
|
|
function toHex(msg) {
|
|
var res = '';
|
|
for (var i = 0; i < msg.length; i++)
|
|
res += zero2(msg[i].toString(16));
|
|
return res;
|
|
}
|
|
exports.toHex = toHex;
|
|
|
|
function htonl(w) {
|
|
var res = (w >>> 24) |
|
|
((w >>> 8) & 0xff00) |
|
|
((w << 8) & 0xff0000) |
|
|
((w & 0xff) << 24);
|
|
return res >>> 0;
|
|
}
|
|
exports.htonl = htonl;
|
|
|
|
function toHex32(msg, endian) {
|
|
var res = '';
|
|
for (var i = 0; i < msg.length; i++) {
|
|
var w = msg[i];
|
|
if (endian === 'little')
|
|
w = htonl(w);
|
|
res += zero8(w.toString(16));
|
|
}
|
|
return res;
|
|
}
|
|
exports.toHex32 = toHex32;
|
|
|
|
function zero2(word) {
|
|
if (word.length === 1)
|
|
return '0' + word;
|
|
else
|
|
return word;
|
|
}
|
|
exports.zero2 = zero2;
|
|
|
|
function zero8(word) {
|
|
if (word.length === 7)
|
|
return '0' + word;
|
|
else if (word.length === 6)
|
|
return '00' + word;
|
|
else if (word.length === 5)
|
|
return '000' + word;
|
|
else if (word.length === 4)
|
|
return '0000' + word;
|
|
else if (word.length === 3)
|
|
return '00000' + word;
|
|
else if (word.length === 2)
|
|
return '000000' + word;
|
|
else if (word.length === 1)
|
|
return '0000000' + word;
|
|
else
|
|
return word;
|
|
}
|
|
exports.zero8 = zero8;
|
|
|
|
function join32(msg, start, end, endian) {
|
|
var len = end - start;
|
|
assert(len % 4 === 0);
|
|
var res = new Array(len / 4);
|
|
for (var i = 0, k = start; i < res.length; i++, k += 4) {
|
|
var w;
|
|
if (endian === 'big')
|
|
w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3];
|
|
else
|
|
w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k];
|
|
res[i] = w >>> 0;
|
|
}
|
|
return res;
|
|
}
|
|
exports.join32 = join32;
|
|
|
|
function split32(msg, endian) {
|
|
var res = new Array(msg.length * 4);
|
|
for (var i = 0, k = 0; i < msg.length; i++, k += 4) {
|
|
var m = msg[i];
|
|
if (endian === 'big') {
|
|
res[k] = m >>> 24;
|
|
res[k + 1] = (m >>> 16) & 0xff;
|
|
res[k + 2] = (m >>> 8) & 0xff;
|
|
res[k + 3] = m & 0xff;
|
|
} else {
|
|
res[k + 3] = m >>> 24;
|
|
res[k + 2] = (m >>> 16) & 0xff;
|
|
res[k + 1] = (m >>> 8) & 0xff;
|
|
res[k] = m & 0xff;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
exports.split32 = split32;
|
|
|
|
function rotr32(w, b) {
|
|
return (w >>> b) | (w << (32 - b));
|
|
}
|
|
exports.rotr32 = rotr32;
|
|
|
|
function rotl32(w, b) {
|
|
return (w << b) | (w >>> (32 - b));
|
|
}
|
|
exports.rotl32 = rotl32;
|
|
|
|
function sum32(a, b) {
|
|
return (a + b) >>> 0;
|
|
}
|
|
exports.sum32 = sum32;
|
|
|
|
function sum32_3(a, b, c) {
|
|
return (a + b + c) >>> 0;
|
|
}
|
|
exports.sum32_3 = sum32_3;
|
|
|
|
function sum32_4(a, b, c, d) {
|
|
return (a + b + c + d) >>> 0;
|
|
}
|
|
exports.sum32_4 = sum32_4;
|
|
|
|
function sum32_5(a, b, c, d, e) {
|
|
return (a + b + c + d + e) >>> 0;
|
|
}
|
|
exports.sum32_5 = sum32_5;
|
|
|
|
function sum64(buf, pos, ah, al) {
|
|
var bh = buf[pos];
|
|
var bl = buf[pos + 1];
|
|
|
|
var lo = (al + bl) >>> 0;
|
|
var hi = (lo < al ? 1 : 0) + ah + bh;
|
|
buf[pos] = hi >>> 0;
|
|
buf[pos + 1] = lo;
|
|
}
|
|
exports.sum64 = sum64;
|
|
|
|
function sum64_hi(ah, al, bh, bl) {
|
|
var lo = (al + bl) >>> 0;
|
|
var hi = (lo < al ? 1 : 0) + ah + bh;
|
|
return hi >>> 0;
|
|
}
|
|
exports.sum64_hi = sum64_hi;
|
|
|
|
function sum64_lo(ah, al, bh, bl) {
|
|
var lo = al + bl;
|
|
return lo >>> 0;
|
|
}
|
|
exports.sum64_lo = sum64_lo;
|
|
|
|
function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) {
|
|
var carry = 0;
|
|
var lo = al;
|
|
lo = (lo + bl) >>> 0;
|
|
carry += lo < al ? 1 : 0;
|
|
lo = (lo + cl) >>> 0;
|
|
carry += lo < cl ? 1 : 0;
|
|
lo = (lo + dl) >>> 0;
|
|
carry += lo < dl ? 1 : 0;
|
|
|
|
var hi = ah + bh + ch + dh + carry;
|
|
return hi >>> 0;
|
|
}
|
|
exports.sum64_4_hi = sum64_4_hi;
|
|
|
|
function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) {
|
|
var lo = al + bl + cl + dl;
|
|
return lo >>> 0;
|
|
}
|
|
exports.sum64_4_lo = sum64_4_lo;
|
|
|
|
function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
|
|
var carry = 0;
|
|
var lo = al;
|
|
lo = (lo + bl) >>> 0;
|
|
carry += lo < al ? 1 : 0;
|
|
lo = (lo + cl) >>> 0;
|
|
carry += lo < cl ? 1 : 0;
|
|
lo = (lo + dl) >>> 0;
|
|
carry += lo < dl ? 1 : 0;
|
|
lo = (lo + el) >>> 0;
|
|
carry += lo < el ? 1 : 0;
|
|
|
|
var hi = ah + bh + ch + dh + eh + carry;
|
|
return hi >>> 0;
|
|
}
|
|
exports.sum64_5_hi = sum64_5_hi;
|
|
|
|
function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
|
|
var lo = al + bl + cl + dl + el;
|
|
|
|
return lo >>> 0;
|
|
}
|
|
exports.sum64_5_lo = sum64_5_lo;
|
|
|
|
function rotr64_hi(ah, al, num) {
|
|
var r = (al << (32 - num)) | (ah >>> num);
|
|
return r >>> 0;
|
|
}
|
|
exports.rotr64_hi = rotr64_hi;
|
|
|
|
function rotr64_lo(ah, al, num) {
|
|
var r = (ah << (32 - num)) | (al >>> num);
|
|
return r >>> 0;
|
|
}
|
|
exports.rotr64_lo = rotr64_lo;
|
|
|
|
function shr64_hi(ah, al, num) {
|
|
return ah >>> num;
|
|
}
|
|
exports.shr64_hi = shr64_hi;
|
|
|
|
function shr64_lo(ah, al, num) {
|
|
var r = (ah << (32 - num)) | (al >>> num);
|
|
return r >>> 0;
|
|
}
|
|
exports.shr64_lo = shr64_lo;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hmac-drbg/lib/hmac-drbg.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/hmac-drbg/lib/hmac-drbg.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var hash = __webpack_require__(/*! hash.js */ "./node_modules/hash.js/lib/hash.js");
|
|
var utils = __webpack_require__(/*! minimalistic-crypto-utils */ "./node_modules/minimalistic-crypto-utils/lib/utils.js");
|
|
var assert = __webpack_require__(/*! minimalistic-assert */ "./node_modules/minimalistic-assert/index.js");
|
|
|
|
function HmacDRBG(options) {
|
|
if (!(this instanceof HmacDRBG))
|
|
return new HmacDRBG(options);
|
|
this.hash = options.hash;
|
|
this.predResist = !!options.predResist;
|
|
|
|
this.outLen = this.hash.outSize;
|
|
this.minEntropy = options.minEntropy || this.hash.hmacStrength;
|
|
|
|
this._reseed = null;
|
|
this.reseedInterval = null;
|
|
this.K = null;
|
|
this.V = null;
|
|
|
|
var entropy = utils.toArray(options.entropy, options.entropyEnc || 'hex');
|
|
var nonce = utils.toArray(options.nonce, options.nonceEnc || 'hex');
|
|
var pers = utils.toArray(options.pers, options.persEnc || 'hex');
|
|
assert(entropy.length >= (this.minEntropy / 8),
|
|
'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');
|
|
this._init(entropy, nonce, pers);
|
|
}
|
|
module.exports = HmacDRBG;
|
|
|
|
HmacDRBG.prototype._init = function init(entropy, nonce, pers) {
|
|
var seed = entropy.concat(nonce).concat(pers);
|
|
|
|
this.K = new Array(this.outLen / 8);
|
|
this.V = new Array(this.outLen / 8);
|
|
for (var i = 0; i < this.V.length; i++) {
|
|
this.K[i] = 0x00;
|
|
this.V[i] = 0x01;
|
|
}
|
|
|
|
this._update(seed);
|
|
this._reseed = 1;
|
|
this.reseedInterval = 0x1000000000000; // 2^48
|
|
};
|
|
|
|
HmacDRBG.prototype._hmac = function hmac() {
|
|
return new hash.hmac(this.hash, this.K);
|
|
};
|
|
|
|
HmacDRBG.prototype._update = function update(seed) {
|
|
var kmac = this._hmac()
|
|
.update(this.V)
|
|
.update([ 0x00 ]);
|
|
if (seed)
|
|
kmac = kmac.update(seed);
|
|
this.K = kmac.digest();
|
|
this.V = this._hmac().update(this.V).digest();
|
|
if (!seed)
|
|
return;
|
|
|
|
this.K = this._hmac()
|
|
.update(this.V)
|
|
.update([ 0x01 ])
|
|
.update(seed)
|
|
.digest();
|
|
this.V = this._hmac().update(this.V).digest();
|
|
};
|
|
|
|
HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) {
|
|
// Optional entropy enc
|
|
if (typeof entropyEnc !== 'string') {
|
|
addEnc = add;
|
|
add = entropyEnc;
|
|
entropyEnc = null;
|
|
}
|
|
|
|
entropy = utils.toArray(entropy, entropyEnc);
|
|
add = utils.toArray(add, addEnc);
|
|
|
|
assert(entropy.length >= (this.minEntropy / 8),
|
|
'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');
|
|
|
|
this._update(entropy.concat(add || []));
|
|
this._reseed = 1;
|
|
};
|
|
|
|
HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) {
|
|
if (this._reseed > this.reseedInterval)
|
|
throw new Error('Reseed is required');
|
|
|
|
// Optional encoding
|
|
if (typeof enc !== 'string') {
|
|
addEnc = add;
|
|
add = enc;
|
|
enc = null;
|
|
}
|
|
|
|
// Optional additional data
|
|
if (add) {
|
|
add = utils.toArray(add, addEnc || 'hex');
|
|
this._update(add);
|
|
}
|
|
|
|
var temp = [];
|
|
while (temp.length < len) {
|
|
this.V = this._hmac().update(this.V).digest();
|
|
temp = temp.concat(this.V);
|
|
}
|
|
|
|
var res = temp.slice(0, len);
|
|
this._update(add);
|
|
this._reseed++;
|
|
return utils.encode(res, enc);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/https-browserify/index.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/https-browserify/index.js ***!
|
|
\************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var http = __webpack_require__(/*! http */ "./node_modules/stream-http/index.js")
|
|
var url = __webpack_require__(/*! url */ "./node_modules/url/url.js")
|
|
|
|
var https = module.exports
|
|
|
|
for (var key in http) {
|
|
if (http.hasOwnProperty(key)) https[key] = http[key]
|
|
}
|
|
|
|
https.request = function (params, cb) {
|
|
params = validateParams(params)
|
|
return http.request.call(this, params, cb)
|
|
}
|
|
|
|
https.get = function (params, cb) {
|
|
params = validateParams(params)
|
|
return http.get.call(this, params, cb)
|
|
}
|
|
|
|
function validateParams (params) {
|
|
if (typeof params === 'string') {
|
|
params = url.parse(params)
|
|
}
|
|
if (!params.protocol) {
|
|
params.protocol = 'https:'
|
|
}
|
|
if (params.protocol !== 'https:') {
|
|
throw new Error('Protocol "' + params.protocol + '" not supported. Expected "https:"')
|
|
}
|
|
return params
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/hybrid-chunk-store/index.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/hybrid-chunk-store/index.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* eslint-env browser */
|
|
const FSAccessChunkStore = __webpack_require__(/*! fs-access-chunk-store */ "./node_modules/fs-access-chunk-store/index.js")
|
|
const IDBChunkStore = __webpack_require__(/*! idb-chunk-store */ "./node_modules/idb-chunk-store/index.js")
|
|
const MemoryChunkStore = __webpack_require__(/*! memory-chunk-store */ "./node_modules/memory-chunk-store/index.js")
|
|
const CacheChunkStore = __webpack_require__(/*! cache-chunk-store */ "./node_modules/cache-chunk-store/index.js")
|
|
|
|
const isChrome = !!window.chrome
|
|
|
|
class HybridChunkStore {
|
|
constructor (chunkLength, opts = {}) {
|
|
this.chunkLength = Number(chunkLength)
|
|
if (!this.chunkLength) throw new Error('First argument must be a chunk length')
|
|
|
|
this.fallbackStore = null
|
|
this.chunkCount = null
|
|
this.stores = []
|
|
this.chunks = []
|
|
|
|
// this is kinda stupid, first it makes the fallback store, then the main store
|
|
// creates a store limited by targetLength, then uses memory as fallback/overflow
|
|
const _mapStore = (TargetStore, targetLenght) => {
|
|
const newOpts = opts
|
|
if (targetLenght && targetLenght < opts.length) {
|
|
this.chunkCount = Math.floor(targetLenght / this.chunkLength)
|
|
const newLenght = this.chunkCount * this.chunkLength
|
|
newOpts.length = opts.length - newLenght
|
|
// ideally this should be blob store, some1 make one pls
|
|
this.fallbackStore = new MemoryChunkStore(this.chunkLength, newOpts)
|
|
this.stores.push(this.fallbackStore)
|
|
newOpts.length = newLenght
|
|
}
|
|
const store = new CacheChunkStore(new TargetStore(this.chunkLength, newOpts), { max: opts.max })
|
|
this.stores.push(store)
|
|
if (this.chunkCount) {
|
|
this.chunks[this.chunkCount - 1] = store
|
|
this.chunks.fill(store)
|
|
} else {
|
|
this.fallbackStore = store
|
|
}
|
|
}
|
|
|
|
this.registration = navigator.storage.estimate().then(estimate => {
|
|
// use less than available
|
|
const remaining = estimate.quota - estimate.usage - Math.max(Number(opts.reserved) || 0, 16777216)
|
|
if ('getDirectory' in navigator.storage) {
|
|
// lets hope the user isn't stupid enough to specify a directory with barely any storage, forgive me tech support people
|
|
_mapStore(FSAccessChunkStore, !(opts.rootDir) && remaining)
|
|
} else {
|
|
// WAH. https://i.kym-cdn.com/entries/icons/original/000/027/528/519.png
|
|
_mapStore(IDBChunkStore, !(isChrome && estimate.quota === 2147483648) && remaining)
|
|
}
|
|
})
|
|
}
|
|
|
|
get (index, opts, cb) {
|
|
this.registration.then(() => {
|
|
if (!this.chunks[index]) {
|
|
this.fallbackStore.get(index - this.chunkCount, opts, cb)
|
|
} else {
|
|
this.chunks[index].get(index, opts, cb)
|
|
}
|
|
})
|
|
}
|
|
|
|
put (index, buf, cb) {
|
|
this.registration.then(() => {
|
|
if (!this.chunks[index]) {
|
|
this.fallbackStore.put(index - this.chunkCount, buf, cb)
|
|
} else {
|
|
this.chunks[index].put(index, buf, cb)
|
|
}
|
|
})
|
|
}
|
|
|
|
close (cb = () => {}) {
|
|
const promises = []
|
|
for (const store of this.stores) {
|
|
promises.push(new Promise(resolve => store.destroy(resolve)))
|
|
}
|
|
Promise.all(promises).then(values => {
|
|
values = values.filter(value => value)
|
|
cb(values.length > 1 ? values : values[0])
|
|
})
|
|
}
|
|
|
|
destroy (cb = () => {}) {
|
|
const promises = []
|
|
for (const store of this.stores) {
|
|
promises.push(new Promise(resolve => store.close(resolve)))
|
|
}
|
|
Promise.all(promises).then(values => {
|
|
values = values.filter(value => value)
|
|
cb(values.length > 1 ? values : values[0])
|
|
})
|
|
}
|
|
}
|
|
|
|
module.exports = HybridChunkStore
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/idb-chunk-store/index.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/idb-chunk-store/index.js ***!
|
|
\***********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
|
|
const idb = __webpack_require__(/*! idb */ "./node_modules/idb/build/esm/index.js")
|
|
|
|
const EventEmitter = __webpack_require__(/*! events */ "./node_modules/events/events.js").EventEmitter
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
|
|
class Storage extends EventEmitter {
|
|
constructor (chunkLength, opts) {
|
|
if (!opts) opts = {}
|
|
super()
|
|
|
|
this.chunkLength = Number(chunkLength)
|
|
if (!this.chunkLength) throw new Error('First argument must be a chunk length')
|
|
|
|
this.closed = false
|
|
this.destroyed = false
|
|
this.length = Number(opts.length) || Infinity
|
|
this.name = opts.name || 'idb-chunk-store'
|
|
|
|
if (this.length !== Infinity) {
|
|
this.lastChunkLength = (this.length % this.chunkLength) || this.chunkLength
|
|
this.lastChunkIndex = Math.ceil(this.length / this.chunkLength) - 1
|
|
}
|
|
|
|
this.dbPromise = idb.openDB(this.name, undefined, {
|
|
upgrade: (db) => {
|
|
db.createObjectStore('chunks')
|
|
},
|
|
blocking: () => {
|
|
// Fires if the database is deleted from outside this Storage object
|
|
this.close()
|
|
},
|
|
terminated: () => {
|
|
this.closed = true
|
|
this.emit('error', new Error('Database unexpectedly closed'))
|
|
}
|
|
})
|
|
}
|
|
|
|
put (index, buf, cb = () => {}) {
|
|
if (this.closed) return queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
|
|
const isLastChunk = (index === this.lastChunkIndex)
|
|
if (isLastChunk && buf.length !== this.lastChunkLength) {
|
|
return queueMicrotask(() => cb(new Error('Last chunk length must be ' + this.lastChunkLength)))
|
|
}
|
|
if (!isLastChunk && buf.length !== this.chunkLength) {
|
|
return queueMicrotask(() => cb(new Error('Chunk length must be ' + this.chunkLength)))
|
|
}
|
|
|
|
// Zero-copy coerce Buffer to Uint8Array
|
|
buf = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)
|
|
|
|
// If the backing buffer is larger, copy out only the relevant slice
|
|
// so extra data doesn't get saved to indexeddb
|
|
if (buf.byteOffset !== 0 || buf.byteLength !== buf.buffer.byteLength) {
|
|
buf = buf.slice()
|
|
}
|
|
|
|
;(async () => {
|
|
try {
|
|
const db = await this.dbPromise
|
|
await db.put('chunks', buf, index)
|
|
} catch (err) {
|
|
cb(err)
|
|
return
|
|
}
|
|
|
|
cb(null)
|
|
})()
|
|
}
|
|
|
|
get (index, opts, cb = () => {}) {
|
|
if (typeof opts === 'function') return this.get(index, {}, opts)
|
|
if (!opts) opts = {}
|
|
if (this.closed) return queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
|
|
;(async () => {
|
|
let rawResult
|
|
try {
|
|
const db = await this.dbPromise
|
|
rawResult = await db.get('chunks', index)
|
|
} catch (err) {
|
|
cb(err)
|
|
return
|
|
}
|
|
|
|
// rawResult should be undefined if the chunk is not found,
|
|
// but some old browsers occasionally return null
|
|
if (rawResult == null) {
|
|
const err = new Error('Chunk not found')
|
|
err.notFound = true
|
|
cb(err)
|
|
return
|
|
}
|
|
|
|
let buf = Buffer.from(rawResult.buffer, rawResult.byteOffset, rawResult.byteLength)
|
|
|
|
const offset = opts.offset || 0
|
|
const len = opts.length || (buf.length - offset)
|
|
|
|
if (offset !== 0 || len !== buf.length) {
|
|
buf = buf.slice(offset, len + offset)
|
|
}
|
|
|
|
cb(null, buf)
|
|
})()
|
|
}
|
|
|
|
close (cb = () => {}) {
|
|
if (this.closed) return queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
this.closed = true
|
|
|
|
;(async () => {
|
|
try {
|
|
const db = await this.dbPromise
|
|
db.close()
|
|
} catch (err) {
|
|
cb(err)
|
|
return
|
|
}
|
|
|
|
cb(null)
|
|
})()
|
|
}
|
|
|
|
destroy (cb = () => {}) {
|
|
if (this.closed) return queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
if (this.destroyed) return queueMicrotask(() => cb(new Error('Storage is destroyed')))
|
|
this.destroyed = true
|
|
|
|
this.close(async (err) => {
|
|
if (err) {
|
|
cb(err)
|
|
return
|
|
}
|
|
|
|
try {
|
|
await idb.deleteDB(this.name)
|
|
} catch (err) {
|
|
cb(err)
|
|
return
|
|
}
|
|
|
|
cb(null)
|
|
})
|
|
}
|
|
}
|
|
module.exports = Storage
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/idb/build/esm/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/idb/build/esm/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "unwrap": () => (/* reexport safe */ _wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.u),
|
|
/* harmony export */ "wrap": () => (/* reexport safe */ _wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.w),
|
|
/* harmony export */ "deleteDB": () => (/* binding */ deleteDB),
|
|
/* harmony export */ "openDB": () => (/* binding */ openDB)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./wrap-idb-value.js */ "./node_modules/idb/build/esm/wrap-idb-value.js");
|
|
|
|
|
|
|
|
/**
|
|
* Open a database.
|
|
*
|
|
* @param name Name of the database.
|
|
* @param version Schema version.
|
|
* @param callbacks Additional callbacks.
|
|
*/
|
|
function openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {
|
|
const request = indexedDB.open(name, version);
|
|
const openPromise = (0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.w)(request);
|
|
if (upgrade) {
|
|
request.addEventListener('upgradeneeded', (event) => {
|
|
upgrade((0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.w)(request.result), event.oldVersion, event.newVersion, (0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.w)(request.transaction));
|
|
});
|
|
}
|
|
if (blocked)
|
|
request.addEventListener('blocked', () => blocked());
|
|
openPromise
|
|
.then((db) => {
|
|
if (terminated)
|
|
db.addEventListener('close', () => terminated());
|
|
if (blocking)
|
|
db.addEventListener('versionchange', () => blocking());
|
|
})
|
|
.catch(() => { });
|
|
return openPromise;
|
|
}
|
|
/**
|
|
* Delete a database.
|
|
*
|
|
* @param name Name of the database.
|
|
*/
|
|
function deleteDB(name, { blocked } = {}) {
|
|
const request = indexedDB.deleteDatabase(name);
|
|
if (blocked)
|
|
request.addEventListener('blocked', () => blocked());
|
|
return (0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.w)(request).then(() => undefined);
|
|
}
|
|
|
|
const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
|
|
const writeMethods = ['put', 'add', 'delete', 'clear'];
|
|
const cachedMethods = new Map();
|
|
function getMethod(target, prop) {
|
|
if (!(target instanceof IDBDatabase &&
|
|
!(prop in target) &&
|
|
typeof prop === 'string')) {
|
|
return;
|
|
}
|
|
if (cachedMethods.get(prop))
|
|
return cachedMethods.get(prop);
|
|
const targetFuncName = prop.replace(/FromIndex$/, '');
|
|
const useIndex = prop !== targetFuncName;
|
|
const isWrite = writeMethods.includes(targetFuncName);
|
|
if (
|
|
// Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
|
|
!(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
|
|
!(isWrite || readMethods.includes(targetFuncName))) {
|
|
return;
|
|
}
|
|
const method = async function (storeName, ...args) {
|
|
// isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
|
|
const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
|
|
let target = tx.store;
|
|
if (useIndex)
|
|
target = target.index(args.shift());
|
|
// Must reject if op rejects.
|
|
// If it's a write operation, must reject if tx.done rejects.
|
|
// Must reject with op rejection first.
|
|
// Must resolve with op value.
|
|
// Must handle both promises (no unhandled rejections)
|
|
return (await Promise.all([
|
|
target[targetFuncName](...args),
|
|
isWrite && tx.done,
|
|
]))[0];
|
|
};
|
|
cachedMethods.set(prop, method);
|
|
return method;
|
|
}
|
|
(0,_wrap_idb_value_js__WEBPACK_IMPORTED_MODULE_0__.r)((oldTraps) => ({
|
|
...oldTraps,
|
|
get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
|
|
has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),
|
|
}));
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/idb/build/esm/wrap-idb-value.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/idb/build/esm/wrap-idb-value.js ***!
|
|
\******************************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "a": () => (/* binding */ reverseTransformCache),
|
|
/* harmony export */ "i": () => (/* binding */ instanceOfAny),
|
|
/* harmony export */ "r": () => (/* binding */ replaceTraps),
|
|
/* harmony export */ "u": () => (/* binding */ unwrap),
|
|
/* harmony export */ "w": () => (/* binding */ wrap)
|
|
/* harmony export */ });
|
|
const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
|
|
|
|
let idbProxyableTypes;
|
|
let cursorAdvanceMethods;
|
|
// This is a function to prevent it throwing up in node environments.
|
|
function getIdbProxyableTypes() {
|
|
return (idbProxyableTypes ||
|
|
(idbProxyableTypes = [
|
|
IDBDatabase,
|
|
IDBObjectStore,
|
|
IDBIndex,
|
|
IDBCursor,
|
|
IDBTransaction,
|
|
]));
|
|
}
|
|
// This is a function to prevent it throwing up in node environments.
|
|
function getCursorAdvanceMethods() {
|
|
return (cursorAdvanceMethods ||
|
|
(cursorAdvanceMethods = [
|
|
IDBCursor.prototype.advance,
|
|
IDBCursor.prototype.continue,
|
|
IDBCursor.prototype.continuePrimaryKey,
|
|
]));
|
|
}
|
|
const cursorRequestMap = new WeakMap();
|
|
const transactionDoneMap = new WeakMap();
|
|
const transactionStoreNamesMap = new WeakMap();
|
|
const transformCache = new WeakMap();
|
|
const reverseTransformCache = new WeakMap();
|
|
function promisifyRequest(request) {
|
|
const promise = new Promise((resolve, reject) => {
|
|
const unlisten = () => {
|
|
request.removeEventListener('success', success);
|
|
request.removeEventListener('error', error);
|
|
};
|
|
const success = () => {
|
|
resolve(wrap(request.result));
|
|
unlisten();
|
|
};
|
|
const error = () => {
|
|
reject(request.error);
|
|
unlisten();
|
|
};
|
|
request.addEventListener('success', success);
|
|
request.addEventListener('error', error);
|
|
});
|
|
promise
|
|
.then((value) => {
|
|
// Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
|
|
// (see wrapFunction).
|
|
if (value instanceof IDBCursor) {
|
|
cursorRequestMap.set(value, request);
|
|
}
|
|
// Catching to avoid "Uncaught Promise exceptions"
|
|
})
|
|
.catch(() => { });
|
|
// This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
|
|
// is because we create many promises from a single IDBRequest.
|
|
reverseTransformCache.set(promise, request);
|
|
return promise;
|
|
}
|
|
function cacheDonePromiseForTransaction(tx) {
|
|
// Early bail if we've already created a done promise for this transaction.
|
|
if (transactionDoneMap.has(tx))
|
|
return;
|
|
const done = new Promise((resolve, reject) => {
|
|
const unlisten = () => {
|
|
tx.removeEventListener('complete', complete);
|
|
tx.removeEventListener('error', error);
|
|
tx.removeEventListener('abort', error);
|
|
};
|
|
const complete = () => {
|
|
resolve();
|
|
unlisten();
|
|
};
|
|
const error = () => {
|
|
reject(tx.error || new DOMException('AbortError', 'AbortError'));
|
|
unlisten();
|
|
};
|
|
tx.addEventListener('complete', complete);
|
|
tx.addEventListener('error', error);
|
|
tx.addEventListener('abort', error);
|
|
});
|
|
// Cache it for later retrieval.
|
|
transactionDoneMap.set(tx, done);
|
|
}
|
|
let idbProxyTraps = {
|
|
get(target, prop, receiver) {
|
|
if (target instanceof IDBTransaction) {
|
|
// Special handling for transaction.done.
|
|
if (prop === 'done')
|
|
return transactionDoneMap.get(target);
|
|
// Polyfill for objectStoreNames because of Edge.
|
|
if (prop === 'objectStoreNames') {
|
|
return target.objectStoreNames || transactionStoreNamesMap.get(target);
|
|
}
|
|
// Make tx.store return the only store in the transaction, or undefined if there are many.
|
|
if (prop === 'store') {
|
|
return receiver.objectStoreNames[1]
|
|
? undefined
|
|
: receiver.objectStore(receiver.objectStoreNames[0]);
|
|
}
|
|
}
|
|
// Else transform whatever we get back.
|
|
return wrap(target[prop]);
|
|
},
|
|
set(target, prop, value) {
|
|
target[prop] = value;
|
|
return true;
|
|
},
|
|
has(target, prop) {
|
|
if (target instanceof IDBTransaction &&
|
|
(prop === 'done' || prop === 'store')) {
|
|
return true;
|
|
}
|
|
return prop in target;
|
|
},
|
|
};
|
|
function replaceTraps(callback) {
|
|
idbProxyTraps = callback(idbProxyTraps);
|
|
}
|
|
function wrapFunction(func) {
|
|
// Due to expected object equality (which is enforced by the caching in `wrap`), we
|
|
// only create one new func per func.
|
|
// Edge doesn't support objectStoreNames (booo), so we polyfill it here.
|
|
if (func === IDBDatabase.prototype.transaction &&
|
|
!('objectStoreNames' in IDBTransaction.prototype)) {
|
|
return function (storeNames, ...args) {
|
|
const tx = func.call(unwrap(this), storeNames, ...args);
|
|
transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
|
|
return wrap(tx);
|
|
};
|
|
}
|
|
// Cursor methods are special, as the behaviour is a little more different to standard IDB. In
|
|
// IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
|
|
// cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
|
|
// with real promises, so each advance methods returns a new promise for the cursor object, or
|
|
// undefined if the end of the cursor has been reached.
|
|
if (getCursorAdvanceMethods().includes(func)) {
|
|
return function (...args) {
|
|
// Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
|
|
// the original object.
|
|
func.apply(unwrap(this), args);
|
|
return wrap(cursorRequestMap.get(this));
|
|
};
|
|
}
|
|
return function (...args) {
|
|
// Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
|
|
// the original object.
|
|
return wrap(func.apply(unwrap(this), args));
|
|
};
|
|
}
|
|
function transformCachableValue(value) {
|
|
if (typeof value === 'function')
|
|
return wrapFunction(value);
|
|
// This doesn't return, it just creates a 'done' promise for the transaction,
|
|
// which is later returned for transaction.done (see idbObjectHandler).
|
|
if (value instanceof IDBTransaction)
|
|
cacheDonePromiseForTransaction(value);
|
|
if (instanceOfAny(value, getIdbProxyableTypes()))
|
|
return new Proxy(value, idbProxyTraps);
|
|
// Return the same value back if we're not going to transform it.
|
|
return value;
|
|
}
|
|
function wrap(value) {
|
|
// We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
|
|
// IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
|
|
if (value instanceof IDBRequest)
|
|
return promisifyRequest(value);
|
|
// If we've already transformed this value before, reuse the transformed value.
|
|
// This is faster, but it also provides object equality.
|
|
if (transformCache.has(value))
|
|
return transformCache.get(value);
|
|
const newValue = transformCachableValue(value);
|
|
// Not all types are transformed.
|
|
// These may be primitive types, so they can't be WeakMap keys.
|
|
if (newValue !== value) {
|
|
transformCache.set(value, newValue);
|
|
reverseTransformCache.set(newValue, value);
|
|
}
|
|
return newValue;
|
|
}
|
|
const unwrap = (value) => reverseTransformCache.get(value);
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ieee754/index.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/ieee754/index.js ***!
|
|
\***************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
|
|
var e, m
|
|
var eLen = (nBytes * 8) - mLen - 1
|
|
var eMax = (1 << eLen) - 1
|
|
var eBias = eMax >> 1
|
|
var nBits = -7
|
|
var i = isLE ? (nBytes - 1) : 0
|
|
var d = isLE ? -1 : 1
|
|
var s = buffer[offset + i]
|
|
|
|
i += d
|
|
|
|
e = s & ((1 << (-nBits)) - 1)
|
|
s >>= (-nBits)
|
|
nBits += eLen
|
|
for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
|
|
|
|
m = e & ((1 << (-nBits)) - 1)
|
|
e >>= (-nBits)
|
|
nBits += mLen
|
|
for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
|
|
|
|
if (e === 0) {
|
|
e = 1 - eBias
|
|
} else if (e === eMax) {
|
|
return m ? NaN : ((s ? -1 : 1) * Infinity)
|
|
} else {
|
|
m = m + Math.pow(2, mLen)
|
|
e = e - eBias
|
|
}
|
|
return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
|
|
}
|
|
|
|
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
|
|
var e, m, c
|
|
var eLen = (nBytes * 8) - mLen - 1
|
|
var eMax = (1 << eLen) - 1
|
|
var eBias = eMax >> 1
|
|
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
|
|
var i = isLE ? 0 : (nBytes - 1)
|
|
var d = isLE ? 1 : -1
|
|
var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
|
|
|
|
value = Math.abs(value)
|
|
|
|
if (isNaN(value) || value === Infinity) {
|
|
m = isNaN(value) ? 1 : 0
|
|
e = eMax
|
|
} else {
|
|
e = Math.floor(Math.log(value) / Math.LN2)
|
|
if (value * (c = Math.pow(2, -e)) < 1) {
|
|
e--
|
|
c *= 2
|
|
}
|
|
if (e + eBias >= 1) {
|
|
value += rt / c
|
|
} else {
|
|
value += rt * Math.pow(2, 1 - eBias)
|
|
}
|
|
if (value * c >= 2) {
|
|
e++
|
|
c /= 2
|
|
}
|
|
|
|
if (e + eBias >= eMax) {
|
|
m = 0
|
|
e = eMax
|
|
} else if (e + eBias >= 1) {
|
|
m = ((value * c) - 1) * Math.pow(2, mLen)
|
|
e = e + eBias
|
|
} else {
|
|
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
|
|
e = 0
|
|
}
|
|
}
|
|
|
|
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
|
|
|
|
e = (e << mLen) | m
|
|
eLen += mLen
|
|
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
|
|
|
|
buffer[offset + i - d] |= s * 128
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/immediate-chunk-store/index.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/immediate-chunk-store/index.js ***!
|
|
\*****************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*! immediate-chunk-store. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
// TODO: remove when window.queueMicrotask() is well supported
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
|
|
class ImmediateStore {
|
|
constructor (store) {
|
|
this.store = store
|
|
this.chunkLength = store.chunkLength
|
|
|
|
if (!this.store || !this.store.get || !this.store.put) {
|
|
throw new Error('First argument must be abstract-chunk-store compliant')
|
|
}
|
|
|
|
this.mem = []
|
|
}
|
|
|
|
put (index, buf, cb = () => {}) {
|
|
this.mem[index] = buf
|
|
this.store.put(index, buf, err => {
|
|
this.mem[index] = null
|
|
cb(err)
|
|
})
|
|
}
|
|
|
|
get (index, opts, cb = () => {}) {
|
|
if (typeof opts === 'function') return this.get(index, null, opts)
|
|
|
|
let buf = this.mem[index]
|
|
|
|
// if the chunk isn't in the immediate memory cache
|
|
if (!buf) {
|
|
return this.store.get(index, opts, cb)
|
|
}
|
|
|
|
if (!opts) opts = {}
|
|
|
|
const offset = opts.offset || 0
|
|
const len = opts.length || (buf.length - offset)
|
|
|
|
if (offset !== 0 || len !== buf.length) {
|
|
buf = buf.slice(offset, len + offset)
|
|
}
|
|
queueMicrotask(() => cb(null, buf))
|
|
}
|
|
|
|
close (cb = () => {}) {
|
|
this.store.close(cb)
|
|
}
|
|
|
|
destroy (cb = () => {}) {
|
|
this.store.destroy(cb)
|
|
}
|
|
}
|
|
|
|
module.exports = ImmediateStore
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/inherits/inherits_browser.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/inherits/inherits_browser.js ***!
|
|
\***************************************************/
|
|
/***/ ((module) => {
|
|
|
|
if (typeof Object.create === 'function') {
|
|
// implementation from standard node.js 'util' module
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
if (superCtor) {
|
|
ctor.super_ = superCtor
|
|
ctor.prototype = Object.create(superCtor.prototype, {
|
|
constructor: {
|
|
value: ctor,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
})
|
|
}
|
|
};
|
|
} else {
|
|
// old school shim for old browsers
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
if (superCtor) {
|
|
ctor.super_ = superCtor
|
|
var TempCtor = function () {}
|
|
TempCtor.prototype = superCtor.prototype
|
|
ctor.prototype = new TempCtor()
|
|
ctor.prototype.constructor = ctor
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/is-arguments/index.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/is-arguments/index.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
|
|
var callBound = __webpack_require__(/*! call-bind/callBound */ "./node_modules/call-bind/callBound.js");
|
|
|
|
var $toString = callBound('Object.prototype.toString');
|
|
|
|
var isStandardArguments = function isArguments(value) {
|
|
if (hasToStringTag && value && typeof value === 'object' && Symbol.toStringTag in value) {
|
|
return false;
|
|
}
|
|
return $toString(value) === '[object Arguments]';
|
|
};
|
|
|
|
var isLegacyArguments = function isArguments(value) {
|
|
if (isStandardArguments(value)) {
|
|
return true;
|
|
}
|
|
return value !== null &&
|
|
typeof value === 'object' &&
|
|
typeof value.length === 'number' &&
|
|
value.length >= 0 &&
|
|
$toString(value) !== '[object Array]' &&
|
|
$toString(value.callee) === '[object Function]';
|
|
};
|
|
|
|
var supportsStandardArguments = (function () {
|
|
return isStandardArguments(arguments);
|
|
}());
|
|
|
|
isStandardArguments.isLegacyArguments = isLegacyArguments; // for tests
|
|
|
|
module.exports = supportsStandardArguments ? isStandardArguments : isLegacyArguments;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/is-ascii/index.js":
|
|
/*!****************************************!*\
|
|
!*** ./node_modules/is-ascii/index.js ***!
|
|
\****************************************/
|
|
/***/ ((module) => {
|
|
|
|
/* (c) 2016 Ari Porad (@ariporad) <http://ariporad.com>. License: ariporad.mit-license.org */
|
|
|
|
// Partially from http://stackoverflow.com/a/94049/1928484, and from another SO answer, which told me that the highest
|
|
// char code that's ascii is 127, but I can't find the link for. Sorry.
|
|
|
|
var MAX_ASCII_CHAR_CODE = 127;
|
|
|
|
module.exports = function isAscii(str) {
|
|
for (var i = 0, strLen = str.length; i < strLen; ++i) {
|
|
if (str.charCodeAt(i) > MAX_ASCII_CHAR_CODE) return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/is-generator-function/index.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/is-generator-function/index.js ***!
|
|
\*****************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var toStr = Object.prototype.toString;
|
|
var fnToStr = Function.prototype.toString;
|
|
var isFnRegex = /^\s*(?:function)?\*/;
|
|
var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
|
|
var getProto = Object.getPrototypeOf;
|
|
var getGeneratorFunc = function () { // eslint-disable-line consistent-return
|
|
if (!hasToStringTag) {
|
|
return false;
|
|
}
|
|
try {
|
|
return Function('return function*() {}')();
|
|
} catch (e) {
|
|
}
|
|
};
|
|
var GeneratorFunction;
|
|
|
|
module.exports = function isGeneratorFunction(fn) {
|
|
if (typeof fn !== 'function') {
|
|
return false;
|
|
}
|
|
if (isFnRegex.test(fnToStr.call(fn))) {
|
|
return true;
|
|
}
|
|
if (!hasToStringTag) {
|
|
var str = toStr.call(fn);
|
|
return str === '[object GeneratorFunction]';
|
|
}
|
|
if (!getProto) {
|
|
return false;
|
|
}
|
|
if (typeof GeneratorFunction === 'undefined') {
|
|
var generatorFunc = getGeneratorFunc();
|
|
GeneratorFunction = generatorFunc ? getProto(generatorFunc) : false;
|
|
}
|
|
return getProto(fn) === GeneratorFunction;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/is-nan/implementation.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/is-nan/implementation.js ***!
|
|
\***********************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
/* http://www.ecma-international.org/ecma-262/6.0/#sec-number.isnan */
|
|
|
|
module.exports = function isNaN(value) {
|
|
return value !== value;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/is-nan/index.js":
|
|
/*!**************************************!*\
|
|
!*** ./node_modules/is-nan/index.js ***!
|
|
\**************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var callBind = __webpack_require__(/*! call-bind */ "./node_modules/call-bind/index.js");
|
|
var define = __webpack_require__(/*! define-properties */ "./node_modules/define-properties/index.js");
|
|
|
|
var implementation = __webpack_require__(/*! ./implementation */ "./node_modules/is-nan/implementation.js");
|
|
var getPolyfill = __webpack_require__(/*! ./polyfill */ "./node_modules/is-nan/polyfill.js");
|
|
var shim = __webpack_require__(/*! ./shim */ "./node_modules/is-nan/shim.js");
|
|
|
|
var polyfill = callBind(getPolyfill(), Number);
|
|
|
|
/* http://www.ecma-international.org/ecma-262/6.0/#sec-number.isnan */
|
|
|
|
define(polyfill, {
|
|
getPolyfill: getPolyfill,
|
|
implementation: implementation,
|
|
shim: shim
|
|
});
|
|
|
|
module.exports = polyfill;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/is-nan/polyfill.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/is-nan/polyfill.js ***!
|
|
\*****************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var implementation = __webpack_require__(/*! ./implementation */ "./node_modules/is-nan/implementation.js");
|
|
|
|
module.exports = function getPolyfill() {
|
|
if (Number.isNaN && Number.isNaN(NaN) && !Number.isNaN('a')) {
|
|
return Number.isNaN;
|
|
}
|
|
return implementation;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/is-nan/shim.js":
|
|
/*!*************************************!*\
|
|
!*** ./node_modules/is-nan/shim.js ***!
|
|
\*************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var define = __webpack_require__(/*! define-properties */ "./node_modules/define-properties/index.js");
|
|
var getPolyfill = __webpack_require__(/*! ./polyfill */ "./node_modules/is-nan/polyfill.js");
|
|
|
|
/* http://www.ecma-international.org/ecma-262/6.0/#sec-number.isnan */
|
|
|
|
module.exports = function shimNumberIsNaN() {
|
|
var polyfill = getPolyfill();
|
|
define(Number, { isNaN: polyfill }, {
|
|
isNaN: function testIsNaN() {
|
|
return Number.isNaN !== polyfill;
|
|
}
|
|
});
|
|
return polyfill;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/is-typed-array/index.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/is-typed-array/index.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var forEach = __webpack_require__(/*! foreach */ "./node_modules/foreach/index.js");
|
|
var availableTypedArrays = __webpack_require__(/*! available-typed-arrays */ "./node_modules/available-typed-arrays/index.js");
|
|
var callBound = __webpack_require__(/*! call-bind/callBound */ "./node_modules/call-bind/callBound.js");
|
|
|
|
var $toString = callBound('Object.prototype.toString');
|
|
var hasSymbols = __webpack_require__(/*! has-symbols */ "./node_modules/has-symbols/index.js")();
|
|
var hasToStringTag = hasSymbols && typeof Symbol.toStringTag === 'symbol';
|
|
|
|
var typedArrays = availableTypedArrays();
|
|
|
|
var $indexOf = callBound('Array.prototype.indexOf', true) || function indexOf(array, value) {
|
|
for (var i = 0; i < array.length; i += 1) {
|
|
if (array[i] === value) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
var $slice = callBound('String.prototype.slice');
|
|
var toStrTags = {};
|
|
var gOPD = __webpack_require__(/*! es-abstract/helpers/getOwnPropertyDescriptor */ "./node_modules/es-abstract/helpers/getOwnPropertyDescriptor.js");
|
|
var getPrototypeOf = Object.getPrototypeOf; // require('getprototypeof');
|
|
if (hasToStringTag && gOPD && getPrototypeOf) {
|
|
forEach(typedArrays, function (typedArray) {
|
|
var arr = new __webpack_require__.g[typedArray]();
|
|
if (!(Symbol.toStringTag in arr)) {
|
|
throw new EvalError('this engine has support for Symbol.toStringTag, but ' + typedArray + ' does not have the property! Please report this.');
|
|
}
|
|
var proto = getPrototypeOf(arr);
|
|
var descriptor = gOPD(proto, Symbol.toStringTag);
|
|
if (!descriptor) {
|
|
var superProto = getPrototypeOf(proto);
|
|
descriptor = gOPD(superProto, Symbol.toStringTag);
|
|
}
|
|
toStrTags[typedArray] = descriptor.get;
|
|
});
|
|
}
|
|
|
|
var tryTypedArrays = function tryAllTypedArrays(value) {
|
|
var anyTrue = false;
|
|
forEach(toStrTags, function (getter, typedArray) {
|
|
if (!anyTrue) {
|
|
try {
|
|
anyTrue = getter.call(value) === typedArray;
|
|
} catch (e) { /**/ }
|
|
}
|
|
});
|
|
return anyTrue;
|
|
};
|
|
|
|
module.exports = function isTypedArray(value) {
|
|
if (!value || typeof value !== 'object') { return false; }
|
|
if (!hasToStringTag) {
|
|
var tag = $slice($toString(value), 8, -1);
|
|
return $indexOf(typedArrays, tag) > -1;
|
|
}
|
|
if (!gOPD) { return false; }
|
|
return tryTypedArrays(value);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/is-typedarray/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/is-typedarray/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = isTypedArray
|
|
isTypedArray.strict = isStrictTypedArray
|
|
isTypedArray.loose = isLooseTypedArray
|
|
|
|
var toString = Object.prototype.toString
|
|
var names = {
|
|
'[object Int8Array]': true
|
|
, '[object Int16Array]': true
|
|
, '[object Int32Array]': true
|
|
, '[object Uint8Array]': true
|
|
, '[object Uint8ClampedArray]': true
|
|
, '[object Uint16Array]': true
|
|
, '[object Uint32Array]': true
|
|
, '[object Float32Array]': true
|
|
, '[object Float64Array]': true
|
|
}
|
|
|
|
function isTypedArray(arr) {
|
|
return (
|
|
isStrictTypedArray(arr)
|
|
|| isLooseTypedArray(arr)
|
|
)
|
|
}
|
|
|
|
function isStrictTypedArray(arr) {
|
|
return (
|
|
arr instanceof Int8Array
|
|
|| arr instanceof Int16Array
|
|
|| arr instanceof Int32Array
|
|
|| arr instanceof Uint8Array
|
|
|| arr instanceof Uint8ClampedArray
|
|
|| arr instanceof Uint16Array
|
|
|| arr instanceof Uint32Array
|
|
|| arr instanceof Float32Array
|
|
|| arr instanceof Float64Array
|
|
)
|
|
}
|
|
|
|
function isLooseTypedArray(arr) {
|
|
return names[toString.call(arr)]
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/junk/index.js":
|
|
/*!************************************!*\
|
|
!*** ./node_modules/junk/index.js ***!
|
|
\************************************/
|
|
/***/ ((module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const blacklist = [
|
|
// # All
|
|
'^npm-debug\\.log$', // Error log for npm
|
|
'^\\..*\\.swp$', // Swap file for vim state
|
|
|
|
// # macOS
|
|
'^\\.DS_Store$', // Stores custom folder attributes
|
|
'^\\.AppleDouble$', // Stores additional file resources
|
|
'^\\.LSOverride$', // Contains the absolute path to the app to be used
|
|
'^Icon\\r$', // Custom Finder icon: http://superuser.com/questions/298785/icon-file-on-os-x-desktop
|
|
'^\\._.*', // Thumbnail
|
|
'^\\.Spotlight-V100(?:$|\\/)', // Directory that might appear on external disk
|
|
'\\.Trashes', // File that might appear on external disk
|
|
'^__MACOSX$', // Resource fork
|
|
|
|
// # Linux
|
|
'~$', // Backup file
|
|
|
|
// # Windows
|
|
'^Thumbs\\.db$', // Image file cache
|
|
'^ehthumbs\\.db$', // Folder config file
|
|
'^Desktop\\.ini$', // Stores custom folder attributes
|
|
'@eaDir$' // Synology Diskstation "hidden" folder where the server stores thumbnails
|
|
];
|
|
|
|
exports.re = () => {
|
|
throw new Error('`junk.re` was renamed to `junk.regex`');
|
|
};
|
|
|
|
exports.regex = new RegExp(blacklist.join('|'));
|
|
|
|
exports.is = filename => exports.regex.test(filename);
|
|
|
|
exports.not = filename => !exports.is(filename);
|
|
|
|
// TODO: Remove this for the next major release
|
|
exports.default = module.exports;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/limiter/index.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/limiter/index.js ***!
|
|
\***************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
exports.RateLimiter = __webpack_require__(/*! ./lib/rateLimiter */ "./node_modules/limiter/lib/rateLimiter.js");
|
|
exports.TokenBucket = __webpack_require__(/*! ./lib/tokenBucket */ "./node_modules/limiter/lib/tokenBucket.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/limiter/lib/clock.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/limiter/lib/clock.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
var getMilliseconds = function() {
|
|
if (typeof process !== 'undefined' && process.hrtime) {
|
|
var hrtime = process.hrtime();
|
|
var seconds = hrtime[0];
|
|
var nanoseconds = hrtime[1];
|
|
|
|
return seconds * 1e3 + Math.floor(nanoseconds / 1e6);
|
|
}
|
|
|
|
return new Date().getTime();
|
|
}
|
|
|
|
module.exports = getMilliseconds;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/limiter/lib/rateLimiter.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/limiter/lib/rateLimiter.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
var TokenBucket = __webpack_require__(/*! ./tokenBucket */ "./node_modules/limiter/lib/tokenBucket.js");
|
|
var getMilliseconds = __webpack_require__(/*! ./clock */ "./node_modules/limiter/lib/clock.js");
|
|
|
|
/**
|
|
* A generic rate limiter. Underneath the hood, this uses a token bucket plus
|
|
* an additional check to limit how many tokens we can remove each interval.
|
|
* @author John Hurliman <jhurliman@jhurliman.org>
|
|
*
|
|
* @param {Number} tokensPerInterval Maximum number of tokens that can be
|
|
* removed at any given moment and over the course of one interval.
|
|
* @param {String|Number} interval The interval length in milliseconds, or as
|
|
* one of the following strings: 'second', 'minute', 'hour', day'.
|
|
* @param {Boolean} fireImmediately Optional. Whether or not the callback
|
|
* will fire immediately when rate limiting is in effect (default is false).
|
|
*/
|
|
var RateLimiter = function(tokensPerInterval, interval, fireImmediately) {
|
|
this.tokenBucket = new TokenBucket(tokensPerInterval, tokensPerInterval,
|
|
interval, null);
|
|
|
|
// Fill the token bucket to start
|
|
this.tokenBucket.content = tokensPerInterval;
|
|
|
|
this.curIntervalStart = getMilliseconds();
|
|
this.tokensThisInterval = 0;
|
|
this.fireImmediately = fireImmediately;
|
|
};
|
|
|
|
RateLimiter.prototype = {
|
|
tokenBucket: null,
|
|
curIntervalStart: 0,
|
|
tokensThisInterval: 0,
|
|
fireImmediately: false,
|
|
|
|
/**
|
|
* Remove the requested number of tokens and fire the given callback. If the
|
|
* rate limiter contains enough tokens and we haven't spent too many tokens
|
|
* in this interval already, this will happen immediately. Otherwise, the
|
|
* removal and callback will happen when enough tokens become available.
|
|
* @param {Number} count The number of tokens to remove.
|
|
* @param {Function} callback(err, remainingTokens)
|
|
* @returns {Boolean} True if the callback was fired immediately, otherwise
|
|
* false.
|
|
*/
|
|
removeTokens: function(count, callback) {
|
|
// Make sure the request isn't for more than we can handle
|
|
if (count > this.tokenBucket.bucketSize) {
|
|
process.nextTick(callback.bind(null, 'Requested tokens ' + count +
|
|
' exceeds maximum tokens per interval ' + this.tokenBucket.bucketSize,
|
|
null));
|
|
return false;
|
|
}
|
|
|
|
var self = this;
|
|
var now = getMilliseconds();
|
|
|
|
// Advance the current interval and reset the current interval token count
|
|
// if needed
|
|
if (now < this.curIntervalStart
|
|
|| now - this.curIntervalStart >= this.tokenBucket.interval) {
|
|
this.curIntervalStart = now;
|
|
this.tokensThisInterval = 0;
|
|
}
|
|
|
|
// If we don't have enough tokens left in this interval, wait until the
|
|
// next interval
|
|
if (count > this.tokenBucket.tokensPerInterval - this.tokensThisInterval) {
|
|
if (this.fireImmediately) {
|
|
process.nextTick(callback.bind(null, null, -1));
|
|
} else {
|
|
var waitInterval = Math.ceil(
|
|
this.curIntervalStart + this.tokenBucket.interval - now);
|
|
|
|
setTimeout(function() {
|
|
self.tokenBucket.removeTokens(count, afterTokensRemoved);
|
|
}, waitInterval);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Remove the requested number of tokens from the token bucket
|
|
return this.tokenBucket.removeTokens(count, afterTokensRemoved);
|
|
|
|
function afterTokensRemoved(err, tokensRemaining) {
|
|
if (err) return callback(err, null);
|
|
|
|
self.tokensThisInterval += count;
|
|
callback(null, tokensRemaining);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Attempt to remove the requested number of tokens and return immediately.
|
|
* If the bucket (and any parent buckets) contains enough tokens and we
|
|
* haven't spent too many tokens in this interval already, this will return
|
|
* true. Otherwise, false is returned.
|
|
* @param {Number} count The number of tokens to remove.
|
|
* @param {Boolean} True if the tokens were successfully removed, otherwise
|
|
* false.
|
|
*/
|
|
tryRemoveTokens: function(count) {
|
|
// Make sure the request isn't for more than we can handle
|
|
if (count > this.tokenBucket.bucketSize)
|
|
return false;
|
|
|
|
var now = getMilliseconds();
|
|
|
|
// Advance the current interval and reset the current interval token count
|
|
// if needed
|
|
if (now < this.curIntervalStart
|
|
|| now - this.curIntervalStart >= this.tokenBucket.interval) {
|
|
this.curIntervalStart = now;
|
|
this.tokensThisInterval = 0;
|
|
}
|
|
|
|
// If we don't have enough tokens left in this interval, return false
|
|
if (count > this.tokenBucket.tokensPerInterval - this.tokensThisInterval)
|
|
return false;
|
|
|
|
// Try to remove the requested number of tokens from the token bucket
|
|
var removed = this.tokenBucket.tryRemoveTokens(count);
|
|
if (removed) {
|
|
this.tokensThisInterval += count;
|
|
}
|
|
return removed;
|
|
},
|
|
|
|
/**
|
|
* Returns the number of tokens remaining in the TokenBucket.
|
|
* @returns {Number} The number of tokens remaining.
|
|
*/
|
|
getTokensRemaining: function () {
|
|
this.tokenBucket.drip();
|
|
return this.tokenBucket.content;
|
|
}
|
|
};
|
|
|
|
module.exports = RateLimiter;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/limiter/lib/tokenBucket.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/limiter/lib/tokenBucket.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
|
|
/**
|
|
* A hierarchical token bucket for rate limiting. See
|
|
* http://en.wikipedia.org/wiki/Token_bucket for more information.
|
|
* @author John Hurliman <jhurliman@cull.tv>
|
|
*
|
|
* @param {Number} bucketSize Maximum number of tokens to hold in the bucket.
|
|
* Also known as the burst rate.
|
|
* @param {Number} tokensPerInterval Number of tokens to drip into the bucket
|
|
* over the course of one interval.
|
|
* @param {String|Number} interval The interval length in milliseconds, or as
|
|
* one of the following strings: 'second', 'minute', 'hour', day'.
|
|
* @param {TokenBucket} parentBucket Optional. A token bucket that will act as
|
|
* the parent of this bucket.
|
|
*/
|
|
var TokenBucket = function(bucketSize, tokensPerInterval, interval, parentBucket) {
|
|
this.bucketSize = bucketSize;
|
|
this.tokensPerInterval = tokensPerInterval;
|
|
|
|
if (typeof interval === 'string') {
|
|
switch (interval) {
|
|
case 'sec': case 'second':
|
|
this.interval = 1000; break;
|
|
case 'min': case 'minute':
|
|
this.interval = 1000 * 60; break;
|
|
case 'hr': case 'hour':
|
|
this.interval = 1000 * 60 * 60; break;
|
|
case 'day':
|
|
this.interval = 1000 * 60 * 60 * 24; break;
|
|
default:
|
|
throw new Error('Invaid interval ' + interval);
|
|
}
|
|
} else {
|
|
this.interval = interval;
|
|
}
|
|
|
|
this.parentBucket = parentBucket;
|
|
this.content = 0;
|
|
this.lastDrip = +new Date();
|
|
};
|
|
|
|
TokenBucket.prototype = {
|
|
bucketSize: 1,
|
|
tokensPerInterval: 1,
|
|
interval: 1000,
|
|
parentBucket: null,
|
|
content: 0,
|
|
lastDrip: 0,
|
|
|
|
/**
|
|
* Remove the requested number of tokens and fire the given callback. If the
|
|
* bucket (and any parent buckets) contains enough tokens this will happen
|
|
* immediately. Otherwise, the removal and callback will happen when enough
|
|
* tokens become available.
|
|
* @param {Number} count The number of tokens to remove.
|
|
* @param {Function} callback(err, remainingTokens)
|
|
* @returns {Boolean} True if the callback was fired immediately, otherwise
|
|
* false.
|
|
*/
|
|
removeTokens: function(count, callback) {
|
|
var self = this;
|
|
|
|
// Is this an infinite size bucket?
|
|
if (!this.bucketSize) {
|
|
process.nextTick(callback.bind(null, null, count, Number.POSITIVE_INFINITY));
|
|
return true;
|
|
}
|
|
|
|
// Make sure the bucket can hold the requested number of tokens
|
|
if (count > this.bucketSize) {
|
|
process.nextTick(callback.bind(null, 'Requested tokens ' + count + ' exceeds bucket size ' +
|
|
this.bucketSize, null));
|
|
return false;
|
|
}
|
|
|
|
// Drip new tokens into this bucket
|
|
this.drip();
|
|
|
|
// If we don't have enough tokens in this bucket, come back later
|
|
if (count > this.content)
|
|
return comeBackLater();
|
|
|
|
if (this.parentBucket) {
|
|
// Remove the requested from the parent bucket first
|
|
return this.parentBucket.removeTokens(count, function(err, remainingTokens) {
|
|
if (err) return callback(err, null);
|
|
|
|
// Check that we still have enough tokens in this bucket
|
|
if (count > self.content)
|
|
return comeBackLater();
|
|
|
|
// Tokens were removed from the parent bucket, now remove them from
|
|
// this bucket and fire the callback. Note that we look at the current
|
|
// bucket and parent bucket's remaining tokens and return the smaller
|
|
// of the two values
|
|
self.content -= count;
|
|
callback(null, Math.min(remainingTokens, self.content));
|
|
});
|
|
} else {
|
|
// Remove the requested tokens from this bucket and fire the callback
|
|
this.content -= count;
|
|
process.nextTick(callback.bind(null, null, this.content));
|
|
return true;
|
|
}
|
|
|
|
function comeBackLater() {
|
|
// How long do we need to wait to make up the difference in tokens?
|
|
var waitInterval = Math.ceil(
|
|
(count - self.content) * (self.interval / self.tokensPerInterval));
|
|
setTimeout(function() { self.removeTokens(count, callback); }, waitInterval);
|
|
return false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Attempt to remove the requested number of tokens and return immediately.
|
|
* If the bucket (and any parent buckets) contains enough tokens this will
|
|
* return true, otherwise false is returned.
|
|
* @param {Number} count The number of tokens to remove.
|
|
* @param {Boolean} True if the tokens were successfully removed, otherwise
|
|
* false.
|
|
*/
|
|
tryRemoveTokens: function(count) {
|
|
// Is this an infinite size bucket?
|
|
if (!this.bucketSize)
|
|
return true;
|
|
|
|
// Make sure the bucket can hold the requested number of tokens
|
|
if (count > this.bucketSize)
|
|
return false;
|
|
|
|
// Drip new tokens into this bucket
|
|
this.drip();
|
|
|
|
// If we don't have enough tokens in this bucket, return false
|
|
if (count > this.content)
|
|
return false;
|
|
|
|
// Try to remove the requested tokens from the parent bucket
|
|
if (this.parentBucket && !this.parentBucket.tryRemoveTokens(count))
|
|
return false;
|
|
|
|
// Remove the requested tokens from this bucket and return
|
|
this.content -= count;
|
|
return true;
|
|
},
|
|
|
|
/**
|
|
* Add any new tokens to the bucket since the last drip.
|
|
* @returns {Boolean} True if new tokens were added, otherwise false.
|
|
*/
|
|
drip: function() {
|
|
if (!this.tokensPerInterval) {
|
|
this.content = this.bucketSize;
|
|
return;
|
|
}
|
|
|
|
var now = +new Date();
|
|
var deltaMS = Math.max(now - this.lastDrip, 0);
|
|
this.lastDrip = now;
|
|
|
|
var dripAmount = deltaMS * (this.tokensPerInterval / this.interval);
|
|
this.content = Math.min(this.content + dripAmount, this.bucketSize);
|
|
}
|
|
};
|
|
|
|
module.exports = TokenBucket;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/lru/index.js":
|
|
/*!***********************************!*\
|
|
!*** ./node_modules/lru/index.js ***!
|
|
\***********************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var events = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
|
|
module.exports = LRU
|
|
|
|
function LRU (opts) {
|
|
if (!(this instanceof LRU)) return new LRU(opts)
|
|
if (typeof opts === 'number') opts = {max: opts}
|
|
if (!opts) opts = {}
|
|
events.EventEmitter.call(this)
|
|
this.cache = {}
|
|
this.head = this.tail = null
|
|
this.length = 0
|
|
this.max = opts.max || 1000
|
|
this.maxAge = opts.maxAge || 0
|
|
}
|
|
|
|
inherits(LRU, events.EventEmitter)
|
|
|
|
Object.defineProperty(LRU.prototype, 'keys', {
|
|
get: function () { return Object.keys(this.cache) }
|
|
})
|
|
|
|
LRU.prototype.clear = function () {
|
|
this.cache = {}
|
|
this.head = this.tail = null
|
|
this.length = 0
|
|
}
|
|
|
|
LRU.prototype.remove = function (key) {
|
|
if (typeof key !== 'string') key = '' + key
|
|
if (!this.cache.hasOwnProperty(key)) return
|
|
|
|
var element = this.cache[key]
|
|
delete this.cache[key]
|
|
this._unlink(key, element.prev, element.next)
|
|
return element.value
|
|
}
|
|
|
|
LRU.prototype._unlink = function (key, prev, next) {
|
|
this.length--
|
|
|
|
if (this.length === 0) {
|
|
this.head = this.tail = null
|
|
} else {
|
|
if (this.head === key) {
|
|
this.head = prev
|
|
this.cache[this.head].next = null
|
|
} else if (this.tail === key) {
|
|
this.tail = next
|
|
this.cache[this.tail].prev = null
|
|
} else {
|
|
this.cache[prev].next = next
|
|
this.cache[next].prev = prev
|
|
}
|
|
}
|
|
}
|
|
|
|
LRU.prototype.peek = function (key) {
|
|
if (!this.cache.hasOwnProperty(key)) return
|
|
|
|
var element = this.cache[key]
|
|
|
|
if (!this._checkAge(key, element)) return
|
|
return element.value
|
|
}
|
|
|
|
LRU.prototype.set = function (key, value) {
|
|
if (typeof key !== 'string') key = '' + key
|
|
|
|
var element
|
|
|
|
if (this.cache.hasOwnProperty(key)) {
|
|
element = this.cache[key]
|
|
element.value = value
|
|
if (this.maxAge) element.modified = Date.now()
|
|
|
|
// If it's already the head, there's nothing more to do:
|
|
if (key === this.head) return value
|
|
this._unlink(key, element.prev, element.next)
|
|
} else {
|
|
element = {value: value, modified: 0, next: null, prev: null}
|
|
if (this.maxAge) element.modified = Date.now()
|
|
this.cache[key] = element
|
|
|
|
// Eviction is only possible if the key didn't already exist:
|
|
if (this.length === this.max) this.evict()
|
|
}
|
|
|
|
this.length++
|
|
element.next = null
|
|
element.prev = this.head
|
|
|
|
if (this.head) this.cache[this.head].next = key
|
|
this.head = key
|
|
|
|
if (!this.tail) this.tail = key
|
|
return value
|
|
}
|
|
|
|
LRU.prototype._checkAge = function (key, element) {
|
|
if (this.maxAge && (Date.now() - element.modified) > this.maxAge) {
|
|
this.remove(key)
|
|
this.emit('evict', {key: key, value: element.value})
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
LRU.prototype.get = function (key) {
|
|
if (typeof key !== 'string') key = '' + key
|
|
if (!this.cache.hasOwnProperty(key)) return
|
|
|
|
var element = this.cache[key]
|
|
|
|
if (!this._checkAge(key, element)) return
|
|
|
|
if (this.head !== key) {
|
|
if (key === this.tail) {
|
|
this.tail = element.next
|
|
this.cache[this.tail].prev = null
|
|
} else {
|
|
// Set prev.next -> element.next:
|
|
this.cache[element.prev].next = element.next
|
|
}
|
|
|
|
// Set element.next.prev -> element.prev:
|
|
this.cache[element.next].prev = element.prev
|
|
|
|
// Element is the new head
|
|
this.cache[this.head].next = key
|
|
element.prev = this.head
|
|
element.next = null
|
|
this.head = key
|
|
}
|
|
|
|
return element.value
|
|
}
|
|
|
|
LRU.prototype.evict = function () {
|
|
if (!this.tail) return
|
|
var key = this.tail
|
|
var value = this.remove(this.tail)
|
|
this.emit('evict', {key: key, value: value})
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/lt_donthave/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/lt_donthave/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! lt_donthave. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */
|
|
const arrayRemove = __webpack_require__(/*! unordered-array-remove */ "./node_modules/unordered-array-remove/index.js")
|
|
const { EventEmitter } = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('lt_donthave')
|
|
|
|
module.exports = () => {
|
|
class ltDontHave extends EventEmitter {
|
|
constructor (wire) {
|
|
super()
|
|
|
|
this._peerSupports = false
|
|
this._wire = wire
|
|
}
|
|
|
|
onExtendedHandshake () {
|
|
this._peerSupports = true
|
|
}
|
|
|
|
onMessage (buf) {
|
|
let index
|
|
try {
|
|
index = buf.readUInt32BE()
|
|
} catch (err) {
|
|
// drop invalid messages
|
|
return
|
|
}
|
|
|
|
if (!this._wire.peerPieces.get(index)) return
|
|
debug('got donthave %d', index)
|
|
this._wire.peerPieces.set(index, false)
|
|
|
|
this.emit('donthave', index)
|
|
this._failRequests(index)
|
|
}
|
|
|
|
donthave (index) {
|
|
if (!this._peerSupports) return
|
|
|
|
debug('donthave %d', index)
|
|
const buf = Buffer.alloc(4)
|
|
buf.writeUInt32BE(index)
|
|
|
|
this._wire.extended('lt_donthave', buf)
|
|
}
|
|
|
|
_failRequests (index) {
|
|
const requests = this._wire.requests
|
|
for (let i = 0; i < requests.length; i++) {
|
|
const req = requests[i]
|
|
if (req.piece === index) {
|
|
arrayRemove(requests, i)
|
|
i -= 1 // Check the new value at the same slot
|
|
this._wire._callback(req, new Error('peer sent donthave'), null)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Name of the bittorrent-protocol extension
|
|
ltDontHave.prototype.name = 'lt_donthave'
|
|
|
|
return ltDontHave
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/magnet-uri/index.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/magnet-uri/index.js ***!
|
|
\******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! magnet-uri. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */
|
|
module.exports = magnetURIDecode
|
|
module.exports.decode = magnetURIDecode
|
|
module.exports.encode = magnetURIEncode
|
|
|
|
const base32 = __webpack_require__(/*! thirty-two */ "./node_modules/thirty-two/lib/thirty-two/index.js")
|
|
const bep53Range = __webpack_require__(/*! bep53-range */ "./node_modules/bep53-range/index.js")
|
|
|
|
/**
|
|
* Parse a magnet URI and return an object of keys/values
|
|
*
|
|
* @param {string} uri
|
|
* @return {Object} parsed uri
|
|
*/
|
|
function magnetURIDecode (uri) {
|
|
const result = {}
|
|
|
|
// Support 'magnet:' and 'stream-magnet:' uris
|
|
const data = uri.split('magnet:?')[1]
|
|
|
|
const params = (data && data.length >= 0)
|
|
? data.split('&')
|
|
: []
|
|
|
|
params.forEach(param => {
|
|
const keyval = param.split('=')
|
|
|
|
// This keyval is invalid, skip it
|
|
if (keyval.length !== 2) return
|
|
|
|
const key = keyval[0]
|
|
let val = keyval[1]
|
|
|
|
// Clean up torrent name
|
|
if (key === 'dn') val = decodeURIComponent(val).replace(/\+/g, ' ')
|
|
|
|
// Address tracker (tr), exact source (xs), and acceptable source (as) are encoded
|
|
// URIs, so decode them
|
|
if (key === 'tr' || key === 'xs' || key === 'as' || key === 'ws') {
|
|
val = decodeURIComponent(val)
|
|
}
|
|
|
|
// Return keywords as an array
|
|
if (key === 'kt') val = decodeURIComponent(val).split('+')
|
|
|
|
// Cast file index (ix) to a number
|
|
if (key === 'ix') val = Number(val)
|
|
|
|
// bep53
|
|
if (key === 'so') val = bep53Range.parse(decodeURIComponent(val).split(','))
|
|
|
|
// If there are repeated parameters, return an array of values
|
|
if (result[key]) {
|
|
if (!Array.isArray(result[key])) {
|
|
result[key] = [result[key]]
|
|
}
|
|
|
|
result[key].push(val)
|
|
} else {
|
|
result[key] = val
|
|
}
|
|
})
|
|
|
|
// Convenience properties for parity with `parse-torrent-file` module
|
|
let m
|
|
if (result.xt) {
|
|
const xts = Array.isArray(result.xt) ? result.xt : [result.xt]
|
|
xts.forEach(xt => {
|
|
if ((m = xt.match(/^urn:btih:(.{40})/))) {
|
|
result.infoHash = m[1].toLowerCase()
|
|
} else if ((m = xt.match(/^urn:btih:(.{32})/))) {
|
|
const decodedStr = base32.decode(m[1])
|
|
result.infoHash = Buffer.from(decodedStr, 'binary').toString('hex')
|
|
} else if ((m = xt.match(/^urn:btmh:1220(.{64})/))) {
|
|
result.infoHashV2 = m[1].toLowerCase()
|
|
}
|
|
})
|
|
}
|
|
|
|
if (result.xs) {
|
|
const xss = Array.isArray(result.xs) ? result.xs : [result.xs]
|
|
xss.forEach(xs => {
|
|
if ((m = xs.match(/^urn:btpk:(.{64})/))) {
|
|
result.publicKey = m[1].toLowerCase()
|
|
}
|
|
})
|
|
}
|
|
|
|
if (result.infoHash) result.infoHashBuffer = Buffer.from(result.infoHash, 'hex')
|
|
if (result.infoHashV2) result.infoHashV2Buffer = Buffer.from(result.infoHashV2, 'hex')
|
|
if (result.publicKey) result.publicKeyBuffer = Buffer.from(result.publicKey, 'hex')
|
|
|
|
if (result.dn) result.name = result.dn
|
|
if (result.kt) result.keywords = result.kt
|
|
|
|
result.announce = []
|
|
if (typeof result.tr === 'string' || Array.isArray(result.tr)) {
|
|
result.announce = result.announce.concat(result.tr)
|
|
}
|
|
|
|
result.urlList = []
|
|
if (typeof result.as === 'string' || Array.isArray(result.as)) {
|
|
result.urlList = result.urlList.concat(result.as)
|
|
}
|
|
if (typeof result.ws === 'string' || Array.isArray(result.ws)) {
|
|
result.urlList = result.urlList.concat(result.ws)
|
|
}
|
|
|
|
result.peerAddresses = []
|
|
if (typeof result['x.pe'] === 'string' || Array.isArray(result['x.pe'])) {
|
|
result.peerAddresses = result.peerAddresses.concat(result['x.pe'])
|
|
}
|
|
|
|
// remove duplicates by converting to Set and back
|
|
result.announce = Array.from(new Set(result.announce))
|
|
result.urlList = Array.from(new Set(result.urlList))
|
|
result.peerAddresses = Array.from(new Set(result.peerAddresses))
|
|
|
|
return result
|
|
}
|
|
|
|
function magnetURIEncode (obj) {
|
|
obj = Object.assign({}, obj) // clone obj, so we can mutate it
|
|
|
|
// support using convenience names, in addition to spec names
|
|
// (example: `infoHash` for `xt`, `name` for `dn`)
|
|
|
|
// Deduplicate xt by using a set
|
|
let xts = new Set()
|
|
if (obj.xt && typeof obj.xt === 'string') xts.add(obj.xt)
|
|
if (obj.xt && Array.isArray(obj.xt)) xts = new Set(obj.xt)
|
|
if (obj.infoHashBuffer) xts.add(`urn:btih:${obj.infoHashBuffer.toString('hex')}`)
|
|
if (obj.infoHash) xts.add(`urn:btih:${obj.infoHash}`)
|
|
if (obj.infoHashV2Buffer) xts.add(obj.xt = `urn:btmh:1220${obj.infoHashV2Buffer.toString('hex')}`)
|
|
if (obj.infoHashV2) xts.add(`urn:btmh:1220${obj.infoHashV2}`)
|
|
const xtsDeduped = Array.from(xts)
|
|
if (xtsDeduped.length === 1) obj.xt = xtsDeduped[0]
|
|
if (xtsDeduped.length > 1) obj.xt = xtsDeduped
|
|
|
|
if (obj.publicKeyBuffer) obj.xs = `urn:btpk:${obj.publicKeyBuffer.toString('hex')}`
|
|
if (obj.publicKey) obj.xs = `urn:btpk:${obj.publicKey}`
|
|
if (obj.name) obj.dn = obj.name
|
|
if (obj.keywords) obj.kt = obj.keywords
|
|
if (obj.announce) obj.tr = obj.announce
|
|
if (obj.urlList) {
|
|
obj.ws = obj.urlList
|
|
delete obj.as
|
|
}
|
|
if (obj.peerAddresses) obj['x.pe'] = obj.peerAddresses
|
|
|
|
let result = 'magnet:?'
|
|
Object.keys(obj)
|
|
.filter(key => key.length === 2 || key === 'x.pe')
|
|
.forEach((key, i) => {
|
|
const values = Array.isArray(obj[key]) ? obj[key] : [obj[key]]
|
|
values.forEach((val, j) => {
|
|
if ((i > 0 || j > 0) && ((key !== 'kt' && key !== 'so') || j === 0)) result += '&'
|
|
|
|
if (key === 'dn') val = encodeURIComponent(val).replace(/%20/g, '+')
|
|
if (key === 'tr' || key === 'as' || key === 'ws') {
|
|
val = encodeURIComponent(val)
|
|
}
|
|
// Don't URI encode BEP46 keys
|
|
if (key === 'xs' && !val.startsWith('urn:btpk:')) {
|
|
val = encodeURIComponent(val)
|
|
}
|
|
if (key === 'kt') val = encodeURIComponent(val)
|
|
if (key === 'so') return
|
|
|
|
if (key === 'kt' && j > 0) result += `+${val}`
|
|
else result += `${key}=${val}`
|
|
})
|
|
if (key === 'so') result += `${key}=${bep53Range.compose(values)}`
|
|
})
|
|
|
|
return result
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/matroska-subtitles/dist/matroska-subtitles.module.js":
|
|
/*!***************************************************************************!*\
|
|
!*** ./node_modules/matroska-subtitles/dist/matroska-subtitles.module.js ***!
|
|
\***************************************************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "SubtitleParser": () => (/* binding */ SubtitleParser),
|
|
/* harmony export */ "SubtitleStream": () => (/* binding */ SubtitleStream)
|
|
/* harmony export */ });
|
|
/* harmony import */ var ebml_stream__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ebml-stream */ "./node_modules/ebml-stream/lib/index.js");
|
|
/* harmony import */ var readable_stream__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js");
|
|
/* harmony import */ var readable_stream__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(readable_stream__WEBPACK_IMPORTED_MODULE_1__);
|
|
/* harmony import */ var zlib__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! zlib */ "./node_modules/browserify-zlib/lib/index.js");
|
|
/* harmony import */ var zlib__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(zlib__WEBPACK_IMPORTED_MODULE_2__);
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
|
|
|
|
|
|
|
|
const SSA_TYPES = new Set(['ssa', 'ass']);
|
|
const SSA_KEYS = ['readOrder', 'layer', 'style', 'name', 'marginL', 'marginR', 'marginV', 'effect', 'text'];
|
|
|
|
function getData(chunk, id) {
|
|
const el = chunk.Children.find(c => c.id === id);
|
|
return el ? el.data : undefined;
|
|
}
|
|
|
|
class SubtitleParserBase extends readable_stream__WEBPACK_IMPORTED_MODULE_1__.Transform {
|
|
constructor() {
|
|
super();
|
|
this.subtitleTracks = new Map();
|
|
this.timecodeScale = 1;
|
|
this._currentClusterTimecode = null;
|
|
this.decoder = new ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlStreamDecoder({
|
|
bufferTagIds: [ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.TimecodeScale, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.Tracks, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.BlockGroup, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.AttachedFile]
|
|
});
|
|
this.decoder.on('data', this.parseEbmlSubtitles.bind(this));
|
|
}
|
|
|
|
parseEbmlSubtitles(chunk) {
|
|
// Segment Information
|
|
if (chunk.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.TimecodeScale) {
|
|
this.timecodeScale = chunk.data / 1000000;
|
|
} // Assumption: This is a Cluster `Timecode`
|
|
|
|
|
|
if (chunk.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.Timecode) {
|
|
this._currentClusterTimecode = chunk.data;
|
|
}
|
|
|
|
if (chunk.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.Tracks) {
|
|
for (const entry of chunk.Children.filter(c => c.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.TrackEntry)) {
|
|
// Skip non subtitle tracks
|
|
if (getData(entry, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.TrackType) !== 0x11) continue;
|
|
const codecID = getData(entry, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.CodecID) || '';
|
|
|
|
if (codecID.startsWith('S_TEXT')) {
|
|
const track = {
|
|
number: getData(entry, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.TrackNumber),
|
|
language: getData(entry, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.Language),
|
|
type: codecID.substring(7).toLowerCase()
|
|
};
|
|
const name = getData(entry, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.Name);
|
|
|
|
if (name) {
|
|
track.name = name;
|
|
}
|
|
|
|
const header = getData(entry, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.CodecPrivate);
|
|
|
|
if (header) {
|
|
track.header = header.toString();
|
|
} // TODO: Assume zlib deflate compression
|
|
|
|
|
|
const compressed = entry.Children.find(c => c.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.ContentEncodings && c.Children.find(cc => cc.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.ContentEncoding && cc.Children.find(ccc => ccc.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.ContentCompression)));
|
|
|
|
if (compressed) {
|
|
track._compressed = true;
|
|
}
|
|
|
|
this.subtitleTracks.set(track.number, track);
|
|
}
|
|
}
|
|
|
|
this.emit('tracks', Array.from(this.subtitleTracks.values()));
|
|
}
|
|
|
|
if (chunk.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.BlockGroup) {
|
|
const block = chunk.Children.find(c => c.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.Block);
|
|
|
|
if (block && this.subtitleTracks.has(block.track)) {
|
|
const blockDuration = getData(chunk, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.BlockDuration);
|
|
const track = this.subtitleTracks.get(block.track);
|
|
const payload = track._compressed ? (0,zlib__WEBPACK_IMPORTED_MODULE_2__.inflateSync)(Buffer.from(block.payload)) : block.payload;
|
|
const subtitle = {
|
|
text: payload.toString('utf8'),
|
|
time: (block.value + this._currentClusterTimecode) * this.timecodeScale,
|
|
duration: blockDuration * this.timecodeScale
|
|
};
|
|
|
|
if (SSA_TYPES.has(track.type)) {
|
|
// extract SSA/ASS keys
|
|
const values = subtitle.text.split(','); // ignore read-order, and skip layer if ssa
|
|
|
|
for (let i = track.type === 'ssa' ? 2 : 1; i < 8; i++) {
|
|
subtitle[SSA_KEYS[i]] = values[i];
|
|
}
|
|
|
|
subtitle.text = values.slice(8).join(',');
|
|
}
|
|
|
|
this.emit('subtitle', subtitle, block.track);
|
|
}
|
|
} // Parse attached files, mainly to allow extracting subtitle font files.
|
|
|
|
|
|
if (chunk.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.AttachedFile) {
|
|
this.emit('file', {
|
|
filename: getData(chunk, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.FileName),
|
|
mimetype: getData(chunk, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.FileMimeType),
|
|
data: getData(chunk, ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.FileData)
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
class SubtitleParser extends SubtitleParserBase {
|
|
constructor() {
|
|
super();
|
|
this.decoder.on('data', chunk => {
|
|
if (chunk.id === ebml_stream__WEBPACK_IMPORTED_MODULE_0__.EbmlTagId.Tracks) {
|
|
// stop decoding if no subtitle tracks are present
|
|
if (this.subtitleTracks.size === 0) this.end();
|
|
}
|
|
});
|
|
}
|
|
|
|
_write(chunk, _, callback) {
|
|
this.decoder.write(chunk);
|
|
callback(null, chunk);
|
|
}
|
|
|
|
}
|
|
|
|
class SubtitleStream extends SubtitleParserBase {
|
|
constructor(prevInstance) {
|
|
super();
|
|
|
|
if (prevInstance instanceof SubtitleStream) {
|
|
prevInstance.once('drain', () => prevInstance.end()); // copy previous metadata
|
|
|
|
this.subtitleTracks = prevInstance.subtitleTracks;
|
|
this.timecodeScale = prevInstance.timecodeScale; // may not be at ebml tag offset
|
|
|
|
this.unstable = true;
|
|
}
|
|
} // passthrough stream: data is intercepted but not transformed
|
|
|
|
|
|
_transform(chunk, _, callback) {
|
|
if (this.unstable) {
|
|
// the ebml decoder expects to see a tag, so we won't use it until we find a cluster
|
|
for (let i = 0; i < chunk.length - 12; i++) {
|
|
// cluster id
|
|
if (chunk[i] === 0x1f && chunk[i + 1] === 0x43 && chunk[i + 2] === 0xb6 && chunk[i + 3] === 0x75) {
|
|
// length of cluster size tag
|
|
const len = 8 - Math.floor(Math.log2(chunk[i + 4])); // first tag in cluster is cluster timecode
|
|
|
|
if (chunk[i + 4 + len] === 0xe7) {
|
|
// okay this is probably a cluster
|
|
this.unstable = false;
|
|
this.decoderWrite(chunk.slice(i));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
this.decoderWrite(chunk);
|
|
}
|
|
|
|
callback(null, chunk);
|
|
}
|
|
|
|
decoderWrite(chunk) {
|
|
// passthrough stream should allow chained streams to continue on error
|
|
try {
|
|
this.decoder.write(chunk);
|
|
} catch (err) {
|
|
console.warn('[matroska-subtitles] EBML stream decoding error');
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//# sourceMappingURL=matroska-subtitles.module.js.map
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/md5.js/index.js":
|
|
/*!**************************************!*\
|
|
!*** ./node_modules/md5.js/index.js ***!
|
|
\**************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var HashBase = __webpack_require__(/*! hash-base */ "./node_modules/hash-base/index.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var ARRAY16 = new Array(16)
|
|
|
|
function MD5 () {
|
|
HashBase.call(this, 64)
|
|
|
|
// state
|
|
this._a = 0x67452301
|
|
this._b = 0xefcdab89
|
|
this._c = 0x98badcfe
|
|
this._d = 0x10325476
|
|
}
|
|
|
|
inherits(MD5, HashBase)
|
|
|
|
MD5.prototype._update = function () {
|
|
var M = ARRAY16
|
|
for (var i = 0; i < 16; ++i) M[i] = this._block.readInt32LE(i * 4)
|
|
|
|
var a = this._a
|
|
var b = this._b
|
|
var c = this._c
|
|
var d = this._d
|
|
|
|
a = fnF(a, b, c, d, M[0], 0xd76aa478, 7)
|
|
d = fnF(d, a, b, c, M[1], 0xe8c7b756, 12)
|
|
c = fnF(c, d, a, b, M[2], 0x242070db, 17)
|
|
b = fnF(b, c, d, a, M[3], 0xc1bdceee, 22)
|
|
a = fnF(a, b, c, d, M[4], 0xf57c0faf, 7)
|
|
d = fnF(d, a, b, c, M[5], 0x4787c62a, 12)
|
|
c = fnF(c, d, a, b, M[6], 0xa8304613, 17)
|
|
b = fnF(b, c, d, a, M[7], 0xfd469501, 22)
|
|
a = fnF(a, b, c, d, M[8], 0x698098d8, 7)
|
|
d = fnF(d, a, b, c, M[9], 0x8b44f7af, 12)
|
|
c = fnF(c, d, a, b, M[10], 0xffff5bb1, 17)
|
|
b = fnF(b, c, d, a, M[11], 0x895cd7be, 22)
|
|
a = fnF(a, b, c, d, M[12], 0x6b901122, 7)
|
|
d = fnF(d, a, b, c, M[13], 0xfd987193, 12)
|
|
c = fnF(c, d, a, b, M[14], 0xa679438e, 17)
|
|
b = fnF(b, c, d, a, M[15], 0x49b40821, 22)
|
|
|
|
a = fnG(a, b, c, d, M[1], 0xf61e2562, 5)
|
|
d = fnG(d, a, b, c, M[6], 0xc040b340, 9)
|
|
c = fnG(c, d, a, b, M[11], 0x265e5a51, 14)
|
|
b = fnG(b, c, d, a, M[0], 0xe9b6c7aa, 20)
|
|
a = fnG(a, b, c, d, M[5], 0xd62f105d, 5)
|
|
d = fnG(d, a, b, c, M[10], 0x02441453, 9)
|
|
c = fnG(c, d, a, b, M[15], 0xd8a1e681, 14)
|
|
b = fnG(b, c, d, a, M[4], 0xe7d3fbc8, 20)
|
|
a = fnG(a, b, c, d, M[9], 0x21e1cde6, 5)
|
|
d = fnG(d, a, b, c, M[14], 0xc33707d6, 9)
|
|
c = fnG(c, d, a, b, M[3], 0xf4d50d87, 14)
|
|
b = fnG(b, c, d, a, M[8], 0x455a14ed, 20)
|
|
a = fnG(a, b, c, d, M[13], 0xa9e3e905, 5)
|
|
d = fnG(d, a, b, c, M[2], 0xfcefa3f8, 9)
|
|
c = fnG(c, d, a, b, M[7], 0x676f02d9, 14)
|
|
b = fnG(b, c, d, a, M[12], 0x8d2a4c8a, 20)
|
|
|
|
a = fnH(a, b, c, d, M[5], 0xfffa3942, 4)
|
|
d = fnH(d, a, b, c, M[8], 0x8771f681, 11)
|
|
c = fnH(c, d, a, b, M[11], 0x6d9d6122, 16)
|
|
b = fnH(b, c, d, a, M[14], 0xfde5380c, 23)
|
|
a = fnH(a, b, c, d, M[1], 0xa4beea44, 4)
|
|
d = fnH(d, a, b, c, M[4], 0x4bdecfa9, 11)
|
|
c = fnH(c, d, a, b, M[7], 0xf6bb4b60, 16)
|
|
b = fnH(b, c, d, a, M[10], 0xbebfbc70, 23)
|
|
a = fnH(a, b, c, d, M[13], 0x289b7ec6, 4)
|
|
d = fnH(d, a, b, c, M[0], 0xeaa127fa, 11)
|
|
c = fnH(c, d, a, b, M[3], 0xd4ef3085, 16)
|
|
b = fnH(b, c, d, a, M[6], 0x04881d05, 23)
|
|
a = fnH(a, b, c, d, M[9], 0xd9d4d039, 4)
|
|
d = fnH(d, a, b, c, M[12], 0xe6db99e5, 11)
|
|
c = fnH(c, d, a, b, M[15], 0x1fa27cf8, 16)
|
|
b = fnH(b, c, d, a, M[2], 0xc4ac5665, 23)
|
|
|
|
a = fnI(a, b, c, d, M[0], 0xf4292244, 6)
|
|
d = fnI(d, a, b, c, M[7], 0x432aff97, 10)
|
|
c = fnI(c, d, a, b, M[14], 0xab9423a7, 15)
|
|
b = fnI(b, c, d, a, M[5], 0xfc93a039, 21)
|
|
a = fnI(a, b, c, d, M[12], 0x655b59c3, 6)
|
|
d = fnI(d, a, b, c, M[3], 0x8f0ccc92, 10)
|
|
c = fnI(c, d, a, b, M[10], 0xffeff47d, 15)
|
|
b = fnI(b, c, d, a, M[1], 0x85845dd1, 21)
|
|
a = fnI(a, b, c, d, M[8], 0x6fa87e4f, 6)
|
|
d = fnI(d, a, b, c, M[15], 0xfe2ce6e0, 10)
|
|
c = fnI(c, d, a, b, M[6], 0xa3014314, 15)
|
|
b = fnI(b, c, d, a, M[13], 0x4e0811a1, 21)
|
|
a = fnI(a, b, c, d, M[4], 0xf7537e82, 6)
|
|
d = fnI(d, a, b, c, M[11], 0xbd3af235, 10)
|
|
c = fnI(c, d, a, b, M[2], 0x2ad7d2bb, 15)
|
|
b = fnI(b, c, d, a, M[9], 0xeb86d391, 21)
|
|
|
|
this._a = (this._a + a) | 0
|
|
this._b = (this._b + b) | 0
|
|
this._c = (this._c + c) | 0
|
|
this._d = (this._d + d) | 0
|
|
}
|
|
|
|
MD5.prototype._digest = function () {
|
|
// create padding and handle blocks
|
|
this._block[this._blockOffset++] = 0x80
|
|
if (this._blockOffset > 56) {
|
|
this._block.fill(0, this._blockOffset, 64)
|
|
this._update()
|
|
this._blockOffset = 0
|
|
}
|
|
|
|
this._block.fill(0, this._blockOffset, 56)
|
|
this._block.writeUInt32LE(this._length[0], 56)
|
|
this._block.writeUInt32LE(this._length[1], 60)
|
|
this._update()
|
|
|
|
// produce result
|
|
var buffer = Buffer.allocUnsafe(16)
|
|
buffer.writeInt32LE(this._a, 0)
|
|
buffer.writeInt32LE(this._b, 4)
|
|
buffer.writeInt32LE(this._c, 8)
|
|
buffer.writeInt32LE(this._d, 12)
|
|
return buffer
|
|
}
|
|
|
|
function rotl (x, n) {
|
|
return (x << n) | (x >>> (32 - n))
|
|
}
|
|
|
|
function fnF (a, b, c, d, m, k, s) {
|
|
return (rotl((a + ((b & c) | ((~b) & d)) + m + k) | 0, s) + b) | 0
|
|
}
|
|
|
|
function fnG (a, b, c, d, m, k, s) {
|
|
return (rotl((a + ((b & d) | (c & (~d))) + m + k) | 0, s) + b) | 0
|
|
}
|
|
|
|
function fnH (a, b, c, d, m, k, s) {
|
|
return (rotl((a + (b ^ c ^ d) + m + k) | 0, s) + b) | 0
|
|
}
|
|
|
|
function fnI (a, b, c, d, m, k, s) {
|
|
return (rotl((a + ((c ^ (b | (~d)))) + m + k) | 0, s) + b) | 0
|
|
}
|
|
|
|
module.exports = MD5
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mediasource/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/mediasource/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*! mediasource. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
module.exports = MediaElementWrapper
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
var toArrayBuffer = __webpack_require__(/*! to-arraybuffer */ "./node_modules/to-arraybuffer/index.js")
|
|
|
|
var MediaSource = typeof window !== 'undefined' && window.MediaSource
|
|
|
|
var DEFAULT_BUFFER_DURATION = 60 // seconds
|
|
|
|
function MediaElementWrapper (elem, opts) {
|
|
var self = this
|
|
if (!(self instanceof MediaElementWrapper)) return new MediaElementWrapper(elem, opts)
|
|
|
|
if (!MediaSource) throw new Error('web browser lacks MediaSource support')
|
|
|
|
if (!opts) opts = {}
|
|
self._debug = opts.debug
|
|
self._bufferDuration = opts.bufferDuration || DEFAULT_BUFFER_DURATION
|
|
self._elem = elem
|
|
self._mediaSource = new MediaSource()
|
|
self._streams = []
|
|
self.detailedError = null
|
|
|
|
self._errorHandler = function () {
|
|
self._elem.removeEventListener('error', self._errorHandler)
|
|
var streams = self._streams.slice()
|
|
streams.forEach(function (stream) {
|
|
stream.destroy(self._elem.error)
|
|
})
|
|
}
|
|
self._elem.addEventListener('error', self._errorHandler)
|
|
|
|
self._elem.src = window.URL.createObjectURL(self._mediaSource)
|
|
}
|
|
|
|
/*
|
|
* `obj` can be a previous value returned by this function
|
|
* or a string
|
|
*/
|
|
MediaElementWrapper.prototype.createWriteStream = function (obj) {
|
|
var self = this
|
|
|
|
return new MediaSourceStream(self, obj)
|
|
}
|
|
|
|
/*
|
|
* Use to trigger an error on the underlying media element
|
|
*/
|
|
MediaElementWrapper.prototype.error = function (err) {
|
|
var self = this
|
|
|
|
// be careful not to overwrite any existing detailedError values
|
|
if (!self.detailedError) {
|
|
self.detailedError = err
|
|
}
|
|
self._dumpDebugData()
|
|
try {
|
|
self._mediaSource.endOfStream('decode')
|
|
} catch (err) {}
|
|
|
|
try {
|
|
// Attempt to clean up object URL
|
|
window.URL.revokeObjectURL(self._elem.src)
|
|
} catch (err) {}
|
|
}
|
|
|
|
/*
|
|
* When self._debug is set, dump all data to files
|
|
*/
|
|
MediaElementWrapper.prototype._dumpDebugData = function () {
|
|
var self = this
|
|
|
|
if (self._debug) {
|
|
self._debug = false // prevent multiple dumps on multiple errors
|
|
self._streams.forEach(function (stream, i) {
|
|
downloadBuffers(stream._debugBuffers, 'mediasource-stream-' + i)
|
|
})
|
|
}
|
|
}
|
|
|
|
inherits(MediaSourceStream, stream.Writable)
|
|
|
|
function MediaSourceStream (wrapper, obj) {
|
|
var self = this
|
|
stream.Writable.call(self)
|
|
|
|
self._wrapper = wrapper
|
|
self._elem = wrapper._elem
|
|
self._mediaSource = wrapper._mediaSource
|
|
self._allStreams = wrapper._streams
|
|
self._allStreams.push(self)
|
|
self._bufferDuration = wrapper._bufferDuration
|
|
self._sourceBuffer = null
|
|
self._debugBuffers = []
|
|
|
|
self._openHandler = function () {
|
|
self._onSourceOpen()
|
|
}
|
|
self._flowHandler = function () {
|
|
self._flow()
|
|
}
|
|
self._errorHandler = function (err) {
|
|
if (!self.destroyed) {
|
|
self.emit('error', err)
|
|
}
|
|
}
|
|
|
|
if (typeof obj === 'string') {
|
|
self._type = obj
|
|
// Need to create a new sourceBuffer
|
|
if (self._mediaSource.readyState === 'open') {
|
|
self._createSourceBuffer()
|
|
} else {
|
|
self._mediaSource.addEventListener('sourceopen', self._openHandler)
|
|
}
|
|
} else if (obj._sourceBuffer === null) {
|
|
obj.destroy()
|
|
self._type = obj._type // The old stream was created but hasn't finished initializing
|
|
self._mediaSource.addEventListener('sourceopen', self._openHandler)
|
|
} else if (obj._sourceBuffer) {
|
|
obj.destroy()
|
|
self._type = obj._type
|
|
self._sourceBuffer = obj._sourceBuffer // Copy over the old sourceBuffer
|
|
self._debugBuffers = obj._debugBuffers // Copy over previous debug data
|
|
self._sourceBuffer.addEventListener('updateend', self._flowHandler)
|
|
self._sourceBuffer.addEventListener('error', self._errorHandler)
|
|
} else {
|
|
throw new Error('The argument to MediaElementWrapper.createWriteStream must be a string or a previous stream returned from that function')
|
|
}
|
|
|
|
self._elem.addEventListener('timeupdate', self._flowHandler)
|
|
|
|
self.on('error', function (err) {
|
|
self._wrapper.error(err)
|
|
})
|
|
|
|
self.on('finish', function () {
|
|
if (self.destroyed) return
|
|
self._finished = true
|
|
if (self._allStreams.every(function (other) { return other._finished })) {
|
|
self._wrapper._dumpDebugData()
|
|
try {
|
|
self._mediaSource.endOfStream()
|
|
} catch (err) {}
|
|
}
|
|
})
|
|
}
|
|
|
|
MediaSourceStream.prototype._onSourceOpen = function () {
|
|
var self = this
|
|
if (self.destroyed) return
|
|
|
|
self._mediaSource.removeEventListener('sourceopen', self._openHandler)
|
|
self._createSourceBuffer()
|
|
}
|
|
|
|
MediaSourceStream.prototype.destroy = function (err) {
|
|
var self = this
|
|
if (self.destroyed) return
|
|
self.destroyed = true
|
|
|
|
// Remove from allStreams
|
|
self._allStreams.splice(self._allStreams.indexOf(self), 1)
|
|
|
|
self._mediaSource.removeEventListener('sourceopen', self._openHandler)
|
|
self._elem.removeEventListener('timeupdate', self._flowHandler)
|
|
if (self._sourceBuffer) {
|
|
self._sourceBuffer.removeEventListener('updateend', self._flowHandler)
|
|
self._sourceBuffer.removeEventListener('error', self._errorHandler)
|
|
if (self._mediaSource.readyState === 'open') {
|
|
self._sourceBuffer.abort()
|
|
}
|
|
}
|
|
|
|
if (err) self.emit('error', err)
|
|
self.emit('close')
|
|
}
|
|
|
|
MediaSourceStream.prototype._createSourceBuffer = function () {
|
|
var self = this
|
|
if (self.destroyed) return
|
|
|
|
if (MediaSource.isTypeSupported(self._type)) {
|
|
self._sourceBuffer = self._mediaSource.addSourceBuffer(self._type)
|
|
self._sourceBuffer.addEventListener('updateend', self._flowHandler)
|
|
self._sourceBuffer.addEventListener('error', self._errorHandler)
|
|
if (self._cb) {
|
|
var cb = self._cb
|
|
self._cb = null
|
|
cb()
|
|
}
|
|
} else {
|
|
self.destroy(new Error('The provided type is not supported'))
|
|
}
|
|
}
|
|
|
|
MediaSourceStream.prototype._write = function (chunk, encoding, cb) {
|
|
var self = this
|
|
if (self.destroyed) return
|
|
if (!self._sourceBuffer) {
|
|
self._cb = function (err) {
|
|
if (err) return cb(err)
|
|
self._write(chunk, encoding, cb)
|
|
}
|
|
return
|
|
}
|
|
|
|
if (self._sourceBuffer.updating) {
|
|
return cb(new Error('Cannot append buffer while source buffer updating'))
|
|
}
|
|
|
|
var arr = toArrayBuffer(chunk)
|
|
if (self._wrapper._debug) {
|
|
self._debugBuffers.push(arr)
|
|
}
|
|
|
|
try {
|
|
self._sourceBuffer.appendBuffer(arr)
|
|
} catch (err) {
|
|
// appendBuffer can throw for a number of reasons, most notably when the data
|
|
// being appended is invalid or if appendBuffer is called after another error
|
|
// already occurred on the media element. In Chrome, there may be useful debugging
|
|
// info in chrome://media-internals
|
|
self.destroy(err)
|
|
return
|
|
}
|
|
self._cb = cb
|
|
}
|
|
|
|
MediaSourceStream.prototype._flow = function () {
|
|
var self = this
|
|
|
|
if (self.destroyed || !self._sourceBuffer || self._sourceBuffer.updating) {
|
|
return
|
|
}
|
|
|
|
if (self._mediaSource.readyState === 'open') {
|
|
// check buffer size
|
|
if (self._getBufferDuration() > self._bufferDuration) {
|
|
return
|
|
}
|
|
}
|
|
|
|
if (self._cb) {
|
|
var cb = self._cb
|
|
self._cb = null
|
|
cb()
|
|
}
|
|
}
|
|
|
|
// TODO: if zero actually works in all browsers, remove the logic associated with this below
|
|
var EPSILON = 0
|
|
|
|
MediaSourceStream.prototype._getBufferDuration = function () {
|
|
var self = this
|
|
|
|
var buffered = self._sourceBuffer.buffered
|
|
var currentTime = self._elem.currentTime
|
|
var bufferEnd = -1 // end of the buffer
|
|
// This is a little over complex because some browsers seem to separate the
|
|
// buffered region into multiple sections with slight gaps.
|
|
for (var i = 0; i < buffered.length; i++) {
|
|
var start = buffered.start(i)
|
|
var end = buffered.end(i) + EPSILON
|
|
|
|
if (start > currentTime) {
|
|
// Reached past the joined buffer
|
|
break
|
|
} else if (bufferEnd >= 0 || currentTime <= end) {
|
|
// Found the start/continuation of the joined buffer
|
|
bufferEnd = end
|
|
}
|
|
}
|
|
|
|
var bufferedTime = bufferEnd - currentTime
|
|
if (bufferedTime < 0) {
|
|
bufferedTime = 0
|
|
}
|
|
|
|
return bufferedTime
|
|
}
|
|
|
|
function downloadBuffers (bufs, name) {
|
|
var a = document.createElement('a')
|
|
a.href = window.URL.createObjectURL(new window.Blob(bufs))
|
|
a.download = name
|
|
a.click()
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/memory-chunk-store/index.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/memory-chunk-store/index.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
module.exports = Storage
|
|
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
|
|
function Storage (chunkLength, opts) {
|
|
if (!(this instanceof Storage)) return new Storage(chunkLength, opts)
|
|
if (!opts) opts = {}
|
|
|
|
this.chunkLength = Number(chunkLength)
|
|
if (!this.chunkLength) throw new Error('First argument must be a chunk length')
|
|
|
|
this.chunks = []
|
|
this.closed = false
|
|
this.length = Number(opts.length) || Infinity
|
|
|
|
if (this.length !== Infinity) {
|
|
this.lastChunkLength = (this.length % this.chunkLength) || this.chunkLength
|
|
this.lastChunkIndex = Math.ceil(this.length / this.chunkLength) - 1
|
|
}
|
|
}
|
|
|
|
Storage.prototype.put = function (index, buf, cb = () => {}) {
|
|
if (this.closed) return queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
|
|
const isLastChunk = (index === this.lastChunkIndex)
|
|
if (isLastChunk && buf.length !== this.lastChunkLength) {
|
|
return queueMicrotask(() => cb(new Error('Last chunk length must be ' + this.lastChunkLength)))
|
|
}
|
|
if (!isLastChunk && buf.length !== this.chunkLength) {
|
|
return queueMicrotask(() => cb(new Error('Chunk length must be ' + this.chunkLength)))
|
|
}
|
|
this.chunks[index] = buf
|
|
queueMicrotask(() => cb(null))
|
|
}
|
|
|
|
Storage.prototype.get = function (index, opts, cb = () => {}) {
|
|
if (typeof opts === 'function') return this.get(index, null, opts)
|
|
if (this.closed) return queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
|
|
let buf = this.chunks[index]
|
|
|
|
if (!buf) {
|
|
const err = new Error('Chunk not found')
|
|
err.notFound = true
|
|
return queueMicrotask(() => cb(err))
|
|
}
|
|
|
|
if (!opts) opts = {}
|
|
|
|
const offset = opts.offset || 0
|
|
const len = opts.length || (buf.length - offset)
|
|
|
|
if (offset !== 0 || len !== buf.length) {
|
|
buf = buf.slice(offset, len + offset)
|
|
}
|
|
|
|
queueMicrotask(() => cb(null, buf))
|
|
}
|
|
|
|
Storage.prototype.close = Storage.prototype.destroy = function (cb = () => {}) {
|
|
if (this.closed) return queueMicrotask(() => cb(new Error('Storage is closed')))
|
|
this.closed = true
|
|
this.chunks = null
|
|
queueMicrotask(() => cb(null))
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/miller-rabin/lib/mr.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/miller-rabin/lib/mr.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var bn = __webpack_require__(/*! bn.js */ "./node_modules/miller-rabin/node_modules/bn.js/lib/bn.js");
|
|
var brorand = __webpack_require__(/*! brorand */ "./node_modules/brorand/index.js");
|
|
|
|
function MillerRabin(rand) {
|
|
this.rand = rand || new brorand.Rand();
|
|
}
|
|
module.exports = MillerRabin;
|
|
|
|
MillerRabin.create = function create(rand) {
|
|
return new MillerRabin(rand);
|
|
};
|
|
|
|
MillerRabin.prototype._randbelow = function _randbelow(n) {
|
|
var len = n.bitLength();
|
|
var min_bytes = Math.ceil(len / 8);
|
|
|
|
// Generage random bytes until a number less than n is found.
|
|
// This ensures that 0..n-1 have an equal probability of being selected.
|
|
do
|
|
var a = new bn(this.rand.generate(min_bytes));
|
|
while (a.cmp(n) >= 0);
|
|
|
|
return a;
|
|
};
|
|
|
|
MillerRabin.prototype._randrange = function _randrange(start, stop) {
|
|
// Generate a random number greater than or equal to start and less than stop.
|
|
var size = stop.sub(start);
|
|
return start.add(this._randbelow(size));
|
|
};
|
|
|
|
MillerRabin.prototype.test = function test(n, k, cb) {
|
|
var len = n.bitLength();
|
|
var red = bn.mont(n);
|
|
var rone = new bn(1).toRed(red);
|
|
|
|
if (!k)
|
|
k = Math.max(1, (len / 48) | 0);
|
|
|
|
// Find d and s, (n - 1) = (2 ^ s) * d;
|
|
var n1 = n.subn(1);
|
|
for (var s = 0; !n1.testn(s); s++) {}
|
|
var d = n.shrn(s);
|
|
|
|
var rn1 = n1.toRed(red);
|
|
|
|
var prime = true;
|
|
for (; k > 0; k--) {
|
|
var a = this._randrange(new bn(2), n1);
|
|
if (cb)
|
|
cb(a);
|
|
|
|
var x = a.toRed(red).redPow(d);
|
|
if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
|
|
continue;
|
|
|
|
for (var i = 1; i < s; i++) {
|
|
x = x.redSqr();
|
|
|
|
if (x.cmp(rone) === 0)
|
|
return false;
|
|
if (x.cmp(rn1) === 0)
|
|
break;
|
|
}
|
|
|
|
if (i === s)
|
|
return false;
|
|
}
|
|
|
|
return prime;
|
|
};
|
|
|
|
MillerRabin.prototype.getDivisor = function getDivisor(n, k) {
|
|
var len = n.bitLength();
|
|
var red = bn.mont(n);
|
|
var rone = new bn(1).toRed(red);
|
|
|
|
if (!k)
|
|
k = Math.max(1, (len / 48) | 0);
|
|
|
|
// Find d and s, (n - 1) = (2 ^ s) * d;
|
|
var n1 = n.subn(1);
|
|
for (var s = 0; !n1.testn(s); s++) {}
|
|
var d = n.shrn(s);
|
|
|
|
var rn1 = n1.toRed(red);
|
|
|
|
for (; k > 0; k--) {
|
|
var a = this._randrange(new bn(2), n1);
|
|
|
|
var g = n.gcd(a);
|
|
if (g.cmpn(1) !== 0)
|
|
return g;
|
|
|
|
var x = a.toRed(red).redPow(d);
|
|
if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
|
|
continue;
|
|
|
|
for (var i = 1; i < s; i++) {
|
|
x = x.redSqr();
|
|
|
|
if (x.cmp(rone) === 0)
|
|
return x.fromRed().subn(1).gcd(n);
|
|
if (x.cmp(rn1) === 0)
|
|
break;
|
|
}
|
|
|
|
if (i === s) {
|
|
x = x.redSqr();
|
|
return x.fromRed().subn(1).gcd(n);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/miller-rabin/node_modules/bn.js/lib/bn.js":
|
|
/*!****************************************************************!*\
|
|
!*** ./node_modules/miller-rabin/node_modules/bn.js/lib/bn.js ***!
|
|
\****************************************************************/
|
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
/* module decorator */ module = __webpack_require__.nmd(module);
|
|
(function (module, exports) {
|
|
'use strict';
|
|
|
|
// Utils
|
|
function assert (val, msg) {
|
|
if (!val) throw new Error(msg || 'Assertion failed');
|
|
}
|
|
|
|
// Could use `inherits` module, but don't want to move from single file
|
|
// architecture yet.
|
|
function inherits (ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
var TempCtor = function () {};
|
|
TempCtor.prototype = superCtor.prototype;
|
|
ctor.prototype = new TempCtor();
|
|
ctor.prototype.constructor = ctor;
|
|
}
|
|
|
|
// BN
|
|
|
|
function BN (number, base, endian) {
|
|
if (BN.isBN(number)) {
|
|
return number;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.words = null;
|
|
this.length = 0;
|
|
|
|
// Reduction context
|
|
this.red = null;
|
|
|
|
if (number !== null) {
|
|
if (base === 'le' || base === 'be') {
|
|
endian = base;
|
|
base = 10;
|
|
}
|
|
|
|
this._init(number || 0, base || 10, endian || 'be');
|
|
}
|
|
}
|
|
if (typeof module === 'object') {
|
|
module.exports = BN;
|
|
} else {
|
|
exports.BN = BN;
|
|
}
|
|
|
|
BN.BN = BN;
|
|
BN.wordSize = 26;
|
|
|
|
var Buffer;
|
|
try {
|
|
if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') {
|
|
Buffer = window.Buffer;
|
|
} else {
|
|
Buffer = __webpack_require__(/*! buffer */ "?0aec").Buffer;
|
|
}
|
|
} catch (e) {
|
|
}
|
|
|
|
BN.isBN = function isBN (num) {
|
|
if (num instanceof BN) {
|
|
return true;
|
|
}
|
|
|
|
return num !== null && typeof num === 'object' &&
|
|
num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
|
|
};
|
|
|
|
BN.max = function max (left, right) {
|
|
if (left.cmp(right) > 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.min = function min (left, right) {
|
|
if (left.cmp(right) < 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.prototype._init = function init (number, base, endian) {
|
|
if (typeof number === 'number') {
|
|
return this._initNumber(number, base, endian);
|
|
}
|
|
|
|
if (typeof number === 'object') {
|
|
return this._initArray(number, base, endian);
|
|
}
|
|
|
|
if (base === 'hex') {
|
|
base = 16;
|
|
}
|
|
assert(base === (base | 0) && base >= 2 && base <= 36);
|
|
|
|
number = number.toString().replace(/\s+/g, '');
|
|
var start = 0;
|
|
if (number[0] === '-') {
|
|
start++;
|
|
this.negative = 1;
|
|
}
|
|
|
|
if (start < number.length) {
|
|
if (base === 16) {
|
|
this._parseHex(number, start, endian);
|
|
} else {
|
|
this._parseBase(number, base, start);
|
|
if (endian === 'le') {
|
|
this._initArray(this.toArray(), base, endian);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
BN.prototype._initNumber = function _initNumber (number, base, endian) {
|
|
if (number < 0) {
|
|
this.negative = 1;
|
|
number = -number;
|
|
}
|
|
if (number < 0x4000000) {
|
|
this.words = [ number & 0x3ffffff ];
|
|
this.length = 1;
|
|
} else if (number < 0x10000000000000) {
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff
|
|
];
|
|
this.length = 2;
|
|
} else {
|
|
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff,
|
|
1
|
|
];
|
|
this.length = 3;
|
|
}
|
|
|
|
if (endian !== 'le') return;
|
|
|
|
// Reverse the bytes
|
|
this._initArray(this.toArray(), base, endian);
|
|
};
|
|
|
|
BN.prototype._initArray = function _initArray (number, base, endian) {
|
|
// Perhaps a Uint8Array
|
|
assert(typeof number.length === 'number');
|
|
if (number.length <= 0) {
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
return this;
|
|
}
|
|
|
|
this.length = Math.ceil(number.length / 3);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
var j, w;
|
|
var off = 0;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
|
|
w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
} else if (endian === 'le') {
|
|
for (i = 0, j = 0; i < number.length; i += 3) {
|
|
w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
return this.strip();
|
|
};
|
|
|
|
function parseHex4Bits (string, index) {
|
|
var c = string.charCodeAt(index);
|
|
// 'A' - 'F'
|
|
if (c >= 65 && c <= 70) {
|
|
return c - 55;
|
|
// 'a' - 'f'
|
|
} else if (c >= 97 && c <= 102) {
|
|
return c - 87;
|
|
// '0' - '9'
|
|
} else {
|
|
return (c - 48) & 0xf;
|
|
}
|
|
}
|
|
|
|
function parseHexByte (string, lowerBound, index) {
|
|
var r = parseHex4Bits(string, index);
|
|
if (index - 1 >= lowerBound) {
|
|
r |= parseHex4Bits(string, index - 1) << 4;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseHex = function _parseHex (number, start, endian) {
|
|
// Create possibly bigger array to ensure that it fits the number
|
|
this.length = Math.ceil((number.length - start) / 6);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
// 24-bits chunks
|
|
var off = 0;
|
|
var j = 0;
|
|
|
|
var w;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1; i >= start; i -= 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
} else {
|
|
var parseLength = number.length - start;
|
|
for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
function parseBase (str, start, end, mul) {
|
|
var r = 0;
|
|
var len = Math.min(str.length, end);
|
|
for (var i = start; i < len; i++) {
|
|
var c = str.charCodeAt(i) - 48;
|
|
|
|
r *= mul;
|
|
|
|
// 'a'
|
|
if (c >= 49) {
|
|
r += c - 49 + 0xa;
|
|
|
|
// 'A'
|
|
} else if (c >= 17) {
|
|
r += c - 17 + 0xa;
|
|
|
|
// '0' - '9'
|
|
} else {
|
|
r += c;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseBase = function _parseBase (number, base, start) {
|
|
// Initialize as zero
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
|
|
// Find length of limb in base
|
|
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
|
|
limbLen++;
|
|
}
|
|
limbLen--;
|
|
limbPow = (limbPow / base) | 0;
|
|
|
|
var total = number.length - start;
|
|
var mod = total % limbLen;
|
|
var end = Math.min(total, total - mod) + start;
|
|
|
|
var word = 0;
|
|
for (var i = start; i < end; i += limbLen) {
|
|
word = parseBase(number, i, i + limbLen, base);
|
|
|
|
this.imuln(limbPow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
if (mod !== 0) {
|
|
var pow = 1;
|
|
word = parseBase(number, i, number.length, base);
|
|
|
|
for (i = 0; i < mod; i++) {
|
|
pow *= base;
|
|
}
|
|
|
|
this.imuln(pow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
BN.prototype.copy = function copy (dest) {
|
|
dest.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
dest.words[i] = this.words[i];
|
|
}
|
|
dest.length = this.length;
|
|
dest.negative = this.negative;
|
|
dest.red = this.red;
|
|
};
|
|
|
|
BN.prototype.clone = function clone () {
|
|
var r = new BN(null);
|
|
this.copy(r);
|
|
return r;
|
|
};
|
|
|
|
BN.prototype._expand = function _expand (size) {
|
|
while (this.length < size) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
// Remove leading `0` from `this`
|
|
BN.prototype.strip = function strip () {
|
|
while (this.length > 1 && this.words[this.length - 1] === 0) {
|
|
this.length--;
|
|
}
|
|
return this._normSign();
|
|
};
|
|
|
|
BN.prototype._normSign = function _normSign () {
|
|
// -0 = 0
|
|
if (this.length === 1 && this.words[0] === 0) {
|
|
this.negative = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.inspect = function inspect () {
|
|
return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
|
|
};
|
|
|
|
/*
|
|
|
|
var zeros = [];
|
|
var groupSizes = [];
|
|
var groupBases = [];
|
|
|
|
var s = '';
|
|
var i = -1;
|
|
while (++i < BN.wordSize) {
|
|
zeros[i] = s;
|
|
s += '0';
|
|
}
|
|
groupSizes[0] = 0;
|
|
groupSizes[1] = 0;
|
|
groupBases[0] = 0;
|
|
groupBases[1] = 0;
|
|
var base = 2 - 1;
|
|
while (++base < 36 + 1) {
|
|
var groupSize = 0;
|
|
var groupBase = 1;
|
|
while (groupBase < (1 << BN.wordSize) / base) {
|
|
groupBase *= base;
|
|
groupSize += 1;
|
|
}
|
|
groupSizes[base] = groupSize;
|
|
groupBases[base] = groupBase;
|
|
}
|
|
|
|
*/
|
|
|
|
var zeros = [
|
|
'',
|
|
'0',
|
|
'00',
|
|
'000',
|
|
'0000',
|
|
'00000',
|
|
'000000',
|
|
'0000000',
|
|
'00000000',
|
|
'000000000',
|
|
'0000000000',
|
|
'00000000000',
|
|
'000000000000',
|
|
'0000000000000',
|
|
'00000000000000',
|
|
'000000000000000',
|
|
'0000000000000000',
|
|
'00000000000000000',
|
|
'000000000000000000',
|
|
'0000000000000000000',
|
|
'00000000000000000000',
|
|
'000000000000000000000',
|
|
'0000000000000000000000',
|
|
'00000000000000000000000',
|
|
'000000000000000000000000',
|
|
'0000000000000000000000000'
|
|
];
|
|
|
|
var groupSizes = [
|
|
0, 0,
|
|
25, 16, 12, 11, 10, 9, 8,
|
|
8, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5
|
|
];
|
|
|
|
var groupBases = [
|
|
0, 0,
|
|
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
|
|
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
|
|
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
|
|
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
|
|
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
|
|
];
|
|
|
|
BN.prototype.toString = function toString (base, padding) {
|
|
base = base || 10;
|
|
padding = padding | 0 || 1;
|
|
|
|
var out;
|
|
if (base === 16 || base === 'hex') {
|
|
out = '';
|
|
var off = 0;
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = this.words[i];
|
|
var word = (((w << off) | carry) & 0xffffff).toString(16);
|
|
carry = (w >>> (24 - off)) & 0xffffff;
|
|
if (carry !== 0 || i !== this.length - 1) {
|
|
out = zeros[6 - word.length] + word + out;
|
|
} else {
|
|
out = word + out;
|
|
}
|
|
off += 2;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
i--;
|
|
}
|
|
}
|
|
if (carry !== 0) {
|
|
out = carry.toString(16) + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
if (base === (base | 0) && base >= 2 && base <= 36) {
|
|
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
|
|
var groupSize = groupSizes[base];
|
|
// var groupBase = Math.pow(base, groupSize);
|
|
var groupBase = groupBases[base];
|
|
out = '';
|
|
var c = this.clone();
|
|
c.negative = 0;
|
|
while (!c.isZero()) {
|
|
var r = c.modn(groupBase).toString(base);
|
|
c = c.idivn(groupBase);
|
|
|
|
if (!c.isZero()) {
|
|
out = zeros[groupSize - r.length] + r + out;
|
|
} else {
|
|
out = r + out;
|
|
}
|
|
}
|
|
if (this.isZero()) {
|
|
out = '0' + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
assert(false, 'Base should be between 2 and 36');
|
|
};
|
|
|
|
BN.prototype.toNumber = function toNumber () {
|
|
var ret = this.words[0];
|
|
if (this.length === 2) {
|
|
ret += this.words[1] * 0x4000000;
|
|
} else if (this.length === 3 && this.words[2] === 0x01) {
|
|
// NOTE: at this stage it is known that the top bit is set
|
|
ret += 0x10000000000000 + (this.words[1] * 0x4000000);
|
|
} else if (this.length > 2) {
|
|
assert(false, 'Number can only safely store up to 53 bits');
|
|
}
|
|
return (this.negative !== 0) ? -ret : ret;
|
|
};
|
|
|
|
BN.prototype.toJSON = function toJSON () {
|
|
return this.toString(16);
|
|
};
|
|
|
|
BN.prototype.toBuffer = function toBuffer (endian, length) {
|
|
assert(typeof Buffer !== 'undefined');
|
|
return this.toArrayLike(Buffer, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArray = function toArray (endian, length) {
|
|
return this.toArrayLike(Array, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
|
|
var byteLength = this.byteLength();
|
|
var reqLength = length || Math.max(1, byteLength);
|
|
assert(byteLength <= reqLength, 'byte array longer than desired length');
|
|
assert(reqLength > 0, 'Requested array length <= 0');
|
|
|
|
this.strip();
|
|
var littleEndian = endian === 'le';
|
|
var res = new ArrayType(reqLength);
|
|
|
|
var b, i;
|
|
var q = this.clone();
|
|
if (!littleEndian) {
|
|
// Assume big-endian
|
|
for (i = 0; i < reqLength - byteLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[reqLength - i - 1] = b;
|
|
}
|
|
} else {
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[i] = b;
|
|
}
|
|
|
|
for (; i < reqLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
if (Math.clz32) {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
return 32 - Math.clz32(w);
|
|
};
|
|
} else {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
var t = w;
|
|
var r = 0;
|
|
if (t >= 0x1000) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if (t >= 0x40) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if (t >= 0x8) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if (t >= 0x02) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
return r + t;
|
|
};
|
|
}
|
|
|
|
BN.prototype._zeroBits = function _zeroBits (w) {
|
|
// Short-cut
|
|
if (w === 0) return 26;
|
|
|
|
var t = w;
|
|
var r = 0;
|
|
if ((t & 0x1fff) === 0) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if ((t & 0x7f) === 0) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if ((t & 0xf) === 0) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if ((t & 0x3) === 0) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
if ((t & 0x1) === 0) {
|
|
r++;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
// Return number of used bits in a BN
|
|
BN.prototype.bitLength = function bitLength () {
|
|
var w = this.words[this.length - 1];
|
|
var hi = this._countBits(w);
|
|
return (this.length - 1) * 26 + hi;
|
|
};
|
|
|
|
function toBitArray (num) {
|
|
var w = new Array(num.bitLength());
|
|
|
|
for (var bit = 0; bit < w.length; bit++) {
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
// Number of trailing zero bits
|
|
BN.prototype.zeroBits = function zeroBits () {
|
|
if (this.isZero()) return 0;
|
|
|
|
var r = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var b = this._zeroBits(this.words[i]);
|
|
r += b;
|
|
if (b !== 26) break;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
BN.prototype.byteLength = function byteLength () {
|
|
return Math.ceil(this.bitLength() / 8);
|
|
};
|
|
|
|
BN.prototype.toTwos = function toTwos (width) {
|
|
if (this.negative !== 0) {
|
|
return this.abs().inotn(width).iaddn(1);
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.fromTwos = function fromTwos (width) {
|
|
if (this.testn(width - 1)) {
|
|
return this.notn(width).iaddn(1).ineg();
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.isNeg = function isNeg () {
|
|
return this.negative !== 0;
|
|
};
|
|
|
|
// Return negative clone of `this`
|
|
BN.prototype.neg = function neg () {
|
|
return this.clone().ineg();
|
|
};
|
|
|
|
BN.prototype.ineg = function ineg () {
|
|
if (!this.isZero()) {
|
|
this.negative ^= 1;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Or `num` with `this` in-place
|
|
BN.prototype.iuor = function iuor (num) {
|
|
while (this.length < num.length) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
|
|
for (var i = 0; i < num.length; i++) {
|
|
this.words[i] = this.words[i] | num.words[i];
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ior = function ior (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuor(num);
|
|
};
|
|
|
|
// Or `num` with `this`
|
|
BN.prototype.or = function or (num) {
|
|
if (this.length > num.length) return this.clone().ior(num);
|
|
return num.clone().ior(this);
|
|
};
|
|
|
|
BN.prototype.uor = function uor (num) {
|
|
if (this.length > num.length) return this.clone().iuor(num);
|
|
return num.clone().iuor(this);
|
|
};
|
|
|
|
// And `num` with `this` in-place
|
|
BN.prototype.iuand = function iuand (num) {
|
|
// b = min-length(num, this)
|
|
var b;
|
|
if (this.length > num.length) {
|
|
b = num;
|
|
} else {
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = this.words[i] & num.words[i];
|
|
}
|
|
|
|
this.length = b.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.iand = function iand (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuand(num);
|
|
};
|
|
|
|
// And `num` with `this`
|
|
BN.prototype.and = function and (num) {
|
|
if (this.length > num.length) return this.clone().iand(num);
|
|
return num.clone().iand(this);
|
|
};
|
|
|
|
BN.prototype.uand = function uand (num) {
|
|
if (this.length > num.length) return this.clone().iuand(num);
|
|
return num.clone().iuand(this);
|
|
};
|
|
|
|
// Xor `num` with `this` in-place
|
|
BN.prototype.iuxor = function iuxor (num) {
|
|
// a.length > b.length
|
|
var a;
|
|
var b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = a.words[i] ^ b.words[i];
|
|
}
|
|
|
|
if (this !== a) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = a.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ixor = function ixor (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuxor(num);
|
|
};
|
|
|
|
// Xor `num` with `this`
|
|
BN.prototype.xor = function xor (num) {
|
|
if (this.length > num.length) return this.clone().ixor(num);
|
|
return num.clone().ixor(this);
|
|
};
|
|
|
|
BN.prototype.uxor = function uxor (num) {
|
|
if (this.length > num.length) return this.clone().iuxor(num);
|
|
return num.clone().iuxor(this);
|
|
};
|
|
|
|
// Not ``this`` with ``width`` bitwidth
|
|
BN.prototype.inotn = function inotn (width) {
|
|
assert(typeof width === 'number' && width >= 0);
|
|
|
|
var bytesNeeded = Math.ceil(width / 26) | 0;
|
|
var bitsLeft = width % 26;
|
|
|
|
// Extend the buffer with leading zeroes
|
|
this._expand(bytesNeeded);
|
|
|
|
if (bitsLeft > 0) {
|
|
bytesNeeded--;
|
|
}
|
|
|
|
// Handle complete words
|
|
for (var i = 0; i < bytesNeeded; i++) {
|
|
this.words[i] = ~this.words[i] & 0x3ffffff;
|
|
}
|
|
|
|
// Handle the residue
|
|
if (bitsLeft > 0) {
|
|
this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
|
|
}
|
|
|
|
// And remove leading zeroes
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.notn = function notn (width) {
|
|
return this.clone().inotn(width);
|
|
};
|
|
|
|
// Set `bit` of `this`
|
|
BN.prototype.setn = function setn (bit, val) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
this._expand(off + 1);
|
|
|
|
if (val) {
|
|
this.words[off] = this.words[off] | (1 << wbit);
|
|
} else {
|
|
this.words[off] = this.words[off] & ~(1 << wbit);
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Add `num` to `this` in-place
|
|
BN.prototype.iadd = function iadd (num) {
|
|
var r;
|
|
|
|
// negative + positive
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
this.negative = 0;
|
|
r = this.isub(num);
|
|
this.negative ^= 1;
|
|
return this._normSign();
|
|
|
|
// positive + negative
|
|
} else if (this.negative === 0 && num.negative !== 0) {
|
|
num.negative = 0;
|
|
r = this.isub(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
}
|
|
|
|
// a.length > b.length
|
|
var a, b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
|
|
this.length = a.length;
|
|
if (carry !== 0) {
|
|
this.words[this.length] = carry;
|
|
this.length++;
|
|
// Copy the rest of the words
|
|
} else if (a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Add `num` to `this`
|
|
BN.prototype.add = function add (num) {
|
|
var res;
|
|
if (num.negative !== 0 && this.negative === 0) {
|
|
num.negative = 0;
|
|
res = this.sub(num);
|
|
num.negative ^= 1;
|
|
return res;
|
|
} else if (num.negative === 0 && this.negative !== 0) {
|
|
this.negative = 0;
|
|
res = num.sub(this);
|
|
this.negative = 1;
|
|
return res;
|
|
}
|
|
|
|
if (this.length > num.length) return this.clone().iadd(num);
|
|
|
|
return num.clone().iadd(this);
|
|
};
|
|
|
|
// Subtract `num` from `this` in-place
|
|
BN.prototype.isub = function isub (num) {
|
|
// this - (-num) = this + num
|
|
if (num.negative !== 0) {
|
|
num.negative = 0;
|
|
var r = this.iadd(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
|
|
// -this - num = -(this + num)
|
|
} else if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iadd(num);
|
|
this.negative = 1;
|
|
return this._normSign();
|
|
}
|
|
|
|
// At this point both numbers are positive
|
|
var cmp = this.cmp(num);
|
|
|
|
// Optimization - zeroify
|
|
if (cmp === 0) {
|
|
this.negative = 0;
|
|
this.length = 1;
|
|
this.words[0] = 0;
|
|
return this;
|
|
}
|
|
|
|
// a > b
|
|
var a, b;
|
|
if (cmp > 0) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
|
|
// Copy rest of the words
|
|
if (carry === 0 && i < a.length && a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = Math.max(this.length, i);
|
|
|
|
if (a !== this) {
|
|
this.negative = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Subtract `num` from `this`
|
|
BN.prototype.sub = function sub (num) {
|
|
return this.clone().isub(num);
|
|
};
|
|
|
|
function smallMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
var len = (self.length + num.length) | 0;
|
|
out.length = len;
|
|
len = (len - 1) | 0;
|
|
|
|
// Peel one iteration (compiler can't do it, because of code complexity)
|
|
var a = self.words[0] | 0;
|
|
var b = num.words[0] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
var carry = (r / 0x4000000) | 0;
|
|
out.words[0] = lo;
|
|
|
|
for (var k = 1; k < len; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = carry >>> 26;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = (k - j) | 0;
|
|
a = self.words[i] | 0;
|
|
b = num.words[j] | 0;
|
|
r = a * b + rword;
|
|
ncarry += (r / 0x4000000) | 0;
|
|
rword = r & 0x3ffffff;
|
|
}
|
|
out.words[k] = rword | 0;
|
|
carry = ncarry | 0;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry | 0;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
// TODO(indutny): it may be reasonable to omit it for users who don't need
|
|
// to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
|
|
// multiplication (like elliptic secp256k1).
|
|
var comb10MulTo = function comb10MulTo (self, num, out) {
|
|
var a = self.words;
|
|
var b = num.words;
|
|
var o = out.words;
|
|
var c = 0;
|
|
var lo;
|
|
var mid;
|
|
var hi;
|
|
var a0 = a[0] | 0;
|
|
var al0 = a0 & 0x1fff;
|
|
var ah0 = a0 >>> 13;
|
|
var a1 = a[1] | 0;
|
|
var al1 = a1 & 0x1fff;
|
|
var ah1 = a1 >>> 13;
|
|
var a2 = a[2] | 0;
|
|
var al2 = a2 & 0x1fff;
|
|
var ah2 = a2 >>> 13;
|
|
var a3 = a[3] | 0;
|
|
var al3 = a3 & 0x1fff;
|
|
var ah3 = a3 >>> 13;
|
|
var a4 = a[4] | 0;
|
|
var al4 = a4 & 0x1fff;
|
|
var ah4 = a4 >>> 13;
|
|
var a5 = a[5] | 0;
|
|
var al5 = a5 & 0x1fff;
|
|
var ah5 = a5 >>> 13;
|
|
var a6 = a[6] | 0;
|
|
var al6 = a6 & 0x1fff;
|
|
var ah6 = a6 >>> 13;
|
|
var a7 = a[7] | 0;
|
|
var al7 = a7 & 0x1fff;
|
|
var ah7 = a7 >>> 13;
|
|
var a8 = a[8] | 0;
|
|
var al8 = a8 & 0x1fff;
|
|
var ah8 = a8 >>> 13;
|
|
var a9 = a[9] | 0;
|
|
var al9 = a9 & 0x1fff;
|
|
var ah9 = a9 >>> 13;
|
|
var b0 = b[0] | 0;
|
|
var bl0 = b0 & 0x1fff;
|
|
var bh0 = b0 >>> 13;
|
|
var b1 = b[1] | 0;
|
|
var bl1 = b1 & 0x1fff;
|
|
var bh1 = b1 >>> 13;
|
|
var b2 = b[2] | 0;
|
|
var bl2 = b2 & 0x1fff;
|
|
var bh2 = b2 >>> 13;
|
|
var b3 = b[3] | 0;
|
|
var bl3 = b3 & 0x1fff;
|
|
var bh3 = b3 >>> 13;
|
|
var b4 = b[4] | 0;
|
|
var bl4 = b4 & 0x1fff;
|
|
var bh4 = b4 >>> 13;
|
|
var b5 = b[5] | 0;
|
|
var bl5 = b5 & 0x1fff;
|
|
var bh5 = b5 >>> 13;
|
|
var b6 = b[6] | 0;
|
|
var bl6 = b6 & 0x1fff;
|
|
var bh6 = b6 >>> 13;
|
|
var b7 = b[7] | 0;
|
|
var bl7 = b7 & 0x1fff;
|
|
var bh7 = b7 >>> 13;
|
|
var b8 = b[8] | 0;
|
|
var bl8 = b8 & 0x1fff;
|
|
var bh8 = b8 >>> 13;
|
|
var b9 = b[9] | 0;
|
|
var bl9 = b9 & 0x1fff;
|
|
var bh9 = b9 >>> 13;
|
|
|
|
out.negative = self.negative ^ num.negative;
|
|
out.length = 19;
|
|
/* k = 0 */
|
|
lo = Math.imul(al0, bl0);
|
|
mid = Math.imul(al0, bh0);
|
|
mid = (mid + Math.imul(ah0, bl0)) | 0;
|
|
hi = Math.imul(ah0, bh0);
|
|
var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
|
|
w0 &= 0x3ffffff;
|
|
/* k = 1 */
|
|
lo = Math.imul(al1, bl0);
|
|
mid = Math.imul(al1, bh0);
|
|
mid = (mid + Math.imul(ah1, bl0)) | 0;
|
|
hi = Math.imul(ah1, bh0);
|
|
lo = (lo + Math.imul(al0, bl1)) | 0;
|
|
mid = (mid + Math.imul(al0, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh1)) | 0;
|
|
var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
|
|
w1 &= 0x3ffffff;
|
|
/* k = 2 */
|
|
lo = Math.imul(al2, bl0);
|
|
mid = Math.imul(al2, bh0);
|
|
mid = (mid + Math.imul(ah2, bl0)) | 0;
|
|
hi = Math.imul(ah2, bh0);
|
|
lo = (lo + Math.imul(al1, bl1)) | 0;
|
|
mid = (mid + Math.imul(al1, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh1)) | 0;
|
|
lo = (lo + Math.imul(al0, bl2)) | 0;
|
|
mid = (mid + Math.imul(al0, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh2)) | 0;
|
|
var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
|
|
w2 &= 0x3ffffff;
|
|
/* k = 3 */
|
|
lo = Math.imul(al3, bl0);
|
|
mid = Math.imul(al3, bh0);
|
|
mid = (mid + Math.imul(ah3, bl0)) | 0;
|
|
hi = Math.imul(ah3, bh0);
|
|
lo = (lo + Math.imul(al2, bl1)) | 0;
|
|
mid = (mid + Math.imul(al2, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh1)) | 0;
|
|
lo = (lo + Math.imul(al1, bl2)) | 0;
|
|
mid = (mid + Math.imul(al1, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh2)) | 0;
|
|
lo = (lo + Math.imul(al0, bl3)) | 0;
|
|
mid = (mid + Math.imul(al0, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh3)) | 0;
|
|
var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
|
|
w3 &= 0x3ffffff;
|
|
/* k = 4 */
|
|
lo = Math.imul(al4, bl0);
|
|
mid = Math.imul(al4, bh0);
|
|
mid = (mid + Math.imul(ah4, bl0)) | 0;
|
|
hi = Math.imul(ah4, bh0);
|
|
lo = (lo + Math.imul(al3, bl1)) | 0;
|
|
mid = (mid + Math.imul(al3, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh1)) | 0;
|
|
lo = (lo + Math.imul(al2, bl2)) | 0;
|
|
mid = (mid + Math.imul(al2, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh2)) | 0;
|
|
lo = (lo + Math.imul(al1, bl3)) | 0;
|
|
mid = (mid + Math.imul(al1, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh3)) | 0;
|
|
lo = (lo + Math.imul(al0, bl4)) | 0;
|
|
mid = (mid + Math.imul(al0, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh4)) | 0;
|
|
var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
|
|
w4 &= 0x3ffffff;
|
|
/* k = 5 */
|
|
lo = Math.imul(al5, bl0);
|
|
mid = Math.imul(al5, bh0);
|
|
mid = (mid + Math.imul(ah5, bl0)) | 0;
|
|
hi = Math.imul(ah5, bh0);
|
|
lo = (lo + Math.imul(al4, bl1)) | 0;
|
|
mid = (mid + Math.imul(al4, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh1)) | 0;
|
|
lo = (lo + Math.imul(al3, bl2)) | 0;
|
|
mid = (mid + Math.imul(al3, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh2)) | 0;
|
|
lo = (lo + Math.imul(al2, bl3)) | 0;
|
|
mid = (mid + Math.imul(al2, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh3)) | 0;
|
|
lo = (lo + Math.imul(al1, bl4)) | 0;
|
|
mid = (mid + Math.imul(al1, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh4)) | 0;
|
|
lo = (lo + Math.imul(al0, bl5)) | 0;
|
|
mid = (mid + Math.imul(al0, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh5)) | 0;
|
|
var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
|
|
w5 &= 0x3ffffff;
|
|
/* k = 6 */
|
|
lo = Math.imul(al6, bl0);
|
|
mid = Math.imul(al6, bh0);
|
|
mid = (mid + Math.imul(ah6, bl0)) | 0;
|
|
hi = Math.imul(ah6, bh0);
|
|
lo = (lo + Math.imul(al5, bl1)) | 0;
|
|
mid = (mid + Math.imul(al5, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh1)) | 0;
|
|
lo = (lo + Math.imul(al4, bl2)) | 0;
|
|
mid = (mid + Math.imul(al4, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh2)) | 0;
|
|
lo = (lo + Math.imul(al3, bl3)) | 0;
|
|
mid = (mid + Math.imul(al3, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh3)) | 0;
|
|
lo = (lo + Math.imul(al2, bl4)) | 0;
|
|
mid = (mid + Math.imul(al2, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh4)) | 0;
|
|
lo = (lo + Math.imul(al1, bl5)) | 0;
|
|
mid = (mid + Math.imul(al1, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh5)) | 0;
|
|
lo = (lo + Math.imul(al0, bl6)) | 0;
|
|
mid = (mid + Math.imul(al0, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh6)) | 0;
|
|
var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
|
|
w6 &= 0x3ffffff;
|
|
/* k = 7 */
|
|
lo = Math.imul(al7, bl0);
|
|
mid = Math.imul(al7, bh0);
|
|
mid = (mid + Math.imul(ah7, bl0)) | 0;
|
|
hi = Math.imul(ah7, bh0);
|
|
lo = (lo + Math.imul(al6, bl1)) | 0;
|
|
mid = (mid + Math.imul(al6, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh1)) | 0;
|
|
lo = (lo + Math.imul(al5, bl2)) | 0;
|
|
mid = (mid + Math.imul(al5, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh2)) | 0;
|
|
lo = (lo + Math.imul(al4, bl3)) | 0;
|
|
mid = (mid + Math.imul(al4, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh3)) | 0;
|
|
lo = (lo + Math.imul(al3, bl4)) | 0;
|
|
mid = (mid + Math.imul(al3, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh4)) | 0;
|
|
lo = (lo + Math.imul(al2, bl5)) | 0;
|
|
mid = (mid + Math.imul(al2, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh5)) | 0;
|
|
lo = (lo + Math.imul(al1, bl6)) | 0;
|
|
mid = (mid + Math.imul(al1, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh6)) | 0;
|
|
lo = (lo + Math.imul(al0, bl7)) | 0;
|
|
mid = (mid + Math.imul(al0, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh7)) | 0;
|
|
var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
|
|
w7 &= 0x3ffffff;
|
|
/* k = 8 */
|
|
lo = Math.imul(al8, bl0);
|
|
mid = Math.imul(al8, bh0);
|
|
mid = (mid + Math.imul(ah8, bl0)) | 0;
|
|
hi = Math.imul(ah8, bh0);
|
|
lo = (lo + Math.imul(al7, bl1)) | 0;
|
|
mid = (mid + Math.imul(al7, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh1)) | 0;
|
|
lo = (lo + Math.imul(al6, bl2)) | 0;
|
|
mid = (mid + Math.imul(al6, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh2)) | 0;
|
|
lo = (lo + Math.imul(al5, bl3)) | 0;
|
|
mid = (mid + Math.imul(al5, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh3)) | 0;
|
|
lo = (lo + Math.imul(al4, bl4)) | 0;
|
|
mid = (mid + Math.imul(al4, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh4)) | 0;
|
|
lo = (lo + Math.imul(al3, bl5)) | 0;
|
|
mid = (mid + Math.imul(al3, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh5)) | 0;
|
|
lo = (lo + Math.imul(al2, bl6)) | 0;
|
|
mid = (mid + Math.imul(al2, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh6)) | 0;
|
|
lo = (lo + Math.imul(al1, bl7)) | 0;
|
|
mid = (mid + Math.imul(al1, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh7)) | 0;
|
|
lo = (lo + Math.imul(al0, bl8)) | 0;
|
|
mid = (mid + Math.imul(al0, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh8)) | 0;
|
|
var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
|
|
w8 &= 0x3ffffff;
|
|
/* k = 9 */
|
|
lo = Math.imul(al9, bl0);
|
|
mid = Math.imul(al9, bh0);
|
|
mid = (mid + Math.imul(ah9, bl0)) | 0;
|
|
hi = Math.imul(ah9, bh0);
|
|
lo = (lo + Math.imul(al8, bl1)) | 0;
|
|
mid = (mid + Math.imul(al8, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh1)) | 0;
|
|
lo = (lo + Math.imul(al7, bl2)) | 0;
|
|
mid = (mid + Math.imul(al7, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh2)) | 0;
|
|
lo = (lo + Math.imul(al6, bl3)) | 0;
|
|
mid = (mid + Math.imul(al6, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh3)) | 0;
|
|
lo = (lo + Math.imul(al5, bl4)) | 0;
|
|
mid = (mid + Math.imul(al5, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh4)) | 0;
|
|
lo = (lo + Math.imul(al4, bl5)) | 0;
|
|
mid = (mid + Math.imul(al4, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh5)) | 0;
|
|
lo = (lo + Math.imul(al3, bl6)) | 0;
|
|
mid = (mid + Math.imul(al3, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh6)) | 0;
|
|
lo = (lo + Math.imul(al2, bl7)) | 0;
|
|
mid = (mid + Math.imul(al2, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh7)) | 0;
|
|
lo = (lo + Math.imul(al1, bl8)) | 0;
|
|
mid = (mid + Math.imul(al1, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh8)) | 0;
|
|
lo = (lo + Math.imul(al0, bl9)) | 0;
|
|
mid = (mid + Math.imul(al0, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh9)) | 0;
|
|
var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
|
|
w9 &= 0x3ffffff;
|
|
/* k = 10 */
|
|
lo = Math.imul(al9, bl1);
|
|
mid = Math.imul(al9, bh1);
|
|
mid = (mid + Math.imul(ah9, bl1)) | 0;
|
|
hi = Math.imul(ah9, bh1);
|
|
lo = (lo + Math.imul(al8, bl2)) | 0;
|
|
mid = (mid + Math.imul(al8, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh2)) | 0;
|
|
lo = (lo + Math.imul(al7, bl3)) | 0;
|
|
mid = (mid + Math.imul(al7, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh3)) | 0;
|
|
lo = (lo + Math.imul(al6, bl4)) | 0;
|
|
mid = (mid + Math.imul(al6, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh4)) | 0;
|
|
lo = (lo + Math.imul(al5, bl5)) | 0;
|
|
mid = (mid + Math.imul(al5, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh5)) | 0;
|
|
lo = (lo + Math.imul(al4, bl6)) | 0;
|
|
mid = (mid + Math.imul(al4, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh6)) | 0;
|
|
lo = (lo + Math.imul(al3, bl7)) | 0;
|
|
mid = (mid + Math.imul(al3, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh7)) | 0;
|
|
lo = (lo + Math.imul(al2, bl8)) | 0;
|
|
mid = (mid + Math.imul(al2, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh8)) | 0;
|
|
lo = (lo + Math.imul(al1, bl9)) | 0;
|
|
mid = (mid + Math.imul(al1, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh9)) | 0;
|
|
var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
|
|
w10 &= 0x3ffffff;
|
|
/* k = 11 */
|
|
lo = Math.imul(al9, bl2);
|
|
mid = Math.imul(al9, bh2);
|
|
mid = (mid + Math.imul(ah9, bl2)) | 0;
|
|
hi = Math.imul(ah9, bh2);
|
|
lo = (lo + Math.imul(al8, bl3)) | 0;
|
|
mid = (mid + Math.imul(al8, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh3)) | 0;
|
|
lo = (lo + Math.imul(al7, bl4)) | 0;
|
|
mid = (mid + Math.imul(al7, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh4)) | 0;
|
|
lo = (lo + Math.imul(al6, bl5)) | 0;
|
|
mid = (mid + Math.imul(al6, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh5)) | 0;
|
|
lo = (lo + Math.imul(al5, bl6)) | 0;
|
|
mid = (mid + Math.imul(al5, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh6)) | 0;
|
|
lo = (lo + Math.imul(al4, bl7)) | 0;
|
|
mid = (mid + Math.imul(al4, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh7)) | 0;
|
|
lo = (lo + Math.imul(al3, bl8)) | 0;
|
|
mid = (mid + Math.imul(al3, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh8)) | 0;
|
|
lo = (lo + Math.imul(al2, bl9)) | 0;
|
|
mid = (mid + Math.imul(al2, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh9)) | 0;
|
|
var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
|
|
w11 &= 0x3ffffff;
|
|
/* k = 12 */
|
|
lo = Math.imul(al9, bl3);
|
|
mid = Math.imul(al9, bh3);
|
|
mid = (mid + Math.imul(ah9, bl3)) | 0;
|
|
hi = Math.imul(ah9, bh3);
|
|
lo = (lo + Math.imul(al8, bl4)) | 0;
|
|
mid = (mid + Math.imul(al8, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh4)) | 0;
|
|
lo = (lo + Math.imul(al7, bl5)) | 0;
|
|
mid = (mid + Math.imul(al7, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh5)) | 0;
|
|
lo = (lo + Math.imul(al6, bl6)) | 0;
|
|
mid = (mid + Math.imul(al6, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh6)) | 0;
|
|
lo = (lo + Math.imul(al5, bl7)) | 0;
|
|
mid = (mid + Math.imul(al5, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh7)) | 0;
|
|
lo = (lo + Math.imul(al4, bl8)) | 0;
|
|
mid = (mid + Math.imul(al4, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh8)) | 0;
|
|
lo = (lo + Math.imul(al3, bl9)) | 0;
|
|
mid = (mid + Math.imul(al3, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh9)) | 0;
|
|
var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
|
|
w12 &= 0x3ffffff;
|
|
/* k = 13 */
|
|
lo = Math.imul(al9, bl4);
|
|
mid = Math.imul(al9, bh4);
|
|
mid = (mid + Math.imul(ah9, bl4)) | 0;
|
|
hi = Math.imul(ah9, bh4);
|
|
lo = (lo + Math.imul(al8, bl5)) | 0;
|
|
mid = (mid + Math.imul(al8, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh5)) | 0;
|
|
lo = (lo + Math.imul(al7, bl6)) | 0;
|
|
mid = (mid + Math.imul(al7, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh6)) | 0;
|
|
lo = (lo + Math.imul(al6, bl7)) | 0;
|
|
mid = (mid + Math.imul(al6, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh7)) | 0;
|
|
lo = (lo + Math.imul(al5, bl8)) | 0;
|
|
mid = (mid + Math.imul(al5, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh8)) | 0;
|
|
lo = (lo + Math.imul(al4, bl9)) | 0;
|
|
mid = (mid + Math.imul(al4, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh9)) | 0;
|
|
var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
|
|
w13 &= 0x3ffffff;
|
|
/* k = 14 */
|
|
lo = Math.imul(al9, bl5);
|
|
mid = Math.imul(al9, bh5);
|
|
mid = (mid + Math.imul(ah9, bl5)) | 0;
|
|
hi = Math.imul(ah9, bh5);
|
|
lo = (lo + Math.imul(al8, bl6)) | 0;
|
|
mid = (mid + Math.imul(al8, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh6)) | 0;
|
|
lo = (lo + Math.imul(al7, bl7)) | 0;
|
|
mid = (mid + Math.imul(al7, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh7)) | 0;
|
|
lo = (lo + Math.imul(al6, bl8)) | 0;
|
|
mid = (mid + Math.imul(al6, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh8)) | 0;
|
|
lo = (lo + Math.imul(al5, bl9)) | 0;
|
|
mid = (mid + Math.imul(al5, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh9)) | 0;
|
|
var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
|
|
w14 &= 0x3ffffff;
|
|
/* k = 15 */
|
|
lo = Math.imul(al9, bl6);
|
|
mid = Math.imul(al9, bh6);
|
|
mid = (mid + Math.imul(ah9, bl6)) | 0;
|
|
hi = Math.imul(ah9, bh6);
|
|
lo = (lo + Math.imul(al8, bl7)) | 0;
|
|
mid = (mid + Math.imul(al8, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh7)) | 0;
|
|
lo = (lo + Math.imul(al7, bl8)) | 0;
|
|
mid = (mid + Math.imul(al7, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh8)) | 0;
|
|
lo = (lo + Math.imul(al6, bl9)) | 0;
|
|
mid = (mid + Math.imul(al6, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh9)) | 0;
|
|
var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
|
|
w15 &= 0x3ffffff;
|
|
/* k = 16 */
|
|
lo = Math.imul(al9, bl7);
|
|
mid = Math.imul(al9, bh7);
|
|
mid = (mid + Math.imul(ah9, bl7)) | 0;
|
|
hi = Math.imul(ah9, bh7);
|
|
lo = (lo + Math.imul(al8, bl8)) | 0;
|
|
mid = (mid + Math.imul(al8, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh8)) | 0;
|
|
lo = (lo + Math.imul(al7, bl9)) | 0;
|
|
mid = (mid + Math.imul(al7, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh9)) | 0;
|
|
var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
|
|
w16 &= 0x3ffffff;
|
|
/* k = 17 */
|
|
lo = Math.imul(al9, bl8);
|
|
mid = Math.imul(al9, bh8);
|
|
mid = (mid + Math.imul(ah9, bl8)) | 0;
|
|
hi = Math.imul(ah9, bh8);
|
|
lo = (lo + Math.imul(al8, bl9)) | 0;
|
|
mid = (mid + Math.imul(al8, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh9)) | 0;
|
|
var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
|
|
w17 &= 0x3ffffff;
|
|
/* k = 18 */
|
|
lo = Math.imul(al9, bl9);
|
|
mid = Math.imul(al9, bh9);
|
|
mid = (mid + Math.imul(ah9, bl9)) | 0;
|
|
hi = Math.imul(ah9, bh9);
|
|
var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
|
|
w18 &= 0x3ffffff;
|
|
o[0] = w0;
|
|
o[1] = w1;
|
|
o[2] = w2;
|
|
o[3] = w3;
|
|
o[4] = w4;
|
|
o[5] = w5;
|
|
o[6] = w6;
|
|
o[7] = w7;
|
|
o[8] = w8;
|
|
o[9] = w9;
|
|
o[10] = w10;
|
|
o[11] = w11;
|
|
o[12] = w12;
|
|
o[13] = w13;
|
|
o[14] = w14;
|
|
o[15] = w15;
|
|
o[16] = w16;
|
|
o[17] = w17;
|
|
o[18] = w18;
|
|
if (c !== 0) {
|
|
o[19] = c;
|
|
out.length++;
|
|
}
|
|
return out;
|
|
};
|
|
|
|
// Polyfill comb
|
|
if (!Math.imul) {
|
|
comb10MulTo = smallMulTo;
|
|
}
|
|
|
|
function bigMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
out.length = self.length + num.length;
|
|
|
|
var carry = 0;
|
|
var hncarry = 0;
|
|
for (var k = 0; k < out.length - 1; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = hncarry;
|
|
hncarry = 0;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = k - j;
|
|
var a = self.words[i] | 0;
|
|
var b = num.words[j] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
|
|
lo = (lo + rword) | 0;
|
|
rword = lo & 0x3ffffff;
|
|
ncarry = (ncarry + (lo >>> 26)) | 0;
|
|
|
|
hncarry += ncarry >>> 26;
|
|
ncarry &= 0x3ffffff;
|
|
}
|
|
out.words[k] = rword;
|
|
carry = ncarry;
|
|
ncarry = hncarry;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
function jumboMulTo (self, num, out) {
|
|
var fftm = new FFTM();
|
|
return fftm.mulp(self, num, out);
|
|
}
|
|
|
|
BN.prototype.mulTo = function mulTo (num, out) {
|
|
var res;
|
|
var len = this.length + num.length;
|
|
if (this.length === 10 && num.length === 10) {
|
|
res = comb10MulTo(this, num, out);
|
|
} else if (len < 63) {
|
|
res = smallMulTo(this, num, out);
|
|
} else if (len < 1024) {
|
|
res = bigMulTo(this, num, out);
|
|
} else {
|
|
res = jumboMulTo(this, num, out);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Cooley-Tukey algorithm for FFT
|
|
// slightly revisited to rely on looping instead of recursion
|
|
|
|
function FFTM (x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
FFTM.prototype.makeRBT = function makeRBT (N) {
|
|
var t = new Array(N);
|
|
var l = BN.prototype._countBits(N) - 1;
|
|
for (var i = 0; i < N; i++) {
|
|
t[i] = this.revBin(i, l, N);
|
|
}
|
|
|
|
return t;
|
|
};
|
|
|
|
// Returns binary-reversed representation of `x`
|
|
FFTM.prototype.revBin = function revBin (x, l, N) {
|
|
if (x === 0 || x === N - 1) return x;
|
|
|
|
var rb = 0;
|
|
for (var i = 0; i < l; i++) {
|
|
rb |= (x & 1) << (l - i - 1);
|
|
x >>= 1;
|
|
}
|
|
|
|
return rb;
|
|
};
|
|
|
|
// Performs "tweedling" phase, therefore 'emulating'
|
|
// behaviour of the recursive algorithm
|
|
FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
|
|
for (var i = 0; i < N; i++) {
|
|
rtws[i] = rws[rbt[i]];
|
|
itws[i] = iws[rbt[i]];
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
|
|
this.permute(rbt, rws, iws, rtws, itws, N);
|
|
|
|
for (var s = 1; s < N; s <<= 1) {
|
|
var l = s << 1;
|
|
|
|
var rtwdf = Math.cos(2 * Math.PI / l);
|
|
var itwdf = Math.sin(2 * Math.PI / l);
|
|
|
|
for (var p = 0; p < N; p += l) {
|
|
var rtwdf_ = rtwdf;
|
|
var itwdf_ = itwdf;
|
|
|
|
for (var j = 0; j < s; j++) {
|
|
var re = rtws[p + j];
|
|
var ie = itws[p + j];
|
|
|
|
var ro = rtws[p + j + s];
|
|
var io = itws[p + j + s];
|
|
|
|
var rx = rtwdf_ * ro - itwdf_ * io;
|
|
|
|
io = rtwdf_ * io + itwdf_ * ro;
|
|
ro = rx;
|
|
|
|
rtws[p + j] = re + ro;
|
|
itws[p + j] = ie + io;
|
|
|
|
rtws[p + j + s] = re - ro;
|
|
itws[p + j + s] = ie - io;
|
|
|
|
/* jshint maxdepth : false */
|
|
if (j !== l) {
|
|
rx = rtwdf * rtwdf_ - itwdf * itwdf_;
|
|
|
|
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
|
|
rtwdf_ = rx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
|
|
var N = Math.max(m, n) | 1;
|
|
var odd = N & 1;
|
|
var i = 0;
|
|
for (N = N / 2 | 0; N; N = N >>> 1) {
|
|
i++;
|
|
}
|
|
|
|
return 1 << i + 1 + odd;
|
|
};
|
|
|
|
FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
|
|
if (N <= 1) return;
|
|
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var t = rws[i];
|
|
|
|
rws[i] = rws[N - i - 1];
|
|
rws[N - i - 1] = t;
|
|
|
|
t = iws[i];
|
|
|
|
iws[i] = -iws[N - i - 1];
|
|
iws[N - i - 1] = -t;
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.normalize13b = function normalize13b (ws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
|
|
Math.round(ws[2 * i] / N) +
|
|
carry;
|
|
|
|
ws[i] = w & 0x3ffffff;
|
|
|
|
if (w < 0x4000000) {
|
|
carry = 0;
|
|
} else {
|
|
carry = w / 0x4000000 | 0;
|
|
}
|
|
}
|
|
|
|
return ws;
|
|
};
|
|
|
|
FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < len; i++) {
|
|
carry = carry + (ws[i] | 0);
|
|
|
|
rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
|
|
rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
|
|
}
|
|
|
|
// Pad with zeroes
|
|
for (i = 2 * len; i < N; ++i) {
|
|
rws[i] = 0;
|
|
}
|
|
|
|
assert(carry === 0);
|
|
assert((carry & ~0x1fff) === 0);
|
|
};
|
|
|
|
FFTM.prototype.stub = function stub (N) {
|
|
var ph = new Array(N);
|
|
for (var i = 0; i < N; i++) {
|
|
ph[i] = 0;
|
|
}
|
|
|
|
return ph;
|
|
};
|
|
|
|
FFTM.prototype.mulp = function mulp (x, y, out) {
|
|
var N = 2 * this.guessLen13b(x.length, y.length);
|
|
|
|
var rbt = this.makeRBT(N);
|
|
|
|
var _ = this.stub(N);
|
|
|
|
var rws = new Array(N);
|
|
var rwst = new Array(N);
|
|
var iwst = new Array(N);
|
|
|
|
var nrws = new Array(N);
|
|
var nrwst = new Array(N);
|
|
var niwst = new Array(N);
|
|
|
|
var rmws = out.words;
|
|
rmws.length = N;
|
|
|
|
this.convert13b(x.words, x.length, rws, N);
|
|
this.convert13b(y.words, y.length, nrws, N);
|
|
|
|
this.transform(rws, _, rwst, iwst, N, rbt);
|
|
this.transform(nrws, _, nrwst, niwst, N, rbt);
|
|
|
|
for (var i = 0; i < N; i++) {
|
|
var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
|
|
iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
|
|
rwst[i] = rx;
|
|
}
|
|
|
|
this.conjugate(rwst, iwst, N);
|
|
this.transform(rwst, iwst, rmws, _, N, rbt);
|
|
this.conjugate(rmws, _, N);
|
|
this.normalize13b(rmws, N);
|
|
|
|
out.negative = x.negative ^ y.negative;
|
|
out.length = x.length + y.length;
|
|
return out.strip();
|
|
};
|
|
|
|
// Multiply `this` by `num`
|
|
BN.prototype.mul = function mul (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return this.mulTo(num, out);
|
|
};
|
|
|
|
// Multiply employing FFT
|
|
BN.prototype.mulf = function mulf (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return jumboMulTo(this, num, out);
|
|
};
|
|
|
|
// In-place Multiplication
|
|
BN.prototype.imul = function imul (num) {
|
|
return this.clone().mulTo(num, this);
|
|
};
|
|
|
|
BN.prototype.imuln = function imuln (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
|
|
// Carry
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = (this.words[i] | 0) * num;
|
|
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
|
|
carry >>= 26;
|
|
carry += (w / 0x4000000) | 0;
|
|
// NOTE: lo is 27bit maximum
|
|
carry += lo >>> 26;
|
|
this.words[i] = lo & 0x3ffffff;
|
|
}
|
|
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.muln = function muln (num) {
|
|
return this.clone().imuln(num);
|
|
};
|
|
|
|
// `this` * `this`
|
|
BN.prototype.sqr = function sqr () {
|
|
return this.mul(this);
|
|
};
|
|
|
|
// `this` * `this` in-place
|
|
BN.prototype.isqr = function isqr () {
|
|
return this.imul(this.clone());
|
|
};
|
|
|
|
// Math.pow(`this`, `num`)
|
|
BN.prototype.pow = function pow (num) {
|
|
var w = toBitArray(num);
|
|
if (w.length === 0) return new BN(1);
|
|
|
|
// Skip leading zeroes
|
|
var res = this;
|
|
for (var i = 0; i < w.length; i++, res = res.sqr()) {
|
|
if (w[i] !== 0) break;
|
|
}
|
|
|
|
if (++i < w.length) {
|
|
for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
|
|
if (w[i] === 0) continue;
|
|
|
|
res = res.mul(q);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Shift-left in-place
|
|
BN.prototype.iushln = function iushln (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
|
|
var i;
|
|
|
|
if (r !== 0) {
|
|
var carry = 0;
|
|
|
|
for (i = 0; i < this.length; i++) {
|
|
var newCarry = this.words[i] & carryMask;
|
|
var c = ((this.words[i] | 0) - newCarry) << r;
|
|
this.words[i] = c | carry;
|
|
carry = newCarry >>> (26 - r);
|
|
}
|
|
|
|
if (carry) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
}
|
|
|
|
if (s !== 0) {
|
|
for (i = this.length - 1; i >= 0; i--) {
|
|
this.words[i + s] = this.words[i];
|
|
}
|
|
|
|
for (i = 0; i < s; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
this.length += s;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishln = function ishln (bits) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushln(bits);
|
|
};
|
|
|
|
// Shift-right in-place
|
|
// NOTE: `hint` is a lowest bit before trailing zeroes
|
|
// NOTE: if `extended` is present - it will be filled with destroyed bits
|
|
BN.prototype.iushrn = function iushrn (bits, hint, extended) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var h;
|
|
if (hint) {
|
|
h = (hint - (hint % 26)) / 26;
|
|
} else {
|
|
h = 0;
|
|
}
|
|
|
|
var r = bits % 26;
|
|
var s = Math.min((bits - r) / 26, this.length);
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
var maskedWords = extended;
|
|
|
|
h -= s;
|
|
h = Math.max(0, h);
|
|
|
|
// Extended mode, copy masked part
|
|
if (maskedWords) {
|
|
for (var i = 0; i < s; i++) {
|
|
maskedWords.words[i] = this.words[i];
|
|
}
|
|
maskedWords.length = s;
|
|
}
|
|
|
|
if (s === 0) {
|
|
// No-op, we should not move anything at all
|
|
} else if (this.length > s) {
|
|
this.length -= s;
|
|
for (i = 0; i < this.length; i++) {
|
|
this.words[i] = this.words[i + s];
|
|
}
|
|
} else {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
|
|
var word = this.words[i] | 0;
|
|
this.words[i] = (carry << (26 - r)) | (word >>> r);
|
|
carry = word & mask;
|
|
}
|
|
|
|
// Push carried bits as a mask
|
|
if (maskedWords && carry !== 0) {
|
|
maskedWords.words[maskedWords.length++] = carry;
|
|
}
|
|
|
|
if (this.length === 0) {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishrn = function ishrn (bits, hint, extended) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushrn(bits, hint, extended);
|
|
};
|
|
|
|
// Shift-left
|
|
BN.prototype.shln = function shln (bits) {
|
|
return this.clone().ishln(bits);
|
|
};
|
|
|
|
BN.prototype.ushln = function ushln (bits) {
|
|
return this.clone().iushln(bits);
|
|
};
|
|
|
|
// Shift-right
|
|
BN.prototype.shrn = function shrn (bits) {
|
|
return this.clone().ishrn(bits);
|
|
};
|
|
|
|
BN.prototype.ushrn = function ushrn (bits) {
|
|
return this.clone().iushrn(bits);
|
|
};
|
|
|
|
// Test if n bit is set
|
|
BN.prototype.testn = function testn (bit) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) return false;
|
|
|
|
// Check bit and return
|
|
var w = this.words[s];
|
|
|
|
return !!(w & q);
|
|
};
|
|
|
|
// Return only lowers bits of number (in-place)
|
|
BN.prototype.imaskn = function imaskn (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
|
|
assert(this.negative === 0, 'imaskn works only with positive numbers');
|
|
|
|
if (this.length <= s) {
|
|
return this;
|
|
}
|
|
|
|
if (r !== 0) {
|
|
s++;
|
|
}
|
|
this.length = Math.min(s, this.length);
|
|
|
|
if (r !== 0) {
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
this.words[this.length - 1] &= mask;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Return only lowers bits of number
|
|
BN.prototype.maskn = function maskn (bits) {
|
|
return this.clone().imaskn(bits);
|
|
};
|
|
|
|
// Add plain number `num` to `this`
|
|
BN.prototype.iaddn = function iaddn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.isubn(-num);
|
|
|
|
// Possible sign change
|
|
if (this.negative !== 0) {
|
|
if (this.length === 1 && (this.words[0] | 0) < num) {
|
|
this.words[0] = num - (this.words[0] | 0);
|
|
this.negative = 0;
|
|
return this;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.isubn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
// Add without checks
|
|
return this._iaddn(num);
|
|
};
|
|
|
|
BN.prototype._iaddn = function _iaddn (num) {
|
|
this.words[0] += num;
|
|
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
|
|
this.words[i] -= 0x4000000;
|
|
if (i === this.length - 1) {
|
|
this.words[i + 1] = 1;
|
|
} else {
|
|
this.words[i + 1]++;
|
|
}
|
|
}
|
|
this.length = Math.max(this.length, i + 1);
|
|
|
|
return this;
|
|
};
|
|
|
|
// Subtract plain number `num` from `this`
|
|
BN.prototype.isubn = function isubn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.iaddn(-num);
|
|
|
|
if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iaddn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
this.words[0] -= num;
|
|
|
|
if (this.length === 1 && this.words[0] < 0) {
|
|
this.words[0] = -this.words[0];
|
|
this.negative = 1;
|
|
} else {
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
|
|
this.words[i] += 0x4000000;
|
|
this.words[i + 1] -= 1;
|
|
}
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.addn = function addn (num) {
|
|
return this.clone().iaddn(num);
|
|
};
|
|
|
|
BN.prototype.subn = function subn (num) {
|
|
return this.clone().isubn(num);
|
|
};
|
|
|
|
BN.prototype.iabs = function iabs () {
|
|
this.negative = 0;
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.abs = function abs () {
|
|
return this.clone().iabs();
|
|
};
|
|
|
|
BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
|
|
var len = num.length + shift;
|
|
var i;
|
|
|
|
this._expand(len);
|
|
|
|
var w;
|
|
var carry = 0;
|
|
for (i = 0; i < num.length; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
var right = (num.words[i] | 0) * mul;
|
|
w -= right & 0x3ffffff;
|
|
carry = (w >> 26) - ((right / 0x4000000) | 0);
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
for (; i < this.length - shift; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
|
|
if (carry === 0) return this.strip();
|
|
|
|
// Subtraction overflow
|
|
assert(carry === -1);
|
|
carry = 0;
|
|
for (i = 0; i < this.length; i++) {
|
|
w = -(this.words[i] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i] = w & 0x3ffffff;
|
|
}
|
|
this.negative = 1;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype._wordDiv = function _wordDiv (num, mode) {
|
|
var shift = this.length - num.length;
|
|
|
|
var a = this.clone();
|
|
var b = num;
|
|
|
|
// Normalize
|
|
var bhi = b.words[b.length - 1] | 0;
|
|
var bhiBits = this._countBits(bhi);
|
|
shift = 26 - bhiBits;
|
|
if (shift !== 0) {
|
|
b = b.ushln(shift);
|
|
a.iushln(shift);
|
|
bhi = b.words[b.length - 1] | 0;
|
|
}
|
|
|
|
// Initialize quotient
|
|
var m = a.length - b.length;
|
|
var q;
|
|
|
|
if (mode !== 'mod') {
|
|
q = new BN(null);
|
|
q.length = m + 1;
|
|
q.words = new Array(q.length);
|
|
for (var i = 0; i < q.length; i++) {
|
|
q.words[i] = 0;
|
|
}
|
|
}
|
|
|
|
var diff = a.clone()._ishlnsubmul(b, 1, m);
|
|
if (diff.negative === 0) {
|
|
a = diff;
|
|
if (q) {
|
|
q.words[m] = 1;
|
|
}
|
|
}
|
|
|
|
for (var j = m - 1; j >= 0; j--) {
|
|
var qj = (a.words[b.length + j] | 0) * 0x4000000 +
|
|
(a.words[b.length + j - 1] | 0);
|
|
|
|
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
|
|
// (0x7ffffff)
|
|
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
|
|
|
|
a._ishlnsubmul(b, qj, j);
|
|
while (a.negative !== 0) {
|
|
qj--;
|
|
a.negative = 0;
|
|
a._ishlnsubmul(b, 1, j);
|
|
if (!a.isZero()) {
|
|
a.negative ^= 1;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.words[j] = qj;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.strip();
|
|
}
|
|
a.strip();
|
|
|
|
// Denormalize
|
|
if (mode !== 'div' && shift !== 0) {
|
|
a.iushrn(shift);
|
|
}
|
|
|
|
return {
|
|
div: q || null,
|
|
mod: a
|
|
};
|
|
};
|
|
|
|
// NOTE: 1) `mode` can be set to `mod` to request mod only,
|
|
// to `div` to request div only, or be absent to
|
|
// request both div & mod
|
|
// 2) `positive` is true if unsigned mod is requested
|
|
BN.prototype.divmod = function divmod (num, mode, positive) {
|
|
assert(!num.isZero());
|
|
|
|
if (this.isZero()) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: new BN(0)
|
|
};
|
|
}
|
|
|
|
var div, mod, res;
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
res = this.neg().divmod(num, mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.iadd(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
if (this.negative === 0 && num.negative !== 0) {
|
|
res = this.divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: res.mod
|
|
};
|
|
}
|
|
|
|
if ((this.negative & num.negative) !== 0) {
|
|
res = this.neg().divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.isub(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: res.div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
// Both numbers are positive at this point
|
|
|
|
// Strip both numbers to approximate shift value
|
|
if (num.length > this.length || this.cmp(num) < 0) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: this
|
|
};
|
|
}
|
|
|
|
// Very short reduction
|
|
if (num.length === 1) {
|
|
if (mode === 'div') {
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: null
|
|
};
|
|
}
|
|
|
|
if (mode === 'mod') {
|
|
return {
|
|
div: null,
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return this._wordDiv(num, mode);
|
|
};
|
|
|
|
// Find `this` / `num`
|
|
BN.prototype.div = function div (num) {
|
|
return this.divmod(num, 'div', false).div;
|
|
};
|
|
|
|
// Find `this` % `num`
|
|
BN.prototype.mod = function mod (num) {
|
|
return this.divmod(num, 'mod', false).mod;
|
|
};
|
|
|
|
BN.prototype.umod = function umod (num) {
|
|
return this.divmod(num, 'mod', true).mod;
|
|
};
|
|
|
|
// Find Round(`this` / `num`)
|
|
BN.prototype.divRound = function divRound (num) {
|
|
var dm = this.divmod(num);
|
|
|
|
// Fast case - exact division
|
|
if (dm.mod.isZero()) return dm.div;
|
|
|
|
var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
|
|
|
|
var half = num.ushrn(1);
|
|
var r2 = num.andln(1);
|
|
var cmp = mod.cmp(half);
|
|
|
|
// Round down
|
|
if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
|
|
|
|
// Round up
|
|
return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
|
|
};
|
|
|
|
BN.prototype.modn = function modn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
var p = (1 << 26) % num;
|
|
|
|
var acc = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
acc = (p * acc + (this.words[i] | 0)) % num;
|
|
}
|
|
|
|
return acc;
|
|
};
|
|
|
|
// In-place division by number
|
|
BN.prototype.idivn = function idivn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
|
|
var carry = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var w = (this.words[i] | 0) + carry * 0x4000000;
|
|
this.words[i] = (w / num) | 0;
|
|
carry = w % num;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.divn = function divn (num) {
|
|
return this.clone().idivn(num);
|
|
};
|
|
|
|
BN.prototype.egcd = function egcd (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var x = this;
|
|
var y = p.clone();
|
|
|
|
if (x.negative !== 0) {
|
|
x = x.umod(p);
|
|
} else {
|
|
x = x.clone();
|
|
}
|
|
|
|
// A * x + B * y = x
|
|
var A = new BN(1);
|
|
var B = new BN(0);
|
|
|
|
// C * x + D * y = y
|
|
var C = new BN(0);
|
|
var D = new BN(1);
|
|
|
|
var g = 0;
|
|
|
|
while (x.isEven() && y.isEven()) {
|
|
x.iushrn(1);
|
|
y.iushrn(1);
|
|
++g;
|
|
}
|
|
|
|
var yp = y.clone();
|
|
var xp = x.clone();
|
|
|
|
while (!x.isZero()) {
|
|
for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
x.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (A.isOdd() || B.isOdd()) {
|
|
A.iadd(yp);
|
|
B.isub(xp);
|
|
}
|
|
|
|
A.iushrn(1);
|
|
B.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
y.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (C.isOdd() || D.isOdd()) {
|
|
C.iadd(yp);
|
|
D.isub(xp);
|
|
}
|
|
|
|
C.iushrn(1);
|
|
D.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (x.cmp(y) >= 0) {
|
|
x.isub(y);
|
|
A.isub(C);
|
|
B.isub(D);
|
|
} else {
|
|
y.isub(x);
|
|
C.isub(A);
|
|
D.isub(B);
|
|
}
|
|
}
|
|
|
|
return {
|
|
a: C,
|
|
b: D,
|
|
gcd: y.iushln(g)
|
|
};
|
|
};
|
|
|
|
// This is reduced incarnation of the binary EEA
|
|
// above, designated to invert members of the
|
|
// _prime_ fields F(p) at a maximal speed
|
|
BN.prototype._invmp = function _invmp (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var a = this;
|
|
var b = p.clone();
|
|
|
|
if (a.negative !== 0) {
|
|
a = a.umod(p);
|
|
} else {
|
|
a = a.clone();
|
|
}
|
|
|
|
var x1 = new BN(1);
|
|
var x2 = new BN(0);
|
|
|
|
var delta = b.clone();
|
|
|
|
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
|
|
for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
a.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (x1.isOdd()) {
|
|
x1.iadd(delta);
|
|
}
|
|
|
|
x1.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
b.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (x2.isOdd()) {
|
|
x2.iadd(delta);
|
|
}
|
|
|
|
x2.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (a.cmp(b) >= 0) {
|
|
a.isub(b);
|
|
x1.isub(x2);
|
|
} else {
|
|
b.isub(a);
|
|
x2.isub(x1);
|
|
}
|
|
}
|
|
|
|
var res;
|
|
if (a.cmpn(1) === 0) {
|
|
res = x1;
|
|
} else {
|
|
res = x2;
|
|
}
|
|
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(p);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gcd = function gcd (num) {
|
|
if (this.isZero()) return num.abs();
|
|
if (num.isZero()) return this.abs();
|
|
|
|
var a = this.clone();
|
|
var b = num.clone();
|
|
a.negative = 0;
|
|
b.negative = 0;
|
|
|
|
// Remove common factor of two
|
|
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
|
|
a.iushrn(1);
|
|
b.iushrn(1);
|
|
}
|
|
|
|
do {
|
|
while (a.isEven()) {
|
|
a.iushrn(1);
|
|
}
|
|
while (b.isEven()) {
|
|
b.iushrn(1);
|
|
}
|
|
|
|
var r = a.cmp(b);
|
|
if (r < 0) {
|
|
// Swap `a` and `b` to make `a` always bigger than `b`
|
|
var t = a;
|
|
a = b;
|
|
b = t;
|
|
} else if (r === 0 || b.cmpn(1) === 0) {
|
|
break;
|
|
}
|
|
|
|
a.isub(b);
|
|
} while (true);
|
|
|
|
return b.iushln(shift);
|
|
};
|
|
|
|
// Invert number in the field F(num)
|
|
BN.prototype.invm = function invm (num) {
|
|
return this.egcd(num).a.umod(num);
|
|
};
|
|
|
|
BN.prototype.isEven = function isEven () {
|
|
return (this.words[0] & 1) === 0;
|
|
};
|
|
|
|
BN.prototype.isOdd = function isOdd () {
|
|
return (this.words[0] & 1) === 1;
|
|
};
|
|
|
|
// And first word and num
|
|
BN.prototype.andln = function andln (num) {
|
|
return this.words[0] & num;
|
|
};
|
|
|
|
// Increment at the bit position in-line
|
|
BN.prototype.bincn = function bincn (bit) {
|
|
assert(typeof bit === 'number');
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) {
|
|
this._expand(s + 1);
|
|
this.words[s] |= q;
|
|
return this;
|
|
}
|
|
|
|
// Add bit and propagate, if needed
|
|
var carry = q;
|
|
for (var i = s; carry !== 0 && i < this.length; i++) {
|
|
var w = this.words[i] | 0;
|
|
w += carry;
|
|
carry = w >>> 26;
|
|
w &= 0x3ffffff;
|
|
this.words[i] = w;
|
|
}
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.isZero = function isZero () {
|
|
return this.length === 1 && this.words[0] === 0;
|
|
};
|
|
|
|
BN.prototype.cmpn = function cmpn (num) {
|
|
var negative = num < 0;
|
|
|
|
if (this.negative !== 0 && !negative) return -1;
|
|
if (this.negative === 0 && negative) return 1;
|
|
|
|
this.strip();
|
|
|
|
var res;
|
|
if (this.length > 1) {
|
|
res = 1;
|
|
} else {
|
|
if (negative) {
|
|
num = -num;
|
|
}
|
|
|
|
assert(num <= 0x3ffffff, 'Number is too big');
|
|
|
|
var w = this.words[0] | 0;
|
|
res = w === num ? 0 : w < num ? -1 : 1;
|
|
}
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Compare two numbers and return:
|
|
// 1 - if `this` > `num`
|
|
// 0 - if `this` == `num`
|
|
// -1 - if `this` < `num`
|
|
BN.prototype.cmp = function cmp (num) {
|
|
if (this.negative !== 0 && num.negative === 0) return -1;
|
|
if (this.negative === 0 && num.negative !== 0) return 1;
|
|
|
|
var res = this.ucmp(num);
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Unsigned comparison
|
|
BN.prototype.ucmp = function ucmp (num) {
|
|
// At this point both numbers have the same sign
|
|
if (this.length > num.length) return 1;
|
|
if (this.length < num.length) return -1;
|
|
|
|
var res = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var a = this.words[i] | 0;
|
|
var b = num.words[i] | 0;
|
|
|
|
if (a === b) continue;
|
|
if (a < b) {
|
|
res = -1;
|
|
} else if (a > b) {
|
|
res = 1;
|
|
}
|
|
break;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gtn = function gtn (num) {
|
|
return this.cmpn(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gt = function gt (num) {
|
|
return this.cmp(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gten = function gten (num) {
|
|
return this.cmpn(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.gte = function gte (num) {
|
|
return this.cmp(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.ltn = function ltn (num) {
|
|
return this.cmpn(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lt = function lt (num) {
|
|
return this.cmp(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lten = function lten (num) {
|
|
return this.cmpn(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.lte = function lte (num) {
|
|
return this.cmp(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.eqn = function eqn (num) {
|
|
return this.cmpn(num) === 0;
|
|
};
|
|
|
|
BN.prototype.eq = function eq (num) {
|
|
return this.cmp(num) === 0;
|
|
};
|
|
|
|
//
|
|
// A reduce context, could be using montgomery or something better, depending
|
|
// on the `m` itself.
|
|
//
|
|
BN.red = function red (num) {
|
|
return new Red(num);
|
|
};
|
|
|
|
BN.prototype.toRed = function toRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
assert(this.negative === 0, 'red works only with positives');
|
|
return ctx.convertTo(this)._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.fromRed = function fromRed () {
|
|
assert(this.red, 'fromRed works only with numbers in reduction context');
|
|
return this.red.convertFrom(this);
|
|
};
|
|
|
|
BN.prototype._forceRed = function _forceRed (ctx) {
|
|
this.red = ctx;
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.forceRed = function forceRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
return this._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.redAdd = function redAdd (num) {
|
|
assert(this.red, 'redAdd works only with red numbers');
|
|
return this.red.add(this, num);
|
|
};
|
|
|
|
BN.prototype.redIAdd = function redIAdd (num) {
|
|
assert(this.red, 'redIAdd works only with red numbers');
|
|
return this.red.iadd(this, num);
|
|
};
|
|
|
|
BN.prototype.redSub = function redSub (num) {
|
|
assert(this.red, 'redSub works only with red numbers');
|
|
return this.red.sub(this, num);
|
|
};
|
|
|
|
BN.prototype.redISub = function redISub (num) {
|
|
assert(this.red, 'redISub works only with red numbers');
|
|
return this.red.isub(this, num);
|
|
};
|
|
|
|
BN.prototype.redShl = function redShl (num) {
|
|
assert(this.red, 'redShl works only with red numbers');
|
|
return this.red.shl(this, num);
|
|
};
|
|
|
|
BN.prototype.redMul = function redMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.mul(this, num);
|
|
};
|
|
|
|
BN.prototype.redIMul = function redIMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.imul(this, num);
|
|
};
|
|
|
|
BN.prototype.redSqr = function redSqr () {
|
|
assert(this.red, 'redSqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqr(this);
|
|
};
|
|
|
|
BN.prototype.redISqr = function redISqr () {
|
|
assert(this.red, 'redISqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.isqr(this);
|
|
};
|
|
|
|
// Square root over p
|
|
BN.prototype.redSqrt = function redSqrt () {
|
|
assert(this.red, 'redSqrt works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqrt(this);
|
|
};
|
|
|
|
BN.prototype.redInvm = function redInvm () {
|
|
assert(this.red, 'redInvm works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.invm(this);
|
|
};
|
|
|
|
// Return negative clone of `this` % `red modulo`
|
|
BN.prototype.redNeg = function redNeg () {
|
|
assert(this.red, 'redNeg works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.neg(this);
|
|
};
|
|
|
|
BN.prototype.redPow = function redPow (num) {
|
|
assert(this.red && !num.red, 'redPow(normalNum)');
|
|
this.red._verify1(this);
|
|
return this.red.pow(this, num);
|
|
};
|
|
|
|
// Prime numbers with efficient reduction
|
|
var primes = {
|
|
k256: null,
|
|
p224: null,
|
|
p192: null,
|
|
p25519: null
|
|
};
|
|
|
|
// Pseudo-Mersenne prime
|
|
function MPrime (name, p) {
|
|
// P = 2 ^ N - K
|
|
this.name = name;
|
|
this.p = new BN(p, 16);
|
|
this.n = this.p.bitLength();
|
|
this.k = new BN(1).iushln(this.n).isub(this.p);
|
|
|
|
this.tmp = this._tmp();
|
|
}
|
|
|
|
MPrime.prototype._tmp = function _tmp () {
|
|
var tmp = new BN(null);
|
|
tmp.words = new Array(Math.ceil(this.n / 13));
|
|
return tmp;
|
|
};
|
|
|
|
MPrime.prototype.ireduce = function ireduce (num) {
|
|
// Assumes that `num` is less than `P^2`
|
|
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
|
|
var r = num;
|
|
var rlen;
|
|
|
|
do {
|
|
this.split(r, this.tmp);
|
|
r = this.imulK(r);
|
|
r = r.iadd(this.tmp);
|
|
rlen = r.bitLength();
|
|
} while (rlen > this.n);
|
|
|
|
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
|
|
if (cmp === 0) {
|
|
r.words[0] = 0;
|
|
r.length = 1;
|
|
} else if (cmp > 0) {
|
|
r.isub(this.p);
|
|
} else {
|
|
if (r.strip !== undefined) {
|
|
// r is BN v4 instance
|
|
r.strip();
|
|
} else {
|
|
// r is BN v5 instance
|
|
r._strip();
|
|
}
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
MPrime.prototype.split = function split (input, out) {
|
|
input.iushrn(this.n, 0, out);
|
|
};
|
|
|
|
MPrime.prototype.imulK = function imulK (num) {
|
|
return num.imul(this.k);
|
|
};
|
|
|
|
function K256 () {
|
|
MPrime.call(
|
|
this,
|
|
'k256',
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
|
|
}
|
|
inherits(K256, MPrime);
|
|
|
|
K256.prototype.split = function split (input, output) {
|
|
// 256 = 9 * 26 + 22
|
|
var mask = 0x3fffff;
|
|
|
|
var outLen = Math.min(input.length, 9);
|
|
for (var i = 0; i < outLen; i++) {
|
|
output.words[i] = input.words[i];
|
|
}
|
|
output.length = outLen;
|
|
|
|
if (input.length <= 9) {
|
|
input.words[0] = 0;
|
|
input.length = 1;
|
|
return;
|
|
}
|
|
|
|
// Shift by 9 limbs
|
|
var prev = input.words[9];
|
|
output.words[output.length++] = prev & mask;
|
|
|
|
for (i = 10; i < input.length; i++) {
|
|
var next = input.words[i] | 0;
|
|
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
|
|
prev = next;
|
|
}
|
|
prev >>>= 22;
|
|
input.words[i - 10] = prev;
|
|
if (prev === 0 && input.length > 10) {
|
|
input.length -= 10;
|
|
} else {
|
|
input.length -= 9;
|
|
}
|
|
};
|
|
|
|
K256.prototype.imulK = function imulK (num) {
|
|
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
|
|
num.words[num.length] = 0;
|
|
num.words[num.length + 1] = 0;
|
|
num.length += 2;
|
|
|
|
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
|
|
var lo = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var w = num.words[i] | 0;
|
|
lo += w * 0x3d1;
|
|
num.words[i] = lo & 0x3ffffff;
|
|
lo = w * 0x40 + ((lo / 0x4000000) | 0);
|
|
}
|
|
|
|
// Fast length reduction
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
}
|
|
}
|
|
return num;
|
|
};
|
|
|
|
function P224 () {
|
|
MPrime.call(
|
|
this,
|
|
'p224',
|
|
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
|
|
}
|
|
inherits(P224, MPrime);
|
|
|
|
function P192 () {
|
|
MPrime.call(
|
|
this,
|
|
'p192',
|
|
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
|
|
}
|
|
inherits(P192, MPrime);
|
|
|
|
function P25519 () {
|
|
// 2 ^ 255 - 19
|
|
MPrime.call(
|
|
this,
|
|
'25519',
|
|
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
|
|
}
|
|
inherits(P25519, MPrime);
|
|
|
|
P25519.prototype.imulK = function imulK (num) {
|
|
// K = 0x13
|
|
var carry = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var hi = (num.words[i] | 0) * 0x13 + carry;
|
|
var lo = hi & 0x3ffffff;
|
|
hi >>>= 26;
|
|
|
|
num.words[i] = lo;
|
|
carry = hi;
|
|
}
|
|
if (carry !== 0) {
|
|
num.words[num.length++] = carry;
|
|
}
|
|
return num;
|
|
};
|
|
|
|
// Exported mostly for testing purposes, use plain name instead
|
|
BN._prime = function prime (name) {
|
|
// Cached version of prime
|
|
if (primes[name]) return primes[name];
|
|
|
|
var prime;
|
|
if (name === 'k256') {
|
|
prime = new K256();
|
|
} else if (name === 'p224') {
|
|
prime = new P224();
|
|
} else if (name === 'p192') {
|
|
prime = new P192();
|
|
} else if (name === 'p25519') {
|
|
prime = new P25519();
|
|
} else {
|
|
throw new Error('Unknown prime ' + name);
|
|
}
|
|
primes[name] = prime;
|
|
|
|
return prime;
|
|
};
|
|
|
|
//
|
|
// Base reduction engine
|
|
//
|
|
function Red (m) {
|
|
if (typeof m === 'string') {
|
|
var prime = BN._prime(m);
|
|
this.m = prime.p;
|
|
this.prime = prime;
|
|
} else {
|
|
assert(m.gtn(1), 'modulus must be greater than 1');
|
|
this.m = m;
|
|
this.prime = null;
|
|
}
|
|
}
|
|
|
|
Red.prototype._verify1 = function _verify1 (a) {
|
|
assert(a.negative === 0, 'red works only with positives');
|
|
assert(a.red, 'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype._verify2 = function _verify2 (a, b) {
|
|
assert((a.negative | b.negative) === 0, 'red works only with positives');
|
|
assert(a.red && a.red === b.red,
|
|
'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype.imod = function imod (a) {
|
|
if (this.prime) return this.prime.ireduce(a)._forceRed(this);
|
|
return a.umod(this.m)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.neg = function neg (a) {
|
|
if (a.isZero()) {
|
|
return a.clone();
|
|
}
|
|
|
|
return this.m.sub(a)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.add = function add (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.add(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.iadd = function iadd (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.iadd(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.sub = function sub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.sub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.isub = function isub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.isub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.shl = function shl (a, num) {
|
|
this._verify1(a);
|
|
return this.imod(a.ushln(num));
|
|
};
|
|
|
|
Red.prototype.imul = function imul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.imul(b));
|
|
};
|
|
|
|
Red.prototype.mul = function mul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.mul(b));
|
|
};
|
|
|
|
Red.prototype.isqr = function isqr (a) {
|
|
return this.imul(a, a.clone());
|
|
};
|
|
|
|
Red.prototype.sqr = function sqr (a) {
|
|
return this.mul(a, a);
|
|
};
|
|
|
|
Red.prototype.sqrt = function sqrt (a) {
|
|
if (a.isZero()) return a.clone();
|
|
|
|
var mod3 = this.m.andln(3);
|
|
assert(mod3 % 2 === 1);
|
|
|
|
// Fast case
|
|
if (mod3 === 3) {
|
|
var pow = this.m.add(new BN(1)).iushrn(2);
|
|
return this.pow(a, pow);
|
|
}
|
|
|
|
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
|
|
//
|
|
// Find Q and S, that Q * 2 ^ S = (P - 1)
|
|
var q = this.m.subn(1);
|
|
var s = 0;
|
|
while (!q.isZero() && q.andln(1) === 0) {
|
|
s++;
|
|
q.iushrn(1);
|
|
}
|
|
assert(!q.isZero());
|
|
|
|
var one = new BN(1).toRed(this);
|
|
var nOne = one.redNeg();
|
|
|
|
// Find quadratic non-residue
|
|
// NOTE: Max is such because of generalized Riemann hypothesis.
|
|
var lpow = this.m.subn(1).iushrn(1);
|
|
var z = this.m.bitLength();
|
|
z = new BN(2 * z * z).toRed(this);
|
|
|
|
while (this.pow(z, lpow).cmp(nOne) !== 0) {
|
|
z.redIAdd(nOne);
|
|
}
|
|
|
|
var c = this.pow(z, q);
|
|
var r = this.pow(a, q.addn(1).iushrn(1));
|
|
var t = this.pow(a, q);
|
|
var m = s;
|
|
while (t.cmp(one) !== 0) {
|
|
var tmp = t;
|
|
for (var i = 0; tmp.cmp(one) !== 0; i++) {
|
|
tmp = tmp.redSqr();
|
|
}
|
|
assert(i < m);
|
|
var b = this.pow(c, new BN(1).iushln(m - i - 1));
|
|
|
|
r = r.redMul(b);
|
|
c = b.redSqr();
|
|
t = t.redMul(c);
|
|
m = i;
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
Red.prototype.invm = function invm (a) {
|
|
var inv = a._invmp(this.m);
|
|
if (inv.negative !== 0) {
|
|
inv.negative = 0;
|
|
return this.imod(inv).redNeg();
|
|
} else {
|
|
return this.imod(inv);
|
|
}
|
|
};
|
|
|
|
Red.prototype.pow = function pow (a, num) {
|
|
if (num.isZero()) return new BN(1).toRed(this);
|
|
if (num.cmpn(1) === 0) return a.clone();
|
|
|
|
var windowSize = 4;
|
|
var wnd = new Array(1 << windowSize);
|
|
wnd[0] = new BN(1).toRed(this);
|
|
wnd[1] = a;
|
|
for (var i = 2; i < wnd.length; i++) {
|
|
wnd[i] = this.mul(wnd[i - 1], a);
|
|
}
|
|
|
|
var res = wnd[0];
|
|
var current = 0;
|
|
var currentLen = 0;
|
|
var start = num.bitLength() % 26;
|
|
if (start === 0) {
|
|
start = 26;
|
|
}
|
|
|
|
for (i = num.length - 1; i >= 0; i--) {
|
|
var word = num.words[i];
|
|
for (var j = start - 1; j >= 0; j--) {
|
|
var bit = (word >> j) & 1;
|
|
if (res !== wnd[0]) {
|
|
res = this.sqr(res);
|
|
}
|
|
|
|
if (bit === 0 && current === 0) {
|
|
currentLen = 0;
|
|
continue;
|
|
}
|
|
|
|
current <<= 1;
|
|
current |= bit;
|
|
currentLen++;
|
|
if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
|
|
|
|
res = this.mul(res, wnd[current]);
|
|
currentLen = 0;
|
|
current = 0;
|
|
}
|
|
start = 26;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.convertTo = function convertTo (num) {
|
|
var r = num.umod(this.m);
|
|
|
|
return r === num ? r.clone() : r;
|
|
};
|
|
|
|
Red.prototype.convertFrom = function convertFrom (num) {
|
|
var res = num.clone();
|
|
res.red = null;
|
|
return res;
|
|
};
|
|
|
|
//
|
|
// Montgomery method engine
|
|
//
|
|
|
|
BN.mont = function mont (num) {
|
|
return new Mont(num);
|
|
};
|
|
|
|
function Mont (m) {
|
|
Red.call(this, m);
|
|
|
|
this.shift = this.m.bitLength();
|
|
if (this.shift % 26 !== 0) {
|
|
this.shift += 26 - (this.shift % 26);
|
|
}
|
|
|
|
this.r = new BN(1).iushln(this.shift);
|
|
this.r2 = this.imod(this.r.sqr());
|
|
this.rinv = this.r._invmp(this.m);
|
|
|
|
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
|
|
this.minv = this.minv.umod(this.r);
|
|
this.minv = this.r.sub(this.minv);
|
|
}
|
|
inherits(Mont, Red);
|
|
|
|
Mont.prototype.convertTo = function convertTo (num) {
|
|
return this.imod(num.ushln(this.shift));
|
|
};
|
|
|
|
Mont.prototype.convertFrom = function convertFrom (num) {
|
|
var r = this.imod(num.mul(this.rinv));
|
|
r.red = null;
|
|
return r;
|
|
};
|
|
|
|
Mont.prototype.imul = function imul (a, b) {
|
|
if (a.isZero() || b.isZero()) {
|
|
a.words[0] = 0;
|
|
a.length = 1;
|
|
return a;
|
|
}
|
|
|
|
var t = a.imul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.mul = function mul (a, b) {
|
|
if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
|
|
|
|
var t = a.mul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.invm = function invm (a) {
|
|
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
|
|
var res = this.imod(a._invmp(this.m).mul(this.r2));
|
|
return res._forceRed(this);
|
|
};
|
|
})( false || module, this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mime/Mime.js":
|
|
/*!***********************************!*\
|
|
!*** ./node_modules/mime/Mime.js ***!
|
|
\***********************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
/**
|
|
* @param typeMap [Object] Map of MIME type -> Array[extensions]
|
|
* @param ...
|
|
*/
|
|
function Mime() {
|
|
this._types = Object.create(null);
|
|
this._extensions = Object.create(null);
|
|
|
|
for (let i = 0; i < arguments.length; i++) {
|
|
this.define(arguments[i]);
|
|
}
|
|
|
|
this.define = this.define.bind(this);
|
|
this.getType = this.getType.bind(this);
|
|
this.getExtension = this.getExtension.bind(this);
|
|
}
|
|
|
|
/**
|
|
* Define mimetype -> extension mappings. Each key is a mime-type that maps
|
|
* to an array of extensions associated with the type. The first extension is
|
|
* used as the default extension for the type.
|
|
*
|
|
* e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']});
|
|
*
|
|
* If a type declares an extension that has already been defined, an error will
|
|
* be thrown. To suppress this error and force the extension to be associated
|
|
* with the new type, pass `force`=true. Alternatively, you may prefix the
|
|
* extension with "*" to map the type to extension, without mapping the
|
|
* extension to the type.
|
|
*
|
|
* e.g. mime.define({'audio/wav', ['wav']}, {'audio/x-wav', ['*wav']});
|
|
*
|
|
*
|
|
* @param map (Object) type definitions
|
|
* @param force (Boolean) if true, force overriding of existing definitions
|
|
*/
|
|
Mime.prototype.define = function(typeMap, force) {
|
|
for (let type in typeMap) {
|
|
let extensions = typeMap[type].map(function(t) {
|
|
return t.toLowerCase();
|
|
});
|
|
type = type.toLowerCase();
|
|
|
|
for (let i = 0; i < extensions.length; i++) {
|
|
const ext = extensions[i];
|
|
|
|
// '*' prefix = not the preferred type for this extension. So fixup the
|
|
// extension, and skip it.
|
|
if (ext[0] === '*') {
|
|
continue;
|
|
}
|
|
|
|
if (!force && (ext in this._types)) {
|
|
throw new Error(
|
|
'Attempt to change mapping for "' + ext +
|
|
'" extension from "' + this._types[ext] + '" to "' + type +
|
|
'". Pass `force=true` to allow this, otherwise remove "' + ext +
|
|
'" from the list of extensions for "' + type + '".'
|
|
);
|
|
}
|
|
|
|
this._types[ext] = type;
|
|
}
|
|
|
|
// Use first extension as default
|
|
if (force || !this._extensions[type]) {
|
|
const ext = extensions[0];
|
|
this._extensions[type] = (ext[0] !== '*') ? ext : ext.substr(1);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Lookup a mime type based on extension
|
|
*/
|
|
Mime.prototype.getType = function(path) {
|
|
path = String(path);
|
|
let last = path.replace(/^.*[/\\]/, '').toLowerCase();
|
|
let ext = last.replace(/^.*\./, '').toLowerCase();
|
|
|
|
let hasPath = last.length < path.length;
|
|
let hasDot = ext.length < last.length - 1;
|
|
|
|
return (hasDot || !hasPath) && this._types[ext] || null;
|
|
};
|
|
|
|
/**
|
|
* Return file extension associated with a mime type
|
|
*/
|
|
Mime.prototype.getExtension = function(type) {
|
|
type = /^\s*([^;\s]*)/.test(type) && RegExp.$1;
|
|
return type && this._extensions[type.toLowerCase()] || null;
|
|
};
|
|
|
|
module.exports = Mime;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mime/index.js":
|
|
/*!************************************!*\
|
|
!*** ./node_modules/mime/index.js ***!
|
|
\************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
let Mime = __webpack_require__(/*! ./Mime */ "./node_modules/mime/Mime.js");
|
|
module.exports = new Mime(__webpack_require__(/*! ./types/standard */ "./node_modules/mime/types/standard.js"), __webpack_require__(/*! ./types/other */ "./node_modules/mime/types/other.js"));
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mime/types/other.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/mime/types/other.js ***!
|
|
\******************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = {"application/prs.cww":["cww"],"application/vnd.1000minds.decision-model+xml":["1km"],"application/vnd.3gpp.pic-bw-large":["plb"],"application/vnd.3gpp.pic-bw-small":["psb"],"application/vnd.3gpp.pic-bw-var":["pvb"],"application/vnd.3gpp2.tcap":["tcap"],"application/vnd.3m.post-it-notes":["pwn"],"application/vnd.accpac.simply.aso":["aso"],"application/vnd.accpac.simply.imp":["imp"],"application/vnd.acucobol":["acu"],"application/vnd.acucorp":["atc","acutc"],"application/vnd.adobe.air-application-installer-package+zip":["air"],"application/vnd.adobe.formscentral.fcdt":["fcdt"],"application/vnd.adobe.fxp":["fxp","fxpl"],"application/vnd.adobe.xdp+xml":["xdp"],"application/vnd.adobe.xfdf":["xfdf"],"application/vnd.ahead.space":["ahead"],"application/vnd.airzip.filesecure.azf":["azf"],"application/vnd.airzip.filesecure.azs":["azs"],"application/vnd.amazon.ebook":["azw"],"application/vnd.americandynamics.acc":["acc"],"application/vnd.amiga.ami":["ami"],"application/vnd.android.package-archive":["apk"],"application/vnd.anser-web-certificate-issue-initiation":["cii"],"application/vnd.anser-web-funds-transfer-initiation":["fti"],"application/vnd.antix.game-component":["atx"],"application/vnd.apple.installer+xml":["mpkg"],"application/vnd.apple.keynote":["key"],"application/vnd.apple.mpegurl":["m3u8"],"application/vnd.apple.numbers":["numbers"],"application/vnd.apple.pages":["pages"],"application/vnd.apple.pkpass":["pkpass"],"application/vnd.aristanetworks.swi":["swi"],"application/vnd.astraea-software.iota":["iota"],"application/vnd.audiograph":["aep"],"application/vnd.balsamiq.bmml+xml":["bmml"],"application/vnd.blueice.multipass":["mpm"],"application/vnd.bmi":["bmi"],"application/vnd.businessobjects":["rep"],"application/vnd.chemdraw+xml":["cdxml"],"application/vnd.chipnuts.karaoke-mmd":["mmd"],"application/vnd.cinderella":["cdy"],"application/vnd.citationstyles.style+xml":["csl"],"application/vnd.claymore":["cla"],"application/vnd.cloanto.rp9":["rp9"],"application/vnd.clonk.c4group":["c4g","c4d","c4f","c4p","c4u"],"application/vnd.cluetrust.cartomobile-config":["c11amc"],"application/vnd.cluetrust.cartomobile-config-pkg":["c11amz"],"application/vnd.commonspace":["csp"],"application/vnd.contact.cmsg":["cdbcmsg"],"application/vnd.cosmocaller":["cmc"],"application/vnd.crick.clicker":["clkx"],"application/vnd.crick.clicker.keyboard":["clkk"],"application/vnd.crick.clicker.palette":["clkp"],"application/vnd.crick.clicker.template":["clkt"],"application/vnd.crick.clicker.wordbank":["clkw"],"application/vnd.criticaltools.wbs+xml":["wbs"],"application/vnd.ctc-posml":["pml"],"application/vnd.cups-ppd":["ppd"],"application/vnd.curl.car":["car"],"application/vnd.curl.pcurl":["pcurl"],"application/vnd.dart":["dart"],"application/vnd.data-vision.rdz":["rdz"],"application/vnd.dbf":["dbf"],"application/vnd.dece.data":["uvf","uvvf","uvd","uvvd"],"application/vnd.dece.ttml+xml":["uvt","uvvt"],"application/vnd.dece.unspecified":["uvx","uvvx"],"application/vnd.dece.zip":["uvz","uvvz"],"application/vnd.denovo.fcselayout-link":["fe_launch"],"application/vnd.dna":["dna"],"application/vnd.dolby.mlp":["mlp"],"application/vnd.dpgraph":["dpg"],"application/vnd.dreamfactory":["dfac"],"application/vnd.ds-keypoint":["kpxx"],"application/vnd.dvb.ait":["ait"],"application/vnd.dvb.service":["svc"],"application/vnd.dynageo":["geo"],"application/vnd.ecowin.chart":["mag"],"application/vnd.enliven":["nml"],"application/vnd.epson.esf":["esf"],"application/vnd.epson.msf":["msf"],"application/vnd.epson.quickanime":["qam"],"application/vnd.epson.salt":["slt"],"application/vnd.epson.ssf":["ssf"],"application/vnd.eszigno3+xml":["es3","et3"],"application/vnd.ezpix-album":["ez2"],"application/vnd.ezpix-package":["ez3"],"application/vnd.fdf":["fdf"],"application/vnd.fdsn.mseed":["mseed"],"application/vnd.fdsn.seed":["seed","dataless"],"application/vnd.flographit":["gph"],"application/vnd.fluxtime.clip":["ftc"],"application/vnd.framemaker":["fm","frame","maker","book"],"application/vnd.frogans.fnc":["fnc"],"application/vnd.frogans.ltf":["ltf"],"application/vnd.fsc.weblaunch":["fsc"],"application/vnd.fujitsu.oasys":["oas"],"application/vnd.fujitsu.oasys2":["oa2"],"application/vnd.fujitsu.oasys3":["oa3"],"application/vnd.fujitsu.oasysgp":["fg5"],"application/vnd.fujitsu.oasysprs":["bh2"],"application/vnd.fujixerox.ddd":["ddd"],"application/vnd.fujixerox.docuworks":["xdw"],"application/vnd.fujixerox.docuworks.binder":["xbd"],"application/vnd.fuzzysheet":["fzs"],"application/vnd.genomatix.tuxedo":["txd"],"application/vnd.geogebra.file":["ggb"],"application/vnd.geogebra.tool":["ggt"],"application/vnd.geometry-explorer":["gex","gre"],"application/vnd.geonext":["gxt"],"application/vnd.geoplan":["g2w"],"application/vnd.geospace":["g3w"],"application/vnd.gmx":["gmx"],"application/vnd.google-apps.document":["gdoc"],"application/vnd.google-apps.presentation":["gslides"],"application/vnd.google-apps.spreadsheet":["gsheet"],"application/vnd.google-earth.kml+xml":["kml"],"application/vnd.google-earth.kmz":["kmz"],"application/vnd.grafeq":["gqf","gqs"],"application/vnd.groove-account":["gac"],"application/vnd.groove-help":["ghf"],"application/vnd.groove-identity-message":["gim"],"application/vnd.groove-injector":["grv"],"application/vnd.groove-tool-message":["gtm"],"application/vnd.groove-tool-template":["tpl"],"application/vnd.groove-vcard":["vcg"],"application/vnd.hal+xml":["hal"],"application/vnd.handheld-entertainment+xml":["zmm"],"application/vnd.hbci":["hbci"],"application/vnd.hhe.lesson-player":["les"],"application/vnd.hp-hpgl":["hpgl"],"application/vnd.hp-hpid":["hpid"],"application/vnd.hp-hps":["hps"],"application/vnd.hp-jlyt":["jlt"],"application/vnd.hp-pcl":["pcl"],"application/vnd.hp-pclxl":["pclxl"],"application/vnd.hydrostatix.sof-data":["sfd-hdstx"],"application/vnd.ibm.minipay":["mpy"],"application/vnd.ibm.modcap":["afp","listafp","list3820"],"application/vnd.ibm.rights-management":["irm"],"application/vnd.ibm.secure-container":["sc"],"application/vnd.iccprofile":["icc","icm"],"application/vnd.igloader":["igl"],"application/vnd.immervision-ivp":["ivp"],"application/vnd.immervision-ivu":["ivu"],"application/vnd.insors.igm":["igm"],"application/vnd.intercon.formnet":["xpw","xpx"],"application/vnd.intergeo":["i2g"],"application/vnd.intu.qbo":["qbo"],"application/vnd.intu.qfx":["qfx"],"application/vnd.ipunplugged.rcprofile":["rcprofile"],"application/vnd.irepository.package+xml":["irp"],"application/vnd.is-xpr":["xpr"],"application/vnd.isac.fcs":["fcs"],"application/vnd.jam":["jam"],"application/vnd.jcp.javame.midlet-rms":["rms"],"application/vnd.jisp":["jisp"],"application/vnd.joost.joda-archive":["joda"],"application/vnd.kahootz":["ktz","ktr"],"application/vnd.kde.karbon":["karbon"],"application/vnd.kde.kchart":["chrt"],"application/vnd.kde.kformula":["kfo"],"application/vnd.kde.kivio":["flw"],"application/vnd.kde.kontour":["kon"],"application/vnd.kde.kpresenter":["kpr","kpt"],"application/vnd.kde.kspread":["ksp"],"application/vnd.kde.kword":["kwd","kwt"],"application/vnd.kenameaapp":["htke"],"application/vnd.kidspiration":["kia"],"application/vnd.kinar":["kne","knp"],"application/vnd.koan":["skp","skd","skt","skm"],"application/vnd.kodak-descriptor":["sse"],"application/vnd.las.las+xml":["lasxml"],"application/vnd.llamagraphics.life-balance.desktop":["lbd"],"application/vnd.llamagraphics.life-balance.exchange+xml":["lbe"],"application/vnd.lotus-1-2-3":["123"],"application/vnd.lotus-approach":["apr"],"application/vnd.lotus-freelance":["pre"],"application/vnd.lotus-notes":["nsf"],"application/vnd.lotus-organizer":["org"],"application/vnd.lotus-screencam":["scm"],"application/vnd.lotus-wordpro":["lwp"],"application/vnd.macports.portpkg":["portpkg"],"application/vnd.mcd":["mcd"],"application/vnd.medcalcdata":["mc1"],"application/vnd.mediastation.cdkey":["cdkey"],"application/vnd.mfer":["mwf"],"application/vnd.mfmp":["mfm"],"application/vnd.micrografx.flo":["flo"],"application/vnd.micrografx.igx":["igx"],"application/vnd.mif":["mif"],"application/vnd.mobius.daf":["daf"],"application/vnd.mobius.dis":["dis"],"application/vnd.mobius.mbk":["mbk"],"application/vnd.mobius.mqy":["mqy"],"application/vnd.mobius.msl":["msl"],"application/vnd.mobius.plc":["plc"],"application/vnd.mobius.txf":["txf"],"application/vnd.mophun.application":["mpn"],"application/vnd.mophun.certificate":["mpc"],"application/vnd.mozilla.xul+xml":["xul"],"application/vnd.ms-artgalry":["cil"],"application/vnd.ms-cab-compressed":["cab"],"application/vnd.ms-excel":["xls","xlm","xla","xlc","xlt","xlw"],"application/vnd.ms-excel.addin.macroenabled.12":["xlam"],"application/vnd.ms-excel.sheet.binary.macroenabled.12":["xlsb"],"application/vnd.ms-excel.sheet.macroenabled.12":["xlsm"],"application/vnd.ms-excel.template.macroenabled.12":["xltm"],"application/vnd.ms-fontobject":["eot"],"application/vnd.ms-htmlhelp":["chm"],"application/vnd.ms-ims":["ims"],"application/vnd.ms-lrm":["lrm"],"application/vnd.ms-officetheme":["thmx"],"application/vnd.ms-outlook":["msg"],"application/vnd.ms-pki.seccat":["cat"],"application/vnd.ms-pki.stl":["*stl"],"application/vnd.ms-powerpoint":["ppt","pps","pot"],"application/vnd.ms-powerpoint.addin.macroenabled.12":["ppam"],"application/vnd.ms-powerpoint.presentation.macroenabled.12":["pptm"],"application/vnd.ms-powerpoint.slide.macroenabled.12":["sldm"],"application/vnd.ms-powerpoint.slideshow.macroenabled.12":["ppsm"],"application/vnd.ms-powerpoint.template.macroenabled.12":["potm"],"application/vnd.ms-project":["mpp","mpt"],"application/vnd.ms-word.document.macroenabled.12":["docm"],"application/vnd.ms-word.template.macroenabled.12":["dotm"],"application/vnd.ms-works":["wps","wks","wcm","wdb"],"application/vnd.ms-wpl":["wpl"],"application/vnd.ms-xpsdocument":["xps"],"application/vnd.mseq":["mseq"],"application/vnd.musician":["mus"],"application/vnd.muvee.style":["msty"],"application/vnd.mynfc":["taglet"],"application/vnd.neurolanguage.nlu":["nlu"],"application/vnd.nitf":["ntf","nitf"],"application/vnd.noblenet-directory":["nnd"],"application/vnd.noblenet-sealer":["nns"],"application/vnd.noblenet-web":["nnw"],"application/vnd.nokia.n-gage.ac+xml":["*ac"],"application/vnd.nokia.n-gage.data":["ngdat"],"application/vnd.nokia.n-gage.symbian.install":["n-gage"],"application/vnd.nokia.radio-preset":["rpst"],"application/vnd.nokia.radio-presets":["rpss"],"application/vnd.novadigm.edm":["edm"],"application/vnd.novadigm.edx":["edx"],"application/vnd.novadigm.ext":["ext"],"application/vnd.oasis.opendocument.chart":["odc"],"application/vnd.oasis.opendocument.chart-template":["otc"],"application/vnd.oasis.opendocument.database":["odb"],"application/vnd.oasis.opendocument.formula":["odf"],"application/vnd.oasis.opendocument.formula-template":["odft"],"application/vnd.oasis.opendocument.graphics":["odg"],"application/vnd.oasis.opendocument.graphics-template":["otg"],"application/vnd.oasis.opendocument.image":["odi"],"application/vnd.oasis.opendocument.image-template":["oti"],"application/vnd.oasis.opendocument.presentation":["odp"],"application/vnd.oasis.opendocument.presentation-template":["otp"],"application/vnd.oasis.opendocument.spreadsheet":["ods"],"application/vnd.oasis.opendocument.spreadsheet-template":["ots"],"application/vnd.oasis.opendocument.text":["odt"],"application/vnd.oasis.opendocument.text-master":["odm"],"application/vnd.oasis.opendocument.text-template":["ott"],"application/vnd.oasis.opendocument.text-web":["oth"],"application/vnd.olpc-sugar":["xo"],"application/vnd.oma.dd2+xml":["dd2"],"application/vnd.openblox.game+xml":["obgx"],"application/vnd.openofficeorg.extension":["oxt"],"application/vnd.openstreetmap.data+xml":["osm"],"application/vnd.openxmlformats-officedocument.presentationml.presentation":["pptx"],"application/vnd.openxmlformats-officedocument.presentationml.slide":["sldx"],"application/vnd.openxmlformats-officedocument.presentationml.slideshow":["ppsx"],"application/vnd.openxmlformats-officedocument.presentationml.template":["potx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":["xlsx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.template":["xltx"],"application/vnd.openxmlformats-officedocument.wordprocessingml.document":["docx"],"application/vnd.openxmlformats-officedocument.wordprocessingml.template":["dotx"],"application/vnd.osgeo.mapguide.package":["mgp"],"application/vnd.osgi.dp":["dp"],"application/vnd.osgi.subsystem":["esa"],"application/vnd.palm":["pdb","pqa","oprc"],"application/vnd.pawaafile":["paw"],"application/vnd.pg.format":["str"],"application/vnd.pg.osasli":["ei6"],"application/vnd.picsel":["efif"],"application/vnd.pmi.widget":["wg"],"application/vnd.pocketlearn":["plf"],"application/vnd.powerbuilder6":["pbd"],"application/vnd.previewsystems.box":["box"],"application/vnd.proteus.magazine":["mgz"],"application/vnd.publishare-delta-tree":["qps"],"application/vnd.pvi.ptid1":["ptid"],"application/vnd.quark.quarkxpress":["qxd","qxt","qwd","qwt","qxl","qxb"],"application/vnd.rar":["rar"],"application/vnd.realvnc.bed":["bed"],"application/vnd.recordare.musicxml":["mxl"],"application/vnd.recordare.musicxml+xml":["musicxml"],"application/vnd.rig.cryptonote":["cryptonote"],"application/vnd.rim.cod":["cod"],"application/vnd.rn-realmedia":["rm"],"application/vnd.rn-realmedia-vbr":["rmvb"],"application/vnd.route66.link66+xml":["link66"],"application/vnd.sailingtracker.track":["st"],"application/vnd.seemail":["see"],"application/vnd.sema":["sema"],"application/vnd.semd":["semd"],"application/vnd.semf":["semf"],"application/vnd.shana.informed.formdata":["ifm"],"application/vnd.shana.informed.formtemplate":["itp"],"application/vnd.shana.informed.interchange":["iif"],"application/vnd.shana.informed.package":["ipk"],"application/vnd.simtech-mindmapper":["twd","twds"],"application/vnd.smaf":["mmf"],"application/vnd.smart.teacher":["teacher"],"application/vnd.software602.filler.form+xml":["fo"],"application/vnd.solent.sdkm+xml":["sdkm","sdkd"],"application/vnd.spotfire.dxp":["dxp"],"application/vnd.spotfire.sfs":["sfs"],"application/vnd.stardivision.calc":["sdc"],"application/vnd.stardivision.draw":["sda"],"application/vnd.stardivision.impress":["sdd"],"application/vnd.stardivision.math":["smf"],"application/vnd.stardivision.writer":["sdw","vor"],"application/vnd.stardivision.writer-global":["sgl"],"application/vnd.stepmania.package":["smzip"],"application/vnd.stepmania.stepchart":["sm"],"application/vnd.sun.wadl+xml":["wadl"],"application/vnd.sun.xml.calc":["sxc"],"application/vnd.sun.xml.calc.template":["stc"],"application/vnd.sun.xml.draw":["sxd"],"application/vnd.sun.xml.draw.template":["std"],"application/vnd.sun.xml.impress":["sxi"],"application/vnd.sun.xml.impress.template":["sti"],"application/vnd.sun.xml.math":["sxm"],"application/vnd.sun.xml.writer":["sxw"],"application/vnd.sun.xml.writer.global":["sxg"],"application/vnd.sun.xml.writer.template":["stw"],"application/vnd.sus-calendar":["sus","susp"],"application/vnd.svd":["svd"],"application/vnd.symbian.install":["sis","sisx"],"application/vnd.syncml+xml":["xsm"],"application/vnd.syncml.dm+wbxml":["bdm"],"application/vnd.syncml.dm+xml":["xdm"],"application/vnd.syncml.dmddf+xml":["ddf"],"application/vnd.tao.intent-module-archive":["tao"],"application/vnd.tcpdump.pcap":["pcap","cap","dmp"],"application/vnd.tmobile-livetv":["tmo"],"application/vnd.trid.tpt":["tpt"],"application/vnd.triscape.mxs":["mxs"],"application/vnd.trueapp":["tra"],"application/vnd.ufdl":["ufd","ufdl"],"application/vnd.uiq.theme":["utz"],"application/vnd.umajin":["umj"],"application/vnd.unity":["unityweb"],"application/vnd.uoml+xml":["uoml"],"application/vnd.vcx":["vcx"],"application/vnd.visio":["vsd","vst","vss","vsw"],"application/vnd.visionary":["vis"],"application/vnd.vsf":["vsf"],"application/vnd.wap.wbxml":["wbxml"],"application/vnd.wap.wmlc":["wmlc"],"application/vnd.wap.wmlscriptc":["wmlsc"],"application/vnd.webturbo":["wtb"],"application/vnd.wolfram.player":["nbp"],"application/vnd.wordperfect":["wpd"],"application/vnd.wqd":["wqd"],"application/vnd.wt.stf":["stf"],"application/vnd.xara":["xar"],"application/vnd.xfdl":["xfdl"],"application/vnd.yamaha.hv-dic":["hvd"],"application/vnd.yamaha.hv-script":["hvs"],"application/vnd.yamaha.hv-voice":["hvp"],"application/vnd.yamaha.openscoreformat":["osf"],"application/vnd.yamaha.openscoreformat.osfpvg+xml":["osfpvg"],"application/vnd.yamaha.smaf-audio":["saf"],"application/vnd.yamaha.smaf-phrase":["spf"],"application/vnd.yellowriver-custom-menu":["cmp"],"application/vnd.zul":["zir","zirz"],"application/vnd.zzazz.deck+xml":["zaz"],"application/x-7z-compressed":["7z"],"application/x-abiword":["abw"],"application/x-ace-compressed":["ace"],"application/x-apple-diskimage":["*dmg"],"application/x-arj":["arj"],"application/x-authorware-bin":["aab","x32","u32","vox"],"application/x-authorware-map":["aam"],"application/x-authorware-seg":["aas"],"application/x-bcpio":["bcpio"],"application/x-bdoc":["*bdoc"],"application/x-bittorrent":["torrent"],"application/x-blorb":["blb","blorb"],"application/x-bzip":["bz"],"application/x-bzip2":["bz2","boz"],"application/x-cbr":["cbr","cba","cbt","cbz","cb7"],"application/x-cdlink":["vcd"],"application/x-cfs-compressed":["cfs"],"application/x-chat":["chat"],"application/x-chess-pgn":["pgn"],"application/x-chrome-extension":["crx"],"application/x-cocoa":["cco"],"application/x-conference":["nsc"],"application/x-cpio":["cpio"],"application/x-csh":["csh"],"application/x-debian-package":["*deb","udeb"],"application/x-dgc-compressed":["dgc"],"application/x-director":["dir","dcr","dxr","cst","cct","cxt","w3d","fgd","swa"],"application/x-doom":["wad"],"application/x-dtbncx+xml":["ncx"],"application/x-dtbook+xml":["dtb"],"application/x-dtbresource+xml":["res"],"application/x-dvi":["dvi"],"application/x-envoy":["evy"],"application/x-eva":["eva"],"application/x-font-bdf":["bdf"],"application/x-font-ghostscript":["gsf"],"application/x-font-linux-psf":["psf"],"application/x-font-pcf":["pcf"],"application/x-font-snf":["snf"],"application/x-font-type1":["pfa","pfb","pfm","afm"],"application/x-freearc":["arc"],"application/x-futuresplash":["spl"],"application/x-gca-compressed":["gca"],"application/x-glulx":["ulx"],"application/x-gnumeric":["gnumeric"],"application/x-gramps-xml":["gramps"],"application/x-gtar":["gtar"],"application/x-hdf":["hdf"],"application/x-httpd-php":["php"],"application/x-install-instructions":["install"],"application/x-iso9660-image":["*iso"],"application/x-java-archive-diff":["jardiff"],"application/x-java-jnlp-file":["jnlp"],"application/x-keepass2":["kdbx"],"application/x-latex":["latex"],"application/x-lua-bytecode":["luac"],"application/x-lzh-compressed":["lzh","lha"],"application/x-makeself":["run"],"application/x-mie":["mie"],"application/x-mobipocket-ebook":["prc","mobi"],"application/x-ms-application":["application"],"application/x-ms-shortcut":["lnk"],"application/x-ms-wmd":["wmd"],"application/x-ms-wmz":["wmz"],"application/x-ms-xbap":["xbap"],"application/x-msaccess":["mdb"],"application/x-msbinder":["obd"],"application/x-mscardfile":["crd"],"application/x-msclip":["clp"],"application/x-msdos-program":["*exe"],"application/x-msdownload":["*exe","*dll","com","bat","*msi"],"application/x-msmediaview":["mvb","m13","m14"],"application/x-msmetafile":["*wmf","*wmz","*emf","emz"],"application/x-msmoney":["mny"],"application/x-mspublisher":["pub"],"application/x-msschedule":["scd"],"application/x-msterminal":["trm"],"application/x-mswrite":["wri"],"application/x-netcdf":["nc","cdf"],"application/x-ns-proxy-autoconfig":["pac"],"application/x-nzb":["nzb"],"application/x-perl":["pl","pm"],"application/x-pilot":["*prc","*pdb"],"application/x-pkcs12":["p12","pfx"],"application/x-pkcs7-certificates":["p7b","spc"],"application/x-pkcs7-certreqresp":["p7r"],"application/x-rar-compressed":["*rar"],"application/x-redhat-package-manager":["rpm"],"application/x-research-info-systems":["ris"],"application/x-sea":["sea"],"application/x-sh":["sh"],"application/x-shar":["shar"],"application/x-shockwave-flash":["swf"],"application/x-silverlight-app":["xap"],"application/x-sql":["sql"],"application/x-stuffit":["sit"],"application/x-stuffitx":["sitx"],"application/x-subrip":["srt"],"application/x-sv4cpio":["sv4cpio"],"application/x-sv4crc":["sv4crc"],"application/x-t3vm-image":["t3"],"application/x-tads":["gam"],"application/x-tar":["tar"],"application/x-tcl":["tcl","tk"],"application/x-tex":["tex"],"application/x-tex-tfm":["tfm"],"application/x-texinfo":["texinfo","texi"],"application/x-tgif":["*obj"],"application/x-ustar":["ustar"],"application/x-virtualbox-hdd":["hdd"],"application/x-virtualbox-ova":["ova"],"application/x-virtualbox-ovf":["ovf"],"application/x-virtualbox-vbox":["vbox"],"application/x-virtualbox-vbox-extpack":["vbox-extpack"],"application/x-virtualbox-vdi":["vdi"],"application/x-virtualbox-vhd":["vhd"],"application/x-virtualbox-vmdk":["vmdk"],"application/x-wais-source":["src"],"application/x-web-app-manifest+json":["webapp"],"application/x-x509-ca-cert":["der","crt","pem"],"application/x-xfig":["fig"],"application/x-xliff+xml":["*xlf"],"application/x-xpinstall":["xpi"],"application/x-xz":["xz"],"application/x-zmachine":["z1","z2","z3","z4","z5","z6","z7","z8"],"audio/vnd.dece.audio":["uva","uvva"],"audio/vnd.digital-winds":["eol"],"audio/vnd.dra":["dra"],"audio/vnd.dts":["dts"],"audio/vnd.dts.hd":["dtshd"],"audio/vnd.lucent.voice":["lvp"],"audio/vnd.ms-playready.media.pya":["pya"],"audio/vnd.nuera.ecelp4800":["ecelp4800"],"audio/vnd.nuera.ecelp7470":["ecelp7470"],"audio/vnd.nuera.ecelp9600":["ecelp9600"],"audio/vnd.rip":["rip"],"audio/x-aac":["aac"],"audio/x-aiff":["aif","aiff","aifc"],"audio/x-caf":["caf"],"audio/x-flac":["flac"],"audio/x-m4a":["*m4a"],"audio/x-matroska":["mka"],"audio/x-mpegurl":["m3u"],"audio/x-ms-wax":["wax"],"audio/x-ms-wma":["wma"],"audio/x-pn-realaudio":["ram","ra"],"audio/x-pn-realaudio-plugin":["rmp"],"audio/x-realaudio":["*ra"],"audio/x-wav":["*wav"],"chemical/x-cdx":["cdx"],"chemical/x-cif":["cif"],"chemical/x-cmdf":["cmdf"],"chemical/x-cml":["cml"],"chemical/x-csml":["csml"],"chemical/x-xyz":["xyz"],"image/prs.btif":["btif"],"image/prs.pti":["pti"],"image/vnd.adobe.photoshop":["psd"],"image/vnd.airzip.accelerator.azv":["azv"],"image/vnd.dece.graphic":["uvi","uvvi","uvg","uvvg"],"image/vnd.djvu":["djvu","djv"],"image/vnd.dvb.subtitle":["*sub"],"image/vnd.dwg":["dwg"],"image/vnd.dxf":["dxf"],"image/vnd.fastbidsheet":["fbs"],"image/vnd.fpx":["fpx"],"image/vnd.fst":["fst"],"image/vnd.fujixerox.edmics-mmr":["mmr"],"image/vnd.fujixerox.edmics-rlc":["rlc"],"image/vnd.microsoft.icon":["ico"],"image/vnd.ms-dds":["dds"],"image/vnd.ms-modi":["mdi"],"image/vnd.ms-photo":["wdp"],"image/vnd.net-fpx":["npx"],"image/vnd.pco.b16":["b16"],"image/vnd.tencent.tap":["tap"],"image/vnd.valve.source.texture":["vtf"],"image/vnd.wap.wbmp":["wbmp"],"image/vnd.xiff":["xif"],"image/vnd.zbrush.pcx":["pcx"],"image/x-3ds":["3ds"],"image/x-cmu-raster":["ras"],"image/x-cmx":["cmx"],"image/x-freehand":["fh","fhc","fh4","fh5","fh7"],"image/x-icon":["*ico"],"image/x-jng":["jng"],"image/x-mrsid-image":["sid"],"image/x-ms-bmp":["*bmp"],"image/x-pcx":["*pcx"],"image/x-pict":["pic","pct"],"image/x-portable-anymap":["pnm"],"image/x-portable-bitmap":["pbm"],"image/x-portable-graymap":["pgm"],"image/x-portable-pixmap":["ppm"],"image/x-rgb":["rgb"],"image/x-tga":["tga"],"image/x-xbitmap":["xbm"],"image/x-xpixmap":["xpm"],"image/x-xwindowdump":["xwd"],"message/vnd.wfa.wsc":["wsc"],"model/vnd.collada+xml":["dae"],"model/vnd.dwf":["dwf"],"model/vnd.gdl":["gdl"],"model/vnd.gtw":["gtw"],"model/vnd.mts":["mts"],"model/vnd.opengex":["ogex"],"model/vnd.parasolid.transmit.binary":["x_b"],"model/vnd.parasolid.transmit.text":["x_t"],"model/vnd.usdz+zip":["usdz"],"model/vnd.valve.source.compiled-map":["bsp"],"model/vnd.vtu":["vtu"],"text/prs.lines.tag":["dsc"],"text/vnd.curl":["curl"],"text/vnd.curl.dcurl":["dcurl"],"text/vnd.curl.mcurl":["mcurl"],"text/vnd.curl.scurl":["scurl"],"text/vnd.dvb.subtitle":["sub"],"text/vnd.fly":["fly"],"text/vnd.fmi.flexstor":["flx"],"text/vnd.graphviz":["gv"],"text/vnd.in3d.3dml":["3dml"],"text/vnd.in3d.spot":["spot"],"text/vnd.sun.j2me.app-descriptor":["jad"],"text/vnd.wap.wml":["wml"],"text/vnd.wap.wmlscript":["wmls"],"text/x-asm":["s","asm"],"text/x-c":["c","cc","cxx","cpp","h","hh","dic"],"text/x-component":["htc"],"text/x-fortran":["f","for","f77","f90"],"text/x-handlebars-template":["hbs"],"text/x-java-source":["java"],"text/x-lua":["lua"],"text/x-markdown":["mkd"],"text/x-nfo":["nfo"],"text/x-opml":["opml"],"text/x-org":["*org"],"text/x-pascal":["p","pas"],"text/x-processing":["pde"],"text/x-sass":["sass"],"text/x-scss":["scss"],"text/x-setext":["etx"],"text/x-sfv":["sfv"],"text/x-suse-ymp":["ymp"],"text/x-uuencode":["uu"],"text/x-vcalendar":["vcs"],"text/x-vcard":["vcf"],"video/vnd.dece.hd":["uvh","uvvh"],"video/vnd.dece.mobile":["uvm","uvvm"],"video/vnd.dece.pd":["uvp","uvvp"],"video/vnd.dece.sd":["uvs","uvvs"],"video/vnd.dece.video":["uvv","uvvv"],"video/vnd.dvb.file":["dvb"],"video/vnd.fvt":["fvt"],"video/vnd.mpegurl":["mxu","m4u"],"video/vnd.ms-playready.media.pyv":["pyv"],"video/vnd.uvvu.mp4":["uvu","uvvu"],"video/vnd.vivo":["viv"],"video/x-f4v":["f4v"],"video/x-fli":["fli"],"video/x-flv":["flv"],"video/x-m4v":["m4v"],"video/x-matroska":["mkv","mk3d","mks"],"video/x-mng":["mng"],"video/x-ms-asf":["asf","asx"],"video/x-ms-vob":["vob"],"video/x-ms-wm":["wm"],"video/x-ms-wmv":["wmv"],"video/x-ms-wmx":["wmx"],"video/x-ms-wvx":["wvx"],"video/x-msvideo":["avi"],"video/x-sgi-movie":["movie"],"video/x-smv":["smv"],"x-conference/x-cooltalk":["ice"]};
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mime/types/standard.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/mime/types/standard.js ***!
|
|
\*********************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = {"application/andrew-inset":["ez"],"application/applixware":["aw"],"application/atom+xml":["atom"],"application/atomcat+xml":["atomcat"],"application/atomdeleted+xml":["atomdeleted"],"application/atomsvc+xml":["atomsvc"],"application/atsc-dwd+xml":["dwd"],"application/atsc-held+xml":["held"],"application/atsc-rsat+xml":["rsat"],"application/bdoc":["bdoc"],"application/calendar+xml":["xcs"],"application/ccxml+xml":["ccxml"],"application/cdfx+xml":["cdfx"],"application/cdmi-capability":["cdmia"],"application/cdmi-container":["cdmic"],"application/cdmi-domain":["cdmid"],"application/cdmi-object":["cdmio"],"application/cdmi-queue":["cdmiq"],"application/cu-seeme":["cu"],"application/dash+xml":["mpd"],"application/davmount+xml":["davmount"],"application/docbook+xml":["dbk"],"application/dssc+der":["dssc"],"application/dssc+xml":["xdssc"],"application/ecmascript":["ecma","es"],"application/emma+xml":["emma"],"application/emotionml+xml":["emotionml"],"application/epub+zip":["epub"],"application/exi":["exi"],"application/fdt+xml":["fdt"],"application/font-tdpfr":["pfr"],"application/geo+json":["geojson"],"application/gml+xml":["gml"],"application/gpx+xml":["gpx"],"application/gxf":["gxf"],"application/gzip":["gz"],"application/hjson":["hjson"],"application/hyperstudio":["stk"],"application/inkml+xml":["ink","inkml"],"application/ipfix":["ipfix"],"application/its+xml":["its"],"application/java-archive":["jar","war","ear"],"application/java-serialized-object":["ser"],"application/java-vm":["class"],"application/javascript":["js","mjs"],"application/json":["json","map"],"application/json5":["json5"],"application/jsonml+json":["jsonml"],"application/ld+json":["jsonld"],"application/lgr+xml":["lgr"],"application/lost+xml":["lostxml"],"application/mac-binhex40":["hqx"],"application/mac-compactpro":["cpt"],"application/mads+xml":["mads"],"application/manifest+json":["webmanifest"],"application/marc":["mrc"],"application/marcxml+xml":["mrcx"],"application/mathematica":["ma","nb","mb"],"application/mathml+xml":["mathml"],"application/mbox":["mbox"],"application/mediaservercontrol+xml":["mscml"],"application/metalink+xml":["metalink"],"application/metalink4+xml":["meta4"],"application/mets+xml":["mets"],"application/mmt-aei+xml":["maei"],"application/mmt-usd+xml":["musd"],"application/mods+xml":["mods"],"application/mp21":["m21","mp21"],"application/mp4":["mp4s","m4p"],"application/mrb-consumer+xml":["*xdf"],"application/mrb-publish+xml":["*xdf"],"application/msword":["doc","dot"],"application/mxf":["mxf"],"application/n-quads":["nq"],"application/n-triples":["nt"],"application/node":["cjs"],"application/octet-stream":["bin","dms","lrf","mar","so","dist","distz","pkg","bpk","dump","elc","deploy","exe","dll","deb","dmg","iso","img","msi","msp","msm","buffer"],"application/oda":["oda"],"application/oebps-package+xml":["opf"],"application/ogg":["ogx"],"application/omdoc+xml":["omdoc"],"application/onenote":["onetoc","onetoc2","onetmp","onepkg"],"application/oxps":["oxps"],"application/p2p-overlay+xml":["relo"],"application/patch-ops-error+xml":["*xer"],"application/pdf":["pdf"],"application/pgp-encrypted":["pgp"],"application/pgp-signature":["asc","sig"],"application/pics-rules":["prf"],"application/pkcs10":["p10"],"application/pkcs7-mime":["p7m","p7c"],"application/pkcs7-signature":["p7s"],"application/pkcs8":["p8"],"application/pkix-attr-cert":["ac"],"application/pkix-cert":["cer"],"application/pkix-crl":["crl"],"application/pkix-pkipath":["pkipath"],"application/pkixcmp":["pki"],"application/pls+xml":["pls"],"application/postscript":["ai","eps","ps"],"application/provenance+xml":["provx"],"application/pskc+xml":["pskcxml"],"application/raml+yaml":["raml"],"application/rdf+xml":["rdf","owl"],"application/reginfo+xml":["rif"],"application/relax-ng-compact-syntax":["rnc"],"application/resource-lists+xml":["rl"],"application/resource-lists-diff+xml":["rld"],"application/rls-services+xml":["rs"],"application/route-apd+xml":["rapd"],"application/route-s-tsid+xml":["sls"],"application/route-usd+xml":["rusd"],"application/rpki-ghostbusters":["gbr"],"application/rpki-manifest":["mft"],"application/rpki-roa":["roa"],"application/rsd+xml":["rsd"],"application/rss+xml":["rss"],"application/rtf":["rtf"],"application/sbml+xml":["sbml"],"application/scvp-cv-request":["scq"],"application/scvp-cv-response":["scs"],"application/scvp-vp-request":["spq"],"application/scvp-vp-response":["spp"],"application/sdp":["sdp"],"application/senml+xml":["senmlx"],"application/sensml+xml":["sensmlx"],"application/set-payment-initiation":["setpay"],"application/set-registration-initiation":["setreg"],"application/shf+xml":["shf"],"application/sieve":["siv","sieve"],"application/smil+xml":["smi","smil"],"application/sparql-query":["rq"],"application/sparql-results+xml":["srx"],"application/srgs":["gram"],"application/srgs+xml":["grxml"],"application/sru+xml":["sru"],"application/ssdl+xml":["ssdl"],"application/ssml+xml":["ssml"],"application/swid+xml":["swidtag"],"application/tei+xml":["tei","teicorpus"],"application/thraud+xml":["tfi"],"application/timestamped-data":["tsd"],"application/toml":["toml"],"application/ttml+xml":["ttml"],"application/ubjson":["ubj"],"application/urc-ressheet+xml":["rsheet"],"application/urc-targetdesc+xml":["td"],"application/voicexml+xml":["vxml"],"application/wasm":["wasm"],"application/widget":["wgt"],"application/winhlp":["hlp"],"application/wsdl+xml":["wsdl"],"application/wspolicy+xml":["wspolicy"],"application/xaml+xml":["xaml"],"application/xcap-att+xml":["xav"],"application/xcap-caps+xml":["xca"],"application/xcap-diff+xml":["xdf"],"application/xcap-el+xml":["xel"],"application/xcap-error+xml":["xer"],"application/xcap-ns+xml":["xns"],"application/xenc+xml":["xenc"],"application/xhtml+xml":["xhtml","xht"],"application/xliff+xml":["xlf"],"application/xml":["xml","xsl","xsd","rng"],"application/xml-dtd":["dtd"],"application/xop+xml":["xop"],"application/xproc+xml":["xpl"],"application/xslt+xml":["*xsl","xslt"],"application/xspf+xml":["xspf"],"application/xv+xml":["mxml","xhvml","xvml","xvm"],"application/yang":["yang"],"application/yin+xml":["yin"],"application/zip":["zip"],"audio/3gpp":["*3gpp"],"audio/adpcm":["adp"],"audio/amr":["amr"],"audio/basic":["au","snd"],"audio/midi":["mid","midi","kar","rmi"],"audio/mobile-xmf":["mxmf"],"audio/mp3":["*mp3"],"audio/mp4":["m4a","mp4a"],"audio/mpeg":["mpga","mp2","mp2a","mp3","m2a","m3a"],"audio/ogg":["oga","ogg","spx","opus"],"audio/s3m":["s3m"],"audio/silk":["sil"],"audio/wav":["wav"],"audio/wave":["*wav"],"audio/webm":["weba"],"audio/xm":["xm"],"font/collection":["ttc"],"font/otf":["otf"],"font/ttf":["ttf"],"font/woff":["woff"],"font/woff2":["woff2"],"image/aces":["exr"],"image/apng":["apng"],"image/avif":["avif"],"image/bmp":["bmp"],"image/cgm":["cgm"],"image/dicom-rle":["drle"],"image/emf":["emf"],"image/fits":["fits"],"image/g3fax":["g3"],"image/gif":["gif"],"image/heic":["heic"],"image/heic-sequence":["heics"],"image/heif":["heif"],"image/heif-sequence":["heifs"],"image/hej2k":["hej2"],"image/hsj2":["hsj2"],"image/ief":["ief"],"image/jls":["jls"],"image/jp2":["jp2","jpg2"],"image/jpeg":["jpeg","jpg","jpe"],"image/jph":["jph"],"image/jphc":["jhc"],"image/jpm":["jpm"],"image/jpx":["jpx","jpf"],"image/jxr":["jxr"],"image/jxra":["jxra"],"image/jxrs":["jxrs"],"image/jxs":["jxs"],"image/jxsc":["jxsc"],"image/jxsi":["jxsi"],"image/jxss":["jxss"],"image/ktx":["ktx"],"image/ktx2":["ktx2"],"image/png":["png"],"image/sgi":["sgi"],"image/svg+xml":["svg","svgz"],"image/t38":["t38"],"image/tiff":["tif","tiff"],"image/tiff-fx":["tfx"],"image/webp":["webp"],"image/wmf":["wmf"],"message/disposition-notification":["disposition-notification"],"message/global":["u8msg"],"message/global-delivery-status":["u8dsn"],"message/global-disposition-notification":["u8mdn"],"message/global-headers":["u8hdr"],"message/rfc822":["eml","mime"],"model/3mf":["3mf"],"model/gltf+json":["gltf"],"model/gltf-binary":["glb"],"model/iges":["igs","iges"],"model/mesh":["msh","mesh","silo"],"model/mtl":["mtl"],"model/obj":["obj"],"model/stl":["stl"],"model/vrml":["wrl","vrml"],"model/x3d+binary":["*x3db","x3dbz"],"model/x3d+fastinfoset":["x3db"],"model/x3d+vrml":["*x3dv","x3dvz"],"model/x3d+xml":["x3d","x3dz"],"model/x3d-vrml":["x3dv"],"text/cache-manifest":["appcache","manifest"],"text/calendar":["ics","ifb"],"text/coffeescript":["coffee","litcoffee"],"text/css":["css"],"text/csv":["csv"],"text/html":["html","htm","shtml"],"text/jade":["jade"],"text/jsx":["jsx"],"text/less":["less"],"text/markdown":["markdown","md"],"text/mathml":["mml"],"text/mdx":["mdx"],"text/n3":["n3"],"text/plain":["txt","text","conf","def","list","log","in","ini"],"text/richtext":["rtx"],"text/rtf":["*rtf"],"text/sgml":["sgml","sgm"],"text/shex":["shex"],"text/slim":["slim","slm"],"text/spdx":["spdx"],"text/stylus":["stylus","styl"],"text/tab-separated-values":["tsv"],"text/troff":["t","tr","roff","man","me","ms"],"text/turtle":["ttl"],"text/uri-list":["uri","uris","urls"],"text/vcard":["vcard"],"text/vtt":["vtt"],"text/xml":["*xml"],"text/yaml":["yaml","yml"],"video/3gpp":["3gp","3gpp"],"video/3gpp2":["3g2"],"video/h261":["h261"],"video/h263":["h263"],"video/h264":["h264"],"video/iso.segment":["m4s"],"video/jpeg":["jpgv"],"video/jpm":["*jpm","jpgm"],"video/mj2":["mj2","mjp2"],"video/mp2t":["ts"],"video/mp4":["mp4","mp4v","mpg4"],"video/mpeg":["mpeg","mpg","mpe","m1v","m2v"],"video/ogg":["ogv"],"video/quicktime":["qt","mov"],"video/webm":["webm"]};
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/minimalistic-assert/index.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/minimalistic-assert/index.js ***!
|
|
\***************************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = assert;
|
|
|
|
function assert(val, msg) {
|
|
if (!val)
|
|
throw new Error(msg || 'Assertion failed');
|
|
}
|
|
|
|
assert.equal = function assertEqual(l, r, msg) {
|
|
if (l != r)
|
|
throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r));
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/minimalistic-crypto-utils/lib/utils.js":
|
|
/*!*************************************************************!*\
|
|
!*** ./node_modules/minimalistic-crypto-utils/lib/utils.js ***!
|
|
\*************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var utils = exports;
|
|
|
|
function toArray(msg, enc) {
|
|
if (Array.isArray(msg))
|
|
return msg.slice();
|
|
if (!msg)
|
|
return [];
|
|
var res = [];
|
|
if (typeof msg !== 'string') {
|
|
for (var i = 0; i < msg.length; i++)
|
|
res[i] = msg[i] | 0;
|
|
return res;
|
|
}
|
|
if (enc === 'hex') {
|
|
msg = msg.replace(/[^a-z0-9]+/ig, '');
|
|
if (msg.length % 2 !== 0)
|
|
msg = '0' + msg;
|
|
for (var i = 0; i < msg.length; i += 2)
|
|
res.push(parseInt(msg[i] + msg[i + 1], 16));
|
|
} else {
|
|
for (var i = 0; i < msg.length; i++) {
|
|
var c = msg.charCodeAt(i);
|
|
var hi = c >> 8;
|
|
var lo = c & 0xff;
|
|
if (hi)
|
|
res.push(hi, lo);
|
|
else
|
|
res.push(lo);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
utils.toArray = toArray;
|
|
|
|
function zero2(word) {
|
|
if (word.length === 1)
|
|
return '0' + word;
|
|
else
|
|
return word;
|
|
}
|
|
utils.zero2 = zero2;
|
|
|
|
function toHex(msg) {
|
|
var res = '';
|
|
for (var i = 0; i < msg.length; i++)
|
|
res += zero2(msg[i].toString(16));
|
|
return res;
|
|
}
|
|
utils.toHex = toHex;
|
|
|
|
utils.encode = function encode(arr, enc) {
|
|
if (enc === 'hex')
|
|
return toHex(arr);
|
|
else
|
|
return arr;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mp4-box-encoding/boxes.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/mp4-box-encoding/boxes.js ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
// This is an intentionally recursive require. I don't like it either.
|
|
var Box = __webpack_require__(/*! ./index */ "./node_modules/mp4-box-encoding/index.js")
|
|
var Descriptor = __webpack_require__(/*! ./descriptor */ "./node_modules/mp4-box-encoding/descriptor.js")
|
|
var uint64be = __webpack_require__(/*! uint64be */ "./node_modules/uint64be/index.js")
|
|
|
|
var TIME_OFFSET = 2082844800000
|
|
|
|
/*
|
|
TODO:
|
|
test these
|
|
add new box versions
|
|
*/
|
|
|
|
// These have 'version' and 'flags' fields in the headers
|
|
exports.fullBoxes = {}
|
|
var fullBoxes = [
|
|
'mvhd',
|
|
'tkhd',
|
|
'mdhd',
|
|
'vmhd',
|
|
'smhd',
|
|
'stsd',
|
|
'esds',
|
|
'stsz',
|
|
'stco',
|
|
'co64',
|
|
'stss',
|
|
'stts',
|
|
'ctts',
|
|
'stsc',
|
|
'dref',
|
|
'elst',
|
|
'hdlr',
|
|
'mehd',
|
|
'trex',
|
|
'mfhd',
|
|
'tfhd',
|
|
'tfdt',
|
|
'trun'
|
|
]
|
|
fullBoxes.forEach(function (type) {
|
|
exports.fullBoxes[type] = true
|
|
})
|
|
|
|
exports.ftyp = {}
|
|
exports.ftyp.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.ftyp.encodingLength(box))
|
|
var brands = box.compatibleBrands || []
|
|
buf.write(box.brand, 0, 4, 'ascii')
|
|
buf.writeUInt32BE(box.brandVersion, 4)
|
|
for (var i = 0; i < brands.length; i++) buf.write(brands[i], 8 + (i * 4), 4, 'ascii')
|
|
exports.ftyp.encode.bytes = 8 + brands.length * 4
|
|
return buf
|
|
}
|
|
exports.ftyp.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
var brand = buf.toString('ascii', 0, 4)
|
|
var version = buf.readUInt32BE(4)
|
|
var compatibleBrands = []
|
|
for (var i = 8; i < buf.length; i += 4) compatibleBrands.push(buf.toString('ascii', i, i + 4))
|
|
return {
|
|
brand: brand,
|
|
brandVersion: version,
|
|
compatibleBrands: compatibleBrands
|
|
}
|
|
}
|
|
exports.ftyp.encodingLength = function (box) {
|
|
return 8 + (box.compatibleBrands || []).length * 4
|
|
}
|
|
|
|
exports.mvhd = {}
|
|
exports.mvhd.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(96)
|
|
writeDate(box.ctime || new Date(), buf, 0)
|
|
writeDate(box.mtime || new Date(), buf, 4)
|
|
buf.writeUInt32BE(box.timeScale || 0, 8)
|
|
buf.writeUInt32BE(box.duration || 0, 12)
|
|
writeFixed32(box.preferredRate || 0, buf, 16)
|
|
writeFixed16(box.preferredVolume || 0, buf, 20)
|
|
writeReserved(buf, 22, 32)
|
|
writeMatrix(box.matrix, buf, 32)
|
|
buf.writeUInt32BE(box.previewTime || 0, 68)
|
|
buf.writeUInt32BE(box.previewDuration || 0, 72)
|
|
buf.writeUInt32BE(box.posterTime || 0, 76)
|
|
buf.writeUInt32BE(box.selectionTime || 0, 80)
|
|
buf.writeUInt32BE(box.selectionDuration || 0, 84)
|
|
buf.writeUInt32BE(box.currentTime || 0, 88)
|
|
buf.writeUInt32BE(box.nextTrackId || 0, 92)
|
|
exports.mvhd.encode.bytes = 96
|
|
return buf
|
|
}
|
|
exports.mvhd.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
return {
|
|
ctime: readDate(buf, 0),
|
|
mtime: readDate(buf, 4),
|
|
timeScale: buf.readUInt32BE(8),
|
|
duration: buf.readUInt32BE(12),
|
|
preferredRate: readFixed32(buf, 16),
|
|
preferredVolume: readFixed16(buf, 20),
|
|
matrix: readMatrix(buf.slice(32, 68)),
|
|
previewTime: buf.readUInt32BE(68),
|
|
previewDuration: buf.readUInt32BE(72),
|
|
posterTime: buf.readUInt32BE(76),
|
|
selectionTime: buf.readUInt32BE(80),
|
|
selectionDuration: buf.readUInt32BE(84),
|
|
currentTime: buf.readUInt32BE(88),
|
|
nextTrackId: buf.readUInt32BE(92)
|
|
}
|
|
}
|
|
exports.mvhd.encodingLength = function (box) {
|
|
return 96
|
|
}
|
|
|
|
exports.tkhd = {}
|
|
exports.tkhd.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(80)
|
|
writeDate(box.ctime || new Date(), buf, 0)
|
|
writeDate(box.mtime || new Date(), buf, 4)
|
|
buf.writeUInt32BE(box.trackId || 0, 8)
|
|
writeReserved(buf, 12, 16)
|
|
buf.writeUInt32BE(box.duration || 0, 16)
|
|
writeReserved(buf, 20, 28)
|
|
buf.writeUInt16BE(box.layer || 0, 28)
|
|
buf.writeUInt16BE(box.alternateGroup || 0, 30)
|
|
buf.writeUInt16BE(box.volume || 0, 32)
|
|
writeMatrix(box.matrix, buf, 36)
|
|
buf.writeUInt32BE(box.trackWidth || 0, 72)
|
|
buf.writeUInt32BE(box.trackHeight || 0, 76)
|
|
exports.tkhd.encode.bytes = 80
|
|
return buf
|
|
}
|
|
exports.tkhd.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
return {
|
|
ctime: readDate(buf, 0),
|
|
mtime: readDate(buf, 4),
|
|
trackId: buf.readUInt32BE(8),
|
|
duration: buf.readUInt32BE(16),
|
|
layer: buf.readUInt16BE(28),
|
|
alternateGroup: buf.readUInt16BE(30),
|
|
volume: buf.readUInt16BE(32),
|
|
matrix: readMatrix(buf.slice(36, 72)),
|
|
trackWidth: buf.readUInt32BE(72),
|
|
trackHeight: buf.readUInt32BE(76)
|
|
}
|
|
}
|
|
exports.tkhd.encodingLength = function (box) {
|
|
return 80
|
|
}
|
|
|
|
exports.mdhd = {}
|
|
exports.mdhd.encode = function (box, buf, offset) {
|
|
if (box.version === 1) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(32)
|
|
writeDate64(box.ctime || new Date(), buf, 0)
|
|
writeDate64(box.mtime || new Date(), buf, 8)
|
|
buf.writeUInt32BE(box.timeScale || 0, 16)
|
|
// Node only supports integer <= 48bit. Waiting for BigInt!
|
|
buf.writeUIntBE(box.duration || 0, 20, 6)
|
|
buf.writeUInt16BE(box.language || 0, 28)
|
|
buf.writeUInt16BE(box.quality || 0, 30)
|
|
exports.mdhd.encode.bytes = 32
|
|
return buf
|
|
}
|
|
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(20)
|
|
writeDate(box.ctime || new Date(), buf, 0)
|
|
writeDate(box.mtime || new Date(), buf, 4)
|
|
buf.writeUInt32BE(box.timeScale || 0, 8)
|
|
buf.writeUInt32BE(box.duration || 0, 12)
|
|
buf.writeUInt16BE(box.language || 0, 16)
|
|
buf.writeUInt16BE(box.quality || 0, 18)
|
|
exports.mdhd.encode.bytes = 20
|
|
return buf
|
|
}
|
|
|
|
exports.mdhd.decode = function (buf, offset, end) {
|
|
buf = buf.slice(offset)
|
|
|
|
var version1 = (end - offset) !== 20
|
|
|
|
// In version 1 creation time and modification time are unsigned long
|
|
if (version1) {
|
|
return {
|
|
ctime: readDate64(buf, 0),
|
|
mtime: readDate64(buf, 8),
|
|
timeScale: buf.readUInt32BE(16),
|
|
// Node only supports integer <= 48bit. Waiting for BigInt!
|
|
duration: buf.readUIntBE(20, 6),
|
|
language: buf.readUInt16BE(28),
|
|
quality: buf.readUInt16BE(30)
|
|
}
|
|
}
|
|
|
|
return {
|
|
ctime: readDate(buf, 0),
|
|
mtime: readDate(buf, 4),
|
|
timeScale: buf.readUInt32BE(8),
|
|
duration: buf.readUInt32BE(12),
|
|
language: buf.readUInt16BE(16),
|
|
quality: buf.readUInt16BE(18)
|
|
}
|
|
}
|
|
exports.mdhd.encodingLength = function (box) {
|
|
if (box.version === 1) return 32
|
|
|
|
return 20
|
|
}
|
|
|
|
exports.vmhd = {}
|
|
exports.vmhd.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(8)
|
|
buf.writeUInt16BE(box.graphicsMode || 0, 0)
|
|
var opcolor = box.opcolor || [0, 0, 0]
|
|
buf.writeUInt16BE(opcolor[0], 2)
|
|
buf.writeUInt16BE(opcolor[1], 4)
|
|
buf.writeUInt16BE(opcolor[2], 6)
|
|
exports.vmhd.encode.bytes = 8
|
|
return buf
|
|
}
|
|
exports.vmhd.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
return {
|
|
graphicsMode: buf.readUInt16BE(0),
|
|
opcolor: [buf.readUInt16BE(2), buf.readUInt16BE(4), buf.readUInt16BE(6)]
|
|
}
|
|
}
|
|
exports.vmhd.encodingLength = function (box) {
|
|
return 8
|
|
}
|
|
|
|
exports.smhd = {}
|
|
exports.smhd.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(4)
|
|
buf.writeUInt16BE(box.balance || 0, 0)
|
|
writeReserved(buf, 2, 4)
|
|
exports.smhd.encode.bytes = 4
|
|
return buf
|
|
}
|
|
exports.smhd.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
return {
|
|
balance: buf.readUInt16BE(0)
|
|
}
|
|
}
|
|
exports.smhd.encodingLength = function (box) {
|
|
return 4
|
|
}
|
|
|
|
exports.stsd = {}
|
|
exports.stsd.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.stsd.encodingLength(box))
|
|
var entries = box.entries || []
|
|
|
|
buf.writeUInt32BE(entries.length, 0)
|
|
|
|
var ptr = 4
|
|
for (var i = 0; i < entries.length; i++) {
|
|
var entry = entries[i]
|
|
Box.encode(entry, buf, ptr)
|
|
ptr += Box.encode.bytes
|
|
}
|
|
|
|
exports.stsd.encode.bytes = ptr
|
|
return buf
|
|
}
|
|
exports.stsd.decode = function (buf, offset, end) {
|
|
buf = buf.slice(offset)
|
|
var num = buf.readUInt32BE(0)
|
|
var entries = new Array(num)
|
|
var ptr = 4
|
|
|
|
for (var i = 0; i < num; i++) {
|
|
var entry = Box.decode(buf, ptr, end)
|
|
entries[i] = entry
|
|
ptr += entry.length
|
|
}
|
|
|
|
return {
|
|
entries: entries
|
|
}
|
|
}
|
|
exports.stsd.encodingLength = function (box) {
|
|
var totalSize = 4
|
|
if (!box.entries) return totalSize
|
|
for (var i = 0; i < box.entries.length; i++) {
|
|
totalSize += Box.encodingLength(box.entries[i])
|
|
}
|
|
return totalSize
|
|
}
|
|
|
|
exports.avc1 = exports.VisualSampleEntry = {}
|
|
exports.VisualSampleEntry.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.VisualSampleEntry.encodingLength(box))
|
|
|
|
writeReserved(buf, 0, 6)
|
|
buf.writeUInt16BE(box.dataReferenceIndex || 0, 6)
|
|
writeReserved(buf, 8, 24)
|
|
buf.writeUInt16BE(box.width || 0, 24)
|
|
buf.writeUInt16BE(box.height || 0, 26)
|
|
buf.writeUInt32BE(box.hResolution || 0x480000, 28)
|
|
buf.writeUInt32BE(box.vResolution || 0x480000, 32)
|
|
writeReserved(buf, 36, 40)
|
|
buf.writeUInt16BE(box.frameCount || 1, 40)
|
|
var compressorName = box.compressorName || ''
|
|
var nameLen = Math.min(compressorName.length, 31)
|
|
buf.writeUInt8(nameLen, 42)
|
|
buf.write(compressorName, 43, nameLen, 'utf8')
|
|
buf.writeUInt16BE(box.depth || 0x18, 74)
|
|
buf.writeInt16BE(-1, 76)
|
|
|
|
var ptr = 78
|
|
var children = box.children || []
|
|
children.forEach(function (child) {
|
|
Box.encode(child, buf, ptr)
|
|
ptr += Box.encode.bytes
|
|
})
|
|
exports.VisualSampleEntry.encode.bytes = ptr
|
|
}
|
|
exports.VisualSampleEntry.decode = function (buf, offset, end) {
|
|
buf = buf.slice(offset)
|
|
var length = end - offset
|
|
var nameLen = Math.min(buf.readUInt8(42), 31)
|
|
var box = {
|
|
dataReferenceIndex: buf.readUInt16BE(6),
|
|
width: buf.readUInt16BE(24),
|
|
height: buf.readUInt16BE(26),
|
|
hResolution: buf.readUInt32BE(28),
|
|
vResolution: buf.readUInt32BE(32),
|
|
frameCount: buf.readUInt16BE(40),
|
|
compressorName: buf.toString('utf8', 43, 43 + nameLen),
|
|
depth: buf.readUInt16BE(74),
|
|
children: []
|
|
}
|
|
|
|
var ptr = 78
|
|
while (length - ptr >= 8) {
|
|
var child = Box.decode(buf, ptr, length)
|
|
box.children.push(child)
|
|
box[child.type] = child
|
|
ptr += child.length
|
|
}
|
|
|
|
return box
|
|
}
|
|
exports.VisualSampleEntry.encodingLength = function (box) {
|
|
var len = 78
|
|
var children = box.children || []
|
|
children.forEach(function (child) {
|
|
len += Box.encodingLength(child)
|
|
})
|
|
return len
|
|
}
|
|
|
|
exports.avcC = {}
|
|
exports.avcC.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(box.buffer.length)
|
|
|
|
box.buffer.copy(buf)
|
|
exports.avcC.encode.bytes = box.buffer.length
|
|
}
|
|
exports.avcC.decode = function (buf, offset, end) {
|
|
buf = buf.slice(offset, end)
|
|
|
|
return {
|
|
mimeCodec: buf.toString('hex', 1, 4),
|
|
buffer: Buffer.from(buf)
|
|
}
|
|
}
|
|
exports.avcC.encodingLength = function (box) {
|
|
return box.buffer.length
|
|
}
|
|
|
|
exports.mp4a = exports.AudioSampleEntry = {}
|
|
exports.AudioSampleEntry.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.AudioSampleEntry.encodingLength(box))
|
|
|
|
writeReserved(buf, 0, 6)
|
|
buf.writeUInt16BE(box.dataReferenceIndex || 0, 6)
|
|
writeReserved(buf, 8, 16)
|
|
buf.writeUInt16BE(box.channelCount || 2, 16)
|
|
buf.writeUInt16BE(box.sampleSize || 16, 18)
|
|
writeReserved(buf, 20, 24)
|
|
buf.writeUInt32BE(box.sampleRate || 0, 24)
|
|
|
|
var ptr = 28
|
|
var children = box.children || []
|
|
children.forEach(function (child) {
|
|
Box.encode(child, buf, ptr)
|
|
ptr += Box.encode.bytes
|
|
})
|
|
exports.AudioSampleEntry.encode.bytes = ptr
|
|
}
|
|
exports.AudioSampleEntry.decode = function (buf, offset, end) {
|
|
buf = buf.slice(offset, end)
|
|
var length = end - offset
|
|
var box = {
|
|
dataReferenceIndex: buf.readUInt16BE(6),
|
|
channelCount: buf.readUInt16BE(16),
|
|
sampleSize: buf.readUInt16BE(18),
|
|
sampleRate: buf.readUInt32BE(24),
|
|
children: []
|
|
}
|
|
|
|
var ptr = 28
|
|
while (length - ptr >= 8) {
|
|
var child = Box.decode(buf, ptr, length)
|
|
box.children.push(child)
|
|
box[child.type] = child
|
|
ptr += child.length
|
|
}
|
|
|
|
return box
|
|
}
|
|
exports.AudioSampleEntry.encodingLength = function (box) {
|
|
var len = 28
|
|
var children = box.children || []
|
|
children.forEach(function (child) {
|
|
len += Box.encodingLength(child)
|
|
})
|
|
return len
|
|
}
|
|
|
|
exports.esds = {}
|
|
exports.esds.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(box.buffer.length)
|
|
|
|
box.buffer.copy(buf, 0)
|
|
exports.esds.encode.bytes = box.buffer.length
|
|
}
|
|
exports.esds.decode = function (buf, offset, end) {
|
|
buf = buf.slice(offset, end)
|
|
|
|
var desc = Descriptor.Descriptor.decode(buf, 0, buf.length)
|
|
var esd = (desc.tagName === 'ESDescriptor') ? desc : {}
|
|
var dcd = esd.DecoderConfigDescriptor || {}
|
|
var oti = dcd.oti || 0
|
|
var dsi = dcd.DecoderSpecificInfo
|
|
var audioConfig = dsi ? (dsi.buffer.readUInt8(0) & 0xf8) >> 3 : 0
|
|
|
|
var mimeCodec = null
|
|
if (oti) {
|
|
mimeCodec = oti.toString(16)
|
|
if (audioConfig) {
|
|
mimeCodec += '.' + audioConfig
|
|
}
|
|
}
|
|
|
|
return {
|
|
mimeCodec: mimeCodec,
|
|
buffer: Buffer.from(buf.slice(0))
|
|
}
|
|
}
|
|
exports.esds.encodingLength = function (box) {
|
|
return box.buffer.length
|
|
}
|
|
|
|
// TODO: integrate the two versions in a saner way
|
|
exports.stsz = {}
|
|
exports.stsz.encode = function (box, buf, offset) {
|
|
var entries = box.entries || []
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.stsz.encodingLength(box))
|
|
|
|
buf.writeUInt32BE(0, 0)
|
|
buf.writeUInt32BE(entries.length, 4)
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
buf.writeUInt32BE(entries[i], i * 4 + 8)
|
|
}
|
|
|
|
exports.stsz.encode.bytes = 8 + entries.length * 4
|
|
return buf
|
|
}
|
|
exports.stsz.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
var size = buf.readUInt32BE(0)
|
|
var num = buf.readUInt32BE(4)
|
|
var entries = new Array(num)
|
|
|
|
for (var i = 0; i < num; i++) {
|
|
if (size === 0) {
|
|
entries[i] = buf.readUInt32BE(i * 4 + 8)
|
|
} else {
|
|
entries[i] = size
|
|
}
|
|
}
|
|
|
|
return {
|
|
entries: entries
|
|
}
|
|
}
|
|
exports.stsz.encodingLength = function (box) {
|
|
return 8 + box.entries.length * 4
|
|
}
|
|
|
|
exports.stss =
|
|
exports.stco = {}
|
|
exports.stco.encode = function (box, buf, offset) {
|
|
var entries = box.entries || []
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.stco.encodingLength(box))
|
|
|
|
buf.writeUInt32BE(entries.length, 0)
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
buf.writeUInt32BE(entries[i], i * 4 + 4)
|
|
}
|
|
|
|
exports.stco.encode.bytes = 4 + entries.length * 4
|
|
return buf
|
|
}
|
|
exports.stco.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
var num = buf.readUInt32BE(0)
|
|
var entries = new Array(num)
|
|
|
|
for (var i = 0; i < num; i++) {
|
|
entries[i] = buf.readUInt32BE(i * 4 + 4)
|
|
}
|
|
|
|
return {
|
|
entries: entries
|
|
}
|
|
}
|
|
exports.stco.encodingLength = function (box) {
|
|
return 4 + box.entries.length * 4
|
|
}
|
|
|
|
exports.co64 = {}
|
|
exports.co64.encode = function (box, buf, offset) {
|
|
var entries = box.entries || []
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.co64.encodingLength(box))
|
|
|
|
buf.writeUInt32BE(entries.length, 0)
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
uint64be.encode(entries[i], buf, i * 8 + 4)
|
|
}
|
|
|
|
exports.co64.encode.bytes = 4 + entries.length * 8
|
|
return buf
|
|
}
|
|
exports.co64.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
var num = buf.readUInt32BE(0)
|
|
var entries = new Array(num)
|
|
|
|
for (var i = 0; i < num; i++) {
|
|
entries[i] = uint64be.decode(buf, i * 8 + 4)
|
|
}
|
|
|
|
return {
|
|
entries: entries
|
|
}
|
|
}
|
|
exports.co64.encodingLength = function (box) {
|
|
return 4 + box.entries.length * 8
|
|
}
|
|
|
|
exports.stts = {}
|
|
exports.stts.encode = function (box, buf, offset) {
|
|
var entries = box.entries || []
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.stts.encodingLength(box))
|
|
|
|
buf.writeUInt32BE(entries.length, 0)
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
var ptr = i * 8 + 4
|
|
buf.writeUInt32BE(entries[i].count || 0, ptr)
|
|
buf.writeUInt32BE(entries[i].duration || 0, ptr + 4)
|
|
}
|
|
|
|
exports.stts.encode.bytes = 4 + box.entries.length * 8
|
|
return buf
|
|
}
|
|
exports.stts.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
var num = buf.readUInt32BE(0)
|
|
var entries = new Array(num)
|
|
|
|
for (var i = 0; i < num; i++) {
|
|
var ptr = i * 8 + 4
|
|
entries[i] = {
|
|
count: buf.readUInt32BE(ptr),
|
|
duration: buf.readUInt32BE(ptr + 4)
|
|
}
|
|
}
|
|
|
|
return {
|
|
entries: entries
|
|
}
|
|
}
|
|
exports.stts.encodingLength = function (box) {
|
|
return 4 + box.entries.length * 8
|
|
}
|
|
|
|
exports.ctts = {}
|
|
exports.ctts.encode = function (box, buf, offset) {
|
|
var entries = box.entries || []
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.ctts.encodingLength(box))
|
|
|
|
buf.writeUInt32BE(entries.length, 0)
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
var ptr = i * 8 + 4
|
|
buf.writeUInt32BE(entries[i].count || 0, ptr)
|
|
buf.writeUInt32BE(entries[i].compositionOffset || 0, ptr + 4)
|
|
}
|
|
|
|
exports.ctts.encode.bytes = 4 + entries.length * 8
|
|
return buf
|
|
}
|
|
exports.ctts.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
var num = buf.readUInt32BE(0)
|
|
var entries = new Array(num)
|
|
|
|
for (var i = 0; i < num; i++) {
|
|
var ptr = i * 8 + 4
|
|
entries[i] = {
|
|
count: buf.readUInt32BE(ptr),
|
|
compositionOffset: buf.readInt32BE(ptr + 4)
|
|
}
|
|
}
|
|
|
|
return {
|
|
entries: entries
|
|
}
|
|
}
|
|
exports.ctts.encodingLength = function (box) {
|
|
return 4 + box.entries.length * 8
|
|
}
|
|
|
|
exports.stsc = {}
|
|
exports.stsc.encode = function (box, buf, offset) {
|
|
var entries = box.entries || []
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.stsc.encodingLength(box))
|
|
|
|
buf.writeUInt32BE(entries.length, 0)
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
var ptr = i * 12 + 4
|
|
buf.writeUInt32BE(entries[i].firstChunk || 0, ptr)
|
|
buf.writeUInt32BE(entries[i].samplesPerChunk || 0, ptr + 4)
|
|
buf.writeUInt32BE(entries[i].sampleDescriptionId || 0, ptr + 8)
|
|
}
|
|
|
|
exports.stsc.encode.bytes = 4 + entries.length * 12
|
|
return buf
|
|
}
|
|
exports.stsc.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
var num = buf.readUInt32BE(0)
|
|
var entries = new Array(num)
|
|
|
|
for (var i = 0; i < num; i++) {
|
|
var ptr = i * 12 + 4
|
|
entries[i] = {
|
|
firstChunk: buf.readUInt32BE(ptr),
|
|
samplesPerChunk: buf.readUInt32BE(ptr + 4),
|
|
sampleDescriptionId: buf.readUInt32BE(ptr + 8)
|
|
}
|
|
}
|
|
|
|
return {
|
|
entries: entries
|
|
}
|
|
}
|
|
exports.stsc.encodingLength = function (box) {
|
|
return 4 + box.entries.length * 12
|
|
}
|
|
|
|
exports.dref = {}
|
|
exports.dref.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.dref.encodingLength(box))
|
|
var entries = box.entries || []
|
|
|
|
buf.writeUInt32BE(entries.length, 0)
|
|
|
|
var ptr = 4
|
|
for (var i = 0; i < entries.length; i++) {
|
|
var entry = entries[i]
|
|
var size = (entry.buf ? entry.buf.length : 0) + 4 + 4
|
|
|
|
buf.writeUInt32BE(size, ptr)
|
|
ptr += 4
|
|
|
|
buf.write(entry.type, ptr, 4, 'ascii')
|
|
ptr += 4
|
|
|
|
if (entry.buf) {
|
|
entry.buf.copy(buf, ptr)
|
|
ptr += entry.buf.length
|
|
}
|
|
}
|
|
|
|
exports.dref.encode.bytes = ptr
|
|
return buf
|
|
}
|
|
exports.dref.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
var num = buf.readUInt32BE(0)
|
|
var entries = new Array(num)
|
|
var ptr = 4
|
|
|
|
for (var i = 0; i < num; i++) {
|
|
var size = buf.readUInt32BE(ptr)
|
|
var type = buf.toString('ascii', ptr + 4, ptr + 8)
|
|
var tmp = buf.slice(ptr + 8, ptr + size)
|
|
ptr += size
|
|
|
|
entries[i] = {
|
|
type: type,
|
|
buf: tmp
|
|
}
|
|
}
|
|
|
|
return {
|
|
entries: entries
|
|
}
|
|
}
|
|
exports.dref.encodingLength = function (box) {
|
|
var totalSize = 4
|
|
if (!box.entries) return totalSize
|
|
for (var i = 0; i < box.entries.length; i++) {
|
|
var buf = box.entries[i].buf
|
|
totalSize += (buf ? buf.length : 0) + 4 + 4
|
|
}
|
|
return totalSize
|
|
}
|
|
|
|
exports.elst = {}
|
|
exports.elst.encode = function (box, buf, offset) {
|
|
var entries = box.entries || []
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.elst.encodingLength(box))
|
|
|
|
buf.writeUInt32BE(entries.length, 0)
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
var ptr = i * 12 + 4
|
|
buf.writeUInt32BE(entries[i].trackDuration || 0, ptr)
|
|
buf.writeUInt32BE(entries[i].mediaTime || 0, ptr + 4)
|
|
writeFixed32(entries[i].mediaRate || 0, buf, ptr + 8)
|
|
}
|
|
|
|
exports.elst.encode.bytes = 4 + entries.length * 12
|
|
return buf
|
|
}
|
|
exports.elst.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
var num = buf.readUInt32BE(0)
|
|
var entries = new Array(num)
|
|
|
|
for (var i = 0; i < num; i++) {
|
|
var ptr = i * 12 + 4
|
|
entries[i] = {
|
|
trackDuration: buf.readUInt32BE(ptr),
|
|
mediaTime: buf.readInt32BE(ptr + 4),
|
|
mediaRate: readFixed32(buf, ptr + 8)
|
|
}
|
|
}
|
|
|
|
return {
|
|
entries: entries
|
|
}
|
|
}
|
|
exports.elst.encodingLength = function (box) {
|
|
return 4 + box.entries.length * 12
|
|
}
|
|
|
|
exports.hdlr = {}
|
|
exports.hdlr.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(exports.hdlr.encodingLength(box))
|
|
|
|
var len = 21 + (box.name || '').length
|
|
buf.fill(0, 0, len)
|
|
|
|
buf.write(box.handlerType || '', 4, 4, 'ascii')
|
|
writeString(box.name || '', buf, 20)
|
|
|
|
exports.hdlr.encode.bytes = len
|
|
return buf
|
|
}
|
|
exports.hdlr.decode = function (buf, offset, end) {
|
|
buf = buf.slice(offset)
|
|
return {
|
|
handlerType: buf.toString('ascii', 4, 8),
|
|
name: readString(buf, 20, end)
|
|
}
|
|
}
|
|
exports.hdlr.encodingLength = function (box) {
|
|
return 21 + (box.name || '').length
|
|
}
|
|
|
|
exports.mehd = {}
|
|
exports.mehd.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(4)
|
|
|
|
buf.writeUInt32BE(box.fragmentDuration || 0, 0)
|
|
exports.mehd.encode.bytes = 4
|
|
return buf
|
|
}
|
|
exports.mehd.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
return {
|
|
fragmentDuration: buf.readUInt32BE(0)
|
|
}
|
|
}
|
|
exports.mehd.encodingLength = function (box) {
|
|
return 4
|
|
}
|
|
|
|
exports.trex = {}
|
|
exports.trex.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(20)
|
|
|
|
buf.writeUInt32BE(box.trackId || 0, 0)
|
|
buf.writeUInt32BE(box.defaultSampleDescriptionIndex || 0, 4)
|
|
buf.writeUInt32BE(box.defaultSampleDuration || 0, 8)
|
|
buf.writeUInt32BE(box.defaultSampleSize || 0, 12)
|
|
buf.writeUInt32BE(box.defaultSampleFlags || 0, 16)
|
|
exports.trex.encode.bytes = 20
|
|
return buf
|
|
}
|
|
exports.trex.decode = function (buf, offset) {
|
|
buf = buf.slice(offset)
|
|
return {
|
|
trackId: buf.readUInt32BE(0),
|
|
defaultSampleDescriptionIndex: buf.readUInt32BE(4),
|
|
defaultSampleDuration: buf.readUInt32BE(8),
|
|
defaultSampleSize: buf.readUInt32BE(12),
|
|
defaultSampleFlags: buf.readUInt32BE(16)
|
|
}
|
|
}
|
|
exports.trex.encodingLength = function (box) {
|
|
return 20
|
|
}
|
|
|
|
exports.mfhd = {}
|
|
exports.mfhd.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(4)
|
|
|
|
buf.writeUInt32BE(box.sequenceNumber || 0, 0)
|
|
exports.mfhd.encode.bytes = 4
|
|
return buf
|
|
}
|
|
exports.mfhd.decode = function (buf, offset) {
|
|
return {
|
|
sequenceNumber: buf.readUInt32BE(0)
|
|
}
|
|
}
|
|
exports.mfhd.encodingLength = function (box) {
|
|
return 4
|
|
}
|
|
|
|
exports.tfhd = {}
|
|
exports.tfhd.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(4)
|
|
buf.writeUInt32BE(box.trackId, 0)
|
|
exports.tfhd.encode.bytes = 4
|
|
return buf
|
|
}
|
|
exports.tfhd.decode = function (buf, offset) {
|
|
// TODO: this
|
|
}
|
|
exports.tfhd.encodingLength = function (box) {
|
|
// TODO: this is wrong!
|
|
return 4
|
|
}
|
|
|
|
exports.tfdt = {}
|
|
exports.tfdt.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(4)
|
|
|
|
buf.writeUInt32BE(box.baseMediaDecodeTime || 0, 0)
|
|
exports.tfdt.encode.bytes = 4
|
|
return buf
|
|
}
|
|
exports.tfdt.decode = function (buf, offset) {
|
|
// TODO: this
|
|
}
|
|
exports.tfdt.encodingLength = function (box) {
|
|
return 4
|
|
}
|
|
|
|
exports.trun = {}
|
|
exports.trun.encode = function (box, buf, offset) {
|
|
buf = buf ? buf.slice(offset) : Buffer.alloc(8 + box.entries.length * 16)
|
|
|
|
// TODO: this is wrong
|
|
buf.writeUInt32BE(box.entries.length, 0)
|
|
buf.writeInt32BE(box.dataOffset, 4)
|
|
var ptr = 8
|
|
for (var i = 0; i < box.entries.length; i++) {
|
|
var entry = box.entries[i]
|
|
buf.writeUInt32BE(entry.sampleDuration, ptr)
|
|
ptr += 4
|
|
|
|
buf.writeUInt32BE(entry.sampleSize, ptr)
|
|
ptr += 4
|
|
|
|
buf.writeUInt32BE(entry.sampleFlags, ptr)
|
|
ptr += 4
|
|
|
|
if ((box.version || 0) === 0) {
|
|
buf.writeUInt32BE(entry.sampleCompositionTimeOffset, ptr)
|
|
} else {
|
|
buf.writeInt32BE(entry.sampleCompositionTimeOffset, ptr)
|
|
}
|
|
ptr += 4
|
|
}
|
|
exports.trun.encode.bytes = ptr
|
|
}
|
|
exports.trun.decode = function (buf, offset) {
|
|
// TODO: this
|
|
}
|
|
exports.trun.encodingLength = function (box) {
|
|
// TODO: this is wrong
|
|
return 8 + box.entries.length * 16
|
|
}
|
|
|
|
exports.mdat = {}
|
|
exports.mdat.encode = function (box, buf, offset) {
|
|
if (box.buffer) {
|
|
box.buffer.copy(buf, offset)
|
|
exports.mdat.encode.bytes = box.buffer.length
|
|
} else {
|
|
exports.mdat.encode.bytes = exports.mdat.encodingLength(box)
|
|
}
|
|
}
|
|
exports.mdat.decode = function (buf, start, end) {
|
|
return {
|
|
buffer: Buffer.from(buf.slice(start, end))
|
|
}
|
|
}
|
|
exports.mdat.encodingLength = function (box) {
|
|
return box.buffer ? box.buffer.length : box.contentLength
|
|
}
|
|
|
|
function writeReserved (buf, offset, end) {
|
|
for (var i = offset; i < end; i++) buf[i] = 0
|
|
}
|
|
|
|
function writeDate (date, buf, offset) {
|
|
buf.writeUInt32BE(Math.floor((date.getTime() + TIME_OFFSET) / 1000), offset)
|
|
}
|
|
|
|
function writeDate64 (date, buf, offset) {
|
|
// Node only supports integer <= 48bit. Waiting for BigInt!
|
|
buf.writeUIntBE(Math.floor((date.getTime() + TIME_OFFSET) / 1000), offset, 6)
|
|
}
|
|
|
|
// TODO: think something is wrong here
|
|
function writeFixed32 (num, buf, offset) {
|
|
buf.writeUInt16BE(Math.floor(num) % (256 * 256), offset)
|
|
buf.writeUInt16BE(Math.floor(num * 256 * 256) % (256 * 256), offset + 2)
|
|
}
|
|
|
|
function writeFixed16 (num, buf, offset) {
|
|
buf[offset] = Math.floor(num) % 256
|
|
buf[offset + 1] = Math.floor(num * 256) % 256
|
|
}
|
|
|
|
function writeMatrix (list, buf, offset) {
|
|
if (!list) list = [0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
for (var i = 0; i < list.length; i++) {
|
|
writeFixed32(list[i], buf, offset + i * 4)
|
|
}
|
|
}
|
|
|
|
function writeString (str, buf, offset) {
|
|
var strBuffer = Buffer.from(str, 'utf8')
|
|
strBuffer.copy(buf, offset)
|
|
buf[offset + strBuffer.length] = 0
|
|
}
|
|
|
|
function readMatrix (buf) {
|
|
var list = new Array(buf.length / 4)
|
|
for (var i = 0; i < list.length; i++) list[i] = readFixed32(buf, i * 4)
|
|
return list
|
|
}
|
|
|
|
function readDate64 (buf, offset) {
|
|
// Node only supports integer <= 48bit. Waiting for BigInt!
|
|
return new Date(buf.readUIntBE(offset, 6) * 1000 - TIME_OFFSET)
|
|
}
|
|
|
|
function readDate (buf, offset) {
|
|
return new Date(buf.readUInt32BE(offset) * 1000 - TIME_OFFSET)
|
|
}
|
|
|
|
function readFixed32 (buf, offset) {
|
|
return buf.readUInt16BE(offset) + buf.readUInt16BE(offset + 2) / (256 * 256)
|
|
}
|
|
|
|
function readFixed16 (buf, offset) {
|
|
return buf[offset] + buf[offset + 1] / 256
|
|
}
|
|
|
|
function readString (buf, offset, length) {
|
|
var i
|
|
for (i = 0; i < length; i++) {
|
|
if (buf[offset + i] === 0) {
|
|
break
|
|
}
|
|
}
|
|
return buf.toString('utf8', offset, offset + i)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mp4-box-encoding/descriptor.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/mp4-box-encoding/descriptor.js ***!
|
|
\*****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
var tagToName = {
|
|
0x03: 'ESDescriptor',
|
|
0x04: 'DecoderConfigDescriptor',
|
|
0x05: 'DecoderSpecificInfo',
|
|
0x06: 'SLConfigDescriptor'
|
|
}
|
|
|
|
exports.Descriptor = {}
|
|
exports.Descriptor.decode = function (buf, start, end) {
|
|
var tag = buf.readUInt8(start)
|
|
var ptr = start + 1
|
|
var lenByte
|
|
var len = 0
|
|
do {
|
|
lenByte = buf.readUInt8(ptr++)
|
|
len = (len << 7) | (lenByte & 0x7f)
|
|
} while (lenByte & 0x80)
|
|
|
|
var obj
|
|
var tagName = tagToName[tag] // May be undefined; that's ok
|
|
if (exports[tagName]) {
|
|
obj = exports[tagName].decode(buf, ptr, end)
|
|
} else {
|
|
obj = {
|
|
buffer: Buffer.from(buf.slice(ptr, ptr + len))
|
|
}
|
|
}
|
|
|
|
obj.tag = tag
|
|
obj.tagName = tagName
|
|
obj.length = (ptr - start) + len
|
|
obj.contentsLen = len
|
|
return obj
|
|
}
|
|
|
|
exports.DescriptorArray = {}
|
|
exports.DescriptorArray.decode = function (buf, start, end) {
|
|
var ptr = start
|
|
var obj = {}
|
|
while (ptr + 2 <= end) {
|
|
var descriptor = exports.Descriptor.decode(buf, ptr, end)
|
|
ptr += descriptor.length
|
|
var tagName = tagToName[descriptor.tag] || ('Descriptor' + descriptor.tag)
|
|
obj[tagName] = descriptor
|
|
}
|
|
return obj
|
|
}
|
|
|
|
exports.ESDescriptor = {}
|
|
exports.ESDescriptor.decode = function (buf, start, end) {
|
|
var flags = buf.readUInt8(start + 2)
|
|
var ptr = start + 3
|
|
if (flags & 0x80) {
|
|
ptr += 2
|
|
}
|
|
if (flags & 0x40) {
|
|
var len = buf.readUInt8(ptr)
|
|
ptr += len + 1
|
|
}
|
|
if (flags & 0x20) {
|
|
ptr += 2
|
|
}
|
|
return exports.DescriptorArray.decode(buf, ptr, end)
|
|
}
|
|
|
|
exports.DecoderConfigDescriptor = {}
|
|
exports.DecoderConfigDescriptor.decode = function (buf, start, end) {
|
|
var oti = buf.readUInt8(start)
|
|
var obj = exports.DescriptorArray.decode(buf, start + 13, end)
|
|
obj.oti = oti
|
|
return obj
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mp4-box-encoding/index.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/mp4-box-encoding/index.js ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
// var assert = require('assert')
|
|
var uint64be = __webpack_require__(/*! uint64be */ "./node_modules/uint64be/index.js")
|
|
|
|
var boxes = __webpack_require__(/*! ./boxes */ "./node_modules/mp4-box-encoding/boxes.js")
|
|
|
|
var UINT32_MAX = 4294967295
|
|
|
|
var Box = exports
|
|
|
|
/*
|
|
* Lists the proper order for boxes inside containers.
|
|
* Five-character names ending in 's' indicate arrays instead of single elements.
|
|
*/
|
|
var containers = exports.containers = {
|
|
'moov': ['mvhd', 'meta', 'traks', 'mvex'],
|
|
'trak': ['tkhd', 'tref', 'trgr', 'edts', 'meta', 'mdia', 'udta'],
|
|
'edts': ['elst'],
|
|
'mdia': ['mdhd', 'hdlr', 'elng', 'minf'],
|
|
'minf': ['vmhd', 'smhd', 'hmhd', 'sthd', 'nmhd', 'dinf', 'stbl'],
|
|
'dinf': ['dref'],
|
|
'stbl': ['stsd', 'stts', 'ctts', 'cslg', 'stsc', 'stsz', 'stz2', 'stco', 'co64', 'stss', 'stsh', 'padb', 'stdp', 'sdtp', 'sbgps', 'sgpds', 'subss', 'saizs', 'saios'],
|
|
'mvex': ['mehd', 'trexs', 'leva'],
|
|
'moof': ['mfhd', 'meta', 'trafs'],
|
|
'traf': ['tfhd', 'tfdt', 'trun', 'sbgps', 'sgpds', 'subss', 'saizs', 'saios', 'meta']
|
|
}
|
|
|
|
Box.encode = function (obj, buffer, offset) {
|
|
Box.encodingLength(obj) // sets every level appropriately
|
|
offset = offset || 0
|
|
buffer = buffer || Buffer.alloc(obj.length)
|
|
return Box._encode(obj, buffer, offset)
|
|
}
|
|
|
|
Box._encode = function (obj, buffer, offset) {
|
|
var type = obj.type
|
|
var len = obj.length
|
|
if (len > UINT32_MAX) {
|
|
len = 1
|
|
}
|
|
buffer.writeUInt32BE(len, offset)
|
|
buffer.write(obj.type, offset + 4, 4, 'ascii')
|
|
var ptr = offset + 8
|
|
if (len === 1) {
|
|
uint64be.encode(obj.length, buffer, ptr)
|
|
ptr += 8
|
|
}
|
|
if (boxes.fullBoxes[type]) {
|
|
buffer.writeUInt32BE(obj.flags || 0, ptr)
|
|
buffer.writeUInt8(obj.version || 0, ptr)
|
|
ptr += 4
|
|
}
|
|
|
|
if (containers[type]) {
|
|
var contents = containers[type]
|
|
contents.forEach(function (childType) {
|
|
if (childType.length === 5) {
|
|
var entry = obj[childType] || []
|
|
childType = childType.substr(0, 4)
|
|
entry.forEach(function (child) {
|
|
Box._encode(child, buffer, ptr)
|
|
ptr += Box.encode.bytes
|
|
})
|
|
} else if (obj[childType]) {
|
|
Box._encode(obj[childType], buffer, ptr)
|
|
ptr += Box.encode.bytes
|
|
}
|
|
})
|
|
if (obj.otherBoxes) {
|
|
obj.otherBoxes.forEach(function (child) {
|
|
Box._encode(child, buffer, ptr)
|
|
ptr += Box.encode.bytes
|
|
})
|
|
}
|
|
} else if (boxes[type]) {
|
|
var encode = boxes[type].encode
|
|
encode(obj, buffer, ptr)
|
|
ptr += encode.bytes
|
|
} else if (obj.buffer) {
|
|
var buf = obj.buffer
|
|
buf.copy(buffer, ptr)
|
|
ptr += obj.buffer.length
|
|
} else {
|
|
throw new Error('Either `type` must be set to a known type (not\'' + type + '\') or `buffer` must be set')
|
|
}
|
|
|
|
Box.encode.bytes = ptr - offset
|
|
// assert.equal(ptr - offset, obj.length, 'Error encoding \'' + type + '\': wrote ' + ptr - offset + ' bytes, expecting ' + obj.length)
|
|
return buffer
|
|
}
|
|
|
|
/*
|
|
* Returns an object with `type` and `size` fields,
|
|
* or if there isn't enough data, returns the total
|
|
* number of bytes needed to read the headers
|
|
*/
|
|
Box.readHeaders = function (buffer, start, end) {
|
|
start = start || 0
|
|
end = end || buffer.length
|
|
if (end - start < 8) {
|
|
return 8
|
|
}
|
|
|
|
var len = buffer.readUInt32BE(start)
|
|
var type = buffer.toString('ascii', start + 4, start + 8)
|
|
var ptr = start + 8
|
|
|
|
if (len === 1) {
|
|
if (end - start < 16) {
|
|
return 16
|
|
}
|
|
|
|
len = uint64be.decode(buffer, ptr)
|
|
ptr += 8
|
|
}
|
|
|
|
var version
|
|
var flags
|
|
if (boxes.fullBoxes[type]) {
|
|
version = buffer.readUInt8(ptr)
|
|
flags = buffer.readUInt32BE(ptr) & 0xffffff
|
|
ptr += 4
|
|
}
|
|
|
|
return {
|
|
length: len,
|
|
headersLen: ptr - start,
|
|
contentLen: len - (ptr - start),
|
|
type: type,
|
|
version: version,
|
|
flags: flags
|
|
}
|
|
}
|
|
|
|
Box.decode = function (buffer, start, end) {
|
|
start = start || 0
|
|
end = end || buffer.length
|
|
var headers = Box.readHeaders(buffer, start, end)
|
|
if (!headers || headers.length > end - start) {
|
|
throw new Error('Data too short')
|
|
}
|
|
|
|
return Box.decodeWithoutHeaders(headers, buffer, start + headers.headersLen, start + headers.length)
|
|
}
|
|
|
|
Box.decodeWithoutHeaders = function (headers, buffer, start, end) {
|
|
start = start || 0
|
|
end = end || buffer.length
|
|
var type = headers.type
|
|
var obj = {}
|
|
if (containers[type]) {
|
|
obj.otherBoxes = []
|
|
var contents = containers[type]
|
|
var ptr = start
|
|
while (end - ptr >= 8) {
|
|
var child = Box.decode(buffer, ptr, end)
|
|
ptr += child.length
|
|
if (contents.indexOf(child.type) >= 0) {
|
|
obj[child.type] = child
|
|
} else if (contents.indexOf(child.type + 's') >= 0) {
|
|
var childType = child.type + 's'
|
|
var entry = obj[childType] = obj[childType] || []
|
|
entry.push(child)
|
|
} else {
|
|
obj.otherBoxes.push(child)
|
|
}
|
|
}
|
|
} else if (boxes[type]) {
|
|
var decode = boxes[type].decode
|
|
obj = decode(buffer, start, end)
|
|
} else {
|
|
obj.buffer = Buffer.from(buffer.slice(start, end))
|
|
}
|
|
|
|
obj.length = headers.length
|
|
obj.contentLen = headers.contentLen
|
|
obj.type = headers.type
|
|
obj.version = headers.version
|
|
obj.flags = headers.flags
|
|
return obj
|
|
}
|
|
|
|
Box.encodingLength = function (obj) {
|
|
var type = obj.type
|
|
|
|
var len = 8
|
|
if (boxes.fullBoxes[type]) {
|
|
len += 4
|
|
}
|
|
|
|
if (containers[type]) {
|
|
var contents = containers[type]
|
|
contents.forEach(function (childType) {
|
|
if (childType.length === 5) {
|
|
var entry = obj[childType] || []
|
|
childType = childType.substr(0, 4)
|
|
entry.forEach(function (child) {
|
|
child.type = childType
|
|
len += Box.encodingLength(child)
|
|
})
|
|
} else if (obj[childType]) {
|
|
var child = obj[childType]
|
|
child.type = childType
|
|
len += Box.encodingLength(child)
|
|
}
|
|
})
|
|
if (obj.otherBoxes) {
|
|
obj.otherBoxes.forEach(function (child) {
|
|
len += Box.encodingLength(child)
|
|
})
|
|
}
|
|
} else if (boxes[type]) {
|
|
len += boxes[type].encodingLength(obj)
|
|
} else if (obj.buffer) {
|
|
len += obj.buffer.length
|
|
} else {
|
|
throw new Error('Either `type` must be set to a known type (not\'' + type + '\') or `buffer` must be set')
|
|
}
|
|
|
|
if (len > UINT32_MAX) {
|
|
len += 8
|
|
}
|
|
|
|
obj.length = len
|
|
return len
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mp4-stream/decode.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/mp4-stream/decode.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
var stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
var nextEvent = __webpack_require__(/*! next-event */ "./node_modules/next-event/index.js")
|
|
var Box = __webpack_require__(/*! mp4-box-encoding */ "./node_modules/mp4-box-encoding/index.js")
|
|
|
|
var EMPTY = Buffer.alloc(0)
|
|
|
|
class Decoder extends stream.Writable {
|
|
constructor (opts) {
|
|
super(opts)
|
|
|
|
this.destroyed = false
|
|
|
|
this._pending = 0
|
|
this._missing = 0
|
|
this._ignoreEmpty = false
|
|
this._buf = null
|
|
this._str = null
|
|
this._cb = null
|
|
this._ondrain = null
|
|
this._writeBuffer = null
|
|
this._writeCb = null
|
|
|
|
this._ondrain = null
|
|
this._kick()
|
|
}
|
|
|
|
destroy (err) {
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
if (err) this.emit('error', err)
|
|
this.emit('close')
|
|
}
|
|
|
|
_write (data, enc, next) {
|
|
if (this.destroyed) return
|
|
var drained = !this._str || !this._str._writableState.needDrain
|
|
|
|
while (data.length && !this.destroyed) {
|
|
if (!this._missing && !this._ignoreEmpty) {
|
|
this._writeBuffer = data
|
|
this._writeCb = next
|
|
return
|
|
}
|
|
|
|
var consumed = data.length < this._missing ? data.length : this._missing
|
|
if (this._buf) data.copy(this._buf, this._buf.length - this._missing)
|
|
else if (this._str) drained = this._str.write(consumed === data.length ? data : data.slice(0, consumed))
|
|
|
|
this._missing -= consumed
|
|
|
|
if (!this._missing) {
|
|
var buf = this._buf
|
|
var cb = this._cb
|
|
var stream = this._str
|
|
|
|
this._buf = this._cb = this._str = this._ondrain = null
|
|
drained = true
|
|
|
|
this._ignoreEmpty = false
|
|
if (stream) stream.end()
|
|
if (cb) cb(buf)
|
|
}
|
|
|
|
data = consumed === data.length ? EMPTY : data.slice(consumed)
|
|
}
|
|
|
|
if (this._pending && !this._missing) {
|
|
this._writeBuffer = data
|
|
this._writeCb = next
|
|
return
|
|
}
|
|
|
|
if (drained) next()
|
|
else this._ondrain(next)
|
|
}
|
|
|
|
_buffer (size, cb) {
|
|
this._missing = size
|
|
this._buf = Buffer.alloc(size)
|
|
this._cb = cb
|
|
}
|
|
|
|
_stream (size, cb) {
|
|
this._missing = size
|
|
this._str = new MediaData(this)
|
|
this._ondrain = nextEvent(this._str, 'drain')
|
|
this._pending++
|
|
this._str.on('end', () => {
|
|
this._pending--
|
|
this._kick()
|
|
})
|
|
this._cb = cb
|
|
return this._str
|
|
}
|
|
|
|
_readBox () {
|
|
const bufferHeaders = (len, buf) => {
|
|
this._buffer(len, additionalBuf => {
|
|
if (buf) {
|
|
buf = Buffer.concat([buf, additionalBuf])
|
|
} else {
|
|
buf = additionalBuf
|
|
}
|
|
var headers = Box.readHeaders(buf)
|
|
if (typeof headers === 'number') {
|
|
bufferHeaders(headers - buf.length, buf)
|
|
} else {
|
|
this._pending++
|
|
this._headers = headers
|
|
this.emit('box', headers)
|
|
}
|
|
})
|
|
}
|
|
|
|
bufferHeaders(8)
|
|
}
|
|
|
|
stream () {
|
|
if (!this._headers) throw new Error('this function can only be called once after \'box\' is emitted')
|
|
var headers = this._headers
|
|
this._headers = null
|
|
|
|
return this._stream(headers.contentLen, () => {
|
|
this._pending--
|
|
this._kick()
|
|
})
|
|
}
|
|
|
|
decode (cb) {
|
|
if (!this._headers) throw new Error('this function can only be called once after \'box\' is emitted')
|
|
var headers = this._headers
|
|
this._headers = null
|
|
|
|
this._buffer(headers.contentLen, buf => {
|
|
var box = Box.decodeWithoutHeaders(headers, buf)
|
|
cb(box)
|
|
this._pending--
|
|
this._kick()
|
|
})
|
|
}
|
|
|
|
ignore () {
|
|
if (!this._headers) throw new Error('this function can only be called once after \'box\' is emitted')
|
|
var headers = this._headers
|
|
this._headers = null
|
|
|
|
this._missing = headers.contentLen
|
|
if (this._missing === 0) {
|
|
this._ignoreEmpty = true
|
|
}
|
|
this._cb = () => {
|
|
this._pending--
|
|
this._kick()
|
|
}
|
|
}
|
|
|
|
_kick () {
|
|
if (this._pending) return
|
|
if (!this._buf && !this._str) this._readBox()
|
|
if (this._writeBuffer) {
|
|
var next = this._writeCb
|
|
var buffer = this._writeBuffer
|
|
this._writeBuffer = null
|
|
this._writeCb = null
|
|
this._write(buffer, null, next)
|
|
}
|
|
}
|
|
}
|
|
|
|
class MediaData extends stream.PassThrough {
|
|
constructor (parent) {
|
|
super()
|
|
this._parent = parent
|
|
this.destroyed = false
|
|
}
|
|
|
|
destroy (err) {
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
this._parent.destroy(err)
|
|
if (err) this.emit('error', err)
|
|
this.emit('close')
|
|
}
|
|
}
|
|
|
|
module.exports = Decoder
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mp4-stream/encode.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/mp4-stream/encode.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
var stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
var Box = __webpack_require__(/*! mp4-box-encoding */ "./node_modules/mp4-box-encoding/index.js")
|
|
var queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
|
|
function noop () {}
|
|
|
|
class Encoder extends stream.Readable {
|
|
constructor (opts) {
|
|
super(opts)
|
|
|
|
this.destroyed = false
|
|
|
|
this._finalized = false
|
|
this._reading = false
|
|
this._stream = null
|
|
this._drain = null
|
|
this._want = false
|
|
|
|
this._onreadable = () => {
|
|
if (!this._want) return
|
|
this._want = false
|
|
this._read()
|
|
}
|
|
|
|
this._onend = () => {
|
|
this._stream = null
|
|
}
|
|
}
|
|
|
|
mdat (size, cb) {
|
|
this.mediaData(size, cb)
|
|
}
|
|
|
|
mediaData (size, cb) {
|
|
var stream = new MediaData(this)
|
|
this.box({ type: 'mdat', contentLength: size, encodeBufferLen: 8, stream: stream }, cb)
|
|
return stream
|
|
}
|
|
|
|
box (box, cb) {
|
|
if (!cb) cb = noop
|
|
if (this.destroyed) return cb(new Error('Encoder is destroyed'))
|
|
|
|
var buf
|
|
if (box.encodeBufferLen) {
|
|
buf = Buffer.alloc(box.encodeBufferLen)
|
|
}
|
|
if (box.stream) {
|
|
box.buffer = null
|
|
buf = Box.encode(box, buf)
|
|
this.push(buf)
|
|
this._stream = box.stream
|
|
this._stream.on('readable', this._onreadable)
|
|
this._stream.on('end', this._onend)
|
|
this._stream.on('end', cb)
|
|
this._forward()
|
|
} else {
|
|
buf = Box.encode(box, buf)
|
|
var drained = this.push(buf)
|
|
if (drained) return queueMicrotask(cb)
|
|
this._drain = cb
|
|
}
|
|
}
|
|
|
|
destroy (err) {
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
if (this._stream && this._stream.destroy) this._stream.destroy()
|
|
this._stream = null
|
|
if (this._drain) {
|
|
var cb = this._drain
|
|
this._drain = null
|
|
cb(err)
|
|
}
|
|
if (err) this.emit('error', err)
|
|
this.emit('close')
|
|
}
|
|
|
|
finalize () {
|
|
this._finalized = true
|
|
if (!this._stream && !this._drain) {
|
|
this.push(null)
|
|
}
|
|
}
|
|
|
|
_forward () {
|
|
if (!this._stream) return
|
|
|
|
while (!this.destroyed) {
|
|
var buf = this._stream.read()
|
|
|
|
if (!buf) {
|
|
this._want = !!this._stream
|
|
return
|
|
}
|
|
|
|
if (!this.push(buf)) return
|
|
}
|
|
}
|
|
|
|
_read () {
|
|
if (this._reading || this.destroyed) return
|
|
this._reading = true
|
|
|
|
if (this._stream) this._forward()
|
|
if (this._drain) {
|
|
var drain = this._drain
|
|
this._drain = null
|
|
drain()
|
|
}
|
|
|
|
this._reading = false
|
|
if (this._finalized) {
|
|
this.push(null)
|
|
}
|
|
}
|
|
}
|
|
|
|
class MediaData extends stream.PassThrough {
|
|
constructor (parent) {
|
|
super()
|
|
this._parent = parent
|
|
this.destroyed = false
|
|
}
|
|
|
|
destroy (err) {
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
this._parent.destroy(err)
|
|
if (err) this.emit('error', err)
|
|
this.emit('close')
|
|
}
|
|
}
|
|
|
|
module.exports = Encoder
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/mp4-stream/index.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/mp4-stream/index.js ***!
|
|
\******************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
const Decoder = __webpack_require__(/*! ./decode */ "./node_modules/mp4-stream/decode.js")
|
|
const Encoder = __webpack_require__(/*! ./encode */ "./node_modules/mp4-stream/encode.js")
|
|
|
|
exports.decode = opts => new Decoder(opts)
|
|
exports.encode = opts => new Encoder(opts)
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ms/index.js":
|
|
/*!**********************************!*\
|
|
!*** ./node_modules/ms/index.js ***!
|
|
\**********************************/
|
|
/***/ ((module) => {
|
|
|
|
/**
|
|
* Helpers.
|
|
*/
|
|
|
|
var s = 1000;
|
|
var m = s * 60;
|
|
var h = m * 60;
|
|
var d = h * 24;
|
|
var w = d * 7;
|
|
var y = d * 365.25;
|
|
|
|
/**
|
|
* Parse or format the given `val`.
|
|
*
|
|
* Options:
|
|
*
|
|
* - `long` verbose formatting [false]
|
|
*
|
|
* @param {String|Number} val
|
|
* @param {Object} [options]
|
|
* @throws {Error} throw an error if val is not a non-empty string or a number
|
|
* @return {String|Number}
|
|
* @api public
|
|
*/
|
|
|
|
module.exports = function(val, options) {
|
|
options = options || {};
|
|
var type = typeof val;
|
|
if (type === 'string' && val.length > 0) {
|
|
return parse(val);
|
|
} else if (type === 'number' && isFinite(val)) {
|
|
return options.long ? fmtLong(val) : fmtShort(val);
|
|
}
|
|
throw new Error(
|
|
'val is not a non-empty string or a valid number. val=' +
|
|
JSON.stringify(val)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Parse the given `str` and return milliseconds.
|
|
*
|
|
* @param {String} str
|
|
* @return {Number}
|
|
* @api private
|
|
*/
|
|
|
|
function parse(str) {
|
|
str = String(str);
|
|
if (str.length > 100) {
|
|
return;
|
|
}
|
|
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
|
|
str
|
|
);
|
|
if (!match) {
|
|
return;
|
|
}
|
|
var n = parseFloat(match[1]);
|
|
var type = (match[2] || 'ms').toLowerCase();
|
|
switch (type) {
|
|
case 'years':
|
|
case 'year':
|
|
case 'yrs':
|
|
case 'yr':
|
|
case 'y':
|
|
return n * y;
|
|
case 'weeks':
|
|
case 'week':
|
|
case 'w':
|
|
return n * w;
|
|
case 'days':
|
|
case 'day':
|
|
case 'd':
|
|
return n * d;
|
|
case 'hours':
|
|
case 'hour':
|
|
case 'hrs':
|
|
case 'hr':
|
|
case 'h':
|
|
return n * h;
|
|
case 'minutes':
|
|
case 'minute':
|
|
case 'mins':
|
|
case 'min':
|
|
case 'm':
|
|
return n * m;
|
|
case 'seconds':
|
|
case 'second':
|
|
case 'secs':
|
|
case 'sec':
|
|
case 's':
|
|
return n * s;
|
|
case 'milliseconds':
|
|
case 'millisecond':
|
|
case 'msecs':
|
|
case 'msec':
|
|
case 'ms':
|
|
return n;
|
|
default:
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Short format for `ms`.
|
|
*
|
|
* @param {Number} ms
|
|
* @return {String}
|
|
* @api private
|
|
*/
|
|
|
|
function fmtShort(ms) {
|
|
var msAbs = Math.abs(ms);
|
|
if (msAbs >= d) {
|
|
return Math.round(ms / d) + 'd';
|
|
}
|
|
if (msAbs >= h) {
|
|
return Math.round(ms / h) + 'h';
|
|
}
|
|
if (msAbs >= m) {
|
|
return Math.round(ms / m) + 'm';
|
|
}
|
|
if (msAbs >= s) {
|
|
return Math.round(ms / s) + 's';
|
|
}
|
|
return ms + 'ms';
|
|
}
|
|
|
|
/**
|
|
* Long format for `ms`.
|
|
*
|
|
* @param {Number} ms
|
|
* @return {String}
|
|
* @api private
|
|
*/
|
|
|
|
function fmtLong(ms) {
|
|
var msAbs = Math.abs(ms);
|
|
if (msAbs >= d) {
|
|
return plural(ms, msAbs, d, 'day');
|
|
}
|
|
if (msAbs >= h) {
|
|
return plural(ms, msAbs, h, 'hour');
|
|
}
|
|
if (msAbs >= m) {
|
|
return plural(ms, msAbs, m, 'minute');
|
|
}
|
|
if (msAbs >= s) {
|
|
return plural(ms, msAbs, s, 'second');
|
|
}
|
|
return ms + ' ms';
|
|
}
|
|
|
|
/**
|
|
* Pluralization helper.
|
|
*/
|
|
|
|
function plural(ms, msAbs, n, name) {
|
|
var isPlural = msAbs >= n * 1.5;
|
|
return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/multistream/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/multistream/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*! multistream. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
const stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
const once = __webpack_require__(/*! once */ "./node_modules/once/once.js")
|
|
|
|
function toStreams2Obj (s) {
|
|
return toStreams2(s, { objectMode: true, highWaterMark: 16 })
|
|
}
|
|
|
|
function toStreams2Buf (s) {
|
|
return toStreams2(s)
|
|
}
|
|
|
|
function toStreams2 (s, opts) {
|
|
if (!s || typeof s === 'function' || s._readableState) return s
|
|
|
|
const wrap = new stream.Readable(opts).wrap(s)
|
|
if (s.destroy) {
|
|
wrap.destroy = s.destroy.bind(s)
|
|
}
|
|
return wrap
|
|
}
|
|
|
|
class MultiStream extends stream.Readable {
|
|
constructor (streams, opts) {
|
|
super({ ...opts, autoDestroy: true })
|
|
|
|
this._drained = false
|
|
this._forwarding = false
|
|
this._current = null
|
|
this._toStreams2 = (opts && opts.objectMode) ? toStreams2Obj : toStreams2Buf
|
|
|
|
if (typeof streams === 'function') {
|
|
this._queue = streams
|
|
} else {
|
|
this._queue = streams.map(this._toStreams2)
|
|
this._queue.forEach(stream => {
|
|
if (typeof stream !== 'function') this._attachErrorListener(stream)
|
|
})
|
|
}
|
|
|
|
this._next()
|
|
}
|
|
|
|
_read () {
|
|
this._drained = true
|
|
this._forward()
|
|
}
|
|
|
|
_forward () {
|
|
if (this._forwarding || !this._drained || !this._current) return
|
|
this._forwarding = true
|
|
|
|
let chunk
|
|
while (this._drained && (chunk = this._current.read()) !== null) {
|
|
this._drained = this.push(chunk)
|
|
}
|
|
|
|
this._forwarding = false
|
|
}
|
|
|
|
_destroy (err, cb) {
|
|
let streams = []
|
|
if (this._current) streams.push(this._current)
|
|
if (typeof this._queue !== 'function') streams = streams.concat(this._queue)
|
|
|
|
if (streams.length === 0) {
|
|
cb(err)
|
|
} else {
|
|
let counter = streams.length
|
|
let er = err
|
|
streams.forEach(stream => {
|
|
destroy(stream, err, err => {
|
|
er = er || err
|
|
if (--counter === 0) {
|
|
cb(er)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
_next () {
|
|
this._current = null
|
|
|
|
if (typeof this._queue === 'function') {
|
|
this._queue((err, stream) => {
|
|
if (err) return this.destroy(err)
|
|
stream = this._toStreams2(stream)
|
|
this._attachErrorListener(stream)
|
|
this._gotNextStream(stream)
|
|
})
|
|
} else {
|
|
let stream = this._queue.shift()
|
|
if (typeof stream === 'function') {
|
|
stream = this._toStreams2(stream())
|
|
this._attachErrorListener(stream)
|
|
}
|
|
this._gotNextStream(stream)
|
|
}
|
|
}
|
|
|
|
_gotNextStream (stream) {
|
|
if (!stream) {
|
|
this.push(null)
|
|
return
|
|
}
|
|
|
|
this._current = stream
|
|
this._forward()
|
|
|
|
const onReadable = () => {
|
|
this._forward()
|
|
}
|
|
|
|
const onClose = () => {
|
|
if (!stream._readableState.ended && !stream.destroyed) {
|
|
const err = new Error('ERR_STREAM_PREMATURE_CLOSE')
|
|
err.code = 'ERR_STREAM_PREMATURE_CLOSE'
|
|
this.destroy(err)
|
|
}
|
|
}
|
|
|
|
const onEnd = () => {
|
|
this._current = null
|
|
stream.removeListener('readable', onReadable)
|
|
stream.removeListener('end', onEnd)
|
|
stream.removeListener('close', onClose)
|
|
stream.destroy()
|
|
this._next()
|
|
}
|
|
|
|
stream.on('readable', onReadable)
|
|
stream.once('end', onEnd)
|
|
stream.once('close', onClose)
|
|
}
|
|
|
|
_attachErrorListener (stream) {
|
|
if (!stream) return
|
|
|
|
const onError = (err) => {
|
|
stream.removeListener('error', onError)
|
|
this.destroy(err)
|
|
}
|
|
|
|
stream.once('error', onError)
|
|
}
|
|
}
|
|
|
|
MultiStream.obj = streams => (
|
|
new MultiStream(streams, { objectMode: true, highWaterMark: 16 })
|
|
)
|
|
|
|
module.exports = MultiStream
|
|
|
|
// Normalize stream destroy w/ callback.
|
|
function destroy (stream, err, cb) {
|
|
if (!stream.destroy || stream.destroyed) {
|
|
cb(err)
|
|
} else {
|
|
const callback = once(er => cb(er || err))
|
|
stream
|
|
.on('error', callback)
|
|
.on('close', () => callback())
|
|
.destroy(err, callback)
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/next-event/index.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/next-event/index.js ***!
|
|
\******************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = nextEvent
|
|
|
|
function nextEvent (emitter, name) {
|
|
var next = null
|
|
emitter.on(name, function (data) {
|
|
if (!next) return
|
|
var fn = next
|
|
next = null
|
|
fn(data)
|
|
})
|
|
|
|
return function (once) {
|
|
next = once
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/object-is/implementation.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/object-is/implementation.js ***!
|
|
\**************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var numberIsNaN = function (value) {
|
|
return value !== value;
|
|
};
|
|
|
|
module.exports = function is(a, b) {
|
|
if (a === 0 && b === 0) {
|
|
return 1 / a === 1 / b;
|
|
}
|
|
if (a === b) {
|
|
return true;
|
|
}
|
|
if (numberIsNaN(a) && numberIsNaN(b)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/object-is/index.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/object-is/index.js ***!
|
|
\*****************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var define = __webpack_require__(/*! define-properties */ "./node_modules/define-properties/index.js");
|
|
var callBind = __webpack_require__(/*! call-bind */ "./node_modules/call-bind/index.js");
|
|
|
|
var implementation = __webpack_require__(/*! ./implementation */ "./node_modules/object-is/implementation.js");
|
|
var getPolyfill = __webpack_require__(/*! ./polyfill */ "./node_modules/object-is/polyfill.js");
|
|
var shim = __webpack_require__(/*! ./shim */ "./node_modules/object-is/shim.js");
|
|
|
|
var polyfill = callBind(getPolyfill(), Object);
|
|
|
|
define(polyfill, {
|
|
getPolyfill: getPolyfill,
|
|
implementation: implementation,
|
|
shim: shim
|
|
});
|
|
|
|
module.exports = polyfill;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/object-is/polyfill.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/object-is/polyfill.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var implementation = __webpack_require__(/*! ./implementation */ "./node_modules/object-is/implementation.js");
|
|
|
|
module.exports = function getPolyfill() {
|
|
return typeof Object.is === 'function' ? Object.is : implementation;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/object-is/shim.js":
|
|
/*!****************************************!*\
|
|
!*** ./node_modules/object-is/shim.js ***!
|
|
\****************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var getPolyfill = __webpack_require__(/*! ./polyfill */ "./node_modules/object-is/polyfill.js");
|
|
var define = __webpack_require__(/*! define-properties */ "./node_modules/define-properties/index.js");
|
|
|
|
module.exports = function shimObjectIs() {
|
|
var polyfill = getPolyfill();
|
|
define(Object, { is: polyfill }, {
|
|
is: function testObjectIs() {
|
|
return Object.is !== polyfill;
|
|
}
|
|
});
|
|
return polyfill;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/object-keys/implementation.js":
|
|
/*!****************************************************!*\
|
|
!*** ./node_modules/object-keys/implementation.js ***!
|
|
\****************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var keysShim;
|
|
if (!Object.keys) {
|
|
// modified from https://github.com/es-shims/es5-shim
|
|
var has = Object.prototype.hasOwnProperty;
|
|
var toStr = Object.prototype.toString;
|
|
var isArgs = __webpack_require__(/*! ./isArguments */ "./node_modules/object-keys/isArguments.js"); // eslint-disable-line global-require
|
|
var isEnumerable = Object.prototype.propertyIsEnumerable;
|
|
var hasDontEnumBug = !isEnumerable.call({ toString: null }, 'toString');
|
|
var hasProtoEnumBug = isEnumerable.call(function () {}, 'prototype');
|
|
var dontEnums = [
|
|
'toString',
|
|
'toLocaleString',
|
|
'valueOf',
|
|
'hasOwnProperty',
|
|
'isPrototypeOf',
|
|
'propertyIsEnumerable',
|
|
'constructor'
|
|
];
|
|
var equalsConstructorPrototype = function (o) {
|
|
var ctor = o.constructor;
|
|
return ctor && ctor.prototype === o;
|
|
};
|
|
var excludedKeys = {
|
|
$applicationCache: true,
|
|
$console: true,
|
|
$external: true,
|
|
$frame: true,
|
|
$frameElement: true,
|
|
$frames: true,
|
|
$innerHeight: true,
|
|
$innerWidth: true,
|
|
$onmozfullscreenchange: true,
|
|
$onmozfullscreenerror: true,
|
|
$outerHeight: true,
|
|
$outerWidth: true,
|
|
$pageXOffset: true,
|
|
$pageYOffset: true,
|
|
$parent: true,
|
|
$scrollLeft: true,
|
|
$scrollTop: true,
|
|
$scrollX: true,
|
|
$scrollY: true,
|
|
$self: true,
|
|
$webkitIndexedDB: true,
|
|
$webkitStorageInfo: true,
|
|
$window: true
|
|
};
|
|
var hasAutomationEqualityBug = (function () {
|
|
/* global window */
|
|
if (typeof window === 'undefined') { return false; }
|
|
for (var k in window) {
|
|
try {
|
|
if (!excludedKeys['$' + k] && has.call(window, k) && window[k] !== null && typeof window[k] === 'object') {
|
|
try {
|
|
equalsConstructorPrototype(window[k]);
|
|
} catch (e) {
|
|
return true;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}());
|
|
var equalsConstructorPrototypeIfNotBuggy = function (o) {
|
|
/* global window */
|
|
if (typeof window === 'undefined' || !hasAutomationEqualityBug) {
|
|
return equalsConstructorPrototype(o);
|
|
}
|
|
try {
|
|
return equalsConstructorPrototype(o);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
keysShim = function keys(object) {
|
|
var isObject = object !== null && typeof object === 'object';
|
|
var isFunction = toStr.call(object) === '[object Function]';
|
|
var isArguments = isArgs(object);
|
|
var isString = isObject && toStr.call(object) === '[object String]';
|
|
var theKeys = [];
|
|
|
|
if (!isObject && !isFunction && !isArguments) {
|
|
throw new TypeError('Object.keys called on a non-object');
|
|
}
|
|
|
|
var skipProto = hasProtoEnumBug && isFunction;
|
|
if (isString && object.length > 0 && !has.call(object, 0)) {
|
|
for (var i = 0; i < object.length; ++i) {
|
|
theKeys.push(String(i));
|
|
}
|
|
}
|
|
|
|
if (isArguments && object.length > 0) {
|
|
for (var j = 0; j < object.length; ++j) {
|
|
theKeys.push(String(j));
|
|
}
|
|
} else {
|
|
for (var name in object) {
|
|
if (!(skipProto && name === 'prototype') && has.call(object, name)) {
|
|
theKeys.push(String(name));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hasDontEnumBug) {
|
|
var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);
|
|
|
|
for (var k = 0; k < dontEnums.length; ++k) {
|
|
if (!(skipConstructor && dontEnums[k] === 'constructor') && has.call(object, dontEnums[k])) {
|
|
theKeys.push(dontEnums[k]);
|
|
}
|
|
}
|
|
}
|
|
return theKeys;
|
|
};
|
|
}
|
|
module.exports = keysShim;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/object-keys/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/object-keys/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var slice = Array.prototype.slice;
|
|
var isArgs = __webpack_require__(/*! ./isArguments */ "./node_modules/object-keys/isArguments.js");
|
|
|
|
var origKeys = Object.keys;
|
|
var keysShim = origKeys ? function keys(o) { return origKeys(o); } : __webpack_require__(/*! ./implementation */ "./node_modules/object-keys/implementation.js");
|
|
|
|
var originalKeys = Object.keys;
|
|
|
|
keysShim.shim = function shimObjectKeys() {
|
|
if (Object.keys) {
|
|
var keysWorksWithArguments = (function () {
|
|
// Safari 5.0 bug
|
|
var args = Object.keys(arguments);
|
|
return args && args.length === arguments.length;
|
|
}(1, 2));
|
|
if (!keysWorksWithArguments) {
|
|
Object.keys = function keys(object) { // eslint-disable-line func-name-matching
|
|
if (isArgs(object)) {
|
|
return originalKeys(slice.call(object));
|
|
}
|
|
return originalKeys(object);
|
|
};
|
|
}
|
|
} else {
|
|
Object.keys = keysShim;
|
|
}
|
|
return Object.keys || keysShim;
|
|
};
|
|
|
|
module.exports = keysShim;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/object-keys/isArguments.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/object-keys/isArguments.js ***!
|
|
\*************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var toStr = Object.prototype.toString;
|
|
|
|
module.exports = function isArguments(value) {
|
|
var str = toStr.call(value);
|
|
var isArgs = str === '[object Arguments]';
|
|
if (!isArgs) {
|
|
isArgs = str !== '[object Array]' &&
|
|
value !== null &&
|
|
typeof value === 'object' &&
|
|
typeof value.length === 'number' &&
|
|
value.length >= 0 &&
|
|
toStr.call(value.callee) === '[object Function]';
|
|
}
|
|
return isArgs;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/once/once.js":
|
|
/*!***********************************!*\
|
|
!*** ./node_modules/once/once.js ***!
|
|
\***********************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var wrappy = __webpack_require__(/*! wrappy */ "./node_modules/wrappy/wrappy.js")
|
|
module.exports = wrappy(once)
|
|
module.exports.strict = wrappy(onceStrict)
|
|
|
|
once.proto = once(function () {
|
|
Object.defineProperty(Function.prototype, 'once', {
|
|
value: function () {
|
|
return once(this)
|
|
},
|
|
configurable: true
|
|
})
|
|
|
|
Object.defineProperty(Function.prototype, 'onceStrict', {
|
|
value: function () {
|
|
return onceStrict(this)
|
|
},
|
|
configurable: true
|
|
})
|
|
})
|
|
|
|
function once (fn) {
|
|
var f = function () {
|
|
if (f.called) return f.value
|
|
f.called = true
|
|
return f.value = fn.apply(this, arguments)
|
|
}
|
|
f.called = false
|
|
return f
|
|
}
|
|
|
|
function onceStrict (fn) {
|
|
var f = function () {
|
|
if (f.called)
|
|
throw new Error(f.onceError)
|
|
f.called = true
|
|
return f.value = fn.apply(this, arguments)
|
|
}
|
|
var name = fn.name || 'Function wrapped with `once`'
|
|
f.onceError = name + " shouldn't be called more than once"
|
|
f.called = false
|
|
return f
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/parse-asn1/aesid.json":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/parse-asn1/aesid.json ***!
|
|
\********************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = JSON.parse('{"2.16.840.1.101.3.4.1.1":"aes-128-ecb","2.16.840.1.101.3.4.1.2":"aes-128-cbc","2.16.840.1.101.3.4.1.3":"aes-128-ofb","2.16.840.1.101.3.4.1.4":"aes-128-cfb","2.16.840.1.101.3.4.1.21":"aes-192-ecb","2.16.840.1.101.3.4.1.22":"aes-192-cbc","2.16.840.1.101.3.4.1.23":"aes-192-ofb","2.16.840.1.101.3.4.1.24":"aes-192-cfb","2.16.840.1.101.3.4.1.41":"aes-256-ecb","2.16.840.1.101.3.4.1.42":"aes-256-cbc","2.16.840.1.101.3.4.1.43":"aes-256-ofb","2.16.840.1.101.3.4.1.44":"aes-256-cfb"}');
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/parse-asn1/asn1.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/parse-asn1/asn1.js ***!
|
|
\*****************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// from https://github.com/indutny/self-signed/blob/gh-pages/lib/asn1.js
|
|
// Fedor, you are amazing.
|
|
|
|
|
|
var asn1 = __webpack_require__(/*! asn1.js */ "./node_modules/asn1.js/lib/asn1.js")
|
|
|
|
exports.certificate = __webpack_require__(/*! ./certificate */ "./node_modules/parse-asn1/certificate.js")
|
|
|
|
var RSAPrivateKey = asn1.define('RSAPrivateKey', function () {
|
|
this.seq().obj(
|
|
this.key('version').int(),
|
|
this.key('modulus').int(),
|
|
this.key('publicExponent').int(),
|
|
this.key('privateExponent').int(),
|
|
this.key('prime1').int(),
|
|
this.key('prime2').int(),
|
|
this.key('exponent1').int(),
|
|
this.key('exponent2').int(),
|
|
this.key('coefficient').int()
|
|
)
|
|
})
|
|
exports.RSAPrivateKey = RSAPrivateKey
|
|
|
|
var RSAPublicKey = asn1.define('RSAPublicKey', function () {
|
|
this.seq().obj(
|
|
this.key('modulus').int(),
|
|
this.key('publicExponent').int()
|
|
)
|
|
})
|
|
exports.RSAPublicKey = RSAPublicKey
|
|
|
|
var PublicKey = asn1.define('SubjectPublicKeyInfo', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').use(AlgorithmIdentifier),
|
|
this.key('subjectPublicKey').bitstr()
|
|
)
|
|
})
|
|
exports.PublicKey = PublicKey
|
|
|
|
var AlgorithmIdentifier = asn1.define('AlgorithmIdentifier', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').objid(),
|
|
this.key('none').null_().optional(),
|
|
this.key('curve').objid().optional(),
|
|
this.key('params').seq().obj(
|
|
this.key('p').int(),
|
|
this.key('q').int(),
|
|
this.key('g').int()
|
|
).optional()
|
|
)
|
|
})
|
|
|
|
var PrivateKeyInfo = asn1.define('PrivateKeyInfo', function () {
|
|
this.seq().obj(
|
|
this.key('version').int(),
|
|
this.key('algorithm').use(AlgorithmIdentifier),
|
|
this.key('subjectPrivateKey').octstr()
|
|
)
|
|
})
|
|
exports.PrivateKey = PrivateKeyInfo
|
|
var EncryptedPrivateKeyInfo = asn1.define('EncryptedPrivateKeyInfo', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').seq().obj(
|
|
this.key('id').objid(),
|
|
this.key('decrypt').seq().obj(
|
|
this.key('kde').seq().obj(
|
|
this.key('id').objid(),
|
|
this.key('kdeparams').seq().obj(
|
|
this.key('salt').octstr(),
|
|
this.key('iters').int()
|
|
)
|
|
),
|
|
this.key('cipher').seq().obj(
|
|
this.key('algo').objid(),
|
|
this.key('iv').octstr()
|
|
)
|
|
)
|
|
),
|
|
this.key('subjectPrivateKey').octstr()
|
|
)
|
|
})
|
|
|
|
exports.EncryptedPrivateKey = EncryptedPrivateKeyInfo
|
|
|
|
var DSAPrivateKey = asn1.define('DSAPrivateKey', function () {
|
|
this.seq().obj(
|
|
this.key('version').int(),
|
|
this.key('p').int(),
|
|
this.key('q').int(),
|
|
this.key('g').int(),
|
|
this.key('pub_key').int(),
|
|
this.key('priv_key').int()
|
|
)
|
|
})
|
|
exports.DSAPrivateKey = DSAPrivateKey
|
|
|
|
exports.DSAparam = asn1.define('DSAparam', function () {
|
|
this.int()
|
|
})
|
|
|
|
var ECPrivateKey = asn1.define('ECPrivateKey', function () {
|
|
this.seq().obj(
|
|
this.key('version').int(),
|
|
this.key('privateKey').octstr(),
|
|
this.key('parameters').optional().explicit(0).use(ECParameters),
|
|
this.key('publicKey').optional().explicit(1).bitstr()
|
|
)
|
|
})
|
|
exports.ECPrivateKey = ECPrivateKey
|
|
|
|
var ECParameters = asn1.define('ECParameters', function () {
|
|
this.choice({
|
|
namedCurve: this.objid()
|
|
})
|
|
})
|
|
|
|
exports.signature = asn1.define('signature', function () {
|
|
this.seq().obj(
|
|
this.key('r').int(),
|
|
this.key('s').int()
|
|
)
|
|
})
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/parse-asn1/certificate.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/parse-asn1/certificate.js ***!
|
|
\************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// from https://github.com/Rantanen/node-dtls/blob/25a7dc861bda38cfeac93a723500eea4f0ac2e86/Certificate.js
|
|
// thanks to @Rantanen
|
|
|
|
|
|
|
|
var asn = __webpack_require__(/*! asn1.js */ "./node_modules/asn1.js/lib/asn1.js")
|
|
|
|
var Time = asn.define('Time', function () {
|
|
this.choice({
|
|
utcTime: this.utctime(),
|
|
generalTime: this.gentime()
|
|
})
|
|
})
|
|
|
|
var AttributeTypeValue = asn.define('AttributeTypeValue', function () {
|
|
this.seq().obj(
|
|
this.key('type').objid(),
|
|
this.key('value').any()
|
|
)
|
|
})
|
|
|
|
var AlgorithmIdentifier = asn.define('AlgorithmIdentifier', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').objid(),
|
|
this.key('parameters').optional(),
|
|
this.key('curve').objid().optional()
|
|
)
|
|
})
|
|
|
|
var SubjectPublicKeyInfo = asn.define('SubjectPublicKeyInfo', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').use(AlgorithmIdentifier),
|
|
this.key('subjectPublicKey').bitstr()
|
|
)
|
|
})
|
|
|
|
var RelativeDistinguishedName = asn.define('RelativeDistinguishedName', function () {
|
|
this.setof(AttributeTypeValue)
|
|
})
|
|
|
|
var RDNSequence = asn.define('RDNSequence', function () {
|
|
this.seqof(RelativeDistinguishedName)
|
|
})
|
|
|
|
var Name = asn.define('Name', function () {
|
|
this.choice({
|
|
rdnSequence: this.use(RDNSequence)
|
|
})
|
|
})
|
|
|
|
var Validity = asn.define('Validity', function () {
|
|
this.seq().obj(
|
|
this.key('notBefore').use(Time),
|
|
this.key('notAfter').use(Time)
|
|
)
|
|
})
|
|
|
|
var Extension = asn.define('Extension', function () {
|
|
this.seq().obj(
|
|
this.key('extnID').objid(),
|
|
this.key('critical').bool().def(false),
|
|
this.key('extnValue').octstr()
|
|
)
|
|
})
|
|
|
|
var TBSCertificate = asn.define('TBSCertificate', function () {
|
|
this.seq().obj(
|
|
this.key('version').explicit(0).int().optional(),
|
|
this.key('serialNumber').int(),
|
|
this.key('signature').use(AlgorithmIdentifier),
|
|
this.key('issuer').use(Name),
|
|
this.key('validity').use(Validity),
|
|
this.key('subject').use(Name),
|
|
this.key('subjectPublicKeyInfo').use(SubjectPublicKeyInfo),
|
|
this.key('issuerUniqueID').implicit(1).bitstr().optional(),
|
|
this.key('subjectUniqueID').implicit(2).bitstr().optional(),
|
|
this.key('extensions').explicit(3).seqof(Extension).optional()
|
|
)
|
|
})
|
|
|
|
var X509Certificate = asn.define('X509Certificate', function () {
|
|
this.seq().obj(
|
|
this.key('tbsCertificate').use(TBSCertificate),
|
|
this.key('signatureAlgorithm').use(AlgorithmIdentifier),
|
|
this.key('signatureValue').bitstr()
|
|
)
|
|
})
|
|
|
|
module.exports = X509Certificate
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/parse-asn1/fixProc.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/parse-asn1/fixProc.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
// adapted from https://github.com/apatil/pemstrip
|
|
var findProc = /Proc-Type: 4,ENCRYPTED[\n\r]+DEK-Info: AES-((?:128)|(?:192)|(?:256))-CBC,([0-9A-H]+)[\n\r]+([0-9A-z\n\r+/=]+)[\n\r]+/m
|
|
var startRegex = /^-----BEGIN ((?:.*? KEY)|CERTIFICATE)-----/m
|
|
var fullRegex = /^-----BEGIN ((?:.*? KEY)|CERTIFICATE)-----([0-9A-z\n\r+/=]+)-----END \1-----$/m
|
|
var evp = __webpack_require__(/*! evp_bytestokey */ "./node_modules/evp_bytestokey/index.js")
|
|
var ciphers = __webpack_require__(/*! browserify-aes */ "./node_modules/browserify-aes/browser.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
module.exports = function (okey, password) {
|
|
var key = okey.toString()
|
|
var match = key.match(findProc)
|
|
var decrypted
|
|
if (!match) {
|
|
var match2 = key.match(fullRegex)
|
|
decrypted = Buffer.from(match2[2].replace(/[\r\n]/g, ''), 'base64')
|
|
} else {
|
|
var suite = 'aes' + match[1]
|
|
var iv = Buffer.from(match[2], 'hex')
|
|
var cipherText = Buffer.from(match[3].replace(/[\r\n]/g, ''), 'base64')
|
|
var cipherKey = evp(password, iv.slice(0, 8), parseInt(match[1], 10)).key
|
|
var out = []
|
|
var cipher = ciphers.createDecipheriv(suite, cipherKey, iv)
|
|
out.push(cipher.update(cipherText))
|
|
out.push(cipher.final())
|
|
decrypted = Buffer.concat(out)
|
|
}
|
|
var tag = key.match(startRegex)[1]
|
|
return {
|
|
tag: tag,
|
|
data: decrypted
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/parse-asn1/index.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/parse-asn1/index.js ***!
|
|
\******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var asn1 = __webpack_require__(/*! ./asn1 */ "./node_modules/parse-asn1/asn1.js")
|
|
var aesid = __webpack_require__(/*! ./aesid.json */ "./node_modules/parse-asn1/aesid.json")
|
|
var fixProc = __webpack_require__(/*! ./fixProc */ "./node_modules/parse-asn1/fixProc.js")
|
|
var ciphers = __webpack_require__(/*! browserify-aes */ "./node_modules/browserify-aes/browser.js")
|
|
var compat = __webpack_require__(/*! pbkdf2 */ "./node_modules/pbkdf2/browser.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
module.exports = parseKeys
|
|
|
|
function parseKeys (buffer) {
|
|
var password
|
|
if (typeof buffer === 'object' && !Buffer.isBuffer(buffer)) {
|
|
password = buffer.passphrase
|
|
buffer = buffer.key
|
|
}
|
|
if (typeof buffer === 'string') {
|
|
buffer = Buffer.from(buffer)
|
|
}
|
|
|
|
var stripped = fixProc(buffer, password)
|
|
|
|
var type = stripped.tag
|
|
var data = stripped.data
|
|
var subtype, ndata
|
|
switch (type) {
|
|
case 'CERTIFICATE':
|
|
ndata = asn1.certificate.decode(data, 'der').tbsCertificate.subjectPublicKeyInfo
|
|
// falls through
|
|
case 'PUBLIC KEY':
|
|
if (!ndata) {
|
|
ndata = asn1.PublicKey.decode(data, 'der')
|
|
}
|
|
subtype = ndata.algorithm.algorithm.join('.')
|
|
switch (subtype) {
|
|
case '1.2.840.113549.1.1.1':
|
|
return asn1.RSAPublicKey.decode(ndata.subjectPublicKey.data, 'der')
|
|
case '1.2.840.10045.2.1':
|
|
ndata.subjectPrivateKey = ndata.subjectPublicKey
|
|
return {
|
|
type: 'ec',
|
|
data: ndata
|
|
}
|
|
case '1.2.840.10040.4.1':
|
|
ndata.algorithm.params.pub_key = asn1.DSAparam.decode(ndata.subjectPublicKey.data, 'der')
|
|
return {
|
|
type: 'dsa',
|
|
data: ndata.algorithm.params
|
|
}
|
|
default: throw new Error('unknown key id ' + subtype)
|
|
}
|
|
// throw new Error('unknown key type ' + type)
|
|
case 'ENCRYPTED PRIVATE KEY':
|
|
data = asn1.EncryptedPrivateKey.decode(data, 'der')
|
|
data = decrypt(data, password)
|
|
// falls through
|
|
case 'PRIVATE KEY':
|
|
ndata = asn1.PrivateKey.decode(data, 'der')
|
|
subtype = ndata.algorithm.algorithm.join('.')
|
|
switch (subtype) {
|
|
case '1.2.840.113549.1.1.1':
|
|
return asn1.RSAPrivateKey.decode(ndata.subjectPrivateKey, 'der')
|
|
case '1.2.840.10045.2.1':
|
|
return {
|
|
curve: ndata.algorithm.curve,
|
|
privateKey: asn1.ECPrivateKey.decode(ndata.subjectPrivateKey, 'der').privateKey
|
|
}
|
|
case '1.2.840.10040.4.1':
|
|
ndata.algorithm.params.priv_key = asn1.DSAparam.decode(ndata.subjectPrivateKey, 'der')
|
|
return {
|
|
type: 'dsa',
|
|
params: ndata.algorithm.params
|
|
}
|
|
default: throw new Error('unknown key id ' + subtype)
|
|
}
|
|
// throw new Error('unknown key type ' + type)
|
|
case 'RSA PUBLIC KEY':
|
|
return asn1.RSAPublicKey.decode(data, 'der')
|
|
case 'RSA PRIVATE KEY':
|
|
return asn1.RSAPrivateKey.decode(data, 'der')
|
|
case 'DSA PRIVATE KEY':
|
|
return {
|
|
type: 'dsa',
|
|
params: asn1.DSAPrivateKey.decode(data, 'der')
|
|
}
|
|
case 'EC PRIVATE KEY':
|
|
data = asn1.ECPrivateKey.decode(data, 'der')
|
|
return {
|
|
curve: data.parameters.value,
|
|
privateKey: data.privateKey
|
|
}
|
|
default: throw new Error('unknown key type ' + type)
|
|
}
|
|
}
|
|
parseKeys.signature = asn1.signature
|
|
function decrypt (data, password) {
|
|
var salt = data.algorithm.decrypt.kde.kdeparams.salt
|
|
var iters = parseInt(data.algorithm.decrypt.kde.kdeparams.iters.toString(), 10)
|
|
var algo = aesid[data.algorithm.decrypt.cipher.algo.join('.')]
|
|
var iv = data.algorithm.decrypt.cipher.iv
|
|
var cipherText = data.subjectPrivateKey
|
|
var keylen = parseInt(algo.split('-')[1], 10) / 8
|
|
var key = compat.pbkdf2Sync(password, salt, iters, keylen, 'sha1')
|
|
var cipher = ciphers.createDecipheriv(algo, key, iv)
|
|
var out = []
|
|
out.push(cipher.update(cipherText))
|
|
out.push(cipher.final())
|
|
return Buffer.concat(out)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/parse-torrent/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/parse-torrent/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! parse-torrent. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */
|
|
/* global Blob */
|
|
|
|
const bencode = __webpack_require__(/*! bencode */ "./node_modules/bencode/lib/index.js")
|
|
const blobToBuffer = __webpack_require__(/*! blob-to-buffer */ "./node_modules/blob-to-buffer/index.js")
|
|
const fs = __webpack_require__(/*! fs */ "?8539") // browser exclude
|
|
const get = __webpack_require__(/*! simple-get */ "./node_modules/simple-get/index.js")
|
|
const magnet = __webpack_require__(/*! magnet-uri */ "./node_modules/magnet-uri/index.js")
|
|
const path = __webpack_require__(/*! path */ "./node_modules/path-browserify/index.js")
|
|
const sha1 = __webpack_require__(/*! simple-sha1 */ "./node_modules/simple-sha1/browser.js")
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
|
|
module.exports = parseTorrent
|
|
module.exports.remote = parseTorrentRemote
|
|
|
|
module.exports.toMagnetURI = magnet.encode
|
|
module.exports.toTorrentFile = encodeTorrentFile
|
|
|
|
/**
|
|
* Parse a torrent identifier (magnet uri, .torrent file, info hash)
|
|
* @param {string|Buffer|Object} torrentId
|
|
* @return {Object}
|
|
*/
|
|
function parseTorrent (torrentId) {
|
|
if (typeof torrentId === 'string' && /^(stream-)?magnet:/.test(torrentId)) {
|
|
// if magnet uri (string)
|
|
const torrentObj = magnet(torrentId)
|
|
|
|
// infoHash won't be defined if a non-bittorrent magnet is passed
|
|
if (!torrentObj.infoHash) {
|
|
throw new Error('Invalid torrent identifier')
|
|
}
|
|
|
|
return torrentObj
|
|
} else if (typeof torrentId === 'string' && (/^[a-f0-9]{40}$/i.test(torrentId) || /^[a-z2-7]{32}$/i.test(torrentId))) {
|
|
// if info hash (hex/base-32 string)
|
|
return magnet(`magnet:?xt=urn:btih:${torrentId}`)
|
|
} else if (Buffer.isBuffer(torrentId) && torrentId.length === 20) {
|
|
// if info hash (buffer)
|
|
return magnet(`magnet:?xt=urn:btih:${torrentId.toString('hex')}`)
|
|
} else if (Buffer.isBuffer(torrentId)) {
|
|
// if .torrent file (buffer)
|
|
return decodeTorrentFile(torrentId) // might throw
|
|
} else if (torrentId && torrentId.infoHash) {
|
|
// if parsed torrent (from `parse-torrent` or `magnet-uri`)
|
|
torrentId.infoHash = torrentId.infoHash.toLowerCase()
|
|
|
|
if (!torrentId.announce) torrentId.announce = []
|
|
|
|
if (typeof torrentId.announce === 'string') {
|
|
torrentId.announce = [torrentId.announce]
|
|
}
|
|
|
|
if (!torrentId.urlList) torrentId.urlList = []
|
|
|
|
return torrentId
|
|
} else {
|
|
throw new Error('Invalid torrent identifier')
|
|
}
|
|
}
|
|
|
|
function parseTorrentRemote (torrentId, opts, cb) {
|
|
if (typeof opts === 'function') return parseTorrentRemote(torrentId, {}, opts)
|
|
if (typeof cb !== 'function') throw new Error('second argument must be a Function')
|
|
|
|
let parsedTorrent
|
|
try {
|
|
parsedTorrent = parseTorrent(torrentId)
|
|
} catch (err) {
|
|
// If torrent fails to parse, it could be a Blob, http/https URL or
|
|
// filesystem path, so don't consider it an error yet.
|
|
}
|
|
|
|
if (parsedTorrent && parsedTorrent.infoHash) {
|
|
queueMicrotask(() => {
|
|
cb(null, parsedTorrent)
|
|
})
|
|
} else if (isBlob(torrentId)) {
|
|
blobToBuffer(torrentId, (err, torrentBuf) => {
|
|
if (err) return cb(new Error(`Error converting Blob: ${err.message}`))
|
|
parseOrThrow(torrentBuf)
|
|
})
|
|
} else if (typeof get === 'function' && /^https?:/.test(torrentId)) {
|
|
// http, or https url to torrent file
|
|
opts = Object.assign({
|
|
url: torrentId,
|
|
timeout: 30 * 1000,
|
|
headers: { 'user-agent': 'WebTorrent (https://webtorrent.io)' }
|
|
}, opts)
|
|
get.concat(opts, (err, res, torrentBuf) => {
|
|
if (err) return cb(new Error(`Error downloading torrent: ${err.message}`))
|
|
parseOrThrow(torrentBuf)
|
|
})
|
|
} else if (typeof fs.readFile === 'function' && typeof torrentId === 'string') {
|
|
// assume it's a filesystem path
|
|
fs.readFile(torrentId, (err, torrentBuf) => {
|
|
if (err) return cb(new Error('Invalid torrent identifier'))
|
|
parseOrThrow(torrentBuf)
|
|
})
|
|
} else {
|
|
queueMicrotask(() => {
|
|
cb(new Error('Invalid torrent identifier'))
|
|
})
|
|
}
|
|
|
|
function parseOrThrow (torrentBuf) {
|
|
try {
|
|
parsedTorrent = parseTorrent(torrentBuf)
|
|
} catch (err) {
|
|
return cb(err)
|
|
}
|
|
if (parsedTorrent && parsedTorrent.infoHash) cb(null, parsedTorrent)
|
|
else cb(new Error('Invalid torrent identifier'))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse a torrent. Throws an exception if the torrent is missing required fields.
|
|
* @param {Buffer|Object} torrent
|
|
* @return {Object} parsed torrent
|
|
*/
|
|
function decodeTorrentFile (torrent) {
|
|
if (Buffer.isBuffer(torrent)) {
|
|
torrent = bencode.decode(torrent)
|
|
}
|
|
|
|
// sanity check
|
|
ensure(torrent.info, 'info')
|
|
ensure(torrent.info['name.utf-8'] || torrent.info.name, 'info.name')
|
|
ensure(torrent.info['piece length'], 'info[\'piece length\']')
|
|
ensure(torrent.info.pieces, 'info.pieces')
|
|
|
|
if (torrent.info.files) {
|
|
torrent.info.files.forEach(file => {
|
|
ensure(typeof file.length === 'number', 'info.files[0].length')
|
|
ensure(file['path.utf-8'] || file.path, 'info.files[0].path')
|
|
})
|
|
} else {
|
|
ensure(typeof torrent.info.length === 'number', 'info.length')
|
|
}
|
|
|
|
const result = {
|
|
info: torrent.info,
|
|
infoBuffer: bencode.encode(torrent.info),
|
|
name: (torrent.info['name.utf-8'] || torrent.info.name).toString(),
|
|
announce: []
|
|
}
|
|
|
|
result.infoHash = sha1.sync(result.infoBuffer)
|
|
result.infoHashBuffer = Buffer.from(result.infoHash, 'hex')
|
|
|
|
if (torrent.info.private !== undefined) result.private = !!torrent.info.private
|
|
|
|
if (torrent['creation date']) result.created = new Date(torrent['creation date'] * 1000)
|
|
if (torrent['created by']) result.createdBy = torrent['created by'].toString()
|
|
|
|
if (Buffer.isBuffer(torrent.comment)) result.comment = torrent.comment.toString()
|
|
|
|
// announce and announce-list will be missing if metadata fetched via ut_metadata
|
|
if (Array.isArray(torrent['announce-list']) && torrent['announce-list'].length > 0) {
|
|
torrent['announce-list'].forEach(urls => {
|
|
urls.forEach(url => {
|
|
result.announce.push(url.toString())
|
|
})
|
|
})
|
|
} else if (torrent.announce) {
|
|
result.announce.push(torrent.announce.toString())
|
|
}
|
|
|
|
// handle url-list (BEP19 / web seeding)
|
|
if (Buffer.isBuffer(torrent['url-list'])) {
|
|
// some clients set url-list to empty string
|
|
torrent['url-list'] = torrent['url-list'].length > 0
|
|
? [torrent['url-list']]
|
|
: []
|
|
}
|
|
result.urlList = (torrent['url-list'] || []).map(url => url.toString())
|
|
|
|
// remove duplicates by converting to Set and back
|
|
result.announce = Array.from(new Set(result.announce))
|
|
result.urlList = Array.from(new Set(result.urlList))
|
|
|
|
const files = torrent.info.files || [torrent.info]
|
|
result.files = files.map((file, i) => {
|
|
const parts = [].concat(result.name, file['path.utf-8'] || file.path || []).map(p => p.toString())
|
|
return {
|
|
path: path.join.apply(null, [path.sep].concat(parts)).slice(1),
|
|
name: parts[parts.length - 1],
|
|
length: file.length,
|
|
offset: files.slice(0, i).reduce(sumLength, 0)
|
|
}
|
|
})
|
|
|
|
result.length = files.reduce(sumLength, 0)
|
|
|
|
const lastFile = result.files[result.files.length - 1]
|
|
|
|
result.pieceLength = torrent.info['piece length']
|
|
result.lastPieceLength = ((lastFile.offset + lastFile.length) % result.pieceLength) || result.pieceLength
|
|
result.pieces = splitPieces(torrent.info.pieces)
|
|
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Convert a parsed torrent object back into a .torrent file buffer.
|
|
* @param {Object} parsed parsed torrent
|
|
* @return {Buffer}
|
|
*/
|
|
function encodeTorrentFile (parsed) {
|
|
const torrent = {
|
|
info: parsed.info
|
|
}
|
|
|
|
torrent['announce-list'] = (parsed.announce || []).map(url => {
|
|
if (!torrent.announce) torrent.announce = url
|
|
url = Buffer.from(url, 'utf8')
|
|
return [url]
|
|
})
|
|
|
|
torrent['url-list'] = parsed.urlList || []
|
|
|
|
if (parsed.private !== undefined) {
|
|
torrent.private = Number(parsed.private)
|
|
}
|
|
|
|
if (parsed.created) {
|
|
torrent['creation date'] = (parsed.created.getTime() / 1000) | 0
|
|
}
|
|
|
|
if (parsed.createdBy) {
|
|
torrent['created by'] = parsed.createdBy
|
|
}
|
|
|
|
if (parsed.comment) {
|
|
torrent.comment = parsed.comment
|
|
}
|
|
|
|
return bencode.encode(torrent)
|
|
}
|
|
|
|
/**
|
|
* Check if `obj` is a W3C `Blob` or `File` object
|
|
* @param {*} obj
|
|
* @return {boolean}
|
|
*/
|
|
function isBlob (obj) {
|
|
return typeof Blob !== 'undefined' && obj instanceof Blob
|
|
}
|
|
|
|
function sumLength (sum, file) {
|
|
return sum + file.length
|
|
}
|
|
|
|
function splitPieces (buf) {
|
|
const pieces = []
|
|
for (let i = 0; i < buf.length; i += 20) {
|
|
pieces.push(buf.slice(i, i + 20).toString('hex'))
|
|
}
|
|
return pieces
|
|
}
|
|
|
|
function ensure (bool, fieldName) {
|
|
if (!bool) throw new Error(`Torrent is missing required field: ${fieldName}`)
|
|
}
|
|
|
|
// Workaround Browserify v13 bug
|
|
// https://github.com/substack/node-browserify/issues/1483
|
|
;(() => { Buffer.alloc(0) })()
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/path-browserify/index.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/path-browserify/index.js ***!
|
|
\***********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
// 'path' module extracted from Node.js v8.11.1 (only the posix part)
|
|
// transplited with Babel
|
|
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
function assertPath(path) {
|
|
if (typeof path !== 'string') {
|
|
throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));
|
|
}
|
|
}
|
|
|
|
// Resolves . and .. elements in a path with directory names
|
|
function normalizeStringPosix(path, allowAboveRoot) {
|
|
var res = '';
|
|
var lastSegmentLength = 0;
|
|
var lastSlash = -1;
|
|
var dots = 0;
|
|
var code;
|
|
for (var i = 0; i <= path.length; ++i) {
|
|
if (i < path.length)
|
|
code = path.charCodeAt(i);
|
|
else if (code === 47 /*/*/)
|
|
break;
|
|
else
|
|
code = 47 /*/*/;
|
|
if (code === 47 /*/*/) {
|
|
if (lastSlash === i - 1 || dots === 1) {
|
|
// NOOP
|
|
} else if (lastSlash !== i - 1 && dots === 2) {
|
|
if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {
|
|
if (res.length > 2) {
|
|
var lastSlashIndex = res.lastIndexOf('/');
|
|
if (lastSlashIndex !== res.length - 1) {
|
|
if (lastSlashIndex === -1) {
|
|
res = '';
|
|
lastSegmentLength = 0;
|
|
} else {
|
|
res = res.slice(0, lastSlashIndex);
|
|
lastSegmentLength = res.length - 1 - res.lastIndexOf('/');
|
|
}
|
|
lastSlash = i;
|
|
dots = 0;
|
|
continue;
|
|
}
|
|
} else if (res.length === 2 || res.length === 1) {
|
|
res = '';
|
|
lastSegmentLength = 0;
|
|
lastSlash = i;
|
|
dots = 0;
|
|
continue;
|
|
}
|
|
}
|
|
if (allowAboveRoot) {
|
|
if (res.length > 0)
|
|
res += '/..';
|
|
else
|
|
res = '..';
|
|
lastSegmentLength = 2;
|
|
}
|
|
} else {
|
|
if (res.length > 0)
|
|
res += '/' + path.slice(lastSlash + 1, i);
|
|
else
|
|
res = path.slice(lastSlash + 1, i);
|
|
lastSegmentLength = i - lastSlash - 1;
|
|
}
|
|
lastSlash = i;
|
|
dots = 0;
|
|
} else if (code === 46 /*.*/ && dots !== -1) {
|
|
++dots;
|
|
} else {
|
|
dots = -1;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
function _format(sep, pathObject) {
|
|
var dir = pathObject.dir || pathObject.root;
|
|
var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');
|
|
if (!dir) {
|
|
return base;
|
|
}
|
|
if (dir === pathObject.root) {
|
|
return dir + base;
|
|
}
|
|
return dir + sep + base;
|
|
}
|
|
|
|
var posix = {
|
|
// path.resolve([from ...], to)
|
|
resolve: function resolve() {
|
|
var resolvedPath = '';
|
|
var resolvedAbsolute = false;
|
|
var cwd;
|
|
|
|
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
|
var path;
|
|
if (i >= 0)
|
|
path = arguments[i];
|
|
else {
|
|
if (cwd === undefined)
|
|
cwd = process.cwd();
|
|
path = cwd;
|
|
}
|
|
|
|
assertPath(path);
|
|
|
|
// Skip empty entries
|
|
if (path.length === 0) {
|
|
continue;
|
|
}
|
|
|
|
resolvedPath = path + '/' + resolvedPath;
|
|
resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;
|
|
}
|
|
|
|
// At this point the path should be resolved to a full absolute path, but
|
|
// handle relative paths to be safe (might happen when process.cwd() fails)
|
|
|
|
// Normalize the path
|
|
resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);
|
|
|
|
if (resolvedAbsolute) {
|
|
if (resolvedPath.length > 0)
|
|
return '/' + resolvedPath;
|
|
else
|
|
return '/';
|
|
} else if (resolvedPath.length > 0) {
|
|
return resolvedPath;
|
|
} else {
|
|
return '.';
|
|
}
|
|
},
|
|
|
|
normalize: function normalize(path) {
|
|
assertPath(path);
|
|
|
|
if (path.length === 0) return '.';
|
|
|
|
var isAbsolute = path.charCodeAt(0) === 47 /*/*/;
|
|
var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;
|
|
|
|
// Normalize the path
|
|
path = normalizeStringPosix(path, !isAbsolute);
|
|
|
|
if (path.length === 0 && !isAbsolute) path = '.';
|
|
if (path.length > 0 && trailingSeparator) path += '/';
|
|
|
|
if (isAbsolute) return '/' + path;
|
|
return path;
|
|
},
|
|
|
|
isAbsolute: function isAbsolute(path) {
|
|
assertPath(path);
|
|
return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;
|
|
},
|
|
|
|
join: function join() {
|
|
if (arguments.length === 0)
|
|
return '.';
|
|
var joined;
|
|
for (var i = 0; i < arguments.length; ++i) {
|
|
var arg = arguments[i];
|
|
assertPath(arg);
|
|
if (arg.length > 0) {
|
|
if (joined === undefined)
|
|
joined = arg;
|
|
else
|
|
joined += '/' + arg;
|
|
}
|
|
}
|
|
if (joined === undefined)
|
|
return '.';
|
|
return posix.normalize(joined);
|
|
},
|
|
|
|
relative: function relative(from, to) {
|
|
assertPath(from);
|
|
assertPath(to);
|
|
|
|
if (from === to) return '';
|
|
|
|
from = posix.resolve(from);
|
|
to = posix.resolve(to);
|
|
|
|
if (from === to) return '';
|
|
|
|
// Trim any leading backslashes
|
|
var fromStart = 1;
|
|
for (; fromStart < from.length; ++fromStart) {
|
|
if (from.charCodeAt(fromStart) !== 47 /*/*/)
|
|
break;
|
|
}
|
|
var fromEnd = from.length;
|
|
var fromLen = fromEnd - fromStart;
|
|
|
|
// Trim any leading backslashes
|
|
var toStart = 1;
|
|
for (; toStart < to.length; ++toStart) {
|
|
if (to.charCodeAt(toStart) !== 47 /*/*/)
|
|
break;
|
|
}
|
|
var toEnd = to.length;
|
|
var toLen = toEnd - toStart;
|
|
|
|
// Compare paths to find the longest common path from root
|
|
var length = fromLen < toLen ? fromLen : toLen;
|
|
var lastCommonSep = -1;
|
|
var i = 0;
|
|
for (; i <= length; ++i) {
|
|
if (i === length) {
|
|
if (toLen > length) {
|
|
if (to.charCodeAt(toStart + i) === 47 /*/*/) {
|
|
// We get here if `from` is the exact base path for `to`.
|
|
// For example: from='/foo/bar'; to='/foo/bar/baz'
|
|
return to.slice(toStart + i + 1);
|
|
} else if (i === 0) {
|
|
// We get here if `from` is the root
|
|
// For example: from='/'; to='/foo'
|
|
return to.slice(toStart + i);
|
|
}
|
|
} else if (fromLen > length) {
|
|
if (from.charCodeAt(fromStart + i) === 47 /*/*/) {
|
|
// We get here if `to` is the exact base path for `from`.
|
|
// For example: from='/foo/bar/baz'; to='/foo/bar'
|
|
lastCommonSep = i;
|
|
} else if (i === 0) {
|
|
// We get here if `to` is the root.
|
|
// For example: from='/foo'; to='/'
|
|
lastCommonSep = 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
var fromCode = from.charCodeAt(fromStart + i);
|
|
var toCode = to.charCodeAt(toStart + i);
|
|
if (fromCode !== toCode)
|
|
break;
|
|
else if (fromCode === 47 /*/*/)
|
|
lastCommonSep = i;
|
|
}
|
|
|
|
var out = '';
|
|
// Generate the relative path based on the path difference between `to`
|
|
// and `from`
|
|
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
|
|
if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {
|
|
if (out.length === 0)
|
|
out += '..';
|
|
else
|
|
out += '/..';
|
|
}
|
|
}
|
|
|
|
// Lastly, append the rest of the destination (`to`) path that comes after
|
|
// the common path parts
|
|
if (out.length > 0)
|
|
return out + to.slice(toStart + lastCommonSep);
|
|
else {
|
|
toStart += lastCommonSep;
|
|
if (to.charCodeAt(toStart) === 47 /*/*/)
|
|
++toStart;
|
|
return to.slice(toStart);
|
|
}
|
|
},
|
|
|
|
_makeLong: function _makeLong(path) {
|
|
return path;
|
|
},
|
|
|
|
dirname: function dirname(path) {
|
|
assertPath(path);
|
|
if (path.length === 0) return '.';
|
|
var code = path.charCodeAt(0);
|
|
var hasRoot = code === 47 /*/*/;
|
|
var end = -1;
|
|
var matchedSlash = true;
|
|
for (var i = path.length - 1; i >= 1; --i) {
|
|
code = path.charCodeAt(i);
|
|
if (code === 47 /*/*/) {
|
|
if (!matchedSlash) {
|
|
end = i;
|
|
break;
|
|
}
|
|
} else {
|
|
// We saw the first non-path separator
|
|
matchedSlash = false;
|
|
}
|
|
}
|
|
|
|
if (end === -1) return hasRoot ? '/' : '.';
|
|
if (hasRoot && end === 1) return '//';
|
|
return path.slice(0, end);
|
|
},
|
|
|
|
basename: function basename(path, ext) {
|
|
if (ext !== undefined && typeof ext !== 'string') throw new TypeError('"ext" argument must be a string');
|
|
assertPath(path);
|
|
|
|
var start = 0;
|
|
var end = -1;
|
|
var matchedSlash = true;
|
|
var i;
|
|
|
|
if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
|
|
if (ext.length === path.length && ext === path) return '';
|
|
var extIdx = ext.length - 1;
|
|
var firstNonSlashEnd = -1;
|
|
for (i = path.length - 1; i >= 0; --i) {
|
|
var code = path.charCodeAt(i);
|
|
if (code === 47 /*/*/) {
|
|
// If we reached a path separator that was not part of a set of path
|
|
// separators at the end of the string, stop now
|
|
if (!matchedSlash) {
|
|
start = i + 1;
|
|
break;
|
|
}
|
|
} else {
|
|
if (firstNonSlashEnd === -1) {
|
|
// We saw the first non-path separator, remember this index in case
|
|
// we need it if the extension ends up not matching
|
|
matchedSlash = false;
|
|
firstNonSlashEnd = i + 1;
|
|
}
|
|
if (extIdx >= 0) {
|
|
// Try to match the explicit extension
|
|
if (code === ext.charCodeAt(extIdx)) {
|
|
if (--extIdx === -1) {
|
|
// We matched the extension, so mark this as the end of our path
|
|
// component
|
|
end = i;
|
|
}
|
|
} else {
|
|
// Extension does not match, so our result is the entire path
|
|
// component
|
|
extIdx = -1;
|
|
end = firstNonSlashEnd;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;
|
|
return path.slice(start, end);
|
|
} else {
|
|
for (i = path.length - 1; i >= 0; --i) {
|
|
if (path.charCodeAt(i) === 47 /*/*/) {
|
|
// If we reached a path separator that was not part of a set of path
|
|
// separators at the end of the string, stop now
|
|
if (!matchedSlash) {
|
|
start = i + 1;
|
|
break;
|
|
}
|
|
} else if (end === -1) {
|
|
// We saw the first non-path separator, mark this as the end of our
|
|
// path component
|
|
matchedSlash = false;
|
|
end = i + 1;
|
|
}
|
|
}
|
|
|
|
if (end === -1) return '';
|
|
return path.slice(start, end);
|
|
}
|
|
},
|
|
|
|
extname: function extname(path) {
|
|
assertPath(path);
|
|
var startDot = -1;
|
|
var startPart = 0;
|
|
var end = -1;
|
|
var matchedSlash = true;
|
|
// Track the state of characters (if any) we see before our first dot and
|
|
// after any path separator we find
|
|
var preDotState = 0;
|
|
for (var i = path.length - 1; i >= 0; --i) {
|
|
var code = path.charCodeAt(i);
|
|
if (code === 47 /*/*/) {
|
|
// If we reached a path separator that was not part of a set of path
|
|
// separators at the end of the string, stop now
|
|
if (!matchedSlash) {
|
|
startPart = i + 1;
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
if (end === -1) {
|
|
// We saw the first non-path separator, mark this as the end of our
|
|
// extension
|
|
matchedSlash = false;
|
|
end = i + 1;
|
|
}
|
|
if (code === 46 /*.*/) {
|
|
// If this is our first dot, mark it as the start of our extension
|
|
if (startDot === -1)
|
|
startDot = i;
|
|
else if (preDotState !== 1)
|
|
preDotState = 1;
|
|
} else if (startDot !== -1) {
|
|
// We saw a non-dot and non-path separator before our dot, so we should
|
|
// have a good chance at having a non-empty extension
|
|
preDotState = -1;
|
|
}
|
|
}
|
|
|
|
if (startDot === -1 || end === -1 ||
|
|
// We saw a non-dot character immediately before the dot
|
|
preDotState === 0 ||
|
|
// The (right-most) trimmed path component is exactly '..'
|
|
preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
|
|
return '';
|
|
}
|
|
return path.slice(startDot, end);
|
|
},
|
|
|
|
format: function format(pathObject) {
|
|
if (pathObject === null || typeof pathObject !== 'object') {
|
|
throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
|
|
}
|
|
return _format('/', pathObject);
|
|
},
|
|
|
|
parse: function parse(path) {
|
|
assertPath(path);
|
|
|
|
var ret = { root: '', dir: '', base: '', ext: '', name: '' };
|
|
if (path.length === 0) return ret;
|
|
var code = path.charCodeAt(0);
|
|
var isAbsolute = code === 47 /*/*/;
|
|
var start;
|
|
if (isAbsolute) {
|
|
ret.root = '/';
|
|
start = 1;
|
|
} else {
|
|
start = 0;
|
|
}
|
|
var startDot = -1;
|
|
var startPart = 0;
|
|
var end = -1;
|
|
var matchedSlash = true;
|
|
var i = path.length - 1;
|
|
|
|
// Track the state of characters (if any) we see before our first dot and
|
|
// after any path separator we find
|
|
var preDotState = 0;
|
|
|
|
// Get non-dir info
|
|
for (; i >= start; --i) {
|
|
code = path.charCodeAt(i);
|
|
if (code === 47 /*/*/) {
|
|
// If we reached a path separator that was not part of a set of path
|
|
// separators at the end of the string, stop now
|
|
if (!matchedSlash) {
|
|
startPart = i + 1;
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
if (end === -1) {
|
|
// We saw the first non-path separator, mark this as the end of our
|
|
// extension
|
|
matchedSlash = false;
|
|
end = i + 1;
|
|
}
|
|
if (code === 46 /*.*/) {
|
|
// If this is our first dot, mark it as the start of our extension
|
|
if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;
|
|
} else if (startDot !== -1) {
|
|
// We saw a non-dot and non-path separator before our dot, so we should
|
|
// have a good chance at having a non-empty extension
|
|
preDotState = -1;
|
|
}
|
|
}
|
|
|
|
if (startDot === -1 || end === -1 ||
|
|
// We saw a non-dot character immediately before the dot
|
|
preDotState === 0 ||
|
|
// The (right-most) trimmed path component is exactly '..'
|
|
preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
|
|
if (end !== -1) {
|
|
if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);
|
|
}
|
|
} else {
|
|
if (startPart === 0 && isAbsolute) {
|
|
ret.name = path.slice(1, startDot);
|
|
ret.base = path.slice(1, end);
|
|
} else {
|
|
ret.name = path.slice(startPart, startDot);
|
|
ret.base = path.slice(startPart, end);
|
|
}
|
|
ret.ext = path.slice(startDot, end);
|
|
}
|
|
|
|
if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';
|
|
|
|
return ret;
|
|
},
|
|
|
|
sep: '/',
|
|
delimiter: ':',
|
|
win32: null,
|
|
posix: null
|
|
};
|
|
|
|
posix.posix = posix;
|
|
|
|
module.exports = posix;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/pbkdf2/browser.js":
|
|
/*!****************************************!*\
|
|
!*** ./node_modules/pbkdf2/browser.js ***!
|
|
\****************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
exports.pbkdf2 = __webpack_require__(/*! ./lib/async */ "./node_modules/pbkdf2/lib/async.js")
|
|
exports.pbkdf2Sync = __webpack_require__(/*! ./lib/sync */ "./node_modules/pbkdf2/lib/sync-browser.js")
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/pbkdf2/lib/async.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/pbkdf2/lib/async.js ***!
|
|
\******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var checkParameters = __webpack_require__(/*! ./precondition */ "./node_modules/pbkdf2/lib/precondition.js")
|
|
var defaultEncoding = __webpack_require__(/*! ./default-encoding */ "./node_modules/pbkdf2/lib/default-encoding.js")
|
|
var sync = __webpack_require__(/*! ./sync */ "./node_modules/pbkdf2/lib/sync-browser.js")
|
|
var toBuffer = __webpack_require__(/*! ./to-buffer */ "./node_modules/pbkdf2/lib/to-buffer.js")
|
|
|
|
var ZERO_BUF
|
|
var subtle = __webpack_require__.g.crypto && __webpack_require__.g.crypto.subtle
|
|
var toBrowser = {
|
|
sha: 'SHA-1',
|
|
'sha-1': 'SHA-1',
|
|
sha1: 'SHA-1',
|
|
sha256: 'SHA-256',
|
|
'sha-256': 'SHA-256',
|
|
sha384: 'SHA-384',
|
|
'sha-384': 'SHA-384',
|
|
'sha-512': 'SHA-512',
|
|
sha512: 'SHA-512'
|
|
}
|
|
var checks = []
|
|
function checkNative (algo) {
|
|
if (__webpack_require__.g.process && !__webpack_require__.g.process.browser) {
|
|
return Promise.resolve(false)
|
|
}
|
|
if (!subtle || !subtle.importKey || !subtle.deriveBits) {
|
|
return Promise.resolve(false)
|
|
}
|
|
if (checks[algo] !== undefined) {
|
|
return checks[algo]
|
|
}
|
|
ZERO_BUF = ZERO_BUF || Buffer.alloc(8)
|
|
var prom = browserPbkdf2(ZERO_BUF, ZERO_BUF, 10, 128, algo)
|
|
.then(function () {
|
|
return true
|
|
}).catch(function () {
|
|
return false
|
|
})
|
|
checks[algo] = prom
|
|
return prom
|
|
}
|
|
var nextTick
|
|
function getNextTick () {
|
|
if (nextTick) {
|
|
return nextTick
|
|
}
|
|
if (__webpack_require__.g.process && __webpack_require__.g.process.nextTick) {
|
|
nextTick = __webpack_require__.g.process.nextTick
|
|
} else if (__webpack_require__.g.queueMicrotask) {
|
|
nextTick = __webpack_require__.g.queueMicrotask
|
|
} else if (__webpack_require__.g.setImmediate) {
|
|
nextTick = __webpack_require__.g.setImmediate
|
|
} else {
|
|
nextTick = __webpack_require__.g.setTimeout
|
|
}
|
|
return nextTick
|
|
}
|
|
function browserPbkdf2 (password, salt, iterations, length, algo) {
|
|
return subtle.importKey(
|
|
'raw', password, { name: 'PBKDF2' }, false, ['deriveBits']
|
|
).then(function (key) {
|
|
return subtle.deriveBits({
|
|
name: 'PBKDF2',
|
|
salt: salt,
|
|
iterations: iterations,
|
|
hash: {
|
|
name: algo
|
|
}
|
|
}, key, length << 3)
|
|
}).then(function (res) {
|
|
return Buffer.from(res)
|
|
})
|
|
}
|
|
|
|
function resolvePromise (promise, callback) {
|
|
promise.then(function (out) {
|
|
getNextTick()(function () {
|
|
callback(null, out)
|
|
})
|
|
}, function (e) {
|
|
getNextTick()(function () {
|
|
callback(e)
|
|
})
|
|
})
|
|
}
|
|
module.exports = function (password, salt, iterations, keylen, digest, callback) {
|
|
if (typeof digest === 'function') {
|
|
callback = digest
|
|
digest = undefined
|
|
}
|
|
|
|
digest = digest || 'sha1'
|
|
var algo = toBrowser[digest.toLowerCase()]
|
|
|
|
if (!algo || typeof __webpack_require__.g.Promise !== 'function') {
|
|
getNextTick()(function () {
|
|
var out
|
|
try {
|
|
out = sync(password, salt, iterations, keylen, digest)
|
|
} catch (e) {
|
|
return callback(e)
|
|
}
|
|
callback(null, out)
|
|
})
|
|
return
|
|
}
|
|
|
|
checkParameters(iterations, keylen)
|
|
password = toBuffer(password, defaultEncoding, 'Password')
|
|
salt = toBuffer(salt, defaultEncoding, 'Salt')
|
|
if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2')
|
|
|
|
resolvePromise(checkNative(algo).then(function (resp) {
|
|
if (resp) return browserPbkdf2(password, salt, iterations, keylen, algo)
|
|
|
|
return sync(password, salt, iterations, keylen, digest)
|
|
}), callback)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/pbkdf2/lib/default-encoding.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/pbkdf2/lib/default-encoding.js ***!
|
|
\*****************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
var defaultEncoding
|
|
/* istanbul ignore next */
|
|
if (__webpack_require__.g.process && __webpack_require__.g.process.browser) {
|
|
defaultEncoding = 'utf-8'
|
|
} else if (__webpack_require__.g.process && __webpack_require__.g.process.version) {
|
|
var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10)
|
|
|
|
defaultEncoding = pVersionMajor >= 6 ? 'utf-8' : 'binary'
|
|
} else {
|
|
defaultEncoding = 'utf-8'
|
|
}
|
|
module.exports = defaultEncoding
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/pbkdf2/lib/precondition.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/pbkdf2/lib/precondition.js ***!
|
|
\*************************************************/
|
|
/***/ ((module) => {
|
|
|
|
var MAX_ALLOC = Math.pow(2, 30) - 1 // default in iojs
|
|
|
|
module.exports = function (iterations, keylen) {
|
|
if (typeof iterations !== 'number') {
|
|
throw new TypeError('Iterations not a number')
|
|
}
|
|
|
|
if (iterations < 0) {
|
|
throw new TypeError('Bad iterations')
|
|
}
|
|
|
|
if (typeof keylen !== 'number') {
|
|
throw new TypeError('Key length not a number')
|
|
}
|
|
|
|
if (keylen < 0 || keylen > MAX_ALLOC || keylen !== keylen) { /* eslint no-self-compare: 0 */
|
|
throw new TypeError('Bad key length')
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/pbkdf2/lib/sync-browser.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/pbkdf2/lib/sync-browser.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var md5 = __webpack_require__(/*! create-hash/md5 */ "./node_modules/create-hash/md5.js")
|
|
var RIPEMD160 = __webpack_require__(/*! ripemd160 */ "./node_modules/ripemd160/index.js")
|
|
var sha = __webpack_require__(/*! sha.js */ "./node_modules/sha.js/index.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var checkParameters = __webpack_require__(/*! ./precondition */ "./node_modules/pbkdf2/lib/precondition.js")
|
|
var defaultEncoding = __webpack_require__(/*! ./default-encoding */ "./node_modules/pbkdf2/lib/default-encoding.js")
|
|
var toBuffer = __webpack_require__(/*! ./to-buffer */ "./node_modules/pbkdf2/lib/to-buffer.js")
|
|
|
|
var ZEROS = Buffer.alloc(128)
|
|
var sizes = {
|
|
md5: 16,
|
|
sha1: 20,
|
|
sha224: 28,
|
|
sha256: 32,
|
|
sha384: 48,
|
|
sha512: 64,
|
|
rmd160: 20,
|
|
ripemd160: 20
|
|
}
|
|
|
|
function Hmac (alg, key, saltLen) {
|
|
var hash = getDigest(alg)
|
|
var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64
|
|
|
|
if (key.length > blocksize) {
|
|
key = hash(key)
|
|
} else if (key.length < blocksize) {
|
|
key = Buffer.concat([key, ZEROS], blocksize)
|
|
}
|
|
|
|
var ipad = Buffer.allocUnsafe(blocksize + sizes[alg])
|
|
var opad = Buffer.allocUnsafe(blocksize + sizes[alg])
|
|
for (var i = 0; i < blocksize; i++) {
|
|
ipad[i] = key[i] ^ 0x36
|
|
opad[i] = key[i] ^ 0x5C
|
|
}
|
|
|
|
var ipad1 = Buffer.allocUnsafe(blocksize + saltLen + 4)
|
|
ipad.copy(ipad1, 0, 0, blocksize)
|
|
this.ipad1 = ipad1
|
|
this.ipad2 = ipad
|
|
this.opad = opad
|
|
this.alg = alg
|
|
this.blocksize = blocksize
|
|
this.hash = hash
|
|
this.size = sizes[alg]
|
|
}
|
|
|
|
Hmac.prototype.run = function (data, ipad) {
|
|
data.copy(ipad, this.blocksize)
|
|
var h = this.hash(ipad)
|
|
h.copy(this.opad, this.blocksize)
|
|
return this.hash(this.opad)
|
|
}
|
|
|
|
function getDigest (alg) {
|
|
function shaFunc (data) {
|
|
return sha(alg).update(data).digest()
|
|
}
|
|
function rmd160Func (data) {
|
|
return new RIPEMD160().update(data).digest()
|
|
}
|
|
|
|
if (alg === 'rmd160' || alg === 'ripemd160') return rmd160Func
|
|
if (alg === 'md5') return md5
|
|
return shaFunc
|
|
}
|
|
|
|
function pbkdf2 (password, salt, iterations, keylen, digest) {
|
|
checkParameters(iterations, keylen)
|
|
password = toBuffer(password, defaultEncoding, 'Password')
|
|
salt = toBuffer(salt, defaultEncoding, 'Salt')
|
|
|
|
digest = digest || 'sha1'
|
|
|
|
var hmac = new Hmac(digest, password, salt.length)
|
|
|
|
var DK = Buffer.allocUnsafe(keylen)
|
|
var block1 = Buffer.allocUnsafe(salt.length + 4)
|
|
salt.copy(block1, 0, 0, salt.length)
|
|
|
|
var destPos = 0
|
|
var hLen = sizes[digest]
|
|
var l = Math.ceil(keylen / hLen)
|
|
|
|
for (var i = 1; i <= l; i++) {
|
|
block1.writeUInt32BE(i, salt.length)
|
|
|
|
var T = hmac.run(block1, hmac.ipad1)
|
|
var U = T
|
|
|
|
for (var j = 1; j < iterations; j++) {
|
|
U = hmac.run(U, hmac.ipad2)
|
|
for (var k = 0; k < hLen; k++) T[k] ^= U[k]
|
|
}
|
|
|
|
T.copy(DK, destPos)
|
|
destPos += hLen
|
|
}
|
|
|
|
return DK
|
|
}
|
|
|
|
module.exports = pbkdf2
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/pbkdf2/lib/to-buffer.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/pbkdf2/lib/to-buffer.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
module.exports = function (thing, encoding, name) {
|
|
if (Buffer.isBuffer(thing)) {
|
|
return thing
|
|
} else if (typeof thing === 'string') {
|
|
return Buffer.from(thing, encoding)
|
|
} else if (ArrayBuffer.isView(thing)) {
|
|
return Buffer.from(thing.buffer)
|
|
} else {
|
|
throw new TypeError(name + ' must be a string, a Buffer, a typed array or a DataView')
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/piece-length/index.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/piece-length/index.js ***!
|
|
\********************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = length
|
|
|
|
function length (bytes) {
|
|
return Math.max(16384, 1 << Math.log2(bytes < 1024 ? 1 : bytes / 1024) + 0.5 | 0)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/process/browser.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/process/browser.js ***!
|
|
\*****************************************/
|
|
/***/ ((module) => {
|
|
|
|
// shim for using process in browser
|
|
var process = module.exports = {};
|
|
|
|
// cached from whatever global is present so that test runners that stub it
|
|
// don't break things. But we need to wrap it in a try catch in case it is
|
|
// wrapped in strict mode code which doesn't define any globals. It's inside a
|
|
// function because try/catches deoptimize in certain engines.
|
|
|
|
var cachedSetTimeout;
|
|
var cachedClearTimeout;
|
|
|
|
function defaultSetTimout() {
|
|
throw new Error('setTimeout has not been defined');
|
|
}
|
|
function defaultClearTimeout () {
|
|
throw new Error('clearTimeout has not been defined');
|
|
}
|
|
(function () {
|
|
try {
|
|
if (typeof setTimeout === 'function') {
|
|
cachedSetTimeout = setTimeout;
|
|
} else {
|
|
cachedSetTimeout = defaultSetTimout;
|
|
}
|
|
} catch (e) {
|
|
cachedSetTimeout = defaultSetTimout;
|
|
}
|
|
try {
|
|
if (typeof clearTimeout === 'function') {
|
|
cachedClearTimeout = clearTimeout;
|
|
} else {
|
|
cachedClearTimeout = defaultClearTimeout;
|
|
}
|
|
} catch (e) {
|
|
cachedClearTimeout = defaultClearTimeout;
|
|
}
|
|
} ())
|
|
function runTimeout(fun) {
|
|
if (cachedSetTimeout === setTimeout) {
|
|
//normal enviroments in sane situations
|
|
return setTimeout(fun, 0);
|
|
}
|
|
// if setTimeout wasn't available but was latter defined
|
|
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
|
|
cachedSetTimeout = setTimeout;
|
|
return setTimeout(fun, 0);
|
|
}
|
|
try {
|
|
// when when somebody has screwed with setTimeout but no I.E. maddness
|
|
return cachedSetTimeout(fun, 0);
|
|
} catch(e){
|
|
try {
|
|
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
|
return cachedSetTimeout.call(null, fun, 0);
|
|
} catch(e){
|
|
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
|
|
return cachedSetTimeout.call(this, fun, 0);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
function runClearTimeout(marker) {
|
|
if (cachedClearTimeout === clearTimeout) {
|
|
//normal enviroments in sane situations
|
|
return clearTimeout(marker);
|
|
}
|
|
// if clearTimeout wasn't available but was latter defined
|
|
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
|
|
cachedClearTimeout = clearTimeout;
|
|
return clearTimeout(marker);
|
|
}
|
|
try {
|
|
// when when somebody has screwed with setTimeout but no I.E. maddness
|
|
return cachedClearTimeout(marker);
|
|
} catch (e){
|
|
try {
|
|
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
|
return cachedClearTimeout.call(null, marker);
|
|
} catch (e){
|
|
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
|
|
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
|
|
return cachedClearTimeout.call(this, marker);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
var queue = [];
|
|
var draining = false;
|
|
var currentQueue;
|
|
var queueIndex = -1;
|
|
|
|
function cleanUpNextTick() {
|
|
if (!draining || !currentQueue) {
|
|
return;
|
|
}
|
|
draining = false;
|
|
if (currentQueue.length) {
|
|
queue = currentQueue.concat(queue);
|
|
} else {
|
|
queueIndex = -1;
|
|
}
|
|
if (queue.length) {
|
|
drainQueue();
|
|
}
|
|
}
|
|
|
|
function drainQueue() {
|
|
if (draining) {
|
|
return;
|
|
}
|
|
var timeout = runTimeout(cleanUpNextTick);
|
|
draining = true;
|
|
|
|
var len = queue.length;
|
|
while(len) {
|
|
currentQueue = queue;
|
|
queue = [];
|
|
while (++queueIndex < len) {
|
|
if (currentQueue) {
|
|
currentQueue[queueIndex].run();
|
|
}
|
|
}
|
|
queueIndex = -1;
|
|
len = queue.length;
|
|
}
|
|
currentQueue = null;
|
|
draining = false;
|
|
runClearTimeout(timeout);
|
|
}
|
|
|
|
process.nextTick = function (fun) {
|
|
var args = new Array(arguments.length - 1);
|
|
if (arguments.length > 1) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
args[i - 1] = arguments[i];
|
|
}
|
|
}
|
|
queue.push(new Item(fun, args));
|
|
if (queue.length === 1 && !draining) {
|
|
runTimeout(drainQueue);
|
|
}
|
|
};
|
|
|
|
// v8 likes predictible objects
|
|
function Item(fun, array) {
|
|
this.fun = fun;
|
|
this.array = array;
|
|
}
|
|
Item.prototype.run = function () {
|
|
this.fun.apply(null, this.array);
|
|
};
|
|
process.title = 'browser';
|
|
process.browser = true;
|
|
process.env = {};
|
|
process.argv = [];
|
|
process.version = ''; // empty string to avoid regexp issues
|
|
process.versions = {};
|
|
|
|
function noop() {}
|
|
|
|
process.on = noop;
|
|
process.addListener = noop;
|
|
process.once = noop;
|
|
process.off = noop;
|
|
process.removeListener = noop;
|
|
process.removeAllListeners = noop;
|
|
process.emit = noop;
|
|
process.prependListener = noop;
|
|
process.prependOnceListener = noop;
|
|
|
|
process.listeners = function (name) { return [] }
|
|
|
|
process.binding = function (name) {
|
|
throw new Error('process.binding is not supported');
|
|
};
|
|
|
|
process.cwd = function () { return '/' };
|
|
process.chdir = function (dir) {
|
|
throw new Error('process.chdir is not supported');
|
|
};
|
|
process.umask = function() { return 0; };
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/public-encrypt/browser.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/public-encrypt/browser.js ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
exports.publicEncrypt = __webpack_require__(/*! ./publicEncrypt */ "./node_modules/public-encrypt/publicEncrypt.js")
|
|
exports.privateDecrypt = __webpack_require__(/*! ./privateDecrypt */ "./node_modules/public-encrypt/privateDecrypt.js")
|
|
|
|
exports.privateEncrypt = function privateEncrypt (key, buf) {
|
|
return exports.publicEncrypt(key, buf, true)
|
|
}
|
|
|
|
exports.publicDecrypt = function publicDecrypt (key, buf) {
|
|
return exports.privateDecrypt(key, buf, true)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/public-encrypt/mgf.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/public-encrypt/mgf.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var createHash = __webpack_require__(/*! create-hash */ "./node_modules/create-hash/browser.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
module.exports = function (seed, len) {
|
|
var t = Buffer.alloc(0)
|
|
var i = 0
|
|
var c
|
|
while (t.length < len) {
|
|
c = i2ops(i++)
|
|
t = Buffer.concat([t, createHash('sha1').update(seed).update(c).digest()])
|
|
}
|
|
return t.slice(0, len)
|
|
}
|
|
|
|
function i2ops (c) {
|
|
var out = Buffer.allocUnsafe(4)
|
|
out.writeUInt32BE(c, 0)
|
|
return out
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/public-encrypt/node_modules/bn.js/lib/bn.js":
|
|
/*!******************************************************************!*\
|
|
!*** ./node_modules/public-encrypt/node_modules/bn.js/lib/bn.js ***!
|
|
\******************************************************************/
|
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
/* module decorator */ module = __webpack_require__.nmd(module);
|
|
(function (module, exports) {
|
|
'use strict';
|
|
|
|
// Utils
|
|
function assert (val, msg) {
|
|
if (!val) throw new Error(msg || 'Assertion failed');
|
|
}
|
|
|
|
// Could use `inherits` module, but don't want to move from single file
|
|
// architecture yet.
|
|
function inherits (ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
var TempCtor = function () {};
|
|
TempCtor.prototype = superCtor.prototype;
|
|
ctor.prototype = new TempCtor();
|
|
ctor.prototype.constructor = ctor;
|
|
}
|
|
|
|
// BN
|
|
|
|
function BN (number, base, endian) {
|
|
if (BN.isBN(number)) {
|
|
return number;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.words = null;
|
|
this.length = 0;
|
|
|
|
// Reduction context
|
|
this.red = null;
|
|
|
|
if (number !== null) {
|
|
if (base === 'le' || base === 'be') {
|
|
endian = base;
|
|
base = 10;
|
|
}
|
|
|
|
this._init(number || 0, base || 10, endian || 'be');
|
|
}
|
|
}
|
|
if (typeof module === 'object') {
|
|
module.exports = BN;
|
|
} else {
|
|
exports.BN = BN;
|
|
}
|
|
|
|
BN.BN = BN;
|
|
BN.wordSize = 26;
|
|
|
|
var Buffer;
|
|
try {
|
|
if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') {
|
|
Buffer = window.Buffer;
|
|
} else {
|
|
Buffer = __webpack_require__(/*! buffer */ "?fbf1").Buffer;
|
|
}
|
|
} catch (e) {
|
|
}
|
|
|
|
BN.isBN = function isBN (num) {
|
|
if (num instanceof BN) {
|
|
return true;
|
|
}
|
|
|
|
return num !== null && typeof num === 'object' &&
|
|
num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
|
|
};
|
|
|
|
BN.max = function max (left, right) {
|
|
if (left.cmp(right) > 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.min = function min (left, right) {
|
|
if (left.cmp(right) < 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.prototype._init = function init (number, base, endian) {
|
|
if (typeof number === 'number') {
|
|
return this._initNumber(number, base, endian);
|
|
}
|
|
|
|
if (typeof number === 'object') {
|
|
return this._initArray(number, base, endian);
|
|
}
|
|
|
|
if (base === 'hex') {
|
|
base = 16;
|
|
}
|
|
assert(base === (base | 0) && base >= 2 && base <= 36);
|
|
|
|
number = number.toString().replace(/\s+/g, '');
|
|
var start = 0;
|
|
if (number[0] === '-') {
|
|
start++;
|
|
this.negative = 1;
|
|
}
|
|
|
|
if (start < number.length) {
|
|
if (base === 16) {
|
|
this._parseHex(number, start, endian);
|
|
} else {
|
|
this._parseBase(number, base, start);
|
|
if (endian === 'le') {
|
|
this._initArray(this.toArray(), base, endian);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
BN.prototype._initNumber = function _initNumber (number, base, endian) {
|
|
if (number < 0) {
|
|
this.negative = 1;
|
|
number = -number;
|
|
}
|
|
if (number < 0x4000000) {
|
|
this.words = [ number & 0x3ffffff ];
|
|
this.length = 1;
|
|
} else if (number < 0x10000000000000) {
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff
|
|
];
|
|
this.length = 2;
|
|
} else {
|
|
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff,
|
|
1
|
|
];
|
|
this.length = 3;
|
|
}
|
|
|
|
if (endian !== 'le') return;
|
|
|
|
// Reverse the bytes
|
|
this._initArray(this.toArray(), base, endian);
|
|
};
|
|
|
|
BN.prototype._initArray = function _initArray (number, base, endian) {
|
|
// Perhaps a Uint8Array
|
|
assert(typeof number.length === 'number');
|
|
if (number.length <= 0) {
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
return this;
|
|
}
|
|
|
|
this.length = Math.ceil(number.length / 3);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
var j, w;
|
|
var off = 0;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
|
|
w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
} else if (endian === 'le') {
|
|
for (i = 0, j = 0; i < number.length; i += 3) {
|
|
w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
return this.strip();
|
|
};
|
|
|
|
function parseHex4Bits (string, index) {
|
|
var c = string.charCodeAt(index);
|
|
// 'A' - 'F'
|
|
if (c >= 65 && c <= 70) {
|
|
return c - 55;
|
|
// 'a' - 'f'
|
|
} else if (c >= 97 && c <= 102) {
|
|
return c - 87;
|
|
// '0' - '9'
|
|
} else {
|
|
return (c - 48) & 0xf;
|
|
}
|
|
}
|
|
|
|
function parseHexByte (string, lowerBound, index) {
|
|
var r = parseHex4Bits(string, index);
|
|
if (index - 1 >= lowerBound) {
|
|
r |= parseHex4Bits(string, index - 1) << 4;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseHex = function _parseHex (number, start, endian) {
|
|
// Create possibly bigger array to ensure that it fits the number
|
|
this.length = Math.ceil((number.length - start) / 6);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
// 24-bits chunks
|
|
var off = 0;
|
|
var j = 0;
|
|
|
|
var w;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1; i >= start; i -= 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
} else {
|
|
var parseLength = number.length - start;
|
|
for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) {
|
|
w = parseHexByte(number, start, i) << off;
|
|
this.words[j] |= w & 0x3ffffff;
|
|
if (off >= 18) {
|
|
off -= 18;
|
|
j += 1;
|
|
this.words[j] |= w >>> 26;
|
|
} else {
|
|
off += 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
function parseBase (str, start, end, mul) {
|
|
var r = 0;
|
|
var len = Math.min(str.length, end);
|
|
for (var i = start; i < len; i++) {
|
|
var c = str.charCodeAt(i) - 48;
|
|
|
|
r *= mul;
|
|
|
|
// 'a'
|
|
if (c >= 49) {
|
|
r += c - 49 + 0xa;
|
|
|
|
// 'A'
|
|
} else if (c >= 17) {
|
|
r += c - 17 + 0xa;
|
|
|
|
// '0' - '9'
|
|
} else {
|
|
r += c;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseBase = function _parseBase (number, base, start) {
|
|
// Initialize as zero
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
|
|
// Find length of limb in base
|
|
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
|
|
limbLen++;
|
|
}
|
|
limbLen--;
|
|
limbPow = (limbPow / base) | 0;
|
|
|
|
var total = number.length - start;
|
|
var mod = total % limbLen;
|
|
var end = Math.min(total, total - mod) + start;
|
|
|
|
var word = 0;
|
|
for (var i = start; i < end; i += limbLen) {
|
|
word = parseBase(number, i, i + limbLen, base);
|
|
|
|
this.imuln(limbPow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
if (mod !== 0) {
|
|
var pow = 1;
|
|
word = parseBase(number, i, number.length, base);
|
|
|
|
for (i = 0; i < mod; i++) {
|
|
pow *= base;
|
|
}
|
|
|
|
this.imuln(pow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
this.strip();
|
|
};
|
|
|
|
BN.prototype.copy = function copy (dest) {
|
|
dest.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
dest.words[i] = this.words[i];
|
|
}
|
|
dest.length = this.length;
|
|
dest.negative = this.negative;
|
|
dest.red = this.red;
|
|
};
|
|
|
|
BN.prototype.clone = function clone () {
|
|
var r = new BN(null);
|
|
this.copy(r);
|
|
return r;
|
|
};
|
|
|
|
BN.prototype._expand = function _expand (size) {
|
|
while (this.length < size) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
// Remove leading `0` from `this`
|
|
BN.prototype.strip = function strip () {
|
|
while (this.length > 1 && this.words[this.length - 1] === 0) {
|
|
this.length--;
|
|
}
|
|
return this._normSign();
|
|
};
|
|
|
|
BN.prototype._normSign = function _normSign () {
|
|
// -0 = 0
|
|
if (this.length === 1 && this.words[0] === 0) {
|
|
this.negative = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.inspect = function inspect () {
|
|
return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
|
|
};
|
|
|
|
/*
|
|
|
|
var zeros = [];
|
|
var groupSizes = [];
|
|
var groupBases = [];
|
|
|
|
var s = '';
|
|
var i = -1;
|
|
while (++i < BN.wordSize) {
|
|
zeros[i] = s;
|
|
s += '0';
|
|
}
|
|
groupSizes[0] = 0;
|
|
groupSizes[1] = 0;
|
|
groupBases[0] = 0;
|
|
groupBases[1] = 0;
|
|
var base = 2 - 1;
|
|
while (++base < 36 + 1) {
|
|
var groupSize = 0;
|
|
var groupBase = 1;
|
|
while (groupBase < (1 << BN.wordSize) / base) {
|
|
groupBase *= base;
|
|
groupSize += 1;
|
|
}
|
|
groupSizes[base] = groupSize;
|
|
groupBases[base] = groupBase;
|
|
}
|
|
|
|
*/
|
|
|
|
var zeros = [
|
|
'',
|
|
'0',
|
|
'00',
|
|
'000',
|
|
'0000',
|
|
'00000',
|
|
'000000',
|
|
'0000000',
|
|
'00000000',
|
|
'000000000',
|
|
'0000000000',
|
|
'00000000000',
|
|
'000000000000',
|
|
'0000000000000',
|
|
'00000000000000',
|
|
'000000000000000',
|
|
'0000000000000000',
|
|
'00000000000000000',
|
|
'000000000000000000',
|
|
'0000000000000000000',
|
|
'00000000000000000000',
|
|
'000000000000000000000',
|
|
'0000000000000000000000',
|
|
'00000000000000000000000',
|
|
'000000000000000000000000',
|
|
'0000000000000000000000000'
|
|
];
|
|
|
|
var groupSizes = [
|
|
0, 0,
|
|
25, 16, 12, 11, 10, 9, 8,
|
|
8, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5
|
|
];
|
|
|
|
var groupBases = [
|
|
0, 0,
|
|
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
|
|
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
|
|
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
|
|
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
|
|
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
|
|
];
|
|
|
|
BN.prototype.toString = function toString (base, padding) {
|
|
base = base || 10;
|
|
padding = padding | 0 || 1;
|
|
|
|
var out;
|
|
if (base === 16 || base === 'hex') {
|
|
out = '';
|
|
var off = 0;
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = this.words[i];
|
|
var word = (((w << off) | carry) & 0xffffff).toString(16);
|
|
carry = (w >>> (24 - off)) & 0xffffff;
|
|
if (carry !== 0 || i !== this.length - 1) {
|
|
out = zeros[6 - word.length] + word + out;
|
|
} else {
|
|
out = word + out;
|
|
}
|
|
off += 2;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
i--;
|
|
}
|
|
}
|
|
if (carry !== 0) {
|
|
out = carry.toString(16) + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
if (base === (base | 0) && base >= 2 && base <= 36) {
|
|
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
|
|
var groupSize = groupSizes[base];
|
|
// var groupBase = Math.pow(base, groupSize);
|
|
var groupBase = groupBases[base];
|
|
out = '';
|
|
var c = this.clone();
|
|
c.negative = 0;
|
|
while (!c.isZero()) {
|
|
var r = c.modn(groupBase).toString(base);
|
|
c = c.idivn(groupBase);
|
|
|
|
if (!c.isZero()) {
|
|
out = zeros[groupSize - r.length] + r + out;
|
|
} else {
|
|
out = r + out;
|
|
}
|
|
}
|
|
if (this.isZero()) {
|
|
out = '0' + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
assert(false, 'Base should be between 2 and 36');
|
|
};
|
|
|
|
BN.prototype.toNumber = function toNumber () {
|
|
var ret = this.words[0];
|
|
if (this.length === 2) {
|
|
ret += this.words[1] * 0x4000000;
|
|
} else if (this.length === 3 && this.words[2] === 0x01) {
|
|
// NOTE: at this stage it is known that the top bit is set
|
|
ret += 0x10000000000000 + (this.words[1] * 0x4000000);
|
|
} else if (this.length > 2) {
|
|
assert(false, 'Number can only safely store up to 53 bits');
|
|
}
|
|
return (this.negative !== 0) ? -ret : ret;
|
|
};
|
|
|
|
BN.prototype.toJSON = function toJSON () {
|
|
return this.toString(16);
|
|
};
|
|
|
|
BN.prototype.toBuffer = function toBuffer (endian, length) {
|
|
assert(typeof Buffer !== 'undefined');
|
|
return this.toArrayLike(Buffer, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArray = function toArray (endian, length) {
|
|
return this.toArrayLike(Array, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
|
|
var byteLength = this.byteLength();
|
|
var reqLength = length || Math.max(1, byteLength);
|
|
assert(byteLength <= reqLength, 'byte array longer than desired length');
|
|
assert(reqLength > 0, 'Requested array length <= 0');
|
|
|
|
this.strip();
|
|
var littleEndian = endian === 'le';
|
|
var res = new ArrayType(reqLength);
|
|
|
|
var b, i;
|
|
var q = this.clone();
|
|
if (!littleEndian) {
|
|
// Assume big-endian
|
|
for (i = 0; i < reqLength - byteLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[reqLength - i - 1] = b;
|
|
}
|
|
} else {
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[i] = b;
|
|
}
|
|
|
|
for (; i < reqLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
if (Math.clz32) {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
return 32 - Math.clz32(w);
|
|
};
|
|
} else {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
var t = w;
|
|
var r = 0;
|
|
if (t >= 0x1000) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if (t >= 0x40) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if (t >= 0x8) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if (t >= 0x02) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
return r + t;
|
|
};
|
|
}
|
|
|
|
BN.prototype._zeroBits = function _zeroBits (w) {
|
|
// Short-cut
|
|
if (w === 0) return 26;
|
|
|
|
var t = w;
|
|
var r = 0;
|
|
if ((t & 0x1fff) === 0) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if ((t & 0x7f) === 0) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if ((t & 0xf) === 0) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if ((t & 0x3) === 0) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
if ((t & 0x1) === 0) {
|
|
r++;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
// Return number of used bits in a BN
|
|
BN.prototype.bitLength = function bitLength () {
|
|
var w = this.words[this.length - 1];
|
|
var hi = this._countBits(w);
|
|
return (this.length - 1) * 26 + hi;
|
|
};
|
|
|
|
function toBitArray (num) {
|
|
var w = new Array(num.bitLength());
|
|
|
|
for (var bit = 0; bit < w.length; bit++) {
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
// Number of trailing zero bits
|
|
BN.prototype.zeroBits = function zeroBits () {
|
|
if (this.isZero()) return 0;
|
|
|
|
var r = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var b = this._zeroBits(this.words[i]);
|
|
r += b;
|
|
if (b !== 26) break;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
BN.prototype.byteLength = function byteLength () {
|
|
return Math.ceil(this.bitLength() / 8);
|
|
};
|
|
|
|
BN.prototype.toTwos = function toTwos (width) {
|
|
if (this.negative !== 0) {
|
|
return this.abs().inotn(width).iaddn(1);
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.fromTwos = function fromTwos (width) {
|
|
if (this.testn(width - 1)) {
|
|
return this.notn(width).iaddn(1).ineg();
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.isNeg = function isNeg () {
|
|
return this.negative !== 0;
|
|
};
|
|
|
|
// Return negative clone of `this`
|
|
BN.prototype.neg = function neg () {
|
|
return this.clone().ineg();
|
|
};
|
|
|
|
BN.prototype.ineg = function ineg () {
|
|
if (!this.isZero()) {
|
|
this.negative ^= 1;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Or `num` with `this` in-place
|
|
BN.prototype.iuor = function iuor (num) {
|
|
while (this.length < num.length) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
|
|
for (var i = 0; i < num.length; i++) {
|
|
this.words[i] = this.words[i] | num.words[i];
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ior = function ior (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuor(num);
|
|
};
|
|
|
|
// Or `num` with `this`
|
|
BN.prototype.or = function or (num) {
|
|
if (this.length > num.length) return this.clone().ior(num);
|
|
return num.clone().ior(this);
|
|
};
|
|
|
|
BN.prototype.uor = function uor (num) {
|
|
if (this.length > num.length) return this.clone().iuor(num);
|
|
return num.clone().iuor(this);
|
|
};
|
|
|
|
// And `num` with `this` in-place
|
|
BN.prototype.iuand = function iuand (num) {
|
|
// b = min-length(num, this)
|
|
var b;
|
|
if (this.length > num.length) {
|
|
b = num;
|
|
} else {
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = this.words[i] & num.words[i];
|
|
}
|
|
|
|
this.length = b.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.iand = function iand (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuand(num);
|
|
};
|
|
|
|
// And `num` with `this`
|
|
BN.prototype.and = function and (num) {
|
|
if (this.length > num.length) return this.clone().iand(num);
|
|
return num.clone().iand(this);
|
|
};
|
|
|
|
BN.prototype.uand = function uand (num) {
|
|
if (this.length > num.length) return this.clone().iuand(num);
|
|
return num.clone().iuand(this);
|
|
};
|
|
|
|
// Xor `num` with `this` in-place
|
|
BN.prototype.iuxor = function iuxor (num) {
|
|
// a.length > b.length
|
|
var a;
|
|
var b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = a.words[i] ^ b.words[i];
|
|
}
|
|
|
|
if (this !== a) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = a.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ixor = function ixor (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuxor(num);
|
|
};
|
|
|
|
// Xor `num` with `this`
|
|
BN.prototype.xor = function xor (num) {
|
|
if (this.length > num.length) return this.clone().ixor(num);
|
|
return num.clone().ixor(this);
|
|
};
|
|
|
|
BN.prototype.uxor = function uxor (num) {
|
|
if (this.length > num.length) return this.clone().iuxor(num);
|
|
return num.clone().iuxor(this);
|
|
};
|
|
|
|
// Not ``this`` with ``width`` bitwidth
|
|
BN.prototype.inotn = function inotn (width) {
|
|
assert(typeof width === 'number' && width >= 0);
|
|
|
|
var bytesNeeded = Math.ceil(width / 26) | 0;
|
|
var bitsLeft = width % 26;
|
|
|
|
// Extend the buffer with leading zeroes
|
|
this._expand(bytesNeeded);
|
|
|
|
if (bitsLeft > 0) {
|
|
bytesNeeded--;
|
|
}
|
|
|
|
// Handle complete words
|
|
for (var i = 0; i < bytesNeeded; i++) {
|
|
this.words[i] = ~this.words[i] & 0x3ffffff;
|
|
}
|
|
|
|
// Handle the residue
|
|
if (bitsLeft > 0) {
|
|
this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
|
|
}
|
|
|
|
// And remove leading zeroes
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.notn = function notn (width) {
|
|
return this.clone().inotn(width);
|
|
};
|
|
|
|
// Set `bit` of `this`
|
|
BN.prototype.setn = function setn (bit, val) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
this._expand(off + 1);
|
|
|
|
if (val) {
|
|
this.words[off] = this.words[off] | (1 << wbit);
|
|
} else {
|
|
this.words[off] = this.words[off] & ~(1 << wbit);
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Add `num` to `this` in-place
|
|
BN.prototype.iadd = function iadd (num) {
|
|
var r;
|
|
|
|
// negative + positive
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
this.negative = 0;
|
|
r = this.isub(num);
|
|
this.negative ^= 1;
|
|
return this._normSign();
|
|
|
|
// positive + negative
|
|
} else if (this.negative === 0 && num.negative !== 0) {
|
|
num.negative = 0;
|
|
r = this.isub(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
}
|
|
|
|
// a.length > b.length
|
|
var a, b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
|
|
this.length = a.length;
|
|
if (carry !== 0) {
|
|
this.words[this.length] = carry;
|
|
this.length++;
|
|
// Copy the rest of the words
|
|
} else if (a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Add `num` to `this`
|
|
BN.prototype.add = function add (num) {
|
|
var res;
|
|
if (num.negative !== 0 && this.negative === 0) {
|
|
num.negative = 0;
|
|
res = this.sub(num);
|
|
num.negative ^= 1;
|
|
return res;
|
|
} else if (num.negative === 0 && this.negative !== 0) {
|
|
this.negative = 0;
|
|
res = num.sub(this);
|
|
this.negative = 1;
|
|
return res;
|
|
}
|
|
|
|
if (this.length > num.length) return this.clone().iadd(num);
|
|
|
|
return num.clone().iadd(this);
|
|
};
|
|
|
|
// Subtract `num` from `this` in-place
|
|
BN.prototype.isub = function isub (num) {
|
|
// this - (-num) = this + num
|
|
if (num.negative !== 0) {
|
|
num.negative = 0;
|
|
var r = this.iadd(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
|
|
// -this - num = -(this + num)
|
|
} else if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iadd(num);
|
|
this.negative = 1;
|
|
return this._normSign();
|
|
}
|
|
|
|
// At this point both numbers are positive
|
|
var cmp = this.cmp(num);
|
|
|
|
// Optimization - zeroify
|
|
if (cmp === 0) {
|
|
this.negative = 0;
|
|
this.length = 1;
|
|
this.words[0] = 0;
|
|
return this;
|
|
}
|
|
|
|
// a > b
|
|
var a, b;
|
|
if (cmp > 0) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
|
|
// Copy rest of the words
|
|
if (carry === 0 && i < a.length && a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = Math.max(this.length, i);
|
|
|
|
if (a !== this) {
|
|
this.negative = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Subtract `num` from `this`
|
|
BN.prototype.sub = function sub (num) {
|
|
return this.clone().isub(num);
|
|
};
|
|
|
|
function smallMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
var len = (self.length + num.length) | 0;
|
|
out.length = len;
|
|
len = (len - 1) | 0;
|
|
|
|
// Peel one iteration (compiler can't do it, because of code complexity)
|
|
var a = self.words[0] | 0;
|
|
var b = num.words[0] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
var carry = (r / 0x4000000) | 0;
|
|
out.words[0] = lo;
|
|
|
|
for (var k = 1; k < len; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = carry >>> 26;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = (k - j) | 0;
|
|
a = self.words[i] | 0;
|
|
b = num.words[j] | 0;
|
|
r = a * b + rword;
|
|
ncarry += (r / 0x4000000) | 0;
|
|
rword = r & 0x3ffffff;
|
|
}
|
|
out.words[k] = rword | 0;
|
|
carry = ncarry | 0;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry | 0;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
// TODO(indutny): it may be reasonable to omit it for users who don't need
|
|
// to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
|
|
// multiplication (like elliptic secp256k1).
|
|
var comb10MulTo = function comb10MulTo (self, num, out) {
|
|
var a = self.words;
|
|
var b = num.words;
|
|
var o = out.words;
|
|
var c = 0;
|
|
var lo;
|
|
var mid;
|
|
var hi;
|
|
var a0 = a[0] | 0;
|
|
var al0 = a0 & 0x1fff;
|
|
var ah0 = a0 >>> 13;
|
|
var a1 = a[1] | 0;
|
|
var al1 = a1 & 0x1fff;
|
|
var ah1 = a1 >>> 13;
|
|
var a2 = a[2] | 0;
|
|
var al2 = a2 & 0x1fff;
|
|
var ah2 = a2 >>> 13;
|
|
var a3 = a[3] | 0;
|
|
var al3 = a3 & 0x1fff;
|
|
var ah3 = a3 >>> 13;
|
|
var a4 = a[4] | 0;
|
|
var al4 = a4 & 0x1fff;
|
|
var ah4 = a4 >>> 13;
|
|
var a5 = a[5] | 0;
|
|
var al5 = a5 & 0x1fff;
|
|
var ah5 = a5 >>> 13;
|
|
var a6 = a[6] | 0;
|
|
var al6 = a6 & 0x1fff;
|
|
var ah6 = a6 >>> 13;
|
|
var a7 = a[7] | 0;
|
|
var al7 = a7 & 0x1fff;
|
|
var ah7 = a7 >>> 13;
|
|
var a8 = a[8] | 0;
|
|
var al8 = a8 & 0x1fff;
|
|
var ah8 = a8 >>> 13;
|
|
var a9 = a[9] | 0;
|
|
var al9 = a9 & 0x1fff;
|
|
var ah9 = a9 >>> 13;
|
|
var b0 = b[0] | 0;
|
|
var bl0 = b0 & 0x1fff;
|
|
var bh0 = b0 >>> 13;
|
|
var b1 = b[1] | 0;
|
|
var bl1 = b1 & 0x1fff;
|
|
var bh1 = b1 >>> 13;
|
|
var b2 = b[2] | 0;
|
|
var bl2 = b2 & 0x1fff;
|
|
var bh2 = b2 >>> 13;
|
|
var b3 = b[3] | 0;
|
|
var bl3 = b3 & 0x1fff;
|
|
var bh3 = b3 >>> 13;
|
|
var b4 = b[4] | 0;
|
|
var bl4 = b4 & 0x1fff;
|
|
var bh4 = b4 >>> 13;
|
|
var b5 = b[5] | 0;
|
|
var bl5 = b5 & 0x1fff;
|
|
var bh5 = b5 >>> 13;
|
|
var b6 = b[6] | 0;
|
|
var bl6 = b6 & 0x1fff;
|
|
var bh6 = b6 >>> 13;
|
|
var b7 = b[7] | 0;
|
|
var bl7 = b7 & 0x1fff;
|
|
var bh7 = b7 >>> 13;
|
|
var b8 = b[8] | 0;
|
|
var bl8 = b8 & 0x1fff;
|
|
var bh8 = b8 >>> 13;
|
|
var b9 = b[9] | 0;
|
|
var bl9 = b9 & 0x1fff;
|
|
var bh9 = b9 >>> 13;
|
|
|
|
out.negative = self.negative ^ num.negative;
|
|
out.length = 19;
|
|
/* k = 0 */
|
|
lo = Math.imul(al0, bl0);
|
|
mid = Math.imul(al0, bh0);
|
|
mid = (mid + Math.imul(ah0, bl0)) | 0;
|
|
hi = Math.imul(ah0, bh0);
|
|
var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
|
|
w0 &= 0x3ffffff;
|
|
/* k = 1 */
|
|
lo = Math.imul(al1, bl0);
|
|
mid = Math.imul(al1, bh0);
|
|
mid = (mid + Math.imul(ah1, bl0)) | 0;
|
|
hi = Math.imul(ah1, bh0);
|
|
lo = (lo + Math.imul(al0, bl1)) | 0;
|
|
mid = (mid + Math.imul(al0, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh1)) | 0;
|
|
var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
|
|
w1 &= 0x3ffffff;
|
|
/* k = 2 */
|
|
lo = Math.imul(al2, bl0);
|
|
mid = Math.imul(al2, bh0);
|
|
mid = (mid + Math.imul(ah2, bl0)) | 0;
|
|
hi = Math.imul(ah2, bh0);
|
|
lo = (lo + Math.imul(al1, bl1)) | 0;
|
|
mid = (mid + Math.imul(al1, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh1)) | 0;
|
|
lo = (lo + Math.imul(al0, bl2)) | 0;
|
|
mid = (mid + Math.imul(al0, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh2)) | 0;
|
|
var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
|
|
w2 &= 0x3ffffff;
|
|
/* k = 3 */
|
|
lo = Math.imul(al3, bl0);
|
|
mid = Math.imul(al3, bh0);
|
|
mid = (mid + Math.imul(ah3, bl0)) | 0;
|
|
hi = Math.imul(ah3, bh0);
|
|
lo = (lo + Math.imul(al2, bl1)) | 0;
|
|
mid = (mid + Math.imul(al2, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh1)) | 0;
|
|
lo = (lo + Math.imul(al1, bl2)) | 0;
|
|
mid = (mid + Math.imul(al1, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh2)) | 0;
|
|
lo = (lo + Math.imul(al0, bl3)) | 0;
|
|
mid = (mid + Math.imul(al0, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh3)) | 0;
|
|
var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
|
|
w3 &= 0x3ffffff;
|
|
/* k = 4 */
|
|
lo = Math.imul(al4, bl0);
|
|
mid = Math.imul(al4, bh0);
|
|
mid = (mid + Math.imul(ah4, bl0)) | 0;
|
|
hi = Math.imul(ah4, bh0);
|
|
lo = (lo + Math.imul(al3, bl1)) | 0;
|
|
mid = (mid + Math.imul(al3, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh1)) | 0;
|
|
lo = (lo + Math.imul(al2, bl2)) | 0;
|
|
mid = (mid + Math.imul(al2, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh2)) | 0;
|
|
lo = (lo + Math.imul(al1, bl3)) | 0;
|
|
mid = (mid + Math.imul(al1, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh3)) | 0;
|
|
lo = (lo + Math.imul(al0, bl4)) | 0;
|
|
mid = (mid + Math.imul(al0, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh4)) | 0;
|
|
var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
|
|
w4 &= 0x3ffffff;
|
|
/* k = 5 */
|
|
lo = Math.imul(al5, bl0);
|
|
mid = Math.imul(al5, bh0);
|
|
mid = (mid + Math.imul(ah5, bl0)) | 0;
|
|
hi = Math.imul(ah5, bh0);
|
|
lo = (lo + Math.imul(al4, bl1)) | 0;
|
|
mid = (mid + Math.imul(al4, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh1)) | 0;
|
|
lo = (lo + Math.imul(al3, bl2)) | 0;
|
|
mid = (mid + Math.imul(al3, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh2)) | 0;
|
|
lo = (lo + Math.imul(al2, bl3)) | 0;
|
|
mid = (mid + Math.imul(al2, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh3)) | 0;
|
|
lo = (lo + Math.imul(al1, bl4)) | 0;
|
|
mid = (mid + Math.imul(al1, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh4)) | 0;
|
|
lo = (lo + Math.imul(al0, bl5)) | 0;
|
|
mid = (mid + Math.imul(al0, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh5)) | 0;
|
|
var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
|
|
w5 &= 0x3ffffff;
|
|
/* k = 6 */
|
|
lo = Math.imul(al6, bl0);
|
|
mid = Math.imul(al6, bh0);
|
|
mid = (mid + Math.imul(ah6, bl0)) | 0;
|
|
hi = Math.imul(ah6, bh0);
|
|
lo = (lo + Math.imul(al5, bl1)) | 0;
|
|
mid = (mid + Math.imul(al5, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh1)) | 0;
|
|
lo = (lo + Math.imul(al4, bl2)) | 0;
|
|
mid = (mid + Math.imul(al4, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh2)) | 0;
|
|
lo = (lo + Math.imul(al3, bl3)) | 0;
|
|
mid = (mid + Math.imul(al3, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh3)) | 0;
|
|
lo = (lo + Math.imul(al2, bl4)) | 0;
|
|
mid = (mid + Math.imul(al2, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh4)) | 0;
|
|
lo = (lo + Math.imul(al1, bl5)) | 0;
|
|
mid = (mid + Math.imul(al1, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh5)) | 0;
|
|
lo = (lo + Math.imul(al0, bl6)) | 0;
|
|
mid = (mid + Math.imul(al0, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh6)) | 0;
|
|
var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
|
|
w6 &= 0x3ffffff;
|
|
/* k = 7 */
|
|
lo = Math.imul(al7, bl0);
|
|
mid = Math.imul(al7, bh0);
|
|
mid = (mid + Math.imul(ah7, bl0)) | 0;
|
|
hi = Math.imul(ah7, bh0);
|
|
lo = (lo + Math.imul(al6, bl1)) | 0;
|
|
mid = (mid + Math.imul(al6, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh1)) | 0;
|
|
lo = (lo + Math.imul(al5, bl2)) | 0;
|
|
mid = (mid + Math.imul(al5, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh2)) | 0;
|
|
lo = (lo + Math.imul(al4, bl3)) | 0;
|
|
mid = (mid + Math.imul(al4, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh3)) | 0;
|
|
lo = (lo + Math.imul(al3, bl4)) | 0;
|
|
mid = (mid + Math.imul(al3, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh4)) | 0;
|
|
lo = (lo + Math.imul(al2, bl5)) | 0;
|
|
mid = (mid + Math.imul(al2, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh5)) | 0;
|
|
lo = (lo + Math.imul(al1, bl6)) | 0;
|
|
mid = (mid + Math.imul(al1, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh6)) | 0;
|
|
lo = (lo + Math.imul(al0, bl7)) | 0;
|
|
mid = (mid + Math.imul(al0, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh7)) | 0;
|
|
var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
|
|
w7 &= 0x3ffffff;
|
|
/* k = 8 */
|
|
lo = Math.imul(al8, bl0);
|
|
mid = Math.imul(al8, bh0);
|
|
mid = (mid + Math.imul(ah8, bl0)) | 0;
|
|
hi = Math.imul(ah8, bh0);
|
|
lo = (lo + Math.imul(al7, bl1)) | 0;
|
|
mid = (mid + Math.imul(al7, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh1)) | 0;
|
|
lo = (lo + Math.imul(al6, bl2)) | 0;
|
|
mid = (mid + Math.imul(al6, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh2)) | 0;
|
|
lo = (lo + Math.imul(al5, bl3)) | 0;
|
|
mid = (mid + Math.imul(al5, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh3)) | 0;
|
|
lo = (lo + Math.imul(al4, bl4)) | 0;
|
|
mid = (mid + Math.imul(al4, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh4)) | 0;
|
|
lo = (lo + Math.imul(al3, bl5)) | 0;
|
|
mid = (mid + Math.imul(al3, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh5)) | 0;
|
|
lo = (lo + Math.imul(al2, bl6)) | 0;
|
|
mid = (mid + Math.imul(al2, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh6)) | 0;
|
|
lo = (lo + Math.imul(al1, bl7)) | 0;
|
|
mid = (mid + Math.imul(al1, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh7)) | 0;
|
|
lo = (lo + Math.imul(al0, bl8)) | 0;
|
|
mid = (mid + Math.imul(al0, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh8)) | 0;
|
|
var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
|
|
w8 &= 0x3ffffff;
|
|
/* k = 9 */
|
|
lo = Math.imul(al9, bl0);
|
|
mid = Math.imul(al9, bh0);
|
|
mid = (mid + Math.imul(ah9, bl0)) | 0;
|
|
hi = Math.imul(ah9, bh0);
|
|
lo = (lo + Math.imul(al8, bl1)) | 0;
|
|
mid = (mid + Math.imul(al8, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh1)) | 0;
|
|
lo = (lo + Math.imul(al7, bl2)) | 0;
|
|
mid = (mid + Math.imul(al7, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh2)) | 0;
|
|
lo = (lo + Math.imul(al6, bl3)) | 0;
|
|
mid = (mid + Math.imul(al6, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh3)) | 0;
|
|
lo = (lo + Math.imul(al5, bl4)) | 0;
|
|
mid = (mid + Math.imul(al5, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh4)) | 0;
|
|
lo = (lo + Math.imul(al4, bl5)) | 0;
|
|
mid = (mid + Math.imul(al4, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh5)) | 0;
|
|
lo = (lo + Math.imul(al3, bl6)) | 0;
|
|
mid = (mid + Math.imul(al3, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh6)) | 0;
|
|
lo = (lo + Math.imul(al2, bl7)) | 0;
|
|
mid = (mid + Math.imul(al2, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh7)) | 0;
|
|
lo = (lo + Math.imul(al1, bl8)) | 0;
|
|
mid = (mid + Math.imul(al1, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh8)) | 0;
|
|
lo = (lo + Math.imul(al0, bl9)) | 0;
|
|
mid = (mid + Math.imul(al0, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh9)) | 0;
|
|
var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
|
|
w9 &= 0x3ffffff;
|
|
/* k = 10 */
|
|
lo = Math.imul(al9, bl1);
|
|
mid = Math.imul(al9, bh1);
|
|
mid = (mid + Math.imul(ah9, bl1)) | 0;
|
|
hi = Math.imul(ah9, bh1);
|
|
lo = (lo + Math.imul(al8, bl2)) | 0;
|
|
mid = (mid + Math.imul(al8, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh2)) | 0;
|
|
lo = (lo + Math.imul(al7, bl3)) | 0;
|
|
mid = (mid + Math.imul(al7, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh3)) | 0;
|
|
lo = (lo + Math.imul(al6, bl4)) | 0;
|
|
mid = (mid + Math.imul(al6, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh4)) | 0;
|
|
lo = (lo + Math.imul(al5, bl5)) | 0;
|
|
mid = (mid + Math.imul(al5, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh5)) | 0;
|
|
lo = (lo + Math.imul(al4, bl6)) | 0;
|
|
mid = (mid + Math.imul(al4, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh6)) | 0;
|
|
lo = (lo + Math.imul(al3, bl7)) | 0;
|
|
mid = (mid + Math.imul(al3, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh7)) | 0;
|
|
lo = (lo + Math.imul(al2, bl8)) | 0;
|
|
mid = (mid + Math.imul(al2, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh8)) | 0;
|
|
lo = (lo + Math.imul(al1, bl9)) | 0;
|
|
mid = (mid + Math.imul(al1, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh9)) | 0;
|
|
var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
|
|
w10 &= 0x3ffffff;
|
|
/* k = 11 */
|
|
lo = Math.imul(al9, bl2);
|
|
mid = Math.imul(al9, bh2);
|
|
mid = (mid + Math.imul(ah9, bl2)) | 0;
|
|
hi = Math.imul(ah9, bh2);
|
|
lo = (lo + Math.imul(al8, bl3)) | 0;
|
|
mid = (mid + Math.imul(al8, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh3)) | 0;
|
|
lo = (lo + Math.imul(al7, bl4)) | 0;
|
|
mid = (mid + Math.imul(al7, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh4)) | 0;
|
|
lo = (lo + Math.imul(al6, bl5)) | 0;
|
|
mid = (mid + Math.imul(al6, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh5)) | 0;
|
|
lo = (lo + Math.imul(al5, bl6)) | 0;
|
|
mid = (mid + Math.imul(al5, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh6)) | 0;
|
|
lo = (lo + Math.imul(al4, bl7)) | 0;
|
|
mid = (mid + Math.imul(al4, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh7)) | 0;
|
|
lo = (lo + Math.imul(al3, bl8)) | 0;
|
|
mid = (mid + Math.imul(al3, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh8)) | 0;
|
|
lo = (lo + Math.imul(al2, bl9)) | 0;
|
|
mid = (mid + Math.imul(al2, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh9)) | 0;
|
|
var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
|
|
w11 &= 0x3ffffff;
|
|
/* k = 12 */
|
|
lo = Math.imul(al9, bl3);
|
|
mid = Math.imul(al9, bh3);
|
|
mid = (mid + Math.imul(ah9, bl3)) | 0;
|
|
hi = Math.imul(ah9, bh3);
|
|
lo = (lo + Math.imul(al8, bl4)) | 0;
|
|
mid = (mid + Math.imul(al8, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh4)) | 0;
|
|
lo = (lo + Math.imul(al7, bl5)) | 0;
|
|
mid = (mid + Math.imul(al7, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh5)) | 0;
|
|
lo = (lo + Math.imul(al6, bl6)) | 0;
|
|
mid = (mid + Math.imul(al6, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh6)) | 0;
|
|
lo = (lo + Math.imul(al5, bl7)) | 0;
|
|
mid = (mid + Math.imul(al5, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh7)) | 0;
|
|
lo = (lo + Math.imul(al4, bl8)) | 0;
|
|
mid = (mid + Math.imul(al4, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh8)) | 0;
|
|
lo = (lo + Math.imul(al3, bl9)) | 0;
|
|
mid = (mid + Math.imul(al3, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh9)) | 0;
|
|
var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
|
|
w12 &= 0x3ffffff;
|
|
/* k = 13 */
|
|
lo = Math.imul(al9, bl4);
|
|
mid = Math.imul(al9, bh4);
|
|
mid = (mid + Math.imul(ah9, bl4)) | 0;
|
|
hi = Math.imul(ah9, bh4);
|
|
lo = (lo + Math.imul(al8, bl5)) | 0;
|
|
mid = (mid + Math.imul(al8, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh5)) | 0;
|
|
lo = (lo + Math.imul(al7, bl6)) | 0;
|
|
mid = (mid + Math.imul(al7, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh6)) | 0;
|
|
lo = (lo + Math.imul(al6, bl7)) | 0;
|
|
mid = (mid + Math.imul(al6, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh7)) | 0;
|
|
lo = (lo + Math.imul(al5, bl8)) | 0;
|
|
mid = (mid + Math.imul(al5, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh8)) | 0;
|
|
lo = (lo + Math.imul(al4, bl9)) | 0;
|
|
mid = (mid + Math.imul(al4, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh9)) | 0;
|
|
var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
|
|
w13 &= 0x3ffffff;
|
|
/* k = 14 */
|
|
lo = Math.imul(al9, bl5);
|
|
mid = Math.imul(al9, bh5);
|
|
mid = (mid + Math.imul(ah9, bl5)) | 0;
|
|
hi = Math.imul(ah9, bh5);
|
|
lo = (lo + Math.imul(al8, bl6)) | 0;
|
|
mid = (mid + Math.imul(al8, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh6)) | 0;
|
|
lo = (lo + Math.imul(al7, bl7)) | 0;
|
|
mid = (mid + Math.imul(al7, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh7)) | 0;
|
|
lo = (lo + Math.imul(al6, bl8)) | 0;
|
|
mid = (mid + Math.imul(al6, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh8)) | 0;
|
|
lo = (lo + Math.imul(al5, bl9)) | 0;
|
|
mid = (mid + Math.imul(al5, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh9)) | 0;
|
|
var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
|
|
w14 &= 0x3ffffff;
|
|
/* k = 15 */
|
|
lo = Math.imul(al9, bl6);
|
|
mid = Math.imul(al9, bh6);
|
|
mid = (mid + Math.imul(ah9, bl6)) | 0;
|
|
hi = Math.imul(ah9, bh6);
|
|
lo = (lo + Math.imul(al8, bl7)) | 0;
|
|
mid = (mid + Math.imul(al8, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh7)) | 0;
|
|
lo = (lo + Math.imul(al7, bl8)) | 0;
|
|
mid = (mid + Math.imul(al7, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh8)) | 0;
|
|
lo = (lo + Math.imul(al6, bl9)) | 0;
|
|
mid = (mid + Math.imul(al6, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh9)) | 0;
|
|
var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
|
|
w15 &= 0x3ffffff;
|
|
/* k = 16 */
|
|
lo = Math.imul(al9, bl7);
|
|
mid = Math.imul(al9, bh7);
|
|
mid = (mid + Math.imul(ah9, bl7)) | 0;
|
|
hi = Math.imul(ah9, bh7);
|
|
lo = (lo + Math.imul(al8, bl8)) | 0;
|
|
mid = (mid + Math.imul(al8, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh8)) | 0;
|
|
lo = (lo + Math.imul(al7, bl9)) | 0;
|
|
mid = (mid + Math.imul(al7, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh9)) | 0;
|
|
var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
|
|
w16 &= 0x3ffffff;
|
|
/* k = 17 */
|
|
lo = Math.imul(al9, bl8);
|
|
mid = Math.imul(al9, bh8);
|
|
mid = (mid + Math.imul(ah9, bl8)) | 0;
|
|
hi = Math.imul(ah9, bh8);
|
|
lo = (lo + Math.imul(al8, bl9)) | 0;
|
|
mid = (mid + Math.imul(al8, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh9)) | 0;
|
|
var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
|
|
w17 &= 0x3ffffff;
|
|
/* k = 18 */
|
|
lo = Math.imul(al9, bl9);
|
|
mid = Math.imul(al9, bh9);
|
|
mid = (mid + Math.imul(ah9, bl9)) | 0;
|
|
hi = Math.imul(ah9, bh9);
|
|
var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
|
|
w18 &= 0x3ffffff;
|
|
o[0] = w0;
|
|
o[1] = w1;
|
|
o[2] = w2;
|
|
o[3] = w3;
|
|
o[4] = w4;
|
|
o[5] = w5;
|
|
o[6] = w6;
|
|
o[7] = w7;
|
|
o[8] = w8;
|
|
o[9] = w9;
|
|
o[10] = w10;
|
|
o[11] = w11;
|
|
o[12] = w12;
|
|
o[13] = w13;
|
|
o[14] = w14;
|
|
o[15] = w15;
|
|
o[16] = w16;
|
|
o[17] = w17;
|
|
o[18] = w18;
|
|
if (c !== 0) {
|
|
o[19] = c;
|
|
out.length++;
|
|
}
|
|
return out;
|
|
};
|
|
|
|
// Polyfill comb
|
|
if (!Math.imul) {
|
|
comb10MulTo = smallMulTo;
|
|
}
|
|
|
|
function bigMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
out.length = self.length + num.length;
|
|
|
|
var carry = 0;
|
|
var hncarry = 0;
|
|
for (var k = 0; k < out.length - 1; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = hncarry;
|
|
hncarry = 0;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = k - j;
|
|
var a = self.words[i] | 0;
|
|
var b = num.words[j] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
|
|
lo = (lo + rword) | 0;
|
|
rword = lo & 0x3ffffff;
|
|
ncarry = (ncarry + (lo >>> 26)) | 0;
|
|
|
|
hncarry += ncarry >>> 26;
|
|
ncarry &= 0x3ffffff;
|
|
}
|
|
out.words[k] = rword;
|
|
carry = ncarry;
|
|
ncarry = hncarry;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
function jumboMulTo (self, num, out) {
|
|
var fftm = new FFTM();
|
|
return fftm.mulp(self, num, out);
|
|
}
|
|
|
|
BN.prototype.mulTo = function mulTo (num, out) {
|
|
var res;
|
|
var len = this.length + num.length;
|
|
if (this.length === 10 && num.length === 10) {
|
|
res = comb10MulTo(this, num, out);
|
|
} else if (len < 63) {
|
|
res = smallMulTo(this, num, out);
|
|
} else if (len < 1024) {
|
|
res = bigMulTo(this, num, out);
|
|
} else {
|
|
res = jumboMulTo(this, num, out);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Cooley-Tukey algorithm for FFT
|
|
// slightly revisited to rely on looping instead of recursion
|
|
|
|
function FFTM (x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
FFTM.prototype.makeRBT = function makeRBT (N) {
|
|
var t = new Array(N);
|
|
var l = BN.prototype._countBits(N) - 1;
|
|
for (var i = 0; i < N; i++) {
|
|
t[i] = this.revBin(i, l, N);
|
|
}
|
|
|
|
return t;
|
|
};
|
|
|
|
// Returns binary-reversed representation of `x`
|
|
FFTM.prototype.revBin = function revBin (x, l, N) {
|
|
if (x === 0 || x === N - 1) return x;
|
|
|
|
var rb = 0;
|
|
for (var i = 0; i < l; i++) {
|
|
rb |= (x & 1) << (l - i - 1);
|
|
x >>= 1;
|
|
}
|
|
|
|
return rb;
|
|
};
|
|
|
|
// Performs "tweedling" phase, therefore 'emulating'
|
|
// behaviour of the recursive algorithm
|
|
FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
|
|
for (var i = 0; i < N; i++) {
|
|
rtws[i] = rws[rbt[i]];
|
|
itws[i] = iws[rbt[i]];
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
|
|
this.permute(rbt, rws, iws, rtws, itws, N);
|
|
|
|
for (var s = 1; s < N; s <<= 1) {
|
|
var l = s << 1;
|
|
|
|
var rtwdf = Math.cos(2 * Math.PI / l);
|
|
var itwdf = Math.sin(2 * Math.PI / l);
|
|
|
|
for (var p = 0; p < N; p += l) {
|
|
var rtwdf_ = rtwdf;
|
|
var itwdf_ = itwdf;
|
|
|
|
for (var j = 0; j < s; j++) {
|
|
var re = rtws[p + j];
|
|
var ie = itws[p + j];
|
|
|
|
var ro = rtws[p + j + s];
|
|
var io = itws[p + j + s];
|
|
|
|
var rx = rtwdf_ * ro - itwdf_ * io;
|
|
|
|
io = rtwdf_ * io + itwdf_ * ro;
|
|
ro = rx;
|
|
|
|
rtws[p + j] = re + ro;
|
|
itws[p + j] = ie + io;
|
|
|
|
rtws[p + j + s] = re - ro;
|
|
itws[p + j + s] = ie - io;
|
|
|
|
/* jshint maxdepth : false */
|
|
if (j !== l) {
|
|
rx = rtwdf * rtwdf_ - itwdf * itwdf_;
|
|
|
|
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
|
|
rtwdf_ = rx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
|
|
var N = Math.max(m, n) | 1;
|
|
var odd = N & 1;
|
|
var i = 0;
|
|
for (N = N / 2 | 0; N; N = N >>> 1) {
|
|
i++;
|
|
}
|
|
|
|
return 1 << i + 1 + odd;
|
|
};
|
|
|
|
FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
|
|
if (N <= 1) return;
|
|
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var t = rws[i];
|
|
|
|
rws[i] = rws[N - i - 1];
|
|
rws[N - i - 1] = t;
|
|
|
|
t = iws[i];
|
|
|
|
iws[i] = -iws[N - i - 1];
|
|
iws[N - i - 1] = -t;
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.normalize13b = function normalize13b (ws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
|
|
Math.round(ws[2 * i] / N) +
|
|
carry;
|
|
|
|
ws[i] = w & 0x3ffffff;
|
|
|
|
if (w < 0x4000000) {
|
|
carry = 0;
|
|
} else {
|
|
carry = w / 0x4000000 | 0;
|
|
}
|
|
}
|
|
|
|
return ws;
|
|
};
|
|
|
|
FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < len; i++) {
|
|
carry = carry + (ws[i] | 0);
|
|
|
|
rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
|
|
rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
|
|
}
|
|
|
|
// Pad with zeroes
|
|
for (i = 2 * len; i < N; ++i) {
|
|
rws[i] = 0;
|
|
}
|
|
|
|
assert(carry === 0);
|
|
assert((carry & ~0x1fff) === 0);
|
|
};
|
|
|
|
FFTM.prototype.stub = function stub (N) {
|
|
var ph = new Array(N);
|
|
for (var i = 0; i < N; i++) {
|
|
ph[i] = 0;
|
|
}
|
|
|
|
return ph;
|
|
};
|
|
|
|
FFTM.prototype.mulp = function mulp (x, y, out) {
|
|
var N = 2 * this.guessLen13b(x.length, y.length);
|
|
|
|
var rbt = this.makeRBT(N);
|
|
|
|
var _ = this.stub(N);
|
|
|
|
var rws = new Array(N);
|
|
var rwst = new Array(N);
|
|
var iwst = new Array(N);
|
|
|
|
var nrws = new Array(N);
|
|
var nrwst = new Array(N);
|
|
var niwst = new Array(N);
|
|
|
|
var rmws = out.words;
|
|
rmws.length = N;
|
|
|
|
this.convert13b(x.words, x.length, rws, N);
|
|
this.convert13b(y.words, y.length, nrws, N);
|
|
|
|
this.transform(rws, _, rwst, iwst, N, rbt);
|
|
this.transform(nrws, _, nrwst, niwst, N, rbt);
|
|
|
|
for (var i = 0; i < N; i++) {
|
|
var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
|
|
iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
|
|
rwst[i] = rx;
|
|
}
|
|
|
|
this.conjugate(rwst, iwst, N);
|
|
this.transform(rwst, iwst, rmws, _, N, rbt);
|
|
this.conjugate(rmws, _, N);
|
|
this.normalize13b(rmws, N);
|
|
|
|
out.negative = x.negative ^ y.negative;
|
|
out.length = x.length + y.length;
|
|
return out.strip();
|
|
};
|
|
|
|
// Multiply `this` by `num`
|
|
BN.prototype.mul = function mul (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return this.mulTo(num, out);
|
|
};
|
|
|
|
// Multiply employing FFT
|
|
BN.prototype.mulf = function mulf (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return jumboMulTo(this, num, out);
|
|
};
|
|
|
|
// In-place Multiplication
|
|
BN.prototype.imul = function imul (num) {
|
|
return this.clone().mulTo(num, this);
|
|
};
|
|
|
|
BN.prototype.imuln = function imuln (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
|
|
// Carry
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = (this.words[i] | 0) * num;
|
|
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
|
|
carry >>= 26;
|
|
carry += (w / 0x4000000) | 0;
|
|
// NOTE: lo is 27bit maximum
|
|
carry += lo >>> 26;
|
|
this.words[i] = lo & 0x3ffffff;
|
|
}
|
|
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.muln = function muln (num) {
|
|
return this.clone().imuln(num);
|
|
};
|
|
|
|
// `this` * `this`
|
|
BN.prototype.sqr = function sqr () {
|
|
return this.mul(this);
|
|
};
|
|
|
|
// `this` * `this` in-place
|
|
BN.prototype.isqr = function isqr () {
|
|
return this.imul(this.clone());
|
|
};
|
|
|
|
// Math.pow(`this`, `num`)
|
|
BN.prototype.pow = function pow (num) {
|
|
var w = toBitArray(num);
|
|
if (w.length === 0) return new BN(1);
|
|
|
|
// Skip leading zeroes
|
|
var res = this;
|
|
for (var i = 0; i < w.length; i++, res = res.sqr()) {
|
|
if (w[i] !== 0) break;
|
|
}
|
|
|
|
if (++i < w.length) {
|
|
for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
|
|
if (w[i] === 0) continue;
|
|
|
|
res = res.mul(q);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Shift-left in-place
|
|
BN.prototype.iushln = function iushln (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
|
|
var i;
|
|
|
|
if (r !== 0) {
|
|
var carry = 0;
|
|
|
|
for (i = 0; i < this.length; i++) {
|
|
var newCarry = this.words[i] & carryMask;
|
|
var c = ((this.words[i] | 0) - newCarry) << r;
|
|
this.words[i] = c | carry;
|
|
carry = newCarry >>> (26 - r);
|
|
}
|
|
|
|
if (carry) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
}
|
|
|
|
if (s !== 0) {
|
|
for (i = this.length - 1; i >= 0; i--) {
|
|
this.words[i + s] = this.words[i];
|
|
}
|
|
|
|
for (i = 0; i < s; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
this.length += s;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishln = function ishln (bits) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushln(bits);
|
|
};
|
|
|
|
// Shift-right in-place
|
|
// NOTE: `hint` is a lowest bit before trailing zeroes
|
|
// NOTE: if `extended` is present - it will be filled with destroyed bits
|
|
BN.prototype.iushrn = function iushrn (bits, hint, extended) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var h;
|
|
if (hint) {
|
|
h = (hint - (hint % 26)) / 26;
|
|
} else {
|
|
h = 0;
|
|
}
|
|
|
|
var r = bits % 26;
|
|
var s = Math.min((bits - r) / 26, this.length);
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
var maskedWords = extended;
|
|
|
|
h -= s;
|
|
h = Math.max(0, h);
|
|
|
|
// Extended mode, copy masked part
|
|
if (maskedWords) {
|
|
for (var i = 0; i < s; i++) {
|
|
maskedWords.words[i] = this.words[i];
|
|
}
|
|
maskedWords.length = s;
|
|
}
|
|
|
|
if (s === 0) {
|
|
// No-op, we should not move anything at all
|
|
} else if (this.length > s) {
|
|
this.length -= s;
|
|
for (i = 0; i < this.length; i++) {
|
|
this.words[i] = this.words[i + s];
|
|
}
|
|
} else {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
|
|
var word = this.words[i] | 0;
|
|
this.words[i] = (carry << (26 - r)) | (word >>> r);
|
|
carry = word & mask;
|
|
}
|
|
|
|
// Push carried bits as a mask
|
|
if (maskedWords && carry !== 0) {
|
|
maskedWords.words[maskedWords.length++] = carry;
|
|
}
|
|
|
|
if (this.length === 0) {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishrn = function ishrn (bits, hint, extended) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushrn(bits, hint, extended);
|
|
};
|
|
|
|
// Shift-left
|
|
BN.prototype.shln = function shln (bits) {
|
|
return this.clone().ishln(bits);
|
|
};
|
|
|
|
BN.prototype.ushln = function ushln (bits) {
|
|
return this.clone().iushln(bits);
|
|
};
|
|
|
|
// Shift-right
|
|
BN.prototype.shrn = function shrn (bits) {
|
|
return this.clone().ishrn(bits);
|
|
};
|
|
|
|
BN.prototype.ushrn = function ushrn (bits) {
|
|
return this.clone().iushrn(bits);
|
|
};
|
|
|
|
// Test if n bit is set
|
|
BN.prototype.testn = function testn (bit) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) return false;
|
|
|
|
// Check bit and return
|
|
var w = this.words[s];
|
|
|
|
return !!(w & q);
|
|
};
|
|
|
|
// Return only lowers bits of number (in-place)
|
|
BN.prototype.imaskn = function imaskn (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
|
|
assert(this.negative === 0, 'imaskn works only with positive numbers');
|
|
|
|
if (this.length <= s) {
|
|
return this;
|
|
}
|
|
|
|
if (r !== 0) {
|
|
s++;
|
|
}
|
|
this.length = Math.min(s, this.length);
|
|
|
|
if (r !== 0) {
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
this.words[this.length - 1] &= mask;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Return only lowers bits of number
|
|
BN.prototype.maskn = function maskn (bits) {
|
|
return this.clone().imaskn(bits);
|
|
};
|
|
|
|
// Add plain number `num` to `this`
|
|
BN.prototype.iaddn = function iaddn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.isubn(-num);
|
|
|
|
// Possible sign change
|
|
if (this.negative !== 0) {
|
|
if (this.length === 1 && (this.words[0] | 0) < num) {
|
|
this.words[0] = num - (this.words[0] | 0);
|
|
this.negative = 0;
|
|
return this;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.isubn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
// Add without checks
|
|
return this._iaddn(num);
|
|
};
|
|
|
|
BN.prototype._iaddn = function _iaddn (num) {
|
|
this.words[0] += num;
|
|
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
|
|
this.words[i] -= 0x4000000;
|
|
if (i === this.length - 1) {
|
|
this.words[i + 1] = 1;
|
|
} else {
|
|
this.words[i + 1]++;
|
|
}
|
|
}
|
|
this.length = Math.max(this.length, i + 1);
|
|
|
|
return this;
|
|
};
|
|
|
|
// Subtract plain number `num` from `this`
|
|
BN.prototype.isubn = function isubn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.iaddn(-num);
|
|
|
|
if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iaddn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
this.words[0] -= num;
|
|
|
|
if (this.length === 1 && this.words[0] < 0) {
|
|
this.words[0] = -this.words[0];
|
|
this.negative = 1;
|
|
} else {
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
|
|
this.words[i] += 0x4000000;
|
|
this.words[i + 1] -= 1;
|
|
}
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.addn = function addn (num) {
|
|
return this.clone().iaddn(num);
|
|
};
|
|
|
|
BN.prototype.subn = function subn (num) {
|
|
return this.clone().isubn(num);
|
|
};
|
|
|
|
BN.prototype.iabs = function iabs () {
|
|
this.negative = 0;
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.abs = function abs () {
|
|
return this.clone().iabs();
|
|
};
|
|
|
|
BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
|
|
var len = num.length + shift;
|
|
var i;
|
|
|
|
this._expand(len);
|
|
|
|
var w;
|
|
var carry = 0;
|
|
for (i = 0; i < num.length; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
var right = (num.words[i] | 0) * mul;
|
|
w -= right & 0x3ffffff;
|
|
carry = (w >> 26) - ((right / 0x4000000) | 0);
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
for (; i < this.length - shift; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
|
|
if (carry === 0) return this.strip();
|
|
|
|
// Subtraction overflow
|
|
assert(carry === -1);
|
|
carry = 0;
|
|
for (i = 0; i < this.length; i++) {
|
|
w = -(this.words[i] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i] = w & 0x3ffffff;
|
|
}
|
|
this.negative = 1;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype._wordDiv = function _wordDiv (num, mode) {
|
|
var shift = this.length - num.length;
|
|
|
|
var a = this.clone();
|
|
var b = num;
|
|
|
|
// Normalize
|
|
var bhi = b.words[b.length - 1] | 0;
|
|
var bhiBits = this._countBits(bhi);
|
|
shift = 26 - bhiBits;
|
|
if (shift !== 0) {
|
|
b = b.ushln(shift);
|
|
a.iushln(shift);
|
|
bhi = b.words[b.length - 1] | 0;
|
|
}
|
|
|
|
// Initialize quotient
|
|
var m = a.length - b.length;
|
|
var q;
|
|
|
|
if (mode !== 'mod') {
|
|
q = new BN(null);
|
|
q.length = m + 1;
|
|
q.words = new Array(q.length);
|
|
for (var i = 0; i < q.length; i++) {
|
|
q.words[i] = 0;
|
|
}
|
|
}
|
|
|
|
var diff = a.clone()._ishlnsubmul(b, 1, m);
|
|
if (diff.negative === 0) {
|
|
a = diff;
|
|
if (q) {
|
|
q.words[m] = 1;
|
|
}
|
|
}
|
|
|
|
for (var j = m - 1; j >= 0; j--) {
|
|
var qj = (a.words[b.length + j] | 0) * 0x4000000 +
|
|
(a.words[b.length + j - 1] | 0);
|
|
|
|
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
|
|
// (0x7ffffff)
|
|
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
|
|
|
|
a._ishlnsubmul(b, qj, j);
|
|
while (a.negative !== 0) {
|
|
qj--;
|
|
a.negative = 0;
|
|
a._ishlnsubmul(b, 1, j);
|
|
if (!a.isZero()) {
|
|
a.negative ^= 1;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.words[j] = qj;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.strip();
|
|
}
|
|
a.strip();
|
|
|
|
// Denormalize
|
|
if (mode !== 'div' && shift !== 0) {
|
|
a.iushrn(shift);
|
|
}
|
|
|
|
return {
|
|
div: q || null,
|
|
mod: a
|
|
};
|
|
};
|
|
|
|
// NOTE: 1) `mode` can be set to `mod` to request mod only,
|
|
// to `div` to request div only, or be absent to
|
|
// request both div & mod
|
|
// 2) `positive` is true if unsigned mod is requested
|
|
BN.prototype.divmod = function divmod (num, mode, positive) {
|
|
assert(!num.isZero());
|
|
|
|
if (this.isZero()) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: new BN(0)
|
|
};
|
|
}
|
|
|
|
var div, mod, res;
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
res = this.neg().divmod(num, mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.iadd(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
if (this.negative === 0 && num.negative !== 0) {
|
|
res = this.divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: res.mod
|
|
};
|
|
}
|
|
|
|
if ((this.negative & num.negative) !== 0) {
|
|
res = this.neg().divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.isub(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: res.div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
// Both numbers are positive at this point
|
|
|
|
// Strip both numbers to approximate shift value
|
|
if (num.length > this.length || this.cmp(num) < 0) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: this
|
|
};
|
|
}
|
|
|
|
// Very short reduction
|
|
if (num.length === 1) {
|
|
if (mode === 'div') {
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: null
|
|
};
|
|
}
|
|
|
|
if (mode === 'mod') {
|
|
return {
|
|
div: null,
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return this._wordDiv(num, mode);
|
|
};
|
|
|
|
// Find `this` / `num`
|
|
BN.prototype.div = function div (num) {
|
|
return this.divmod(num, 'div', false).div;
|
|
};
|
|
|
|
// Find `this` % `num`
|
|
BN.prototype.mod = function mod (num) {
|
|
return this.divmod(num, 'mod', false).mod;
|
|
};
|
|
|
|
BN.prototype.umod = function umod (num) {
|
|
return this.divmod(num, 'mod', true).mod;
|
|
};
|
|
|
|
// Find Round(`this` / `num`)
|
|
BN.prototype.divRound = function divRound (num) {
|
|
var dm = this.divmod(num);
|
|
|
|
// Fast case - exact division
|
|
if (dm.mod.isZero()) return dm.div;
|
|
|
|
var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
|
|
|
|
var half = num.ushrn(1);
|
|
var r2 = num.andln(1);
|
|
var cmp = mod.cmp(half);
|
|
|
|
// Round down
|
|
if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
|
|
|
|
// Round up
|
|
return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
|
|
};
|
|
|
|
BN.prototype.modn = function modn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
var p = (1 << 26) % num;
|
|
|
|
var acc = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
acc = (p * acc + (this.words[i] | 0)) % num;
|
|
}
|
|
|
|
return acc;
|
|
};
|
|
|
|
// In-place division by number
|
|
BN.prototype.idivn = function idivn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
|
|
var carry = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var w = (this.words[i] | 0) + carry * 0x4000000;
|
|
this.words[i] = (w / num) | 0;
|
|
carry = w % num;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.divn = function divn (num) {
|
|
return this.clone().idivn(num);
|
|
};
|
|
|
|
BN.prototype.egcd = function egcd (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var x = this;
|
|
var y = p.clone();
|
|
|
|
if (x.negative !== 0) {
|
|
x = x.umod(p);
|
|
} else {
|
|
x = x.clone();
|
|
}
|
|
|
|
// A * x + B * y = x
|
|
var A = new BN(1);
|
|
var B = new BN(0);
|
|
|
|
// C * x + D * y = y
|
|
var C = new BN(0);
|
|
var D = new BN(1);
|
|
|
|
var g = 0;
|
|
|
|
while (x.isEven() && y.isEven()) {
|
|
x.iushrn(1);
|
|
y.iushrn(1);
|
|
++g;
|
|
}
|
|
|
|
var yp = y.clone();
|
|
var xp = x.clone();
|
|
|
|
while (!x.isZero()) {
|
|
for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
x.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (A.isOdd() || B.isOdd()) {
|
|
A.iadd(yp);
|
|
B.isub(xp);
|
|
}
|
|
|
|
A.iushrn(1);
|
|
B.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
y.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (C.isOdd() || D.isOdd()) {
|
|
C.iadd(yp);
|
|
D.isub(xp);
|
|
}
|
|
|
|
C.iushrn(1);
|
|
D.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (x.cmp(y) >= 0) {
|
|
x.isub(y);
|
|
A.isub(C);
|
|
B.isub(D);
|
|
} else {
|
|
y.isub(x);
|
|
C.isub(A);
|
|
D.isub(B);
|
|
}
|
|
}
|
|
|
|
return {
|
|
a: C,
|
|
b: D,
|
|
gcd: y.iushln(g)
|
|
};
|
|
};
|
|
|
|
// This is reduced incarnation of the binary EEA
|
|
// above, designated to invert members of the
|
|
// _prime_ fields F(p) at a maximal speed
|
|
BN.prototype._invmp = function _invmp (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var a = this;
|
|
var b = p.clone();
|
|
|
|
if (a.negative !== 0) {
|
|
a = a.umod(p);
|
|
} else {
|
|
a = a.clone();
|
|
}
|
|
|
|
var x1 = new BN(1);
|
|
var x2 = new BN(0);
|
|
|
|
var delta = b.clone();
|
|
|
|
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
|
|
for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
a.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (x1.isOdd()) {
|
|
x1.iadd(delta);
|
|
}
|
|
|
|
x1.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
b.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (x2.isOdd()) {
|
|
x2.iadd(delta);
|
|
}
|
|
|
|
x2.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (a.cmp(b) >= 0) {
|
|
a.isub(b);
|
|
x1.isub(x2);
|
|
} else {
|
|
b.isub(a);
|
|
x2.isub(x1);
|
|
}
|
|
}
|
|
|
|
var res;
|
|
if (a.cmpn(1) === 0) {
|
|
res = x1;
|
|
} else {
|
|
res = x2;
|
|
}
|
|
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(p);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gcd = function gcd (num) {
|
|
if (this.isZero()) return num.abs();
|
|
if (num.isZero()) return this.abs();
|
|
|
|
var a = this.clone();
|
|
var b = num.clone();
|
|
a.negative = 0;
|
|
b.negative = 0;
|
|
|
|
// Remove common factor of two
|
|
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
|
|
a.iushrn(1);
|
|
b.iushrn(1);
|
|
}
|
|
|
|
do {
|
|
while (a.isEven()) {
|
|
a.iushrn(1);
|
|
}
|
|
while (b.isEven()) {
|
|
b.iushrn(1);
|
|
}
|
|
|
|
var r = a.cmp(b);
|
|
if (r < 0) {
|
|
// Swap `a` and `b` to make `a` always bigger than `b`
|
|
var t = a;
|
|
a = b;
|
|
b = t;
|
|
} else if (r === 0 || b.cmpn(1) === 0) {
|
|
break;
|
|
}
|
|
|
|
a.isub(b);
|
|
} while (true);
|
|
|
|
return b.iushln(shift);
|
|
};
|
|
|
|
// Invert number in the field F(num)
|
|
BN.prototype.invm = function invm (num) {
|
|
return this.egcd(num).a.umod(num);
|
|
};
|
|
|
|
BN.prototype.isEven = function isEven () {
|
|
return (this.words[0] & 1) === 0;
|
|
};
|
|
|
|
BN.prototype.isOdd = function isOdd () {
|
|
return (this.words[0] & 1) === 1;
|
|
};
|
|
|
|
// And first word and num
|
|
BN.prototype.andln = function andln (num) {
|
|
return this.words[0] & num;
|
|
};
|
|
|
|
// Increment at the bit position in-line
|
|
BN.prototype.bincn = function bincn (bit) {
|
|
assert(typeof bit === 'number');
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) {
|
|
this._expand(s + 1);
|
|
this.words[s] |= q;
|
|
return this;
|
|
}
|
|
|
|
// Add bit and propagate, if needed
|
|
var carry = q;
|
|
for (var i = s; carry !== 0 && i < this.length; i++) {
|
|
var w = this.words[i] | 0;
|
|
w += carry;
|
|
carry = w >>> 26;
|
|
w &= 0x3ffffff;
|
|
this.words[i] = w;
|
|
}
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.isZero = function isZero () {
|
|
return this.length === 1 && this.words[0] === 0;
|
|
};
|
|
|
|
BN.prototype.cmpn = function cmpn (num) {
|
|
var negative = num < 0;
|
|
|
|
if (this.negative !== 0 && !negative) return -1;
|
|
if (this.negative === 0 && negative) return 1;
|
|
|
|
this.strip();
|
|
|
|
var res;
|
|
if (this.length > 1) {
|
|
res = 1;
|
|
} else {
|
|
if (negative) {
|
|
num = -num;
|
|
}
|
|
|
|
assert(num <= 0x3ffffff, 'Number is too big');
|
|
|
|
var w = this.words[0] | 0;
|
|
res = w === num ? 0 : w < num ? -1 : 1;
|
|
}
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Compare two numbers and return:
|
|
// 1 - if `this` > `num`
|
|
// 0 - if `this` == `num`
|
|
// -1 - if `this` < `num`
|
|
BN.prototype.cmp = function cmp (num) {
|
|
if (this.negative !== 0 && num.negative === 0) return -1;
|
|
if (this.negative === 0 && num.negative !== 0) return 1;
|
|
|
|
var res = this.ucmp(num);
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Unsigned comparison
|
|
BN.prototype.ucmp = function ucmp (num) {
|
|
// At this point both numbers have the same sign
|
|
if (this.length > num.length) return 1;
|
|
if (this.length < num.length) return -1;
|
|
|
|
var res = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var a = this.words[i] | 0;
|
|
var b = num.words[i] | 0;
|
|
|
|
if (a === b) continue;
|
|
if (a < b) {
|
|
res = -1;
|
|
} else if (a > b) {
|
|
res = 1;
|
|
}
|
|
break;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gtn = function gtn (num) {
|
|
return this.cmpn(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gt = function gt (num) {
|
|
return this.cmp(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gten = function gten (num) {
|
|
return this.cmpn(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.gte = function gte (num) {
|
|
return this.cmp(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.ltn = function ltn (num) {
|
|
return this.cmpn(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lt = function lt (num) {
|
|
return this.cmp(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lten = function lten (num) {
|
|
return this.cmpn(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.lte = function lte (num) {
|
|
return this.cmp(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.eqn = function eqn (num) {
|
|
return this.cmpn(num) === 0;
|
|
};
|
|
|
|
BN.prototype.eq = function eq (num) {
|
|
return this.cmp(num) === 0;
|
|
};
|
|
|
|
//
|
|
// A reduce context, could be using montgomery or something better, depending
|
|
// on the `m` itself.
|
|
//
|
|
BN.red = function red (num) {
|
|
return new Red(num);
|
|
};
|
|
|
|
BN.prototype.toRed = function toRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
assert(this.negative === 0, 'red works only with positives');
|
|
return ctx.convertTo(this)._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.fromRed = function fromRed () {
|
|
assert(this.red, 'fromRed works only with numbers in reduction context');
|
|
return this.red.convertFrom(this);
|
|
};
|
|
|
|
BN.prototype._forceRed = function _forceRed (ctx) {
|
|
this.red = ctx;
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.forceRed = function forceRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
return this._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.redAdd = function redAdd (num) {
|
|
assert(this.red, 'redAdd works only with red numbers');
|
|
return this.red.add(this, num);
|
|
};
|
|
|
|
BN.prototype.redIAdd = function redIAdd (num) {
|
|
assert(this.red, 'redIAdd works only with red numbers');
|
|
return this.red.iadd(this, num);
|
|
};
|
|
|
|
BN.prototype.redSub = function redSub (num) {
|
|
assert(this.red, 'redSub works only with red numbers');
|
|
return this.red.sub(this, num);
|
|
};
|
|
|
|
BN.prototype.redISub = function redISub (num) {
|
|
assert(this.red, 'redISub works only with red numbers');
|
|
return this.red.isub(this, num);
|
|
};
|
|
|
|
BN.prototype.redShl = function redShl (num) {
|
|
assert(this.red, 'redShl works only with red numbers');
|
|
return this.red.shl(this, num);
|
|
};
|
|
|
|
BN.prototype.redMul = function redMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.mul(this, num);
|
|
};
|
|
|
|
BN.prototype.redIMul = function redIMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.imul(this, num);
|
|
};
|
|
|
|
BN.prototype.redSqr = function redSqr () {
|
|
assert(this.red, 'redSqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqr(this);
|
|
};
|
|
|
|
BN.prototype.redISqr = function redISqr () {
|
|
assert(this.red, 'redISqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.isqr(this);
|
|
};
|
|
|
|
// Square root over p
|
|
BN.prototype.redSqrt = function redSqrt () {
|
|
assert(this.red, 'redSqrt works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqrt(this);
|
|
};
|
|
|
|
BN.prototype.redInvm = function redInvm () {
|
|
assert(this.red, 'redInvm works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.invm(this);
|
|
};
|
|
|
|
// Return negative clone of `this` % `red modulo`
|
|
BN.prototype.redNeg = function redNeg () {
|
|
assert(this.red, 'redNeg works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.neg(this);
|
|
};
|
|
|
|
BN.prototype.redPow = function redPow (num) {
|
|
assert(this.red && !num.red, 'redPow(normalNum)');
|
|
this.red._verify1(this);
|
|
return this.red.pow(this, num);
|
|
};
|
|
|
|
// Prime numbers with efficient reduction
|
|
var primes = {
|
|
k256: null,
|
|
p224: null,
|
|
p192: null,
|
|
p25519: null
|
|
};
|
|
|
|
// Pseudo-Mersenne prime
|
|
function MPrime (name, p) {
|
|
// P = 2 ^ N - K
|
|
this.name = name;
|
|
this.p = new BN(p, 16);
|
|
this.n = this.p.bitLength();
|
|
this.k = new BN(1).iushln(this.n).isub(this.p);
|
|
|
|
this.tmp = this._tmp();
|
|
}
|
|
|
|
MPrime.prototype._tmp = function _tmp () {
|
|
var tmp = new BN(null);
|
|
tmp.words = new Array(Math.ceil(this.n / 13));
|
|
return tmp;
|
|
};
|
|
|
|
MPrime.prototype.ireduce = function ireduce (num) {
|
|
// Assumes that `num` is less than `P^2`
|
|
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
|
|
var r = num;
|
|
var rlen;
|
|
|
|
do {
|
|
this.split(r, this.tmp);
|
|
r = this.imulK(r);
|
|
r = r.iadd(this.tmp);
|
|
rlen = r.bitLength();
|
|
} while (rlen > this.n);
|
|
|
|
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
|
|
if (cmp === 0) {
|
|
r.words[0] = 0;
|
|
r.length = 1;
|
|
} else if (cmp > 0) {
|
|
r.isub(this.p);
|
|
} else {
|
|
if (r.strip !== undefined) {
|
|
// r is BN v4 instance
|
|
r.strip();
|
|
} else {
|
|
// r is BN v5 instance
|
|
r._strip();
|
|
}
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
MPrime.prototype.split = function split (input, out) {
|
|
input.iushrn(this.n, 0, out);
|
|
};
|
|
|
|
MPrime.prototype.imulK = function imulK (num) {
|
|
return num.imul(this.k);
|
|
};
|
|
|
|
function K256 () {
|
|
MPrime.call(
|
|
this,
|
|
'k256',
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
|
|
}
|
|
inherits(K256, MPrime);
|
|
|
|
K256.prototype.split = function split (input, output) {
|
|
// 256 = 9 * 26 + 22
|
|
var mask = 0x3fffff;
|
|
|
|
var outLen = Math.min(input.length, 9);
|
|
for (var i = 0; i < outLen; i++) {
|
|
output.words[i] = input.words[i];
|
|
}
|
|
output.length = outLen;
|
|
|
|
if (input.length <= 9) {
|
|
input.words[0] = 0;
|
|
input.length = 1;
|
|
return;
|
|
}
|
|
|
|
// Shift by 9 limbs
|
|
var prev = input.words[9];
|
|
output.words[output.length++] = prev & mask;
|
|
|
|
for (i = 10; i < input.length; i++) {
|
|
var next = input.words[i] | 0;
|
|
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
|
|
prev = next;
|
|
}
|
|
prev >>>= 22;
|
|
input.words[i - 10] = prev;
|
|
if (prev === 0 && input.length > 10) {
|
|
input.length -= 10;
|
|
} else {
|
|
input.length -= 9;
|
|
}
|
|
};
|
|
|
|
K256.prototype.imulK = function imulK (num) {
|
|
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
|
|
num.words[num.length] = 0;
|
|
num.words[num.length + 1] = 0;
|
|
num.length += 2;
|
|
|
|
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
|
|
var lo = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var w = num.words[i] | 0;
|
|
lo += w * 0x3d1;
|
|
num.words[i] = lo & 0x3ffffff;
|
|
lo = w * 0x40 + ((lo / 0x4000000) | 0);
|
|
}
|
|
|
|
// Fast length reduction
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
}
|
|
}
|
|
return num;
|
|
};
|
|
|
|
function P224 () {
|
|
MPrime.call(
|
|
this,
|
|
'p224',
|
|
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
|
|
}
|
|
inherits(P224, MPrime);
|
|
|
|
function P192 () {
|
|
MPrime.call(
|
|
this,
|
|
'p192',
|
|
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
|
|
}
|
|
inherits(P192, MPrime);
|
|
|
|
function P25519 () {
|
|
// 2 ^ 255 - 19
|
|
MPrime.call(
|
|
this,
|
|
'25519',
|
|
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
|
|
}
|
|
inherits(P25519, MPrime);
|
|
|
|
P25519.prototype.imulK = function imulK (num) {
|
|
// K = 0x13
|
|
var carry = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var hi = (num.words[i] | 0) * 0x13 + carry;
|
|
var lo = hi & 0x3ffffff;
|
|
hi >>>= 26;
|
|
|
|
num.words[i] = lo;
|
|
carry = hi;
|
|
}
|
|
if (carry !== 0) {
|
|
num.words[num.length++] = carry;
|
|
}
|
|
return num;
|
|
};
|
|
|
|
// Exported mostly for testing purposes, use plain name instead
|
|
BN._prime = function prime (name) {
|
|
// Cached version of prime
|
|
if (primes[name]) return primes[name];
|
|
|
|
var prime;
|
|
if (name === 'k256') {
|
|
prime = new K256();
|
|
} else if (name === 'p224') {
|
|
prime = new P224();
|
|
} else if (name === 'p192') {
|
|
prime = new P192();
|
|
} else if (name === 'p25519') {
|
|
prime = new P25519();
|
|
} else {
|
|
throw new Error('Unknown prime ' + name);
|
|
}
|
|
primes[name] = prime;
|
|
|
|
return prime;
|
|
};
|
|
|
|
//
|
|
// Base reduction engine
|
|
//
|
|
function Red (m) {
|
|
if (typeof m === 'string') {
|
|
var prime = BN._prime(m);
|
|
this.m = prime.p;
|
|
this.prime = prime;
|
|
} else {
|
|
assert(m.gtn(1), 'modulus must be greater than 1');
|
|
this.m = m;
|
|
this.prime = null;
|
|
}
|
|
}
|
|
|
|
Red.prototype._verify1 = function _verify1 (a) {
|
|
assert(a.negative === 0, 'red works only with positives');
|
|
assert(a.red, 'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype._verify2 = function _verify2 (a, b) {
|
|
assert((a.negative | b.negative) === 0, 'red works only with positives');
|
|
assert(a.red && a.red === b.red,
|
|
'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype.imod = function imod (a) {
|
|
if (this.prime) return this.prime.ireduce(a)._forceRed(this);
|
|
return a.umod(this.m)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.neg = function neg (a) {
|
|
if (a.isZero()) {
|
|
return a.clone();
|
|
}
|
|
|
|
return this.m.sub(a)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.add = function add (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.add(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.iadd = function iadd (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.iadd(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.sub = function sub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.sub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.isub = function isub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.isub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.shl = function shl (a, num) {
|
|
this._verify1(a);
|
|
return this.imod(a.ushln(num));
|
|
};
|
|
|
|
Red.prototype.imul = function imul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.imul(b));
|
|
};
|
|
|
|
Red.prototype.mul = function mul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.mul(b));
|
|
};
|
|
|
|
Red.prototype.isqr = function isqr (a) {
|
|
return this.imul(a, a.clone());
|
|
};
|
|
|
|
Red.prototype.sqr = function sqr (a) {
|
|
return this.mul(a, a);
|
|
};
|
|
|
|
Red.prototype.sqrt = function sqrt (a) {
|
|
if (a.isZero()) return a.clone();
|
|
|
|
var mod3 = this.m.andln(3);
|
|
assert(mod3 % 2 === 1);
|
|
|
|
// Fast case
|
|
if (mod3 === 3) {
|
|
var pow = this.m.add(new BN(1)).iushrn(2);
|
|
return this.pow(a, pow);
|
|
}
|
|
|
|
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
|
|
//
|
|
// Find Q and S, that Q * 2 ^ S = (P - 1)
|
|
var q = this.m.subn(1);
|
|
var s = 0;
|
|
while (!q.isZero() && q.andln(1) === 0) {
|
|
s++;
|
|
q.iushrn(1);
|
|
}
|
|
assert(!q.isZero());
|
|
|
|
var one = new BN(1).toRed(this);
|
|
var nOne = one.redNeg();
|
|
|
|
// Find quadratic non-residue
|
|
// NOTE: Max is such because of generalized Riemann hypothesis.
|
|
var lpow = this.m.subn(1).iushrn(1);
|
|
var z = this.m.bitLength();
|
|
z = new BN(2 * z * z).toRed(this);
|
|
|
|
while (this.pow(z, lpow).cmp(nOne) !== 0) {
|
|
z.redIAdd(nOne);
|
|
}
|
|
|
|
var c = this.pow(z, q);
|
|
var r = this.pow(a, q.addn(1).iushrn(1));
|
|
var t = this.pow(a, q);
|
|
var m = s;
|
|
while (t.cmp(one) !== 0) {
|
|
var tmp = t;
|
|
for (var i = 0; tmp.cmp(one) !== 0; i++) {
|
|
tmp = tmp.redSqr();
|
|
}
|
|
assert(i < m);
|
|
var b = this.pow(c, new BN(1).iushln(m - i - 1));
|
|
|
|
r = r.redMul(b);
|
|
c = b.redSqr();
|
|
t = t.redMul(c);
|
|
m = i;
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
Red.prototype.invm = function invm (a) {
|
|
var inv = a._invmp(this.m);
|
|
if (inv.negative !== 0) {
|
|
inv.negative = 0;
|
|
return this.imod(inv).redNeg();
|
|
} else {
|
|
return this.imod(inv);
|
|
}
|
|
};
|
|
|
|
Red.prototype.pow = function pow (a, num) {
|
|
if (num.isZero()) return new BN(1).toRed(this);
|
|
if (num.cmpn(1) === 0) return a.clone();
|
|
|
|
var windowSize = 4;
|
|
var wnd = new Array(1 << windowSize);
|
|
wnd[0] = new BN(1).toRed(this);
|
|
wnd[1] = a;
|
|
for (var i = 2; i < wnd.length; i++) {
|
|
wnd[i] = this.mul(wnd[i - 1], a);
|
|
}
|
|
|
|
var res = wnd[0];
|
|
var current = 0;
|
|
var currentLen = 0;
|
|
var start = num.bitLength() % 26;
|
|
if (start === 0) {
|
|
start = 26;
|
|
}
|
|
|
|
for (i = num.length - 1; i >= 0; i--) {
|
|
var word = num.words[i];
|
|
for (var j = start - 1; j >= 0; j--) {
|
|
var bit = (word >> j) & 1;
|
|
if (res !== wnd[0]) {
|
|
res = this.sqr(res);
|
|
}
|
|
|
|
if (bit === 0 && current === 0) {
|
|
currentLen = 0;
|
|
continue;
|
|
}
|
|
|
|
current <<= 1;
|
|
current |= bit;
|
|
currentLen++;
|
|
if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
|
|
|
|
res = this.mul(res, wnd[current]);
|
|
currentLen = 0;
|
|
current = 0;
|
|
}
|
|
start = 26;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.convertTo = function convertTo (num) {
|
|
var r = num.umod(this.m);
|
|
|
|
return r === num ? r.clone() : r;
|
|
};
|
|
|
|
Red.prototype.convertFrom = function convertFrom (num) {
|
|
var res = num.clone();
|
|
res.red = null;
|
|
return res;
|
|
};
|
|
|
|
//
|
|
// Montgomery method engine
|
|
//
|
|
|
|
BN.mont = function mont (num) {
|
|
return new Mont(num);
|
|
};
|
|
|
|
function Mont (m) {
|
|
Red.call(this, m);
|
|
|
|
this.shift = this.m.bitLength();
|
|
if (this.shift % 26 !== 0) {
|
|
this.shift += 26 - (this.shift % 26);
|
|
}
|
|
|
|
this.r = new BN(1).iushln(this.shift);
|
|
this.r2 = this.imod(this.r.sqr());
|
|
this.rinv = this.r._invmp(this.m);
|
|
|
|
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
|
|
this.minv = this.minv.umod(this.r);
|
|
this.minv = this.r.sub(this.minv);
|
|
}
|
|
inherits(Mont, Red);
|
|
|
|
Mont.prototype.convertTo = function convertTo (num) {
|
|
return this.imod(num.ushln(this.shift));
|
|
};
|
|
|
|
Mont.prototype.convertFrom = function convertFrom (num) {
|
|
var r = this.imod(num.mul(this.rinv));
|
|
r.red = null;
|
|
return r;
|
|
};
|
|
|
|
Mont.prototype.imul = function imul (a, b) {
|
|
if (a.isZero() || b.isZero()) {
|
|
a.words[0] = 0;
|
|
a.length = 1;
|
|
return a;
|
|
}
|
|
|
|
var t = a.imul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.mul = function mul (a, b) {
|
|
if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
|
|
|
|
var t = a.mul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.invm = function invm (a) {
|
|
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
|
|
var res = this.imod(a._invmp(this.m).mul(this.r2));
|
|
return res._forceRed(this);
|
|
};
|
|
})( false || module, this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/public-encrypt/privateDecrypt.js":
|
|
/*!*******************************************************!*\
|
|
!*** ./node_modules/public-encrypt/privateDecrypt.js ***!
|
|
\*******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var parseKeys = __webpack_require__(/*! parse-asn1 */ "./node_modules/parse-asn1/index.js")
|
|
var mgf = __webpack_require__(/*! ./mgf */ "./node_modules/public-encrypt/mgf.js")
|
|
var xor = __webpack_require__(/*! ./xor */ "./node_modules/public-encrypt/xor.js")
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/public-encrypt/node_modules/bn.js/lib/bn.js")
|
|
var crt = __webpack_require__(/*! browserify-rsa */ "./node_modules/browserify-rsa/index.js")
|
|
var createHash = __webpack_require__(/*! create-hash */ "./node_modules/create-hash/browser.js")
|
|
var withPublic = __webpack_require__(/*! ./withPublic */ "./node_modules/public-encrypt/withPublic.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
module.exports = function privateDecrypt (privateKey, enc, reverse) {
|
|
var padding
|
|
if (privateKey.padding) {
|
|
padding = privateKey.padding
|
|
} else if (reverse) {
|
|
padding = 1
|
|
} else {
|
|
padding = 4
|
|
}
|
|
|
|
var key = parseKeys(privateKey)
|
|
var k = key.modulus.byteLength()
|
|
if (enc.length > k || new BN(enc).cmp(key.modulus) >= 0) {
|
|
throw new Error('decryption error')
|
|
}
|
|
var msg
|
|
if (reverse) {
|
|
msg = withPublic(new BN(enc), key)
|
|
} else {
|
|
msg = crt(enc, key)
|
|
}
|
|
var zBuffer = Buffer.alloc(k - msg.length)
|
|
msg = Buffer.concat([zBuffer, msg], k)
|
|
if (padding === 4) {
|
|
return oaep(key, msg)
|
|
} else if (padding === 1) {
|
|
return pkcs1(key, msg, reverse)
|
|
} else if (padding === 3) {
|
|
return msg
|
|
} else {
|
|
throw new Error('unknown padding')
|
|
}
|
|
}
|
|
|
|
function oaep (key, msg) {
|
|
var k = key.modulus.byteLength()
|
|
var iHash = createHash('sha1').update(Buffer.alloc(0)).digest()
|
|
var hLen = iHash.length
|
|
if (msg[0] !== 0) {
|
|
throw new Error('decryption error')
|
|
}
|
|
var maskedSeed = msg.slice(1, hLen + 1)
|
|
var maskedDb = msg.slice(hLen + 1)
|
|
var seed = xor(maskedSeed, mgf(maskedDb, hLen))
|
|
var db = xor(maskedDb, mgf(seed, k - hLen - 1))
|
|
if (compare(iHash, db.slice(0, hLen))) {
|
|
throw new Error('decryption error')
|
|
}
|
|
var i = hLen
|
|
while (db[i] === 0) {
|
|
i++
|
|
}
|
|
if (db[i++] !== 1) {
|
|
throw new Error('decryption error')
|
|
}
|
|
return db.slice(i)
|
|
}
|
|
|
|
function pkcs1 (key, msg, reverse) {
|
|
var p1 = msg.slice(0, 2)
|
|
var i = 2
|
|
var status = 0
|
|
while (msg[i++] !== 0) {
|
|
if (i >= msg.length) {
|
|
status++
|
|
break
|
|
}
|
|
}
|
|
var ps = msg.slice(2, i - 1)
|
|
|
|
if ((p1.toString('hex') !== '0002' && !reverse) || (p1.toString('hex') !== '0001' && reverse)) {
|
|
status++
|
|
}
|
|
if (ps.length < 8) {
|
|
status++
|
|
}
|
|
if (status) {
|
|
throw new Error('decryption error')
|
|
}
|
|
return msg.slice(i)
|
|
}
|
|
function compare (a, b) {
|
|
a = Buffer.from(a)
|
|
b = Buffer.from(b)
|
|
var dif = 0
|
|
var len = a.length
|
|
if (a.length !== b.length) {
|
|
dif++
|
|
len = Math.min(a.length, b.length)
|
|
}
|
|
var i = -1
|
|
while (++i < len) {
|
|
dif += (a[i] ^ b[i])
|
|
}
|
|
return dif
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/public-encrypt/publicEncrypt.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/public-encrypt/publicEncrypt.js ***!
|
|
\******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var parseKeys = __webpack_require__(/*! parse-asn1 */ "./node_modules/parse-asn1/index.js")
|
|
var randomBytes = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js")
|
|
var createHash = __webpack_require__(/*! create-hash */ "./node_modules/create-hash/browser.js")
|
|
var mgf = __webpack_require__(/*! ./mgf */ "./node_modules/public-encrypt/mgf.js")
|
|
var xor = __webpack_require__(/*! ./xor */ "./node_modules/public-encrypt/xor.js")
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/public-encrypt/node_modules/bn.js/lib/bn.js")
|
|
var withPublic = __webpack_require__(/*! ./withPublic */ "./node_modules/public-encrypt/withPublic.js")
|
|
var crt = __webpack_require__(/*! browserify-rsa */ "./node_modules/browserify-rsa/index.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
module.exports = function publicEncrypt (publicKey, msg, reverse) {
|
|
var padding
|
|
if (publicKey.padding) {
|
|
padding = publicKey.padding
|
|
} else if (reverse) {
|
|
padding = 1
|
|
} else {
|
|
padding = 4
|
|
}
|
|
var key = parseKeys(publicKey)
|
|
var paddedMsg
|
|
if (padding === 4) {
|
|
paddedMsg = oaep(key, msg)
|
|
} else if (padding === 1) {
|
|
paddedMsg = pkcs1(key, msg, reverse)
|
|
} else if (padding === 3) {
|
|
paddedMsg = new BN(msg)
|
|
if (paddedMsg.cmp(key.modulus) >= 0) {
|
|
throw new Error('data too long for modulus')
|
|
}
|
|
} else {
|
|
throw new Error('unknown padding')
|
|
}
|
|
if (reverse) {
|
|
return crt(paddedMsg, key)
|
|
} else {
|
|
return withPublic(paddedMsg, key)
|
|
}
|
|
}
|
|
|
|
function oaep (key, msg) {
|
|
var k = key.modulus.byteLength()
|
|
var mLen = msg.length
|
|
var iHash = createHash('sha1').update(Buffer.alloc(0)).digest()
|
|
var hLen = iHash.length
|
|
var hLen2 = 2 * hLen
|
|
if (mLen > k - hLen2 - 2) {
|
|
throw new Error('message too long')
|
|
}
|
|
var ps = Buffer.alloc(k - mLen - hLen2 - 2)
|
|
var dblen = k - hLen - 1
|
|
var seed = randomBytes(hLen)
|
|
var maskedDb = xor(Buffer.concat([iHash, ps, Buffer.alloc(1, 1), msg], dblen), mgf(seed, dblen))
|
|
var maskedSeed = xor(seed, mgf(maskedDb, hLen))
|
|
return new BN(Buffer.concat([Buffer.alloc(1), maskedSeed, maskedDb], k))
|
|
}
|
|
function pkcs1 (key, msg, reverse) {
|
|
var mLen = msg.length
|
|
var k = key.modulus.byteLength()
|
|
if (mLen > k - 11) {
|
|
throw new Error('message too long')
|
|
}
|
|
var ps
|
|
if (reverse) {
|
|
ps = Buffer.alloc(k - mLen - 3, 0xff)
|
|
} else {
|
|
ps = nonZero(k - mLen - 3)
|
|
}
|
|
return new BN(Buffer.concat([Buffer.from([0, reverse ? 1 : 2]), ps, Buffer.alloc(1), msg], k))
|
|
}
|
|
function nonZero (len) {
|
|
var out = Buffer.allocUnsafe(len)
|
|
var i = 0
|
|
var cache = randomBytes(len * 2)
|
|
var cur = 0
|
|
var num
|
|
while (i < len) {
|
|
if (cur === cache.length) {
|
|
cache = randomBytes(len * 2)
|
|
cur = 0
|
|
}
|
|
num = cache[cur++]
|
|
if (num) {
|
|
out[i++] = num
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/public-encrypt/withPublic.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/public-encrypt/withPublic.js ***!
|
|
\***************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var BN = __webpack_require__(/*! bn.js */ "./node_modules/public-encrypt/node_modules/bn.js/lib/bn.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
function withPublic (paddedMsg, key) {
|
|
return Buffer.from(paddedMsg
|
|
.toRed(BN.mont(key.modulus))
|
|
.redPow(new BN(key.publicExponent))
|
|
.fromRed()
|
|
.toArray())
|
|
}
|
|
|
|
module.exports = withPublic
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/public-encrypt/xor.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/public-encrypt/xor.js ***!
|
|
\********************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = function xor (a, b) {
|
|
var len = a.length
|
|
var i = -1
|
|
while (++i < len) {
|
|
a[i] ^= b[i]
|
|
}
|
|
return a
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/pump/index.js":
|
|
/*!************************************!*\
|
|
!*** ./node_modules/pump/index.js ***!
|
|
\************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
var once = __webpack_require__(/*! once */ "./node_modules/once/once.js")
|
|
var eos = __webpack_require__(/*! end-of-stream */ "./node_modules/end-of-stream/index.js")
|
|
var fs = __webpack_require__(/*! fs */ "?7874") // we only need fs to get the ReadStream and WriteStream prototypes
|
|
|
|
var noop = function () {}
|
|
var ancient = /^v?\.0/.test(process.version)
|
|
|
|
var isFn = function (fn) {
|
|
return typeof fn === 'function'
|
|
}
|
|
|
|
var isFS = function (stream) {
|
|
if (!ancient) return false // newer node version do not need to care about fs is a special way
|
|
if (!fs) return false // browser
|
|
return (stream instanceof (fs.ReadStream || noop) || stream instanceof (fs.WriteStream || noop)) && isFn(stream.close)
|
|
}
|
|
|
|
var isRequest = function (stream) {
|
|
return stream.setHeader && isFn(stream.abort)
|
|
}
|
|
|
|
var destroyer = function (stream, reading, writing, callback) {
|
|
callback = once(callback)
|
|
|
|
var closed = false
|
|
stream.on('close', function () {
|
|
closed = true
|
|
})
|
|
|
|
eos(stream, {readable: reading, writable: writing}, function (err) {
|
|
if (err) return callback(err)
|
|
closed = true
|
|
callback()
|
|
})
|
|
|
|
var destroyed = false
|
|
return function (err) {
|
|
if (closed) return
|
|
if (destroyed) return
|
|
destroyed = true
|
|
|
|
if (isFS(stream)) return stream.close(noop) // use close for fs streams to avoid fd leaks
|
|
if (isRequest(stream)) return stream.abort() // request.destroy just do .end - .abort is what we want
|
|
|
|
if (isFn(stream.destroy)) return stream.destroy()
|
|
|
|
callback(err || new Error('stream was destroyed'))
|
|
}
|
|
}
|
|
|
|
var call = function (fn) {
|
|
fn()
|
|
}
|
|
|
|
var pipe = function (from, to) {
|
|
return from.pipe(to)
|
|
}
|
|
|
|
var pump = function () {
|
|
var streams = Array.prototype.slice.call(arguments)
|
|
var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop
|
|
|
|
if (Array.isArray(streams[0])) streams = streams[0]
|
|
if (streams.length < 2) throw new Error('pump requires two streams per minimum')
|
|
|
|
var error
|
|
var destroys = streams.map(function (stream, i) {
|
|
var reading = i < streams.length - 1
|
|
var writing = i > 0
|
|
return destroyer(stream, reading, writing, function (err) {
|
|
if (!error) error = err
|
|
if (err) destroys.forEach(call)
|
|
if (reading) return
|
|
destroys.forEach(call)
|
|
callback(error)
|
|
})
|
|
})
|
|
|
|
return streams.reduce(pipe)
|
|
}
|
|
|
|
module.exports = pump
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/querystring/decode.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/querystring/decode.js ***!
|
|
\********************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
// If obj.hasOwnProperty has been overridden, then calling
|
|
// obj.hasOwnProperty(prop) will break.
|
|
// See: https://github.com/joyent/node/issues/1707
|
|
function hasOwnProperty(obj, prop) {
|
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
}
|
|
|
|
module.exports = function(qs, sep, eq, options) {
|
|
sep = sep || '&';
|
|
eq = eq || '=';
|
|
var obj = {};
|
|
|
|
if (typeof qs !== 'string' || qs.length === 0) {
|
|
return obj;
|
|
}
|
|
|
|
var regexp = /\+/g;
|
|
qs = qs.split(sep);
|
|
|
|
var maxKeys = 1000;
|
|
if (options && typeof options.maxKeys === 'number') {
|
|
maxKeys = options.maxKeys;
|
|
}
|
|
|
|
var len = qs.length;
|
|
// maxKeys <= 0 means that we should not limit keys count
|
|
if (maxKeys > 0 && len > maxKeys) {
|
|
len = maxKeys;
|
|
}
|
|
|
|
for (var i = 0; i < len; ++i) {
|
|
var x = qs[i].replace(regexp, '%20'),
|
|
idx = x.indexOf(eq),
|
|
kstr, vstr, k, v;
|
|
|
|
if (idx >= 0) {
|
|
kstr = x.substr(0, idx);
|
|
vstr = x.substr(idx + 1);
|
|
} else {
|
|
kstr = x;
|
|
vstr = '';
|
|
}
|
|
|
|
k = decodeURIComponent(kstr);
|
|
v = decodeURIComponent(vstr);
|
|
|
|
if (!hasOwnProperty(obj, k)) {
|
|
obj[k] = v;
|
|
} else if (Array.isArray(obj[k])) {
|
|
obj[k].push(v);
|
|
} else {
|
|
obj[k] = [obj[k], v];
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/querystring/encode.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/querystring/encode.js ***!
|
|
\********************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
var stringifyPrimitive = function(v) {
|
|
switch (typeof v) {
|
|
case 'string':
|
|
return v;
|
|
|
|
case 'boolean':
|
|
return v ? 'true' : 'false';
|
|
|
|
case 'number':
|
|
return isFinite(v) ? v : '';
|
|
|
|
default:
|
|
return '';
|
|
}
|
|
};
|
|
|
|
module.exports = function(obj, sep, eq, name) {
|
|
sep = sep || '&';
|
|
eq = eq || '=';
|
|
if (obj === null) {
|
|
obj = undefined;
|
|
}
|
|
|
|
if (typeof obj === 'object') {
|
|
return Object.keys(obj).map(function(k) {
|
|
var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
|
|
if (Array.isArray(obj[k])) {
|
|
return obj[k].map(function(v) {
|
|
return ks + encodeURIComponent(stringifyPrimitive(v));
|
|
}).join(sep);
|
|
} else {
|
|
return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
|
|
}
|
|
}).join(sep);
|
|
|
|
}
|
|
|
|
if (!name) return '';
|
|
return encodeURIComponent(stringifyPrimitive(name)) + eq +
|
|
encodeURIComponent(stringifyPrimitive(obj));
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/querystring/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/querystring/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
exports.decode = exports.parse = __webpack_require__(/*! ./decode */ "./node_modules/querystring/decode.js");
|
|
exports.encode = exports.stringify = __webpack_require__(/*! ./encode */ "./node_modules/querystring/encode.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/queue-microtask/index.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/queue-microtask/index.js ***!
|
|
\***********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
let promise
|
|
|
|
module.exports = typeof queueMicrotask === 'function'
|
|
? queueMicrotask.bind(typeof window !== 'undefined' ? window : __webpack_require__.g)
|
|
// reuse resolved promise, and allocate it lazily
|
|
: cb => (promise || (promise = Promise.resolve()))
|
|
.then(cb)
|
|
.catch(err => setTimeout(() => { throw err }, 0))
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/random-iterate/index.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/random-iterate/index.js ***!
|
|
\**********************************************/
|
|
/***/ ((module) => {
|
|
|
|
var iterate = function (list) {
|
|
var offset = 0
|
|
return function () {
|
|
if (offset === list.length) return null
|
|
|
|
var len = list.length - offset
|
|
var i = (Math.random() * len) | 0
|
|
var el = list[offset + i]
|
|
|
|
var tmp = list[offset]
|
|
list[offset] = el
|
|
list[offset + i] = tmp
|
|
offset++
|
|
|
|
return el
|
|
}
|
|
}
|
|
|
|
module.exports = iterate
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/randombytes/browser.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/randombytes/browser.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
|
|
|
|
// limit of Crypto.getRandomValues()
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
|
|
var MAX_BYTES = 65536
|
|
|
|
// Node supports requesting up to this number of bytes
|
|
// https://github.com/nodejs/node/blob/master/lib/internal/crypto/random.js#L48
|
|
var MAX_UINT32 = 4294967295
|
|
|
|
function oldBrowser () {
|
|
throw new Error('Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11')
|
|
}
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
var crypto = __webpack_require__.g.crypto || __webpack_require__.g.msCrypto
|
|
|
|
if (crypto && crypto.getRandomValues) {
|
|
module.exports = randomBytes
|
|
} else {
|
|
module.exports = oldBrowser
|
|
}
|
|
|
|
function randomBytes (size, cb) {
|
|
// phantomjs needs to throw
|
|
if (size > MAX_UINT32) throw new RangeError('requested too many random bytes')
|
|
|
|
var bytes = Buffer.allocUnsafe(size)
|
|
|
|
if (size > 0) { // getRandomValues fails on IE if size == 0
|
|
if (size > MAX_BYTES) { // this is the max bytes crypto.getRandomValues
|
|
// can do at once see https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
|
|
for (var generated = 0; generated < size; generated += MAX_BYTES) {
|
|
// buffer.slice automatically checks if the end is past the end of
|
|
// the buffer so we don't have to here
|
|
crypto.getRandomValues(bytes.slice(generated, generated + MAX_BYTES))
|
|
}
|
|
} else {
|
|
crypto.getRandomValues(bytes)
|
|
}
|
|
}
|
|
|
|
if (typeof cb === 'function') {
|
|
return process.nextTick(function () {
|
|
cb(null, bytes)
|
|
})
|
|
}
|
|
|
|
return bytes
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/randomfill/browser.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/randomfill/browser.js ***!
|
|
\********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
|
|
|
|
function oldBrowser () {
|
|
throw new Error('secure random number generation not supported by this browser\nuse chrome, FireFox or Internet Explorer 11')
|
|
}
|
|
var safeBuffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js")
|
|
var randombytes = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js")
|
|
var Buffer = safeBuffer.Buffer
|
|
var kBufferMaxLength = safeBuffer.kMaxLength
|
|
var crypto = __webpack_require__.g.crypto || __webpack_require__.g.msCrypto
|
|
var kMaxUint32 = Math.pow(2, 32) - 1
|
|
function assertOffset (offset, length) {
|
|
if (typeof offset !== 'number' || offset !== offset) { // eslint-disable-line no-self-compare
|
|
throw new TypeError('offset must be a number')
|
|
}
|
|
|
|
if (offset > kMaxUint32 || offset < 0) {
|
|
throw new TypeError('offset must be a uint32')
|
|
}
|
|
|
|
if (offset > kBufferMaxLength || offset > length) {
|
|
throw new RangeError('offset out of range')
|
|
}
|
|
}
|
|
|
|
function assertSize (size, offset, length) {
|
|
if (typeof size !== 'number' || size !== size) { // eslint-disable-line no-self-compare
|
|
throw new TypeError('size must be a number')
|
|
}
|
|
|
|
if (size > kMaxUint32 || size < 0) {
|
|
throw new TypeError('size must be a uint32')
|
|
}
|
|
|
|
if (size + offset > length || size > kBufferMaxLength) {
|
|
throw new RangeError('buffer too small')
|
|
}
|
|
}
|
|
if ((crypto && crypto.getRandomValues) || !process.browser) {
|
|
exports.randomFill = randomFill
|
|
exports.randomFillSync = randomFillSync
|
|
} else {
|
|
exports.randomFill = oldBrowser
|
|
exports.randomFillSync = oldBrowser
|
|
}
|
|
function randomFill (buf, offset, size, cb) {
|
|
if (!Buffer.isBuffer(buf) && !(buf instanceof __webpack_require__.g.Uint8Array)) {
|
|
throw new TypeError('"buf" argument must be a Buffer or Uint8Array')
|
|
}
|
|
|
|
if (typeof offset === 'function') {
|
|
cb = offset
|
|
offset = 0
|
|
size = buf.length
|
|
} else if (typeof size === 'function') {
|
|
cb = size
|
|
size = buf.length - offset
|
|
} else if (typeof cb !== 'function') {
|
|
throw new TypeError('"cb" argument must be a function')
|
|
}
|
|
assertOffset(offset, buf.length)
|
|
assertSize(size, offset, buf.length)
|
|
return actualFill(buf, offset, size, cb)
|
|
}
|
|
|
|
function actualFill (buf, offset, size, cb) {
|
|
if (process.browser) {
|
|
var ourBuf = buf.buffer
|
|
var uint = new Uint8Array(ourBuf, offset, size)
|
|
crypto.getRandomValues(uint)
|
|
if (cb) {
|
|
process.nextTick(function () {
|
|
cb(null, buf)
|
|
})
|
|
return
|
|
}
|
|
return buf
|
|
}
|
|
if (cb) {
|
|
randombytes(size, function (err, bytes) {
|
|
if (err) {
|
|
return cb(err)
|
|
}
|
|
bytes.copy(buf, offset)
|
|
cb(null, buf)
|
|
})
|
|
return
|
|
}
|
|
var bytes = randombytes(size)
|
|
bytes.copy(buf, offset)
|
|
return buf
|
|
}
|
|
function randomFillSync (buf, offset, size) {
|
|
if (typeof offset === 'undefined') {
|
|
offset = 0
|
|
}
|
|
if (!Buffer.isBuffer(buf) && !(buf instanceof __webpack_require__.g.Uint8Array)) {
|
|
throw new TypeError('"buf" argument must be a Buffer or Uint8Array')
|
|
}
|
|
|
|
assertOffset(offset, buf.length)
|
|
|
|
if (size === undefined) size = buf.length - offset
|
|
|
|
assertSize(size, offset, buf.length)
|
|
|
|
return actualFill(buf, offset, size)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/range-parser/index.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/range-parser/index.js ***!
|
|
\********************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
/*!
|
|
* range-parser
|
|
* Copyright(c) 2012-2014 TJ Holowaychuk
|
|
* Copyright(c) 2015-2016 Douglas Christopher Wilson
|
|
* MIT Licensed
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
* Module exports.
|
|
* @public
|
|
*/
|
|
|
|
module.exports = rangeParser
|
|
|
|
/**
|
|
* Parse "Range" header `str` relative to the given file `size`.
|
|
*
|
|
* @param {Number} size
|
|
* @param {String} str
|
|
* @param {Object} [options]
|
|
* @return {Array}
|
|
* @public
|
|
*/
|
|
|
|
function rangeParser (size, str, options) {
|
|
if (typeof str !== 'string') {
|
|
throw new TypeError('argument str must be a string')
|
|
}
|
|
|
|
var index = str.indexOf('=')
|
|
|
|
if (index === -1) {
|
|
return -2
|
|
}
|
|
|
|
// split the range string
|
|
var arr = str.slice(index + 1).split(',')
|
|
var ranges = []
|
|
|
|
// add ranges type
|
|
ranges.type = str.slice(0, index)
|
|
|
|
// parse all ranges
|
|
for (var i = 0; i < arr.length; i++) {
|
|
var range = arr[i].split('-')
|
|
var start = parseInt(range[0], 10)
|
|
var end = parseInt(range[1], 10)
|
|
|
|
// -nnn
|
|
if (isNaN(start)) {
|
|
start = size - end
|
|
end = size - 1
|
|
// nnn-
|
|
} else if (isNaN(end)) {
|
|
end = size - 1
|
|
}
|
|
|
|
// limit last-byte-pos to current length
|
|
if (end > size - 1) {
|
|
end = size - 1
|
|
}
|
|
|
|
// invalid or unsatisifiable
|
|
if (isNaN(start) || isNaN(end) || start > end || start < 0) {
|
|
continue
|
|
}
|
|
|
|
// add range
|
|
ranges.push({
|
|
start: start,
|
|
end: end
|
|
})
|
|
}
|
|
|
|
if (ranges.length < 1) {
|
|
// unsatisifiable
|
|
return -1
|
|
}
|
|
|
|
return options && options.combine
|
|
? combineRanges(ranges)
|
|
: ranges
|
|
}
|
|
|
|
/**
|
|
* Combine overlapping & adjacent ranges.
|
|
* @private
|
|
*/
|
|
|
|
function combineRanges (ranges) {
|
|
var ordered = ranges.map(mapWithIndex).sort(sortByRangeStart)
|
|
|
|
for (var j = 0, i = 1; i < ordered.length; i++) {
|
|
var range = ordered[i]
|
|
var current = ordered[j]
|
|
|
|
if (range.start > current.end + 1) {
|
|
// next range
|
|
ordered[++j] = range
|
|
} else if (range.end > current.end) {
|
|
// extend range
|
|
current.end = range.end
|
|
current.index = Math.min(current.index, range.index)
|
|
}
|
|
}
|
|
|
|
// trim ordered array
|
|
ordered.length = j + 1
|
|
|
|
// generate combined range
|
|
var combined = ordered.sort(sortByRangeIndex).map(mapWithoutIndex)
|
|
|
|
// copy ranges type
|
|
combined.type = ranges.type
|
|
|
|
return combined
|
|
}
|
|
|
|
/**
|
|
* Map function to add index value to ranges.
|
|
* @private
|
|
*/
|
|
|
|
function mapWithIndex (range, index) {
|
|
return {
|
|
start: range.start,
|
|
end: range.end,
|
|
index: index
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Map function to remove index value from ranges.
|
|
* @private
|
|
*/
|
|
|
|
function mapWithoutIndex (range) {
|
|
return {
|
|
start: range.start,
|
|
end: range.end
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sort function to sort ranges by index.
|
|
* @private
|
|
*/
|
|
|
|
function sortByRangeIndex (a, b) {
|
|
return a.index - b.index
|
|
}
|
|
|
|
/**
|
|
* Sort function to sort ranges by start position.
|
|
* @private
|
|
*/
|
|
|
|
function sortByRangeStart (a, b) {
|
|
return a.start - b.start
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/range-slice-stream/index.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/range-slice-stream/index.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*
|
|
Instance of writable stream.
|
|
|
|
call .get(length) or .discard(length) to get a stream (relative to the last end)
|
|
|
|
emits 'stalled' once everything is written
|
|
|
|
*/
|
|
const { Writable, PassThrough } = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
|
|
class RangeSliceStream extends Writable {
|
|
constructor (offset, opts = {}) {
|
|
super(opts)
|
|
|
|
this.destroyed = false
|
|
this._queue = []
|
|
this._position = offset || 0
|
|
this._cb = null
|
|
this._buffer = null
|
|
this._out = null
|
|
}
|
|
|
|
_write (chunk, encoding, cb) {
|
|
let drained = true
|
|
|
|
while (true) {
|
|
if (this.destroyed) {
|
|
return
|
|
}
|
|
|
|
// Wait for more queue entries
|
|
if (this._queue.length === 0) {
|
|
this._buffer = chunk
|
|
this._cb = cb
|
|
return
|
|
}
|
|
|
|
this._buffer = null
|
|
var currRange = this._queue[0]
|
|
// Relative to the start of chunk, what data do we need?
|
|
const writeStart = Math.max(currRange.start - this._position, 0)
|
|
const writeEnd = currRange.end - this._position
|
|
|
|
// Check if we need to throw it all away
|
|
if (writeStart >= chunk.length) {
|
|
this._position += chunk.length
|
|
return cb(null)
|
|
}
|
|
|
|
// Check if we need to use it all
|
|
let toWrite
|
|
if (writeEnd > chunk.length) {
|
|
this._position += chunk.length
|
|
if (writeStart === 0) {
|
|
toWrite = chunk
|
|
} else {
|
|
toWrite = chunk.slice(writeStart)
|
|
}
|
|
drained = currRange.stream.write(toWrite) && drained
|
|
break
|
|
}
|
|
|
|
this._position += writeEnd
|
|
|
|
toWrite = (writeStart === 0 && writeEnd === chunk.length)
|
|
? chunk
|
|
: chunk.slice(writeStart, writeEnd)
|
|
|
|
drained = currRange.stream.write(toWrite) && drained
|
|
if (currRange.last) {
|
|
currRange.stream.end()
|
|
}
|
|
chunk = chunk.slice(writeEnd)
|
|
this._queue.shift()
|
|
}
|
|
|
|
if (drained) {
|
|
cb(null)
|
|
} else {
|
|
currRange.stream.once('drain', cb.bind(null, null))
|
|
}
|
|
}
|
|
|
|
slice (ranges) {
|
|
if (this.destroyed) return null
|
|
|
|
if (!Array.isArray(ranges)) ranges = [ranges]
|
|
|
|
const str = new PassThrough()
|
|
|
|
ranges.forEach((range, i) => {
|
|
this._queue.push({
|
|
start: range.start,
|
|
end: range.end,
|
|
stream: str,
|
|
last: i === ranges.length - 1
|
|
})
|
|
})
|
|
|
|
if (this._buffer) {
|
|
this._write(this._buffer, null, this._cb)
|
|
}
|
|
|
|
return str
|
|
}
|
|
|
|
destroy (err) {
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
|
|
if (err) this.emit('error', err)
|
|
}
|
|
}
|
|
|
|
module.exports = RangeSliceStream
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/rc4/rc4.js":
|
|
/*!*********************************!*\
|
|
!*** ./node_modules/rc4/rc4.js ***!
|
|
\*********************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// Based on RC4 algorithm, as described in
|
|
// http://en.wikipedia.org/wiki/RC4
|
|
|
|
function isInteger(n) {
|
|
return parseInt(n, 10) === n;
|
|
}
|
|
|
|
function createRC4(N) {
|
|
function identityPermutation() {
|
|
var s = new Array(N);
|
|
for (var i = 0; i < N; i++) {
|
|
s[i] = i;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
// :: string | array integer -> array integer
|
|
function seed(key) {
|
|
if (key === undefined) {
|
|
key = new Array(N);
|
|
for (var k = 0; k < N; k++) {
|
|
key[k] = Math.floor(Math.random() * N);
|
|
}
|
|
} else if (typeof key === "string") {
|
|
// to string
|
|
key = "" + key;
|
|
key = key.split("").map(function (c) { return c.charCodeAt(0) % N; });
|
|
} else if (Array.isArray(key)) {
|
|
if (!key.every(function (v) {
|
|
return typeof v === "number" && v === (v | 0);
|
|
})) {
|
|
throw new TypeError("invalid seed key specified: not array of integers");
|
|
}
|
|
} else {
|
|
throw new TypeError("invalid seed key specified");
|
|
}
|
|
|
|
var keylen = key.length;
|
|
|
|
// resed state
|
|
var s = identityPermutation();
|
|
|
|
var j = 0;
|
|
for (var i = 0; i < N; i++) {
|
|
j = (j + s[i] + key[i % keylen]) % N;
|
|
var tmp = s[i];
|
|
s[i] = s[j];
|
|
s[j] = tmp;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
/* eslint-disable no-shadow */
|
|
function RC4(key) {
|
|
this.s = seed(key);
|
|
this.i = 0;
|
|
this.j = 0;
|
|
}
|
|
/* eslint-enable no-shadow */
|
|
|
|
RC4.prototype.randomNative = function () {
|
|
this.i = (this.i + 1) % N;
|
|
this.j = (this.j + this.s[this.i]) % N;
|
|
|
|
var tmp = this.s[this.i];
|
|
this.s[this.i] = this.s[this.j];
|
|
this.s[this.j] = tmp;
|
|
|
|
var k = this.s[(this.s[this.i] + this.s[this.j]) % N];
|
|
|
|
return k;
|
|
};
|
|
|
|
RC4.prototype.randomUInt32 = function () {
|
|
var a = this.randomByte();
|
|
var b = this.randomByte();
|
|
var c = this.randomByte();
|
|
var d = this.randomByte();
|
|
|
|
return ((a * 256 + b) * 256 + c) * 256 + d;
|
|
};
|
|
|
|
RC4.prototype.randomFloat = function () {
|
|
return this.randomUInt32() / 0x100000000;
|
|
};
|
|
|
|
RC4.prototype.random = function () {
|
|
var a;
|
|
var b;
|
|
|
|
if (arguments.length === 1) {
|
|
a = 0;
|
|
b = arguments[0];
|
|
} else if (arguments.length === 2) {
|
|
a = arguments[0];
|
|
b = arguments[1];
|
|
} else {
|
|
throw new TypeError("random takes one or two integer arguments");
|
|
}
|
|
|
|
if (!isInteger(a) || !isInteger(b)) {
|
|
throw new TypeError("random takes one or two integer arguments");
|
|
}
|
|
|
|
return a + this.randomUInt32() % (b - a + 1);
|
|
};
|
|
|
|
RC4.prototype.currentState = function () {
|
|
return {
|
|
i: this.i,
|
|
j: this.j,
|
|
s: this.s.slice(), // copy
|
|
};
|
|
};
|
|
|
|
RC4.prototype.setState = function (state) {
|
|
var s = state.s;
|
|
var i = state.i;
|
|
var j = state.j;
|
|
|
|
/* eslint-disable yoda */
|
|
if (!(i === (i | 0) && 0 <= i && i < N)) {
|
|
throw new Error("state.i should be integer [0, " + (N - 1) + "]");
|
|
}
|
|
|
|
if (!(j === (j | 0) && 0 <= j && j < N)) {
|
|
throw new Error("state.j should be integer [0, " + (N - 1) + "]");
|
|
}
|
|
/* eslint-enable yoda */
|
|
|
|
// check length
|
|
if (!Array.isArray(s) || s.length !== N) {
|
|
throw new Error("state should be array of length " + N);
|
|
}
|
|
|
|
// check that all params are there
|
|
for (var k = 0; k < N; k++) {
|
|
if (s.indexOf(k) === -1) {
|
|
throw new Error("state should be permutation of 0.." + (N - 1) + ": " + k + " is missing");
|
|
}
|
|
}
|
|
|
|
this.i = i;
|
|
this.j = j;
|
|
this.s = s.slice(); // assign copy
|
|
};
|
|
|
|
return RC4;
|
|
}
|
|
|
|
var RC4 = createRC4(256);
|
|
RC4.prototype.randomByte = RC4.prototype.randomNative;
|
|
|
|
var RC4small = createRC4(16);
|
|
RC4small.prototype.randomByte = function () {
|
|
var a = this.randomNative();
|
|
var b = this.randomNative();
|
|
|
|
return a * 16 + b;
|
|
};
|
|
|
|
var ordA = "a".charCodeAt(0);
|
|
var ord0 = "0".charCodeAt(0);
|
|
|
|
function toHex(n) {
|
|
return n < 10 ? String.fromCharCode(ord0 + n) : String.fromCharCode(ordA + n - 10);
|
|
}
|
|
|
|
function fromHex(c) {
|
|
return parseInt(c, 16);
|
|
}
|
|
|
|
RC4small.prototype.currentStateString = function () {
|
|
var state = this.currentState();
|
|
|
|
var i = toHex(state.i);
|
|
var j = toHex(state.j);
|
|
|
|
var res = i + j + state.s.map(toHex).join("");
|
|
return res;
|
|
};
|
|
|
|
RC4small.prototype.setStateString = function (stateString) {
|
|
if (!stateString.match(/^[0-9a-f]{18}$/)) {
|
|
throw new TypeError("RC4small stateString should be 18 hex character string");
|
|
}
|
|
|
|
var i = fromHex(stateString[0]);
|
|
var j = fromHex(stateString[1]);
|
|
var s = stateString.split("").slice(2).map(fromHex);
|
|
|
|
this.setState({
|
|
i: i,
|
|
j: j,
|
|
s: s,
|
|
});
|
|
};
|
|
|
|
RC4.RC4small = RC4small;
|
|
|
|
module.exports = RC4;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/errors-browser.js":
|
|
/*!********************************************************!*\
|
|
!*** ./node_modules/readable-stream/errors-browser.js ***!
|
|
\********************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
|
|
|
|
var codes = {};
|
|
|
|
function createErrorType(code, message, Base) {
|
|
if (!Base) {
|
|
Base = Error;
|
|
}
|
|
|
|
function getMessage(arg1, arg2, arg3) {
|
|
if (typeof message === 'string') {
|
|
return message;
|
|
} else {
|
|
return message(arg1, arg2, arg3);
|
|
}
|
|
}
|
|
|
|
var NodeError =
|
|
/*#__PURE__*/
|
|
function (_Base) {
|
|
_inheritsLoose(NodeError, _Base);
|
|
|
|
function NodeError(arg1, arg2, arg3) {
|
|
return _Base.call(this, getMessage(arg1, arg2, arg3)) || this;
|
|
}
|
|
|
|
return NodeError;
|
|
}(Base);
|
|
|
|
NodeError.prototype.name = Base.name;
|
|
NodeError.prototype.code = code;
|
|
codes[code] = NodeError;
|
|
} // https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js
|
|
|
|
|
|
function oneOf(expected, thing) {
|
|
if (Array.isArray(expected)) {
|
|
var len = expected.length;
|
|
expected = expected.map(function (i) {
|
|
return String(i);
|
|
});
|
|
|
|
if (len > 2) {
|
|
return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(', '), ", or ") + expected[len - 1];
|
|
} else if (len === 2) {
|
|
return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]);
|
|
} else {
|
|
return "of ".concat(thing, " ").concat(expected[0]);
|
|
}
|
|
} else {
|
|
return "of ".concat(thing, " ").concat(String(expected));
|
|
}
|
|
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
|
|
|
|
|
|
function startsWith(str, search, pos) {
|
|
return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
|
|
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
|
|
|
|
|
|
function endsWith(str, search, this_len) {
|
|
if (this_len === undefined || this_len > str.length) {
|
|
this_len = str.length;
|
|
}
|
|
|
|
return str.substring(this_len - search.length, this_len) === search;
|
|
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
|
|
|
|
|
|
function includes(str, search, start) {
|
|
if (typeof start !== 'number') {
|
|
start = 0;
|
|
}
|
|
|
|
if (start + search.length > str.length) {
|
|
return false;
|
|
} else {
|
|
return str.indexOf(search, start) !== -1;
|
|
}
|
|
}
|
|
|
|
createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) {
|
|
return 'The value "' + value + '" is invalid for option "' + name + '"';
|
|
}, TypeError);
|
|
createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) {
|
|
// determiner: 'must be' or 'must not be'
|
|
var determiner;
|
|
|
|
if (typeof expected === 'string' && startsWith(expected, 'not ')) {
|
|
determiner = 'must not be';
|
|
expected = expected.replace(/^not /, '');
|
|
} else {
|
|
determiner = 'must be';
|
|
}
|
|
|
|
var msg;
|
|
|
|
if (endsWith(name, ' argument')) {
|
|
// For cases like 'first argument'
|
|
msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, 'type'));
|
|
} else {
|
|
var type = includes(name, '.') ? 'property' : 'argument';
|
|
msg = "The \"".concat(name, "\" ").concat(type, " ").concat(determiner, " ").concat(oneOf(expected, 'type'));
|
|
}
|
|
|
|
msg += ". Received type ".concat(typeof actual);
|
|
return msg;
|
|
}, TypeError);
|
|
createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF');
|
|
createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) {
|
|
return 'The ' + name + ' method is not implemented';
|
|
});
|
|
createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close');
|
|
createErrorType('ERR_STREAM_DESTROYED', function (name) {
|
|
return 'Cannot call ' + name + ' after a stream was destroyed';
|
|
});
|
|
createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times');
|
|
createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable');
|
|
createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end');
|
|
createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError);
|
|
createErrorType('ERR_UNKNOWN_ENCODING', function (arg) {
|
|
return 'Unknown encoding: ' + arg;
|
|
}, TypeError);
|
|
createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event');
|
|
module.exports.codes = codes;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/_stream_duplex.js":
|
|
/*!************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/_stream_duplex.js ***!
|
|
\************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
// a duplex stream is just a stream that is both readable and writable.
|
|
// Since JS doesn't have multiple prototypal inheritance, this class
|
|
// prototypally inherits from Readable, and then parasitically from
|
|
// Writable.
|
|
|
|
/*<replacement>*/
|
|
|
|
var objectKeys = Object.keys || function (obj) {
|
|
var keys = [];
|
|
|
|
for (var key in obj) {
|
|
keys.push(key);
|
|
}
|
|
|
|
return keys;
|
|
};
|
|
/*</replacement>*/
|
|
|
|
|
|
module.exports = Duplex;
|
|
|
|
var Readable = __webpack_require__(/*! ./_stream_readable */ "./node_modules/readable-stream/lib/_stream_readable.js");
|
|
|
|
var Writable = __webpack_require__(/*! ./_stream_writable */ "./node_modules/readable-stream/lib/_stream_writable.js");
|
|
|
|
__webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")(Duplex, Readable);
|
|
|
|
{
|
|
// Allow the keys array to be GC'ed.
|
|
var keys = objectKeys(Writable.prototype);
|
|
|
|
for (var v = 0; v < keys.length; v++) {
|
|
var method = keys[v];
|
|
if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
|
|
}
|
|
}
|
|
|
|
function Duplex(options) {
|
|
if (!(this instanceof Duplex)) return new Duplex(options);
|
|
Readable.call(this, options);
|
|
Writable.call(this, options);
|
|
this.allowHalfOpen = true;
|
|
|
|
if (options) {
|
|
if (options.readable === false) this.readable = false;
|
|
if (options.writable === false) this.writable = false;
|
|
|
|
if (options.allowHalfOpen === false) {
|
|
this.allowHalfOpen = false;
|
|
this.once('end', onend);
|
|
}
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
return this._writableState.highWaterMark;
|
|
}
|
|
});
|
|
Object.defineProperty(Duplex.prototype, 'writableBuffer', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
return this._writableState && this._writableState.getBuffer();
|
|
}
|
|
});
|
|
Object.defineProperty(Duplex.prototype, 'writableLength', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
return this._writableState.length;
|
|
}
|
|
}); // the no-half-open enforcer
|
|
|
|
function onend() {
|
|
// If the writable side ended, then we're ok.
|
|
if (this._writableState.ended) return; // no more data can be written.
|
|
// But allow more writes to happen in this tick.
|
|
|
|
process.nextTick(onEndNT, this);
|
|
}
|
|
|
|
function onEndNT(self) {
|
|
self.end();
|
|
}
|
|
|
|
Object.defineProperty(Duplex.prototype, 'destroyed', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
if (this._readableState === undefined || this._writableState === undefined) {
|
|
return false;
|
|
}
|
|
|
|
return this._readableState.destroyed && this._writableState.destroyed;
|
|
},
|
|
set: function set(value) {
|
|
// we ignore the value if the stream
|
|
// has not been initialized yet
|
|
if (this._readableState === undefined || this._writableState === undefined) {
|
|
return;
|
|
} // backward compatibility, the user is explicitly
|
|
// managing destroyed
|
|
|
|
|
|
this._readableState.destroyed = value;
|
|
this._writableState.destroyed = value;
|
|
}
|
|
});
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/_stream_passthrough.js":
|
|
/*!*****************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/_stream_passthrough.js ***!
|
|
\*****************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
// a passthrough stream.
|
|
// basically just the most minimal sort of Transform stream.
|
|
// Every written chunk gets output as-is.
|
|
|
|
|
|
module.exports = PassThrough;
|
|
|
|
var Transform = __webpack_require__(/*! ./_stream_transform */ "./node_modules/readable-stream/lib/_stream_transform.js");
|
|
|
|
__webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")(PassThrough, Transform);
|
|
|
|
function PassThrough(options) {
|
|
if (!(this instanceof PassThrough)) return new PassThrough(options);
|
|
Transform.call(this, options);
|
|
}
|
|
|
|
PassThrough.prototype._transform = function (chunk, encoding, cb) {
|
|
cb(null, chunk);
|
|
};
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/_stream_readable.js":
|
|
/*!**************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/_stream_readable.js ***!
|
|
\**************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
module.exports = Readable;
|
|
/*<replacement>*/
|
|
|
|
var Duplex;
|
|
/*</replacement>*/
|
|
|
|
Readable.ReadableState = ReadableState;
|
|
/*<replacement>*/
|
|
|
|
var EE = __webpack_require__(/*! events */ "./node_modules/events/events.js").EventEmitter;
|
|
|
|
var EElistenerCount = function EElistenerCount(emitter, type) {
|
|
return emitter.listeners(type).length;
|
|
};
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
|
|
|
|
var Stream = __webpack_require__(/*! ./internal/streams/stream */ "./node_modules/readable-stream/lib/internal/streams/stream-browser.js");
|
|
/*</replacement>*/
|
|
|
|
|
|
var Buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js").Buffer;
|
|
|
|
var OurUint8Array = __webpack_require__.g.Uint8Array || function () {};
|
|
|
|
function _uint8ArrayToBuffer(chunk) {
|
|
return Buffer.from(chunk);
|
|
}
|
|
|
|
function _isUint8Array(obj) {
|
|
return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
|
|
}
|
|
/*<replacement>*/
|
|
|
|
|
|
var debugUtil = __webpack_require__(/*! util */ "?d17e");
|
|
|
|
var debug;
|
|
|
|
if (debugUtil && debugUtil.debuglog) {
|
|
debug = debugUtil.debuglog('stream');
|
|
} else {
|
|
debug = function debug() {};
|
|
}
|
|
/*</replacement>*/
|
|
|
|
|
|
var BufferList = __webpack_require__(/*! ./internal/streams/buffer_list */ "./node_modules/readable-stream/lib/internal/streams/buffer_list.js");
|
|
|
|
var destroyImpl = __webpack_require__(/*! ./internal/streams/destroy */ "./node_modules/readable-stream/lib/internal/streams/destroy.js");
|
|
|
|
var _require = __webpack_require__(/*! ./internal/streams/state */ "./node_modules/readable-stream/lib/internal/streams/state.js"),
|
|
getHighWaterMark = _require.getHighWaterMark;
|
|
|
|
var _require$codes = __webpack_require__(/*! ../errors */ "./node_modules/readable-stream/errors-browser.js").codes,
|
|
ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE,
|
|
ERR_STREAM_PUSH_AFTER_EOF = _require$codes.ERR_STREAM_PUSH_AFTER_EOF,
|
|
ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED,
|
|
ERR_STREAM_UNSHIFT_AFTER_END_EVENT = _require$codes.ERR_STREAM_UNSHIFT_AFTER_END_EVENT; // Lazy loaded to improve the startup performance.
|
|
|
|
|
|
var StringDecoder;
|
|
var createReadableStreamAsyncIterator;
|
|
var from;
|
|
|
|
__webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")(Readable, Stream);
|
|
|
|
var errorOrDestroy = destroyImpl.errorOrDestroy;
|
|
var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume'];
|
|
|
|
function prependListener(emitter, event, fn) {
|
|
// Sadly this is not cacheable as some libraries bundle their own
|
|
// event emitter implementation with them.
|
|
if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); // This is a hack to make sure that our error handler is attached before any
|
|
// userland ones. NEVER DO THIS. This is here only because this code needs
|
|
// to continue to work with older versions of Node.js that do not include
|
|
// the prependListener() method. The goal is to eventually remove this hack.
|
|
|
|
if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (Array.isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]];
|
|
}
|
|
|
|
function ReadableState(options, stream, isDuplex) {
|
|
Duplex = Duplex || __webpack_require__(/*! ./_stream_duplex */ "./node_modules/readable-stream/lib/_stream_duplex.js");
|
|
options = options || {}; // Duplex streams are both readable and writable, but share
|
|
// the same options object.
|
|
// However, some cases require setting options to different
|
|
// values for the readable and the writable sides of the duplex stream.
|
|
// These options can be provided separately as readableXXX and writableXXX.
|
|
|
|
if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag. Used to make read(n) ignore n and to
|
|
// make all the buffer merging and length checks go away
|
|
|
|
this.objectMode = !!options.objectMode;
|
|
if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; // the point at which it stops calling _read() to fill the buffer
|
|
// Note: 0 is a valid value, means "don't call _read preemptively ever"
|
|
|
|
this.highWaterMark = getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex); // A linked list is used to store data chunks instead of an array because the
|
|
// linked list can remove elements from the beginning faster than
|
|
// array.shift()
|
|
|
|
this.buffer = new BufferList();
|
|
this.length = 0;
|
|
this.pipes = null;
|
|
this.pipesCount = 0;
|
|
this.flowing = null;
|
|
this.ended = false;
|
|
this.endEmitted = false;
|
|
this.reading = false; // a flag to be able to tell if the event 'readable'/'data' is emitted
|
|
// immediately, or on a later tick. We set this to true at first, because
|
|
// any actions that shouldn't happen until "later" should generally also
|
|
// not happen before the first read call.
|
|
|
|
this.sync = true; // whenever we return null, then we set a flag to say
|
|
// that we're awaiting a 'readable' event emission.
|
|
|
|
this.needReadable = false;
|
|
this.emittedReadable = false;
|
|
this.readableListening = false;
|
|
this.resumeScheduled = false;
|
|
this.paused = true; // Should close be emitted on destroy. Defaults to true.
|
|
|
|
this.emitClose = options.emitClose !== false; // Should .destroy() be called after 'end' (and potentially 'finish')
|
|
|
|
this.autoDestroy = !!options.autoDestroy; // has it been destroyed
|
|
|
|
this.destroyed = false; // Crypto is kind of old and crusty. Historically, its default string
|
|
// encoding is 'binary' so we have to make this configurable.
|
|
// Everything else in the universe uses 'utf8', though.
|
|
|
|
this.defaultEncoding = options.defaultEncoding || 'utf8'; // the number of writers that are awaiting a drain event in .pipe()s
|
|
|
|
this.awaitDrain = 0; // if true, a maybeReadMore has been scheduled
|
|
|
|
this.readingMore = false;
|
|
this.decoder = null;
|
|
this.encoding = null;
|
|
|
|
if (options.encoding) {
|
|
if (!StringDecoder) StringDecoder = __webpack_require__(/*! string_decoder/ */ "./node_modules/string_decoder/lib/string_decoder.js").StringDecoder;
|
|
this.decoder = new StringDecoder(options.encoding);
|
|
this.encoding = options.encoding;
|
|
}
|
|
}
|
|
|
|
function Readable(options) {
|
|
Duplex = Duplex || __webpack_require__(/*! ./_stream_duplex */ "./node_modules/readable-stream/lib/_stream_duplex.js");
|
|
if (!(this instanceof Readable)) return new Readable(options); // Checking for a Stream.Duplex instance is faster here instead of inside
|
|
// the ReadableState constructor, at least with V8 6.5
|
|
|
|
var isDuplex = this instanceof Duplex;
|
|
this._readableState = new ReadableState(options, this, isDuplex); // legacy
|
|
|
|
this.readable = true;
|
|
|
|
if (options) {
|
|
if (typeof options.read === 'function') this._read = options.read;
|
|
if (typeof options.destroy === 'function') this._destroy = options.destroy;
|
|
}
|
|
|
|
Stream.call(this);
|
|
}
|
|
|
|
Object.defineProperty(Readable.prototype, 'destroyed', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
if (this._readableState === undefined) {
|
|
return false;
|
|
}
|
|
|
|
return this._readableState.destroyed;
|
|
},
|
|
set: function set(value) {
|
|
// we ignore the value if the stream
|
|
// has not been initialized yet
|
|
if (!this._readableState) {
|
|
return;
|
|
} // backward compatibility, the user is explicitly
|
|
// managing destroyed
|
|
|
|
|
|
this._readableState.destroyed = value;
|
|
}
|
|
});
|
|
Readable.prototype.destroy = destroyImpl.destroy;
|
|
Readable.prototype._undestroy = destroyImpl.undestroy;
|
|
|
|
Readable.prototype._destroy = function (err, cb) {
|
|
cb(err);
|
|
}; // Manually shove something into the read() buffer.
|
|
// This returns true if the highWaterMark has not been hit yet,
|
|
// similar to how Writable.write() returns true if you should
|
|
// write() some more.
|
|
|
|
|
|
Readable.prototype.push = function (chunk, encoding) {
|
|
var state = this._readableState;
|
|
var skipChunkCheck;
|
|
|
|
if (!state.objectMode) {
|
|
if (typeof chunk === 'string') {
|
|
encoding = encoding || state.defaultEncoding;
|
|
|
|
if (encoding !== state.encoding) {
|
|
chunk = Buffer.from(chunk, encoding);
|
|
encoding = '';
|
|
}
|
|
|
|
skipChunkCheck = true;
|
|
}
|
|
} else {
|
|
skipChunkCheck = true;
|
|
}
|
|
|
|
return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
|
|
}; // Unshift should *always* be something directly out of read()
|
|
|
|
|
|
Readable.prototype.unshift = function (chunk) {
|
|
return readableAddChunk(this, chunk, null, true, false);
|
|
};
|
|
|
|
function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
|
|
debug('readableAddChunk', chunk);
|
|
var state = stream._readableState;
|
|
|
|
if (chunk === null) {
|
|
state.reading = false;
|
|
onEofChunk(stream, state);
|
|
} else {
|
|
var er;
|
|
if (!skipChunkCheck) er = chunkInvalid(state, chunk);
|
|
|
|
if (er) {
|
|
errorOrDestroy(stream, er);
|
|
} else if (state.objectMode || chunk && chunk.length > 0) {
|
|
if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) {
|
|
chunk = _uint8ArrayToBuffer(chunk);
|
|
}
|
|
|
|
if (addToFront) {
|
|
if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT());else addChunk(stream, state, chunk, true);
|
|
} else if (state.ended) {
|
|
errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF());
|
|
} else if (state.destroyed) {
|
|
return false;
|
|
} else {
|
|
state.reading = false;
|
|
|
|
if (state.decoder && !encoding) {
|
|
chunk = state.decoder.write(chunk);
|
|
if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state);
|
|
} else {
|
|
addChunk(stream, state, chunk, false);
|
|
}
|
|
}
|
|
} else if (!addToFront) {
|
|
state.reading = false;
|
|
maybeReadMore(stream, state);
|
|
}
|
|
} // We can push more data if we are below the highWaterMark.
|
|
// Also, if we have no data yet, we can stand some more bytes.
|
|
// This is to work around cases where hwm=0, such as the repl.
|
|
|
|
|
|
return !state.ended && (state.length < state.highWaterMark || state.length === 0);
|
|
}
|
|
|
|
function addChunk(stream, state, chunk, addToFront) {
|
|
if (state.flowing && state.length === 0 && !state.sync) {
|
|
state.awaitDrain = 0;
|
|
stream.emit('data', chunk);
|
|
} else {
|
|
// update the buffer info.
|
|
state.length += state.objectMode ? 1 : chunk.length;
|
|
if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk);
|
|
if (state.needReadable) emitReadable(stream);
|
|
}
|
|
|
|
maybeReadMore(stream, state);
|
|
}
|
|
|
|
function chunkInvalid(state, chunk) {
|
|
var er;
|
|
|
|
if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
|
|
er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk);
|
|
}
|
|
|
|
return er;
|
|
}
|
|
|
|
Readable.prototype.isPaused = function () {
|
|
return this._readableState.flowing === false;
|
|
}; // backwards compatibility.
|
|
|
|
|
|
Readable.prototype.setEncoding = function (enc) {
|
|
if (!StringDecoder) StringDecoder = __webpack_require__(/*! string_decoder/ */ "./node_modules/string_decoder/lib/string_decoder.js").StringDecoder;
|
|
var decoder = new StringDecoder(enc);
|
|
this._readableState.decoder = decoder; // If setEncoding(null), decoder.encoding equals utf8
|
|
|
|
this._readableState.encoding = this._readableState.decoder.encoding; // Iterate over current buffer to convert already stored Buffers:
|
|
|
|
var p = this._readableState.buffer.head;
|
|
var content = '';
|
|
|
|
while (p !== null) {
|
|
content += decoder.write(p.data);
|
|
p = p.next;
|
|
}
|
|
|
|
this._readableState.buffer.clear();
|
|
|
|
if (content !== '') this._readableState.buffer.push(content);
|
|
this._readableState.length = content.length;
|
|
return this;
|
|
}; // Don't raise the hwm > 1GB
|
|
|
|
|
|
var MAX_HWM = 0x40000000;
|
|
|
|
function computeNewHighWaterMark(n) {
|
|
if (n >= MAX_HWM) {
|
|
// TODO(ronag): Throw ERR_VALUE_OUT_OF_RANGE.
|
|
n = MAX_HWM;
|
|
} else {
|
|
// Get the next highest power of 2 to prevent increasing hwm excessively in
|
|
// tiny amounts
|
|
n--;
|
|
n |= n >>> 1;
|
|
n |= n >>> 2;
|
|
n |= n >>> 4;
|
|
n |= n >>> 8;
|
|
n |= n >>> 16;
|
|
n++;
|
|
}
|
|
|
|
return n;
|
|
} // This function is designed to be inlinable, so please take care when making
|
|
// changes to the function body.
|
|
|
|
|
|
function howMuchToRead(n, state) {
|
|
if (n <= 0 || state.length === 0 && state.ended) return 0;
|
|
if (state.objectMode) return 1;
|
|
|
|
if (n !== n) {
|
|
// Only flow one buffer at a time
|
|
if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length;
|
|
} // If we're asking for more than the current hwm, then raise the hwm.
|
|
|
|
|
|
if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
|
|
if (n <= state.length) return n; // Don't have enough
|
|
|
|
if (!state.ended) {
|
|
state.needReadable = true;
|
|
return 0;
|
|
}
|
|
|
|
return state.length;
|
|
} // you can override either this method, or the async _read(n) below.
|
|
|
|
|
|
Readable.prototype.read = function (n) {
|
|
debug('read', n);
|
|
n = parseInt(n, 10);
|
|
var state = this._readableState;
|
|
var nOrig = n;
|
|
if (n !== 0) state.emittedReadable = false; // if we're doing read(0) to trigger a readable event, but we
|
|
// already have a bunch of data in the buffer, then just trigger
|
|
// the 'readable' event and move on.
|
|
|
|
if (n === 0 && state.needReadable && ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) {
|
|
debug('read: emitReadable', state.length, state.ended);
|
|
if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this);
|
|
return null;
|
|
}
|
|
|
|
n = howMuchToRead(n, state); // if we've ended, and we're now clear, then finish it up.
|
|
|
|
if (n === 0 && state.ended) {
|
|
if (state.length === 0) endReadable(this);
|
|
return null;
|
|
} // All the actual chunk generation logic needs to be
|
|
// *below* the call to _read. The reason is that in certain
|
|
// synthetic stream cases, such as passthrough streams, _read
|
|
// may be a completely synchronous operation which may change
|
|
// the state of the read buffer, providing enough data when
|
|
// before there was *not* enough.
|
|
//
|
|
// So, the steps are:
|
|
// 1. Figure out what the state of things will be after we do
|
|
// a read from the buffer.
|
|
//
|
|
// 2. If that resulting state will trigger a _read, then call _read.
|
|
// Note that this may be asynchronous, or synchronous. Yes, it is
|
|
// deeply ugly to write APIs this way, but that still doesn't mean
|
|
// that the Readable class should behave improperly, as streams are
|
|
// designed to be sync/async agnostic.
|
|
// Take note if the _read call is sync or async (ie, if the read call
|
|
// has returned yet), so that we know whether or not it's safe to emit
|
|
// 'readable' etc.
|
|
//
|
|
// 3. Actually pull the requested chunks out of the buffer and return.
|
|
// if we need a readable event, then we need to do some reading.
|
|
|
|
|
|
var doRead = state.needReadable;
|
|
debug('need readable', doRead); // if we currently have less than the highWaterMark, then also read some
|
|
|
|
if (state.length === 0 || state.length - n < state.highWaterMark) {
|
|
doRead = true;
|
|
debug('length less than watermark', doRead);
|
|
} // however, if we've ended, then there's no point, and if we're already
|
|
// reading, then it's unnecessary.
|
|
|
|
|
|
if (state.ended || state.reading) {
|
|
doRead = false;
|
|
debug('reading or ended', doRead);
|
|
} else if (doRead) {
|
|
debug('do read');
|
|
state.reading = true;
|
|
state.sync = true; // if the length is currently zero, then we *need* a readable event.
|
|
|
|
if (state.length === 0) state.needReadable = true; // call internal read method
|
|
|
|
this._read(state.highWaterMark);
|
|
|
|
state.sync = false; // If _read pushed data synchronously, then `reading` will be false,
|
|
// and we need to re-evaluate how much data we can return to the user.
|
|
|
|
if (!state.reading) n = howMuchToRead(nOrig, state);
|
|
}
|
|
|
|
var ret;
|
|
if (n > 0) ret = fromList(n, state);else ret = null;
|
|
|
|
if (ret === null) {
|
|
state.needReadable = state.length <= state.highWaterMark;
|
|
n = 0;
|
|
} else {
|
|
state.length -= n;
|
|
state.awaitDrain = 0;
|
|
}
|
|
|
|
if (state.length === 0) {
|
|
// If we have nothing in the buffer, then we want to know
|
|
// as soon as we *do* get something into the buffer.
|
|
if (!state.ended) state.needReadable = true; // If we tried to read() past the EOF, then emit end on the next tick.
|
|
|
|
if (nOrig !== n && state.ended) endReadable(this);
|
|
}
|
|
|
|
if (ret !== null) this.emit('data', ret);
|
|
return ret;
|
|
};
|
|
|
|
function onEofChunk(stream, state) {
|
|
debug('onEofChunk');
|
|
if (state.ended) return;
|
|
|
|
if (state.decoder) {
|
|
var chunk = state.decoder.end();
|
|
|
|
if (chunk && chunk.length) {
|
|
state.buffer.push(chunk);
|
|
state.length += state.objectMode ? 1 : chunk.length;
|
|
}
|
|
}
|
|
|
|
state.ended = true;
|
|
|
|
if (state.sync) {
|
|
// if we are sync, wait until next tick to emit the data.
|
|
// Otherwise we risk emitting data in the flow()
|
|
// the readable code triggers during a read() call
|
|
emitReadable(stream);
|
|
} else {
|
|
// emit 'readable' now to make sure it gets picked up.
|
|
state.needReadable = false;
|
|
|
|
if (!state.emittedReadable) {
|
|
state.emittedReadable = true;
|
|
emitReadable_(stream);
|
|
}
|
|
}
|
|
} // Don't emit readable right away in sync mode, because this can trigger
|
|
// another read() call => stack overflow. This way, it might trigger
|
|
// a nextTick recursion warning, but that's not so bad.
|
|
|
|
|
|
function emitReadable(stream) {
|
|
var state = stream._readableState;
|
|
debug('emitReadable', state.needReadable, state.emittedReadable);
|
|
state.needReadable = false;
|
|
|
|
if (!state.emittedReadable) {
|
|
debug('emitReadable', state.flowing);
|
|
state.emittedReadable = true;
|
|
process.nextTick(emitReadable_, stream);
|
|
}
|
|
}
|
|
|
|
function emitReadable_(stream) {
|
|
var state = stream._readableState;
|
|
debug('emitReadable_', state.destroyed, state.length, state.ended);
|
|
|
|
if (!state.destroyed && (state.length || state.ended)) {
|
|
stream.emit('readable');
|
|
state.emittedReadable = false;
|
|
} // The stream needs another readable event if
|
|
// 1. It is not flowing, as the flow mechanism will take
|
|
// care of it.
|
|
// 2. It is not ended.
|
|
// 3. It is below the highWaterMark, so we can schedule
|
|
// another readable later.
|
|
|
|
|
|
state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark;
|
|
flow(stream);
|
|
} // at this point, the user has presumably seen the 'readable' event,
|
|
// and called read() to consume some data. that may have triggered
|
|
// in turn another _read(n) call, in which case reading = true if
|
|
// it's in progress.
|
|
// However, if we're not ended, or reading, and the length < hwm,
|
|
// then go ahead and try to read some more preemptively.
|
|
|
|
|
|
function maybeReadMore(stream, state) {
|
|
if (!state.readingMore) {
|
|
state.readingMore = true;
|
|
process.nextTick(maybeReadMore_, stream, state);
|
|
}
|
|
}
|
|
|
|
function maybeReadMore_(stream, state) {
|
|
// Attempt to read more data if we should.
|
|
//
|
|
// The conditions for reading more data are (one of):
|
|
// - Not enough data buffered (state.length < state.highWaterMark). The loop
|
|
// is responsible for filling the buffer with enough data if such data
|
|
// is available. If highWaterMark is 0 and we are not in the flowing mode
|
|
// we should _not_ attempt to buffer any extra data. We'll get more data
|
|
// when the stream consumer calls read() instead.
|
|
// - No data in the buffer, and the stream is in flowing mode. In this mode
|
|
// the loop below is responsible for ensuring read() is called. Failing to
|
|
// call read here would abort the flow and there's no other mechanism for
|
|
// continuing the flow if the stream consumer has just subscribed to the
|
|
// 'data' event.
|
|
//
|
|
// In addition to the above conditions to keep reading data, the following
|
|
// conditions prevent the data from being read:
|
|
// - The stream has ended (state.ended).
|
|
// - There is already a pending 'read' operation (state.reading). This is a
|
|
// case where the the stream has called the implementation defined _read()
|
|
// method, but they are processing the call asynchronously and have _not_
|
|
// called push() with new data. In this case we skip performing more
|
|
// read()s. The execution ends in this method again after the _read() ends
|
|
// up calling push() with more data.
|
|
while (!state.reading && !state.ended && (state.length < state.highWaterMark || state.flowing && state.length === 0)) {
|
|
var len = state.length;
|
|
debug('maybeReadMore read 0');
|
|
stream.read(0);
|
|
if (len === state.length) // didn't get any data, stop spinning.
|
|
break;
|
|
}
|
|
|
|
state.readingMore = false;
|
|
} // abstract method. to be overridden in specific implementation classes.
|
|
// call cb(er, data) where data is <= n in length.
|
|
// for virtual (non-string, non-buffer) streams, "length" is somewhat
|
|
// arbitrary, and perhaps not very meaningful.
|
|
|
|
|
|
Readable.prototype._read = function (n) {
|
|
errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED('_read()'));
|
|
};
|
|
|
|
Readable.prototype.pipe = function (dest, pipeOpts) {
|
|
var src = this;
|
|
var state = this._readableState;
|
|
|
|
switch (state.pipesCount) {
|
|
case 0:
|
|
state.pipes = dest;
|
|
break;
|
|
|
|
case 1:
|
|
state.pipes = [state.pipes, dest];
|
|
break;
|
|
|
|
default:
|
|
state.pipes.push(dest);
|
|
break;
|
|
}
|
|
|
|
state.pipesCount += 1;
|
|
debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
|
|
var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
|
|
var endFn = doEnd ? onend : unpipe;
|
|
if (state.endEmitted) process.nextTick(endFn);else src.once('end', endFn);
|
|
dest.on('unpipe', onunpipe);
|
|
|
|
function onunpipe(readable, unpipeInfo) {
|
|
debug('onunpipe');
|
|
|
|
if (readable === src) {
|
|
if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
|
|
unpipeInfo.hasUnpiped = true;
|
|
cleanup();
|
|
}
|
|
}
|
|
}
|
|
|
|
function onend() {
|
|
debug('onend');
|
|
dest.end();
|
|
} // when the dest drains, it reduces the awaitDrain counter
|
|
// on the source. This would be more elegant with a .once()
|
|
// handler in flow(), but adding and removing repeatedly is
|
|
// too slow.
|
|
|
|
|
|
var ondrain = pipeOnDrain(src);
|
|
dest.on('drain', ondrain);
|
|
var cleanedUp = false;
|
|
|
|
function cleanup() {
|
|
debug('cleanup'); // cleanup event handlers once the pipe is broken
|
|
|
|
dest.removeListener('close', onclose);
|
|
dest.removeListener('finish', onfinish);
|
|
dest.removeListener('drain', ondrain);
|
|
dest.removeListener('error', onerror);
|
|
dest.removeListener('unpipe', onunpipe);
|
|
src.removeListener('end', onend);
|
|
src.removeListener('end', unpipe);
|
|
src.removeListener('data', ondata);
|
|
cleanedUp = true; // if the reader is waiting for a drain event from this
|
|
// specific writer, then it would cause it to never start
|
|
// flowing again.
|
|
// So, if this is awaiting a drain, then we just call it now.
|
|
// If we don't know, then assume that we are waiting for one.
|
|
|
|
if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
|
|
}
|
|
|
|
src.on('data', ondata);
|
|
|
|
function ondata(chunk) {
|
|
debug('ondata');
|
|
var ret = dest.write(chunk);
|
|
debug('dest.write', ret);
|
|
|
|
if (ret === false) {
|
|
// If the user unpiped during `dest.write()`, it is possible
|
|
// to get stuck in a permanently paused state if that write
|
|
// also returned false.
|
|
// => Check whether `dest` is still a piping destination.
|
|
if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
|
|
debug('false write response, pause', state.awaitDrain);
|
|
state.awaitDrain++;
|
|
}
|
|
|
|
src.pause();
|
|
}
|
|
} // if the dest has an error, then stop piping into it.
|
|
// however, don't suppress the throwing behavior for this.
|
|
|
|
|
|
function onerror(er) {
|
|
debug('onerror', er);
|
|
unpipe();
|
|
dest.removeListener('error', onerror);
|
|
if (EElistenerCount(dest, 'error') === 0) errorOrDestroy(dest, er);
|
|
} // Make sure our error handler is attached before userland ones.
|
|
|
|
|
|
prependListener(dest, 'error', onerror); // Both close and finish should trigger unpipe, but only once.
|
|
|
|
function onclose() {
|
|
dest.removeListener('finish', onfinish);
|
|
unpipe();
|
|
}
|
|
|
|
dest.once('close', onclose);
|
|
|
|
function onfinish() {
|
|
debug('onfinish');
|
|
dest.removeListener('close', onclose);
|
|
unpipe();
|
|
}
|
|
|
|
dest.once('finish', onfinish);
|
|
|
|
function unpipe() {
|
|
debug('unpipe');
|
|
src.unpipe(dest);
|
|
} // tell the dest that it's being piped to
|
|
|
|
|
|
dest.emit('pipe', src); // start the flow if it hasn't been started already.
|
|
|
|
if (!state.flowing) {
|
|
debug('pipe resume');
|
|
src.resume();
|
|
}
|
|
|
|
return dest;
|
|
};
|
|
|
|
function pipeOnDrain(src) {
|
|
return function pipeOnDrainFunctionResult() {
|
|
var state = src._readableState;
|
|
debug('pipeOnDrain', state.awaitDrain);
|
|
if (state.awaitDrain) state.awaitDrain--;
|
|
|
|
if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
|
|
state.flowing = true;
|
|
flow(src);
|
|
}
|
|
};
|
|
}
|
|
|
|
Readable.prototype.unpipe = function (dest) {
|
|
var state = this._readableState;
|
|
var unpipeInfo = {
|
|
hasUnpiped: false
|
|
}; // if we're not piping anywhere, then do nothing.
|
|
|
|
if (state.pipesCount === 0) return this; // just one destination. most common case.
|
|
|
|
if (state.pipesCount === 1) {
|
|
// passed in one, but it's not the right one.
|
|
if (dest && dest !== state.pipes) return this;
|
|
if (!dest) dest = state.pipes; // got a match.
|
|
|
|
state.pipes = null;
|
|
state.pipesCount = 0;
|
|
state.flowing = false;
|
|
if (dest) dest.emit('unpipe', this, unpipeInfo);
|
|
return this;
|
|
} // slow case. multiple pipe destinations.
|
|
|
|
|
|
if (!dest) {
|
|
// remove all.
|
|
var dests = state.pipes;
|
|
var len = state.pipesCount;
|
|
state.pipes = null;
|
|
state.pipesCount = 0;
|
|
state.flowing = false;
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
dests[i].emit('unpipe', this, {
|
|
hasUnpiped: false
|
|
});
|
|
}
|
|
|
|
return this;
|
|
} // try to find the right one.
|
|
|
|
|
|
var index = indexOf(state.pipes, dest);
|
|
if (index === -1) return this;
|
|
state.pipes.splice(index, 1);
|
|
state.pipesCount -= 1;
|
|
if (state.pipesCount === 1) state.pipes = state.pipes[0];
|
|
dest.emit('unpipe', this, unpipeInfo);
|
|
return this;
|
|
}; // set up data events if they are asked for
|
|
// Ensure readable listeners eventually get something
|
|
|
|
|
|
Readable.prototype.on = function (ev, fn) {
|
|
var res = Stream.prototype.on.call(this, ev, fn);
|
|
var state = this._readableState;
|
|
|
|
if (ev === 'data') {
|
|
// update readableListening so that resume() may be a no-op
|
|
// a few lines down. This is needed to support once('readable').
|
|
state.readableListening = this.listenerCount('readable') > 0; // Try start flowing on next tick if stream isn't explicitly paused
|
|
|
|
if (state.flowing !== false) this.resume();
|
|
} else if (ev === 'readable') {
|
|
if (!state.endEmitted && !state.readableListening) {
|
|
state.readableListening = state.needReadable = true;
|
|
state.flowing = false;
|
|
state.emittedReadable = false;
|
|
debug('on readable', state.length, state.reading);
|
|
|
|
if (state.length) {
|
|
emitReadable(this);
|
|
} else if (!state.reading) {
|
|
process.nextTick(nReadingNextTick, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Readable.prototype.addListener = Readable.prototype.on;
|
|
|
|
Readable.prototype.removeListener = function (ev, fn) {
|
|
var res = Stream.prototype.removeListener.call(this, ev, fn);
|
|
|
|
if (ev === 'readable') {
|
|
// We need to check if there is someone still listening to
|
|
// readable and reset the state. However this needs to happen
|
|
// after readable has been emitted but before I/O (nextTick) to
|
|
// support once('readable', fn) cycles. This means that calling
|
|
// resume within the same tick will have no
|
|
// effect.
|
|
process.nextTick(updateReadableListening, this);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Readable.prototype.removeAllListeners = function (ev) {
|
|
var res = Stream.prototype.removeAllListeners.apply(this, arguments);
|
|
|
|
if (ev === 'readable' || ev === undefined) {
|
|
// We need to check if there is someone still listening to
|
|
// readable and reset the state. However this needs to happen
|
|
// after readable has been emitted but before I/O (nextTick) to
|
|
// support once('readable', fn) cycles. This means that calling
|
|
// resume within the same tick will have no
|
|
// effect.
|
|
process.nextTick(updateReadableListening, this);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
function updateReadableListening(self) {
|
|
var state = self._readableState;
|
|
state.readableListening = self.listenerCount('readable') > 0;
|
|
|
|
if (state.resumeScheduled && !state.paused) {
|
|
// flowing needs to be set to true now, otherwise
|
|
// the upcoming resume will not flow.
|
|
state.flowing = true; // crude way to check if we should resume
|
|
} else if (self.listenerCount('data') > 0) {
|
|
self.resume();
|
|
}
|
|
}
|
|
|
|
function nReadingNextTick(self) {
|
|
debug('readable nexttick read 0');
|
|
self.read(0);
|
|
} // pause() and resume() are remnants of the legacy readable stream API
|
|
// If the user uses them, then switch into old mode.
|
|
|
|
|
|
Readable.prototype.resume = function () {
|
|
var state = this._readableState;
|
|
|
|
if (!state.flowing) {
|
|
debug('resume'); // we flow only if there is no one listening
|
|
// for readable, but we still have to call
|
|
// resume()
|
|
|
|
state.flowing = !state.readableListening;
|
|
resume(this, state);
|
|
}
|
|
|
|
state.paused = false;
|
|
return this;
|
|
};
|
|
|
|
function resume(stream, state) {
|
|
if (!state.resumeScheduled) {
|
|
state.resumeScheduled = true;
|
|
process.nextTick(resume_, stream, state);
|
|
}
|
|
}
|
|
|
|
function resume_(stream, state) {
|
|
debug('resume', state.reading);
|
|
|
|
if (!state.reading) {
|
|
stream.read(0);
|
|
}
|
|
|
|
state.resumeScheduled = false;
|
|
stream.emit('resume');
|
|
flow(stream);
|
|
if (state.flowing && !state.reading) stream.read(0);
|
|
}
|
|
|
|
Readable.prototype.pause = function () {
|
|
debug('call pause flowing=%j', this._readableState.flowing);
|
|
|
|
if (this._readableState.flowing !== false) {
|
|
debug('pause');
|
|
this._readableState.flowing = false;
|
|
this.emit('pause');
|
|
}
|
|
|
|
this._readableState.paused = true;
|
|
return this;
|
|
};
|
|
|
|
function flow(stream) {
|
|
var state = stream._readableState;
|
|
debug('flow', state.flowing);
|
|
|
|
while (state.flowing && stream.read() !== null) {
|
|
;
|
|
}
|
|
} // wrap an old-style stream as the async data source.
|
|
// This is *not* part of the readable stream interface.
|
|
// It is an ugly unfortunate mess of history.
|
|
|
|
|
|
Readable.prototype.wrap = function (stream) {
|
|
var _this = this;
|
|
|
|
var state = this._readableState;
|
|
var paused = false;
|
|
stream.on('end', function () {
|
|
debug('wrapped end');
|
|
|
|
if (state.decoder && !state.ended) {
|
|
var chunk = state.decoder.end();
|
|
if (chunk && chunk.length) _this.push(chunk);
|
|
}
|
|
|
|
_this.push(null);
|
|
});
|
|
stream.on('data', function (chunk) {
|
|
debug('wrapped data');
|
|
if (state.decoder) chunk = state.decoder.write(chunk); // don't skip over falsy values in objectMode
|
|
|
|
if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return;
|
|
|
|
var ret = _this.push(chunk);
|
|
|
|
if (!ret) {
|
|
paused = true;
|
|
stream.pause();
|
|
}
|
|
}); // proxy all the other methods.
|
|
// important when wrapping filters and duplexes.
|
|
|
|
for (var i in stream) {
|
|
if (this[i] === undefined && typeof stream[i] === 'function') {
|
|
this[i] = function methodWrap(method) {
|
|
return function methodWrapReturnFunction() {
|
|
return stream[method].apply(stream, arguments);
|
|
};
|
|
}(i);
|
|
}
|
|
} // proxy certain important events.
|
|
|
|
|
|
for (var n = 0; n < kProxyEvents.length; n++) {
|
|
stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n]));
|
|
} // when we try to consume some more bytes, simply unpause the
|
|
// underlying stream.
|
|
|
|
|
|
this._read = function (n) {
|
|
debug('wrapped _read', n);
|
|
|
|
if (paused) {
|
|
paused = false;
|
|
stream.resume();
|
|
}
|
|
};
|
|
|
|
return this;
|
|
};
|
|
|
|
if (typeof Symbol === 'function') {
|
|
Readable.prototype[Symbol.asyncIterator] = function () {
|
|
if (createReadableStreamAsyncIterator === undefined) {
|
|
createReadableStreamAsyncIterator = __webpack_require__(/*! ./internal/streams/async_iterator */ "./node_modules/readable-stream/lib/internal/streams/async_iterator.js");
|
|
}
|
|
|
|
return createReadableStreamAsyncIterator(this);
|
|
};
|
|
}
|
|
|
|
Object.defineProperty(Readable.prototype, 'readableHighWaterMark', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
return this._readableState.highWaterMark;
|
|
}
|
|
});
|
|
Object.defineProperty(Readable.prototype, 'readableBuffer', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
return this._readableState && this._readableState.buffer;
|
|
}
|
|
});
|
|
Object.defineProperty(Readable.prototype, 'readableFlowing', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
return this._readableState.flowing;
|
|
},
|
|
set: function set(state) {
|
|
if (this._readableState) {
|
|
this._readableState.flowing = state;
|
|
}
|
|
}
|
|
}); // exposed for testing purposes only.
|
|
|
|
Readable._fromList = fromList;
|
|
Object.defineProperty(Readable.prototype, 'readableLength', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
return this._readableState.length;
|
|
}
|
|
}); // Pluck off n bytes from an array of buffers.
|
|
// Length is the combined lengths of all the buffers in the list.
|
|
// This function is designed to be inlinable, so please take care when making
|
|
// changes to the function body.
|
|
|
|
function fromList(n, state) {
|
|
// nothing buffered
|
|
if (state.length === 0) return null;
|
|
var ret;
|
|
if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) {
|
|
// read it all, truncate the list
|
|
if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.first();else ret = state.buffer.concat(state.length);
|
|
state.buffer.clear();
|
|
} else {
|
|
// read part of list
|
|
ret = state.buffer.consume(n, state.decoder);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
function endReadable(stream) {
|
|
var state = stream._readableState;
|
|
debug('endReadable', state.endEmitted);
|
|
|
|
if (!state.endEmitted) {
|
|
state.ended = true;
|
|
process.nextTick(endReadableNT, state, stream);
|
|
}
|
|
}
|
|
|
|
function endReadableNT(state, stream) {
|
|
debug('endReadableNT', state.endEmitted, state.length); // Check that we didn't get one last unshift.
|
|
|
|
if (!state.endEmitted && state.length === 0) {
|
|
state.endEmitted = true;
|
|
stream.readable = false;
|
|
stream.emit('end');
|
|
|
|
if (state.autoDestroy) {
|
|
// In case of duplex streams we need a way to detect
|
|
// if the writable side is ready for autoDestroy as well
|
|
var wState = stream._writableState;
|
|
|
|
if (!wState || wState.autoDestroy && wState.finished) {
|
|
stream.destroy();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (typeof Symbol === 'function') {
|
|
Readable.from = function (iterable, opts) {
|
|
if (from === undefined) {
|
|
from = __webpack_require__(/*! ./internal/streams/from */ "./node_modules/readable-stream/lib/internal/streams/from-browser.js");
|
|
}
|
|
|
|
return from(Readable, iterable, opts);
|
|
};
|
|
}
|
|
|
|
function indexOf(xs, x) {
|
|
for (var i = 0, l = xs.length; i < l; i++) {
|
|
if (xs[i] === x) return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/_stream_transform.js":
|
|
/*!***************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/_stream_transform.js ***!
|
|
\***************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
// a transform stream is a readable/writable stream where you do
|
|
// something with the data. Sometimes it's called a "filter",
|
|
// but that's not a great name for it, since that implies a thing where
|
|
// some bits pass through, and others are simply ignored. (That would
|
|
// be a valid example of a transform, of course.)
|
|
//
|
|
// While the output is causally related to the input, it's not a
|
|
// necessarily symmetric or synchronous transformation. For example,
|
|
// a zlib stream might take multiple plain-text writes(), and then
|
|
// emit a single compressed chunk some time in the future.
|
|
//
|
|
// Here's how this works:
|
|
//
|
|
// The Transform stream has all the aspects of the readable and writable
|
|
// stream classes. When you write(chunk), that calls _write(chunk,cb)
|
|
// internally, and returns false if there's a lot of pending writes
|
|
// buffered up. When you call read(), that calls _read(n) until
|
|
// there's enough pending readable data buffered up.
|
|
//
|
|
// In a transform stream, the written data is placed in a buffer. When
|
|
// _read(n) is called, it transforms the queued up data, calling the
|
|
// buffered _write cb's as it consumes chunks. If consuming a single
|
|
// written chunk would result in multiple output chunks, then the first
|
|
// outputted bit calls the readcb, and subsequent chunks just go into
|
|
// the read buffer, and will cause it to emit 'readable' if necessary.
|
|
//
|
|
// This way, back-pressure is actually determined by the reading side,
|
|
// since _read has to be called to start processing a new chunk. However,
|
|
// a pathological inflate type of transform can cause excessive buffering
|
|
// here. For example, imagine a stream where every byte of input is
|
|
// interpreted as an integer from 0-255, and then results in that many
|
|
// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in
|
|
// 1kb of data being output. In this case, you could write a very small
|
|
// amount of input, and end up with a very large amount of output. In
|
|
// such a pathological inflating mechanism, there'd be no way to tell
|
|
// the system to stop doing the transform. A single 4MB write could
|
|
// cause the system to run out of memory.
|
|
//
|
|
// However, even in such a pathological case, only a single written chunk
|
|
// would be consumed, and then the rest would wait (un-transformed) until
|
|
// the results of the previous transformed chunk were consumed.
|
|
|
|
|
|
module.exports = Transform;
|
|
|
|
var _require$codes = __webpack_require__(/*! ../errors */ "./node_modules/readable-stream/errors-browser.js").codes,
|
|
ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED,
|
|
ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK,
|
|
ERR_TRANSFORM_ALREADY_TRANSFORMING = _require$codes.ERR_TRANSFORM_ALREADY_TRANSFORMING,
|
|
ERR_TRANSFORM_WITH_LENGTH_0 = _require$codes.ERR_TRANSFORM_WITH_LENGTH_0;
|
|
|
|
var Duplex = __webpack_require__(/*! ./_stream_duplex */ "./node_modules/readable-stream/lib/_stream_duplex.js");
|
|
|
|
__webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")(Transform, Duplex);
|
|
|
|
function afterTransform(er, data) {
|
|
var ts = this._transformState;
|
|
ts.transforming = false;
|
|
var cb = ts.writecb;
|
|
|
|
if (cb === null) {
|
|
return this.emit('error', new ERR_MULTIPLE_CALLBACK());
|
|
}
|
|
|
|
ts.writechunk = null;
|
|
ts.writecb = null;
|
|
if (data != null) // single equals check for both `null` and `undefined`
|
|
this.push(data);
|
|
cb(er);
|
|
var rs = this._readableState;
|
|
rs.reading = false;
|
|
|
|
if (rs.needReadable || rs.length < rs.highWaterMark) {
|
|
this._read(rs.highWaterMark);
|
|
}
|
|
}
|
|
|
|
function Transform(options) {
|
|
if (!(this instanceof Transform)) return new Transform(options);
|
|
Duplex.call(this, options);
|
|
this._transformState = {
|
|
afterTransform: afterTransform.bind(this),
|
|
needTransform: false,
|
|
transforming: false,
|
|
writecb: null,
|
|
writechunk: null,
|
|
writeencoding: null
|
|
}; // start out asking for a readable event once data is transformed.
|
|
|
|
this._readableState.needReadable = true; // we have implemented the _read method, and done the other things
|
|
// that Readable wants before the first _read call, so unset the
|
|
// sync guard flag.
|
|
|
|
this._readableState.sync = false;
|
|
|
|
if (options) {
|
|
if (typeof options.transform === 'function') this._transform = options.transform;
|
|
if (typeof options.flush === 'function') this._flush = options.flush;
|
|
} // When the writable side finishes, then flush out anything remaining.
|
|
|
|
|
|
this.on('prefinish', prefinish);
|
|
}
|
|
|
|
function prefinish() {
|
|
var _this = this;
|
|
|
|
if (typeof this._flush === 'function' && !this._readableState.destroyed) {
|
|
this._flush(function (er, data) {
|
|
done(_this, er, data);
|
|
});
|
|
} else {
|
|
done(this, null, null);
|
|
}
|
|
}
|
|
|
|
Transform.prototype.push = function (chunk, encoding) {
|
|
this._transformState.needTransform = false;
|
|
return Duplex.prototype.push.call(this, chunk, encoding);
|
|
}; // This is the part where you do stuff!
|
|
// override this function in implementation classes.
|
|
// 'chunk' is an input chunk.
|
|
//
|
|
// Call `push(newChunk)` to pass along transformed output
|
|
// to the readable side. You may call 'push' zero or more times.
|
|
//
|
|
// Call `cb(err)` when you are done with this chunk. If you pass
|
|
// an error, then that'll put the hurt on the whole operation. If you
|
|
// never call cb(), then you'll never get another chunk.
|
|
|
|
|
|
Transform.prototype._transform = function (chunk, encoding, cb) {
|
|
cb(new ERR_METHOD_NOT_IMPLEMENTED('_transform()'));
|
|
};
|
|
|
|
Transform.prototype._write = function (chunk, encoding, cb) {
|
|
var ts = this._transformState;
|
|
ts.writecb = cb;
|
|
ts.writechunk = chunk;
|
|
ts.writeencoding = encoding;
|
|
|
|
if (!ts.transforming) {
|
|
var rs = this._readableState;
|
|
if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
|
|
}
|
|
}; // Doesn't matter what the args are here.
|
|
// _transform does all the work.
|
|
// That we got here means that the readable side wants more data.
|
|
|
|
|
|
Transform.prototype._read = function (n) {
|
|
var ts = this._transformState;
|
|
|
|
if (ts.writechunk !== null && !ts.transforming) {
|
|
ts.transforming = true;
|
|
|
|
this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
|
|
} else {
|
|
// mark that we need a transform, so that any data that comes in
|
|
// will get processed, now that we've asked for it.
|
|
ts.needTransform = true;
|
|
}
|
|
};
|
|
|
|
Transform.prototype._destroy = function (err, cb) {
|
|
Duplex.prototype._destroy.call(this, err, function (err2) {
|
|
cb(err2);
|
|
});
|
|
};
|
|
|
|
function done(stream, er, data) {
|
|
if (er) return stream.emit('error', er);
|
|
if (data != null) // single equals check for both `null` and `undefined`
|
|
stream.push(data); // TODO(BridgeAR): Write a test for these two error cases
|
|
// if there's nothing in the write buffer, then that means
|
|
// that nothing more will ever be provided
|
|
|
|
if (stream._writableState.length) throw new ERR_TRANSFORM_WITH_LENGTH_0();
|
|
if (stream._transformState.transforming) throw new ERR_TRANSFORM_ALREADY_TRANSFORMING();
|
|
return stream.push(null);
|
|
}
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/_stream_writable.js":
|
|
/*!**************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/_stream_writable.js ***!
|
|
\**************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
// A bit simpler than readable streams.
|
|
// Implement an async ._write(chunk, encoding, cb), and it'll handle all
|
|
// the drain event emission and buffering.
|
|
|
|
|
|
module.exports = Writable;
|
|
/* <replacement> */
|
|
|
|
function WriteReq(chunk, encoding, cb) {
|
|
this.chunk = chunk;
|
|
this.encoding = encoding;
|
|
this.callback = cb;
|
|
this.next = null;
|
|
} // It seems a linked list but it is not
|
|
// there will be only 2 of these for each stream
|
|
|
|
|
|
function CorkedRequest(state) {
|
|
var _this = this;
|
|
|
|
this.next = null;
|
|
this.entry = null;
|
|
|
|
this.finish = function () {
|
|
onCorkedFinish(_this, state);
|
|
};
|
|
}
|
|
/* </replacement> */
|
|
|
|
/*<replacement>*/
|
|
|
|
|
|
var Duplex;
|
|
/*</replacement>*/
|
|
|
|
Writable.WritableState = WritableState;
|
|
/*<replacement>*/
|
|
|
|
var internalUtil = {
|
|
deprecate: __webpack_require__(/*! util-deprecate */ "./node_modules/util-deprecate/browser.js")
|
|
};
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
|
|
var Stream = __webpack_require__(/*! ./internal/streams/stream */ "./node_modules/readable-stream/lib/internal/streams/stream-browser.js");
|
|
/*</replacement>*/
|
|
|
|
|
|
var Buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js").Buffer;
|
|
|
|
var OurUint8Array = __webpack_require__.g.Uint8Array || function () {};
|
|
|
|
function _uint8ArrayToBuffer(chunk) {
|
|
return Buffer.from(chunk);
|
|
}
|
|
|
|
function _isUint8Array(obj) {
|
|
return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
|
|
}
|
|
|
|
var destroyImpl = __webpack_require__(/*! ./internal/streams/destroy */ "./node_modules/readable-stream/lib/internal/streams/destroy.js");
|
|
|
|
var _require = __webpack_require__(/*! ./internal/streams/state */ "./node_modules/readable-stream/lib/internal/streams/state.js"),
|
|
getHighWaterMark = _require.getHighWaterMark;
|
|
|
|
var _require$codes = __webpack_require__(/*! ../errors */ "./node_modules/readable-stream/errors-browser.js").codes,
|
|
ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE,
|
|
ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED,
|
|
ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK,
|
|
ERR_STREAM_CANNOT_PIPE = _require$codes.ERR_STREAM_CANNOT_PIPE,
|
|
ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED,
|
|
ERR_STREAM_NULL_VALUES = _require$codes.ERR_STREAM_NULL_VALUES,
|
|
ERR_STREAM_WRITE_AFTER_END = _require$codes.ERR_STREAM_WRITE_AFTER_END,
|
|
ERR_UNKNOWN_ENCODING = _require$codes.ERR_UNKNOWN_ENCODING;
|
|
|
|
var errorOrDestroy = destroyImpl.errorOrDestroy;
|
|
|
|
__webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")(Writable, Stream);
|
|
|
|
function nop() {}
|
|
|
|
function WritableState(options, stream, isDuplex) {
|
|
Duplex = Duplex || __webpack_require__(/*! ./_stream_duplex */ "./node_modules/readable-stream/lib/_stream_duplex.js");
|
|
options = options || {}; // Duplex streams are both readable and writable, but share
|
|
// the same options object.
|
|
// However, some cases require setting options to different
|
|
// values for the readable and the writable sides of the duplex stream,
|
|
// e.g. options.readableObjectMode vs. options.writableObjectMode, etc.
|
|
|
|
if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag to indicate whether or not this stream
|
|
// contains buffers or objects.
|
|
|
|
this.objectMode = !!options.objectMode;
|
|
if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; // the point at which write() starts returning false
|
|
// Note: 0 is a valid value, means that we always return false if
|
|
// the entire buffer is not flushed immediately on write()
|
|
|
|
this.highWaterMark = getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex); // if _final has been called
|
|
|
|
this.finalCalled = false; // drain event flag.
|
|
|
|
this.needDrain = false; // at the start of calling end()
|
|
|
|
this.ending = false; // when end() has been called, and returned
|
|
|
|
this.ended = false; // when 'finish' is emitted
|
|
|
|
this.finished = false; // has it been destroyed
|
|
|
|
this.destroyed = false; // should we decode strings into buffers before passing to _write?
|
|
// this is here so that some node-core streams can optimize string
|
|
// handling at a lower level.
|
|
|
|
var noDecode = options.decodeStrings === false;
|
|
this.decodeStrings = !noDecode; // Crypto is kind of old and crusty. Historically, its default string
|
|
// encoding is 'binary' so we have to make this configurable.
|
|
// Everything else in the universe uses 'utf8', though.
|
|
|
|
this.defaultEncoding = options.defaultEncoding || 'utf8'; // not an actual buffer we keep track of, but a measurement
|
|
// of how much we're waiting to get pushed to some underlying
|
|
// socket or file.
|
|
|
|
this.length = 0; // a flag to see when we're in the middle of a write.
|
|
|
|
this.writing = false; // when true all writes will be buffered until .uncork() call
|
|
|
|
this.corked = 0; // a flag to be able to tell if the onwrite cb is called immediately,
|
|
// or on a later tick. We set this to true at first, because any
|
|
// actions that shouldn't happen until "later" should generally also
|
|
// not happen before the first write call.
|
|
|
|
this.sync = true; // a flag to know if we're processing previously buffered items, which
|
|
// may call the _write() callback in the same tick, so that we don't
|
|
// end up in an overlapped onwrite situation.
|
|
|
|
this.bufferProcessing = false; // the callback that's passed to _write(chunk,cb)
|
|
|
|
this.onwrite = function (er) {
|
|
onwrite(stream, er);
|
|
}; // the callback that the user supplies to write(chunk,encoding,cb)
|
|
|
|
|
|
this.writecb = null; // the amount that is being written when _write is called.
|
|
|
|
this.writelen = 0;
|
|
this.bufferedRequest = null;
|
|
this.lastBufferedRequest = null; // number of pending user-supplied write callbacks
|
|
// this must be 0 before 'finish' can be emitted
|
|
|
|
this.pendingcb = 0; // emit prefinish if the only thing we're waiting for is _write cbs
|
|
// This is relevant for synchronous Transform streams
|
|
|
|
this.prefinished = false; // True if the error was already emitted and should not be thrown again
|
|
|
|
this.errorEmitted = false; // Should close be emitted on destroy. Defaults to true.
|
|
|
|
this.emitClose = options.emitClose !== false; // Should .destroy() be called after 'finish' (and potentially 'end')
|
|
|
|
this.autoDestroy = !!options.autoDestroy; // count buffered requests
|
|
|
|
this.bufferedRequestCount = 0; // allocate the first CorkedRequest, there is always
|
|
// one allocated and free to use, and we maintain at most two
|
|
|
|
this.corkedRequestsFree = new CorkedRequest(this);
|
|
}
|
|
|
|
WritableState.prototype.getBuffer = function getBuffer() {
|
|
var current = this.bufferedRequest;
|
|
var out = [];
|
|
|
|
while (current) {
|
|
out.push(current);
|
|
current = current.next;
|
|
}
|
|
|
|
return out;
|
|
};
|
|
|
|
(function () {
|
|
try {
|
|
Object.defineProperty(WritableState.prototype, 'buffer', {
|
|
get: internalUtil.deprecate(function writableStateBufferGetter() {
|
|
return this.getBuffer();
|
|
}, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003')
|
|
});
|
|
} catch (_) {}
|
|
})(); // Test _writableState for inheritance to account for Duplex streams,
|
|
// whose prototype chain only points to Readable.
|
|
|
|
|
|
var realHasInstance;
|
|
|
|
if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
|
|
realHasInstance = Function.prototype[Symbol.hasInstance];
|
|
Object.defineProperty(Writable, Symbol.hasInstance, {
|
|
value: function value(object) {
|
|
if (realHasInstance.call(this, object)) return true;
|
|
if (this !== Writable) return false;
|
|
return object && object._writableState instanceof WritableState;
|
|
}
|
|
});
|
|
} else {
|
|
realHasInstance = function realHasInstance(object) {
|
|
return object instanceof this;
|
|
};
|
|
}
|
|
|
|
function Writable(options) {
|
|
Duplex = Duplex || __webpack_require__(/*! ./_stream_duplex */ "./node_modules/readable-stream/lib/_stream_duplex.js"); // Writable ctor is applied to Duplexes, too.
|
|
// `realHasInstance` is necessary because using plain `instanceof`
|
|
// would return false, as no `_writableState` property is attached.
|
|
// Trying to use the custom `instanceof` for Writable here will also break the
|
|
// Node.js LazyTransform implementation, which has a non-trivial getter for
|
|
// `_writableState` that would lead to infinite recursion.
|
|
// Checking for a Stream.Duplex instance is faster here instead of inside
|
|
// the WritableState constructor, at least with V8 6.5
|
|
|
|
var isDuplex = this instanceof Duplex;
|
|
if (!isDuplex && !realHasInstance.call(Writable, this)) return new Writable(options);
|
|
this._writableState = new WritableState(options, this, isDuplex); // legacy.
|
|
|
|
this.writable = true;
|
|
|
|
if (options) {
|
|
if (typeof options.write === 'function') this._write = options.write;
|
|
if (typeof options.writev === 'function') this._writev = options.writev;
|
|
if (typeof options.destroy === 'function') this._destroy = options.destroy;
|
|
if (typeof options.final === 'function') this._final = options.final;
|
|
}
|
|
|
|
Stream.call(this);
|
|
} // Otherwise people can pipe Writable streams, which is just wrong.
|
|
|
|
|
|
Writable.prototype.pipe = function () {
|
|
errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE());
|
|
};
|
|
|
|
function writeAfterEnd(stream, cb) {
|
|
var er = new ERR_STREAM_WRITE_AFTER_END(); // TODO: defer error events consistently everywhere, not just the cb
|
|
|
|
errorOrDestroy(stream, er);
|
|
process.nextTick(cb, er);
|
|
} // Checks that a user-supplied chunk is valid, especially for the particular
|
|
// mode the stream is in. Currently this means that `null` is never accepted
|
|
// and undefined/non-string values are only allowed in object mode.
|
|
|
|
|
|
function validChunk(stream, state, chunk, cb) {
|
|
var er;
|
|
|
|
if (chunk === null) {
|
|
er = new ERR_STREAM_NULL_VALUES();
|
|
} else if (typeof chunk !== 'string' && !state.objectMode) {
|
|
er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk);
|
|
}
|
|
|
|
if (er) {
|
|
errorOrDestroy(stream, er);
|
|
process.nextTick(cb, er);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Writable.prototype.write = function (chunk, encoding, cb) {
|
|
var state = this._writableState;
|
|
var ret = false;
|
|
|
|
var isBuf = !state.objectMode && _isUint8Array(chunk);
|
|
|
|
if (isBuf && !Buffer.isBuffer(chunk)) {
|
|
chunk = _uint8ArrayToBuffer(chunk);
|
|
}
|
|
|
|
if (typeof encoding === 'function') {
|
|
cb = encoding;
|
|
encoding = null;
|
|
}
|
|
|
|
if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;
|
|
if (typeof cb !== 'function') cb = nop;
|
|
if (state.ending) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) {
|
|
state.pendingcb++;
|
|
ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
|
|
}
|
|
return ret;
|
|
};
|
|
|
|
Writable.prototype.cork = function () {
|
|
this._writableState.corked++;
|
|
};
|
|
|
|
Writable.prototype.uncork = function () {
|
|
var state = this._writableState;
|
|
|
|
if (state.corked) {
|
|
state.corked--;
|
|
if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
|
|
}
|
|
};
|
|
|
|
Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
|
|
// node::ParseEncoding() requires lower case.
|
|
if (typeof encoding === 'string') encoding = encoding.toLowerCase();
|
|
if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new ERR_UNKNOWN_ENCODING(encoding);
|
|
this._writableState.defaultEncoding = encoding;
|
|
return this;
|
|
};
|
|
|
|
Object.defineProperty(Writable.prototype, 'writableBuffer', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
return this._writableState && this._writableState.getBuffer();
|
|
}
|
|
});
|
|
|
|
function decodeChunk(state, chunk, encoding) {
|
|
if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
|
|
chunk = Buffer.from(chunk, encoding);
|
|
}
|
|
|
|
return chunk;
|
|
}
|
|
|
|
Object.defineProperty(Writable.prototype, 'writableHighWaterMark', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
return this._writableState.highWaterMark;
|
|
}
|
|
}); // if we're already writing something, then just put this
|
|
// in the queue, and wait our turn. Otherwise, call _write
|
|
// If we return false, then we need a drain event, so set that flag.
|
|
|
|
function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
|
|
if (!isBuf) {
|
|
var newChunk = decodeChunk(state, chunk, encoding);
|
|
|
|
if (chunk !== newChunk) {
|
|
isBuf = true;
|
|
encoding = 'buffer';
|
|
chunk = newChunk;
|
|
}
|
|
}
|
|
|
|
var len = state.objectMode ? 1 : chunk.length;
|
|
state.length += len;
|
|
var ret = state.length < state.highWaterMark; // we must ensure that previous needDrain will not be reset to false.
|
|
|
|
if (!ret) state.needDrain = true;
|
|
|
|
if (state.writing || state.corked) {
|
|
var last = state.lastBufferedRequest;
|
|
state.lastBufferedRequest = {
|
|
chunk: chunk,
|
|
encoding: encoding,
|
|
isBuf: isBuf,
|
|
callback: cb,
|
|
next: null
|
|
};
|
|
|
|
if (last) {
|
|
last.next = state.lastBufferedRequest;
|
|
} else {
|
|
state.bufferedRequest = state.lastBufferedRequest;
|
|
}
|
|
|
|
state.bufferedRequestCount += 1;
|
|
} else {
|
|
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
function doWrite(stream, state, writev, len, chunk, encoding, cb) {
|
|
state.writelen = len;
|
|
state.writecb = cb;
|
|
state.writing = true;
|
|
state.sync = true;
|
|
if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write'));else if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
|
|
state.sync = false;
|
|
}
|
|
|
|
function onwriteError(stream, state, sync, er, cb) {
|
|
--state.pendingcb;
|
|
|
|
if (sync) {
|
|
// defer the callback if we are being called synchronously
|
|
// to avoid piling up things on the stack
|
|
process.nextTick(cb, er); // this can emit finish, and it will always happen
|
|
// after error
|
|
|
|
process.nextTick(finishMaybe, stream, state);
|
|
stream._writableState.errorEmitted = true;
|
|
errorOrDestroy(stream, er);
|
|
} else {
|
|
// the caller expect this to happen before if
|
|
// it is async
|
|
cb(er);
|
|
stream._writableState.errorEmitted = true;
|
|
errorOrDestroy(stream, er); // this can emit finish, but finish must
|
|
// always follow error
|
|
|
|
finishMaybe(stream, state);
|
|
}
|
|
}
|
|
|
|
function onwriteStateUpdate(state) {
|
|
state.writing = false;
|
|
state.writecb = null;
|
|
state.length -= state.writelen;
|
|
state.writelen = 0;
|
|
}
|
|
|
|
function onwrite(stream, er) {
|
|
var state = stream._writableState;
|
|
var sync = state.sync;
|
|
var cb = state.writecb;
|
|
if (typeof cb !== 'function') throw new ERR_MULTIPLE_CALLBACK();
|
|
onwriteStateUpdate(state);
|
|
if (er) onwriteError(stream, state, sync, er, cb);else {
|
|
// Check if we're actually ready to finish, but don't emit yet
|
|
var finished = needFinish(state) || stream.destroyed;
|
|
|
|
if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
|
|
clearBuffer(stream, state);
|
|
}
|
|
|
|
if (sync) {
|
|
process.nextTick(afterWrite, stream, state, finished, cb);
|
|
} else {
|
|
afterWrite(stream, state, finished, cb);
|
|
}
|
|
}
|
|
}
|
|
|
|
function afterWrite(stream, state, finished, cb) {
|
|
if (!finished) onwriteDrain(stream, state);
|
|
state.pendingcb--;
|
|
cb();
|
|
finishMaybe(stream, state);
|
|
} // Must force callback to be called on nextTick, so that we don't
|
|
// emit 'drain' before the write() consumer gets the 'false' return
|
|
// value, and has a chance to attach a 'drain' listener.
|
|
|
|
|
|
function onwriteDrain(stream, state) {
|
|
if (state.length === 0 && state.needDrain) {
|
|
state.needDrain = false;
|
|
stream.emit('drain');
|
|
}
|
|
} // if there's something in the buffer waiting, then process it
|
|
|
|
|
|
function clearBuffer(stream, state) {
|
|
state.bufferProcessing = true;
|
|
var entry = state.bufferedRequest;
|
|
|
|
if (stream._writev && entry && entry.next) {
|
|
// Fast case, write everything using _writev()
|
|
var l = state.bufferedRequestCount;
|
|
var buffer = new Array(l);
|
|
var holder = state.corkedRequestsFree;
|
|
holder.entry = entry;
|
|
var count = 0;
|
|
var allBuffers = true;
|
|
|
|
while (entry) {
|
|
buffer[count] = entry;
|
|
if (!entry.isBuf) allBuffers = false;
|
|
entry = entry.next;
|
|
count += 1;
|
|
}
|
|
|
|
buffer.allBuffers = allBuffers;
|
|
doWrite(stream, state, true, state.length, buffer, '', holder.finish); // doWrite is almost always async, defer these to save a bit of time
|
|
// as the hot path ends with doWrite
|
|
|
|
state.pendingcb++;
|
|
state.lastBufferedRequest = null;
|
|
|
|
if (holder.next) {
|
|
state.corkedRequestsFree = holder.next;
|
|
holder.next = null;
|
|
} else {
|
|
state.corkedRequestsFree = new CorkedRequest(state);
|
|
}
|
|
|
|
state.bufferedRequestCount = 0;
|
|
} else {
|
|
// Slow case, write chunks one-by-one
|
|
while (entry) {
|
|
var chunk = entry.chunk;
|
|
var encoding = entry.encoding;
|
|
var cb = entry.callback;
|
|
var len = state.objectMode ? 1 : chunk.length;
|
|
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
entry = entry.next;
|
|
state.bufferedRequestCount--; // if we didn't call the onwrite immediately, then
|
|
// it means that we need to wait until it does.
|
|
// also, that means that the chunk and cb are currently
|
|
// being processed, so move the buffer counter past them.
|
|
|
|
if (state.writing) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (entry === null) state.lastBufferedRequest = null;
|
|
}
|
|
|
|
state.bufferedRequest = entry;
|
|
state.bufferProcessing = false;
|
|
}
|
|
|
|
Writable.prototype._write = function (chunk, encoding, cb) {
|
|
cb(new ERR_METHOD_NOT_IMPLEMENTED('_write()'));
|
|
};
|
|
|
|
Writable.prototype._writev = null;
|
|
|
|
Writable.prototype.end = function (chunk, encoding, cb) {
|
|
var state = this._writableState;
|
|
|
|
if (typeof chunk === 'function') {
|
|
cb = chunk;
|
|
chunk = null;
|
|
encoding = null;
|
|
} else if (typeof encoding === 'function') {
|
|
cb = encoding;
|
|
encoding = null;
|
|
}
|
|
|
|
if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); // .end() fully uncorks
|
|
|
|
if (state.corked) {
|
|
state.corked = 1;
|
|
this.uncork();
|
|
} // ignore unnecessary end() calls.
|
|
|
|
|
|
if (!state.ending) endWritable(this, state, cb);
|
|
return this;
|
|
};
|
|
|
|
Object.defineProperty(Writable.prototype, 'writableLength', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
return this._writableState.length;
|
|
}
|
|
});
|
|
|
|
function needFinish(state) {
|
|
return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
|
|
}
|
|
|
|
function callFinal(stream, state) {
|
|
stream._final(function (err) {
|
|
state.pendingcb--;
|
|
|
|
if (err) {
|
|
errorOrDestroy(stream, err);
|
|
}
|
|
|
|
state.prefinished = true;
|
|
stream.emit('prefinish');
|
|
finishMaybe(stream, state);
|
|
});
|
|
}
|
|
|
|
function prefinish(stream, state) {
|
|
if (!state.prefinished && !state.finalCalled) {
|
|
if (typeof stream._final === 'function' && !state.destroyed) {
|
|
state.pendingcb++;
|
|
state.finalCalled = true;
|
|
process.nextTick(callFinal, stream, state);
|
|
} else {
|
|
state.prefinished = true;
|
|
stream.emit('prefinish');
|
|
}
|
|
}
|
|
}
|
|
|
|
function finishMaybe(stream, state) {
|
|
var need = needFinish(state);
|
|
|
|
if (need) {
|
|
prefinish(stream, state);
|
|
|
|
if (state.pendingcb === 0) {
|
|
state.finished = true;
|
|
stream.emit('finish');
|
|
|
|
if (state.autoDestroy) {
|
|
// In case of duplex streams we need a way to detect
|
|
// if the readable side is ready for autoDestroy as well
|
|
var rState = stream._readableState;
|
|
|
|
if (!rState || rState.autoDestroy && rState.endEmitted) {
|
|
stream.destroy();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return need;
|
|
}
|
|
|
|
function endWritable(stream, state, cb) {
|
|
state.ending = true;
|
|
finishMaybe(stream, state);
|
|
|
|
if (cb) {
|
|
if (state.finished) process.nextTick(cb);else stream.once('finish', cb);
|
|
}
|
|
|
|
state.ended = true;
|
|
stream.writable = false;
|
|
}
|
|
|
|
function onCorkedFinish(corkReq, state, err) {
|
|
var entry = corkReq.entry;
|
|
corkReq.entry = null;
|
|
|
|
while (entry) {
|
|
var cb = entry.callback;
|
|
state.pendingcb--;
|
|
cb(err);
|
|
entry = entry.next;
|
|
} // reuse the free corkReq.
|
|
|
|
|
|
state.corkedRequestsFree.next = corkReq;
|
|
}
|
|
|
|
Object.defineProperty(Writable.prototype, 'destroyed', {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function get() {
|
|
if (this._writableState === undefined) {
|
|
return false;
|
|
}
|
|
|
|
return this._writableState.destroyed;
|
|
},
|
|
set: function set(value) {
|
|
// we ignore the value if the stream
|
|
// has not been initialized yet
|
|
if (!this._writableState) {
|
|
return;
|
|
} // backward compatibility, the user is explicitly
|
|
// managing destroyed
|
|
|
|
|
|
this._writableState.destroyed = value;
|
|
}
|
|
});
|
|
Writable.prototype.destroy = destroyImpl.destroy;
|
|
Writable.prototype._undestroy = destroyImpl.undestroy;
|
|
|
|
Writable.prototype._destroy = function (err, cb) {
|
|
cb(err);
|
|
};
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/internal/streams/async_iterator.js":
|
|
/*!*****************************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/internal/streams/async_iterator.js ***!
|
|
\*****************************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
|
|
|
|
var _Object$setPrototypeO;
|
|
|
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
|
|
var finished = __webpack_require__(/*! ./end-of-stream */ "./node_modules/readable-stream/lib/internal/streams/end-of-stream.js");
|
|
|
|
var kLastResolve = Symbol('lastResolve');
|
|
var kLastReject = Symbol('lastReject');
|
|
var kError = Symbol('error');
|
|
var kEnded = Symbol('ended');
|
|
var kLastPromise = Symbol('lastPromise');
|
|
var kHandlePromise = Symbol('handlePromise');
|
|
var kStream = Symbol('stream');
|
|
|
|
function createIterResult(value, done) {
|
|
return {
|
|
value: value,
|
|
done: done
|
|
};
|
|
}
|
|
|
|
function readAndResolve(iter) {
|
|
var resolve = iter[kLastResolve];
|
|
|
|
if (resolve !== null) {
|
|
var data = iter[kStream].read(); // we defer if data is null
|
|
// we can be expecting either 'end' or
|
|
// 'error'
|
|
|
|
if (data !== null) {
|
|
iter[kLastPromise] = null;
|
|
iter[kLastResolve] = null;
|
|
iter[kLastReject] = null;
|
|
resolve(createIterResult(data, false));
|
|
}
|
|
}
|
|
}
|
|
|
|
function onReadable(iter) {
|
|
// we wait for the next tick, because it might
|
|
// emit an error with process.nextTick
|
|
process.nextTick(readAndResolve, iter);
|
|
}
|
|
|
|
function wrapForNext(lastPromise, iter) {
|
|
return function (resolve, reject) {
|
|
lastPromise.then(function () {
|
|
if (iter[kEnded]) {
|
|
resolve(createIterResult(undefined, true));
|
|
return;
|
|
}
|
|
|
|
iter[kHandlePromise](resolve, reject);
|
|
}, reject);
|
|
};
|
|
}
|
|
|
|
var AsyncIteratorPrototype = Object.getPrototypeOf(function () {});
|
|
var ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf((_Object$setPrototypeO = {
|
|
get stream() {
|
|
return this[kStream];
|
|
},
|
|
|
|
next: function next() {
|
|
var _this = this;
|
|
|
|
// if we have detected an error in the meanwhile
|
|
// reject straight away
|
|
var error = this[kError];
|
|
|
|
if (error !== null) {
|
|
return Promise.reject(error);
|
|
}
|
|
|
|
if (this[kEnded]) {
|
|
return Promise.resolve(createIterResult(undefined, true));
|
|
}
|
|
|
|
if (this[kStream].destroyed) {
|
|
// We need to defer via nextTick because if .destroy(err) is
|
|
// called, the error will be emitted via nextTick, and
|
|
// we cannot guarantee that there is no error lingering around
|
|
// waiting to be emitted.
|
|
return new Promise(function (resolve, reject) {
|
|
process.nextTick(function () {
|
|
if (_this[kError]) {
|
|
reject(_this[kError]);
|
|
} else {
|
|
resolve(createIterResult(undefined, true));
|
|
}
|
|
});
|
|
});
|
|
} // if we have multiple next() calls
|
|
// we will wait for the previous Promise to finish
|
|
// this logic is optimized to support for await loops,
|
|
// where next() is only called once at a time
|
|
|
|
|
|
var lastPromise = this[kLastPromise];
|
|
var promise;
|
|
|
|
if (lastPromise) {
|
|
promise = new Promise(wrapForNext(lastPromise, this));
|
|
} else {
|
|
// fast path needed to support multiple this.push()
|
|
// without triggering the next() queue
|
|
var data = this[kStream].read();
|
|
|
|
if (data !== null) {
|
|
return Promise.resolve(createIterResult(data, false));
|
|
}
|
|
|
|
promise = new Promise(this[kHandlePromise]);
|
|
}
|
|
|
|
this[kLastPromise] = promise;
|
|
return promise;
|
|
}
|
|
}, _defineProperty(_Object$setPrototypeO, Symbol.asyncIterator, function () {
|
|
return this;
|
|
}), _defineProperty(_Object$setPrototypeO, "return", function _return() {
|
|
var _this2 = this;
|
|
|
|
// destroy(err, cb) is a private API
|
|
// we can guarantee we have that here, because we control the
|
|
// Readable class this is attached to
|
|
return new Promise(function (resolve, reject) {
|
|
_this2[kStream].destroy(null, function (err) {
|
|
if (err) {
|
|
reject(err);
|
|
return;
|
|
}
|
|
|
|
resolve(createIterResult(undefined, true));
|
|
});
|
|
});
|
|
}), _Object$setPrototypeO), AsyncIteratorPrototype);
|
|
|
|
var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator(stream) {
|
|
var _Object$create;
|
|
|
|
var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, {
|
|
value: stream,
|
|
writable: true
|
|
}), _defineProperty(_Object$create, kLastResolve, {
|
|
value: null,
|
|
writable: true
|
|
}), _defineProperty(_Object$create, kLastReject, {
|
|
value: null,
|
|
writable: true
|
|
}), _defineProperty(_Object$create, kError, {
|
|
value: null,
|
|
writable: true
|
|
}), _defineProperty(_Object$create, kEnded, {
|
|
value: stream._readableState.endEmitted,
|
|
writable: true
|
|
}), _defineProperty(_Object$create, kHandlePromise, {
|
|
value: function value(resolve, reject) {
|
|
var data = iterator[kStream].read();
|
|
|
|
if (data) {
|
|
iterator[kLastPromise] = null;
|
|
iterator[kLastResolve] = null;
|
|
iterator[kLastReject] = null;
|
|
resolve(createIterResult(data, false));
|
|
} else {
|
|
iterator[kLastResolve] = resolve;
|
|
iterator[kLastReject] = reject;
|
|
}
|
|
},
|
|
writable: true
|
|
}), _Object$create));
|
|
iterator[kLastPromise] = null;
|
|
finished(stream, function (err) {
|
|
if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') {
|
|
var reject = iterator[kLastReject]; // reject if we are waiting for data in the Promise
|
|
// returned by next() and store the error
|
|
|
|
if (reject !== null) {
|
|
iterator[kLastPromise] = null;
|
|
iterator[kLastResolve] = null;
|
|
iterator[kLastReject] = null;
|
|
reject(err);
|
|
}
|
|
|
|
iterator[kError] = err;
|
|
return;
|
|
}
|
|
|
|
var resolve = iterator[kLastResolve];
|
|
|
|
if (resolve !== null) {
|
|
iterator[kLastPromise] = null;
|
|
iterator[kLastResolve] = null;
|
|
iterator[kLastReject] = null;
|
|
resolve(createIterResult(undefined, true));
|
|
}
|
|
|
|
iterator[kEnded] = true;
|
|
});
|
|
stream.on('readable', onReadable.bind(null, iterator));
|
|
return iterator;
|
|
};
|
|
|
|
module.exports = createReadableStreamAsyncIterator;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/internal/streams/buffer_list.js":
|
|
/*!**************************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/internal/streams/buffer_list.js ***!
|
|
\**************************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
|
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
|
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
|
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
|
|
var _require = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js"),
|
|
Buffer = _require.Buffer;
|
|
|
|
var _require2 = __webpack_require__(/*! util */ "?ed1b"),
|
|
inspect = _require2.inspect;
|
|
|
|
var custom = inspect && inspect.custom || 'inspect';
|
|
|
|
function copyBuffer(src, target, offset) {
|
|
Buffer.prototype.copy.call(src, target, offset);
|
|
}
|
|
|
|
module.exports =
|
|
/*#__PURE__*/
|
|
function () {
|
|
function BufferList() {
|
|
_classCallCheck(this, BufferList);
|
|
|
|
this.head = null;
|
|
this.tail = null;
|
|
this.length = 0;
|
|
}
|
|
|
|
_createClass(BufferList, [{
|
|
key: "push",
|
|
value: function push(v) {
|
|
var entry = {
|
|
data: v,
|
|
next: null
|
|
};
|
|
if (this.length > 0) this.tail.next = entry;else this.head = entry;
|
|
this.tail = entry;
|
|
++this.length;
|
|
}
|
|
}, {
|
|
key: "unshift",
|
|
value: function unshift(v) {
|
|
var entry = {
|
|
data: v,
|
|
next: this.head
|
|
};
|
|
if (this.length === 0) this.tail = entry;
|
|
this.head = entry;
|
|
++this.length;
|
|
}
|
|
}, {
|
|
key: "shift",
|
|
value: function shift() {
|
|
if (this.length === 0) return;
|
|
var ret = this.head.data;
|
|
if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
|
|
--this.length;
|
|
return ret;
|
|
}
|
|
}, {
|
|
key: "clear",
|
|
value: function clear() {
|
|
this.head = this.tail = null;
|
|
this.length = 0;
|
|
}
|
|
}, {
|
|
key: "join",
|
|
value: function join(s) {
|
|
if (this.length === 0) return '';
|
|
var p = this.head;
|
|
var ret = '' + p.data;
|
|
|
|
while (p = p.next) {
|
|
ret += s + p.data;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
}, {
|
|
key: "concat",
|
|
value: function concat(n) {
|
|
if (this.length === 0) return Buffer.alloc(0);
|
|
var ret = Buffer.allocUnsafe(n >>> 0);
|
|
var p = this.head;
|
|
var i = 0;
|
|
|
|
while (p) {
|
|
copyBuffer(p.data, ret, i);
|
|
i += p.data.length;
|
|
p = p.next;
|
|
}
|
|
|
|
return ret;
|
|
} // Consumes a specified amount of bytes or characters from the buffered data.
|
|
|
|
}, {
|
|
key: "consume",
|
|
value: function consume(n, hasStrings) {
|
|
var ret;
|
|
|
|
if (n < this.head.data.length) {
|
|
// `slice` is the same for buffers and strings.
|
|
ret = this.head.data.slice(0, n);
|
|
this.head.data = this.head.data.slice(n);
|
|
} else if (n === this.head.data.length) {
|
|
// First chunk is a perfect match.
|
|
ret = this.shift();
|
|
} else {
|
|
// Result spans more than one buffer.
|
|
ret = hasStrings ? this._getString(n) : this._getBuffer(n);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
}, {
|
|
key: "first",
|
|
value: function first() {
|
|
return this.head.data;
|
|
} // Consumes a specified amount of characters from the buffered data.
|
|
|
|
}, {
|
|
key: "_getString",
|
|
value: function _getString(n) {
|
|
var p = this.head;
|
|
var c = 1;
|
|
var ret = p.data;
|
|
n -= ret.length;
|
|
|
|
while (p = p.next) {
|
|
var str = p.data;
|
|
var nb = n > str.length ? str.length : n;
|
|
if (nb === str.length) ret += str;else ret += str.slice(0, n);
|
|
n -= nb;
|
|
|
|
if (n === 0) {
|
|
if (nb === str.length) {
|
|
++c;
|
|
if (p.next) this.head = p.next;else this.head = this.tail = null;
|
|
} else {
|
|
this.head = p;
|
|
p.data = str.slice(nb);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
++c;
|
|
}
|
|
|
|
this.length -= c;
|
|
return ret;
|
|
} // Consumes a specified amount of bytes from the buffered data.
|
|
|
|
}, {
|
|
key: "_getBuffer",
|
|
value: function _getBuffer(n) {
|
|
var ret = Buffer.allocUnsafe(n);
|
|
var p = this.head;
|
|
var c = 1;
|
|
p.data.copy(ret);
|
|
n -= p.data.length;
|
|
|
|
while (p = p.next) {
|
|
var buf = p.data;
|
|
var nb = n > buf.length ? buf.length : n;
|
|
buf.copy(ret, ret.length - n, 0, nb);
|
|
n -= nb;
|
|
|
|
if (n === 0) {
|
|
if (nb === buf.length) {
|
|
++c;
|
|
if (p.next) this.head = p.next;else this.head = this.tail = null;
|
|
} else {
|
|
this.head = p;
|
|
p.data = buf.slice(nb);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
++c;
|
|
}
|
|
|
|
this.length -= c;
|
|
return ret;
|
|
} // Make sure the linked list only shows the minimal necessary information.
|
|
|
|
}, {
|
|
key: custom,
|
|
value: function value(_, options) {
|
|
return inspect(this, _objectSpread({}, options, {
|
|
// Only inspect one level.
|
|
depth: 0,
|
|
// It should not recurse.
|
|
customInspect: false
|
|
}));
|
|
}
|
|
}]);
|
|
|
|
return BufferList;
|
|
}();
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/internal/streams/destroy.js":
|
|
/*!**********************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/internal/streams/destroy.js ***!
|
|
\**********************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
// undocumented cb() API, needed for core, not for public API
|
|
|
|
function destroy(err, cb) {
|
|
var _this = this;
|
|
|
|
var readableDestroyed = this._readableState && this._readableState.destroyed;
|
|
var writableDestroyed = this._writableState && this._writableState.destroyed;
|
|
|
|
if (readableDestroyed || writableDestroyed) {
|
|
if (cb) {
|
|
cb(err);
|
|
} else if (err) {
|
|
if (!this._writableState) {
|
|
process.nextTick(emitErrorNT, this, err);
|
|
} else if (!this._writableState.errorEmitted) {
|
|
this._writableState.errorEmitted = true;
|
|
process.nextTick(emitErrorNT, this, err);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
} // we set destroyed to true before firing error callbacks in order
|
|
// to make it re-entrance safe in case destroy() is called within callbacks
|
|
|
|
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = true;
|
|
} // if this is a duplex stream mark the writable part as destroyed as well
|
|
|
|
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = true;
|
|
}
|
|
|
|
this._destroy(err || null, function (err) {
|
|
if (!cb && err) {
|
|
if (!_this._writableState) {
|
|
process.nextTick(emitErrorAndCloseNT, _this, err);
|
|
} else if (!_this._writableState.errorEmitted) {
|
|
_this._writableState.errorEmitted = true;
|
|
process.nextTick(emitErrorAndCloseNT, _this, err);
|
|
} else {
|
|
process.nextTick(emitCloseNT, _this);
|
|
}
|
|
} else if (cb) {
|
|
process.nextTick(emitCloseNT, _this);
|
|
cb(err);
|
|
} else {
|
|
process.nextTick(emitCloseNT, _this);
|
|
}
|
|
});
|
|
|
|
return this;
|
|
}
|
|
|
|
function emitErrorAndCloseNT(self, err) {
|
|
emitErrorNT(self, err);
|
|
emitCloseNT(self);
|
|
}
|
|
|
|
function emitCloseNT(self) {
|
|
if (self._writableState && !self._writableState.emitClose) return;
|
|
if (self._readableState && !self._readableState.emitClose) return;
|
|
self.emit('close');
|
|
}
|
|
|
|
function undestroy() {
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = false;
|
|
this._readableState.reading = false;
|
|
this._readableState.ended = false;
|
|
this._readableState.endEmitted = false;
|
|
}
|
|
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = false;
|
|
this._writableState.ended = false;
|
|
this._writableState.ending = false;
|
|
this._writableState.finalCalled = false;
|
|
this._writableState.prefinished = false;
|
|
this._writableState.finished = false;
|
|
this._writableState.errorEmitted = false;
|
|
}
|
|
}
|
|
|
|
function emitErrorNT(self, err) {
|
|
self.emit('error', err);
|
|
}
|
|
|
|
function errorOrDestroy(stream, err) {
|
|
// We have tests that rely on errors being emitted
|
|
// in the same tick, so changing this is semver major.
|
|
// For now when you opt-in to autoDestroy we allow
|
|
// the error to be emitted nextTick. In a future
|
|
// semver major update we should change the default to this.
|
|
var rState = stream._readableState;
|
|
var wState = stream._writableState;
|
|
if (rState && rState.autoDestroy || wState && wState.autoDestroy) stream.destroy(err);else stream.emit('error', err);
|
|
}
|
|
|
|
module.exports = {
|
|
destroy: destroy,
|
|
undestroy: undestroy,
|
|
errorOrDestroy: errorOrDestroy
|
|
};
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/internal/streams/end-of-stream.js":
|
|
/*!****************************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/internal/streams/end-of-stream.js ***!
|
|
\****************************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// Ported from https://github.com/mafintosh/end-of-stream with
|
|
// permission from the author, Mathias Buus (@mafintosh).
|
|
|
|
|
|
var ERR_STREAM_PREMATURE_CLOSE = __webpack_require__(/*! ../../../errors */ "./node_modules/readable-stream/errors-browser.js").codes.ERR_STREAM_PREMATURE_CLOSE;
|
|
|
|
function once(callback) {
|
|
var called = false;
|
|
return function () {
|
|
if (called) return;
|
|
called = true;
|
|
|
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
|
|
callback.apply(this, args);
|
|
};
|
|
}
|
|
|
|
function noop() {}
|
|
|
|
function isRequest(stream) {
|
|
return stream.setHeader && typeof stream.abort === 'function';
|
|
}
|
|
|
|
function eos(stream, opts, callback) {
|
|
if (typeof opts === 'function') return eos(stream, null, opts);
|
|
if (!opts) opts = {};
|
|
callback = once(callback || noop);
|
|
var readable = opts.readable || opts.readable !== false && stream.readable;
|
|
var writable = opts.writable || opts.writable !== false && stream.writable;
|
|
|
|
var onlegacyfinish = function onlegacyfinish() {
|
|
if (!stream.writable) onfinish();
|
|
};
|
|
|
|
var writableEnded = stream._writableState && stream._writableState.finished;
|
|
|
|
var onfinish = function onfinish() {
|
|
writable = false;
|
|
writableEnded = true;
|
|
if (!readable) callback.call(stream);
|
|
};
|
|
|
|
var readableEnded = stream._readableState && stream._readableState.endEmitted;
|
|
|
|
var onend = function onend() {
|
|
readable = false;
|
|
readableEnded = true;
|
|
if (!writable) callback.call(stream);
|
|
};
|
|
|
|
var onerror = function onerror(err) {
|
|
callback.call(stream, err);
|
|
};
|
|
|
|
var onclose = function onclose() {
|
|
var err;
|
|
|
|
if (readable && !readableEnded) {
|
|
if (!stream._readableState || !stream._readableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE();
|
|
return callback.call(stream, err);
|
|
}
|
|
|
|
if (writable && !writableEnded) {
|
|
if (!stream._writableState || !stream._writableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE();
|
|
return callback.call(stream, err);
|
|
}
|
|
};
|
|
|
|
var onrequest = function onrequest() {
|
|
stream.req.on('finish', onfinish);
|
|
};
|
|
|
|
if (isRequest(stream)) {
|
|
stream.on('complete', onfinish);
|
|
stream.on('abort', onclose);
|
|
if (stream.req) onrequest();else stream.on('request', onrequest);
|
|
} else if (writable && !stream._writableState) {
|
|
// legacy streams
|
|
stream.on('end', onlegacyfinish);
|
|
stream.on('close', onlegacyfinish);
|
|
}
|
|
|
|
stream.on('end', onend);
|
|
stream.on('finish', onfinish);
|
|
if (opts.error !== false) stream.on('error', onerror);
|
|
stream.on('close', onclose);
|
|
return function () {
|
|
stream.removeListener('complete', onfinish);
|
|
stream.removeListener('abort', onclose);
|
|
stream.removeListener('request', onrequest);
|
|
if (stream.req) stream.req.removeListener('finish', onfinish);
|
|
stream.removeListener('end', onlegacyfinish);
|
|
stream.removeListener('close', onlegacyfinish);
|
|
stream.removeListener('finish', onfinish);
|
|
stream.removeListener('end', onend);
|
|
stream.removeListener('error', onerror);
|
|
stream.removeListener('close', onclose);
|
|
};
|
|
}
|
|
|
|
module.exports = eos;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/internal/streams/from-browser.js":
|
|
/*!***************************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/internal/streams/from-browser.js ***!
|
|
\***************************************************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = function () {
|
|
throw new Error('Readable.from is not available in the browser')
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/internal/streams/pipeline.js":
|
|
/*!***********************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/internal/streams/pipeline.js ***!
|
|
\***********************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// Ported from https://github.com/mafintosh/pump with
|
|
// permission from the author, Mathias Buus (@mafintosh).
|
|
|
|
|
|
var eos;
|
|
|
|
function once(callback) {
|
|
var called = false;
|
|
return function () {
|
|
if (called) return;
|
|
called = true;
|
|
callback.apply(void 0, arguments);
|
|
};
|
|
}
|
|
|
|
var _require$codes = __webpack_require__(/*! ../../../errors */ "./node_modules/readable-stream/errors-browser.js").codes,
|
|
ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS,
|
|
ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED;
|
|
|
|
function noop(err) {
|
|
// Rethrow the error if it exists to avoid swallowing it
|
|
if (err) throw err;
|
|
}
|
|
|
|
function isRequest(stream) {
|
|
return stream.setHeader && typeof stream.abort === 'function';
|
|
}
|
|
|
|
function destroyer(stream, reading, writing, callback) {
|
|
callback = once(callback);
|
|
var closed = false;
|
|
stream.on('close', function () {
|
|
closed = true;
|
|
});
|
|
if (eos === undefined) eos = __webpack_require__(/*! ./end-of-stream */ "./node_modules/readable-stream/lib/internal/streams/end-of-stream.js");
|
|
eos(stream, {
|
|
readable: reading,
|
|
writable: writing
|
|
}, function (err) {
|
|
if (err) return callback(err);
|
|
closed = true;
|
|
callback();
|
|
});
|
|
var destroyed = false;
|
|
return function (err) {
|
|
if (closed) return;
|
|
if (destroyed) return;
|
|
destroyed = true; // request.destroy just do .end - .abort is what we want
|
|
|
|
if (isRequest(stream)) return stream.abort();
|
|
if (typeof stream.destroy === 'function') return stream.destroy();
|
|
callback(err || new ERR_STREAM_DESTROYED('pipe'));
|
|
};
|
|
}
|
|
|
|
function call(fn) {
|
|
fn();
|
|
}
|
|
|
|
function pipe(from, to) {
|
|
return from.pipe(to);
|
|
}
|
|
|
|
function popCallback(streams) {
|
|
if (!streams.length) return noop;
|
|
if (typeof streams[streams.length - 1] !== 'function') return noop;
|
|
return streams.pop();
|
|
}
|
|
|
|
function pipeline() {
|
|
for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
streams[_key] = arguments[_key];
|
|
}
|
|
|
|
var callback = popCallback(streams);
|
|
if (Array.isArray(streams[0])) streams = streams[0];
|
|
|
|
if (streams.length < 2) {
|
|
throw new ERR_MISSING_ARGS('streams');
|
|
}
|
|
|
|
var error;
|
|
var destroys = streams.map(function (stream, i) {
|
|
var reading = i < streams.length - 1;
|
|
var writing = i > 0;
|
|
return destroyer(stream, reading, writing, function (err) {
|
|
if (!error) error = err;
|
|
if (err) destroys.forEach(call);
|
|
if (reading) return;
|
|
destroys.forEach(call);
|
|
callback(error);
|
|
});
|
|
});
|
|
return streams.reduce(pipe);
|
|
}
|
|
|
|
module.exports = pipeline;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/internal/streams/state.js":
|
|
/*!********************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/internal/streams/state.js ***!
|
|
\********************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var ERR_INVALID_OPT_VALUE = __webpack_require__(/*! ../../../errors */ "./node_modules/readable-stream/errors-browser.js").codes.ERR_INVALID_OPT_VALUE;
|
|
|
|
function highWaterMarkFrom(options, isDuplex, duplexKey) {
|
|
return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null;
|
|
}
|
|
|
|
function getHighWaterMark(state, options, duplexKey, isDuplex) {
|
|
var hwm = highWaterMarkFrom(options, isDuplex, duplexKey);
|
|
|
|
if (hwm != null) {
|
|
if (!(isFinite(hwm) && Math.floor(hwm) === hwm) || hwm < 0) {
|
|
var name = isDuplex ? duplexKey : 'highWaterMark';
|
|
throw new ERR_INVALID_OPT_VALUE(name, hwm);
|
|
}
|
|
|
|
return Math.floor(hwm);
|
|
} // Default value
|
|
|
|
|
|
return state.objectMode ? 16 : 16 * 1024;
|
|
}
|
|
|
|
module.exports = {
|
|
getHighWaterMark: getHighWaterMark
|
|
};
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/lib/internal/streams/stream-browser.js":
|
|
/*!*****************************************************************************!*\
|
|
!*** ./node_modules/readable-stream/lib/internal/streams/stream-browser.js ***!
|
|
\*****************************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
module.exports = __webpack_require__(/*! events */ "./node_modules/events/events.js").EventEmitter;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/readable-stream/readable-browser.js":
|
|
/*!**********************************************************!*\
|
|
!*** ./node_modules/readable-stream/readable-browser.js ***!
|
|
\**********************************************************/
|
|
/***/ ((module, exports, __webpack_require__) => {
|
|
|
|
exports = module.exports = __webpack_require__(/*! ./lib/_stream_readable.js */ "./node_modules/readable-stream/lib/_stream_readable.js");
|
|
exports.Stream = exports;
|
|
exports.Readable = exports;
|
|
exports.Writable = __webpack_require__(/*! ./lib/_stream_writable.js */ "./node_modules/readable-stream/lib/_stream_writable.js");
|
|
exports.Duplex = __webpack_require__(/*! ./lib/_stream_duplex.js */ "./node_modules/readable-stream/lib/_stream_duplex.js");
|
|
exports.Transform = __webpack_require__(/*! ./lib/_stream_transform.js */ "./node_modules/readable-stream/lib/_stream_transform.js");
|
|
exports.PassThrough = __webpack_require__(/*! ./lib/_stream_passthrough.js */ "./node_modules/readable-stream/lib/_stream_passthrough.js");
|
|
exports.finished = __webpack_require__(/*! ./lib/internal/streams/end-of-stream.js */ "./node_modules/readable-stream/lib/internal/streams/end-of-stream.js");
|
|
exports.pipeline = __webpack_require__(/*! ./lib/internal/streams/pipeline.js */ "./node_modules/readable-stream/lib/internal/streams/pipeline.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/render-media/index.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/render-media/index.js ***!
|
|
\********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
/*! render-media. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
exports.render = render
|
|
exports.append = append
|
|
exports.mime = __webpack_require__(/*! ./lib/mime.json */ "./node_modules/render-media/lib/mime.json")
|
|
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('render-media')
|
|
const isAscii = __webpack_require__(/*! is-ascii */ "./node_modules/is-ascii/index.js")
|
|
const MediaElementWrapper = __webpack_require__(/*! mediasource */ "./node_modules/mediasource/index.js")
|
|
const path = __webpack_require__(/*! path */ "./node_modules/path-browserify/index.js")
|
|
const streamToBlobURL = __webpack_require__(/*! stream-to-blob-url */ "./node_modules/stream-to-blob-url/index.js")
|
|
const VideoStream = __webpack_require__(/*! videostream */ "./node_modules/videostream/videostream.js")
|
|
|
|
// Note: Everything listed in VIDEOSTREAM_EXTS should also appear in either
|
|
// MEDIASOURCE_VIDEO_EXTS or MEDIASOURCE_AUDIO_EXTS.
|
|
const VIDEOSTREAM_EXTS = [
|
|
'.m4a',
|
|
'.m4b',
|
|
'.m4p',
|
|
'.m4v',
|
|
'.mp4'
|
|
]
|
|
|
|
const MEDIASOURCE_VIDEO_EXTS = [
|
|
'.m4v',
|
|
'.mkv',
|
|
'.mp4',
|
|
'.webm'
|
|
]
|
|
|
|
const MEDIASOURCE_AUDIO_EXTS = [
|
|
'.m4a',
|
|
'.m4b',
|
|
'.m4p',
|
|
'.mp3'
|
|
]
|
|
|
|
const MEDIASOURCE_EXTS = [].concat(
|
|
MEDIASOURCE_VIDEO_EXTS,
|
|
MEDIASOURCE_AUDIO_EXTS
|
|
)
|
|
|
|
const VIDEO_EXTS = [
|
|
'.mov',
|
|
'.ogv'
|
|
]
|
|
|
|
const AUDIO_EXTS = [
|
|
'.aac',
|
|
'.oga',
|
|
'.ogg',
|
|
'.wav',
|
|
'.flac'
|
|
]
|
|
|
|
const IMAGE_EXTS = [
|
|
'.bmp',
|
|
'.gif',
|
|
'.jpeg',
|
|
'.jpg',
|
|
'.png',
|
|
'.svg'
|
|
]
|
|
|
|
const IFRAME_EXTS = [
|
|
'.css',
|
|
'.html',
|
|
'.js',
|
|
'.md',
|
|
'.pdf',
|
|
'.srt',
|
|
'.txt'
|
|
]
|
|
|
|
// Maximum file length for which the Blob URL strategy will be attempted
|
|
// See: https://github.com/feross/render-media/issues/18
|
|
const MAX_BLOB_LENGTH = 200 * 1000 * 1000 // 200 MB
|
|
|
|
const MediaSource = typeof window !== 'undefined' && window.MediaSource
|
|
|
|
function render (file, elem, opts, cb) {
|
|
if (typeof opts === 'function') {
|
|
cb = opts
|
|
opts = {}
|
|
}
|
|
if (!opts) opts = {}
|
|
if (!cb) cb = () => {}
|
|
|
|
validateFile(file)
|
|
parseOpts(opts)
|
|
|
|
if (typeof elem === 'string') elem = document.querySelector(elem)
|
|
|
|
renderMedia(file, tagName => {
|
|
if (elem.nodeName !== tagName.toUpperCase()) {
|
|
const extname = path.extname(file.name).toLowerCase()
|
|
|
|
throw new Error(
|
|
`Cannot render "${extname}" inside a "${elem.nodeName.toLowerCase()}" element, expected "${tagName}"`
|
|
)
|
|
}
|
|
|
|
if (tagName === 'video' || tagName === 'audio') setMediaOpts(elem, opts)
|
|
|
|
return elem
|
|
}, opts, cb)
|
|
}
|
|
|
|
function append (file, rootElem, opts, cb) {
|
|
if (typeof opts === 'function') {
|
|
cb = opts
|
|
opts = {}
|
|
}
|
|
if (!opts) opts = {}
|
|
if (!cb) cb = () => {}
|
|
|
|
validateFile(file)
|
|
parseOpts(opts)
|
|
|
|
if (typeof rootElem === 'string') rootElem = document.querySelector(rootElem)
|
|
|
|
if (rootElem && (rootElem.nodeName === 'VIDEO' || rootElem.nodeName === 'AUDIO')) {
|
|
throw new Error(
|
|
'Invalid video/audio node argument. Argument must be root element that ' +
|
|
'video/audio tag will be appended to.'
|
|
)
|
|
}
|
|
|
|
renderMedia(file, getElem, opts, done)
|
|
|
|
function getElem (tagName) {
|
|
if (tagName === 'video' || tagName === 'audio') return createMedia(tagName)
|
|
else return createElem(tagName)
|
|
}
|
|
|
|
function createMedia (tagName) {
|
|
const elem = createElem(tagName)
|
|
setMediaOpts(elem, opts)
|
|
rootElem.appendChild(elem)
|
|
return elem
|
|
}
|
|
|
|
function createElem (tagName) {
|
|
const elem = document.createElement(tagName)
|
|
rootElem.appendChild(elem)
|
|
return elem
|
|
}
|
|
|
|
function done (err, elem) {
|
|
if (err && elem) elem.remove()
|
|
cb(err, elem)
|
|
}
|
|
}
|
|
|
|
function renderMedia (file, getElem, opts, cb) {
|
|
const extname = path.extname(file.name).toLowerCase()
|
|
let currentTime = 0
|
|
let elem
|
|
|
|
if (MEDIASOURCE_EXTS.includes(extname)) {
|
|
renderMediaSource()
|
|
} else if (VIDEO_EXTS.includes(extname)) {
|
|
renderMediaElement('video')
|
|
} else if (AUDIO_EXTS.includes(extname)) {
|
|
renderMediaElement('audio')
|
|
} else if (IMAGE_EXTS.includes(extname)) {
|
|
renderImage()
|
|
} else if (IFRAME_EXTS.includes(extname)) {
|
|
renderIframe()
|
|
} else {
|
|
tryRenderIframe()
|
|
}
|
|
|
|
function renderMediaSource () {
|
|
const tagName = MEDIASOURCE_VIDEO_EXTS.includes(extname) ? 'video' : 'audio'
|
|
|
|
if (MediaSource) {
|
|
if (VIDEOSTREAM_EXTS.includes(extname)) {
|
|
useVideostream()
|
|
} else {
|
|
useMediaSource()
|
|
}
|
|
} else {
|
|
useBlobURL()
|
|
}
|
|
|
|
function useVideostream () {
|
|
debug(`Use \`videostream\` package for ${file.name}`)
|
|
prepareElem()
|
|
elem.addEventListener('error', fallbackToMediaSource)
|
|
elem.addEventListener('loadstart', onLoadStart)
|
|
elem.addEventListener('loadedmetadata', onLoadedMetadata)
|
|
new VideoStream(file, elem) /* eslint-disable-line no-new */
|
|
}
|
|
|
|
function useMediaSource () {
|
|
debug(`Use MediaSource API for ${file.name}`)
|
|
prepareElem()
|
|
elem.addEventListener('error', fallbackToBlobURL)
|
|
elem.addEventListener('loadstart', onLoadStart)
|
|
elem.addEventListener('loadedmetadata', onLoadedMetadata)
|
|
|
|
const wrapper = new MediaElementWrapper(elem)
|
|
const writable = wrapper.createWriteStream(getCodec(file.name))
|
|
file.createReadStream().pipe(writable)
|
|
|
|
if (currentTime) elem.currentTime = currentTime
|
|
}
|
|
|
|
function useBlobURL () {
|
|
debug(`Use Blob URL for ${file.name}`)
|
|
prepareElem()
|
|
elem.addEventListener('error', fatalError)
|
|
elem.addEventListener('loadstart', onLoadStart)
|
|
elem.addEventListener('loadedmetadata', onLoadedMetadata)
|
|
getBlobURL(file, (err, url) => {
|
|
if (err) return fatalError(err)
|
|
elem.src = url
|
|
if (currentTime) elem.currentTime = currentTime
|
|
})
|
|
}
|
|
|
|
function fallbackToMediaSource (err) {
|
|
debug('videostream error: fallback to MediaSource API: %o', err.message || err)
|
|
elem.removeEventListener('error', fallbackToMediaSource)
|
|
elem.removeEventListener('loadedmetadata', onLoadedMetadata)
|
|
|
|
useMediaSource()
|
|
}
|
|
|
|
function fallbackToBlobURL (err) {
|
|
debug('MediaSource API error: fallback to Blob URL: %o', err.message || err)
|
|
if (!checkBlobLength()) return
|
|
|
|
elem.removeEventListener('error', fallbackToBlobURL)
|
|
elem.removeEventListener('loadedmetadata', onLoadedMetadata)
|
|
|
|
useBlobURL()
|
|
}
|
|
|
|
function prepareElem () {
|
|
if (!elem) {
|
|
elem = getElem(tagName)
|
|
|
|
elem.addEventListener('progress', () => {
|
|
currentTime = elem.currentTime
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkBlobLength () {
|
|
if (typeof file.length === 'number' && file.length > opts.maxBlobLength) {
|
|
debug(
|
|
'File length too large for Blob URL approach: %d (max: %d)',
|
|
file.length, opts.maxBlobLength
|
|
)
|
|
fatalError(new Error(
|
|
`File length too large for Blob URL approach: ${file.length} (max: ${opts.maxBlobLength})`
|
|
))
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
function renderMediaElement (type) {
|
|
if (!checkBlobLength()) return
|
|
|
|
elem = getElem(type)
|
|
getBlobURL(file, (err, url) => {
|
|
if (err) return fatalError(err)
|
|
elem.addEventListener('error', fatalError)
|
|
elem.addEventListener('loadstart', onLoadStart)
|
|
elem.addEventListener('loadedmetadata', onLoadedMetadata)
|
|
elem.src = url
|
|
})
|
|
}
|
|
|
|
function onLoadStart () {
|
|
elem.removeEventListener('loadstart', onLoadStart)
|
|
if (opts.autoplay) {
|
|
const playPromise = elem.play()
|
|
if (typeof playPromise !== 'undefined') playPromise.catch(fatalError)
|
|
}
|
|
}
|
|
|
|
function onLoadedMetadata () {
|
|
elem.removeEventListener('loadedmetadata', onLoadedMetadata)
|
|
cb(null, elem)
|
|
}
|
|
|
|
function renderImage () {
|
|
elem = getElem('img')
|
|
getBlobURL(file, (err, url) => {
|
|
if (err) return fatalError(err)
|
|
elem.src = url
|
|
elem.alt = file.name
|
|
cb(null, elem)
|
|
})
|
|
}
|
|
|
|
function renderIframe () {
|
|
getBlobURL(file, (err, url) => {
|
|
if (err) return fatalError(err)
|
|
|
|
if (extname !== '.pdf') {
|
|
// Render iframe
|
|
elem = getElem('iframe')
|
|
elem.sandbox = 'allow-forms allow-scripts'
|
|
elem.src = url
|
|
} else {
|
|
// Render .pdf
|
|
elem = getElem('object')
|
|
// Firefox-only: `typemustmatch` keeps the embedded file from running unless
|
|
// its content type matches the specified `type` attribute
|
|
elem.setAttribute('typemustmatch', true)
|
|
elem.setAttribute('type', 'application/pdf')
|
|
elem.setAttribute('data', url)
|
|
}
|
|
cb(null, elem)
|
|
})
|
|
}
|
|
|
|
function tryRenderIframe () {
|
|
debug('Unknown file extension "%s" - will attempt to render into iframe', extname)
|
|
|
|
let str = ''
|
|
file.createReadStream({ start: 0, end: 1000 })
|
|
.setEncoding('utf8')
|
|
.on('data', chunk => {
|
|
str += chunk
|
|
})
|
|
.on('end', done)
|
|
.on('error', cb)
|
|
|
|
function done () {
|
|
if (isAscii(str)) {
|
|
debug('File extension "%s" appears ascii, so will render.', extname)
|
|
renderIframe()
|
|
} else {
|
|
debug('File extension "%s" appears non-ascii, will not render.', extname)
|
|
cb(new Error(`Unsupported file type "${extname}": Cannot append to DOM`))
|
|
}
|
|
}
|
|
}
|
|
|
|
function fatalError (err) {
|
|
err.message = `Error rendering file "${file.name}": ${err.message}`
|
|
debug(err.message)
|
|
cb(err)
|
|
}
|
|
}
|
|
|
|
function getBlobURL (file, cb) {
|
|
const extname = path.extname(file.name).toLowerCase()
|
|
streamToBlobURL(file.createReadStream(), exports.mime[extname])
|
|
.then(
|
|
blobUrl => cb(null, blobUrl),
|
|
err => cb(err)
|
|
)
|
|
}
|
|
|
|
function validateFile (file) {
|
|
if (file == null) {
|
|
throw new Error('file cannot be null or undefined')
|
|
}
|
|
if (typeof file.name !== 'string') {
|
|
throw new Error('missing or invalid file.name property')
|
|
}
|
|
if (typeof file.createReadStream !== 'function') {
|
|
throw new Error('missing or invalid file.createReadStream property')
|
|
}
|
|
}
|
|
|
|
function getCodec (name) {
|
|
const extname = path.extname(name).toLowerCase()
|
|
return {
|
|
'.m4a': 'audio/mp4; codecs="mp4a.40.5"',
|
|
'.m4b': 'audio/mp4; codecs="mp4a.40.5"',
|
|
'.m4p': 'audio/mp4; codecs="mp4a.40.5"',
|
|
'.m4v': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
|
|
'.mkv': 'video/webm; codecs="avc1.640029, mp4a.40.5"',
|
|
'.mp3': 'audio/mpeg',
|
|
'.mp4': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
|
|
'.webm': 'video/webm; codecs="vorbis, vp8"'
|
|
}[extname]
|
|
}
|
|
|
|
function parseOpts (opts) {
|
|
if (opts.autoplay == null) opts.autoplay = false
|
|
if (opts.muted == null) opts.muted = false
|
|
if (opts.controls == null) opts.controls = true
|
|
if (opts.maxBlobLength == null) opts.maxBlobLength = MAX_BLOB_LENGTH
|
|
}
|
|
|
|
function setMediaOpts (elem, opts) {
|
|
elem.autoplay = !!opts.autoplay
|
|
elem.muted = !!opts.muted
|
|
elem.controls = !!opts.controls
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/render-media/lib/mime.json":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/render-media/lib/mime.json ***!
|
|
\*************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = JSON.parse('{".3gp":"video/3gpp",".aac":"audio/aac",".aif":"audio/x-aiff",".aiff":"audio/x-aiff",".atom":"application/atom+xml",".avi":"video/x-msvideo",".bmp":"image/bmp",".bz2":"application/x-bzip2",".conf":"text/plain",".css":"text/css",".csv":"text/plain",".diff":"text/x-diff",".doc":"application/msword",".flv":"video/x-flv",".gif":"image/gif",".gz":"application/x-gzip",".htm":"text/html",".html":"text/html",".ico":"image/vnd.microsoft.icon",".ics":"text/calendar",".iso":"application/octet-stream",".jar":"application/java-archive",".jpeg":"image/jpeg",".jpg":"image/jpeg",".js":"application/javascript",".json":"application/json",".less":"text/css",".log":"text/plain",".m3u":"audio/x-mpegurl",".m4a":"audio/x-m4a",".m4b":"audio/mp4",".m4p":"audio/mp4",".m4v":"video/x-m4v",".manifest":"text/cache-manifest",".markdown":"text/x-markdown",".mathml":"application/mathml+xml",".md":"text/x-markdown",".mid":"audio/midi",".midi":"audio/midi",".mov":"video/quicktime",".mp3":"audio/mpeg",".mp4":"video/mp4",".mp4v":"video/mp4",".mpeg":"video/mpeg",".mpg":"video/mpeg",".odp":"application/vnd.oasis.opendocument.presentation",".ods":"application/vnd.oasis.opendocument.spreadsheet",".odt":"application/vnd.oasis.opendocument.text",".oga":"audio/ogg",".ogg":"application/ogg",".pdf":"application/pdf",".png":"image/png",".pps":"application/vnd.ms-powerpoint",".ppt":"application/vnd.ms-powerpoint",".ps":"application/postscript",".psd":"image/vnd.adobe.photoshop",".qt":"video/quicktime",".rar":"application/x-rar-compressed",".rdf":"application/rdf+xml",".rss":"application/rss+xml",".rtf":"application/rtf",".svg":"image/svg+xml",".svgz":"image/svg+xml",".swf":"application/x-shockwave-flash",".tar":"application/x-tar",".tbz":"application/x-bzip-compressed-tar",".text":"text/plain",".tif":"image/tiff",".tiff":"image/tiff",".torrent":"application/x-bittorrent",".ttf":"application/x-font-ttf",".txt":"text/plain",".wav":"audio/wav",".webm":"video/webm",".wma":"audio/x-ms-wma",".wmv":"video/x-ms-wmv",".xls":"application/vnd.ms-excel",".xml":"application/xml",".yaml":"text/yaml",".yml":"text/yaml",".zip":"application/zip"}');
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ripemd160/index.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/ripemd160/index.js ***!
|
|
\*****************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
var Buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js").Buffer
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var HashBase = __webpack_require__(/*! hash-base */ "./node_modules/hash-base/index.js")
|
|
|
|
var ARRAY16 = new Array(16)
|
|
|
|
var zl = [
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
|
|
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
|
|
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
|
|
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
|
|
]
|
|
|
|
var zr = [
|
|
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
|
|
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
|
|
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
|
|
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
|
|
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
|
|
]
|
|
|
|
var sl = [
|
|
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
|
|
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
|
|
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
|
|
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
|
|
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
|
|
]
|
|
|
|
var sr = [
|
|
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
|
|
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
|
|
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
|
|
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
|
|
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
|
|
]
|
|
|
|
var hl = [0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e]
|
|
var hr = [0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000]
|
|
|
|
function RIPEMD160 () {
|
|
HashBase.call(this, 64)
|
|
|
|
// state
|
|
this._a = 0x67452301
|
|
this._b = 0xefcdab89
|
|
this._c = 0x98badcfe
|
|
this._d = 0x10325476
|
|
this._e = 0xc3d2e1f0
|
|
}
|
|
|
|
inherits(RIPEMD160, HashBase)
|
|
|
|
RIPEMD160.prototype._update = function () {
|
|
var words = ARRAY16
|
|
for (var j = 0; j < 16; ++j) words[j] = this._block.readInt32LE(j * 4)
|
|
|
|
var al = this._a | 0
|
|
var bl = this._b | 0
|
|
var cl = this._c | 0
|
|
var dl = this._d | 0
|
|
var el = this._e | 0
|
|
|
|
var ar = this._a | 0
|
|
var br = this._b | 0
|
|
var cr = this._c | 0
|
|
var dr = this._d | 0
|
|
var er = this._e | 0
|
|
|
|
// computation
|
|
for (var i = 0; i < 80; i += 1) {
|
|
var tl
|
|
var tr
|
|
if (i < 16) {
|
|
tl = fn1(al, bl, cl, dl, el, words[zl[i]], hl[0], sl[i])
|
|
tr = fn5(ar, br, cr, dr, er, words[zr[i]], hr[0], sr[i])
|
|
} else if (i < 32) {
|
|
tl = fn2(al, bl, cl, dl, el, words[zl[i]], hl[1], sl[i])
|
|
tr = fn4(ar, br, cr, dr, er, words[zr[i]], hr[1], sr[i])
|
|
} else if (i < 48) {
|
|
tl = fn3(al, bl, cl, dl, el, words[zl[i]], hl[2], sl[i])
|
|
tr = fn3(ar, br, cr, dr, er, words[zr[i]], hr[2], sr[i])
|
|
} else if (i < 64) {
|
|
tl = fn4(al, bl, cl, dl, el, words[zl[i]], hl[3], sl[i])
|
|
tr = fn2(ar, br, cr, dr, er, words[zr[i]], hr[3], sr[i])
|
|
} else { // if (i<80) {
|
|
tl = fn5(al, bl, cl, dl, el, words[zl[i]], hl[4], sl[i])
|
|
tr = fn1(ar, br, cr, dr, er, words[zr[i]], hr[4], sr[i])
|
|
}
|
|
|
|
al = el
|
|
el = dl
|
|
dl = rotl(cl, 10)
|
|
cl = bl
|
|
bl = tl
|
|
|
|
ar = er
|
|
er = dr
|
|
dr = rotl(cr, 10)
|
|
cr = br
|
|
br = tr
|
|
}
|
|
|
|
// update state
|
|
var t = (this._b + cl + dr) | 0
|
|
this._b = (this._c + dl + er) | 0
|
|
this._c = (this._d + el + ar) | 0
|
|
this._d = (this._e + al + br) | 0
|
|
this._e = (this._a + bl + cr) | 0
|
|
this._a = t
|
|
}
|
|
|
|
RIPEMD160.prototype._digest = function () {
|
|
// create padding and handle blocks
|
|
this._block[this._blockOffset++] = 0x80
|
|
if (this._blockOffset > 56) {
|
|
this._block.fill(0, this._blockOffset, 64)
|
|
this._update()
|
|
this._blockOffset = 0
|
|
}
|
|
|
|
this._block.fill(0, this._blockOffset, 56)
|
|
this._block.writeUInt32LE(this._length[0], 56)
|
|
this._block.writeUInt32LE(this._length[1], 60)
|
|
this._update()
|
|
|
|
// produce result
|
|
var buffer = Buffer.alloc ? Buffer.alloc(20) : new Buffer(20)
|
|
buffer.writeInt32LE(this._a, 0)
|
|
buffer.writeInt32LE(this._b, 4)
|
|
buffer.writeInt32LE(this._c, 8)
|
|
buffer.writeInt32LE(this._d, 12)
|
|
buffer.writeInt32LE(this._e, 16)
|
|
return buffer
|
|
}
|
|
|
|
function rotl (x, n) {
|
|
return (x << n) | (x >>> (32 - n))
|
|
}
|
|
|
|
function fn1 (a, b, c, d, e, m, k, s) {
|
|
return (rotl((a + (b ^ c ^ d) + m + k) | 0, s) + e) | 0
|
|
}
|
|
|
|
function fn2 (a, b, c, d, e, m, k, s) {
|
|
return (rotl((a + ((b & c) | ((~b) & d)) + m + k) | 0, s) + e) | 0
|
|
}
|
|
|
|
function fn3 (a, b, c, d, e, m, k, s) {
|
|
return (rotl((a + ((b | (~c)) ^ d) + m + k) | 0, s) + e) | 0
|
|
}
|
|
|
|
function fn4 (a, b, c, d, e, m, k, s) {
|
|
return (rotl((a + ((b & d) | (c & (~d))) + m + k) | 0, s) + e) | 0
|
|
}
|
|
|
|
function fn5 (a, b, c, d, e, m, k, s) {
|
|
return (rotl((a + (b ^ (c | (~d))) + m + k) | 0, s) + e) | 0
|
|
}
|
|
|
|
module.exports = RIPEMD160
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/run-parallel-limit/index.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/run-parallel-limit/index.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*! run-parallel-limit. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
module.exports = runParallelLimit
|
|
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
|
|
function runParallelLimit (tasks, limit, cb) {
|
|
if (typeof limit !== 'number') throw new Error('second argument must be a Number')
|
|
let results, len, pending, keys, isErrored
|
|
let isSync = true
|
|
let next
|
|
|
|
if (Array.isArray(tasks)) {
|
|
results = []
|
|
pending = len = tasks.length
|
|
} else {
|
|
keys = Object.keys(tasks)
|
|
results = {}
|
|
pending = len = keys.length
|
|
}
|
|
|
|
function done (err) {
|
|
function end () {
|
|
if (cb) cb(err, results)
|
|
cb = null
|
|
}
|
|
if (isSync) queueMicrotask(end)
|
|
else end()
|
|
}
|
|
|
|
function each (i, err, result) {
|
|
results[i] = result
|
|
if (err) isErrored = true
|
|
if (--pending === 0 || err) {
|
|
done(err)
|
|
} else if (!isErrored && next < len) {
|
|
let key
|
|
if (keys) {
|
|
key = keys[next]
|
|
next += 1
|
|
tasks[key](function (err, result) { each(key, err, result) })
|
|
} else {
|
|
key = next
|
|
next += 1
|
|
tasks[key](function (err, result) { each(key, err, result) })
|
|
}
|
|
}
|
|
}
|
|
|
|
next = limit
|
|
if (!pending) {
|
|
// empty
|
|
done(null)
|
|
} else if (keys) {
|
|
// object
|
|
keys.some(function (key, i) {
|
|
tasks[key](function (err, result) { each(key, err, result) })
|
|
if (i === limit - 1) return true // early return
|
|
return false
|
|
})
|
|
} else {
|
|
// array
|
|
tasks.some(function (task, i) {
|
|
task(function (err, result) { each(i, err, result) })
|
|
if (i === limit - 1) return true // early return
|
|
return false
|
|
})
|
|
}
|
|
|
|
isSync = false
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/run-parallel/index.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/run-parallel/index.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*! run-parallel. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
module.exports = runParallel
|
|
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
|
|
function runParallel (tasks, cb) {
|
|
let results, pending, keys
|
|
let isSync = true
|
|
|
|
if (Array.isArray(tasks)) {
|
|
results = []
|
|
pending = tasks.length
|
|
} else {
|
|
keys = Object.keys(tasks)
|
|
results = {}
|
|
pending = keys.length
|
|
}
|
|
|
|
function done (err) {
|
|
function end () {
|
|
if (cb) cb(err, results)
|
|
cb = null
|
|
}
|
|
if (isSync) queueMicrotask(end)
|
|
else end()
|
|
}
|
|
|
|
function each (i, err, result) {
|
|
results[i] = result
|
|
if (--pending === 0 || err) {
|
|
done(err)
|
|
}
|
|
}
|
|
|
|
if (!pending) {
|
|
// empty
|
|
done(null)
|
|
} else if (keys) {
|
|
// object
|
|
keys.forEach(function (key) {
|
|
tasks[key](function (err, result) { each(key, err, result) })
|
|
})
|
|
} else {
|
|
// array
|
|
tasks.forEach(function (task, i) {
|
|
task(function (err, result) { each(i, err, result) })
|
|
})
|
|
}
|
|
|
|
isSync = false
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/rusha/dist/rusha.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/rusha/dist/rusha.js ***!
|
|
\******************************************/
|
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
if(true)
|
|
module.exports = factory();
|
|
else {}
|
|
})(typeof self !== 'undefined' ? self : this, function() {
|
|
return /******/ (function(modules) { // webpackBootstrap
|
|
/******/ // The module cache
|
|
/******/ var installedModules = {};
|
|
/******/
|
|
/******/ // The require function
|
|
/******/ function __nested_webpack_require_570__(moduleId) {
|
|
/******/
|
|
/******/ // Check if module is in cache
|
|
/******/ if(installedModules[moduleId]) {
|
|
/******/ return installedModules[moduleId].exports;
|
|
/******/ }
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = installedModules[moduleId] = {
|
|
/******/ i: moduleId,
|
|
/******/ l: false,
|
|
/******/ exports: {}
|
|
/******/ };
|
|
/******/
|
|
/******/ // Execute the module function
|
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __nested_webpack_require_570__);
|
|
/******/
|
|
/******/ // Flag the module as loaded
|
|
/******/ module.l = true;
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/******/
|
|
/******/ // expose the modules object (__webpack_modules__)
|
|
/******/ __nested_webpack_require_570__.m = modules;
|
|
/******/
|
|
/******/ // expose the module cache
|
|
/******/ __nested_webpack_require_570__.c = installedModules;
|
|
/******/
|
|
/******/ // define getter function for harmony exports
|
|
/******/ __nested_webpack_require_570__.d = function(exports, name, getter) {
|
|
/******/ if(!__nested_webpack_require_570__.o(exports, name)) {
|
|
/******/ Object.defineProperty(exports, name, {
|
|
/******/ configurable: false,
|
|
/******/ enumerable: true,
|
|
/******/ get: getter
|
|
/******/ });
|
|
/******/ }
|
|
/******/ };
|
|
/******/
|
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
/******/ __nested_webpack_require_570__.n = function(module) {
|
|
/******/ var getter = module && module.__esModule ?
|
|
/******/ function getDefault() { return module['default']; } :
|
|
/******/ function getModuleExports() { return module; };
|
|
/******/ __nested_webpack_require_570__.d(getter, 'a', getter);
|
|
/******/ return getter;
|
|
/******/ };
|
|
/******/
|
|
/******/ // Object.prototype.hasOwnProperty.call
|
|
/******/ __nested_webpack_require_570__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
/******/
|
|
/******/ // __webpack_public_path__
|
|
/******/ __nested_webpack_require_570__.p = "";
|
|
/******/
|
|
/******/ // Load entry module and return exports
|
|
/******/ return __nested_webpack_require_570__(__nested_webpack_require_570__.s = 3);
|
|
/******/ })
|
|
/************************************************************************/
|
|
/******/ ([
|
|
/* 0 */
|
|
/***/ (function(module, exports, __nested_webpack_require_2847__) {
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
/* eslint-env commonjs, browser */
|
|
|
|
var RushaCore = __nested_webpack_require_2847__(5);
|
|
|
|
var _require = __nested_webpack_require_2847__(1),
|
|
toHex = _require.toHex,
|
|
ceilHeapSize = _require.ceilHeapSize;
|
|
|
|
var conv = __nested_webpack_require_2847__(6);
|
|
|
|
// Calculate the length of buffer that the sha1 routine uses
|
|
// including the padding.
|
|
var padlen = function (len) {
|
|
for (len += 9; len % 64 > 0; len += 1) {}
|
|
return len;
|
|
};
|
|
|
|
var padZeroes = function (bin, len) {
|
|
var h8 = new Uint8Array(bin.buffer);
|
|
var om = len % 4,
|
|
align = len - om;
|
|
switch (om) {
|
|
case 0:
|
|
h8[align + 3] = 0;
|
|
case 1:
|
|
h8[align + 2] = 0;
|
|
case 2:
|
|
h8[align + 1] = 0;
|
|
case 3:
|
|
h8[align + 0] = 0;
|
|
}
|
|
for (var i = (len >> 2) + 1; i < bin.length; i++) {
|
|
bin[i] = 0;
|
|
}
|
|
};
|
|
|
|
var padData = function (bin, chunkLen, msgLen) {
|
|
bin[chunkLen >> 2] |= 0x80 << 24 - (chunkLen % 4 << 3);
|
|
// To support msgLen >= 2 GiB, use a float division when computing the
|
|
// high 32-bits of the big-endian message length in bits.
|
|
bin[((chunkLen >> 2) + 2 & ~0x0f) + 14] = msgLen / (1 << 29) | 0;
|
|
bin[((chunkLen >> 2) + 2 & ~0x0f) + 15] = msgLen << 3;
|
|
};
|
|
|
|
var getRawDigest = function (heap, padMaxChunkLen) {
|
|
var io = new Int32Array(heap, padMaxChunkLen + 320, 5);
|
|
var out = new Int32Array(5);
|
|
var arr = new DataView(out.buffer);
|
|
arr.setInt32(0, io[0], false);
|
|
arr.setInt32(4, io[1], false);
|
|
arr.setInt32(8, io[2], false);
|
|
arr.setInt32(12, io[3], false);
|
|
arr.setInt32(16, io[4], false);
|
|
return out;
|
|
};
|
|
|
|
var Rusha = function () {
|
|
function Rusha(chunkSize) {
|
|
_classCallCheck(this, Rusha);
|
|
|
|
chunkSize = chunkSize || 64 * 1024;
|
|
if (chunkSize % 64 > 0) {
|
|
throw new Error('Chunk size must be a multiple of 128 bit');
|
|
}
|
|
this._offset = 0;
|
|
this._maxChunkLen = chunkSize;
|
|
this._padMaxChunkLen = padlen(chunkSize);
|
|
// The size of the heap is the sum of:
|
|
// 1. The padded input message size
|
|
// 2. The extended space the algorithm needs (320 byte)
|
|
// 3. The 160 bit state the algoritm uses
|
|
this._heap = new ArrayBuffer(ceilHeapSize(this._padMaxChunkLen + 320 + 20));
|
|
this._h32 = new Int32Array(this._heap);
|
|
this._h8 = new Int8Array(this._heap);
|
|
this._core = new RushaCore({ Int32Array: Int32Array }, {}, this._heap);
|
|
}
|
|
|
|
Rusha.prototype._initState = function _initState(heap, padMsgLen) {
|
|
this._offset = 0;
|
|
var io = new Int32Array(heap, padMsgLen + 320, 5);
|
|
io[0] = 1732584193;
|
|
io[1] = -271733879;
|
|
io[2] = -1732584194;
|
|
io[3] = 271733878;
|
|
io[4] = -1009589776;
|
|
};
|
|
|
|
Rusha.prototype._padChunk = function _padChunk(chunkLen, msgLen) {
|
|
var padChunkLen = padlen(chunkLen);
|
|
var view = new Int32Array(this._heap, 0, padChunkLen >> 2);
|
|
padZeroes(view, chunkLen);
|
|
padData(view, chunkLen, msgLen);
|
|
return padChunkLen;
|
|
};
|
|
|
|
Rusha.prototype._write = function _write(data, chunkOffset, chunkLen, off) {
|
|
conv(data, this._h8, this._h32, chunkOffset, chunkLen, off || 0);
|
|
};
|
|
|
|
Rusha.prototype._coreCall = function _coreCall(data, chunkOffset, chunkLen, msgLen, finalize) {
|
|
var padChunkLen = chunkLen;
|
|
this._write(data, chunkOffset, chunkLen);
|
|
if (finalize) {
|
|
padChunkLen = this._padChunk(chunkLen, msgLen);
|
|
}
|
|
this._core.hash(padChunkLen, this._padMaxChunkLen);
|
|
};
|
|
|
|
Rusha.prototype.rawDigest = function rawDigest(str) {
|
|
var msgLen = str.byteLength || str.length || str.size || 0;
|
|
this._initState(this._heap, this._padMaxChunkLen);
|
|
var chunkOffset = 0,
|
|
chunkLen = this._maxChunkLen;
|
|
for (chunkOffset = 0; msgLen > chunkOffset + chunkLen; chunkOffset += chunkLen) {
|
|
this._coreCall(str, chunkOffset, chunkLen, msgLen, false);
|
|
}
|
|
this._coreCall(str, chunkOffset, msgLen - chunkOffset, msgLen, true);
|
|
return getRawDigest(this._heap, this._padMaxChunkLen);
|
|
};
|
|
|
|
Rusha.prototype.digest = function digest(str) {
|
|
return toHex(this.rawDigest(str).buffer);
|
|
};
|
|
|
|
Rusha.prototype.digestFromString = function digestFromString(str) {
|
|
return this.digest(str);
|
|
};
|
|
|
|
Rusha.prototype.digestFromBuffer = function digestFromBuffer(str) {
|
|
return this.digest(str);
|
|
};
|
|
|
|
Rusha.prototype.digestFromArrayBuffer = function digestFromArrayBuffer(str) {
|
|
return this.digest(str);
|
|
};
|
|
|
|
Rusha.prototype.resetState = function resetState() {
|
|
this._initState(this._heap, this._padMaxChunkLen);
|
|
return this;
|
|
};
|
|
|
|
Rusha.prototype.append = function append(chunk) {
|
|
var chunkOffset = 0;
|
|
var chunkLen = chunk.byteLength || chunk.length || chunk.size || 0;
|
|
var turnOffset = this._offset % this._maxChunkLen;
|
|
var inputLen = void 0;
|
|
|
|
this._offset += chunkLen;
|
|
while (chunkOffset < chunkLen) {
|
|
inputLen = Math.min(chunkLen - chunkOffset, this._maxChunkLen - turnOffset);
|
|
this._write(chunk, chunkOffset, inputLen, turnOffset);
|
|
turnOffset += inputLen;
|
|
chunkOffset += inputLen;
|
|
if (turnOffset === this._maxChunkLen) {
|
|
this._core.hash(this._maxChunkLen, this._padMaxChunkLen);
|
|
turnOffset = 0;
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
Rusha.prototype.getState = function getState() {
|
|
var turnOffset = this._offset % this._maxChunkLen;
|
|
var heap = void 0;
|
|
if (!turnOffset) {
|
|
var io = new Int32Array(this._heap, this._padMaxChunkLen + 320, 5);
|
|
heap = io.buffer.slice(io.byteOffset, io.byteOffset + io.byteLength);
|
|
} else {
|
|
heap = this._heap.slice(0);
|
|
}
|
|
return {
|
|
offset: this._offset,
|
|
heap: heap
|
|
};
|
|
};
|
|
|
|
Rusha.prototype.setState = function setState(state) {
|
|
this._offset = state.offset;
|
|
if (state.heap.byteLength === 20) {
|
|
var io = new Int32Array(this._heap, this._padMaxChunkLen + 320, 5);
|
|
io.set(new Int32Array(state.heap));
|
|
} else {
|
|
this._h32.set(new Int32Array(state.heap));
|
|
}
|
|
return this;
|
|
};
|
|
|
|
Rusha.prototype.rawEnd = function rawEnd() {
|
|
var msgLen = this._offset;
|
|
var chunkLen = msgLen % this._maxChunkLen;
|
|
var padChunkLen = this._padChunk(chunkLen, msgLen);
|
|
this._core.hash(padChunkLen, this._padMaxChunkLen);
|
|
var result = getRawDigest(this._heap, this._padMaxChunkLen);
|
|
this._initState(this._heap, this._padMaxChunkLen);
|
|
return result;
|
|
};
|
|
|
|
Rusha.prototype.end = function end() {
|
|
return toHex(this.rawEnd().buffer);
|
|
};
|
|
|
|
return Rusha;
|
|
}();
|
|
|
|
module.exports = Rusha;
|
|
module.exports._core = RushaCore;
|
|
|
|
/***/ }),
|
|
/* 1 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/* eslint-env commonjs, browser */
|
|
|
|
//
|
|
// toHex
|
|
//
|
|
|
|
var precomputedHex = new Array(256);
|
|
for (var i = 0; i < 256; i++) {
|
|
precomputedHex[i] = (i < 0x10 ? '0' : '') + i.toString(16);
|
|
}
|
|
|
|
module.exports.toHex = function (arrayBuffer) {
|
|
var binarray = new Uint8Array(arrayBuffer);
|
|
var res = new Array(arrayBuffer.byteLength);
|
|
for (var _i = 0; _i < res.length; _i++) {
|
|
res[_i] = precomputedHex[binarray[_i]];
|
|
}
|
|
return res.join('');
|
|
};
|
|
|
|
//
|
|
// ceilHeapSize
|
|
//
|
|
|
|
module.exports.ceilHeapSize = function (v) {
|
|
// The asm.js spec says:
|
|
// The heap object's byteLength must be either
|
|
// 2^n for n in [12, 24) or 2^24 * n for n ≥ 1.
|
|
// Also, byteLengths smaller than 2^16 are deprecated.
|
|
var p = 0;
|
|
// If v is smaller than 2^16, the smallest possible solution
|
|
// is 2^16.
|
|
if (v <= 65536) return 65536;
|
|
// If v < 2^24, we round up to 2^n,
|
|
// otherwise we round up to 2^24 * n.
|
|
if (v < 16777216) {
|
|
for (p = 1; p < v; p = p << 1) {}
|
|
} else {
|
|
for (p = 16777216; p < v; p += 16777216) {}
|
|
}
|
|
return p;
|
|
};
|
|
|
|
//
|
|
// isDedicatedWorkerScope
|
|
//
|
|
|
|
module.exports.isDedicatedWorkerScope = function (self) {
|
|
var isRunningInWorker = 'WorkerGlobalScope' in self && self instanceof self.WorkerGlobalScope;
|
|
var isRunningInSharedWorker = 'SharedWorkerGlobalScope' in self && self instanceof self.SharedWorkerGlobalScope;
|
|
var isRunningInServiceWorker = 'ServiceWorkerGlobalScope' in self && self instanceof self.ServiceWorkerGlobalScope;
|
|
|
|
// Detects whether we run inside a dedicated worker or not.
|
|
//
|
|
// We can't just check for `DedicatedWorkerGlobalScope`, since IE11
|
|
// has a bug where it only supports `WorkerGlobalScope`.
|
|
//
|
|
// Therefore, we consider us as running inside a dedicated worker
|
|
// when we are running inside a worker, but not in a shared or service worker.
|
|
//
|
|
// When new types of workers are introduced, we will need to adjust this code.
|
|
return isRunningInWorker && !isRunningInSharedWorker && !isRunningInServiceWorker;
|
|
};
|
|
|
|
/***/ }),
|
|
/* 2 */
|
|
/***/ (function(module, exports, __nested_webpack_require_11492__) {
|
|
|
|
/* eslint-env commonjs, worker */
|
|
|
|
module.exports = function () {
|
|
var Rusha = __nested_webpack_require_11492__(0);
|
|
|
|
var hashData = function (hasher, data, cb) {
|
|
try {
|
|
return cb(null, hasher.digest(data));
|
|
} catch (e) {
|
|
return cb(e);
|
|
}
|
|
};
|
|
|
|
var hashFile = function (hasher, readTotal, blockSize, file, cb) {
|
|
var reader = new self.FileReader();
|
|
reader.onloadend = function onloadend() {
|
|
if (reader.error) {
|
|
return cb(reader.error);
|
|
}
|
|
var buffer = reader.result;
|
|
readTotal += reader.result.byteLength;
|
|
try {
|
|
hasher.append(buffer);
|
|
} catch (e) {
|
|
cb(e);
|
|
return;
|
|
}
|
|
if (readTotal < file.size) {
|
|
hashFile(hasher, readTotal, blockSize, file, cb);
|
|
} else {
|
|
cb(null, hasher.end());
|
|
}
|
|
};
|
|
reader.readAsArrayBuffer(file.slice(readTotal, readTotal + blockSize));
|
|
};
|
|
|
|
var workerBehaviourEnabled = true;
|
|
|
|
self.onmessage = function (event) {
|
|
if (!workerBehaviourEnabled) {
|
|
return;
|
|
}
|
|
|
|
var data = event.data.data,
|
|
file = event.data.file,
|
|
id = event.data.id;
|
|
if (typeof id === 'undefined') return;
|
|
if (!file && !data) return;
|
|
var blockSize = event.data.blockSize || 4 * 1024 * 1024;
|
|
var hasher = new Rusha(blockSize);
|
|
hasher.resetState();
|
|
var done = function (err, hash) {
|
|
if (!err) {
|
|
self.postMessage({ id: id, hash: hash });
|
|
} else {
|
|
self.postMessage({ id: id, error: err.name });
|
|
}
|
|
};
|
|
if (data) hashData(hasher, data, done);
|
|
if (file) hashFile(hasher, 0, blockSize, file, done);
|
|
};
|
|
|
|
return function () {
|
|
workerBehaviourEnabled = false;
|
|
};
|
|
};
|
|
|
|
/***/ }),
|
|
/* 3 */
|
|
/***/ (function(module, exports, __nested_webpack_require_13254__) {
|
|
|
|
/* eslint-env commonjs, browser */
|
|
|
|
var work = __nested_webpack_require_13254__(4);
|
|
var Rusha = __nested_webpack_require_13254__(0);
|
|
var createHash = __nested_webpack_require_13254__(7);
|
|
var runWorker = __nested_webpack_require_13254__(2);
|
|
|
|
var _require = __nested_webpack_require_13254__(1),
|
|
isDedicatedWorkerScope = _require.isDedicatedWorkerScope;
|
|
|
|
var isRunningInDedicatedWorker = typeof self !== 'undefined' && isDedicatedWorkerScope(self);
|
|
|
|
Rusha.disableWorkerBehaviour = isRunningInDedicatedWorker ? runWorker() : function () {};
|
|
|
|
Rusha.createWorker = function () {
|
|
var worker = work(/*require.resolve*/(2));
|
|
var terminate = worker.terminate;
|
|
worker.terminate = function () {
|
|
URL.revokeObjectURL(worker.objectURL);
|
|
terminate.call(worker);
|
|
};
|
|
return worker;
|
|
};
|
|
|
|
Rusha.createHash = createHash;
|
|
|
|
module.exports = Rusha;
|
|
|
|
/***/ }),
|
|
/* 4 */
|
|
/***/ (function(module, exports, __nested_webpack_require_14111__) {
|
|
|
|
function webpackBootstrapFunc (modules) {
|
|
/******/ // The module cache
|
|
/******/ var installedModules = {};
|
|
|
|
/******/ // The require function
|
|
/******/ function __nested_webpack_require_14289__(moduleId) {
|
|
|
|
/******/ // Check if module is in cache
|
|
/******/ if(installedModules[moduleId])
|
|
/******/ return installedModules[moduleId].exports;
|
|
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = installedModules[moduleId] = {
|
|
/******/ i: moduleId,
|
|
/******/ l: false,
|
|
/******/ exports: {}
|
|
/******/ };
|
|
|
|
/******/ // Execute the module function
|
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __nested_webpack_require_14289__);
|
|
|
|
/******/ // Flag the module as loaded
|
|
/******/ module.l = true;
|
|
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
|
|
/******/ // expose the modules object (__webpack_modules__)
|
|
/******/ __nested_webpack_require_14289__.m = modules;
|
|
|
|
/******/ // expose the module cache
|
|
/******/ __nested_webpack_require_14289__.c = installedModules;
|
|
|
|
/******/ // identity function for calling harmony imports with the correct context
|
|
/******/ __nested_webpack_require_14289__.i = function(value) { return value; };
|
|
|
|
/******/ // define getter function for harmony exports
|
|
/******/ __nested_webpack_require_14289__.d = function(exports, name, getter) {
|
|
/******/ if(!__nested_webpack_require_14289__.o(exports, name)) {
|
|
/******/ Object.defineProperty(exports, name, {
|
|
/******/ configurable: false,
|
|
/******/ enumerable: true,
|
|
/******/ get: getter
|
|
/******/ });
|
|
/******/ }
|
|
/******/ };
|
|
|
|
/******/ // define __esModule on exports
|
|
/******/ __nested_webpack_require_14289__.r = function(exports) {
|
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
/******/ };
|
|
|
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
/******/ __nested_webpack_require_14289__.n = function(module) {
|
|
/******/ var getter = module && module.__esModule ?
|
|
/******/ function getDefault() { return module['default']; } :
|
|
/******/ function getModuleExports() { return module; };
|
|
/******/ __nested_webpack_require_14289__.d(getter, 'a', getter);
|
|
/******/ return getter;
|
|
/******/ };
|
|
|
|
/******/ // Object.prototype.hasOwnProperty.call
|
|
/******/ __nested_webpack_require_14289__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
|
|
/******/ // __webpack_public_path__
|
|
/******/ __nested_webpack_require_14289__.p = "/";
|
|
|
|
/******/ // on error function for async loading
|
|
/******/ __nested_webpack_require_14289__.oe = function(err) { console.error(err); throw err; };
|
|
|
|
var f = __nested_webpack_require_14289__(__nested_webpack_require_14289__.s = ENTRY_MODULE)
|
|
return f.default || f // try to call default if defined to also support babel esmodule exports
|
|
}
|
|
|
|
var moduleNameReqExp = '[\\.|\\-|\\+|\\w|\/|@]+'
|
|
var dependencyRegExp = '\\((\/\\*.*?\\*\/)?\s?.*?(' + moduleNameReqExp + ').*?\\)' // additional chars when output.pathinfo is true
|
|
|
|
// http://stackoverflow.com/a/2593661/130442
|
|
function quoteRegExp (str) {
|
|
return (str + '').replace(/[.?*+^$[\]\\(){}|-]/g, '\\$&')
|
|
}
|
|
|
|
function getModuleDependencies (sources, module, queueName) {
|
|
var retval = {}
|
|
retval[queueName] = []
|
|
|
|
var fnString = module.toString()
|
|
var wrapperSignature = fnString.match(/^function\s?\(\w+,\s*\w+,\s*(\w+)\)/)
|
|
if (!wrapperSignature) return retval
|
|
var webpackRequireName = wrapperSignature[1]
|
|
|
|
// main bundle deps
|
|
var re = new RegExp('(\\\\n|\\W)' + quoteRegExp(webpackRequireName) + dependencyRegExp, 'g')
|
|
var match
|
|
while ((match = re.exec(fnString))) {
|
|
if (match[3] === 'dll-reference') continue
|
|
retval[queueName].push(match[3])
|
|
}
|
|
|
|
// dll deps
|
|
re = new RegExp('\\(' + quoteRegExp(webpackRequireName) + '\\("(dll-reference\\s(' + moduleNameReqExp + '))"\\)\\)' + dependencyRegExp, 'g')
|
|
while ((match = re.exec(fnString))) {
|
|
if (!sources[match[2]]) {
|
|
retval[queueName].push(match[1])
|
|
sources[match[2]] = __nested_webpack_require_14111__(match[1]).m
|
|
}
|
|
retval[match[2]] = retval[match[2]] || []
|
|
retval[match[2]].push(match[4])
|
|
}
|
|
|
|
return retval
|
|
}
|
|
|
|
function hasValuesInQueues (queues) {
|
|
var keys = Object.keys(queues)
|
|
return keys.reduce(function (hasValues, key) {
|
|
return hasValues || queues[key].length > 0
|
|
}, false)
|
|
}
|
|
|
|
function getRequiredModules (sources, moduleId) {
|
|
var modulesQueue = {
|
|
main: [moduleId]
|
|
}
|
|
var requiredModules = {
|
|
main: []
|
|
}
|
|
var seenModules = {
|
|
main: {}
|
|
}
|
|
|
|
while (hasValuesInQueues(modulesQueue)) {
|
|
var queues = Object.keys(modulesQueue)
|
|
for (var i = 0; i < queues.length; i++) {
|
|
var queueName = queues[i]
|
|
var queue = modulesQueue[queueName]
|
|
var moduleToCheck = queue.pop()
|
|
seenModules[queueName] = seenModules[queueName] || {}
|
|
if (seenModules[queueName][moduleToCheck] || !sources[queueName][moduleToCheck]) continue
|
|
seenModules[queueName][moduleToCheck] = true
|
|
requiredModules[queueName] = requiredModules[queueName] || []
|
|
requiredModules[queueName].push(moduleToCheck)
|
|
var newModules = getModuleDependencies(sources, sources[queueName][moduleToCheck], queueName)
|
|
var newModulesKeys = Object.keys(newModules)
|
|
for (var j = 0; j < newModulesKeys.length; j++) {
|
|
modulesQueue[newModulesKeys[j]] = modulesQueue[newModulesKeys[j]] || []
|
|
modulesQueue[newModulesKeys[j]] = modulesQueue[newModulesKeys[j]].concat(newModules[newModulesKeys[j]])
|
|
}
|
|
}
|
|
}
|
|
|
|
return requiredModules
|
|
}
|
|
|
|
module.exports = function (moduleId, options) {
|
|
options = options || {}
|
|
var sources = {
|
|
main: __nested_webpack_require_14111__.m
|
|
}
|
|
|
|
var requiredModules = options.all ? { main: Object.keys(sources) } : getRequiredModules(sources, moduleId)
|
|
|
|
var src = ''
|
|
|
|
Object.keys(requiredModules).filter(function (m) { return m !== 'main' }).forEach(function (module) {
|
|
var entryModule = 0
|
|
while (requiredModules[module][entryModule]) {
|
|
entryModule++
|
|
}
|
|
requiredModules[module].push(entryModule)
|
|
sources[module][entryModule] = '(function(module, exports, __webpack_require__) { module.exports = __webpack_require__; })'
|
|
src = src + 'var ' + module + ' = (' + webpackBootstrapFunc.toString().replace('ENTRY_MODULE', JSON.stringify(entryModule)) + ')({' + requiredModules[module].map(function (id) { return '' + JSON.stringify(id) + ': ' + sources[module][id].toString() }).join(',') + '});\n'
|
|
})
|
|
|
|
src = src + '(' + webpackBootstrapFunc.toString().replace('ENTRY_MODULE', JSON.stringify(moduleId)) + ')({' + requiredModules.main.map(function (id) { return '' + JSON.stringify(id) + ': ' + sources.main[id].toString() }).join(',') + '})(self);'
|
|
|
|
var blob = new window.Blob([src], { type: 'text/javascript' })
|
|
if (options.bare) { return blob }
|
|
|
|
var URL = window.URL || window.webkitURL || window.mozURL || window.msURL
|
|
|
|
var workerUrl = URL.createObjectURL(blob)
|
|
var worker = new window.Worker(workerUrl)
|
|
worker.objectURL = workerUrl
|
|
|
|
return worker
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 5 */
|
|
/***/ (function(module, exports) {
|
|
|
|
// The low-level RushCore module provides the heart of Rusha,
|
|
// a high-speed sha1 implementation working on an Int32Array heap.
|
|
// At first glance, the implementation seems complicated, however
|
|
// with the SHA1 spec at hand, it is obvious this almost a textbook
|
|
// implementation that has a few functions hand-inlined and a few loops
|
|
// hand-unrolled.
|
|
module.exports = function RushaCore(stdlib$840, foreign$841, heap$842) {
|
|
'use asm';
|
|
var H$843 = new stdlib$840.Int32Array(heap$842);
|
|
function hash$844(k$845, x$846) {
|
|
// k in bytes
|
|
k$845 = k$845 | 0;
|
|
x$846 = x$846 | 0;
|
|
var i$847 = 0, j$848 = 0, y0$849 = 0, z0$850 = 0, y1$851 = 0, z1$852 = 0, y2$853 = 0, z2$854 = 0, y3$855 = 0, z3$856 = 0, y4$857 = 0, z4$858 = 0, t0$859 = 0, t1$860 = 0;
|
|
y0$849 = H$843[x$846 + 320 >> 2] | 0;
|
|
y1$851 = H$843[x$846 + 324 >> 2] | 0;
|
|
y2$853 = H$843[x$846 + 328 >> 2] | 0;
|
|
y3$855 = H$843[x$846 + 332 >> 2] | 0;
|
|
y4$857 = H$843[x$846 + 336 >> 2] | 0;
|
|
for (i$847 = 0; (i$847 | 0) < (k$845 | 0); i$847 = i$847 + 64 | 0) {
|
|
z0$850 = y0$849;
|
|
z1$852 = y1$851;
|
|
z2$854 = y2$853;
|
|
z3$856 = y3$855;
|
|
z4$858 = y4$857;
|
|
for (j$848 = 0; (j$848 | 0) < 64; j$848 = j$848 + 4 | 0) {
|
|
t1$860 = H$843[i$847 + j$848 >> 2] | 0;
|
|
t0$859 = ((y0$849 << 5 | y0$849 >>> 27) + (y1$851 & y2$853 | ~y1$851 & y3$855) | 0) + ((t1$860 + y4$857 | 0) + 1518500249 | 0) | 0;
|
|
y4$857 = y3$855;
|
|
y3$855 = y2$853;
|
|
y2$853 = y1$851 << 30 | y1$851 >>> 2;
|
|
y1$851 = y0$849;
|
|
y0$849 = t0$859;
|
|
H$843[k$845 + j$848 >> 2] = t1$860;
|
|
}
|
|
for (j$848 = k$845 + 64 | 0; (j$848 | 0) < (k$845 + 80 | 0); j$848 = j$848 + 4 | 0) {
|
|
t1$860 = (H$843[j$848 - 12 >> 2] ^ H$843[j$848 - 32 >> 2] ^ H$843[j$848 - 56 >> 2] ^ H$843[j$848 - 64 >> 2]) << 1 | (H$843[j$848 - 12 >> 2] ^ H$843[j$848 - 32 >> 2] ^ H$843[j$848 - 56 >> 2] ^ H$843[j$848 - 64 >> 2]) >>> 31;
|
|
t0$859 = ((y0$849 << 5 | y0$849 >>> 27) + (y1$851 & y2$853 | ~y1$851 & y3$855) | 0) + ((t1$860 + y4$857 | 0) + 1518500249 | 0) | 0;
|
|
y4$857 = y3$855;
|
|
y3$855 = y2$853;
|
|
y2$853 = y1$851 << 30 | y1$851 >>> 2;
|
|
y1$851 = y0$849;
|
|
y0$849 = t0$859;
|
|
H$843[j$848 >> 2] = t1$860;
|
|
}
|
|
for (j$848 = k$845 + 80 | 0; (j$848 | 0) < (k$845 + 160 | 0); j$848 = j$848 + 4 | 0) {
|
|
t1$860 = (H$843[j$848 - 12 >> 2] ^ H$843[j$848 - 32 >> 2] ^ H$843[j$848 - 56 >> 2] ^ H$843[j$848 - 64 >> 2]) << 1 | (H$843[j$848 - 12 >> 2] ^ H$843[j$848 - 32 >> 2] ^ H$843[j$848 - 56 >> 2] ^ H$843[j$848 - 64 >> 2]) >>> 31;
|
|
t0$859 = ((y0$849 << 5 | y0$849 >>> 27) + (y1$851 ^ y2$853 ^ y3$855) | 0) + ((t1$860 + y4$857 | 0) + 1859775393 | 0) | 0;
|
|
y4$857 = y3$855;
|
|
y3$855 = y2$853;
|
|
y2$853 = y1$851 << 30 | y1$851 >>> 2;
|
|
y1$851 = y0$849;
|
|
y0$849 = t0$859;
|
|
H$843[j$848 >> 2] = t1$860;
|
|
}
|
|
for (j$848 = k$845 + 160 | 0; (j$848 | 0) < (k$845 + 240 | 0); j$848 = j$848 + 4 | 0) {
|
|
t1$860 = (H$843[j$848 - 12 >> 2] ^ H$843[j$848 - 32 >> 2] ^ H$843[j$848 - 56 >> 2] ^ H$843[j$848 - 64 >> 2]) << 1 | (H$843[j$848 - 12 >> 2] ^ H$843[j$848 - 32 >> 2] ^ H$843[j$848 - 56 >> 2] ^ H$843[j$848 - 64 >> 2]) >>> 31;
|
|
t0$859 = ((y0$849 << 5 | y0$849 >>> 27) + (y1$851 & y2$853 | y1$851 & y3$855 | y2$853 & y3$855) | 0) + ((t1$860 + y4$857 | 0) - 1894007588 | 0) | 0;
|
|
y4$857 = y3$855;
|
|
y3$855 = y2$853;
|
|
y2$853 = y1$851 << 30 | y1$851 >>> 2;
|
|
y1$851 = y0$849;
|
|
y0$849 = t0$859;
|
|
H$843[j$848 >> 2] = t1$860;
|
|
}
|
|
for (j$848 = k$845 + 240 | 0; (j$848 | 0) < (k$845 + 320 | 0); j$848 = j$848 + 4 | 0) {
|
|
t1$860 = (H$843[j$848 - 12 >> 2] ^ H$843[j$848 - 32 >> 2] ^ H$843[j$848 - 56 >> 2] ^ H$843[j$848 - 64 >> 2]) << 1 | (H$843[j$848 - 12 >> 2] ^ H$843[j$848 - 32 >> 2] ^ H$843[j$848 - 56 >> 2] ^ H$843[j$848 - 64 >> 2]) >>> 31;
|
|
t0$859 = ((y0$849 << 5 | y0$849 >>> 27) + (y1$851 ^ y2$853 ^ y3$855) | 0) + ((t1$860 + y4$857 | 0) - 899497514 | 0) | 0;
|
|
y4$857 = y3$855;
|
|
y3$855 = y2$853;
|
|
y2$853 = y1$851 << 30 | y1$851 >>> 2;
|
|
y1$851 = y0$849;
|
|
y0$849 = t0$859;
|
|
H$843[j$848 >> 2] = t1$860;
|
|
}
|
|
y0$849 = y0$849 + z0$850 | 0;
|
|
y1$851 = y1$851 + z1$852 | 0;
|
|
y2$853 = y2$853 + z2$854 | 0;
|
|
y3$855 = y3$855 + z3$856 | 0;
|
|
y4$857 = y4$857 + z4$858 | 0;
|
|
}
|
|
H$843[x$846 + 320 >> 2] = y0$849;
|
|
H$843[x$846 + 324 >> 2] = y1$851;
|
|
H$843[x$846 + 328 >> 2] = y2$853;
|
|
H$843[x$846 + 332 >> 2] = y3$855;
|
|
H$843[x$846 + 336 >> 2] = y4$857;
|
|
}
|
|
return { hash: hash$844 };
|
|
};
|
|
|
|
/***/ }),
|
|
/* 6 */
|
|
/***/ (function(module, exports) {
|
|
|
|
var _this = this;
|
|
|
|
/* eslint-env commonjs, browser */
|
|
|
|
var reader = void 0;
|
|
if (typeof self !== 'undefined' && typeof self.FileReaderSync !== 'undefined') {
|
|
reader = new self.FileReaderSync();
|
|
}
|
|
|
|
// Convert a binary string and write it to the heap.
|
|
// A binary string is expected to only contain char codes < 256.
|
|
var convStr = function (str, H8, H32, start, len, off) {
|
|
var i = void 0,
|
|
om = off % 4,
|
|
lm = (len + om) % 4,
|
|
j = len - lm;
|
|
switch (om) {
|
|
case 0:
|
|
H8[off] = str.charCodeAt(start + 3);
|
|
case 1:
|
|
H8[off + 1 - (om << 1) | 0] = str.charCodeAt(start + 2);
|
|
case 2:
|
|
H8[off + 2 - (om << 1) | 0] = str.charCodeAt(start + 1);
|
|
case 3:
|
|
H8[off + 3 - (om << 1) | 0] = str.charCodeAt(start);
|
|
}
|
|
if (len < lm + (4 - om)) {
|
|
return;
|
|
}
|
|
for (i = 4 - om; i < j; i = i + 4 | 0) {
|
|
H32[off + i >> 2] = str.charCodeAt(start + i) << 24 | str.charCodeAt(start + i + 1) << 16 | str.charCodeAt(start + i + 2) << 8 | str.charCodeAt(start + i + 3);
|
|
}
|
|
switch (lm) {
|
|
case 3:
|
|
H8[off + j + 1 | 0] = str.charCodeAt(start + j + 2);
|
|
case 2:
|
|
H8[off + j + 2 | 0] = str.charCodeAt(start + j + 1);
|
|
case 1:
|
|
H8[off + j + 3 | 0] = str.charCodeAt(start + j);
|
|
}
|
|
};
|
|
|
|
// Convert a buffer or array and write it to the heap.
|
|
// The buffer or array is expected to only contain elements < 256.
|
|
var convBuf = function (buf, H8, H32, start, len, off) {
|
|
var i = void 0,
|
|
om = off % 4,
|
|
lm = (len + om) % 4,
|
|
j = len - lm;
|
|
switch (om) {
|
|
case 0:
|
|
H8[off] = buf[start + 3];
|
|
case 1:
|
|
H8[off + 1 - (om << 1) | 0] = buf[start + 2];
|
|
case 2:
|
|
H8[off + 2 - (om << 1) | 0] = buf[start + 1];
|
|
case 3:
|
|
H8[off + 3 - (om << 1) | 0] = buf[start];
|
|
}
|
|
if (len < lm + (4 - om)) {
|
|
return;
|
|
}
|
|
for (i = 4 - om; i < j; i = i + 4 | 0) {
|
|
H32[off + i >> 2 | 0] = buf[start + i] << 24 | buf[start + i + 1] << 16 | buf[start + i + 2] << 8 | buf[start + i + 3];
|
|
}
|
|
switch (lm) {
|
|
case 3:
|
|
H8[off + j + 1 | 0] = buf[start + j + 2];
|
|
case 2:
|
|
H8[off + j + 2 | 0] = buf[start + j + 1];
|
|
case 1:
|
|
H8[off + j + 3 | 0] = buf[start + j];
|
|
}
|
|
};
|
|
|
|
var convBlob = function (blob, H8, H32, start, len, off) {
|
|
var i = void 0,
|
|
om = off % 4,
|
|
lm = (len + om) % 4,
|
|
j = len - lm;
|
|
var buf = new Uint8Array(reader.readAsArrayBuffer(blob.slice(start, start + len)));
|
|
switch (om) {
|
|
case 0:
|
|
H8[off] = buf[3];
|
|
case 1:
|
|
H8[off + 1 - (om << 1) | 0] = buf[2];
|
|
case 2:
|
|
H8[off + 2 - (om << 1) | 0] = buf[1];
|
|
case 3:
|
|
H8[off + 3 - (om << 1) | 0] = buf[0];
|
|
}
|
|
if (len < lm + (4 - om)) {
|
|
return;
|
|
}
|
|
for (i = 4 - om; i < j; i = i + 4 | 0) {
|
|
H32[off + i >> 2 | 0] = buf[i] << 24 | buf[i + 1] << 16 | buf[i + 2] << 8 | buf[i + 3];
|
|
}
|
|
switch (lm) {
|
|
case 3:
|
|
H8[off + j + 1 | 0] = buf[j + 2];
|
|
case 2:
|
|
H8[off + j + 2 | 0] = buf[j + 1];
|
|
case 1:
|
|
H8[off + j + 3 | 0] = buf[j];
|
|
}
|
|
};
|
|
|
|
module.exports = function (data, H8, H32, start, len, off) {
|
|
if (typeof data === 'string') {
|
|
return convStr(data, H8, H32, start, len, off);
|
|
}
|
|
if (data instanceof Array) {
|
|
return convBuf(data, H8, H32, start, len, off);
|
|
}
|
|
// Safely doing a Buffer check using "this" to avoid Buffer polyfill to be included in the dist
|
|
if (_this && _this.Buffer && _this.Buffer.isBuffer(data)) {
|
|
return convBuf(data, H8, H32, start, len, off);
|
|
}
|
|
if (data instanceof ArrayBuffer) {
|
|
return convBuf(new Uint8Array(data), H8, H32, start, len, off);
|
|
}
|
|
if (data.buffer instanceof ArrayBuffer) {
|
|
return convBuf(new Uint8Array(data.buffer, data.byteOffset, data.byteLength), H8, H32, start, len, off);
|
|
}
|
|
if (data instanceof Blob) {
|
|
return convBlob(data, H8, H32, start, len, off);
|
|
}
|
|
throw new Error('Unsupported data type.');
|
|
};
|
|
|
|
/***/ }),
|
|
/* 7 */
|
|
/***/ (function(module, exports, __nested_webpack_require_30231__) {
|
|
|
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
/* eslint-env commonjs, browser */
|
|
|
|
var Rusha = __nested_webpack_require_30231__(0);
|
|
|
|
var _require = __nested_webpack_require_30231__(1),
|
|
toHex = _require.toHex;
|
|
|
|
var Hash = function () {
|
|
function Hash() {
|
|
_classCallCheck(this, Hash);
|
|
|
|
this._rusha = new Rusha();
|
|
this._rusha.resetState();
|
|
}
|
|
|
|
Hash.prototype.update = function update(data) {
|
|
this._rusha.append(data);
|
|
return this;
|
|
};
|
|
|
|
Hash.prototype.digest = function digest(encoding) {
|
|
var digest = this._rusha.rawEnd().buffer;
|
|
if (!encoding) {
|
|
return digest;
|
|
}
|
|
if (encoding === 'hex') {
|
|
return toHex(digest);
|
|
}
|
|
throw new Error('unsupported digest encoding');
|
|
};
|
|
|
|
_createClass(Hash, [{
|
|
key: 'state',
|
|
get: function () {
|
|
return this._rusha.getState();
|
|
},
|
|
set: function (state) {
|
|
this._rusha.setState(state);
|
|
}
|
|
}]);
|
|
|
|
return Hash;
|
|
}();
|
|
|
|
module.exports = function () {
|
|
return new Hash();
|
|
};
|
|
|
|
/***/ })
|
|
/******/ ]);
|
|
});
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/safe-buffer/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/safe-buffer/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, exports, __webpack_require__) => {
|
|
|
|
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
/* eslint-disable node/no-deprecated-api */
|
|
var buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js")
|
|
var Buffer = buffer.Buffer
|
|
|
|
// alternative to using Object.keys for old browsers
|
|
function copyProps (src, dst) {
|
|
for (var key in src) {
|
|
dst[key] = src[key]
|
|
}
|
|
}
|
|
if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) {
|
|
module.exports = buffer
|
|
} else {
|
|
// Copy properties from require('buffer')
|
|
copyProps(buffer, exports)
|
|
exports.Buffer = SafeBuffer
|
|
}
|
|
|
|
function SafeBuffer (arg, encodingOrOffset, length) {
|
|
return Buffer(arg, encodingOrOffset, length)
|
|
}
|
|
|
|
SafeBuffer.prototype = Object.create(Buffer.prototype)
|
|
|
|
// Copy static methods from Buffer
|
|
copyProps(Buffer, SafeBuffer)
|
|
|
|
SafeBuffer.from = function (arg, encodingOrOffset, length) {
|
|
if (typeof arg === 'number') {
|
|
throw new TypeError('Argument must not be a number')
|
|
}
|
|
return Buffer(arg, encodingOrOffset, length)
|
|
}
|
|
|
|
SafeBuffer.alloc = function (size, fill, encoding) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('Argument must be a number')
|
|
}
|
|
var buf = Buffer(size)
|
|
if (fill !== undefined) {
|
|
if (typeof encoding === 'string') {
|
|
buf.fill(fill, encoding)
|
|
} else {
|
|
buf.fill(fill)
|
|
}
|
|
} else {
|
|
buf.fill(0)
|
|
}
|
|
return buf
|
|
}
|
|
|
|
SafeBuffer.allocUnsafe = function (size) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('Argument must be a number')
|
|
}
|
|
return Buffer(size)
|
|
}
|
|
|
|
SafeBuffer.allocUnsafeSlow = function (size) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('Argument must be a number')
|
|
}
|
|
return buffer.SlowBuffer(size)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/safer-buffer/safer.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/safer-buffer/safer.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
/* eslint-disable node/no-deprecated-api */
|
|
|
|
|
|
|
|
var buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js")
|
|
var Buffer = buffer.Buffer
|
|
|
|
var safer = {}
|
|
|
|
var key
|
|
|
|
for (key in buffer) {
|
|
if (!buffer.hasOwnProperty(key)) continue
|
|
if (key === 'SlowBuffer' || key === 'Buffer') continue
|
|
safer[key] = buffer[key]
|
|
}
|
|
|
|
var Safer = safer.Buffer = {}
|
|
for (key in Buffer) {
|
|
if (!Buffer.hasOwnProperty(key)) continue
|
|
if (key === 'allocUnsafe' || key === 'allocUnsafeSlow') continue
|
|
Safer[key] = Buffer[key]
|
|
}
|
|
|
|
safer.Buffer.prototype = Buffer.prototype
|
|
|
|
if (!Safer.from || Safer.from === Uint8Array.from) {
|
|
Safer.from = function (value, encodingOrOffset, length) {
|
|
if (typeof value === 'number') {
|
|
throw new TypeError('The "value" argument must not be of type number. Received type ' + typeof value)
|
|
}
|
|
if (value && typeof value.length === 'undefined') {
|
|
throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type ' + typeof value)
|
|
}
|
|
return Buffer(value, encodingOrOffset, length)
|
|
}
|
|
}
|
|
|
|
if (!Safer.alloc) {
|
|
Safer.alloc = function (size, fill, encoding) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size)
|
|
}
|
|
if (size < 0 || size >= 2 * (1 << 30)) {
|
|
throw new RangeError('The value "' + size + '" is invalid for option "size"')
|
|
}
|
|
var buf = Buffer(size)
|
|
if (!fill || fill.length === 0) {
|
|
buf.fill(0)
|
|
} else if (typeof encoding === 'string') {
|
|
buf.fill(fill, encoding)
|
|
} else {
|
|
buf.fill(fill)
|
|
}
|
|
return buf
|
|
}
|
|
}
|
|
|
|
if (!safer.kStringMaxLength) {
|
|
try {
|
|
safer.kStringMaxLength = process.binding('buffer').kStringMaxLength
|
|
} catch (e) {
|
|
// we can't determine kStringMaxLength in environments where process.binding
|
|
// is unsupported, so let's not set it
|
|
}
|
|
}
|
|
|
|
if (!safer.constants) {
|
|
safer.constants = {
|
|
MAX_LENGTH: safer.kMaxLength
|
|
}
|
|
if (safer.kStringMaxLength) {
|
|
safer.constants.MAX_STRING_LENGTH = safer.kStringMaxLength
|
|
}
|
|
}
|
|
|
|
module.exports = safer
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/sha.js/hash.js":
|
|
/*!*************************************!*\
|
|
!*** ./node_modules/sha.js/hash.js ***!
|
|
\*************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
// prototype class for hash functions
|
|
function Hash (blockSize, finalSize) {
|
|
this._block = Buffer.alloc(blockSize)
|
|
this._finalSize = finalSize
|
|
this._blockSize = blockSize
|
|
this._len = 0
|
|
}
|
|
|
|
Hash.prototype.update = function (data, enc) {
|
|
if (typeof data === 'string') {
|
|
enc = enc || 'utf8'
|
|
data = Buffer.from(data, enc)
|
|
}
|
|
|
|
var block = this._block
|
|
var blockSize = this._blockSize
|
|
var length = data.length
|
|
var accum = this._len
|
|
|
|
for (var offset = 0; offset < length;) {
|
|
var assigned = accum % blockSize
|
|
var remainder = Math.min(length - offset, blockSize - assigned)
|
|
|
|
for (var i = 0; i < remainder; i++) {
|
|
block[assigned + i] = data[offset + i]
|
|
}
|
|
|
|
accum += remainder
|
|
offset += remainder
|
|
|
|
if ((accum % blockSize) === 0) {
|
|
this._update(block)
|
|
}
|
|
}
|
|
|
|
this._len += length
|
|
return this
|
|
}
|
|
|
|
Hash.prototype.digest = function (enc) {
|
|
var rem = this._len % this._blockSize
|
|
|
|
this._block[rem] = 0x80
|
|
|
|
// zero (rem + 1) trailing bits, where (rem + 1) is the smallest
|
|
// non-negative solution to the equation (length + 1 + (rem + 1)) === finalSize mod blockSize
|
|
this._block.fill(0, rem + 1)
|
|
|
|
if (rem >= this._finalSize) {
|
|
this._update(this._block)
|
|
this._block.fill(0)
|
|
}
|
|
|
|
var bits = this._len * 8
|
|
|
|
// uint32
|
|
if (bits <= 0xffffffff) {
|
|
this._block.writeUInt32BE(bits, this._blockSize - 4)
|
|
|
|
// uint64
|
|
} else {
|
|
var lowBits = (bits & 0xffffffff) >>> 0
|
|
var highBits = (bits - lowBits) / 0x100000000
|
|
|
|
this._block.writeUInt32BE(highBits, this._blockSize - 8)
|
|
this._block.writeUInt32BE(lowBits, this._blockSize - 4)
|
|
}
|
|
|
|
this._update(this._block)
|
|
var hash = this._hash()
|
|
|
|
return enc ? hash.toString(enc) : hash
|
|
}
|
|
|
|
Hash.prototype._update = function () {
|
|
throw new Error('_update must be implemented by subclass')
|
|
}
|
|
|
|
module.exports = Hash
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/sha.js/index.js":
|
|
/*!**************************************!*\
|
|
!*** ./node_modules/sha.js/index.js ***!
|
|
\**************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var exports = module.exports = function SHA (algorithm) {
|
|
algorithm = algorithm.toLowerCase()
|
|
|
|
var Algorithm = exports[algorithm]
|
|
if (!Algorithm) throw new Error(algorithm + ' is not supported (we accept pull requests)')
|
|
|
|
return new Algorithm()
|
|
}
|
|
|
|
exports.sha = __webpack_require__(/*! ./sha */ "./node_modules/sha.js/sha.js")
|
|
exports.sha1 = __webpack_require__(/*! ./sha1 */ "./node_modules/sha.js/sha1.js")
|
|
exports.sha224 = __webpack_require__(/*! ./sha224 */ "./node_modules/sha.js/sha224.js")
|
|
exports.sha256 = __webpack_require__(/*! ./sha256 */ "./node_modules/sha.js/sha256.js")
|
|
exports.sha384 = __webpack_require__(/*! ./sha384 */ "./node_modules/sha.js/sha384.js")
|
|
exports.sha512 = __webpack_require__(/*! ./sha512 */ "./node_modules/sha.js/sha512.js")
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/sha.js/sha.js":
|
|
/*!************************************!*\
|
|
!*** ./node_modules/sha.js/sha.js ***!
|
|
\************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*
|
|
* A JavaScript implementation of the Secure Hash Algorithm, SHA-0, as defined
|
|
* in FIPS PUB 180-1
|
|
* This source code is derived from sha1.js of the same repository.
|
|
* The difference between SHA-0 and SHA-1 is just a bitwise rotate left
|
|
* operation was added.
|
|
*/
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var Hash = __webpack_require__(/*! ./hash */ "./node_modules/sha.js/hash.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var K = [
|
|
0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0
|
|
]
|
|
|
|
var W = new Array(80)
|
|
|
|
function Sha () {
|
|
this.init()
|
|
this._w = W
|
|
|
|
Hash.call(this, 64, 56)
|
|
}
|
|
|
|
inherits(Sha, Hash)
|
|
|
|
Sha.prototype.init = function () {
|
|
this._a = 0x67452301
|
|
this._b = 0xefcdab89
|
|
this._c = 0x98badcfe
|
|
this._d = 0x10325476
|
|
this._e = 0xc3d2e1f0
|
|
|
|
return this
|
|
}
|
|
|
|
function rotl5 (num) {
|
|
return (num << 5) | (num >>> 27)
|
|
}
|
|
|
|
function rotl30 (num) {
|
|
return (num << 30) | (num >>> 2)
|
|
}
|
|
|
|
function ft (s, b, c, d) {
|
|
if (s === 0) return (b & c) | ((~b) & d)
|
|
if (s === 2) return (b & c) | (b & d) | (c & d)
|
|
return b ^ c ^ d
|
|
}
|
|
|
|
Sha.prototype._update = function (M) {
|
|
var W = this._w
|
|
|
|
var a = this._a | 0
|
|
var b = this._b | 0
|
|
var c = this._c | 0
|
|
var d = this._d | 0
|
|
var e = this._e | 0
|
|
|
|
for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4)
|
|
for (; i < 80; ++i) W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]
|
|
|
|
for (var j = 0; j < 80; ++j) {
|
|
var s = ~~(j / 20)
|
|
var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0
|
|
|
|
e = d
|
|
d = c
|
|
c = rotl30(b)
|
|
b = a
|
|
a = t
|
|
}
|
|
|
|
this._a = (a + this._a) | 0
|
|
this._b = (b + this._b) | 0
|
|
this._c = (c + this._c) | 0
|
|
this._d = (d + this._d) | 0
|
|
this._e = (e + this._e) | 0
|
|
}
|
|
|
|
Sha.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(20)
|
|
|
|
H.writeInt32BE(this._a | 0, 0)
|
|
H.writeInt32BE(this._b | 0, 4)
|
|
H.writeInt32BE(this._c | 0, 8)
|
|
H.writeInt32BE(this._d | 0, 12)
|
|
H.writeInt32BE(this._e | 0, 16)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/sha.js/sha1.js":
|
|
/*!*************************************!*\
|
|
!*** ./node_modules/sha.js/sha1.js ***!
|
|
\*************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*
|
|
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
|
|
* in FIPS PUB 180-1
|
|
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
* Distributed under the BSD License
|
|
* See http://pajhome.org.uk/crypt/md5 for details.
|
|
*/
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var Hash = __webpack_require__(/*! ./hash */ "./node_modules/sha.js/hash.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var K = [
|
|
0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0
|
|
]
|
|
|
|
var W = new Array(80)
|
|
|
|
function Sha1 () {
|
|
this.init()
|
|
this._w = W
|
|
|
|
Hash.call(this, 64, 56)
|
|
}
|
|
|
|
inherits(Sha1, Hash)
|
|
|
|
Sha1.prototype.init = function () {
|
|
this._a = 0x67452301
|
|
this._b = 0xefcdab89
|
|
this._c = 0x98badcfe
|
|
this._d = 0x10325476
|
|
this._e = 0xc3d2e1f0
|
|
|
|
return this
|
|
}
|
|
|
|
function rotl1 (num) {
|
|
return (num << 1) | (num >>> 31)
|
|
}
|
|
|
|
function rotl5 (num) {
|
|
return (num << 5) | (num >>> 27)
|
|
}
|
|
|
|
function rotl30 (num) {
|
|
return (num << 30) | (num >>> 2)
|
|
}
|
|
|
|
function ft (s, b, c, d) {
|
|
if (s === 0) return (b & c) | ((~b) & d)
|
|
if (s === 2) return (b & c) | (b & d) | (c & d)
|
|
return b ^ c ^ d
|
|
}
|
|
|
|
Sha1.prototype._update = function (M) {
|
|
var W = this._w
|
|
|
|
var a = this._a | 0
|
|
var b = this._b | 0
|
|
var c = this._c | 0
|
|
var d = this._d | 0
|
|
var e = this._e | 0
|
|
|
|
for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4)
|
|
for (; i < 80; ++i) W[i] = rotl1(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16])
|
|
|
|
for (var j = 0; j < 80; ++j) {
|
|
var s = ~~(j / 20)
|
|
var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0
|
|
|
|
e = d
|
|
d = c
|
|
c = rotl30(b)
|
|
b = a
|
|
a = t
|
|
}
|
|
|
|
this._a = (a + this._a) | 0
|
|
this._b = (b + this._b) | 0
|
|
this._c = (c + this._c) | 0
|
|
this._d = (d + this._d) | 0
|
|
this._e = (e + this._e) | 0
|
|
}
|
|
|
|
Sha1.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(20)
|
|
|
|
H.writeInt32BE(this._a | 0, 0)
|
|
H.writeInt32BE(this._b | 0, 4)
|
|
H.writeInt32BE(this._c | 0, 8)
|
|
H.writeInt32BE(this._d | 0, 12)
|
|
H.writeInt32BE(this._e | 0, 16)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha1
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/sha.js/sha224.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/sha.js/sha224.js ***!
|
|
\***************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/**
|
|
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
|
|
* in FIPS 180-2
|
|
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
*
|
|
*/
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var Sha256 = __webpack_require__(/*! ./sha256 */ "./node_modules/sha.js/sha256.js")
|
|
var Hash = __webpack_require__(/*! ./hash */ "./node_modules/sha.js/hash.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var W = new Array(64)
|
|
|
|
function Sha224 () {
|
|
this.init()
|
|
|
|
this._w = W // new Array(64)
|
|
|
|
Hash.call(this, 64, 56)
|
|
}
|
|
|
|
inherits(Sha224, Sha256)
|
|
|
|
Sha224.prototype.init = function () {
|
|
this._a = 0xc1059ed8
|
|
this._b = 0x367cd507
|
|
this._c = 0x3070dd17
|
|
this._d = 0xf70e5939
|
|
this._e = 0xffc00b31
|
|
this._f = 0x68581511
|
|
this._g = 0x64f98fa7
|
|
this._h = 0xbefa4fa4
|
|
|
|
return this
|
|
}
|
|
|
|
Sha224.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(28)
|
|
|
|
H.writeInt32BE(this._a, 0)
|
|
H.writeInt32BE(this._b, 4)
|
|
H.writeInt32BE(this._c, 8)
|
|
H.writeInt32BE(this._d, 12)
|
|
H.writeInt32BE(this._e, 16)
|
|
H.writeInt32BE(this._f, 20)
|
|
H.writeInt32BE(this._g, 24)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha224
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/sha.js/sha256.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/sha.js/sha256.js ***!
|
|
\***************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/**
|
|
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
|
|
* in FIPS 180-2
|
|
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
*
|
|
*/
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var Hash = __webpack_require__(/*! ./hash */ "./node_modules/sha.js/hash.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var K = [
|
|
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
|
|
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
|
|
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
|
|
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
|
|
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
|
|
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
|
|
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
|
|
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
|
|
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
|
|
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
|
|
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
|
|
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
|
|
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
|
|
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
|
|
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
|
|
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
|
|
]
|
|
|
|
var W = new Array(64)
|
|
|
|
function Sha256 () {
|
|
this.init()
|
|
|
|
this._w = W // new Array(64)
|
|
|
|
Hash.call(this, 64, 56)
|
|
}
|
|
|
|
inherits(Sha256, Hash)
|
|
|
|
Sha256.prototype.init = function () {
|
|
this._a = 0x6a09e667
|
|
this._b = 0xbb67ae85
|
|
this._c = 0x3c6ef372
|
|
this._d = 0xa54ff53a
|
|
this._e = 0x510e527f
|
|
this._f = 0x9b05688c
|
|
this._g = 0x1f83d9ab
|
|
this._h = 0x5be0cd19
|
|
|
|
return this
|
|
}
|
|
|
|
function ch (x, y, z) {
|
|
return z ^ (x & (y ^ z))
|
|
}
|
|
|
|
function maj (x, y, z) {
|
|
return (x & y) | (z & (x | y))
|
|
}
|
|
|
|
function sigma0 (x) {
|
|
return (x >>> 2 | x << 30) ^ (x >>> 13 | x << 19) ^ (x >>> 22 | x << 10)
|
|
}
|
|
|
|
function sigma1 (x) {
|
|
return (x >>> 6 | x << 26) ^ (x >>> 11 | x << 21) ^ (x >>> 25 | x << 7)
|
|
}
|
|
|
|
function gamma0 (x) {
|
|
return (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ (x >>> 3)
|
|
}
|
|
|
|
function gamma1 (x) {
|
|
return (x >>> 17 | x << 15) ^ (x >>> 19 | x << 13) ^ (x >>> 10)
|
|
}
|
|
|
|
Sha256.prototype._update = function (M) {
|
|
var W = this._w
|
|
|
|
var a = this._a | 0
|
|
var b = this._b | 0
|
|
var c = this._c | 0
|
|
var d = this._d | 0
|
|
var e = this._e | 0
|
|
var f = this._f | 0
|
|
var g = this._g | 0
|
|
var h = this._h | 0
|
|
|
|
for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4)
|
|
for (; i < 64; ++i) W[i] = (gamma1(W[i - 2]) + W[i - 7] + gamma0(W[i - 15]) + W[i - 16]) | 0
|
|
|
|
for (var j = 0; j < 64; ++j) {
|
|
var T1 = (h + sigma1(e) + ch(e, f, g) + K[j] + W[j]) | 0
|
|
var T2 = (sigma0(a) + maj(a, b, c)) | 0
|
|
|
|
h = g
|
|
g = f
|
|
f = e
|
|
e = (d + T1) | 0
|
|
d = c
|
|
c = b
|
|
b = a
|
|
a = (T1 + T2) | 0
|
|
}
|
|
|
|
this._a = (a + this._a) | 0
|
|
this._b = (b + this._b) | 0
|
|
this._c = (c + this._c) | 0
|
|
this._d = (d + this._d) | 0
|
|
this._e = (e + this._e) | 0
|
|
this._f = (f + this._f) | 0
|
|
this._g = (g + this._g) | 0
|
|
this._h = (h + this._h) | 0
|
|
}
|
|
|
|
Sha256.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(32)
|
|
|
|
H.writeInt32BE(this._a, 0)
|
|
H.writeInt32BE(this._b, 4)
|
|
H.writeInt32BE(this._c, 8)
|
|
H.writeInt32BE(this._d, 12)
|
|
H.writeInt32BE(this._e, 16)
|
|
H.writeInt32BE(this._f, 20)
|
|
H.writeInt32BE(this._g, 24)
|
|
H.writeInt32BE(this._h, 28)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha256
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/sha.js/sha384.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/sha.js/sha384.js ***!
|
|
\***************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var SHA512 = __webpack_require__(/*! ./sha512 */ "./node_modules/sha.js/sha512.js")
|
|
var Hash = __webpack_require__(/*! ./hash */ "./node_modules/sha.js/hash.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var W = new Array(160)
|
|
|
|
function Sha384 () {
|
|
this.init()
|
|
this._w = W
|
|
|
|
Hash.call(this, 128, 112)
|
|
}
|
|
|
|
inherits(Sha384, SHA512)
|
|
|
|
Sha384.prototype.init = function () {
|
|
this._ah = 0xcbbb9d5d
|
|
this._bh = 0x629a292a
|
|
this._ch = 0x9159015a
|
|
this._dh = 0x152fecd8
|
|
this._eh = 0x67332667
|
|
this._fh = 0x8eb44a87
|
|
this._gh = 0xdb0c2e0d
|
|
this._hh = 0x47b5481d
|
|
|
|
this._al = 0xc1059ed8
|
|
this._bl = 0x367cd507
|
|
this._cl = 0x3070dd17
|
|
this._dl = 0xf70e5939
|
|
this._el = 0xffc00b31
|
|
this._fl = 0x68581511
|
|
this._gl = 0x64f98fa7
|
|
this._hl = 0xbefa4fa4
|
|
|
|
return this
|
|
}
|
|
|
|
Sha384.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(48)
|
|
|
|
function writeInt64BE (h, l, offset) {
|
|
H.writeInt32BE(h, offset)
|
|
H.writeInt32BE(l, offset + 4)
|
|
}
|
|
|
|
writeInt64BE(this._ah, this._al, 0)
|
|
writeInt64BE(this._bh, this._bl, 8)
|
|
writeInt64BE(this._ch, this._cl, 16)
|
|
writeInt64BE(this._dh, this._dl, 24)
|
|
writeInt64BE(this._eh, this._el, 32)
|
|
writeInt64BE(this._fh, this._fl, 40)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha384
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/sha.js/sha512.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/sha.js/sha512.js ***!
|
|
\***************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var Hash = __webpack_require__(/*! ./hash */ "./node_modules/sha.js/hash.js")
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer
|
|
|
|
var K = [
|
|
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
|
|
0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
|
|
0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
|
|
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
|
|
0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
|
|
0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
|
|
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
|
|
0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
|
|
0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
|
|
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
|
|
0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
|
|
0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
|
|
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
|
|
0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
|
|
0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
|
|
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
|
|
0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
|
|
0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
|
|
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
|
|
0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
|
|
0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
|
|
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
|
|
0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
|
|
0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
|
|
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
|
|
0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
|
|
0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
|
|
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
|
|
0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
|
|
0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
|
|
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
|
|
0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
|
|
0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
|
|
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
|
|
0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
|
|
0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
|
|
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
|
|
0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
|
|
0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
|
|
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
|
|
]
|
|
|
|
var W = new Array(160)
|
|
|
|
function Sha512 () {
|
|
this.init()
|
|
this._w = W
|
|
|
|
Hash.call(this, 128, 112)
|
|
}
|
|
|
|
inherits(Sha512, Hash)
|
|
|
|
Sha512.prototype.init = function () {
|
|
this._ah = 0x6a09e667
|
|
this._bh = 0xbb67ae85
|
|
this._ch = 0x3c6ef372
|
|
this._dh = 0xa54ff53a
|
|
this._eh = 0x510e527f
|
|
this._fh = 0x9b05688c
|
|
this._gh = 0x1f83d9ab
|
|
this._hh = 0x5be0cd19
|
|
|
|
this._al = 0xf3bcc908
|
|
this._bl = 0x84caa73b
|
|
this._cl = 0xfe94f82b
|
|
this._dl = 0x5f1d36f1
|
|
this._el = 0xade682d1
|
|
this._fl = 0x2b3e6c1f
|
|
this._gl = 0xfb41bd6b
|
|
this._hl = 0x137e2179
|
|
|
|
return this
|
|
}
|
|
|
|
function Ch (x, y, z) {
|
|
return z ^ (x & (y ^ z))
|
|
}
|
|
|
|
function maj (x, y, z) {
|
|
return (x & y) | (z & (x | y))
|
|
}
|
|
|
|
function sigma0 (x, xl) {
|
|
return (x >>> 28 | xl << 4) ^ (xl >>> 2 | x << 30) ^ (xl >>> 7 | x << 25)
|
|
}
|
|
|
|
function sigma1 (x, xl) {
|
|
return (x >>> 14 | xl << 18) ^ (x >>> 18 | xl << 14) ^ (xl >>> 9 | x << 23)
|
|
}
|
|
|
|
function Gamma0 (x, xl) {
|
|
return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7)
|
|
}
|
|
|
|
function Gamma0l (x, xl) {
|
|
return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7 | xl << 25)
|
|
}
|
|
|
|
function Gamma1 (x, xl) {
|
|
return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6)
|
|
}
|
|
|
|
function Gamma1l (x, xl) {
|
|
return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6 | xl << 26)
|
|
}
|
|
|
|
function getCarry (a, b) {
|
|
return (a >>> 0) < (b >>> 0) ? 1 : 0
|
|
}
|
|
|
|
Sha512.prototype._update = function (M) {
|
|
var W = this._w
|
|
|
|
var ah = this._ah | 0
|
|
var bh = this._bh | 0
|
|
var ch = this._ch | 0
|
|
var dh = this._dh | 0
|
|
var eh = this._eh | 0
|
|
var fh = this._fh | 0
|
|
var gh = this._gh | 0
|
|
var hh = this._hh | 0
|
|
|
|
var al = this._al | 0
|
|
var bl = this._bl | 0
|
|
var cl = this._cl | 0
|
|
var dl = this._dl | 0
|
|
var el = this._el | 0
|
|
var fl = this._fl | 0
|
|
var gl = this._gl | 0
|
|
var hl = this._hl | 0
|
|
|
|
for (var i = 0; i < 32; i += 2) {
|
|
W[i] = M.readInt32BE(i * 4)
|
|
W[i + 1] = M.readInt32BE(i * 4 + 4)
|
|
}
|
|
for (; i < 160; i += 2) {
|
|
var xh = W[i - 15 * 2]
|
|
var xl = W[i - 15 * 2 + 1]
|
|
var gamma0 = Gamma0(xh, xl)
|
|
var gamma0l = Gamma0l(xl, xh)
|
|
|
|
xh = W[i - 2 * 2]
|
|
xl = W[i - 2 * 2 + 1]
|
|
var gamma1 = Gamma1(xh, xl)
|
|
var gamma1l = Gamma1l(xl, xh)
|
|
|
|
// W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]
|
|
var Wi7h = W[i - 7 * 2]
|
|
var Wi7l = W[i - 7 * 2 + 1]
|
|
|
|
var Wi16h = W[i - 16 * 2]
|
|
var Wi16l = W[i - 16 * 2 + 1]
|
|
|
|
var Wil = (gamma0l + Wi7l) | 0
|
|
var Wih = (gamma0 + Wi7h + getCarry(Wil, gamma0l)) | 0
|
|
Wil = (Wil + gamma1l) | 0
|
|
Wih = (Wih + gamma1 + getCarry(Wil, gamma1l)) | 0
|
|
Wil = (Wil + Wi16l) | 0
|
|
Wih = (Wih + Wi16h + getCarry(Wil, Wi16l)) | 0
|
|
|
|
W[i] = Wih
|
|
W[i + 1] = Wil
|
|
}
|
|
|
|
for (var j = 0; j < 160; j += 2) {
|
|
Wih = W[j]
|
|
Wil = W[j + 1]
|
|
|
|
var majh = maj(ah, bh, ch)
|
|
var majl = maj(al, bl, cl)
|
|
|
|
var sigma0h = sigma0(ah, al)
|
|
var sigma0l = sigma0(al, ah)
|
|
var sigma1h = sigma1(eh, el)
|
|
var sigma1l = sigma1(el, eh)
|
|
|
|
// t1 = h + sigma1 + ch + K[j] + W[j]
|
|
var Kih = K[j]
|
|
var Kil = K[j + 1]
|
|
|
|
var chh = Ch(eh, fh, gh)
|
|
var chl = Ch(el, fl, gl)
|
|
|
|
var t1l = (hl + sigma1l) | 0
|
|
var t1h = (hh + sigma1h + getCarry(t1l, hl)) | 0
|
|
t1l = (t1l + chl) | 0
|
|
t1h = (t1h + chh + getCarry(t1l, chl)) | 0
|
|
t1l = (t1l + Kil) | 0
|
|
t1h = (t1h + Kih + getCarry(t1l, Kil)) | 0
|
|
t1l = (t1l + Wil) | 0
|
|
t1h = (t1h + Wih + getCarry(t1l, Wil)) | 0
|
|
|
|
// t2 = sigma0 + maj
|
|
var t2l = (sigma0l + majl) | 0
|
|
var t2h = (sigma0h + majh + getCarry(t2l, sigma0l)) | 0
|
|
|
|
hh = gh
|
|
hl = gl
|
|
gh = fh
|
|
gl = fl
|
|
fh = eh
|
|
fl = el
|
|
el = (dl + t1l) | 0
|
|
eh = (dh + t1h + getCarry(el, dl)) | 0
|
|
dh = ch
|
|
dl = cl
|
|
ch = bh
|
|
cl = bl
|
|
bh = ah
|
|
bl = al
|
|
al = (t1l + t2l) | 0
|
|
ah = (t1h + t2h + getCarry(al, t1l)) | 0
|
|
}
|
|
|
|
this._al = (this._al + al) | 0
|
|
this._bl = (this._bl + bl) | 0
|
|
this._cl = (this._cl + cl) | 0
|
|
this._dl = (this._dl + dl) | 0
|
|
this._el = (this._el + el) | 0
|
|
this._fl = (this._fl + fl) | 0
|
|
this._gl = (this._gl + gl) | 0
|
|
this._hl = (this._hl + hl) | 0
|
|
|
|
this._ah = (this._ah + ah + getCarry(this._al, al)) | 0
|
|
this._bh = (this._bh + bh + getCarry(this._bl, bl)) | 0
|
|
this._ch = (this._ch + ch + getCarry(this._cl, cl)) | 0
|
|
this._dh = (this._dh + dh + getCarry(this._dl, dl)) | 0
|
|
this._eh = (this._eh + eh + getCarry(this._el, el)) | 0
|
|
this._fh = (this._fh + fh + getCarry(this._fl, fl)) | 0
|
|
this._gh = (this._gh + gh + getCarry(this._gl, gl)) | 0
|
|
this._hh = (this._hh + hh + getCarry(this._hl, hl)) | 0
|
|
}
|
|
|
|
Sha512.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(64)
|
|
|
|
function writeInt64BE (h, l, offset) {
|
|
H.writeInt32BE(h, offset)
|
|
H.writeInt32BE(l, offset + 4)
|
|
}
|
|
|
|
writeInt64BE(this._ah, this._al, 0)
|
|
writeInt64BE(this._bh, this._bl, 8)
|
|
writeInt64BE(this._ch, this._cl, 16)
|
|
writeInt64BE(this._dh, this._dl, 24)
|
|
writeInt64BE(this._eh, this._el, 32)
|
|
writeInt64BE(this._fh, this._fl, 40)
|
|
writeInt64BE(this._gh, this._gl, 48)
|
|
writeInt64BE(this._hh, this._hl, 56)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha512
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/simple-concat/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/simple-concat/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! simple-concat. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
module.exports = function (stream, cb) {
|
|
var chunks = []
|
|
stream.on('data', function (chunk) {
|
|
chunks.push(chunk)
|
|
})
|
|
stream.once('end', function () {
|
|
if (cb) cb(null, Buffer.concat(chunks))
|
|
cb = null
|
|
})
|
|
stream.once('error', function (err) {
|
|
if (cb) cb(err)
|
|
cb = null
|
|
})
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/simple-get/index.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/simple-get/index.js ***!
|
|
\******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! simple-get. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
module.exports = simpleGet
|
|
|
|
const concat = __webpack_require__(/*! simple-concat */ "./node_modules/simple-concat/index.js")
|
|
const decompressResponse = __webpack_require__(/*! decompress-response */ "?45bd") // excluded from browser build
|
|
const http = __webpack_require__(/*! http */ "./node_modules/stream-http/index.js")
|
|
const https = __webpack_require__(/*! https */ "./node_modules/https-browserify/index.js")
|
|
const once = __webpack_require__(/*! once */ "./node_modules/once/once.js")
|
|
const querystring = __webpack_require__(/*! querystring */ "./node_modules/querystring/index.js")
|
|
const url = __webpack_require__(/*! url */ "./node_modules/url/url.js")
|
|
|
|
const isStream = o => o !== null && typeof o === 'object' && typeof o.pipe === 'function'
|
|
|
|
function simpleGet (opts, cb) {
|
|
opts = Object.assign({ maxRedirects: 10 }, typeof opts === 'string' ? { url: opts } : opts)
|
|
cb = once(cb)
|
|
|
|
if (opts.url) {
|
|
const { hostname, port, protocol, auth, path } = url.parse(opts.url) // eslint-disable-line node/no-deprecated-api
|
|
delete opts.url
|
|
if (!hostname && !port && !protocol && !auth) opts.path = path // Relative redirect
|
|
else Object.assign(opts, { hostname, port, protocol, auth, path }) // Absolute redirect
|
|
}
|
|
|
|
const headers = { 'accept-encoding': 'gzip, deflate' }
|
|
if (opts.headers) Object.keys(opts.headers).forEach(k => (headers[k.toLowerCase()] = opts.headers[k]))
|
|
opts.headers = headers
|
|
|
|
let body
|
|
if (opts.body) {
|
|
body = opts.json && !isStream(opts.body) ? JSON.stringify(opts.body) : opts.body
|
|
} else if (opts.form) {
|
|
body = typeof opts.form === 'string' ? opts.form : querystring.stringify(opts.form)
|
|
opts.headers['content-type'] = 'application/x-www-form-urlencoded'
|
|
}
|
|
|
|
if (body) {
|
|
if (!opts.method) opts.method = 'POST'
|
|
if (!isStream(body)) opts.headers['content-length'] = Buffer.byteLength(body)
|
|
if (opts.json && !opts.form) opts.headers['content-type'] = 'application/json'
|
|
}
|
|
delete opts.body; delete opts.form
|
|
|
|
if (opts.json) opts.headers.accept = 'application/json'
|
|
if (opts.method) opts.method = opts.method.toUpperCase()
|
|
|
|
const protocol = opts.protocol === 'https:' ? https : http // Support http/https urls
|
|
const req = protocol.request(opts, res => {
|
|
if (opts.followRedirects !== false && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
opts.url = res.headers.location // Follow 3xx redirects
|
|
delete opts.headers.host // Discard `host` header on redirect (see #32)
|
|
res.resume() // Discard response
|
|
|
|
if (opts.method === 'POST' && [301, 302].includes(res.statusCode)) {
|
|
opts.method = 'GET' // On 301/302 redirect, change POST to GET (see #35)
|
|
delete opts.headers['content-length']; delete opts.headers['content-type']
|
|
}
|
|
|
|
if (opts.maxRedirects-- === 0) return cb(new Error('too many redirects'))
|
|
else return simpleGet(opts, cb)
|
|
}
|
|
|
|
const tryUnzip = typeof decompressResponse === 'function' && opts.method !== 'HEAD'
|
|
cb(null, tryUnzip ? decompressResponse(res) : res)
|
|
})
|
|
req.on('timeout', () => {
|
|
req.abort()
|
|
cb(new Error('Request timed out'))
|
|
})
|
|
req.on('error', cb)
|
|
|
|
if (isStream(body)) body.on('error', cb).pipe(req)
|
|
else req.end(body)
|
|
|
|
return req
|
|
}
|
|
|
|
simpleGet.concat = (opts, cb) => {
|
|
return simpleGet(opts, (err, res) => {
|
|
if (err) return cb(err)
|
|
concat(res, (err, data) => {
|
|
if (err) return cb(err)
|
|
if (opts.json) {
|
|
try {
|
|
data = JSON.parse(data.toString())
|
|
} catch (err) {
|
|
return cb(err, res, data)
|
|
}
|
|
}
|
|
cb(null, res, data)
|
|
})
|
|
})
|
|
}
|
|
|
|
;['get', 'post', 'put', 'patch', 'head', 'delete'].forEach(method => {
|
|
simpleGet[method] = (opts, cb) => {
|
|
if (typeof opts === 'string') opts = { url: opts }
|
|
return simpleGet(Object.assign({ method: method.toUpperCase() }, opts), cb)
|
|
}
|
|
})
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/simple-peer/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/simple-peer/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
/*! simple-peer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('simple-peer')
|
|
const getBrowserRTC = __webpack_require__(/*! get-browser-rtc */ "./node_modules/get-browser-rtc/index.js")
|
|
const randombytes = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js")
|
|
const stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js") // TODO: remove when Node 10 is not supported
|
|
const errCode = __webpack_require__(/*! err-code */ "./node_modules/err-code/index.js")
|
|
const { Buffer } = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js")
|
|
|
|
const MAX_BUFFERED_AMOUNT = 64 * 1024
|
|
const ICECOMPLETE_TIMEOUT = 5 * 1000
|
|
const CHANNEL_CLOSING_TIMEOUT = 5 * 1000
|
|
|
|
// HACK: Filter trickle lines when trickle is disabled #354
|
|
function filterTrickle (sdp) {
|
|
return sdp.replace(/a=ice-options:trickle\s\n/g, '')
|
|
}
|
|
|
|
function warn (message) {
|
|
console.warn(message)
|
|
}
|
|
|
|
/**
|
|
* WebRTC peer connection. Same API as node core `net.Socket`, plus a few extra methods.
|
|
* Duplex stream.
|
|
* @param {Object} opts
|
|
*/
|
|
class Peer extends stream.Duplex {
|
|
constructor (opts) {
|
|
opts = Object.assign({
|
|
allowHalfOpen: false
|
|
}, opts)
|
|
|
|
super(opts)
|
|
|
|
this._id = randombytes(4).toString('hex').slice(0, 7)
|
|
this._debug('new peer %o', opts)
|
|
|
|
this.channelName = opts.initiator
|
|
? opts.channelName || randombytes(20).toString('hex')
|
|
: null
|
|
|
|
this.initiator = opts.initiator || false
|
|
this.channelConfig = opts.channelConfig || Peer.channelConfig
|
|
this.channelNegotiated = this.channelConfig.negotiated
|
|
this.config = Object.assign({}, Peer.config, opts.config)
|
|
this.offerOptions = opts.offerOptions || {}
|
|
this.answerOptions = opts.answerOptions || {}
|
|
this.sdpTransform = opts.sdpTransform || (sdp => sdp)
|
|
this.streams = opts.streams || (opts.stream ? [opts.stream] : []) // support old "stream" option
|
|
this.trickle = opts.trickle !== undefined ? opts.trickle : true
|
|
this.allowHalfTrickle = opts.allowHalfTrickle !== undefined ? opts.allowHalfTrickle : false
|
|
this.iceCompleteTimeout = opts.iceCompleteTimeout || ICECOMPLETE_TIMEOUT
|
|
|
|
this.destroyed = false
|
|
this.destroying = false
|
|
this._connected = false
|
|
|
|
this.remoteAddress = undefined
|
|
this.remoteFamily = undefined
|
|
this.remotePort = undefined
|
|
this.localAddress = undefined
|
|
this.localFamily = undefined
|
|
this.localPort = undefined
|
|
|
|
this._wrtc = (opts.wrtc && typeof opts.wrtc === 'object')
|
|
? opts.wrtc
|
|
: getBrowserRTC()
|
|
|
|
if (!this._wrtc) {
|
|
if (typeof window === 'undefined') {
|
|
throw errCode(new Error('No WebRTC support: Specify `opts.wrtc` option in this environment'), 'ERR_WEBRTC_SUPPORT')
|
|
} else {
|
|
throw errCode(new Error('No WebRTC support: Not a supported browser'), 'ERR_WEBRTC_SUPPORT')
|
|
}
|
|
}
|
|
|
|
this._pcReady = false
|
|
this._channelReady = false
|
|
this._iceComplete = false // ice candidate trickle done (got null candidate)
|
|
this._iceCompleteTimer = null // send an offer/answer anyway after some timeout
|
|
this._channel = null
|
|
this._pendingCandidates = []
|
|
|
|
this._isNegotiating = false // is this peer waiting for negotiation to complete?
|
|
this._firstNegotiation = true
|
|
this._batchedNegotiation = false // batch synchronous negotiations
|
|
this._queuedNegotiation = false // is there a queued negotiation request?
|
|
this._sendersAwaitingStable = []
|
|
this._senderMap = new Map()
|
|
this._closingInterval = null
|
|
|
|
this._remoteTracks = []
|
|
this._remoteStreams = []
|
|
|
|
this._chunk = null
|
|
this._cb = null
|
|
this._interval = null
|
|
|
|
try {
|
|
this._pc = new (this._wrtc.RTCPeerConnection)(this.config)
|
|
} catch (err) {
|
|
this.destroy(errCode(err, 'ERR_PC_CONSTRUCTOR'))
|
|
return
|
|
}
|
|
|
|
// We prefer feature detection whenever possible, but sometimes that's not
|
|
// possible for certain implementations.
|
|
this._isReactNativeWebrtc = typeof this._pc._peerConnectionId === 'number'
|
|
|
|
this._pc.oniceconnectionstatechange = () => {
|
|
this._onIceStateChange()
|
|
}
|
|
this._pc.onicegatheringstatechange = () => {
|
|
this._onIceStateChange()
|
|
}
|
|
this._pc.onconnectionstatechange = () => {
|
|
this._onConnectionStateChange()
|
|
}
|
|
this._pc.onsignalingstatechange = () => {
|
|
this._onSignalingStateChange()
|
|
}
|
|
this._pc.onicecandidate = event => {
|
|
this._onIceCandidate(event)
|
|
}
|
|
|
|
// HACK: Fix for odd Firefox behavior, see: https://github.com/feross/simple-peer/pull/783
|
|
if (typeof this._pc.peerIdentity === 'object') {
|
|
this._pc.peerIdentity.catch(err => {
|
|
this.destroy(errCode(err, 'ERR_PC_PEER_IDENTITY'))
|
|
})
|
|
}
|
|
|
|
// Other spec events, unused by this implementation:
|
|
// - onconnectionstatechange
|
|
// - onicecandidateerror
|
|
// - onfingerprintfailure
|
|
// - onnegotiationneeded
|
|
|
|
if (this.initiator || this.channelNegotiated) {
|
|
this._setupData({
|
|
channel: this._pc.createDataChannel(this.channelName, this.channelConfig)
|
|
})
|
|
} else {
|
|
this._pc.ondatachannel = event => {
|
|
this._setupData(event)
|
|
}
|
|
}
|
|
|
|
if (this.streams) {
|
|
this.streams.forEach(stream => {
|
|
this.addStream(stream)
|
|
})
|
|
}
|
|
this._pc.ontrack = event => {
|
|
this._onTrack(event)
|
|
}
|
|
|
|
this._debug('initial negotiation')
|
|
this._needsNegotiation()
|
|
|
|
this._onFinishBound = () => {
|
|
this._onFinish()
|
|
}
|
|
this.once('finish', this._onFinishBound)
|
|
}
|
|
|
|
get bufferSize () {
|
|
return (this._channel && this._channel.bufferedAmount) || 0
|
|
}
|
|
|
|
// HACK: it's possible channel.readyState is "closing" before peer.destroy() fires
|
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=882743
|
|
get connected () {
|
|
return (this._connected && this._channel.readyState === 'open')
|
|
}
|
|
|
|
address () {
|
|
return { port: this.localPort, family: this.localFamily, address: this.localAddress }
|
|
}
|
|
|
|
signal (data) {
|
|
if (this.destroying) return
|
|
if (this.destroyed) throw errCode(new Error('cannot signal after peer is destroyed'), 'ERR_DESTROYED')
|
|
if (typeof data === 'string') {
|
|
try {
|
|
data = JSON.parse(data)
|
|
} catch (err) {
|
|
data = {}
|
|
}
|
|
}
|
|
this._debug('signal()')
|
|
|
|
if (data.renegotiate && this.initiator) {
|
|
this._debug('got request to renegotiate')
|
|
this._needsNegotiation()
|
|
}
|
|
if (data.transceiverRequest && this.initiator) {
|
|
this._debug('got request for transceiver')
|
|
this.addTransceiver(data.transceiverRequest.kind, data.transceiverRequest.init)
|
|
}
|
|
if (data.candidate) {
|
|
if (this._pc.remoteDescription && this._pc.remoteDescription.type) {
|
|
this._addIceCandidate(data.candidate)
|
|
} else {
|
|
this._pendingCandidates.push(data.candidate)
|
|
}
|
|
}
|
|
if (data.sdp) {
|
|
this._pc.setRemoteDescription(new (this._wrtc.RTCSessionDescription)(data))
|
|
.then(() => {
|
|
if (this.destroyed) return
|
|
|
|
this._pendingCandidates.forEach(candidate => {
|
|
this._addIceCandidate(candidate)
|
|
})
|
|
this._pendingCandidates = []
|
|
|
|
if (this._pc.remoteDescription.type === 'offer') this._createAnswer()
|
|
})
|
|
.catch(err => {
|
|
this.destroy(errCode(err, 'ERR_SET_REMOTE_DESCRIPTION'))
|
|
})
|
|
}
|
|
if (!data.sdp && !data.candidate && !data.renegotiate && !data.transceiverRequest) {
|
|
this.destroy(errCode(new Error('signal() called with invalid signal data'), 'ERR_SIGNALING'))
|
|
}
|
|
}
|
|
|
|
_addIceCandidate (candidate) {
|
|
const iceCandidateObj = new this._wrtc.RTCIceCandidate(candidate)
|
|
this._pc.addIceCandidate(iceCandidateObj)
|
|
.catch(err => {
|
|
if (!iceCandidateObj.address || iceCandidateObj.address.endsWith('.local')) {
|
|
warn('Ignoring unsupported ICE candidate.')
|
|
} else {
|
|
this.destroy(errCode(err, 'ERR_ADD_ICE_CANDIDATE'))
|
|
}
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Send text/binary data to the remote peer.
|
|
* @param {ArrayBufferView|ArrayBuffer|Buffer|string|Blob} chunk
|
|
*/
|
|
send (chunk) {
|
|
if (this.destroying) return
|
|
if (this.destroyed) throw errCode(new Error('cannot send after peer is destroyed'), 'ERR_DESTROYED')
|
|
this._channel.send(chunk)
|
|
}
|
|
|
|
/**
|
|
* Add a Transceiver to the connection.
|
|
* @param {String} kind
|
|
* @param {Object} init
|
|
*/
|
|
addTransceiver (kind, init) {
|
|
if (this.destroying) return
|
|
if (this.destroyed) throw errCode(new Error('cannot addTransceiver after peer is destroyed'), 'ERR_DESTROYED')
|
|
this._debug('addTransceiver()')
|
|
|
|
if (this.initiator) {
|
|
try {
|
|
this._pc.addTransceiver(kind, init)
|
|
this._needsNegotiation()
|
|
} catch (err) {
|
|
this.destroy(errCode(err, 'ERR_ADD_TRANSCEIVER'))
|
|
}
|
|
} else {
|
|
this.emit('signal', { // request initiator to renegotiate
|
|
type: 'transceiverRequest',
|
|
transceiverRequest: { kind, init }
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add a MediaStream to the connection.
|
|
* @param {MediaStream} stream
|
|
*/
|
|
addStream (stream) {
|
|
if (this.destroying) return
|
|
if (this.destroyed) throw errCode(new Error('cannot addStream after peer is destroyed'), 'ERR_DESTROYED')
|
|
this._debug('addStream()')
|
|
|
|
stream.getTracks().forEach(track => {
|
|
this.addTrack(track, stream)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Add a MediaStreamTrack to the connection.
|
|
* @param {MediaStreamTrack} track
|
|
* @param {MediaStream} stream
|
|
*/
|
|
addTrack (track, stream) {
|
|
if (this.destroying) return
|
|
if (this.destroyed) throw errCode(new Error('cannot addTrack after peer is destroyed'), 'ERR_DESTROYED')
|
|
this._debug('addTrack()')
|
|
|
|
const submap = this._senderMap.get(track) || new Map() // nested Maps map [track, stream] to sender
|
|
let sender = submap.get(stream)
|
|
if (!sender) {
|
|
sender = this._pc.addTrack(track, stream)
|
|
submap.set(stream, sender)
|
|
this._senderMap.set(track, submap)
|
|
this._needsNegotiation()
|
|
} else if (sender.removed) {
|
|
throw errCode(new Error('Track has been removed. You should enable/disable tracks that you want to re-add.'), 'ERR_SENDER_REMOVED')
|
|
} else {
|
|
throw errCode(new Error('Track has already been added to that stream.'), 'ERR_SENDER_ALREADY_ADDED')
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Replace a MediaStreamTrack by another in the connection.
|
|
* @param {MediaStreamTrack} oldTrack
|
|
* @param {MediaStreamTrack} newTrack
|
|
* @param {MediaStream} stream
|
|
*/
|
|
replaceTrack (oldTrack, newTrack, stream) {
|
|
if (this.destroying) return
|
|
if (this.destroyed) throw errCode(new Error('cannot replaceTrack after peer is destroyed'), 'ERR_DESTROYED')
|
|
this._debug('replaceTrack()')
|
|
|
|
const submap = this._senderMap.get(oldTrack)
|
|
const sender = submap ? submap.get(stream) : null
|
|
if (!sender) {
|
|
throw errCode(new Error('Cannot replace track that was never added.'), 'ERR_TRACK_NOT_ADDED')
|
|
}
|
|
if (newTrack) this._senderMap.set(newTrack, submap)
|
|
|
|
if (sender.replaceTrack != null) {
|
|
sender.replaceTrack(newTrack)
|
|
} else {
|
|
this.destroy(errCode(new Error('replaceTrack is not supported in this browser'), 'ERR_UNSUPPORTED_REPLACETRACK'))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove a MediaStreamTrack from the connection.
|
|
* @param {MediaStreamTrack} track
|
|
* @param {MediaStream} stream
|
|
*/
|
|
removeTrack (track, stream) {
|
|
if (this.destroying) return
|
|
if (this.destroyed) throw errCode(new Error('cannot removeTrack after peer is destroyed'), 'ERR_DESTROYED')
|
|
this._debug('removeSender()')
|
|
|
|
const submap = this._senderMap.get(track)
|
|
const sender = submap ? submap.get(stream) : null
|
|
if (!sender) {
|
|
throw errCode(new Error('Cannot remove track that was never added.'), 'ERR_TRACK_NOT_ADDED')
|
|
}
|
|
try {
|
|
sender.removed = true
|
|
this._pc.removeTrack(sender)
|
|
} catch (err) {
|
|
if (err.name === 'NS_ERROR_UNEXPECTED') {
|
|
this._sendersAwaitingStable.push(sender) // HACK: Firefox must wait until (signalingState === stable) https://bugzilla.mozilla.org/show_bug.cgi?id=1133874
|
|
} else {
|
|
this.destroy(errCode(err, 'ERR_REMOVE_TRACK'))
|
|
}
|
|
}
|
|
this._needsNegotiation()
|
|
}
|
|
|
|
/**
|
|
* Remove a MediaStream from the connection.
|
|
* @param {MediaStream} stream
|
|
*/
|
|
removeStream (stream) {
|
|
if (this.destroying) return
|
|
if (this.destroyed) throw errCode(new Error('cannot removeStream after peer is destroyed'), 'ERR_DESTROYED')
|
|
this._debug('removeSenders()')
|
|
|
|
stream.getTracks().forEach(track => {
|
|
this.removeTrack(track, stream)
|
|
})
|
|
}
|
|
|
|
_needsNegotiation () {
|
|
this._debug('_needsNegotiation')
|
|
if (this._batchedNegotiation) return // batch synchronous renegotiations
|
|
this._batchedNegotiation = true
|
|
queueMicrotask(() => {
|
|
this._batchedNegotiation = false
|
|
if (this.initiator || !this._firstNegotiation) {
|
|
this._debug('starting batched negotiation')
|
|
this.negotiate()
|
|
} else {
|
|
this._debug('non-initiator initial negotiation request discarded')
|
|
}
|
|
this._firstNegotiation = false
|
|
})
|
|
}
|
|
|
|
negotiate () {
|
|
if (this.destroying) return
|
|
if (this.destroyed) throw errCode(new Error('cannot negotiate after peer is destroyed'), 'ERR_DESTROYED')
|
|
|
|
if (this.initiator) {
|
|
if (this._isNegotiating) {
|
|
this._queuedNegotiation = true
|
|
this._debug('already negotiating, queueing')
|
|
} else {
|
|
this._debug('start negotiation')
|
|
setTimeout(() => { // HACK: Chrome crashes if we immediately call createOffer
|
|
this._createOffer()
|
|
}, 0)
|
|
}
|
|
} else {
|
|
if (this._isNegotiating) {
|
|
this._queuedNegotiation = true
|
|
this._debug('already negotiating, queueing')
|
|
} else {
|
|
this._debug('requesting negotiation from initiator')
|
|
this.emit('signal', { // request initiator to renegotiate
|
|
type: 'renegotiate',
|
|
renegotiate: true
|
|
})
|
|
}
|
|
}
|
|
this._isNegotiating = true
|
|
}
|
|
|
|
// TODO: Delete this method once readable-stream is updated to contain a default
|
|
// implementation of destroy() that automatically calls _destroy()
|
|
// See: https://github.com/nodejs/readable-stream/issues/283
|
|
destroy (err) {
|
|
this._destroy(err, () => {})
|
|
}
|
|
|
|
_destroy (err, cb) {
|
|
if (this.destroyed || this.destroying) return
|
|
this.destroying = true
|
|
|
|
this._debug('destroying (error: %s)', err && (err.message || err))
|
|
|
|
queueMicrotask(() => { // allow events concurrent with the call to _destroy() to fire (see #692)
|
|
this.destroyed = true
|
|
this.destroying = false
|
|
|
|
this._debug('destroy (error: %s)', err && (err.message || err))
|
|
|
|
this.readable = this.writable = false
|
|
|
|
if (!this._readableState.ended) this.push(null)
|
|
if (!this._writableState.finished) this.end()
|
|
|
|
this._connected = false
|
|
this._pcReady = false
|
|
this._channelReady = false
|
|
this._remoteTracks = null
|
|
this._remoteStreams = null
|
|
this._senderMap = null
|
|
|
|
clearInterval(this._closingInterval)
|
|
this._closingInterval = null
|
|
|
|
clearInterval(this._interval)
|
|
this._interval = null
|
|
this._chunk = null
|
|
this._cb = null
|
|
|
|
if (this._onFinishBound) this.removeListener('finish', this._onFinishBound)
|
|
this._onFinishBound = null
|
|
|
|
if (this._channel) {
|
|
try {
|
|
this._channel.close()
|
|
} catch (err) {}
|
|
|
|
// allow events concurrent with destruction to be handled
|
|
this._channel.onmessage = null
|
|
this._channel.onopen = null
|
|
this._channel.onclose = null
|
|
this._channel.onerror = null
|
|
}
|
|
if (this._pc) {
|
|
try {
|
|
this._pc.close()
|
|
} catch (err) {}
|
|
|
|
// allow events concurrent with destruction to be handled
|
|
this._pc.oniceconnectionstatechange = null
|
|
this._pc.onicegatheringstatechange = null
|
|
this._pc.onsignalingstatechange = null
|
|
this._pc.onicecandidate = null
|
|
this._pc.ontrack = null
|
|
this._pc.ondatachannel = null
|
|
}
|
|
this._pc = null
|
|
this._channel = null
|
|
|
|
if (err) this.emit('error', err)
|
|
this.emit('close')
|
|
cb()
|
|
})
|
|
}
|
|
|
|
_setupData (event) {
|
|
if (!event.channel) {
|
|
// In some situations `pc.createDataChannel()` returns `undefined` (in wrtc),
|
|
// which is invalid behavior. Handle it gracefully.
|
|
// See: https://github.com/feross/simple-peer/issues/163
|
|
return this.destroy(errCode(new Error('Data channel event is missing `channel` property'), 'ERR_DATA_CHANNEL'))
|
|
}
|
|
|
|
this._channel = event.channel
|
|
this._channel.binaryType = 'arraybuffer'
|
|
|
|
if (typeof this._channel.bufferedAmountLowThreshold === 'number') {
|
|
this._channel.bufferedAmountLowThreshold = MAX_BUFFERED_AMOUNT
|
|
}
|
|
|
|
this.channelName = this._channel.label
|
|
|
|
this._channel.onmessage = event => {
|
|
this._onChannelMessage(event)
|
|
}
|
|
this._channel.onbufferedamountlow = () => {
|
|
this._onChannelBufferedAmountLow()
|
|
}
|
|
this._channel.onopen = () => {
|
|
this._onChannelOpen()
|
|
}
|
|
this._channel.onclose = () => {
|
|
this._onChannelClose()
|
|
}
|
|
this._channel.onerror = event => {
|
|
const err = event.error instanceof Error
|
|
? event.error
|
|
: new Error(`Datachannel error: ${event.message} ${event.filename}:${event.lineno}:${event.colno}`)
|
|
this.destroy(errCode(err, 'ERR_DATA_CHANNEL'))
|
|
}
|
|
|
|
// HACK: Chrome will sometimes get stuck in readyState "closing", let's check for this condition
|
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=882743
|
|
let isClosing = false
|
|
this._closingInterval = setInterval(() => { // No "onclosing" event
|
|
if (this._channel && this._channel.readyState === 'closing') {
|
|
if (isClosing) this._onChannelClose() // closing timed out: equivalent to onclose firing
|
|
isClosing = true
|
|
} else {
|
|
isClosing = false
|
|
}
|
|
}, CHANNEL_CLOSING_TIMEOUT)
|
|
}
|
|
|
|
_read () {}
|
|
|
|
_write (chunk, encoding, cb) {
|
|
if (this.destroyed) return cb(errCode(new Error('cannot write after peer is destroyed'), 'ERR_DATA_CHANNEL'))
|
|
|
|
if (this._connected) {
|
|
try {
|
|
this.send(chunk)
|
|
} catch (err) {
|
|
return this.destroy(errCode(err, 'ERR_DATA_CHANNEL'))
|
|
}
|
|
if (this._channel.bufferedAmount > MAX_BUFFERED_AMOUNT) {
|
|
this._debug('start backpressure: bufferedAmount %d', this._channel.bufferedAmount)
|
|
this._cb = cb
|
|
} else {
|
|
cb(null)
|
|
}
|
|
} else {
|
|
this._debug('write before connect')
|
|
this._chunk = chunk
|
|
this._cb = cb
|
|
}
|
|
}
|
|
|
|
// When stream finishes writing, close socket. Half open connections are not
|
|
// supported.
|
|
_onFinish () {
|
|
if (this.destroyed) return
|
|
|
|
// Wait a bit before destroying so the socket flushes.
|
|
// TODO: is there a more reliable way to accomplish this?
|
|
const destroySoon = () => {
|
|
setTimeout(() => this.destroy(), 1000)
|
|
}
|
|
|
|
if (this._connected) {
|
|
destroySoon()
|
|
} else {
|
|
this.once('connect', destroySoon)
|
|
}
|
|
}
|
|
|
|
_startIceCompleteTimeout () {
|
|
if (this.destroyed) return
|
|
if (this._iceCompleteTimer) return
|
|
this._debug('started iceComplete timeout')
|
|
this._iceCompleteTimer = setTimeout(() => {
|
|
if (!this._iceComplete) {
|
|
this._iceComplete = true
|
|
this._debug('iceComplete timeout completed')
|
|
this.emit('iceTimeout')
|
|
this.emit('_iceComplete')
|
|
}
|
|
}, this.iceCompleteTimeout)
|
|
}
|
|
|
|
_createOffer () {
|
|
if (this.destroyed) return
|
|
|
|
this._pc.createOffer(this.offerOptions)
|
|
.then(offer => {
|
|
if (this.destroyed) return
|
|
if (!this.trickle && !this.allowHalfTrickle) offer.sdp = filterTrickle(offer.sdp)
|
|
offer.sdp = this.sdpTransform(offer.sdp)
|
|
|
|
const sendOffer = () => {
|
|
if (this.destroyed) return
|
|
const signal = this._pc.localDescription || offer
|
|
this._debug('signal')
|
|
this.emit('signal', {
|
|
type: signal.type,
|
|
sdp: signal.sdp
|
|
})
|
|
}
|
|
|
|
const onSuccess = () => {
|
|
this._debug('createOffer success')
|
|
if (this.destroyed) return
|
|
if (this.trickle || this._iceComplete) sendOffer()
|
|
else this.once('_iceComplete', sendOffer) // wait for candidates
|
|
}
|
|
|
|
const onError = err => {
|
|
this.destroy(errCode(err, 'ERR_SET_LOCAL_DESCRIPTION'))
|
|
}
|
|
|
|
this._pc.setLocalDescription(offer)
|
|
.then(onSuccess)
|
|
.catch(onError)
|
|
})
|
|
.catch(err => {
|
|
this.destroy(errCode(err, 'ERR_CREATE_OFFER'))
|
|
})
|
|
}
|
|
|
|
_requestMissingTransceivers () {
|
|
if (this._pc.getTransceivers) {
|
|
this._pc.getTransceivers().forEach(transceiver => {
|
|
if (!transceiver.mid && transceiver.sender.track && !transceiver.requested) {
|
|
transceiver.requested = true // HACK: Safari returns negotiated transceivers with a null mid
|
|
this.addTransceiver(transceiver.sender.track.kind)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
_createAnswer () {
|
|
if (this.destroyed) return
|
|
|
|
this._pc.createAnswer(this.answerOptions)
|
|
.then(answer => {
|
|
if (this.destroyed) return
|
|
if (!this.trickle && !this.allowHalfTrickle) answer.sdp = filterTrickle(answer.sdp)
|
|
answer.sdp = this.sdpTransform(answer.sdp)
|
|
|
|
const sendAnswer = () => {
|
|
if (this.destroyed) return
|
|
const signal = this._pc.localDescription || answer
|
|
this._debug('signal')
|
|
this.emit('signal', {
|
|
type: signal.type,
|
|
sdp: signal.sdp
|
|
})
|
|
if (!this.initiator) this._requestMissingTransceivers()
|
|
}
|
|
|
|
const onSuccess = () => {
|
|
if (this.destroyed) return
|
|
if (this.trickle || this._iceComplete) sendAnswer()
|
|
else this.once('_iceComplete', sendAnswer)
|
|
}
|
|
|
|
const onError = err => {
|
|
this.destroy(errCode(err, 'ERR_SET_LOCAL_DESCRIPTION'))
|
|
}
|
|
|
|
this._pc.setLocalDescription(answer)
|
|
.then(onSuccess)
|
|
.catch(onError)
|
|
})
|
|
.catch(err => {
|
|
this.destroy(errCode(err, 'ERR_CREATE_ANSWER'))
|
|
})
|
|
}
|
|
|
|
_onConnectionStateChange () {
|
|
if (this.destroyed) return
|
|
if (this._pc.connectionState === 'failed') {
|
|
this.destroy(errCode(new Error('Connection failed.'), 'ERR_CONNECTION_FAILURE'))
|
|
}
|
|
}
|
|
|
|
_onIceStateChange () {
|
|
if (this.destroyed) return
|
|
const iceConnectionState = this._pc.iceConnectionState
|
|
const iceGatheringState = this._pc.iceGatheringState
|
|
|
|
this._debug(
|
|
'iceStateChange (connection: %s) (gathering: %s)',
|
|
iceConnectionState,
|
|
iceGatheringState
|
|
)
|
|
this.emit('iceStateChange', iceConnectionState, iceGatheringState)
|
|
|
|
if (iceConnectionState === 'connected' || iceConnectionState === 'completed') {
|
|
this._pcReady = true
|
|
this._maybeReady()
|
|
}
|
|
if (iceConnectionState === 'failed') {
|
|
this.destroy(errCode(new Error('Ice connection failed.'), 'ERR_ICE_CONNECTION_FAILURE'))
|
|
}
|
|
if (iceConnectionState === 'closed') {
|
|
this.destroy(errCode(new Error('Ice connection closed.'), 'ERR_ICE_CONNECTION_CLOSED'))
|
|
}
|
|
}
|
|
|
|
getStats (cb) {
|
|
// statreports can come with a value array instead of properties
|
|
const flattenValues = report => {
|
|
if (Object.prototype.toString.call(report.values) === '[object Array]') {
|
|
report.values.forEach(value => {
|
|
Object.assign(report, value)
|
|
})
|
|
}
|
|
return report
|
|
}
|
|
|
|
// Promise-based getStats() (standard)
|
|
if (this._pc.getStats.length === 0 || this._isReactNativeWebrtc) {
|
|
this._pc.getStats()
|
|
.then(res => {
|
|
const reports = []
|
|
res.forEach(report => {
|
|
reports.push(flattenValues(report))
|
|
})
|
|
cb(null, reports)
|
|
}, err => cb(err))
|
|
|
|
// Single-parameter callback-based getStats() (non-standard)
|
|
} else if (this._pc.getStats.length > 0) {
|
|
this._pc.getStats(res => {
|
|
// If we destroy connection in `connect` callback this code might happen to run when actual connection is already closed
|
|
if (this.destroyed) return
|
|
|
|
const reports = []
|
|
res.result().forEach(result => {
|
|
const report = {}
|
|
result.names().forEach(name => {
|
|
report[name] = result.stat(name)
|
|
})
|
|
report.id = result.id
|
|
report.type = result.type
|
|
report.timestamp = result.timestamp
|
|
reports.push(flattenValues(report))
|
|
})
|
|
cb(null, reports)
|
|
}, err => cb(err))
|
|
|
|
// Unknown browser, skip getStats() since it's anyone's guess which style of
|
|
// getStats() they implement.
|
|
} else {
|
|
cb(null, [])
|
|
}
|
|
}
|
|
|
|
_maybeReady () {
|
|
this._debug('maybeReady pc %s channel %s', this._pcReady, this._channelReady)
|
|
if (this._connected || this._connecting || !this._pcReady || !this._channelReady) return
|
|
|
|
this._connecting = true
|
|
|
|
// HACK: We can't rely on order here, for details see https://github.com/js-platform/node-webrtc/issues/339
|
|
const findCandidatePair = () => {
|
|
if (this.destroyed) return
|
|
|
|
this.getStats((err, items) => {
|
|
if (this.destroyed) return
|
|
|
|
// Treat getStats error as non-fatal. It's not essential.
|
|
if (err) items = []
|
|
|
|
const remoteCandidates = {}
|
|
const localCandidates = {}
|
|
const candidatePairs = {}
|
|
let foundSelectedCandidatePair = false
|
|
|
|
items.forEach(item => {
|
|
// TODO: Once all browsers support the hyphenated stats report types, remove
|
|
// the non-hypenated ones
|
|
if (item.type === 'remotecandidate' || item.type === 'remote-candidate') {
|
|
remoteCandidates[item.id] = item
|
|
}
|
|
if (item.type === 'localcandidate' || item.type === 'local-candidate') {
|
|
localCandidates[item.id] = item
|
|
}
|
|
if (item.type === 'candidatepair' || item.type === 'candidate-pair') {
|
|
candidatePairs[item.id] = item
|
|
}
|
|
})
|
|
|
|
const setSelectedCandidatePair = selectedCandidatePair => {
|
|
foundSelectedCandidatePair = true
|
|
|
|
let local = localCandidates[selectedCandidatePair.localCandidateId]
|
|
|
|
if (local && (local.ip || local.address)) {
|
|
// Spec
|
|
this.localAddress = local.ip || local.address
|
|
this.localPort = Number(local.port)
|
|
} else if (local && local.ipAddress) {
|
|
// Firefox
|
|
this.localAddress = local.ipAddress
|
|
this.localPort = Number(local.portNumber)
|
|
} else if (typeof selectedCandidatePair.googLocalAddress === 'string') {
|
|
// TODO: remove this once Chrome 58 is released
|
|
local = selectedCandidatePair.googLocalAddress.split(':')
|
|
this.localAddress = local[0]
|
|
this.localPort = Number(local[1])
|
|
}
|
|
if (this.localAddress) {
|
|
this.localFamily = this.localAddress.includes(':') ? 'IPv6' : 'IPv4'
|
|
}
|
|
|
|
let remote = remoteCandidates[selectedCandidatePair.remoteCandidateId]
|
|
|
|
if (remote && (remote.ip || remote.address)) {
|
|
// Spec
|
|
this.remoteAddress = remote.ip || remote.address
|
|
this.remotePort = Number(remote.port)
|
|
} else if (remote && remote.ipAddress) {
|
|
// Firefox
|
|
this.remoteAddress = remote.ipAddress
|
|
this.remotePort = Number(remote.portNumber)
|
|
} else if (typeof selectedCandidatePair.googRemoteAddress === 'string') {
|
|
// TODO: remove this once Chrome 58 is released
|
|
remote = selectedCandidatePair.googRemoteAddress.split(':')
|
|
this.remoteAddress = remote[0]
|
|
this.remotePort = Number(remote[1])
|
|
}
|
|
if (this.remoteAddress) {
|
|
this.remoteFamily = this.remoteAddress.includes(':') ? 'IPv6' : 'IPv4'
|
|
}
|
|
|
|
this._debug(
|
|
'connect local: %s:%s remote: %s:%s',
|
|
this.localAddress,
|
|
this.localPort,
|
|
this.remoteAddress,
|
|
this.remotePort
|
|
)
|
|
}
|
|
|
|
items.forEach(item => {
|
|
// Spec-compliant
|
|
if (item.type === 'transport' && item.selectedCandidatePairId) {
|
|
setSelectedCandidatePair(candidatePairs[item.selectedCandidatePairId])
|
|
}
|
|
|
|
// Old implementations
|
|
if (
|
|
(item.type === 'googCandidatePair' && item.googActiveConnection === 'true') ||
|
|
((item.type === 'candidatepair' || item.type === 'candidate-pair') && item.selected)
|
|
) {
|
|
setSelectedCandidatePair(item)
|
|
}
|
|
})
|
|
|
|
// Ignore candidate pair selection in browsers like Safari 11 that do not have any local or remote candidates
|
|
// But wait until at least 1 candidate pair is available
|
|
if (!foundSelectedCandidatePair && (!Object.keys(candidatePairs).length || Object.keys(localCandidates).length)) {
|
|
setTimeout(findCandidatePair, 100)
|
|
return
|
|
} else {
|
|
this._connecting = false
|
|
this._connected = true
|
|
}
|
|
|
|
if (this._chunk) {
|
|
try {
|
|
this.send(this._chunk)
|
|
} catch (err) {
|
|
return this.destroy(errCode(err, 'ERR_DATA_CHANNEL'))
|
|
}
|
|
this._chunk = null
|
|
this._debug('sent chunk from "write before connect"')
|
|
|
|
const cb = this._cb
|
|
this._cb = null
|
|
cb(null)
|
|
}
|
|
|
|
// If `bufferedAmountLowThreshold` and 'onbufferedamountlow' are unsupported,
|
|
// fallback to using setInterval to implement backpressure.
|
|
if (typeof this._channel.bufferedAmountLowThreshold !== 'number') {
|
|
this._interval = setInterval(() => this._onInterval(), 150)
|
|
if (this._interval.unref) this._interval.unref()
|
|
}
|
|
|
|
this._debug('connect')
|
|
this.emit('connect')
|
|
})
|
|
}
|
|
findCandidatePair()
|
|
}
|
|
|
|
_onInterval () {
|
|
if (!this._cb || !this._channel || this._channel.bufferedAmount > MAX_BUFFERED_AMOUNT) {
|
|
return
|
|
}
|
|
this._onChannelBufferedAmountLow()
|
|
}
|
|
|
|
_onSignalingStateChange () {
|
|
if (this.destroyed) return
|
|
|
|
if (this._pc.signalingState === 'stable') {
|
|
this._isNegotiating = false
|
|
|
|
// HACK: Firefox doesn't yet support removing tracks when signalingState !== 'stable'
|
|
this._debug('flushing sender queue', this._sendersAwaitingStable)
|
|
this._sendersAwaitingStable.forEach(sender => {
|
|
this._pc.removeTrack(sender)
|
|
this._queuedNegotiation = true
|
|
})
|
|
this._sendersAwaitingStable = []
|
|
|
|
if (this._queuedNegotiation) {
|
|
this._debug('flushing negotiation queue')
|
|
this._queuedNegotiation = false
|
|
this._needsNegotiation() // negotiate again
|
|
} else {
|
|
this._debug('negotiated')
|
|
this.emit('negotiated')
|
|
}
|
|
}
|
|
|
|
this._debug('signalingStateChange %s', this._pc.signalingState)
|
|
this.emit('signalingStateChange', this._pc.signalingState)
|
|
}
|
|
|
|
_onIceCandidate (event) {
|
|
if (this.destroyed) return
|
|
if (event.candidate && this.trickle) {
|
|
this.emit('signal', {
|
|
type: 'candidate',
|
|
candidate: {
|
|
candidate: event.candidate.candidate,
|
|
sdpMLineIndex: event.candidate.sdpMLineIndex,
|
|
sdpMid: event.candidate.sdpMid
|
|
}
|
|
})
|
|
} else if (!event.candidate && !this._iceComplete) {
|
|
this._iceComplete = true
|
|
this.emit('_iceComplete')
|
|
}
|
|
// as soon as we've received one valid candidate start timeout
|
|
if (event.candidate) {
|
|
this._startIceCompleteTimeout()
|
|
}
|
|
}
|
|
|
|
_onChannelMessage (event) {
|
|
if (this.destroyed) return
|
|
let data = event.data
|
|
if (data instanceof ArrayBuffer) data = Buffer.from(data)
|
|
this.push(data)
|
|
}
|
|
|
|
_onChannelBufferedAmountLow () {
|
|
if (this.destroyed || !this._cb) return
|
|
this._debug('ending backpressure: bufferedAmount %d', this._channel.bufferedAmount)
|
|
const cb = this._cb
|
|
this._cb = null
|
|
cb(null)
|
|
}
|
|
|
|
_onChannelOpen () {
|
|
if (this._connected || this.destroyed) return
|
|
this._debug('on channel open')
|
|
this._channelReady = true
|
|
this._maybeReady()
|
|
}
|
|
|
|
_onChannelClose () {
|
|
if (this.destroyed) return
|
|
this._debug('on channel close')
|
|
this.destroy()
|
|
}
|
|
|
|
_onTrack (event) {
|
|
if (this.destroyed) return
|
|
|
|
event.streams.forEach(eventStream => {
|
|
this._debug('on track')
|
|
this.emit('track', event.track, eventStream)
|
|
|
|
this._remoteTracks.push({
|
|
track: event.track,
|
|
stream: eventStream
|
|
})
|
|
|
|
if (this._remoteStreams.some(remoteStream => {
|
|
return remoteStream.id === eventStream.id
|
|
})) return // Only fire one 'stream' event, even though there may be multiple tracks per stream
|
|
|
|
this._remoteStreams.push(eventStream)
|
|
queueMicrotask(() => {
|
|
this._debug('on stream')
|
|
this.emit('stream', eventStream) // ensure all tracks have been added
|
|
})
|
|
})
|
|
}
|
|
|
|
_debug () {
|
|
const args = [].slice.call(arguments)
|
|
args[0] = '[' + this._id + '] ' + args[0]
|
|
debug.apply(null, args)
|
|
}
|
|
}
|
|
|
|
Peer.WEBRTC_SUPPORT = !!getBrowserRTC()
|
|
|
|
/**
|
|
* Expose peer and data channel config for overriding all Peer
|
|
* instances. Otherwise, just set opts.config or opts.channelConfig
|
|
* when constructing a Peer.
|
|
*/
|
|
Peer.config = {
|
|
iceServers: [
|
|
{
|
|
urls: [
|
|
'stun:stun.l.google.com:19302',
|
|
'stun:global.stun.twilio.com:3478'
|
|
]
|
|
}
|
|
],
|
|
sdpSemantics: 'unified-plan'
|
|
}
|
|
|
|
Peer.channelConfig = {}
|
|
|
|
module.exports = Peer
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/simple-sha1/browser.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/simple-sha1/browser.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* global self */
|
|
|
|
const Rusha = __webpack_require__(/*! rusha */ "./node_modules/rusha/dist/rusha.js")
|
|
const rushaWorkerSha1 = __webpack_require__(/*! ./rusha-worker-sha1 */ "./node_modules/simple-sha1/rusha-worker-sha1.js")
|
|
|
|
const rusha = new Rusha()
|
|
const scope = typeof window !== 'undefined' ? window : self
|
|
const crypto = scope.crypto || scope.msCrypto || {}
|
|
let subtle = crypto.subtle || crypto.webkitSubtle
|
|
|
|
function sha1sync (buf) {
|
|
return rusha.digest(buf)
|
|
}
|
|
|
|
// Browsers throw if they lack support for an algorithm.
|
|
// Promise will be rejected on non-secure origins. (http://goo.gl/lq4gCo)
|
|
try {
|
|
subtle.digest({ name: 'sha-1' }, new Uint8Array()).catch(function () {
|
|
subtle = false
|
|
})
|
|
} catch (err) { subtle = false }
|
|
|
|
function sha1 (buf, cb) {
|
|
if (!subtle) {
|
|
if (typeof window !== 'undefined') {
|
|
rushaWorkerSha1(buf, function onRushaWorkerSha1 (err, hash) {
|
|
if (err) {
|
|
// On error, fallback to synchronous method which cannot fail
|
|
cb(sha1sync(buf))
|
|
return
|
|
}
|
|
|
|
cb(hash)
|
|
})
|
|
} else {
|
|
queueMicrotask(() => cb(sha1sync(buf)))
|
|
}
|
|
return
|
|
}
|
|
|
|
if (typeof buf === 'string') {
|
|
buf = uint8array(buf)
|
|
}
|
|
|
|
subtle.digest({ name: 'sha-1' }, buf)
|
|
.then(function succeed (result) {
|
|
cb(hex(new Uint8Array(result)))
|
|
},
|
|
function fail () {
|
|
// On error, fallback to synchronous method which cannot fail
|
|
cb(sha1sync(buf))
|
|
})
|
|
}
|
|
|
|
function uint8array (s) {
|
|
const l = s.length
|
|
const array = new Uint8Array(l)
|
|
for (let i = 0; i < l; i++) {
|
|
array[i] = s.charCodeAt(i)
|
|
}
|
|
return array
|
|
}
|
|
|
|
function hex (buf) {
|
|
const l = buf.length
|
|
const chars = []
|
|
for (let i = 0; i < l; i++) {
|
|
const bite = buf[i]
|
|
chars.push((bite >>> 4).toString(16))
|
|
chars.push((bite & 0x0f).toString(16))
|
|
}
|
|
return chars.join('')
|
|
}
|
|
|
|
module.exports = sha1
|
|
module.exports.sync = sha1sync
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/simple-sha1/rusha-worker-sha1.js":
|
|
/*!*******************************************************!*\
|
|
!*** ./node_modules/simple-sha1/rusha-worker-sha1.js ***!
|
|
\*******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const Rusha = __webpack_require__(/*! rusha */ "./node_modules/rusha/dist/rusha.js")
|
|
|
|
let worker
|
|
let nextTaskId
|
|
let cbs
|
|
|
|
function init () {
|
|
worker = Rusha.createWorker()
|
|
nextTaskId = 1
|
|
cbs = {} // taskId -> cb
|
|
|
|
worker.onmessage = function onRushaMessage (e) {
|
|
const taskId = e.data.id
|
|
const cb = cbs[taskId]
|
|
delete cbs[taskId]
|
|
|
|
if (e.data.error != null) {
|
|
cb(new Error('Rusha worker error: ' + e.data.error))
|
|
} else {
|
|
cb(null, e.data.hash)
|
|
}
|
|
}
|
|
}
|
|
|
|
function sha1 (buf, cb) {
|
|
if (!worker) init()
|
|
|
|
cbs[nextTaskId] = cb
|
|
worker.postMessage({ id: nextTaskId, data: buf })
|
|
nextTaskId += 1
|
|
}
|
|
|
|
module.exports = sha1
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/simple-websocket/index.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/simple-websocket/index.js ***!
|
|
\************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! simple-websocket. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
/* global WebSocket */
|
|
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('simple-websocket')
|
|
const randombytes = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js")
|
|
const stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js") // TODO: remove when Node 10 is not supported
|
|
const ws = __webpack_require__(/*! ws */ "?c33b") // websockets in node - will be empty object in browser
|
|
|
|
const _WebSocket = typeof ws !== 'function' ? WebSocket : ws
|
|
|
|
const MAX_BUFFERED_AMOUNT = 64 * 1024
|
|
|
|
/**
|
|
* WebSocket. Same API as node core `net.Socket`. Duplex stream.
|
|
* @param {Object} opts
|
|
* @param {string=} opts.url websocket server url
|
|
* @param {string=} opts.socket raw websocket instance to wrap
|
|
*/
|
|
class Socket extends stream.Duplex {
|
|
constructor (opts = {}) {
|
|
// Support simple usage: `new Socket(url)`
|
|
if (typeof opts === 'string') {
|
|
opts = { url: opts }
|
|
}
|
|
|
|
opts = Object.assign({
|
|
allowHalfOpen: false
|
|
}, opts)
|
|
|
|
super(opts)
|
|
|
|
if (opts.url == null && opts.socket == null) {
|
|
throw new Error('Missing required `url` or `socket` option')
|
|
}
|
|
if (opts.url != null && opts.socket != null) {
|
|
throw new Error('Must specify either `url` or `socket` option, not both')
|
|
}
|
|
|
|
this._id = randombytes(4).toString('hex').slice(0, 7)
|
|
this._debug('new websocket: %o', opts)
|
|
|
|
this.connected = false
|
|
this.destroyed = false
|
|
|
|
this._chunk = null
|
|
this._cb = null
|
|
this._interval = null
|
|
|
|
if (opts.socket) {
|
|
this.url = opts.socket.url
|
|
this._ws = opts.socket
|
|
this.connected = opts.socket.readyState === _WebSocket.OPEN
|
|
} else {
|
|
this.url = opts.url
|
|
try {
|
|
if (typeof ws === 'function') {
|
|
// `ws` package accepts options
|
|
this._ws = new _WebSocket(opts.url, null, {
|
|
...opts,
|
|
encoding: undefined // encoding option breaks ws internals
|
|
})
|
|
} else {
|
|
this._ws = new _WebSocket(opts.url)
|
|
}
|
|
} catch (err) {
|
|
queueMicrotask(() => this.destroy(err))
|
|
return
|
|
}
|
|
}
|
|
|
|
this._ws.binaryType = 'arraybuffer'
|
|
|
|
if (opts.socket && this.connected) {
|
|
queueMicrotask(() => this._handleOpen())
|
|
} else {
|
|
this._ws.onopen = () => this._handleOpen()
|
|
}
|
|
|
|
this._ws.onmessage = event => this._handleMessage(event)
|
|
this._ws.onclose = () => this._handleClose()
|
|
this._ws.onerror = err => this._handleError(err)
|
|
|
|
this._handleFinishBound = () => this._handleFinish()
|
|
this.once('finish', this._handleFinishBound)
|
|
}
|
|
|
|
/**
|
|
* Send text/binary data to the WebSocket server.
|
|
* @param {TypedArrayView|ArrayBuffer|Buffer|string|Blob|Object} chunk
|
|
*/
|
|
send (chunk) {
|
|
this._ws.send(chunk)
|
|
}
|
|
|
|
// TODO: Delete this method once readable-stream is updated to contain a default
|
|
// implementation of destroy() that automatically calls _destroy()
|
|
// See: https://github.com/nodejs/readable-stream/issues/283
|
|
destroy (err) {
|
|
this._destroy(err, () => {})
|
|
}
|
|
|
|
_destroy (err, cb) {
|
|
if (this.destroyed) return
|
|
|
|
this._debug('destroy (error: %s)', err && (err.message || err))
|
|
|
|
this.readable = this.writable = false
|
|
if (!this._readableState.ended) this.push(null)
|
|
if (!this._writableState.finished) this.end()
|
|
|
|
this.connected = false
|
|
this.destroyed = true
|
|
|
|
clearInterval(this._interval)
|
|
this._interval = null
|
|
this._chunk = null
|
|
this._cb = null
|
|
|
|
if (this._handleFinishBound) {
|
|
this.removeListener('finish', this._handleFinishBound)
|
|
}
|
|
this._handleFinishBound = null
|
|
|
|
if (this._ws) {
|
|
const ws = this._ws
|
|
const onClose = () => {
|
|
ws.onclose = null
|
|
}
|
|
if (ws.readyState === _WebSocket.CLOSED) {
|
|
onClose()
|
|
} else {
|
|
try {
|
|
ws.onclose = onClose
|
|
ws.close()
|
|
} catch (err) {
|
|
onClose()
|
|
}
|
|
}
|
|
|
|
ws.onopen = null
|
|
ws.onmessage = null
|
|
ws.onerror = () => {}
|
|
}
|
|
this._ws = null
|
|
|
|
if (err) this.emit('error', err)
|
|
this.emit('close')
|
|
cb()
|
|
}
|
|
|
|
_read () {}
|
|
|
|
_write (chunk, encoding, cb) {
|
|
if (this.destroyed) return cb(new Error('cannot write after socket is destroyed'))
|
|
|
|
if (this.connected) {
|
|
try {
|
|
this.send(chunk)
|
|
} catch (err) {
|
|
return this.destroy(err)
|
|
}
|
|
if (typeof ws !== 'function' && this._ws.bufferedAmount > MAX_BUFFERED_AMOUNT) {
|
|
this._debug('start backpressure: bufferedAmount %d', this._ws.bufferedAmount)
|
|
this._cb = cb
|
|
} else {
|
|
cb(null)
|
|
}
|
|
} else {
|
|
this._debug('write before connect')
|
|
this._chunk = chunk
|
|
this._cb = cb
|
|
}
|
|
}
|
|
|
|
_handleOpen () {
|
|
if (this.connected || this.destroyed) return
|
|
this.connected = true
|
|
|
|
if (this._chunk) {
|
|
try {
|
|
this.send(this._chunk)
|
|
} catch (err) {
|
|
return this.destroy(err)
|
|
}
|
|
this._chunk = null
|
|
this._debug('sent chunk from "write before connect"')
|
|
|
|
const cb = this._cb
|
|
this._cb = null
|
|
cb(null)
|
|
}
|
|
|
|
// Backpressure is not implemented in Node.js. The `ws` module has a buggy
|
|
// `bufferedAmount` property. See: https://github.com/websockets/ws/issues/492
|
|
if (typeof ws !== 'function') {
|
|
this._interval = setInterval(() => this._onInterval(), 150)
|
|
if (this._interval.unref) this._interval.unref()
|
|
}
|
|
|
|
this._debug('connect')
|
|
this.emit('connect')
|
|
}
|
|
|
|
_handleMessage (event) {
|
|
if (this.destroyed) return
|
|
let data = event.data
|
|
if (data instanceof ArrayBuffer) data = Buffer.from(data)
|
|
this.push(data)
|
|
}
|
|
|
|
_handleClose () {
|
|
if (this.destroyed) return
|
|
this._debug('on close')
|
|
this.destroy()
|
|
}
|
|
|
|
_handleError (_) {
|
|
this.destroy(new Error(`Error connecting to ${this.url}`))
|
|
}
|
|
|
|
// When stream finishes writing, close socket. Half open connections are not
|
|
// supported.
|
|
_handleFinish () {
|
|
if (this.destroyed) return
|
|
|
|
// Wait a bit before destroying so the socket flushes.
|
|
// TODO: is there a more reliable way to accomplish this?
|
|
const destroySoon = () => {
|
|
setTimeout(() => this.destroy(), 1000)
|
|
}
|
|
|
|
if (this.connected) {
|
|
destroySoon()
|
|
} else {
|
|
this.once('connect', destroySoon)
|
|
}
|
|
}
|
|
|
|
_onInterval () {
|
|
if (!this._cb || !this._ws || this._ws.bufferedAmount > MAX_BUFFERED_AMOUNT) {
|
|
return
|
|
}
|
|
this._debug('ending backpressure: bufferedAmount %d', this._ws.bufferedAmount)
|
|
const cb = this._cb
|
|
this._cb = null
|
|
cb(null)
|
|
}
|
|
|
|
_debug () {
|
|
const args = [].slice.call(arguments)
|
|
args[0] = '[' + this._id + '] ' + args[0]
|
|
debug.apply(null, args)
|
|
}
|
|
}
|
|
|
|
Socket.WEBSOCKET_SUPPORT = !!_WebSocket
|
|
|
|
module.exports = Socket
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/speed-limiter/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/speed-limiter/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const Throttle = __webpack_require__(/*! ./lib/throttle */ "./node_modules/speed-limiter/lib/throttle.js")
|
|
const ThrottleGroup = __webpack_require__(/*! ./lib/throttle-group */ "./node_modules/speed-limiter/lib/throttle-group.js")
|
|
|
|
module.exports = {
|
|
Throttle,
|
|
ThrottleGroup
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/speed-limiter/lib/throttle-group.js":
|
|
/*!**********************************************************!*\
|
|
!*** ./node_modules/speed-limiter/lib/throttle-group.js ***!
|
|
\**********************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const { TokenBucket } = __webpack_require__(/*! limiter */ "./node_modules/limiter/index.js")
|
|
const Throttle = __webpack_require__(/*! ./throttle */ "./node_modules/speed-limiter/lib/throttle.js")
|
|
|
|
class ThrottleGroup {
|
|
constructor (opts = {}) {
|
|
if (typeof opts !== 'object') throw new Error('Options must be an object')
|
|
|
|
this.throttles = []
|
|
this.setEnabled(opts.enabled)
|
|
this.setRate(opts.rate, opts.chunksize)
|
|
}
|
|
|
|
getEnabled () {
|
|
return this._enabled
|
|
}
|
|
|
|
getRate () {
|
|
// Note: bucketSize === tokensPerInterval
|
|
return this.bucket.tokensPerInterval
|
|
}
|
|
|
|
getChunksize () {
|
|
return this.chunksize
|
|
}
|
|
|
|
setEnabled (val = true) {
|
|
if (typeof val !== 'boolean') throw new Error('Enabled must be a boolean')
|
|
|
|
this._enabled = val
|
|
for (const throttle of this.throttles) {
|
|
throttle.setEnabled(val)
|
|
}
|
|
}
|
|
|
|
setRate (rate, chunksize = null) {
|
|
// Note: rate = 0, means we should stop processing chunks
|
|
if (!Number.isInteger(rate) || rate < 0) throw new Error('Rate must be an integer bigger than zero')
|
|
rate = parseInt(rate)
|
|
|
|
if (chunksize && (typeof chunksize !== 'number' || chunksize <= 0)) throw new Error('Chunksize must be bigger than zero')
|
|
chunksize = chunksize || Math.max(parseInt(rate / 10), 1)
|
|
chunksize = parseInt(chunksize)
|
|
if (rate > 0 && chunksize > rate) throw new Error('Chunk size must be smaller than rate')
|
|
|
|
if (!this.bucket) this.bucket = new TokenBucket(rate, rate, 'second', null)
|
|
|
|
this.bucket.bucketSize = rate
|
|
this.bucket.tokensPerInterval = rate
|
|
this.chunksize = chunksize
|
|
}
|
|
|
|
setChunksize (chunksize) {
|
|
if (!Number.isInteger(chunksize) || chunksize <= 0) throw new Error('Chunk size must be an integer bigger than zero')
|
|
const rate = this.getRate()
|
|
chunksize = parseInt(chunksize)
|
|
if (rate > 0 && chunksize > rate) throw new Error('Chunk size must be smaller than rate')
|
|
this.chunksize = chunksize
|
|
}
|
|
|
|
throttle (opts = {}) {
|
|
if (typeof opts !== 'object') throw new Error('Options must be an object')
|
|
|
|
const newThrottle = new Throttle({
|
|
...opts,
|
|
group: this
|
|
})
|
|
|
|
return newThrottle
|
|
}
|
|
|
|
destroy () {
|
|
for (const throttle of this.throttles) {
|
|
throttle.destroy()
|
|
}
|
|
|
|
this.throttles = []
|
|
}
|
|
|
|
_addThrottle (throttle) {
|
|
if (!(throttle instanceof Throttle)) throw new Error('Throttle must be an instance of Throttle')
|
|
|
|
this.throttles.push(throttle)
|
|
}
|
|
|
|
_removeThrottle (throttle) {
|
|
const index = this.throttles.indexOf(throttle)
|
|
if (index > -1) this.throttles.splice(index, 1)
|
|
}
|
|
}
|
|
|
|
module.exports = ThrottleGroup
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/speed-limiter/lib/throttle.js":
|
|
/*!****************************************************!*\
|
|
!*** ./node_modules/speed-limiter/lib/throttle.js ***!
|
|
\****************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const { EventEmitter } = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
const { Transform } = __webpack_require__(/*! streamx */ "./node_modules/streamx/index.js")
|
|
const { wait } = __webpack_require__(/*! ./utils */ "./node_modules/speed-limiter/lib/utils.js")
|
|
|
|
class Throttle extends Transform {
|
|
constructor (opts = {}) {
|
|
super()
|
|
|
|
if (typeof opts !== 'object') throw new Error('Options must be an object')
|
|
|
|
const params = Object.assign({}, opts)
|
|
|
|
if (params.group && !(params.group instanceof ThrottleGroup)) throw new Error('Group must be an instanece of ThrottleGroup')
|
|
else if (!params.group) params.group = new ThrottleGroup(params)
|
|
|
|
this._setEnabled(params.enabled || params.group.enabled)
|
|
this._group = params.group
|
|
this._emitter = new EventEmitter()
|
|
this._destroyed = false
|
|
|
|
this._group._addThrottle(this)
|
|
}
|
|
|
|
getEnabled () {
|
|
return this._enabled
|
|
}
|
|
|
|
getGroup () {
|
|
return this._group
|
|
}
|
|
|
|
_setEnabled (val = true) {
|
|
if (typeof val !== 'boolean') throw new Error('Enabled must be a boolean')
|
|
this._enabled = val
|
|
}
|
|
|
|
setEnabled (val) {
|
|
this._setEnabled(val)
|
|
if (this._enabled) this._emitter.emit('enabled')
|
|
else this._emitter.emit('disabled')
|
|
}
|
|
|
|
_transform (chunk, done) {
|
|
this._processChunk(chunk, done)
|
|
}
|
|
|
|
/* async _waitForPositiveRate () {
|
|
// Stop pushing chunks if rate is zero
|
|
while (this._group.getRate() === 0 && !this._destroyed && this._areBothEnabled()) {
|
|
await wait(1 * 1000) // wait 1 second
|
|
}
|
|
} */
|
|
|
|
async _waitForTokens (amount) {
|
|
// Wait for enabled, destroyed or tokens
|
|
return new Promise((resolve, reject) => {
|
|
let done = false
|
|
const self = this
|
|
function isDone (err) {
|
|
self._emitter.removeListener('disabled', isDone)
|
|
self._emitter.removeListener('destroyed', isDone)
|
|
|
|
if (done) return
|
|
done = true
|
|
if (err) return reject(err)
|
|
resolve()
|
|
}
|
|
this._emitter.once('disabled', isDone)
|
|
this._emitter.once('destroyed', isDone)
|
|
// TODO: next version remove lisener in "isDone"
|
|
this._group.bucket.removeTokens(amount, isDone)
|
|
})
|
|
}
|
|
|
|
_areBothEnabled () {
|
|
return this._enabled && this._group.getEnabled()
|
|
}
|
|
|
|
/* async _throttleChunk (size) {
|
|
// Stop pushing chunks if rate is zero
|
|
await this._waitForPositiveRate()
|
|
if (this._destroyed) return
|
|
if (!this._areBothEnabled()) return
|
|
|
|
// Get tokens from bucket
|
|
await this._waitForTokens(size)
|
|
} */
|
|
|
|
async _processChunk (chunk, done) {
|
|
if (!this._areBothEnabled()) return done(null, chunk)
|
|
|
|
let pos = 0
|
|
let chunksize = this._group.getChunksize()
|
|
let slice = chunk.slice(pos, pos + chunksize)
|
|
while (slice.length > 0) {
|
|
// Check here again because we might be in the middle of a big chunk
|
|
// with a lot of small slices
|
|
if (this._areBothEnabled()) {
|
|
try {
|
|
// WAIT FOR POSITIVE RATE
|
|
// Stop pushing chunks if rate is zero
|
|
while (this._group.getRate() === 0 && !this._destroyed && this._areBothEnabled()) {
|
|
await wait(1000) // wait 1 second
|
|
if (this._destroyed) return
|
|
}
|
|
|
|
// WAIT FOR TOKENS
|
|
if (this._areBothEnabled() && !this._group.bucket.tryRemoveTokens(slice.length)) {
|
|
await this._waitForTokens(slice.length)
|
|
if (this._destroyed) return
|
|
}
|
|
} catch (err) {
|
|
return done(err)
|
|
}
|
|
}
|
|
|
|
this.push(slice)
|
|
pos += chunksize
|
|
|
|
// Calculate params for next slice
|
|
chunksize = (this._areBothEnabled())
|
|
? this._group.getChunksize() // Chunksize might have changed
|
|
: chunk.length - pos // Get the rest of the chunk
|
|
slice = chunk.slice(pos, pos + chunksize)
|
|
}
|
|
|
|
return done()
|
|
}
|
|
|
|
destroy (...args) {
|
|
this._group._removeThrottle(this)
|
|
|
|
this._destroyed = true
|
|
this._emitter.emit('destroyed')
|
|
|
|
super.destroy(...args)
|
|
}
|
|
}
|
|
|
|
module.exports = Throttle
|
|
|
|
// Fix circular dependency
|
|
const ThrottleGroup = __webpack_require__(/*! ./throttle-group */ "./node_modules/speed-limiter/lib/throttle-group.js")
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/speed-limiter/lib/utils.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/speed-limiter/lib/utils.js ***!
|
|
\*************************************************/
|
|
/***/ ((module) => {
|
|
|
|
function wait (time) {
|
|
return new Promise((resolve) => setTimeout(resolve, time))
|
|
}
|
|
|
|
module.exports = {
|
|
wait
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/speedometer/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/speedometer/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module) => {
|
|
|
|
var tick = 1
|
|
var maxTick = 65535
|
|
var resolution = 4
|
|
var timer
|
|
var inc = function () {
|
|
tick = (tick + 1) & maxTick
|
|
}
|
|
|
|
|
|
module.exports = function (seconds) {
|
|
if (!timer) {
|
|
timer = setInterval(inc, (1000 / resolution) | 0)
|
|
if (timer.unref) timer.unref()
|
|
}
|
|
|
|
var size = resolution * (seconds || 5)
|
|
var buffer = [0]
|
|
var pointer = 1
|
|
var last = (tick - 1) & maxTick
|
|
|
|
return function (delta) {
|
|
var dist = (tick - last) & maxTick
|
|
if (dist > size) dist = size
|
|
last = tick
|
|
|
|
while (dist--) {
|
|
if (pointer === size) pointer = 0
|
|
buffer[pointer] = buffer[pointer === 0 ? size - 1 : pointer - 1]
|
|
pointer++
|
|
}
|
|
|
|
if (delta) buffer[pointer - 1] += delta
|
|
|
|
var top = buffer[pointer - 1]
|
|
var btm = buffer.length < size ? 0 : buffer[pointer === size ? 0 : pointer]
|
|
|
|
return buffer.length < resolution ? top : (top - btm) * resolution / buffer.length
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/stream-browserify/index.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/stream-browserify/index.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
module.exports = Stream;
|
|
|
|
var EE = __webpack_require__(/*! events */ "./node_modules/events/events.js").EventEmitter;
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
|
|
inherits(Stream, EE);
|
|
Stream.Readable = __webpack_require__(/*! readable-stream/lib/_stream_readable.js */ "./node_modules/readable-stream/lib/_stream_readable.js");
|
|
Stream.Writable = __webpack_require__(/*! readable-stream/lib/_stream_writable.js */ "./node_modules/readable-stream/lib/_stream_writable.js");
|
|
Stream.Duplex = __webpack_require__(/*! readable-stream/lib/_stream_duplex.js */ "./node_modules/readable-stream/lib/_stream_duplex.js");
|
|
Stream.Transform = __webpack_require__(/*! readable-stream/lib/_stream_transform.js */ "./node_modules/readable-stream/lib/_stream_transform.js");
|
|
Stream.PassThrough = __webpack_require__(/*! readable-stream/lib/_stream_passthrough.js */ "./node_modules/readable-stream/lib/_stream_passthrough.js");
|
|
Stream.finished = __webpack_require__(/*! readable-stream/lib/internal/streams/end-of-stream.js */ "./node_modules/readable-stream/lib/internal/streams/end-of-stream.js")
|
|
Stream.pipeline = __webpack_require__(/*! readable-stream/lib/internal/streams/pipeline.js */ "./node_modules/readable-stream/lib/internal/streams/pipeline.js")
|
|
|
|
// Backwards-compat with node 0.4.x
|
|
Stream.Stream = Stream;
|
|
|
|
|
|
|
|
// old-style streams. Note that the pipe method (the only relevant
|
|
// part of this class) is overridden in the Readable class.
|
|
|
|
function Stream() {
|
|
EE.call(this);
|
|
}
|
|
|
|
Stream.prototype.pipe = function(dest, options) {
|
|
var source = this;
|
|
|
|
function ondata(chunk) {
|
|
if (dest.writable) {
|
|
if (false === dest.write(chunk) && source.pause) {
|
|
source.pause();
|
|
}
|
|
}
|
|
}
|
|
|
|
source.on('data', ondata);
|
|
|
|
function ondrain() {
|
|
if (source.readable && source.resume) {
|
|
source.resume();
|
|
}
|
|
}
|
|
|
|
dest.on('drain', ondrain);
|
|
|
|
// If the 'end' option is not supplied, dest.end() will be called when
|
|
// source gets the 'end' or 'close' events. Only dest.end() once.
|
|
if (!dest._isStdio && (!options || options.end !== false)) {
|
|
source.on('end', onend);
|
|
source.on('close', onclose);
|
|
}
|
|
|
|
var didOnEnd = false;
|
|
function onend() {
|
|
if (didOnEnd) return;
|
|
didOnEnd = true;
|
|
|
|
dest.end();
|
|
}
|
|
|
|
|
|
function onclose() {
|
|
if (didOnEnd) return;
|
|
didOnEnd = true;
|
|
|
|
if (typeof dest.destroy === 'function') dest.destroy();
|
|
}
|
|
|
|
// don't leave dangling pipes when there are errors.
|
|
function onerror(er) {
|
|
cleanup();
|
|
if (EE.listenerCount(this, 'error') === 0) {
|
|
throw er; // Unhandled stream error in pipe.
|
|
}
|
|
}
|
|
|
|
source.on('error', onerror);
|
|
dest.on('error', onerror);
|
|
|
|
// remove all the event listeners that were added.
|
|
function cleanup() {
|
|
source.removeListener('data', ondata);
|
|
dest.removeListener('drain', ondrain);
|
|
|
|
source.removeListener('end', onend);
|
|
source.removeListener('close', onclose);
|
|
|
|
source.removeListener('error', onerror);
|
|
dest.removeListener('error', onerror);
|
|
|
|
source.removeListener('end', cleanup);
|
|
source.removeListener('close', cleanup);
|
|
|
|
dest.removeListener('close', cleanup);
|
|
}
|
|
|
|
source.on('end', cleanup);
|
|
source.on('close', cleanup);
|
|
|
|
dest.on('close', cleanup);
|
|
|
|
dest.emit('pipe', source);
|
|
|
|
// Allow for unix-like usage: A.pipe(B).pipe(C)
|
|
return dest;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/stream-http/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/stream-http/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var ClientRequest = __webpack_require__(/*! ./lib/request */ "./node_modules/stream-http/lib/request.js")
|
|
var response = __webpack_require__(/*! ./lib/response */ "./node_modules/stream-http/lib/response.js")
|
|
var extend = __webpack_require__(/*! xtend */ "./node_modules/xtend/immutable.js")
|
|
var statusCodes = __webpack_require__(/*! builtin-status-codes */ "./node_modules/builtin-status-codes/browser.js")
|
|
var url = __webpack_require__(/*! url */ "./node_modules/url/url.js")
|
|
|
|
var http = exports
|
|
|
|
http.request = function (opts, cb) {
|
|
if (typeof opts === 'string')
|
|
opts = url.parse(opts)
|
|
else
|
|
opts = extend(opts)
|
|
|
|
// Normally, the page is loaded from http or https, so not specifying a protocol
|
|
// will result in a (valid) protocol-relative url. However, this won't work if
|
|
// the protocol is something else, like 'file:'
|
|
var defaultProtocol = __webpack_require__.g.location.protocol.search(/^https?:$/) === -1 ? 'http:' : ''
|
|
|
|
var protocol = opts.protocol || defaultProtocol
|
|
var host = opts.hostname || opts.host
|
|
var port = opts.port
|
|
var path = opts.path || '/'
|
|
|
|
// Necessary for IPv6 addresses
|
|
if (host && host.indexOf(':') !== -1)
|
|
host = '[' + host + ']'
|
|
|
|
// This may be a relative url. The browser should always be able to interpret it correctly.
|
|
opts.url = (host ? (protocol + '//' + host) : '') + (port ? ':' + port : '') + path
|
|
opts.method = (opts.method || 'GET').toUpperCase()
|
|
opts.headers = opts.headers || {}
|
|
|
|
// Also valid opts.auth, opts.mode
|
|
|
|
var req = new ClientRequest(opts)
|
|
if (cb)
|
|
req.on('response', cb)
|
|
return req
|
|
}
|
|
|
|
http.get = function get (opts, cb) {
|
|
var req = http.request(opts, cb)
|
|
req.end()
|
|
return req
|
|
}
|
|
|
|
http.ClientRequest = ClientRequest
|
|
http.IncomingMessage = response.IncomingMessage
|
|
|
|
http.Agent = function () {}
|
|
http.Agent.defaultMaxSockets = 4
|
|
|
|
http.globalAgent = new http.Agent()
|
|
|
|
http.STATUS_CODES = statusCodes
|
|
|
|
http.METHODS = [
|
|
'CHECKOUT',
|
|
'CONNECT',
|
|
'COPY',
|
|
'DELETE',
|
|
'GET',
|
|
'HEAD',
|
|
'LOCK',
|
|
'M-SEARCH',
|
|
'MERGE',
|
|
'MKACTIVITY',
|
|
'MKCOL',
|
|
'MOVE',
|
|
'NOTIFY',
|
|
'OPTIONS',
|
|
'PATCH',
|
|
'POST',
|
|
'PROPFIND',
|
|
'PROPPATCH',
|
|
'PURGE',
|
|
'PUT',
|
|
'REPORT',
|
|
'SEARCH',
|
|
'SUBSCRIBE',
|
|
'TRACE',
|
|
'UNLOCK',
|
|
'UNSUBSCRIBE'
|
|
]
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/stream-http/lib/capability.js":
|
|
/*!****************************************************!*\
|
|
!*** ./node_modules/stream-http/lib/capability.js ***!
|
|
\****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
exports.fetch = isFunction(__webpack_require__.g.fetch) && isFunction(__webpack_require__.g.ReadableStream)
|
|
|
|
exports.writableStream = isFunction(__webpack_require__.g.WritableStream)
|
|
|
|
exports.abortController = isFunction(__webpack_require__.g.AbortController)
|
|
|
|
// The xhr request to example.com may violate some restrictive CSP configurations,
|
|
// so if we're running in a browser that supports `fetch`, avoid calling getXHR()
|
|
// and assume support for certain features below.
|
|
var xhr
|
|
function getXHR () {
|
|
// Cache the xhr value
|
|
if (xhr !== undefined) return xhr
|
|
|
|
if (__webpack_require__.g.XMLHttpRequest) {
|
|
xhr = new __webpack_require__.g.XMLHttpRequest()
|
|
// If XDomainRequest is available (ie only, where xhr might not work
|
|
// cross domain), use the page location. Otherwise use example.com
|
|
// Note: this doesn't actually make an http request.
|
|
try {
|
|
xhr.open('GET', __webpack_require__.g.XDomainRequest ? '/' : 'https://example.com')
|
|
} catch(e) {
|
|
xhr = null
|
|
}
|
|
} else {
|
|
// Service workers don't have XHR
|
|
xhr = null
|
|
}
|
|
return xhr
|
|
}
|
|
|
|
function checkTypeSupport (type) {
|
|
var xhr = getXHR()
|
|
if (!xhr) return false
|
|
try {
|
|
xhr.responseType = type
|
|
return xhr.responseType === type
|
|
} catch (e) {}
|
|
return false
|
|
}
|
|
|
|
// If fetch is supported, then arraybuffer will be supported too. Skip calling
|
|
// checkTypeSupport(), since that calls getXHR().
|
|
exports.arraybuffer = exports.fetch || checkTypeSupport('arraybuffer')
|
|
|
|
// These next two tests unavoidably show warnings in Chrome. Since fetch will always
|
|
// be used if it's available, just return false for these to avoid the warnings.
|
|
exports.msstream = !exports.fetch && checkTypeSupport('ms-stream')
|
|
exports.mozchunkedarraybuffer = !exports.fetch && checkTypeSupport('moz-chunked-arraybuffer')
|
|
|
|
// If fetch is supported, then overrideMimeType will be supported too. Skip calling
|
|
// getXHR().
|
|
exports.overrideMimeType = exports.fetch || (getXHR() ? isFunction(getXHR().overrideMimeType) : false)
|
|
|
|
function isFunction (value) {
|
|
return typeof value === 'function'
|
|
}
|
|
|
|
xhr = null // Help gc
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/stream-http/lib/request.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/stream-http/lib/request.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
var capability = __webpack_require__(/*! ./capability */ "./node_modules/stream-http/lib/capability.js")
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var response = __webpack_require__(/*! ./response */ "./node_modules/stream-http/lib/response.js")
|
|
var stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
|
|
var IncomingMessage = response.IncomingMessage
|
|
var rStates = response.readyStates
|
|
|
|
function decideMode (preferBinary, useFetch) {
|
|
if (capability.fetch && useFetch) {
|
|
return 'fetch'
|
|
} else if (capability.mozchunkedarraybuffer) {
|
|
return 'moz-chunked-arraybuffer'
|
|
} else if (capability.msstream) {
|
|
return 'ms-stream'
|
|
} else if (capability.arraybuffer && preferBinary) {
|
|
return 'arraybuffer'
|
|
} else {
|
|
return 'text'
|
|
}
|
|
}
|
|
|
|
var ClientRequest = module.exports = function (opts) {
|
|
var self = this
|
|
stream.Writable.call(self)
|
|
|
|
self._opts = opts
|
|
self._body = []
|
|
self._headers = {}
|
|
if (opts.auth)
|
|
self.setHeader('Authorization', 'Basic ' + Buffer.from(opts.auth).toString('base64'))
|
|
Object.keys(opts.headers).forEach(function (name) {
|
|
self.setHeader(name, opts.headers[name])
|
|
})
|
|
|
|
var preferBinary
|
|
var useFetch = true
|
|
if (opts.mode === 'disable-fetch' || ('requestTimeout' in opts && !capability.abortController)) {
|
|
// If the use of XHR should be preferred. Not typically needed.
|
|
useFetch = false
|
|
preferBinary = true
|
|
} else if (opts.mode === 'prefer-streaming') {
|
|
// If streaming is a high priority but binary compatibility and
|
|
// the accuracy of the 'content-type' header aren't
|
|
preferBinary = false
|
|
} else if (opts.mode === 'allow-wrong-content-type') {
|
|
// If streaming is more important than preserving the 'content-type' header
|
|
preferBinary = !capability.overrideMimeType
|
|
} else if (!opts.mode || opts.mode === 'default' || opts.mode === 'prefer-fast') {
|
|
// Use binary if text streaming may corrupt data or the content-type header, or for speed
|
|
preferBinary = true
|
|
} else {
|
|
throw new Error('Invalid value for opts.mode')
|
|
}
|
|
self._mode = decideMode(preferBinary, useFetch)
|
|
self._fetchTimer = null
|
|
self._socketTimeout = null
|
|
self._socketTimer = null
|
|
|
|
self.on('finish', function () {
|
|
self._onFinish()
|
|
})
|
|
}
|
|
|
|
inherits(ClientRequest, stream.Writable)
|
|
|
|
ClientRequest.prototype.setHeader = function (name, value) {
|
|
var self = this
|
|
var lowerName = name.toLowerCase()
|
|
// This check is not necessary, but it prevents warnings from browsers about setting unsafe
|
|
// headers. To be honest I'm not entirely sure hiding these warnings is a good thing, but
|
|
// http-browserify did it, so I will too.
|
|
if (unsafeHeaders.indexOf(lowerName) !== -1)
|
|
return
|
|
|
|
self._headers[lowerName] = {
|
|
name: name,
|
|
value: value
|
|
}
|
|
}
|
|
|
|
ClientRequest.prototype.getHeader = function (name) {
|
|
var header = this._headers[name.toLowerCase()]
|
|
if (header)
|
|
return header.value
|
|
return null
|
|
}
|
|
|
|
ClientRequest.prototype.removeHeader = function (name) {
|
|
var self = this
|
|
delete self._headers[name.toLowerCase()]
|
|
}
|
|
|
|
ClientRequest.prototype._onFinish = function () {
|
|
var self = this
|
|
|
|
if (self._destroyed)
|
|
return
|
|
var opts = self._opts
|
|
|
|
if ('timeout' in opts && opts.timeout !== 0) {
|
|
self.setTimeout(opts.timeout)
|
|
}
|
|
|
|
var headersObj = self._headers
|
|
var body = null
|
|
if (opts.method !== 'GET' && opts.method !== 'HEAD') {
|
|
body = new Blob(self._body, {
|
|
type: (headersObj['content-type'] || {}).value || ''
|
|
});
|
|
}
|
|
|
|
// create flattened list of headers
|
|
var headersList = []
|
|
Object.keys(headersObj).forEach(function (keyName) {
|
|
var name = headersObj[keyName].name
|
|
var value = headersObj[keyName].value
|
|
if (Array.isArray(value)) {
|
|
value.forEach(function (v) {
|
|
headersList.push([name, v])
|
|
})
|
|
} else {
|
|
headersList.push([name, value])
|
|
}
|
|
})
|
|
|
|
if (self._mode === 'fetch') {
|
|
var signal = null
|
|
if (capability.abortController) {
|
|
var controller = new AbortController()
|
|
signal = controller.signal
|
|
self._fetchAbortController = controller
|
|
|
|
if ('requestTimeout' in opts && opts.requestTimeout !== 0) {
|
|
self._fetchTimer = __webpack_require__.g.setTimeout(function () {
|
|
self.emit('requestTimeout')
|
|
if (self._fetchAbortController)
|
|
self._fetchAbortController.abort()
|
|
}, opts.requestTimeout)
|
|
}
|
|
}
|
|
|
|
__webpack_require__.g.fetch(self._opts.url, {
|
|
method: self._opts.method,
|
|
headers: headersList,
|
|
body: body || undefined,
|
|
mode: 'cors',
|
|
credentials: opts.withCredentials ? 'include' : 'same-origin',
|
|
signal: signal
|
|
}).then(function (response) {
|
|
self._fetchResponse = response
|
|
self._resetTimers(false)
|
|
self._connect()
|
|
}, function (reason) {
|
|
self._resetTimers(true)
|
|
if (!self._destroyed)
|
|
self.emit('error', reason)
|
|
})
|
|
} else {
|
|
var xhr = self._xhr = new __webpack_require__.g.XMLHttpRequest()
|
|
try {
|
|
xhr.open(self._opts.method, self._opts.url, true)
|
|
} catch (err) {
|
|
process.nextTick(function () {
|
|
self.emit('error', err)
|
|
})
|
|
return
|
|
}
|
|
|
|
// Can't set responseType on really old browsers
|
|
if ('responseType' in xhr)
|
|
xhr.responseType = self._mode
|
|
|
|
if ('withCredentials' in xhr)
|
|
xhr.withCredentials = !!opts.withCredentials
|
|
|
|
if (self._mode === 'text' && 'overrideMimeType' in xhr)
|
|
xhr.overrideMimeType('text/plain; charset=x-user-defined')
|
|
|
|
if ('requestTimeout' in opts) {
|
|
xhr.timeout = opts.requestTimeout
|
|
xhr.ontimeout = function () {
|
|
self.emit('requestTimeout')
|
|
}
|
|
}
|
|
|
|
headersList.forEach(function (header) {
|
|
xhr.setRequestHeader(header[0], header[1])
|
|
})
|
|
|
|
self._response = null
|
|
xhr.onreadystatechange = function () {
|
|
switch (xhr.readyState) {
|
|
case rStates.LOADING:
|
|
case rStates.DONE:
|
|
self._onXHRProgress()
|
|
break
|
|
}
|
|
}
|
|
// Necessary for streaming in Firefox, since xhr.response is ONLY defined
|
|
// in onprogress, not in onreadystatechange with xhr.readyState = 3
|
|
if (self._mode === 'moz-chunked-arraybuffer') {
|
|
xhr.onprogress = function () {
|
|
self._onXHRProgress()
|
|
}
|
|
}
|
|
|
|
xhr.onerror = function () {
|
|
if (self._destroyed)
|
|
return
|
|
self._resetTimers(true)
|
|
self.emit('error', new Error('XHR error'))
|
|
}
|
|
|
|
try {
|
|
xhr.send(body)
|
|
} catch (err) {
|
|
process.nextTick(function () {
|
|
self.emit('error', err)
|
|
})
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if xhr.status is readable and non-zero, indicating no error.
|
|
* Even though the spec says it should be available in readyState 3,
|
|
* accessing it throws an exception in IE8
|
|
*/
|
|
function statusValid (xhr) {
|
|
try {
|
|
var status = xhr.status
|
|
return (status !== null && status !== 0)
|
|
} catch (e) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
ClientRequest.prototype._onXHRProgress = function () {
|
|
var self = this
|
|
|
|
self._resetTimers(false)
|
|
|
|
if (!statusValid(self._xhr) || self._destroyed)
|
|
return
|
|
|
|
if (!self._response)
|
|
self._connect()
|
|
|
|
self._response._onXHRProgress(self._resetTimers.bind(self))
|
|
}
|
|
|
|
ClientRequest.prototype._connect = function () {
|
|
var self = this
|
|
|
|
if (self._destroyed)
|
|
return
|
|
|
|
self._response = new IncomingMessage(self._xhr, self._fetchResponse, self._mode, self._resetTimers.bind(self))
|
|
self._response.on('error', function(err) {
|
|
self.emit('error', err)
|
|
})
|
|
|
|
self.emit('response', self._response)
|
|
}
|
|
|
|
ClientRequest.prototype._write = function (chunk, encoding, cb) {
|
|
var self = this
|
|
|
|
self._body.push(chunk)
|
|
cb()
|
|
}
|
|
|
|
ClientRequest.prototype._resetTimers = function (done) {
|
|
var self = this
|
|
|
|
__webpack_require__.g.clearTimeout(self._socketTimer)
|
|
self._socketTimer = null
|
|
|
|
if (done) {
|
|
__webpack_require__.g.clearTimeout(self._fetchTimer)
|
|
self._fetchTimer = null
|
|
} else if (self._socketTimeout) {
|
|
self._socketTimer = __webpack_require__.g.setTimeout(function () {
|
|
self.emit('timeout')
|
|
}, self._socketTimeout)
|
|
}
|
|
}
|
|
|
|
ClientRequest.prototype.abort = ClientRequest.prototype.destroy = function (err) {
|
|
var self = this
|
|
self._destroyed = true
|
|
self._resetTimers(true)
|
|
if (self._response)
|
|
self._response._destroyed = true
|
|
if (self._xhr)
|
|
self._xhr.abort()
|
|
else if (self._fetchAbortController)
|
|
self._fetchAbortController.abort()
|
|
|
|
if (err)
|
|
self.emit('error', err)
|
|
}
|
|
|
|
ClientRequest.prototype.end = function (data, encoding, cb) {
|
|
var self = this
|
|
if (typeof data === 'function') {
|
|
cb = data
|
|
data = undefined
|
|
}
|
|
|
|
stream.Writable.prototype.end.call(self, data, encoding, cb)
|
|
}
|
|
|
|
ClientRequest.prototype.setTimeout = function (timeout, cb) {
|
|
var self = this
|
|
|
|
if (cb)
|
|
self.once('timeout', cb)
|
|
|
|
self._socketTimeout = timeout
|
|
self._resetTimers(false)
|
|
}
|
|
|
|
ClientRequest.prototype.flushHeaders = function () {}
|
|
ClientRequest.prototype.setNoDelay = function () {}
|
|
ClientRequest.prototype.setSocketKeepAlive = function () {}
|
|
|
|
// Taken from http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader%28%29-method
|
|
var unsafeHeaders = [
|
|
'accept-charset',
|
|
'accept-encoding',
|
|
'access-control-request-headers',
|
|
'access-control-request-method',
|
|
'connection',
|
|
'content-length',
|
|
'cookie',
|
|
'cookie2',
|
|
'date',
|
|
'dnt',
|
|
'expect',
|
|
'host',
|
|
'keep-alive',
|
|
'origin',
|
|
'referer',
|
|
'te',
|
|
'trailer',
|
|
'transfer-encoding',
|
|
'upgrade',
|
|
'via'
|
|
]
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/stream-http/lib/response.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/stream-http/lib/response.js ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
var capability = __webpack_require__(/*! ./capability */ "./node_modules/stream-http/lib/capability.js")
|
|
var inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js")
|
|
var stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
|
|
var rStates = exports.readyStates = {
|
|
UNSENT: 0,
|
|
OPENED: 1,
|
|
HEADERS_RECEIVED: 2,
|
|
LOADING: 3,
|
|
DONE: 4
|
|
}
|
|
|
|
var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode, resetTimers) {
|
|
var self = this
|
|
stream.Readable.call(self)
|
|
|
|
self._mode = mode
|
|
self.headers = {}
|
|
self.rawHeaders = []
|
|
self.trailers = {}
|
|
self.rawTrailers = []
|
|
|
|
// Fake the 'close' event, but only once 'end' fires
|
|
self.on('end', function () {
|
|
// The nextTick is necessary to prevent the 'request' module from causing an infinite loop
|
|
process.nextTick(function () {
|
|
self.emit('close')
|
|
})
|
|
})
|
|
|
|
if (mode === 'fetch') {
|
|
self._fetchResponse = response
|
|
|
|
self.url = response.url
|
|
self.statusCode = response.status
|
|
self.statusMessage = response.statusText
|
|
|
|
response.headers.forEach(function (header, key){
|
|
self.headers[key.toLowerCase()] = header
|
|
self.rawHeaders.push(key, header)
|
|
})
|
|
|
|
if (capability.writableStream) {
|
|
var writable = new WritableStream({
|
|
write: function (chunk) {
|
|
resetTimers(false)
|
|
return new Promise(function (resolve, reject) {
|
|
if (self._destroyed) {
|
|
reject()
|
|
} else if(self.push(Buffer.from(chunk))) {
|
|
resolve()
|
|
} else {
|
|
self._resumeFetch = resolve
|
|
}
|
|
})
|
|
},
|
|
close: function () {
|
|
resetTimers(true)
|
|
if (!self._destroyed)
|
|
self.push(null)
|
|
},
|
|
abort: function (err) {
|
|
resetTimers(true)
|
|
if (!self._destroyed)
|
|
self.emit('error', err)
|
|
}
|
|
})
|
|
|
|
try {
|
|
response.body.pipeTo(writable).catch(function (err) {
|
|
resetTimers(true)
|
|
if (!self._destroyed)
|
|
self.emit('error', err)
|
|
})
|
|
return
|
|
} catch (e) {} // pipeTo method isn't defined. Can't find a better way to feature test this
|
|
}
|
|
// fallback for when writableStream or pipeTo aren't available
|
|
var reader = response.body.getReader()
|
|
function read () {
|
|
reader.read().then(function (result) {
|
|
if (self._destroyed)
|
|
return
|
|
resetTimers(result.done)
|
|
if (result.done) {
|
|
self.push(null)
|
|
return
|
|
}
|
|
self.push(Buffer.from(result.value))
|
|
read()
|
|
}).catch(function (err) {
|
|
resetTimers(true)
|
|
if (!self._destroyed)
|
|
self.emit('error', err)
|
|
})
|
|
}
|
|
read()
|
|
} else {
|
|
self._xhr = xhr
|
|
self._pos = 0
|
|
|
|
self.url = xhr.responseURL
|
|
self.statusCode = xhr.status
|
|
self.statusMessage = xhr.statusText
|
|
var headers = xhr.getAllResponseHeaders().split(/\r?\n/)
|
|
headers.forEach(function (header) {
|
|
var matches = header.match(/^([^:]+):\s*(.*)/)
|
|
if (matches) {
|
|
var key = matches[1].toLowerCase()
|
|
if (key === 'set-cookie') {
|
|
if (self.headers[key] === undefined) {
|
|
self.headers[key] = []
|
|
}
|
|
self.headers[key].push(matches[2])
|
|
} else if (self.headers[key] !== undefined) {
|
|
self.headers[key] += ', ' + matches[2]
|
|
} else {
|
|
self.headers[key] = matches[2]
|
|
}
|
|
self.rawHeaders.push(matches[1], matches[2])
|
|
}
|
|
})
|
|
|
|
self._charset = 'x-user-defined'
|
|
if (!capability.overrideMimeType) {
|
|
var mimeType = self.rawHeaders['mime-type']
|
|
if (mimeType) {
|
|
var charsetMatch = mimeType.match(/;\s*charset=([^;])(;|$)/)
|
|
if (charsetMatch) {
|
|
self._charset = charsetMatch[1].toLowerCase()
|
|
}
|
|
}
|
|
if (!self._charset)
|
|
self._charset = 'utf-8' // best guess
|
|
}
|
|
}
|
|
}
|
|
|
|
inherits(IncomingMessage, stream.Readable)
|
|
|
|
IncomingMessage.prototype._read = function () {
|
|
var self = this
|
|
|
|
var resolve = self._resumeFetch
|
|
if (resolve) {
|
|
self._resumeFetch = null
|
|
resolve()
|
|
}
|
|
}
|
|
|
|
IncomingMessage.prototype._onXHRProgress = function (resetTimers) {
|
|
var self = this
|
|
|
|
var xhr = self._xhr
|
|
|
|
var response = null
|
|
switch (self._mode) {
|
|
case 'text':
|
|
response = xhr.responseText
|
|
if (response.length > self._pos) {
|
|
var newData = response.substr(self._pos)
|
|
if (self._charset === 'x-user-defined') {
|
|
var buffer = Buffer.alloc(newData.length)
|
|
for (var i = 0; i < newData.length; i++)
|
|
buffer[i] = newData.charCodeAt(i) & 0xff
|
|
|
|
self.push(buffer)
|
|
} else {
|
|
self.push(newData, self._charset)
|
|
}
|
|
self._pos = response.length
|
|
}
|
|
break
|
|
case 'arraybuffer':
|
|
if (xhr.readyState !== rStates.DONE || !xhr.response)
|
|
break
|
|
response = xhr.response
|
|
self.push(Buffer.from(new Uint8Array(response)))
|
|
break
|
|
case 'moz-chunked-arraybuffer': // take whole
|
|
response = xhr.response
|
|
if (xhr.readyState !== rStates.LOADING || !response)
|
|
break
|
|
self.push(Buffer.from(new Uint8Array(response)))
|
|
break
|
|
case 'ms-stream':
|
|
response = xhr.response
|
|
if (xhr.readyState !== rStates.LOADING)
|
|
break
|
|
var reader = new __webpack_require__.g.MSStreamReader()
|
|
reader.onprogress = function () {
|
|
if (reader.result.byteLength > self._pos) {
|
|
self.push(Buffer.from(new Uint8Array(reader.result.slice(self._pos))))
|
|
self._pos = reader.result.byteLength
|
|
}
|
|
}
|
|
reader.onload = function () {
|
|
resetTimers(true)
|
|
self.push(null)
|
|
}
|
|
// reader.onerror = ??? // TODO: this
|
|
reader.readAsArrayBuffer(response)
|
|
break
|
|
}
|
|
|
|
// The ms-stream case handles end separately in reader.onload()
|
|
if (self._xhr.readyState === rStates.DONE && self._mode !== 'ms-stream') {
|
|
resetTimers(true)
|
|
self.push(null)
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/stream-to-blob-url/index.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/stream-to-blob-url/index.js ***!
|
|
\**************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/*! stream-to-blob-url. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
module.exports = getBlobURL
|
|
|
|
const getBlob = __webpack_require__(/*! stream-to-blob */ "./node_modules/stream-to-blob/index.js")
|
|
|
|
async function getBlobURL (stream, mimeType) {
|
|
const blob = await getBlob(stream, mimeType)
|
|
const url = URL.createObjectURL(blob)
|
|
return url
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/stream-to-blob/index.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/stream-to-blob/index.js ***!
|
|
\**********************************************/
|
|
/***/ ((module) => {
|
|
|
|
/*! stream-to-blob. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
/* global Blob */
|
|
|
|
module.exports = streamToBlob
|
|
|
|
function streamToBlob (stream, mimeType) {
|
|
if (mimeType != null && typeof mimeType !== 'string') {
|
|
throw new Error('Invalid mimetype, expected string.')
|
|
}
|
|
return new Promise((resolve, reject) => {
|
|
const chunks = []
|
|
stream
|
|
.on('data', chunk => chunks.push(chunk))
|
|
.once('end', () => {
|
|
const blob = mimeType != null
|
|
? new Blob(chunks, { type: mimeType })
|
|
: new Blob(chunks)
|
|
resolve(blob)
|
|
})
|
|
.once('error', reject)
|
|
})
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/stream-with-known-length-to-buffer/index.js":
|
|
/*!******************************************************************!*\
|
|
!*** ./node_modules/stream-with-known-length-to-buffer/index.js ***!
|
|
\******************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! stream-with-known-length-to-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
var once = __webpack_require__(/*! once */ "./node_modules/once/once.js")
|
|
|
|
module.exports = function getBuffer (stream, length, cb) {
|
|
cb = once(cb)
|
|
var buf = Buffer.alloc(length)
|
|
var offset = 0
|
|
stream
|
|
.on('data', function (chunk) {
|
|
chunk.copy(buf, offset)
|
|
offset += chunk.length
|
|
})
|
|
.on('end', function () { cb(null, buf) })
|
|
.on('error', cb)
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/streamx/index.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/streamx/index.js ***!
|
|
\***************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
const { EventEmitter } = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
const STREAM_DESTROYED = new Error('Stream was destroyed')
|
|
const PREMATURE_CLOSE = new Error('Premature close')
|
|
|
|
const FIFO = __webpack_require__(/*! fast-fifo */ "./node_modules/fast-fifo/index.js")
|
|
|
|
/* eslint-disable no-multi-spaces */
|
|
|
|
const MAX = ((1 << 25) - 1)
|
|
|
|
// Shared state
|
|
const OPENING = 0b001
|
|
const DESTROYING = 0b010
|
|
const DESTROYED = 0b100
|
|
|
|
const NOT_OPENING = MAX ^ OPENING
|
|
|
|
// Read state
|
|
const READ_ACTIVE = 0b0000000000001 << 3
|
|
const READ_PRIMARY = 0b0000000000010 << 3
|
|
const READ_SYNC = 0b0000000000100 << 3
|
|
const READ_QUEUED = 0b0000000001000 << 3
|
|
const READ_RESUMED = 0b0000000010000 << 3
|
|
const READ_PIPE_DRAINED = 0b0000000100000 << 3
|
|
const READ_ENDING = 0b0000001000000 << 3
|
|
const READ_EMIT_DATA = 0b0000010000000 << 3
|
|
const READ_EMIT_READABLE = 0b0000100000000 << 3
|
|
const READ_EMITTED_READABLE = 0b0001000000000 << 3
|
|
const READ_DONE = 0b0010000000000 << 3
|
|
const READ_NEXT_TICK = 0b0100000000001 << 3 // also active
|
|
const READ_NEEDS_PUSH = 0b1000000000000 << 3
|
|
|
|
const READ_NOT_ACTIVE = MAX ^ READ_ACTIVE
|
|
const READ_NON_PRIMARY = MAX ^ READ_PRIMARY
|
|
const READ_NON_PRIMARY_AND_PUSHED = MAX ^ (READ_PRIMARY | READ_NEEDS_PUSH)
|
|
const READ_NOT_SYNC = MAX ^ READ_SYNC
|
|
const READ_PUSHED = MAX ^ READ_NEEDS_PUSH
|
|
const READ_PAUSED = MAX ^ READ_RESUMED
|
|
const READ_NOT_QUEUED = MAX ^ (READ_QUEUED | READ_EMITTED_READABLE)
|
|
const READ_NOT_ENDING = MAX ^ READ_ENDING
|
|
const READ_PIPE_NOT_DRAINED = MAX ^ (READ_RESUMED | READ_PIPE_DRAINED)
|
|
const READ_NOT_NEXT_TICK = MAX ^ READ_NEXT_TICK
|
|
|
|
// Write state
|
|
const WRITE_ACTIVE = 0b000000001 << 16
|
|
const WRITE_PRIMARY = 0b000000010 << 16
|
|
const WRITE_SYNC = 0b000000100 << 16
|
|
const WRITE_QUEUED = 0b000001000 << 16
|
|
const WRITE_UNDRAINED = 0b000010000 << 16
|
|
const WRITE_DONE = 0b000100000 << 16
|
|
const WRITE_EMIT_DRAIN = 0b001000000 << 16
|
|
const WRITE_NEXT_TICK = 0b010000001 << 16 // also active
|
|
const WRITE_FINISHING = 0b100000000 << 16
|
|
|
|
const WRITE_NOT_ACTIVE = MAX ^ WRITE_ACTIVE
|
|
const WRITE_NOT_SYNC = MAX ^ WRITE_SYNC
|
|
const WRITE_NON_PRIMARY = MAX ^ WRITE_PRIMARY
|
|
const WRITE_NOT_FINISHING = MAX ^ WRITE_FINISHING
|
|
const WRITE_DRAINED = MAX ^ WRITE_UNDRAINED
|
|
const WRITE_NOT_QUEUED = MAX ^ WRITE_QUEUED
|
|
const WRITE_NOT_NEXT_TICK = MAX ^ WRITE_NEXT_TICK
|
|
|
|
// Combined shared state
|
|
const ACTIVE = READ_ACTIVE | WRITE_ACTIVE
|
|
const NOT_ACTIVE = MAX ^ ACTIVE
|
|
const DONE = READ_DONE | WRITE_DONE
|
|
const DESTROY_STATUS = DESTROYING | DESTROYED
|
|
const OPEN_STATUS = DESTROY_STATUS | OPENING
|
|
const AUTO_DESTROY = DESTROY_STATUS | DONE
|
|
const NON_PRIMARY = WRITE_NON_PRIMARY & READ_NON_PRIMARY
|
|
const TICKING = (WRITE_NEXT_TICK | READ_NEXT_TICK) & NOT_ACTIVE
|
|
const ACTIVE_OR_TICKING = ACTIVE | TICKING
|
|
const IS_OPENING = OPEN_STATUS | TICKING
|
|
|
|
// Combined read state
|
|
const READ_PRIMARY_STATUS = OPEN_STATUS | READ_ENDING | READ_DONE
|
|
const READ_STATUS = OPEN_STATUS | READ_DONE | READ_QUEUED
|
|
const READ_FLOWING = READ_RESUMED | READ_PIPE_DRAINED
|
|
const READ_ACTIVE_AND_SYNC = READ_ACTIVE | READ_SYNC
|
|
const READ_ACTIVE_AND_SYNC_AND_NEEDS_PUSH = READ_ACTIVE | READ_SYNC | READ_NEEDS_PUSH
|
|
const READ_PRIMARY_AND_ACTIVE = READ_PRIMARY | READ_ACTIVE
|
|
const READ_ENDING_STATUS = OPEN_STATUS | READ_ENDING | READ_QUEUED
|
|
const READ_EMIT_READABLE_AND_QUEUED = READ_EMIT_READABLE | READ_QUEUED
|
|
const READ_READABLE_STATUS = OPEN_STATUS | READ_EMIT_READABLE | READ_QUEUED | READ_EMITTED_READABLE
|
|
const SHOULD_NOT_READ = OPEN_STATUS | READ_ACTIVE | READ_ENDING | READ_DONE | READ_NEEDS_PUSH
|
|
const READ_BACKPRESSURE_STATUS = DESTROY_STATUS | READ_ENDING | READ_DONE
|
|
|
|
// Combined write state
|
|
const WRITE_PRIMARY_STATUS = OPEN_STATUS | WRITE_FINISHING | WRITE_DONE
|
|
const WRITE_QUEUED_AND_UNDRAINED = WRITE_QUEUED | WRITE_UNDRAINED
|
|
const WRITE_QUEUED_AND_ACTIVE = WRITE_QUEUED | WRITE_ACTIVE
|
|
const WRITE_DRAIN_STATUS = WRITE_QUEUED | WRITE_UNDRAINED | OPEN_STATUS | WRITE_ACTIVE
|
|
const WRITE_STATUS = OPEN_STATUS | WRITE_ACTIVE | WRITE_QUEUED
|
|
const WRITE_PRIMARY_AND_ACTIVE = WRITE_PRIMARY | WRITE_ACTIVE
|
|
const WRITE_ACTIVE_AND_SYNC = WRITE_ACTIVE | WRITE_SYNC
|
|
const WRITE_FINISHING_STATUS = OPEN_STATUS | WRITE_FINISHING | WRITE_QUEUED
|
|
const WRITE_BACKPRESSURE_STATUS = WRITE_UNDRAINED | DESTROY_STATUS | WRITE_FINISHING | WRITE_DONE
|
|
|
|
const asyncIterator = Symbol.asyncIterator || Symbol('asyncIterator')
|
|
|
|
class WritableState {
|
|
constructor (stream, { highWaterMark = 16384, map = null, mapWritable, byteLength, byteLengthWritable } = {}) {
|
|
this.stream = stream
|
|
this.queue = new FIFO()
|
|
this.highWaterMark = highWaterMark
|
|
this.buffered = 0
|
|
this.error = null
|
|
this.pipeline = null
|
|
this.byteLength = byteLengthWritable || byteLength || defaultByteLength
|
|
this.map = mapWritable || map
|
|
this.afterWrite = afterWrite.bind(this)
|
|
}
|
|
|
|
get ended () {
|
|
return (this.stream._duplexState & WRITE_DONE) !== 0
|
|
}
|
|
|
|
push (data) {
|
|
if (this.map !== null) data = this.map(data)
|
|
|
|
this.buffered += this.byteLength(data)
|
|
this.queue.push(data)
|
|
|
|
if (this.buffered < this.highWaterMark) {
|
|
this.stream._duplexState |= WRITE_QUEUED
|
|
return true
|
|
}
|
|
|
|
this.stream._duplexState |= WRITE_QUEUED_AND_UNDRAINED
|
|
return false
|
|
}
|
|
|
|
shift () {
|
|
const data = this.queue.shift()
|
|
const stream = this.stream
|
|
|
|
this.buffered -= this.byteLength(data)
|
|
if (this.buffered === 0) stream._duplexState &= WRITE_NOT_QUEUED
|
|
|
|
return data
|
|
}
|
|
|
|
end (data) {
|
|
if (typeof data === 'function') this.stream.once('finish', data)
|
|
else if (data !== undefined && data !== null) this.push(data)
|
|
this.stream._duplexState = (this.stream._duplexState | WRITE_FINISHING) & WRITE_NON_PRIMARY
|
|
}
|
|
|
|
autoBatch (data, cb) {
|
|
const buffer = []
|
|
const stream = this.stream
|
|
|
|
buffer.push(data)
|
|
while ((stream._duplexState & WRITE_STATUS) === WRITE_QUEUED_AND_ACTIVE) {
|
|
buffer.push(stream._writableState.shift())
|
|
}
|
|
|
|
if ((stream._duplexState & OPEN_STATUS) !== 0) return cb(null)
|
|
stream._writev(buffer, cb)
|
|
}
|
|
|
|
update () {
|
|
const stream = this.stream
|
|
|
|
while ((stream._duplexState & WRITE_STATUS) === WRITE_QUEUED) {
|
|
const data = this.shift()
|
|
stream._duplexState |= WRITE_ACTIVE_AND_SYNC
|
|
stream._write(data, this.afterWrite)
|
|
stream._duplexState &= WRITE_NOT_SYNC
|
|
}
|
|
|
|
if ((stream._duplexState & WRITE_PRIMARY_AND_ACTIVE) === 0) this.updateNonPrimary()
|
|
}
|
|
|
|
updateNonPrimary () {
|
|
const stream = this.stream
|
|
|
|
if ((stream._duplexState & WRITE_FINISHING_STATUS) === WRITE_FINISHING) {
|
|
stream._duplexState = (stream._duplexState | WRITE_ACTIVE) & WRITE_NOT_FINISHING
|
|
stream._final(afterFinal.bind(this))
|
|
return
|
|
}
|
|
|
|
if ((stream._duplexState & DESTROY_STATUS) === DESTROYING) {
|
|
if ((stream._duplexState & ACTIVE_OR_TICKING) === 0) {
|
|
stream._duplexState |= ACTIVE
|
|
stream._destroy(afterDestroy.bind(this))
|
|
}
|
|
return
|
|
}
|
|
|
|
if ((stream._duplexState & IS_OPENING) === OPENING) {
|
|
stream._duplexState = (stream._duplexState | ACTIVE) & NOT_OPENING
|
|
stream._open(afterOpen.bind(this))
|
|
}
|
|
}
|
|
|
|
updateNextTick () {
|
|
if ((this.stream._duplexState & WRITE_NEXT_TICK) !== 0) return
|
|
this.stream._duplexState |= WRITE_NEXT_TICK
|
|
process.nextTick(updateWriteNT, this)
|
|
}
|
|
}
|
|
|
|
class ReadableState {
|
|
constructor (stream, { highWaterMark = 16384, map = null, mapReadable, byteLength, byteLengthReadable } = {}) {
|
|
this.stream = stream
|
|
this.queue = new FIFO()
|
|
this.highWaterMark = highWaterMark
|
|
this.buffered = 0
|
|
this.error = null
|
|
this.pipeline = null
|
|
this.byteLength = byteLengthReadable || byteLength || defaultByteLength
|
|
this.map = mapReadable || map
|
|
this.pipeTo = null
|
|
this.afterRead = afterRead.bind(this)
|
|
}
|
|
|
|
get ended () {
|
|
return (this.stream._duplexState & READ_DONE) !== 0
|
|
}
|
|
|
|
pipe (pipeTo, cb) {
|
|
if (this.pipeTo !== null) throw new Error('Can only pipe to one destination')
|
|
|
|
this.stream._duplexState |= READ_PIPE_DRAINED
|
|
this.pipeTo = pipeTo
|
|
this.pipeline = new Pipeline(this.stream, pipeTo, cb || null)
|
|
|
|
if (cb) this.stream.on('error', noop) // We already error handle this so supress crashes
|
|
|
|
if (isStreamx(pipeTo)) {
|
|
pipeTo._writableState.pipeline = this.pipeline
|
|
if (cb) pipeTo.on('error', noop) // We already error handle this so supress crashes
|
|
pipeTo.on('finish', this.pipeline.finished.bind(this.pipeline)) // TODO: just call finished from pipeTo itself
|
|
} else {
|
|
const onerror = this.pipeline.done.bind(this.pipeline, pipeTo)
|
|
const onclose = this.pipeline.done.bind(this.pipeline, pipeTo, null) // onclose has a weird bool arg
|
|
pipeTo.on('error', onerror)
|
|
pipeTo.on('close', onclose)
|
|
pipeTo.on('finish', this.pipeline.finished.bind(this.pipeline))
|
|
}
|
|
|
|
pipeTo.on('drain', afterDrain.bind(this))
|
|
this.stream.emit('piping', pipeTo)
|
|
pipeTo.emit('pipe', this.stream)
|
|
}
|
|
|
|
push (data) {
|
|
const stream = this.stream
|
|
|
|
if (data === null) {
|
|
this.highWaterMark = 0
|
|
stream._duplexState = (stream._duplexState | READ_ENDING) & READ_NON_PRIMARY_AND_PUSHED
|
|
return false
|
|
}
|
|
|
|
if (this.map !== null) data = this.map(data)
|
|
this.buffered += this.byteLength(data)
|
|
this.queue.push(data)
|
|
|
|
stream._duplexState = (stream._duplexState | READ_QUEUED) & READ_PUSHED
|
|
|
|
return this.buffered < this.highWaterMark
|
|
}
|
|
|
|
shift () {
|
|
const data = this.queue.shift()
|
|
|
|
this.buffered -= this.byteLength(data)
|
|
if (this.buffered === 0) this.stream._duplexState &= READ_NOT_QUEUED
|
|
return data
|
|
}
|
|
|
|
unshift (data) {
|
|
let tail
|
|
const pending = []
|
|
|
|
while ((tail = this.queue.shift()) !== undefined) {
|
|
pending.push(tail)
|
|
}
|
|
|
|
this.push(data)
|
|
|
|
for (let i = 0; i < pending.length; i++) {
|
|
this.queue.push(pending[i])
|
|
}
|
|
}
|
|
|
|
read () {
|
|
const stream = this.stream
|
|
|
|
if ((stream._duplexState & READ_STATUS) === READ_QUEUED) {
|
|
const data = this.shift()
|
|
if ((stream._duplexState & READ_EMIT_DATA) !== 0) stream.emit('data', data)
|
|
if (this.pipeTo !== null && this.pipeTo.write(data) === false) stream._duplexState &= READ_PIPE_NOT_DRAINED
|
|
return data
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
drain () {
|
|
const stream = this.stream
|
|
|
|
while ((stream._duplexState & READ_STATUS) === READ_QUEUED && (stream._duplexState & READ_FLOWING) !== 0) {
|
|
const data = this.shift()
|
|
if ((stream._duplexState & READ_EMIT_DATA) !== 0) stream.emit('data', data)
|
|
if (this.pipeTo !== null && this.pipeTo.write(data) === false) stream._duplexState &= READ_PIPE_NOT_DRAINED
|
|
}
|
|
}
|
|
|
|
update () {
|
|
const stream = this.stream
|
|
|
|
this.drain()
|
|
|
|
while (this.buffered < this.highWaterMark && (stream._duplexState & SHOULD_NOT_READ) === 0) {
|
|
stream._duplexState |= READ_ACTIVE_AND_SYNC_AND_NEEDS_PUSH
|
|
stream._read(this.afterRead)
|
|
stream._duplexState &= READ_NOT_SYNC
|
|
if ((stream._duplexState & READ_ACTIVE) === 0) this.drain()
|
|
}
|
|
|
|
if ((stream._duplexState & READ_READABLE_STATUS) === READ_EMIT_READABLE_AND_QUEUED) {
|
|
stream._duplexState |= READ_EMITTED_READABLE
|
|
stream.emit('readable')
|
|
}
|
|
|
|
if ((stream._duplexState & READ_PRIMARY_AND_ACTIVE) === 0) this.updateNonPrimary()
|
|
}
|
|
|
|
updateNonPrimary () {
|
|
const stream = this.stream
|
|
|
|
if ((stream._duplexState & READ_ENDING_STATUS) === READ_ENDING) {
|
|
stream._duplexState = (stream._duplexState | READ_DONE) & READ_NOT_ENDING
|
|
stream.emit('end')
|
|
if ((stream._duplexState & AUTO_DESTROY) === DONE) stream._duplexState |= DESTROYING
|
|
if (this.pipeTo !== null) this.pipeTo.end()
|
|
}
|
|
|
|
if ((stream._duplexState & DESTROY_STATUS) === DESTROYING) {
|
|
if ((stream._duplexState & ACTIVE_OR_TICKING) === 0) {
|
|
stream._duplexState |= ACTIVE
|
|
stream._destroy(afterDestroy.bind(this))
|
|
}
|
|
return
|
|
}
|
|
|
|
if ((stream._duplexState & IS_OPENING) === OPENING) {
|
|
stream._duplexState = (stream._duplexState | ACTIVE) & NOT_OPENING
|
|
stream._open(afterOpen.bind(this))
|
|
}
|
|
}
|
|
|
|
updateNextTick () {
|
|
if ((this.stream._duplexState & READ_NEXT_TICK) !== 0) return
|
|
this.stream._duplexState |= READ_NEXT_TICK
|
|
process.nextTick(updateReadNT, this)
|
|
}
|
|
}
|
|
|
|
class TransformState {
|
|
constructor (stream) {
|
|
this.data = null
|
|
this.afterTransform = afterTransform.bind(stream)
|
|
this.afterFinal = null
|
|
}
|
|
}
|
|
|
|
class Pipeline {
|
|
constructor (src, dst, cb) {
|
|
this.from = src
|
|
this.to = dst
|
|
this.afterPipe = cb
|
|
this.error = null
|
|
this.pipeToFinished = false
|
|
}
|
|
|
|
finished () {
|
|
this.pipeToFinished = true
|
|
}
|
|
|
|
done (stream, err) {
|
|
if (err) this.error = err
|
|
|
|
if (stream === this.to) {
|
|
this.to = null
|
|
|
|
if (this.from !== null) {
|
|
if ((this.from._duplexState & READ_DONE) === 0 || !this.pipeToFinished) {
|
|
this.from.destroy(this.error || new Error('Writable stream closed prematurely'))
|
|
}
|
|
return
|
|
}
|
|
}
|
|
|
|
if (stream === this.from) {
|
|
this.from = null
|
|
|
|
if (this.to !== null) {
|
|
if ((stream._duplexState & READ_DONE) === 0) {
|
|
this.to.destroy(this.error || new Error('Readable stream closed before ending'))
|
|
}
|
|
return
|
|
}
|
|
}
|
|
|
|
if (this.afterPipe !== null) this.afterPipe(this.error)
|
|
this.to = this.from = this.afterPipe = null
|
|
}
|
|
}
|
|
|
|
function afterDrain () {
|
|
this.stream._duplexState |= READ_PIPE_DRAINED
|
|
if ((this.stream._duplexState & READ_ACTIVE_AND_SYNC) === 0) this.updateNextTick()
|
|
}
|
|
|
|
function afterFinal (err) {
|
|
const stream = this.stream
|
|
if (err) stream.destroy(err)
|
|
if ((stream._duplexState & DESTROY_STATUS) === 0) {
|
|
stream._duplexState |= WRITE_DONE
|
|
stream.emit('finish')
|
|
}
|
|
if ((stream._duplexState & AUTO_DESTROY) === DONE) {
|
|
stream._duplexState |= DESTROYING
|
|
}
|
|
|
|
stream._duplexState &= WRITE_NOT_ACTIVE
|
|
this.update()
|
|
}
|
|
|
|
function afterDestroy (err) {
|
|
const stream = this.stream
|
|
|
|
if (!err && this.error !== STREAM_DESTROYED) err = this.error
|
|
if (err) stream.emit('error', err)
|
|
stream._duplexState |= DESTROYED
|
|
stream.emit('close')
|
|
|
|
const rs = stream._readableState
|
|
const ws = stream._writableState
|
|
|
|
if (rs !== null && rs.pipeline !== null) rs.pipeline.done(stream, err)
|
|
if (ws !== null && ws.pipeline !== null) ws.pipeline.done(stream, err)
|
|
}
|
|
|
|
function afterWrite (err) {
|
|
const stream = this.stream
|
|
|
|
if (err) stream.destroy(err)
|
|
stream._duplexState &= WRITE_NOT_ACTIVE
|
|
|
|
if ((stream._duplexState & WRITE_DRAIN_STATUS) === WRITE_UNDRAINED) {
|
|
stream._duplexState &= WRITE_DRAINED
|
|
if ((stream._duplexState & WRITE_EMIT_DRAIN) === WRITE_EMIT_DRAIN) {
|
|
stream.emit('drain')
|
|
}
|
|
}
|
|
|
|
if ((stream._duplexState & WRITE_SYNC) === 0) this.update()
|
|
}
|
|
|
|
function afterRead (err) {
|
|
if (err) this.stream.destroy(err)
|
|
this.stream._duplexState &= READ_NOT_ACTIVE
|
|
if ((this.stream._duplexState & READ_SYNC) === 0) this.update()
|
|
}
|
|
|
|
function updateReadNT (rs) {
|
|
rs.stream._duplexState &= READ_NOT_NEXT_TICK
|
|
rs.update()
|
|
}
|
|
|
|
function updateWriteNT (ws) {
|
|
ws.stream._duplexState &= WRITE_NOT_NEXT_TICK
|
|
ws.update()
|
|
}
|
|
|
|
function afterOpen (err) {
|
|
const stream = this.stream
|
|
|
|
if (err) stream.destroy(err)
|
|
|
|
if ((stream._duplexState & DESTROYING) === 0) {
|
|
if ((stream._duplexState & READ_PRIMARY_STATUS) === 0) stream._duplexState |= READ_PRIMARY
|
|
if ((stream._duplexState & WRITE_PRIMARY_STATUS) === 0) stream._duplexState |= WRITE_PRIMARY
|
|
stream.emit('open')
|
|
}
|
|
|
|
stream._duplexState &= NOT_ACTIVE
|
|
|
|
if (stream._writableState !== null) {
|
|
stream._writableState.update()
|
|
}
|
|
|
|
if (stream._readableState !== null) {
|
|
stream._readableState.update()
|
|
}
|
|
}
|
|
|
|
function afterTransform (err, data) {
|
|
if (data !== undefined && data !== null) this.push(data)
|
|
this._writableState.afterWrite(err)
|
|
}
|
|
|
|
class Stream extends EventEmitter {
|
|
constructor (opts) {
|
|
super()
|
|
|
|
this._duplexState = 0
|
|
this._readableState = null
|
|
this._writableState = null
|
|
|
|
if (opts) {
|
|
if (opts.open) this._open = opts.open
|
|
if (opts.destroy) this._destroy = opts.destroy
|
|
if (opts.predestroy) this._predestroy = opts.predestroy
|
|
if (opts.signal) {
|
|
opts.signal.addEventListener('abort', abort.bind(this))
|
|
}
|
|
}
|
|
}
|
|
|
|
_open (cb) {
|
|
cb(null)
|
|
}
|
|
|
|
_destroy (cb) {
|
|
cb(null)
|
|
}
|
|
|
|
_predestroy () {
|
|
// does nothing
|
|
}
|
|
|
|
get readable () {
|
|
return this._readableState !== null ? true : undefined
|
|
}
|
|
|
|
get writable () {
|
|
return this._writableState !== null ? true : undefined
|
|
}
|
|
|
|
get destroyed () {
|
|
return (this._duplexState & DESTROYED) !== 0
|
|
}
|
|
|
|
get destroying () {
|
|
return (this._duplexState & DESTROY_STATUS) !== 0
|
|
}
|
|
|
|
destroy (err) {
|
|
if ((this._duplexState & DESTROY_STATUS) === 0) {
|
|
if (!err) err = STREAM_DESTROYED
|
|
this._duplexState = (this._duplexState | DESTROYING) & NON_PRIMARY
|
|
if (this._readableState !== null) {
|
|
this._readableState.error = err
|
|
this._readableState.updateNextTick()
|
|
}
|
|
if (this._writableState !== null) {
|
|
this._writableState.error = err
|
|
this._writableState.updateNextTick()
|
|
}
|
|
this._predestroy()
|
|
}
|
|
}
|
|
|
|
on (name, fn) {
|
|
if (this._readableState !== null) {
|
|
if (name === 'data') {
|
|
this._duplexState |= (READ_EMIT_DATA | READ_RESUMED)
|
|
this._readableState.updateNextTick()
|
|
}
|
|
if (name === 'readable') {
|
|
this._duplexState |= READ_EMIT_READABLE
|
|
this._readableState.updateNextTick()
|
|
}
|
|
}
|
|
|
|
if (this._writableState !== null) {
|
|
if (name === 'drain') {
|
|
this._duplexState |= WRITE_EMIT_DRAIN
|
|
this._writableState.updateNextTick()
|
|
}
|
|
}
|
|
|
|
return super.on(name, fn)
|
|
}
|
|
}
|
|
|
|
class Readable extends Stream {
|
|
constructor (opts) {
|
|
super(opts)
|
|
|
|
this._duplexState |= OPENING | WRITE_DONE
|
|
this._readableState = new ReadableState(this, opts)
|
|
|
|
if (opts) {
|
|
if (opts.read) this._read = opts.read
|
|
}
|
|
}
|
|
|
|
_read (cb) {
|
|
cb(null)
|
|
}
|
|
|
|
pipe (dest, cb) {
|
|
this._readableState.pipe(dest, cb)
|
|
this._readableState.updateNextTick()
|
|
return dest
|
|
}
|
|
|
|
read () {
|
|
this._readableState.updateNextTick()
|
|
return this._readableState.read()
|
|
}
|
|
|
|
push (data) {
|
|
this._readableState.updateNextTick()
|
|
return this._readableState.push(data)
|
|
}
|
|
|
|
unshift (data) {
|
|
this._readableState.updateNextTick()
|
|
return this._readableState.unshift(data)
|
|
}
|
|
|
|
resume () {
|
|
this._duplexState |= READ_RESUMED
|
|
this._readableState.updateNextTick()
|
|
return this
|
|
}
|
|
|
|
pause () {
|
|
this._duplexState &= READ_PAUSED
|
|
return this
|
|
}
|
|
|
|
static _fromAsyncIterator (ite, opts) {
|
|
let destroy
|
|
|
|
const rs = new Readable({
|
|
...opts,
|
|
read (cb) {
|
|
ite.next().then(push).then(cb.bind(null, null)).catch(cb)
|
|
},
|
|
predestroy () {
|
|
destroy = ite.return()
|
|
},
|
|
destroy (cb) {
|
|
destroy.then(cb.bind(null, null)).catch(cb)
|
|
}
|
|
})
|
|
|
|
return rs
|
|
|
|
function push (data) {
|
|
if (data.done) rs.push(null)
|
|
else rs.push(data.value)
|
|
}
|
|
}
|
|
|
|
static from (data, opts) {
|
|
if (isReadStreamx(data)) return data
|
|
if (data[asyncIterator]) return this._fromAsyncIterator(data[asyncIterator](), opts)
|
|
if (!Array.isArray(data)) data = data === undefined ? [] : [data]
|
|
|
|
let i = 0
|
|
return new Readable({
|
|
...opts,
|
|
read (cb) {
|
|
this.push(i === data.length ? null : data[i++])
|
|
cb(null)
|
|
}
|
|
})
|
|
}
|
|
|
|
static isBackpressured (rs) {
|
|
return (rs._duplexState & READ_BACKPRESSURE_STATUS) !== 0 || rs._readableState.buffered >= rs._readableState.highWaterMark
|
|
}
|
|
|
|
static isPaused (rs) {
|
|
return (rs._duplexState & READ_RESUMED) === 0
|
|
}
|
|
|
|
[asyncIterator] () {
|
|
const stream = this
|
|
|
|
let error = null
|
|
let promiseResolve = null
|
|
let promiseReject = null
|
|
|
|
this.on('error', (err) => { error = err })
|
|
this.on('readable', onreadable)
|
|
this.on('close', onclose)
|
|
|
|
return {
|
|
[asyncIterator] () {
|
|
return this
|
|
},
|
|
next () {
|
|
return new Promise(function (resolve, reject) {
|
|
promiseResolve = resolve
|
|
promiseReject = reject
|
|
const data = stream.read()
|
|
if (data !== null) ondata(data)
|
|
else if ((stream._duplexState & DESTROYED) !== 0) ondata(null)
|
|
})
|
|
},
|
|
return () {
|
|
return destroy(null)
|
|
},
|
|
throw (err) {
|
|
return destroy(err)
|
|
}
|
|
}
|
|
|
|
function onreadable () {
|
|
if (promiseResolve !== null) ondata(stream.read())
|
|
}
|
|
|
|
function onclose () {
|
|
if (promiseResolve !== null) ondata(null)
|
|
}
|
|
|
|
function ondata (data) {
|
|
if (promiseReject === null) return
|
|
if (error) promiseReject(error)
|
|
else if (data === null && (stream._duplexState & READ_DONE) === 0) promiseReject(STREAM_DESTROYED)
|
|
else promiseResolve({ value: data, done: data === null })
|
|
promiseReject = promiseResolve = null
|
|
}
|
|
|
|
function destroy (err) {
|
|
stream.destroy(err)
|
|
return new Promise((resolve, reject) => {
|
|
if (stream._duplexState & DESTROYED) return resolve({ value: undefined, done: true })
|
|
stream.once('close', function () {
|
|
if (err) reject(err)
|
|
else resolve({ value: undefined, done: true })
|
|
})
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
class Writable extends Stream {
|
|
constructor (opts) {
|
|
super(opts)
|
|
|
|
this._duplexState |= OPENING | READ_DONE
|
|
this._writableState = new WritableState(this, opts)
|
|
|
|
if (opts) {
|
|
if (opts.writev) this._writev = opts.writev
|
|
if (opts.write) this._write = opts.write
|
|
if (opts.final) this._final = opts.final
|
|
}
|
|
}
|
|
|
|
_writev (batch, cb) {
|
|
cb(null)
|
|
}
|
|
|
|
_write (data, cb) {
|
|
this._writableState.autoBatch(data, cb)
|
|
}
|
|
|
|
_final (cb) {
|
|
cb(null)
|
|
}
|
|
|
|
static isBackpressured (ws) {
|
|
return (ws._duplexState & WRITE_BACKPRESSURE_STATUS) !== 0
|
|
}
|
|
|
|
write (data) {
|
|
this._writableState.updateNextTick()
|
|
return this._writableState.push(data)
|
|
}
|
|
|
|
end (data) {
|
|
this._writableState.updateNextTick()
|
|
this._writableState.end(data)
|
|
return this
|
|
}
|
|
}
|
|
|
|
class Duplex extends Readable { // and Writable
|
|
constructor (opts) {
|
|
super(opts)
|
|
|
|
this._duplexState = OPENING
|
|
this._writableState = new WritableState(this, opts)
|
|
|
|
if (opts) {
|
|
if (opts.writev) this._writev = opts.writev
|
|
if (opts.write) this._write = opts.write
|
|
if (opts.final) this._final = opts.final
|
|
}
|
|
}
|
|
|
|
_writev (batch, cb) {
|
|
cb(null)
|
|
}
|
|
|
|
_write (data, cb) {
|
|
this._writableState.autoBatch(data, cb)
|
|
}
|
|
|
|
_final (cb) {
|
|
cb(null)
|
|
}
|
|
|
|
write (data) {
|
|
this._writableState.updateNextTick()
|
|
return this._writableState.push(data)
|
|
}
|
|
|
|
end (data) {
|
|
this._writableState.updateNextTick()
|
|
this._writableState.end(data)
|
|
return this
|
|
}
|
|
}
|
|
|
|
class Transform extends Duplex {
|
|
constructor (opts) {
|
|
super(opts)
|
|
this._transformState = new TransformState(this)
|
|
|
|
if (opts) {
|
|
if (opts.transform) this._transform = opts.transform
|
|
if (opts.flush) this._flush = opts.flush
|
|
}
|
|
}
|
|
|
|
_write (data, cb) {
|
|
if (this._readableState.buffered >= this._readableState.highWaterMark) {
|
|
this._transformState.data = data
|
|
} else {
|
|
this._transform(data, this._transformState.afterTransform)
|
|
}
|
|
}
|
|
|
|
_read (cb) {
|
|
if (this._transformState.data !== null) {
|
|
const data = this._transformState.data
|
|
this._transformState.data = null
|
|
cb(null)
|
|
this._transform(data, this._transformState.afterTransform)
|
|
} else {
|
|
cb(null)
|
|
}
|
|
}
|
|
|
|
_transform (data, cb) {
|
|
cb(null, data)
|
|
}
|
|
|
|
_flush (cb) {
|
|
cb(null)
|
|
}
|
|
|
|
_final (cb) {
|
|
this._transformState.afterFinal = cb
|
|
this._flush(transformAfterFlush.bind(this))
|
|
}
|
|
}
|
|
|
|
class PassThrough extends Transform {}
|
|
|
|
function transformAfterFlush (err, data) {
|
|
const cb = this._transformState.afterFinal
|
|
if (err) return cb(err)
|
|
if (data !== null && data !== undefined) this.push(data)
|
|
this.push(null)
|
|
cb(null)
|
|
}
|
|
|
|
function pipelinePromise (...streams) {
|
|
return new Promise((resolve, reject) => {
|
|
return pipeline(...streams, (err) => {
|
|
if (err) return reject(err)
|
|
resolve()
|
|
})
|
|
})
|
|
}
|
|
|
|
function pipeline (stream, ...streams) {
|
|
const all = Array.isArray(stream) ? [...stream, ...streams] : [stream, ...streams]
|
|
const done = (all.length && typeof all[all.length - 1] === 'function') ? all.pop() : null
|
|
|
|
if (all.length < 2) throw new Error('Pipeline requires at least 2 streams')
|
|
|
|
let src = all[0]
|
|
let dest = null
|
|
let error = null
|
|
|
|
for (let i = 1; i < all.length; i++) {
|
|
dest = all[i]
|
|
|
|
if (isStreamx(src)) {
|
|
src.pipe(dest, onerror)
|
|
} else {
|
|
errorHandle(src, true, i > 1, onerror)
|
|
src.pipe(dest)
|
|
}
|
|
|
|
src = dest
|
|
}
|
|
|
|
if (done) {
|
|
let fin = false
|
|
|
|
dest.on('finish', () => { fin = true })
|
|
dest.on('error', err => { error = error || err })
|
|
dest.on('close', () => done(error || (fin ? null : PREMATURE_CLOSE)))
|
|
}
|
|
|
|
return dest
|
|
|
|
function errorHandle (s, rd, wr, onerror) {
|
|
s.on('error', onerror)
|
|
s.on('close', onclose)
|
|
|
|
function onclose () {
|
|
if (rd && s._readableState && !s._readableState.ended) return onerror(PREMATURE_CLOSE)
|
|
if (wr && s._writableState && !s._writableState.ended) return onerror(PREMATURE_CLOSE)
|
|
}
|
|
}
|
|
|
|
function onerror (err) {
|
|
if (!err || error) return
|
|
error = err
|
|
|
|
for (const s of all) {
|
|
s.destroy(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
function isStream (stream) {
|
|
return !!stream._readableState || !!stream._writableState
|
|
}
|
|
|
|
function isStreamx (stream) {
|
|
return typeof stream._duplexState === 'number' && isStream(stream)
|
|
}
|
|
|
|
function isReadStreamx (stream) {
|
|
return isStreamx(stream) && stream.readable
|
|
}
|
|
|
|
function isTypedArray (data) {
|
|
return typeof data === 'object' && data !== null && typeof data.byteLength === 'number'
|
|
}
|
|
|
|
function defaultByteLength (data) {
|
|
return isTypedArray(data) ? data.byteLength : 1024
|
|
}
|
|
|
|
function noop () {}
|
|
|
|
function abort () {
|
|
this.destroy(new Error('Stream aborted.'))
|
|
}
|
|
|
|
module.exports = {
|
|
pipeline,
|
|
pipelinePromise,
|
|
isStream,
|
|
isStreamx,
|
|
Stream,
|
|
Writable,
|
|
Readable,
|
|
Duplex,
|
|
Transform,
|
|
// Export PassThrough for compatibility with Node.js core's stream module
|
|
PassThrough
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/string_decoder/lib/string_decoder.js":
|
|
/*!***********************************************************!*\
|
|
!*** ./node_modules/string_decoder/lib/string_decoder.js ***!
|
|
\***********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
/*<replacement>*/
|
|
|
|
var Buffer = __webpack_require__(/*! safe-buffer */ "./node_modules/safe-buffer/index.js").Buffer;
|
|
/*</replacement>*/
|
|
|
|
var isEncoding = Buffer.isEncoding || function (encoding) {
|
|
encoding = '' + encoding;
|
|
switch (encoding && encoding.toLowerCase()) {
|
|
case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw':
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
};
|
|
|
|
function _normalizeEncoding(enc) {
|
|
if (!enc) return 'utf8';
|
|
var retried;
|
|
while (true) {
|
|
switch (enc) {
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return 'utf8';
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
case 'utf16le':
|
|
case 'utf-16le':
|
|
return 'utf16le';
|
|
case 'latin1':
|
|
case 'binary':
|
|
return 'latin1';
|
|
case 'base64':
|
|
case 'ascii':
|
|
case 'hex':
|
|
return enc;
|
|
default:
|
|
if (retried) return; // undefined
|
|
enc = ('' + enc).toLowerCase();
|
|
retried = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
// Do not cache `Buffer.isEncoding` when checking encoding names as some
|
|
// modules monkey-patch it to support additional encodings
|
|
function normalizeEncoding(enc) {
|
|
var nenc = _normalizeEncoding(enc);
|
|
if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc);
|
|
return nenc || enc;
|
|
}
|
|
|
|
// StringDecoder provides an interface for efficiently splitting a series of
|
|
// buffers into a series of JS strings without breaking apart multi-byte
|
|
// characters.
|
|
exports.StringDecoder = StringDecoder;
|
|
function StringDecoder(encoding) {
|
|
this.encoding = normalizeEncoding(encoding);
|
|
var nb;
|
|
switch (this.encoding) {
|
|
case 'utf16le':
|
|
this.text = utf16Text;
|
|
this.end = utf16End;
|
|
nb = 4;
|
|
break;
|
|
case 'utf8':
|
|
this.fillLast = utf8FillLast;
|
|
nb = 4;
|
|
break;
|
|
case 'base64':
|
|
this.text = base64Text;
|
|
this.end = base64End;
|
|
nb = 3;
|
|
break;
|
|
default:
|
|
this.write = simpleWrite;
|
|
this.end = simpleEnd;
|
|
return;
|
|
}
|
|
this.lastNeed = 0;
|
|
this.lastTotal = 0;
|
|
this.lastChar = Buffer.allocUnsafe(nb);
|
|
}
|
|
|
|
StringDecoder.prototype.write = function (buf) {
|
|
if (buf.length === 0) return '';
|
|
var r;
|
|
var i;
|
|
if (this.lastNeed) {
|
|
r = this.fillLast(buf);
|
|
if (r === undefined) return '';
|
|
i = this.lastNeed;
|
|
this.lastNeed = 0;
|
|
} else {
|
|
i = 0;
|
|
}
|
|
if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i);
|
|
return r || '';
|
|
};
|
|
|
|
StringDecoder.prototype.end = utf8End;
|
|
|
|
// Returns only complete characters in a Buffer
|
|
StringDecoder.prototype.text = utf8Text;
|
|
|
|
// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer
|
|
StringDecoder.prototype.fillLast = function (buf) {
|
|
if (this.lastNeed <= buf.length) {
|
|
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed);
|
|
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
|
}
|
|
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length);
|
|
this.lastNeed -= buf.length;
|
|
};
|
|
|
|
// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a
|
|
// continuation byte. If an invalid byte is detected, -2 is returned.
|
|
function utf8CheckByte(byte) {
|
|
if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4;
|
|
return byte >> 6 === 0x02 ? -1 : -2;
|
|
}
|
|
|
|
// Checks at most 3 bytes at the end of a Buffer in order to detect an
|
|
// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4)
|
|
// needed to complete the UTF-8 character (if applicable) are returned.
|
|
function utf8CheckIncomplete(self, buf, i) {
|
|
var j = buf.length - 1;
|
|
if (j < i) return 0;
|
|
var nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) self.lastNeed = nb - 1;
|
|
return nb;
|
|
}
|
|
if (--j < i || nb === -2) return 0;
|
|
nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) self.lastNeed = nb - 2;
|
|
return nb;
|
|
}
|
|
if (--j < i || nb === -2) return 0;
|
|
nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) {
|
|
if (nb === 2) nb = 0;else self.lastNeed = nb - 3;
|
|
}
|
|
return nb;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Validates as many continuation bytes for a multi-byte UTF-8 character as
|
|
// needed or are available. If we see a non-continuation byte where we expect
|
|
// one, we "replace" the validated continuation bytes we've seen so far with
|
|
// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding
|
|
// behavior. The continuation byte check is included three times in the case
|
|
// where all of the continuation bytes for a character exist in the same buffer.
|
|
// It is also done this way as a slight performance increase instead of using a
|
|
// loop.
|
|
function utf8CheckExtraBytes(self, buf, p) {
|
|
if ((buf[0] & 0xC0) !== 0x80) {
|
|
self.lastNeed = 0;
|
|
return '\ufffd';
|
|
}
|
|
if (self.lastNeed > 1 && buf.length > 1) {
|
|
if ((buf[1] & 0xC0) !== 0x80) {
|
|
self.lastNeed = 1;
|
|
return '\ufffd';
|
|
}
|
|
if (self.lastNeed > 2 && buf.length > 2) {
|
|
if ((buf[2] & 0xC0) !== 0x80) {
|
|
self.lastNeed = 2;
|
|
return '\ufffd';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer.
|
|
function utf8FillLast(buf) {
|
|
var p = this.lastTotal - this.lastNeed;
|
|
var r = utf8CheckExtraBytes(this, buf, p);
|
|
if (r !== undefined) return r;
|
|
if (this.lastNeed <= buf.length) {
|
|
buf.copy(this.lastChar, p, 0, this.lastNeed);
|
|
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
|
}
|
|
buf.copy(this.lastChar, p, 0, buf.length);
|
|
this.lastNeed -= buf.length;
|
|
}
|
|
|
|
// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a
|
|
// partial character, the character's bytes are buffered until the required
|
|
// number of bytes are available.
|
|
function utf8Text(buf, i) {
|
|
var total = utf8CheckIncomplete(this, buf, i);
|
|
if (!this.lastNeed) return buf.toString('utf8', i);
|
|
this.lastTotal = total;
|
|
var end = buf.length - (total - this.lastNeed);
|
|
buf.copy(this.lastChar, 0, end);
|
|
return buf.toString('utf8', i, end);
|
|
}
|
|
|
|
// For UTF-8, a replacement character is added when ending on a partial
|
|
// character.
|
|
function utf8End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : '';
|
|
if (this.lastNeed) return r + '\ufffd';
|
|
return r;
|
|
}
|
|
|
|
// UTF-16LE typically needs two bytes per character, but even if we have an even
|
|
// number of bytes available, we need to check if we end on a leading/high
|
|
// surrogate. In that case, we need to wait for the next two bytes in order to
|
|
// decode the last character properly.
|
|
function utf16Text(buf, i) {
|
|
if ((buf.length - i) % 2 === 0) {
|
|
var r = buf.toString('utf16le', i);
|
|
if (r) {
|
|
var c = r.charCodeAt(r.length - 1);
|
|
if (c >= 0xD800 && c <= 0xDBFF) {
|
|
this.lastNeed = 2;
|
|
this.lastTotal = 4;
|
|
this.lastChar[0] = buf[buf.length - 2];
|
|
this.lastChar[1] = buf[buf.length - 1];
|
|
return r.slice(0, -1);
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
this.lastNeed = 1;
|
|
this.lastTotal = 2;
|
|
this.lastChar[0] = buf[buf.length - 1];
|
|
return buf.toString('utf16le', i, buf.length - 1);
|
|
}
|
|
|
|
// For UTF-16LE we do not explicitly append special replacement characters if we
|
|
// end on a partial character, we simply let v8 handle that.
|
|
function utf16End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : '';
|
|
if (this.lastNeed) {
|
|
var end = this.lastTotal - this.lastNeed;
|
|
return r + this.lastChar.toString('utf16le', 0, end);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
function base64Text(buf, i) {
|
|
var n = (buf.length - i) % 3;
|
|
if (n === 0) return buf.toString('base64', i);
|
|
this.lastNeed = 3 - n;
|
|
this.lastTotal = 3;
|
|
if (n === 1) {
|
|
this.lastChar[0] = buf[buf.length - 1];
|
|
} else {
|
|
this.lastChar[0] = buf[buf.length - 2];
|
|
this.lastChar[1] = buf[buf.length - 1];
|
|
}
|
|
return buf.toString('base64', i, buf.length - n);
|
|
}
|
|
|
|
function base64End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : '';
|
|
if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed);
|
|
return r;
|
|
}
|
|
|
|
// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex)
|
|
function simpleWrite(buf) {
|
|
return buf.toString(this.encoding);
|
|
}
|
|
|
|
function simpleEnd(buf) {
|
|
return buf && buf.length ? this.write(buf) : '';
|
|
}
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/thirty-two/lib/thirty-two/index.js":
|
|
/*!*********************************************************!*\
|
|
!*** ./node_modules/thirty-two/lib/thirty-two/index.js ***!
|
|
\*********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
/*
|
|
Copyright (c) 2011, Chris Umbel
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
*/
|
|
|
|
var base32 = __webpack_require__(/*! ./thirty-two */ "./node_modules/thirty-two/lib/thirty-two/thirty-two.js");
|
|
|
|
exports.encode = base32.encode;
|
|
exports.decode = base32.decode;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/thirty-two/lib/thirty-two/thirty-two.js":
|
|
/*!**************************************************************!*\
|
|
!*** ./node_modules/thirty-two/lib/thirty-two/thirty-two.js ***!
|
|
\**************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*
|
|
Copyright (c) 2011, Chris Umbel
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
*/
|
|
|
|
|
|
var charTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
var byteTable = [
|
|
0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
|
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
|
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
|
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
|
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
|
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
|
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
];
|
|
|
|
function quintetCount(buff) {
|
|
var quintets = Math.floor(buff.length / 5);
|
|
return buff.length % 5 === 0 ? quintets: quintets + 1;
|
|
}
|
|
|
|
exports.encode = function(plain) {
|
|
if(!Buffer.isBuffer(plain)){
|
|
plain = new Buffer(plain);
|
|
}
|
|
var i = 0;
|
|
var j = 0;
|
|
var shiftIndex = 0;
|
|
var digit = 0;
|
|
var encoded = new Buffer(quintetCount(plain) * 8);
|
|
|
|
/* byte by byte isn't as pretty as quintet by quintet but tests a bit
|
|
faster. will have to revisit. */
|
|
while(i < plain.length) {
|
|
var current = plain[i];
|
|
|
|
if(shiftIndex > 3) {
|
|
digit = current & (0xff >> shiftIndex);
|
|
shiftIndex = (shiftIndex + 5) % 8;
|
|
digit = (digit << shiftIndex) | ((i + 1 < plain.length) ?
|
|
plain[i + 1] : 0) >> (8 - shiftIndex);
|
|
i++;
|
|
} else {
|
|
digit = (current >> (8 - (shiftIndex + 5))) & 0x1f;
|
|
shiftIndex = (shiftIndex + 5) % 8;
|
|
if(shiftIndex === 0) i++;
|
|
}
|
|
|
|
encoded[j] = charTable.charCodeAt(digit);
|
|
j++;
|
|
}
|
|
|
|
for(i = j; i < encoded.length; i++) {
|
|
encoded[i] = 0x3d; //'='.charCodeAt(0)
|
|
}
|
|
|
|
return encoded;
|
|
};
|
|
|
|
exports.decode = function(encoded) {
|
|
var shiftIndex = 0;
|
|
var plainDigit = 0;
|
|
var plainChar;
|
|
var plainPos = 0;
|
|
if(!Buffer.isBuffer(encoded)){
|
|
encoded = new Buffer(encoded);
|
|
}
|
|
var decoded = new Buffer(Math.ceil(encoded.length * 5 / 8));
|
|
|
|
/* byte by byte isn't as pretty as octet by octet but tests a bit
|
|
faster. will have to revisit. */
|
|
for(var i = 0; i < encoded.length; i++) {
|
|
if(encoded[i] === 0x3d){ //'='
|
|
break;
|
|
}
|
|
|
|
var encodedByte = encoded[i] - 0x30;
|
|
|
|
if(encodedByte < byteTable.length) {
|
|
plainDigit = byteTable[encodedByte];
|
|
|
|
if(shiftIndex <= 3) {
|
|
shiftIndex = (shiftIndex + 5) % 8;
|
|
|
|
if(shiftIndex === 0) {
|
|
plainChar |= plainDigit;
|
|
decoded[plainPos] = plainChar;
|
|
plainPos++;
|
|
plainChar = 0;
|
|
} else {
|
|
plainChar |= 0xff & (plainDigit << (8 - shiftIndex));
|
|
}
|
|
} else {
|
|
shiftIndex = (shiftIndex + 5) % 8;
|
|
plainChar |= 0xff & (plainDigit >>> shiftIndex);
|
|
decoded[plainPos] = plainChar;
|
|
plainPos++;
|
|
|
|
plainChar = 0xff & (plainDigit << (8 - shiftIndex));
|
|
}
|
|
} else {
|
|
throw new Error('Invalid input - it is not base32 encoded string');
|
|
}
|
|
}
|
|
|
|
return decoded.slice(0, plainPos);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/to-arraybuffer/index.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/to-arraybuffer/index.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var Buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js").Buffer
|
|
|
|
module.exports = function (buf) {
|
|
// If the buffer is backed by a Uint8Array, a faster version will work
|
|
if (buf instanceof Uint8Array) {
|
|
// If the buffer isn't a subarray, return the underlying ArrayBuffer
|
|
if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) {
|
|
return buf.buffer
|
|
} else if (typeof buf.buffer.slice === 'function') {
|
|
// Otherwise we need to get a proper copy
|
|
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)
|
|
}
|
|
}
|
|
|
|
if (Buffer.isBuffer(buf)) {
|
|
// This is the slow version that will work with any Buffer
|
|
// implementation (even in old browsers)
|
|
var arrayCopy = new Uint8Array(buf.length)
|
|
var len = buf.length
|
|
for (var i = 0; i < len; i++) {
|
|
arrayCopy[i] = buf[i]
|
|
}
|
|
return arrayCopy.buffer
|
|
} else {
|
|
throw new Error('Argument must be a Buffer')
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/torrent-discovery/index.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/torrent-discovery/index.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
/*! torrent-discovery. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('torrent-discovery')
|
|
const DHT = __webpack_require__(/*! bittorrent-dht/client */ "?42e5") // empty object in browser
|
|
const EventEmitter = __webpack_require__(/*! events */ "./node_modules/events/events.js").EventEmitter
|
|
const parallel = __webpack_require__(/*! run-parallel */ "./node_modules/run-parallel/index.js")
|
|
const Tracker = __webpack_require__(/*! bittorrent-tracker/client */ "./node_modules/bittorrent-tracker/client.js")
|
|
const LSD = __webpack_require__(/*! bittorrent-lsd */ "?72f0")
|
|
|
|
class Discovery extends EventEmitter {
|
|
constructor (opts) {
|
|
super()
|
|
|
|
if (!opts.peerId) throw new Error('Option `peerId` is required')
|
|
if (!opts.infoHash) throw new Error('Option `infoHash` is required')
|
|
if (!process.browser && !opts.port) throw new Error('Option `port` is required')
|
|
|
|
this.peerId = typeof opts.peerId === 'string'
|
|
? opts.peerId
|
|
: opts.peerId.toString('hex')
|
|
this.infoHash = typeof opts.infoHash === 'string'
|
|
? opts.infoHash.toLowerCase()
|
|
: opts.infoHash.toString('hex')
|
|
this._port = opts.port // torrent port
|
|
this._userAgent = opts.userAgent // User-Agent header for http requests
|
|
|
|
this.destroyed = false
|
|
|
|
this._announce = opts.announce || []
|
|
this._intervalMs = opts.intervalMs || (15 * 60 * 1000)
|
|
this._trackerOpts = null
|
|
this._dhtAnnouncing = false
|
|
this._dhtTimeout = false
|
|
this._internalDHT = false // is the DHT created internally?
|
|
|
|
this._onWarning = err => {
|
|
this.emit('warning', err)
|
|
}
|
|
this._onError = err => {
|
|
this.emit('error', err)
|
|
}
|
|
this._onDHTPeer = (peer, infoHash) => {
|
|
if (infoHash.toString('hex') !== this.infoHash) return
|
|
this.emit('peer', `${peer.host}:${peer.port}`, 'dht')
|
|
}
|
|
this._onTrackerPeer = peer => {
|
|
this.emit('peer', peer, 'tracker')
|
|
}
|
|
this._onTrackerAnnounce = () => {
|
|
this.emit('trackerAnnounce')
|
|
}
|
|
this._onLSDPeer = (peer, infoHash) => {
|
|
this.emit('peer', peer, 'lsd')
|
|
}
|
|
|
|
const createDHT = (port, opts) => {
|
|
const dht = new DHT(opts)
|
|
dht.on('warning', this._onWarning)
|
|
dht.on('error', this._onError)
|
|
dht.listen(port)
|
|
this._internalDHT = true
|
|
return dht
|
|
}
|
|
|
|
if (opts.tracker === false) {
|
|
this.tracker = null
|
|
} else if (opts.tracker && typeof opts.tracker === 'object') {
|
|
this._trackerOpts = Object.assign({}, opts.tracker)
|
|
this.tracker = this._createTracker()
|
|
} else {
|
|
this.tracker = this._createTracker()
|
|
}
|
|
|
|
if (opts.dht === false || typeof DHT !== 'function') {
|
|
this.dht = null
|
|
} else if (opts.dht && typeof opts.dht.addNode === 'function') {
|
|
this.dht = opts.dht
|
|
} else if (opts.dht && typeof opts.dht === 'object') {
|
|
this.dht = createDHT(opts.dhtPort, opts.dht)
|
|
} else {
|
|
this.dht = createDHT(opts.dhtPort)
|
|
}
|
|
|
|
if (this.dht) {
|
|
this.dht.on('peer', this._onDHTPeer)
|
|
this._dhtAnnounce()
|
|
}
|
|
|
|
if (opts.lsd === false || typeof LSD !== 'function') {
|
|
this.lsd = null
|
|
} else {
|
|
this.lsd = this._createLSD()
|
|
}
|
|
}
|
|
|
|
updatePort (port) {
|
|
if (port === this._port) return
|
|
this._port = port
|
|
|
|
if (this.dht) this._dhtAnnounce()
|
|
|
|
if (this.tracker) {
|
|
this.tracker.stop()
|
|
this.tracker.destroy(() => {
|
|
this.tracker = this._createTracker()
|
|
})
|
|
}
|
|
}
|
|
|
|
complete (opts) {
|
|
if (this.tracker) {
|
|
this.tracker.complete(opts)
|
|
}
|
|
}
|
|
|
|
destroy (cb) {
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
|
|
clearTimeout(this._dhtTimeout)
|
|
|
|
const tasks = []
|
|
|
|
if (this.tracker) {
|
|
this.tracker.stop()
|
|
this.tracker.removeListener('warning', this._onWarning)
|
|
this.tracker.removeListener('error', this._onError)
|
|
this.tracker.removeListener('peer', this._onTrackerPeer)
|
|
this.tracker.removeListener('update', this._onTrackerAnnounce)
|
|
tasks.push(cb => {
|
|
this.tracker.destroy(cb)
|
|
})
|
|
}
|
|
|
|
if (this.dht) {
|
|
this.dht.removeListener('peer', this._onDHTPeer)
|
|
}
|
|
|
|
if (this._internalDHT) {
|
|
this.dht.removeListener('warning', this._onWarning)
|
|
this.dht.removeListener('error', this._onError)
|
|
tasks.push(cb => {
|
|
this.dht.destroy(cb)
|
|
})
|
|
}
|
|
|
|
if (this.lsd) {
|
|
this.lsd.removeListener('warning', this._onWarning)
|
|
this.lsd.removeListener('error', this._onError)
|
|
this.lsd.removeListener('peer', this._onLSDPeer)
|
|
tasks.push(cb => {
|
|
this.lsd.destroy(cb)
|
|
})
|
|
}
|
|
|
|
parallel(tasks, cb)
|
|
|
|
// cleanup
|
|
this.dht = null
|
|
this.tracker = null
|
|
this.lsd = null
|
|
this._announce = null
|
|
}
|
|
|
|
_createTracker () {
|
|
const opts = Object.assign({}, this._trackerOpts, {
|
|
infoHash: this.infoHash,
|
|
announce: this._announce,
|
|
peerId: this.peerId,
|
|
port: this._port,
|
|
userAgent: this._userAgent
|
|
})
|
|
|
|
const tracker = new Tracker(opts)
|
|
tracker.on('warning', this._onWarning)
|
|
tracker.on('error', this._onError)
|
|
tracker.on('peer', this._onTrackerPeer)
|
|
tracker.on('update', this._onTrackerAnnounce)
|
|
tracker.setInterval(this._intervalMs)
|
|
tracker.start()
|
|
return tracker
|
|
}
|
|
|
|
_dhtAnnounce () {
|
|
if (this._dhtAnnouncing) return
|
|
debug('dht announce')
|
|
|
|
this._dhtAnnouncing = true
|
|
clearTimeout(this._dhtTimeout)
|
|
|
|
this.dht.announce(this.infoHash, this._port, err => {
|
|
this._dhtAnnouncing = false
|
|
debug('dht announce complete')
|
|
|
|
if (err) this.emit('warning', err)
|
|
this.emit('dhtAnnounce')
|
|
|
|
if (!this.destroyed) {
|
|
this._dhtTimeout = setTimeout(() => {
|
|
this._dhtAnnounce()
|
|
}, this._intervalMs + Math.floor(Math.random() * this._intervalMs / 5))
|
|
if (this._dhtTimeout.unref) this._dhtTimeout.unref()
|
|
}
|
|
})
|
|
}
|
|
|
|
_createLSD () {
|
|
const opts = Object.assign({}, {
|
|
infoHash: this.infoHash,
|
|
peerId: this.peerId,
|
|
port: this._port
|
|
})
|
|
|
|
const lsd = new LSD(opts)
|
|
lsd.on('warning', this._onWarning)
|
|
lsd.on('error', this._onError)
|
|
lsd.on('peer', this._onLSDPeer)
|
|
lsd.start()
|
|
return lsd
|
|
}
|
|
}
|
|
|
|
module.exports = Discovery
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/torrent-piece/index.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/torrent-piece/index.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! torrent-piece. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */
|
|
const BLOCK_LENGTH = 1 << 14
|
|
|
|
class Piece {
|
|
constructor (length) {
|
|
this.length = length
|
|
this.missing = length
|
|
this.sources = null
|
|
|
|
this._chunks = Math.ceil(length / BLOCK_LENGTH)
|
|
this._remainder = (length % BLOCK_LENGTH) || BLOCK_LENGTH
|
|
this._buffered = 0
|
|
this._buffer = null
|
|
this._cancellations = null
|
|
this._reservations = 0
|
|
this._flushed = false
|
|
}
|
|
|
|
chunkLength (i) {
|
|
return i === this._chunks - 1 ? this._remainder : BLOCK_LENGTH
|
|
}
|
|
|
|
chunkLengthRemaining (i) {
|
|
return this.length - (i * BLOCK_LENGTH)
|
|
}
|
|
|
|
chunkOffset (i) {
|
|
return i * BLOCK_LENGTH
|
|
}
|
|
|
|
reserve () {
|
|
if (!this.init()) return -1
|
|
if (this._cancellations.length) return this._cancellations.pop()
|
|
if (this._reservations < this._chunks) return this._reservations++
|
|
return -1
|
|
}
|
|
|
|
reserveRemaining () {
|
|
if (!this.init()) return -1
|
|
if (this._cancellations.length || this._reservations < this._chunks) {
|
|
let min = this._reservations
|
|
while (this._cancellations.length) {
|
|
min = Math.min(min, this._cancellations.pop())
|
|
}
|
|
this._reservations = this._chunks
|
|
return min
|
|
}
|
|
return -1
|
|
}
|
|
|
|
cancel (i) {
|
|
if (!this.init()) return
|
|
this._cancellations.push(i)
|
|
}
|
|
|
|
cancelRemaining (i) {
|
|
if (!this.init()) return
|
|
this._reservations = i
|
|
}
|
|
|
|
get (i) {
|
|
if (!this.init()) return null
|
|
return this._buffer[i]
|
|
}
|
|
|
|
set (i, data, source) {
|
|
if (!this.init()) return false
|
|
const len = data.length
|
|
const blocks = Math.ceil(len / BLOCK_LENGTH)
|
|
for (let j = 0; j < blocks; j++) {
|
|
if (!this._buffer[i + j]) {
|
|
const offset = j * BLOCK_LENGTH
|
|
const splitData = data.slice(offset, offset + BLOCK_LENGTH)
|
|
this._buffered++
|
|
this._buffer[i + j] = splitData
|
|
this.missing -= splitData.length
|
|
if (!this.sources.includes(source)) {
|
|
this.sources.push(source)
|
|
}
|
|
}
|
|
}
|
|
return this._buffered === this._chunks
|
|
}
|
|
|
|
flush () {
|
|
if (!this._buffer || this._chunks !== this._buffered) return null
|
|
const buffer = Buffer.concat(this._buffer, this.length)
|
|
this._buffer = null
|
|
this._cancellations = null
|
|
this.sources = null
|
|
this._flushed = true
|
|
return buffer
|
|
}
|
|
|
|
init () {
|
|
if (this._flushed) return false
|
|
if (this._buffer) return true
|
|
this._buffer = new Array(this._chunks)
|
|
this._cancellations = []
|
|
this.sources = []
|
|
return true
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(Piece, 'BLOCK_LENGTH', { value: BLOCK_LENGTH })
|
|
|
|
module.exports = Piece
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/typedarray-to-buffer/index.js":
|
|
/*!****************************************************!*\
|
|
!*** ./node_modules/typedarray-to-buffer/index.js ***!
|
|
\****************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/**
|
|
* Convert a typed array to a Buffer without a copy
|
|
*
|
|
* Author: Feross Aboukhadijeh <https://feross.org>
|
|
* License: MIT
|
|
*
|
|
* `npm install typedarray-to-buffer`
|
|
*/
|
|
|
|
var isTypedArray = __webpack_require__(/*! is-typedarray */ "./node_modules/is-typedarray/index.js").strict
|
|
|
|
module.exports = function typedarrayToBuffer (arr) {
|
|
if (isTypedArray(arr)) {
|
|
// To avoid a copy, use the typed array's underlying ArrayBuffer to back new Buffer
|
|
var buf = Buffer.from(arr.buffer)
|
|
if (arr.byteLength !== arr.buffer.byteLength) {
|
|
// Respect the "view", i.e. byteOffset and byteLength, without doing a copy
|
|
buf = buf.slice(arr.byteOffset, arr.byteOffset + arr.byteLength)
|
|
}
|
|
return buf
|
|
} else {
|
|
// Pass through all other types to `Buffer.from`
|
|
return Buffer.from(arr)
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/uint64be/index.js":
|
|
/*!****************************************!*\
|
|
!*** ./node_modules/uint64be/index.js ***!
|
|
\****************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
var bufferAlloc = __webpack_require__(/*! buffer-alloc */ "./node_modules/buffer-alloc/index.js")
|
|
|
|
var UINT_32_MAX = Math.pow(2, 32)
|
|
|
|
exports.encodingLength = function () {
|
|
return 8
|
|
}
|
|
|
|
exports.encode = function (num, buf, offset) {
|
|
if (!buf) buf = bufferAlloc(8)
|
|
if (!offset) offset = 0
|
|
|
|
var top = Math.floor(num / UINT_32_MAX)
|
|
var rem = num - top * UINT_32_MAX
|
|
|
|
buf.writeUInt32BE(top, offset)
|
|
buf.writeUInt32BE(rem, offset + 4)
|
|
return buf
|
|
}
|
|
|
|
exports.decode = function (buf, offset) {
|
|
if (!offset) offset = 0
|
|
|
|
var top = buf.readUInt32BE(offset)
|
|
var rem = buf.readUInt32BE(offset + 4)
|
|
|
|
return top * UINT_32_MAX + rem
|
|
}
|
|
|
|
exports.encode.bytes = 8
|
|
exports.decode.bytes = 8
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/unordered-array-remove/index.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/unordered-array-remove/index.js ***!
|
|
\******************************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = remove
|
|
|
|
function remove (arr, i) {
|
|
if (i >= arr.length || i < 0) return
|
|
var last = arr.pop()
|
|
if (i < arr.length) {
|
|
var tmp = arr[i]
|
|
arr[i] = last
|
|
return tmp
|
|
}
|
|
return last
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/url/node_modules/punycode/punycode.js":
|
|
/*!************************************************************!*\
|
|
!*** ./node_modules/url/node_modules/punycode/punycode.js ***!
|
|
\************************************************************/
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* module decorator */ module = __webpack_require__.nmd(module);
|
|
var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.3.2 by @mathias */
|
|
;(function(root) {
|
|
|
|
/** Detect free variables */
|
|
var freeExports = true && exports &&
|
|
!exports.nodeType && exports;
|
|
var freeModule = true && module &&
|
|
!module.nodeType && module;
|
|
var freeGlobal = typeof __webpack_require__.g == 'object' && __webpack_require__.g;
|
|
if (
|
|
freeGlobal.global === freeGlobal ||
|
|
freeGlobal.window === freeGlobal ||
|
|
freeGlobal.self === freeGlobal
|
|
) {
|
|
root = freeGlobal;
|
|
}
|
|
|
|
/**
|
|
* The `punycode` object.
|
|
* @name punycode
|
|
* @type Object
|
|
*/
|
|
var punycode,
|
|
|
|
/** Highest positive signed 32-bit float value */
|
|
maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
|
|
|
|
/** Bootstring parameters */
|
|
base = 36,
|
|
tMin = 1,
|
|
tMax = 26,
|
|
skew = 38,
|
|
damp = 700,
|
|
initialBias = 72,
|
|
initialN = 128, // 0x80
|
|
delimiter = '-', // '\x2D'
|
|
|
|
/** Regular expressions */
|
|
regexPunycode = /^xn--/,
|
|
regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
|
|
regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
|
|
|
|
/** Error messages */
|
|
errors = {
|
|
'overflow': 'Overflow: input needs wider integers to process',
|
|
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
|
|
'invalid-input': 'Invalid input'
|
|
},
|
|
|
|
/** Convenience shortcuts */
|
|
baseMinusTMin = base - tMin,
|
|
floor = Math.floor,
|
|
stringFromCharCode = String.fromCharCode,
|
|
|
|
/** Temporary variable */
|
|
key;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* A generic error utility function.
|
|
* @private
|
|
* @param {String} type The error type.
|
|
* @returns {Error} Throws a `RangeError` with the applicable error message.
|
|
*/
|
|
function error(type) {
|
|
throw RangeError(errors[type]);
|
|
}
|
|
|
|
/**
|
|
* A generic `Array#map` utility function.
|
|
* @private
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} callback The function that gets called for every array
|
|
* item.
|
|
* @returns {Array} A new array of values returned by the callback function.
|
|
*/
|
|
function map(array, fn) {
|
|
var length = array.length;
|
|
var result = [];
|
|
while (length--) {
|
|
result[length] = fn(array[length]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A simple `Array#map`-like wrapper to work with domain name strings or email
|
|
* addresses.
|
|
* @private
|
|
* @param {String} domain The domain name or email address.
|
|
* @param {Function} callback The function that gets called for every
|
|
* character.
|
|
* @returns {Array} A new string of characters returned by the callback
|
|
* function.
|
|
*/
|
|
function mapDomain(string, fn) {
|
|
var parts = string.split('@');
|
|
var result = '';
|
|
if (parts.length > 1) {
|
|
// In email addresses, only the domain name should be punycoded. Leave
|
|
// the local part (i.e. everything up to `@`) intact.
|
|
result = parts[0] + '@';
|
|
string = parts[1];
|
|
}
|
|
// Avoid `split(regex)` for IE8 compatibility. See #17.
|
|
string = string.replace(regexSeparators, '\x2E');
|
|
var labels = string.split('.');
|
|
var encoded = map(labels, fn).join('.');
|
|
return result + encoded;
|
|
}
|
|
|
|
/**
|
|
* Creates an array containing the numeric code points of each Unicode
|
|
* character in the string. While JavaScript uses UCS-2 internally,
|
|
* this function will convert a pair of surrogate halves (each of which
|
|
* UCS-2 exposes as separate characters) into a single code point,
|
|
* matching UTF-16.
|
|
* @see `punycode.ucs2.encode`
|
|
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
|
* @memberOf punycode.ucs2
|
|
* @name decode
|
|
* @param {String} string The Unicode input string (UCS-2).
|
|
* @returns {Array} The new array of code points.
|
|
*/
|
|
function ucs2decode(string) {
|
|
var output = [],
|
|
counter = 0,
|
|
length = string.length,
|
|
value,
|
|
extra;
|
|
while (counter < length) {
|
|
value = string.charCodeAt(counter++);
|
|
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
|
|
// high surrogate, and there is a next character
|
|
extra = string.charCodeAt(counter++);
|
|
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
|
|
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
|
|
} else {
|
|
// unmatched surrogate; only append this code unit, in case the next
|
|
// code unit is the high surrogate of a surrogate pair
|
|
output.push(value);
|
|
counter--;
|
|
}
|
|
} else {
|
|
output.push(value);
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
/**
|
|
* Creates a string based on an array of numeric code points.
|
|
* @see `punycode.ucs2.decode`
|
|
* @memberOf punycode.ucs2
|
|
* @name encode
|
|
* @param {Array} codePoints The array of numeric code points.
|
|
* @returns {String} The new Unicode string (UCS-2).
|
|
*/
|
|
function ucs2encode(array) {
|
|
return map(array, function(value) {
|
|
var output = '';
|
|
if (value > 0xFFFF) {
|
|
value -= 0x10000;
|
|
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
|
|
value = 0xDC00 | value & 0x3FF;
|
|
}
|
|
output += stringFromCharCode(value);
|
|
return output;
|
|
}).join('');
|
|
}
|
|
|
|
/**
|
|
* Converts a basic code point into a digit/integer.
|
|
* @see `digitToBasic()`
|
|
* @private
|
|
* @param {Number} codePoint The basic numeric code point value.
|
|
* @returns {Number} The numeric value of a basic code point (for use in
|
|
* representing integers) in the range `0` to `base - 1`, or `base` if
|
|
* the code point does not represent a value.
|
|
*/
|
|
function basicToDigit(codePoint) {
|
|
if (codePoint - 48 < 10) {
|
|
return codePoint - 22;
|
|
}
|
|
if (codePoint - 65 < 26) {
|
|
return codePoint - 65;
|
|
}
|
|
if (codePoint - 97 < 26) {
|
|
return codePoint - 97;
|
|
}
|
|
return base;
|
|
}
|
|
|
|
/**
|
|
* Converts a digit/integer into a basic code point.
|
|
* @see `basicToDigit()`
|
|
* @private
|
|
* @param {Number} digit The numeric value of a basic code point.
|
|
* @returns {Number} The basic code point whose value (when used for
|
|
* representing integers) is `digit`, which needs to be in the range
|
|
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
|
|
* used; else, the lowercase form is used. The behavior is undefined
|
|
* if `flag` is non-zero and `digit` has no uppercase form.
|
|
*/
|
|
function digitToBasic(digit, flag) {
|
|
// 0..25 map to ASCII a..z or A..Z
|
|
// 26..35 map to ASCII 0..9
|
|
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
|
|
}
|
|
|
|
/**
|
|
* Bias adaptation function as per section 3.4 of RFC 3492.
|
|
* http://tools.ietf.org/html/rfc3492#section-3.4
|
|
* @private
|
|
*/
|
|
function adapt(delta, numPoints, firstTime) {
|
|
var k = 0;
|
|
delta = firstTime ? floor(delta / damp) : delta >> 1;
|
|
delta += floor(delta / numPoints);
|
|
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
|
|
delta = floor(delta / baseMinusTMin);
|
|
}
|
|
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
|
|
}
|
|
|
|
/**
|
|
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
|
|
* symbols.
|
|
* @memberOf punycode
|
|
* @param {String} input The Punycode string of ASCII-only symbols.
|
|
* @returns {String} The resulting string of Unicode symbols.
|
|
*/
|
|
function decode(input) {
|
|
// Don't use UCS-2
|
|
var output = [],
|
|
inputLength = input.length,
|
|
out,
|
|
i = 0,
|
|
n = initialN,
|
|
bias = initialBias,
|
|
basic,
|
|
j,
|
|
index,
|
|
oldi,
|
|
w,
|
|
k,
|
|
digit,
|
|
t,
|
|
/** Cached calculation results */
|
|
baseMinusT;
|
|
|
|
// Handle the basic code points: let `basic` be the number of input code
|
|
// points before the last delimiter, or `0` if there is none, then copy
|
|
// the first basic code points to the output.
|
|
|
|
basic = input.lastIndexOf(delimiter);
|
|
if (basic < 0) {
|
|
basic = 0;
|
|
}
|
|
|
|
for (j = 0; j < basic; ++j) {
|
|
// if it's not a basic code point
|
|
if (input.charCodeAt(j) >= 0x80) {
|
|
error('not-basic');
|
|
}
|
|
output.push(input.charCodeAt(j));
|
|
}
|
|
|
|
// Main decoding loop: start just after the last delimiter if any basic code
|
|
// points were copied; start at the beginning otherwise.
|
|
|
|
for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
|
|
|
|
// `index` is the index of the next character to be consumed.
|
|
// Decode a generalized variable-length integer into `delta`,
|
|
// which gets added to `i`. The overflow checking is easier
|
|
// if we increase `i` as we go, then subtract off its starting
|
|
// value at the end to obtain `delta`.
|
|
for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
|
|
|
|
if (index >= inputLength) {
|
|
error('invalid-input');
|
|
}
|
|
|
|
digit = basicToDigit(input.charCodeAt(index++));
|
|
|
|
if (digit >= base || digit > floor((maxInt - i) / w)) {
|
|
error('overflow');
|
|
}
|
|
|
|
i += digit * w;
|
|
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
|
|
|
|
if (digit < t) {
|
|
break;
|
|
}
|
|
|
|
baseMinusT = base - t;
|
|
if (w > floor(maxInt / baseMinusT)) {
|
|
error('overflow');
|
|
}
|
|
|
|
w *= baseMinusT;
|
|
|
|
}
|
|
|
|
out = output.length + 1;
|
|
bias = adapt(i - oldi, out, oldi == 0);
|
|
|
|
// `i` was supposed to wrap around from `out` to `0`,
|
|
// incrementing `n` each time, so we'll fix that now:
|
|
if (floor(i / out) > maxInt - n) {
|
|
error('overflow');
|
|
}
|
|
|
|
n += floor(i / out);
|
|
i %= out;
|
|
|
|
// Insert `n` at position `i` of the output
|
|
output.splice(i++, 0, n);
|
|
|
|
}
|
|
|
|
return ucs2encode(output);
|
|
}
|
|
|
|
/**
|
|
* Converts a string of Unicode symbols (e.g. a domain name label) to a
|
|
* Punycode string of ASCII-only symbols.
|
|
* @memberOf punycode
|
|
* @param {String} input The string of Unicode symbols.
|
|
* @returns {String} The resulting Punycode string of ASCII-only symbols.
|
|
*/
|
|
function encode(input) {
|
|
var n,
|
|
delta,
|
|
handledCPCount,
|
|
basicLength,
|
|
bias,
|
|
j,
|
|
m,
|
|
q,
|
|
k,
|
|
t,
|
|
currentValue,
|
|
output = [],
|
|
/** `inputLength` will hold the number of code points in `input`. */
|
|
inputLength,
|
|
/** Cached calculation results */
|
|
handledCPCountPlusOne,
|
|
baseMinusT,
|
|
qMinusT;
|
|
|
|
// Convert the input in UCS-2 to Unicode
|
|
input = ucs2decode(input);
|
|
|
|
// Cache the length
|
|
inputLength = input.length;
|
|
|
|
// Initialize the state
|
|
n = initialN;
|
|
delta = 0;
|
|
bias = initialBias;
|
|
|
|
// Handle the basic code points
|
|
for (j = 0; j < inputLength; ++j) {
|
|
currentValue = input[j];
|
|
if (currentValue < 0x80) {
|
|
output.push(stringFromCharCode(currentValue));
|
|
}
|
|
}
|
|
|
|
handledCPCount = basicLength = output.length;
|
|
|
|
// `handledCPCount` is the number of code points that have been handled;
|
|
// `basicLength` is the number of basic code points.
|
|
|
|
// Finish the basic string - if it is not empty - with a delimiter
|
|
if (basicLength) {
|
|
output.push(delimiter);
|
|
}
|
|
|
|
// Main encoding loop:
|
|
while (handledCPCount < inputLength) {
|
|
|
|
// All non-basic code points < n have been handled already. Find the next
|
|
// larger one:
|
|
for (m = maxInt, j = 0; j < inputLength; ++j) {
|
|
currentValue = input[j];
|
|
if (currentValue >= n && currentValue < m) {
|
|
m = currentValue;
|
|
}
|
|
}
|
|
|
|
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
|
|
// but guard against overflow
|
|
handledCPCountPlusOne = handledCPCount + 1;
|
|
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
|
|
error('overflow');
|
|
}
|
|
|
|
delta += (m - n) * handledCPCountPlusOne;
|
|
n = m;
|
|
|
|
for (j = 0; j < inputLength; ++j) {
|
|
currentValue = input[j];
|
|
|
|
if (currentValue < n && ++delta > maxInt) {
|
|
error('overflow');
|
|
}
|
|
|
|
if (currentValue == n) {
|
|
// Represent delta as a generalized variable-length integer
|
|
for (q = delta, k = base; /* no condition */; k += base) {
|
|
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
|
|
if (q < t) {
|
|
break;
|
|
}
|
|
qMinusT = q - t;
|
|
baseMinusT = base - t;
|
|
output.push(
|
|
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
|
|
);
|
|
q = floor(qMinusT / baseMinusT);
|
|
}
|
|
|
|
output.push(stringFromCharCode(digitToBasic(q, 0)));
|
|
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
|
|
delta = 0;
|
|
++handledCPCount;
|
|
}
|
|
}
|
|
|
|
++delta;
|
|
++n;
|
|
|
|
}
|
|
return output.join('');
|
|
}
|
|
|
|
/**
|
|
* Converts a Punycode string representing a domain name or an email address
|
|
* to Unicode. Only the Punycoded parts of the input will be converted, i.e.
|
|
* it doesn't matter if you call it on a string that has already been
|
|
* converted to Unicode.
|
|
* @memberOf punycode
|
|
* @param {String} input The Punycoded domain name or email address to
|
|
* convert to Unicode.
|
|
* @returns {String} The Unicode representation of the given Punycode
|
|
* string.
|
|
*/
|
|
function toUnicode(input) {
|
|
return mapDomain(input, function(string) {
|
|
return regexPunycode.test(string)
|
|
? decode(string.slice(4).toLowerCase())
|
|
: string;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Converts a Unicode string representing a domain name or an email address to
|
|
* Punycode. Only the non-ASCII parts of the domain name will be converted,
|
|
* i.e. it doesn't matter if you call it with a domain that's already in
|
|
* ASCII.
|
|
* @memberOf punycode
|
|
* @param {String} input The domain name or email address to convert, as a
|
|
* Unicode string.
|
|
* @returns {String} The Punycode representation of the given domain name or
|
|
* email address.
|
|
*/
|
|
function toASCII(input) {
|
|
return mapDomain(input, function(string) {
|
|
return regexNonASCII.test(string)
|
|
? 'xn--' + encode(string)
|
|
: string;
|
|
});
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/** Define the public API */
|
|
punycode = {
|
|
/**
|
|
* A string representing the current Punycode.js version number.
|
|
* @memberOf punycode
|
|
* @type String
|
|
*/
|
|
'version': '1.3.2',
|
|
/**
|
|
* An object of methods to convert from JavaScript's internal character
|
|
* representation (UCS-2) to Unicode code points, and back.
|
|
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
|
* @memberOf punycode
|
|
* @type Object
|
|
*/
|
|
'ucs2': {
|
|
'decode': ucs2decode,
|
|
'encode': ucs2encode
|
|
},
|
|
'decode': decode,
|
|
'encode': encode,
|
|
'toASCII': toASCII,
|
|
'toUnicode': toUnicode
|
|
};
|
|
|
|
/** Expose `punycode` */
|
|
// Some AMD build optimizers, like r.js, check for specific condition patterns
|
|
// like the following:
|
|
if (
|
|
true
|
|
) {
|
|
!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
|
|
return punycode;
|
|
}).call(exports, __webpack_require__, exports, module),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
|
|
}(this));
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/url/url.js":
|
|
/*!*********************************!*\
|
|
!*** ./node_modules/url/url.js ***!
|
|
\*********************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
var punycode = __webpack_require__(/*! punycode */ "./node_modules/url/node_modules/punycode/punycode.js");
|
|
var util = __webpack_require__(/*! ./util */ "./node_modules/url/util.js");
|
|
|
|
exports.parse = urlParse;
|
|
exports.resolve = urlResolve;
|
|
exports.resolveObject = urlResolveObject;
|
|
exports.format = urlFormat;
|
|
|
|
exports.Url = Url;
|
|
|
|
function Url() {
|
|
this.protocol = null;
|
|
this.slashes = null;
|
|
this.auth = null;
|
|
this.host = null;
|
|
this.port = null;
|
|
this.hostname = null;
|
|
this.hash = null;
|
|
this.search = null;
|
|
this.query = null;
|
|
this.pathname = null;
|
|
this.path = null;
|
|
this.href = null;
|
|
}
|
|
|
|
// Reference: RFC 3986, RFC 1808, RFC 2396
|
|
|
|
// define these here so at least they only have to be
|
|
// compiled once on the first module load.
|
|
var protocolPattern = /^([a-z0-9.+-]+:)/i,
|
|
portPattern = /:[0-9]*$/,
|
|
|
|
// Special case for a simple path URL
|
|
simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
|
|
|
|
// RFC 2396: characters reserved for delimiting URLs.
|
|
// We actually just auto-escape these.
|
|
delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
|
|
|
|
// RFC 2396: characters not allowed for various reasons.
|
|
unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
|
|
|
|
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
|
|
autoEscape = ['\''].concat(unwise),
|
|
// Characters that are never ever allowed in a hostname.
|
|
// Note that any invalid chars are also handled, but these
|
|
// are the ones that are *expected* to be seen, so we fast-path
|
|
// them.
|
|
nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
|
|
hostEndingChars = ['/', '?', '#'],
|
|
hostnameMaxLen = 255,
|
|
hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
|
|
hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
|
|
// protocols that can allow "unsafe" and "unwise" chars.
|
|
unsafeProtocol = {
|
|
'javascript': true,
|
|
'javascript:': true
|
|
},
|
|
// protocols that never have a hostname.
|
|
hostlessProtocol = {
|
|
'javascript': true,
|
|
'javascript:': true
|
|
},
|
|
// protocols that always contain a // bit.
|
|
slashedProtocol = {
|
|
'http': true,
|
|
'https': true,
|
|
'ftp': true,
|
|
'gopher': true,
|
|
'file': true,
|
|
'http:': true,
|
|
'https:': true,
|
|
'ftp:': true,
|
|
'gopher:': true,
|
|
'file:': true
|
|
},
|
|
querystring = __webpack_require__(/*! querystring */ "./node_modules/querystring/index.js");
|
|
|
|
function urlParse(url, parseQueryString, slashesDenoteHost) {
|
|
if (url && util.isObject(url) && url instanceof Url) return url;
|
|
|
|
var u = new Url;
|
|
u.parse(url, parseQueryString, slashesDenoteHost);
|
|
return u;
|
|
}
|
|
|
|
Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
|
|
if (!util.isString(url)) {
|
|
throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
|
|
}
|
|
|
|
// Copy chrome, IE, opera backslash-handling behavior.
|
|
// Back slashes before the query string get converted to forward slashes
|
|
// See: https://code.google.com/p/chromium/issues/detail?id=25916
|
|
var queryIndex = url.indexOf('?'),
|
|
splitter =
|
|
(queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
|
|
uSplit = url.split(splitter),
|
|
slashRegex = /\\/g;
|
|
uSplit[0] = uSplit[0].replace(slashRegex, '/');
|
|
url = uSplit.join(splitter);
|
|
|
|
var rest = url;
|
|
|
|
// trim before proceeding.
|
|
// This is to support parse stuff like " http://foo.com \n"
|
|
rest = rest.trim();
|
|
|
|
if (!slashesDenoteHost && url.split('#').length === 1) {
|
|
// Try fast path regexp
|
|
var simplePath = simplePathPattern.exec(rest);
|
|
if (simplePath) {
|
|
this.path = rest;
|
|
this.href = rest;
|
|
this.pathname = simplePath[1];
|
|
if (simplePath[2]) {
|
|
this.search = simplePath[2];
|
|
if (parseQueryString) {
|
|
this.query = querystring.parse(this.search.substr(1));
|
|
} else {
|
|
this.query = this.search.substr(1);
|
|
}
|
|
} else if (parseQueryString) {
|
|
this.search = '';
|
|
this.query = {};
|
|
}
|
|
return this;
|
|
}
|
|
}
|
|
|
|
var proto = protocolPattern.exec(rest);
|
|
if (proto) {
|
|
proto = proto[0];
|
|
var lowerProto = proto.toLowerCase();
|
|
this.protocol = lowerProto;
|
|
rest = rest.substr(proto.length);
|
|
}
|
|
|
|
// figure out if it's got a host
|
|
// user@server is *always* interpreted as a hostname, and url
|
|
// resolution will treat //foo/bar as host=foo,path=bar because that's
|
|
// how the browser resolves relative URLs.
|
|
if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
|
|
var slashes = rest.substr(0, 2) === '//';
|
|
if (slashes && !(proto && hostlessProtocol[proto])) {
|
|
rest = rest.substr(2);
|
|
this.slashes = true;
|
|
}
|
|
}
|
|
|
|
if (!hostlessProtocol[proto] &&
|
|
(slashes || (proto && !slashedProtocol[proto]))) {
|
|
|
|
// there's a hostname.
|
|
// the first instance of /, ?, ;, or # ends the host.
|
|
//
|
|
// If there is an @ in the hostname, then non-host chars *are* allowed
|
|
// to the left of the last @ sign, unless some host-ending character
|
|
// comes *before* the @-sign.
|
|
// URLs are obnoxious.
|
|
//
|
|
// ex:
|
|
// http://a@b@c/ => user:a@b host:c
|
|
// http://a@b?@c => user:a host:c path:/?@c
|
|
|
|
// v0.12 TODO(isaacs): This is not quite how Chrome does things.
|
|
// Review our test case against browsers more comprehensively.
|
|
|
|
// find the first instance of any hostEndingChars
|
|
var hostEnd = -1;
|
|
for (var i = 0; i < hostEndingChars.length; i++) {
|
|
var hec = rest.indexOf(hostEndingChars[i]);
|
|
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
|
|
hostEnd = hec;
|
|
}
|
|
|
|
// at this point, either we have an explicit point where the
|
|
// auth portion cannot go past, or the last @ char is the decider.
|
|
var auth, atSign;
|
|
if (hostEnd === -1) {
|
|
// atSign can be anywhere.
|
|
atSign = rest.lastIndexOf('@');
|
|
} else {
|
|
// atSign must be in auth portion.
|
|
// http://a@b/c@d => host:b auth:a path:/c@d
|
|
atSign = rest.lastIndexOf('@', hostEnd);
|
|
}
|
|
|
|
// Now we have a portion which is definitely the auth.
|
|
// Pull that off.
|
|
if (atSign !== -1) {
|
|
auth = rest.slice(0, atSign);
|
|
rest = rest.slice(atSign + 1);
|
|
this.auth = decodeURIComponent(auth);
|
|
}
|
|
|
|
// the host is the remaining to the left of the first non-host char
|
|
hostEnd = -1;
|
|
for (var i = 0; i < nonHostChars.length; i++) {
|
|
var hec = rest.indexOf(nonHostChars[i]);
|
|
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
|
|
hostEnd = hec;
|
|
}
|
|
// if we still have not hit it, then the entire thing is a host.
|
|
if (hostEnd === -1)
|
|
hostEnd = rest.length;
|
|
|
|
this.host = rest.slice(0, hostEnd);
|
|
rest = rest.slice(hostEnd);
|
|
|
|
// pull out port.
|
|
this.parseHost();
|
|
|
|
// we've indicated that there is a hostname,
|
|
// so even if it's empty, it has to be present.
|
|
this.hostname = this.hostname || '';
|
|
|
|
// if hostname begins with [ and ends with ]
|
|
// assume that it's an IPv6 address.
|
|
var ipv6Hostname = this.hostname[0] === '[' &&
|
|
this.hostname[this.hostname.length - 1] === ']';
|
|
|
|
// validate a little.
|
|
if (!ipv6Hostname) {
|
|
var hostparts = this.hostname.split(/\./);
|
|
for (var i = 0, l = hostparts.length; i < l; i++) {
|
|
var part = hostparts[i];
|
|
if (!part) continue;
|
|
if (!part.match(hostnamePartPattern)) {
|
|
var newpart = '';
|
|
for (var j = 0, k = part.length; j < k; j++) {
|
|
if (part.charCodeAt(j) > 127) {
|
|
// we replace non-ASCII char with a temporary placeholder
|
|
// we need this to make sure size of hostname is not
|
|
// broken by replacing non-ASCII by nothing
|
|
newpart += 'x';
|
|
} else {
|
|
newpart += part[j];
|
|
}
|
|
}
|
|
// we test again with ASCII char only
|
|
if (!newpart.match(hostnamePartPattern)) {
|
|
var validParts = hostparts.slice(0, i);
|
|
var notHost = hostparts.slice(i + 1);
|
|
var bit = part.match(hostnamePartStart);
|
|
if (bit) {
|
|
validParts.push(bit[1]);
|
|
notHost.unshift(bit[2]);
|
|
}
|
|
if (notHost.length) {
|
|
rest = '/' + notHost.join('.') + rest;
|
|
}
|
|
this.hostname = validParts.join('.');
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.hostname.length > hostnameMaxLen) {
|
|
this.hostname = '';
|
|
} else {
|
|
// hostnames are always lower case.
|
|
this.hostname = this.hostname.toLowerCase();
|
|
}
|
|
|
|
if (!ipv6Hostname) {
|
|
// IDNA Support: Returns a punycoded representation of "domain".
|
|
// It only converts parts of the domain name that
|
|
// have non-ASCII characters, i.e. it doesn't matter if
|
|
// you call it with a domain that already is ASCII-only.
|
|
this.hostname = punycode.toASCII(this.hostname);
|
|
}
|
|
|
|
var p = this.port ? ':' + this.port : '';
|
|
var h = this.hostname || '';
|
|
this.host = h + p;
|
|
this.href += this.host;
|
|
|
|
// strip [ and ] from the hostname
|
|
// the host field still retains them, though
|
|
if (ipv6Hostname) {
|
|
this.hostname = this.hostname.substr(1, this.hostname.length - 2);
|
|
if (rest[0] !== '/') {
|
|
rest = '/' + rest;
|
|
}
|
|
}
|
|
}
|
|
|
|
// now rest is set to the post-host stuff.
|
|
// chop off any delim chars.
|
|
if (!unsafeProtocol[lowerProto]) {
|
|
|
|
// First, make 100% sure that any "autoEscape" chars get
|
|
// escaped, even if encodeURIComponent doesn't think they
|
|
// need to be.
|
|
for (var i = 0, l = autoEscape.length; i < l; i++) {
|
|
var ae = autoEscape[i];
|
|
if (rest.indexOf(ae) === -1)
|
|
continue;
|
|
var esc = encodeURIComponent(ae);
|
|
if (esc === ae) {
|
|
esc = escape(ae);
|
|
}
|
|
rest = rest.split(ae).join(esc);
|
|
}
|
|
}
|
|
|
|
|
|
// chop off from the tail first.
|
|
var hash = rest.indexOf('#');
|
|
if (hash !== -1) {
|
|
// got a fragment string.
|
|
this.hash = rest.substr(hash);
|
|
rest = rest.slice(0, hash);
|
|
}
|
|
var qm = rest.indexOf('?');
|
|
if (qm !== -1) {
|
|
this.search = rest.substr(qm);
|
|
this.query = rest.substr(qm + 1);
|
|
if (parseQueryString) {
|
|
this.query = querystring.parse(this.query);
|
|
}
|
|
rest = rest.slice(0, qm);
|
|
} else if (parseQueryString) {
|
|
// no query string, but parseQueryString still requested
|
|
this.search = '';
|
|
this.query = {};
|
|
}
|
|
if (rest) this.pathname = rest;
|
|
if (slashedProtocol[lowerProto] &&
|
|
this.hostname && !this.pathname) {
|
|
this.pathname = '/';
|
|
}
|
|
|
|
//to support http.request
|
|
if (this.pathname || this.search) {
|
|
var p = this.pathname || '';
|
|
var s = this.search || '';
|
|
this.path = p + s;
|
|
}
|
|
|
|
// finally, reconstruct the href based on what has been validated.
|
|
this.href = this.format();
|
|
return this;
|
|
};
|
|
|
|
// format a parsed object into a url string
|
|
function urlFormat(obj) {
|
|
// ensure it's an object, and not a string url.
|
|
// If it's an obj, this is a no-op.
|
|
// this way, you can call url_format() on strings
|
|
// to clean up potentially wonky urls.
|
|
if (util.isString(obj)) obj = urlParse(obj);
|
|
if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
|
|
return obj.format();
|
|
}
|
|
|
|
Url.prototype.format = function() {
|
|
var auth = this.auth || '';
|
|
if (auth) {
|
|
auth = encodeURIComponent(auth);
|
|
auth = auth.replace(/%3A/i, ':');
|
|
auth += '@';
|
|
}
|
|
|
|
var protocol = this.protocol || '',
|
|
pathname = this.pathname || '',
|
|
hash = this.hash || '',
|
|
host = false,
|
|
query = '';
|
|
|
|
if (this.host) {
|
|
host = auth + this.host;
|
|
} else if (this.hostname) {
|
|
host = auth + (this.hostname.indexOf(':') === -1 ?
|
|
this.hostname :
|
|
'[' + this.hostname + ']');
|
|
if (this.port) {
|
|
host += ':' + this.port;
|
|
}
|
|
}
|
|
|
|
if (this.query &&
|
|
util.isObject(this.query) &&
|
|
Object.keys(this.query).length) {
|
|
query = querystring.stringify(this.query);
|
|
}
|
|
|
|
var search = this.search || (query && ('?' + query)) || '';
|
|
|
|
if (protocol && protocol.substr(-1) !== ':') protocol += ':';
|
|
|
|
// only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
|
|
// unless they had them to begin with.
|
|
if (this.slashes ||
|
|
(!protocol || slashedProtocol[protocol]) && host !== false) {
|
|
host = '//' + (host || '');
|
|
if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
|
|
} else if (!host) {
|
|
host = '';
|
|
}
|
|
|
|
if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
|
|
if (search && search.charAt(0) !== '?') search = '?' + search;
|
|
|
|
pathname = pathname.replace(/[?#]/g, function(match) {
|
|
return encodeURIComponent(match);
|
|
});
|
|
search = search.replace('#', '%23');
|
|
|
|
return protocol + host + pathname + search + hash;
|
|
};
|
|
|
|
function urlResolve(source, relative) {
|
|
return urlParse(source, false, true).resolve(relative);
|
|
}
|
|
|
|
Url.prototype.resolve = function(relative) {
|
|
return this.resolveObject(urlParse(relative, false, true)).format();
|
|
};
|
|
|
|
function urlResolveObject(source, relative) {
|
|
if (!source) return relative;
|
|
return urlParse(source, false, true).resolveObject(relative);
|
|
}
|
|
|
|
Url.prototype.resolveObject = function(relative) {
|
|
if (util.isString(relative)) {
|
|
var rel = new Url();
|
|
rel.parse(relative, false, true);
|
|
relative = rel;
|
|
}
|
|
|
|
var result = new Url();
|
|
var tkeys = Object.keys(this);
|
|
for (var tk = 0; tk < tkeys.length; tk++) {
|
|
var tkey = tkeys[tk];
|
|
result[tkey] = this[tkey];
|
|
}
|
|
|
|
// hash is always overridden, no matter what.
|
|
// even href="" will remove it.
|
|
result.hash = relative.hash;
|
|
|
|
// if the relative url is empty, then there's nothing left to do here.
|
|
if (relative.href === '') {
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
// hrefs like //foo/bar always cut to the protocol.
|
|
if (relative.slashes && !relative.protocol) {
|
|
// take everything except the protocol from relative
|
|
var rkeys = Object.keys(relative);
|
|
for (var rk = 0; rk < rkeys.length; rk++) {
|
|
var rkey = rkeys[rk];
|
|
if (rkey !== 'protocol')
|
|
result[rkey] = relative[rkey];
|
|
}
|
|
|
|
//urlParse appends trailing / to urls like http://www.example.com
|
|
if (slashedProtocol[result.protocol] &&
|
|
result.hostname && !result.pathname) {
|
|
result.path = result.pathname = '/';
|
|
}
|
|
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
if (relative.protocol && relative.protocol !== result.protocol) {
|
|
// if it's a known url protocol, then changing
|
|
// the protocol does weird things
|
|
// first, if it's not file:, then we MUST have a host,
|
|
// and if there was a path
|
|
// to begin with, then we MUST have a path.
|
|
// if it is file:, then the host is dropped,
|
|
// because that's known to be hostless.
|
|
// anything else is assumed to be absolute.
|
|
if (!slashedProtocol[relative.protocol]) {
|
|
var keys = Object.keys(relative);
|
|
for (var v = 0; v < keys.length; v++) {
|
|
var k = keys[v];
|
|
result[k] = relative[k];
|
|
}
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
result.protocol = relative.protocol;
|
|
if (!relative.host && !hostlessProtocol[relative.protocol]) {
|
|
var relPath = (relative.pathname || '').split('/');
|
|
while (relPath.length && !(relative.host = relPath.shift()));
|
|
if (!relative.host) relative.host = '';
|
|
if (!relative.hostname) relative.hostname = '';
|
|
if (relPath[0] !== '') relPath.unshift('');
|
|
if (relPath.length < 2) relPath.unshift('');
|
|
result.pathname = relPath.join('/');
|
|
} else {
|
|
result.pathname = relative.pathname;
|
|
}
|
|
result.search = relative.search;
|
|
result.query = relative.query;
|
|
result.host = relative.host || '';
|
|
result.auth = relative.auth;
|
|
result.hostname = relative.hostname || relative.host;
|
|
result.port = relative.port;
|
|
// to support http.request
|
|
if (result.pathname || result.search) {
|
|
var p = result.pathname || '';
|
|
var s = result.search || '';
|
|
result.path = p + s;
|
|
}
|
|
result.slashes = result.slashes || relative.slashes;
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
|
|
isRelAbs = (
|
|
relative.host ||
|
|
relative.pathname && relative.pathname.charAt(0) === '/'
|
|
),
|
|
mustEndAbs = (isRelAbs || isSourceAbs ||
|
|
(result.host && relative.pathname)),
|
|
removeAllDots = mustEndAbs,
|
|
srcPath = result.pathname && result.pathname.split('/') || [],
|
|
relPath = relative.pathname && relative.pathname.split('/') || [],
|
|
psychotic = result.protocol && !slashedProtocol[result.protocol];
|
|
|
|
// if the url is a non-slashed url, then relative
|
|
// links like ../.. should be able
|
|
// to crawl up to the hostname, as well. This is strange.
|
|
// result.protocol has already been set by now.
|
|
// Later on, put the first path part into the host field.
|
|
if (psychotic) {
|
|
result.hostname = '';
|
|
result.port = null;
|
|
if (result.host) {
|
|
if (srcPath[0] === '') srcPath[0] = result.host;
|
|
else srcPath.unshift(result.host);
|
|
}
|
|
result.host = '';
|
|
if (relative.protocol) {
|
|
relative.hostname = null;
|
|
relative.port = null;
|
|
if (relative.host) {
|
|
if (relPath[0] === '') relPath[0] = relative.host;
|
|
else relPath.unshift(relative.host);
|
|
}
|
|
relative.host = null;
|
|
}
|
|
mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
|
|
}
|
|
|
|
if (isRelAbs) {
|
|
// it's absolute.
|
|
result.host = (relative.host || relative.host === '') ?
|
|
relative.host : result.host;
|
|
result.hostname = (relative.hostname || relative.hostname === '') ?
|
|
relative.hostname : result.hostname;
|
|
result.search = relative.search;
|
|
result.query = relative.query;
|
|
srcPath = relPath;
|
|
// fall through to the dot-handling below.
|
|
} else if (relPath.length) {
|
|
// it's relative
|
|
// throw away the existing file, and take the new path instead.
|
|
if (!srcPath) srcPath = [];
|
|
srcPath.pop();
|
|
srcPath = srcPath.concat(relPath);
|
|
result.search = relative.search;
|
|
result.query = relative.query;
|
|
} else if (!util.isNullOrUndefined(relative.search)) {
|
|
// just pull out the search.
|
|
// like href='?foo'.
|
|
// Put this after the other two cases because it simplifies the booleans
|
|
if (psychotic) {
|
|
result.hostname = result.host = srcPath.shift();
|
|
//occationaly the auth can get stuck only in host
|
|
//this especially happens in cases like
|
|
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
|
|
var authInHost = result.host && result.host.indexOf('@') > 0 ?
|
|
result.host.split('@') : false;
|
|
if (authInHost) {
|
|
result.auth = authInHost.shift();
|
|
result.host = result.hostname = authInHost.shift();
|
|
}
|
|
}
|
|
result.search = relative.search;
|
|
result.query = relative.query;
|
|
//to support http.request
|
|
if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
|
|
result.path = (result.pathname ? result.pathname : '') +
|
|
(result.search ? result.search : '');
|
|
}
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
if (!srcPath.length) {
|
|
// no path at all. easy.
|
|
// we've already handled the other stuff above.
|
|
result.pathname = null;
|
|
//to support http.request
|
|
if (result.search) {
|
|
result.path = '/' + result.search;
|
|
} else {
|
|
result.path = null;
|
|
}
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
// if a url ENDs in . or .., then it must get a trailing slash.
|
|
// however, if it ends in anything else non-slashy,
|
|
// then it must NOT get a trailing slash.
|
|
var last = srcPath.slice(-1)[0];
|
|
var hasTrailingSlash = (
|
|
(result.host || relative.host || srcPath.length > 1) &&
|
|
(last === '.' || last === '..') || last === '');
|
|
|
|
// strip single dots, resolve double dots to parent dir
|
|
// if the path tries to go above the root, `up` ends up > 0
|
|
var up = 0;
|
|
for (var i = srcPath.length; i >= 0; i--) {
|
|
last = srcPath[i];
|
|
if (last === '.') {
|
|
srcPath.splice(i, 1);
|
|
} else if (last === '..') {
|
|
srcPath.splice(i, 1);
|
|
up++;
|
|
} else if (up) {
|
|
srcPath.splice(i, 1);
|
|
up--;
|
|
}
|
|
}
|
|
|
|
// if the path is allowed to go above the root, restore leading ..s
|
|
if (!mustEndAbs && !removeAllDots) {
|
|
for (; up--; up) {
|
|
srcPath.unshift('..');
|
|
}
|
|
}
|
|
|
|
if (mustEndAbs && srcPath[0] !== '' &&
|
|
(!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
|
|
srcPath.unshift('');
|
|
}
|
|
|
|
if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
|
|
srcPath.push('');
|
|
}
|
|
|
|
var isAbsolute = srcPath[0] === '' ||
|
|
(srcPath[0] && srcPath[0].charAt(0) === '/');
|
|
|
|
// put the host back
|
|
if (psychotic) {
|
|
result.hostname = result.host = isAbsolute ? '' :
|
|
srcPath.length ? srcPath.shift() : '';
|
|
//occationaly the auth can get stuck only in host
|
|
//this especially happens in cases like
|
|
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
|
|
var authInHost = result.host && result.host.indexOf('@') > 0 ?
|
|
result.host.split('@') : false;
|
|
if (authInHost) {
|
|
result.auth = authInHost.shift();
|
|
result.host = result.hostname = authInHost.shift();
|
|
}
|
|
}
|
|
|
|
mustEndAbs = mustEndAbs || (result.host && srcPath.length);
|
|
|
|
if (mustEndAbs && !isAbsolute) {
|
|
srcPath.unshift('');
|
|
}
|
|
|
|
if (!srcPath.length) {
|
|
result.pathname = null;
|
|
result.path = null;
|
|
} else {
|
|
result.pathname = srcPath.join('/');
|
|
}
|
|
|
|
//to support request.http
|
|
if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
|
|
result.path = (result.pathname ? result.pathname : '') +
|
|
(result.search ? result.search : '');
|
|
}
|
|
result.auth = relative.auth || result.auth;
|
|
result.slashes = result.slashes || relative.slashes;
|
|
result.href = result.format();
|
|
return result;
|
|
};
|
|
|
|
Url.prototype.parseHost = function() {
|
|
var host = this.host;
|
|
var port = portPattern.exec(host);
|
|
if (port) {
|
|
port = port[0];
|
|
if (port !== ':') {
|
|
this.port = port.substr(1);
|
|
}
|
|
host = host.substr(0, host.length - port.length);
|
|
}
|
|
if (host) this.hostname = host;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/url/util.js":
|
|
/*!**********************************!*\
|
|
!*** ./node_modules/url/util.js ***!
|
|
\**********************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = {
|
|
isString: function(arg) {
|
|
return typeof(arg) === 'string';
|
|
},
|
|
isObject: function(arg) {
|
|
return typeof(arg) === 'object' && arg !== null;
|
|
},
|
|
isNull: function(arg) {
|
|
return arg === null;
|
|
},
|
|
isNullOrUndefined: function(arg) {
|
|
return arg == null;
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/ut_metadata/index.js":
|
|
/*!*******************************************!*\
|
|
!*** ./node_modules/ut_metadata/index.js ***!
|
|
\*******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/*! ut_metadata. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */
|
|
const { EventEmitter } = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
const bencode = __webpack_require__(/*! bencode */ "./node_modules/bencode/lib/index.js")
|
|
const BitField = __webpack_require__(/*! bitfield */ "./node_modules/bitfield/lib/index.js").default
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('ut_metadata')
|
|
const sha1 = __webpack_require__(/*! simple-sha1 */ "./node_modules/simple-sha1/browser.js")
|
|
|
|
const MAX_METADATA_SIZE = 1E7 // 10 MB
|
|
const BITFIELD_GROW = 1E3
|
|
const PIECE_LENGTH = 1 << 14 // 16 KiB
|
|
|
|
module.exports = metadata => {
|
|
class utMetadata extends EventEmitter {
|
|
constructor (wire) {
|
|
super()
|
|
|
|
this._wire = wire
|
|
|
|
this._fetching = false
|
|
this._metadataComplete = false
|
|
this._metadataSize = null
|
|
// how many reject messages to tolerate before quitting
|
|
this._remainingRejects = null
|
|
|
|
// The largest torrent file that I know of is ~1-2MB, which is ~100
|
|
// pieces. Therefore, cap the bitfield to 10x that (1000 pieces) so a
|
|
// malicious peer can't make it grow to fill all memory.
|
|
this._bitfield = new BitField(0, { grow: BITFIELD_GROW })
|
|
|
|
if (Buffer.isBuffer(metadata)) {
|
|
this.setMetadata(metadata)
|
|
}
|
|
}
|
|
|
|
onHandshake (infoHash, peerId, extensions) {
|
|
this._infoHash = infoHash
|
|
}
|
|
|
|
onExtendedHandshake (handshake) {
|
|
if (!handshake.m || !handshake.m.ut_metadata) {
|
|
return this.emit('warning', new Error('Peer does not support ut_metadata'))
|
|
}
|
|
if (!handshake.metadata_size) {
|
|
return this.emit('warning', new Error('Peer does not have metadata'))
|
|
}
|
|
if (typeof handshake.metadata_size !== 'number' ||
|
|
MAX_METADATA_SIZE < handshake.metadata_size ||
|
|
handshake.metadata_size <= 0) {
|
|
return this.emit('warning', new Error('Peer gave invalid metadata size'))
|
|
}
|
|
|
|
this._metadataSize = handshake.metadata_size
|
|
this._numPieces = Math.ceil(this._metadataSize / PIECE_LENGTH)
|
|
this._remainingRejects = this._numPieces * 2
|
|
|
|
this._requestPieces()
|
|
}
|
|
|
|
onMessage (buf) {
|
|
let dict
|
|
let trailer
|
|
try {
|
|
const str = buf.toString()
|
|
const trailerIndex = str.indexOf('ee') + 2
|
|
dict = bencode.decode(str.substring(0, trailerIndex))
|
|
trailer = buf.slice(trailerIndex)
|
|
} catch (err) {
|
|
// drop invalid messages
|
|
return
|
|
}
|
|
|
|
switch (dict.msg_type) {
|
|
case 0:
|
|
// ut_metadata request (from peer)
|
|
// example: { 'msg_type': 0, 'piece': 0 }
|
|
this._onRequest(dict.piece)
|
|
break
|
|
case 1:
|
|
// ut_metadata data (in response to our request)
|
|
// example: { 'msg_type': 1, 'piece': 0, 'total_size': 3425 }
|
|
this._onData(dict.piece, trailer, dict.total_size)
|
|
break
|
|
case 2:
|
|
// ut_metadata reject (peer doesn't have piece we requested)
|
|
// { 'msg_type': 2, 'piece': 0 }
|
|
this._onReject(dict.piece)
|
|
break
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ask the peer to send metadata.
|
|
* @public
|
|
*/
|
|
fetch () {
|
|
if (this._metadataComplete) {
|
|
return
|
|
}
|
|
this._fetching = true
|
|
if (this._metadataSize) {
|
|
this._requestPieces()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stop asking the peer to send metadata.
|
|
* @public
|
|
*/
|
|
cancel () {
|
|
this._fetching = false
|
|
}
|
|
|
|
setMetadata (metadata) {
|
|
if (this._metadataComplete) return true
|
|
debug('set metadata')
|
|
|
|
// if full torrent dictionary was passed in, pull out just `info` key
|
|
try {
|
|
const info = bencode.decode(metadata).info
|
|
if (info) {
|
|
metadata = bencode.encode(info)
|
|
}
|
|
} catch (err) {}
|
|
|
|
// check hash
|
|
if (this._infoHash && this._infoHash !== sha1.sync(metadata)) {
|
|
return false
|
|
}
|
|
|
|
this.cancel()
|
|
|
|
this.metadata = metadata
|
|
this._metadataComplete = true
|
|
this._metadataSize = this.metadata.length
|
|
this._wire.extendedHandshake.metadata_size = this._metadataSize
|
|
|
|
this.emit('metadata', bencode.encode({
|
|
info: bencode.decode(this.metadata)
|
|
}))
|
|
|
|
return true
|
|
}
|
|
|
|
_send (dict, trailer) {
|
|
let buf = bencode.encode(dict)
|
|
if (Buffer.isBuffer(trailer)) {
|
|
buf = Buffer.concat([buf, trailer])
|
|
}
|
|
this._wire.extended('ut_metadata', buf)
|
|
}
|
|
|
|
_request (piece) {
|
|
this._send({ msg_type: 0, piece })
|
|
}
|
|
|
|
_data (piece, buf, totalSize) {
|
|
const msg = { msg_type: 1, piece }
|
|
if (typeof totalSize === 'number') {
|
|
msg.total_size = totalSize
|
|
}
|
|
this._send(msg, buf)
|
|
}
|
|
|
|
_reject (piece) {
|
|
this._send({ msg_type: 2, piece })
|
|
}
|
|
|
|
_onRequest (piece) {
|
|
if (!this._metadataComplete) {
|
|
this._reject(piece)
|
|
return
|
|
}
|
|
const start = piece * PIECE_LENGTH
|
|
let end = start + PIECE_LENGTH
|
|
if (end > this._metadataSize) {
|
|
end = this._metadataSize
|
|
}
|
|
const buf = this.metadata.slice(start, end)
|
|
this._data(piece, buf, this._metadataSize)
|
|
}
|
|
|
|
_onData (piece, buf, totalSize) {
|
|
if (buf.length > PIECE_LENGTH || !this._fetching) {
|
|
return
|
|
}
|
|
buf.copy(this.metadata, piece * PIECE_LENGTH)
|
|
this._bitfield.set(piece)
|
|
this._checkDone()
|
|
}
|
|
|
|
_onReject (piece) {
|
|
if (this._remainingRejects > 0 && this._fetching) {
|
|
// If we haven't been rejected too much,
|
|
// then try to request the piece again
|
|
this._request(piece)
|
|
this._remainingRejects -= 1
|
|
} else {
|
|
this.emit('warning', new Error('Peer sent "reject" too much'))
|
|
}
|
|
}
|
|
|
|
_requestPieces () {
|
|
if (!this._fetching) return
|
|
this.metadata = Buffer.alloc(this._metadataSize)
|
|
for (let piece = 0; piece < this._numPieces; piece++) {
|
|
this._request(piece)
|
|
}
|
|
}
|
|
|
|
_checkDone () {
|
|
let done = true
|
|
for (let piece = 0; piece < this._numPieces; piece++) {
|
|
if (!this._bitfield.get(piece)) {
|
|
done = false
|
|
break
|
|
}
|
|
}
|
|
if (!done) return
|
|
|
|
// attempt to set metadata -- may fail sha1 check
|
|
const success = this.setMetadata(this.metadata)
|
|
|
|
if (!success) {
|
|
this._failedMetadata()
|
|
}
|
|
}
|
|
|
|
_failedMetadata () {
|
|
// reset bitfield & try again
|
|
this._bitfield = new BitField(0, { grow: BITFIELD_GROW })
|
|
this._remainingRejects -= this._numPieces
|
|
if (this._remainingRejects > 0) {
|
|
this._requestPieces()
|
|
} else {
|
|
this.emit('warning', new Error('Peer sent invalid metadata'))
|
|
}
|
|
}
|
|
}
|
|
|
|
// Name of the bittorrent-protocol extension
|
|
utMetadata.prototype.name = 'ut_metadata'
|
|
|
|
return utMetadata
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/util-deprecate/browser.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/util-deprecate/browser.js ***!
|
|
\************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
|
|
/**
|
|
* Module exports.
|
|
*/
|
|
|
|
module.exports = deprecate;
|
|
|
|
/**
|
|
* Mark that a method should not be used.
|
|
* Returns a modified function which warns once by default.
|
|
*
|
|
* If `localStorage.noDeprecation = true` is set, then it is a no-op.
|
|
*
|
|
* If `localStorage.throwDeprecation = true` is set, then deprecated functions
|
|
* will throw an Error when invoked.
|
|
*
|
|
* If `localStorage.traceDeprecation = true` is set, then deprecated functions
|
|
* will invoke `console.trace()` instead of `console.error()`.
|
|
*
|
|
* @param {Function} fn - the function to deprecate
|
|
* @param {String} msg - the string to print to the console when `fn` is invoked
|
|
* @returns {Function} a new "deprecated" version of `fn`
|
|
* @api public
|
|
*/
|
|
|
|
function deprecate (fn, msg) {
|
|
if (config('noDeprecation')) {
|
|
return fn;
|
|
}
|
|
|
|
var warned = false;
|
|
function deprecated() {
|
|
if (!warned) {
|
|
if (config('throwDeprecation')) {
|
|
throw new Error(msg);
|
|
} else if (config('traceDeprecation')) {
|
|
console.trace(msg);
|
|
} else {
|
|
console.warn(msg);
|
|
}
|
|
warned = true;
|
|
}
|
|
return fn.apply(this, arguments);
|
|
}
|
|
|
|
return deprecated;
|
|
}
|
|
|
|
/**
|
|
* Checks `localStorage` for boolean values for the given `name`.
|
|
*
|
|
* @param {String} name
|
|
* @returns {Boolean}
|
|
* @api private
|
|
*/
|
|
|
|
function config (name) {
|
|
// accessing global.localStorage can trigger a DOMException in sandboxed iframes
|
|
try {
|
|
if (!__webpack_require__.g.localStorage) return false;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
var val = __webpack_require__.g.localStorage[name];
|
|
if (null == val) return false;
|
|
return String(val).toLowerCase() === 'true';
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/util/support/isBufferBrowser.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/util/support/isBufferBrowser.js ***!
|
|
\******************************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = function isBuffer(arg) {
|
|
return arg && typeof arg === 'object'
|
|
&& typeof arg.copy === 'function'
|
|
&& typeof arg.fill === 'function'
|
|
&& typeof arg.readUInt8 === 'function';
|
|
}
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/util/support/types.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/util/support/types.js ***!
|
|
\********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// Currently in sync with Node.js lib/internal/util/types.js
|
|
// https://github.com/nodejs/node/commit/112cc7c27551254aa2b17098fb774867f05ed0d9
|
|
|
|
|
|
|
|
var isArgumentsObject = __webpack_require__(/*! is-arguments */ "./node_modules/is-arguments/index.js");
|
|
var isGeneratorFunction = __webpack_require__(/*! is-generator-function */ "./node_modules/is-generator-function/index.js");
|
|
var whichTypedArray = __webpack_require__(/*! which-typed-array */ "./node_modules/which-typed-array/index.js");
|
|
var isTypedArray = __webpack_require__(/*! is-typed-array */ "./node_modules/is-typed-array/index.js");
|
|
|
|
function uncurryThis(f) {
|
|
return f.call.bind(f);
|
|
}
|
|
|
|
var BigIntSupported = typeof BigInt !== 'undefined';
|
|
var SymbolSupported = typeof Symbol !== 'undefined';
|
|
|
|
var ObjectToString = uncurryThis(Object.prototype.toString);
|
|
|
|
var numberValue = uncurryThis(Number.prototype.valueOf);
|
|
var stringValue = uncurryThis(String.prototype.valueOf);
|
|
var booleanValue = uncurryThis(Boolean.prototype.valueOf);
|
|
|
|
if (BigIntSupported) {
|
|
var bigIntValue = uncurryThis(BigInt.prototype.valueOf);
|
|
}
|
|
|
|
if (SymbolSupported) {
|
|
var symbolValue = uncurryThis(Symbol.prototype.valueOf);
|
|
}
|
|
|
|
function checkBoxedPrimitive(value, prototypeValueOf) {
|
|
if (typeof value !== 'object') {
|
|
return false;
|
|
}
|
|
try {
|
|
prototypeValueOf(value);
|
|
return true;
|
|
} catch(e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
exports.isArgumentsObject = isArgumentsObject;
|
|
exports.isGeneratorFunction = isGeneratorFunction;
|
|
exports.isTypedArray = isTypedArray;
|
|
|
|
// Taken from here and modified for better browser support
|
|
// https://github.com/sindresorhus/p-is-promise/blob/cda35a513bda03f977ad5cde3a079d237e82d7ef/index.js
|
|
function isPromise(input) {
|
|
return (
|
|
(
|
|
typeof Promise !== 'undefined' &&
|
|
input instanceof Promise
|
|
) ||
|
|
(
|
|
input !== null &&
|
|
typeof input === 'object' &&
|
|
typeof input.then === 'function' &&
|
|
typeof input.catch === 'function'
|
|
)
|
|
);
|
|
}
|
|
exports.isPromise = isPromise;
|
|
|
|
function isArrayBufferView(value) {
|
|
if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView) {
|
|
return ArrayBuffer.isView(value);
|
|
}
|
|
|
|
return (
|
|
isTypedArray(value) ||
|
|
isDataView(value)
|
|
);
|
|
}
|
|
exports.isArrayBufferView = isArrayBufferView;
|
|
|
|
|
|
function isUint8Array(value) {
|
|
return whichTypedArray(value) === 'Uint8Array';
|
|
}
|
|
exports.isUint8Array = isUint8Array;
|
|
|
|
function isUint8ClampedArray(value) {
|
|
return whichTypedArray(value) === 'Uint8ClampedArray';
|
|
}
|
|
exports.isUint8ClampedArray = isUint8ClampedArray;
|
|
|
|
function isUint16Array(value) {
|
|
return whichTypedArray(value) === 'Uint16Array';
|
|
}
|
|
exports.isUint16Array = isUint16Array;
|
|
|
|
function isUint32Array(value) {
|
|
return whichTypedArray(value) === 'Uint32Array';
|
|
}
|
|
exports.isUint32Array = isUint32Array;
|
|
|
|
function isInt8Array(value) {
|
|
return whichTypedArray(value) === 'Int8Array';
|
|
}
|
|
exports.isInt8Array = isInt8Array;
|
|
|
|
function isInt16Array(value) {
|
|
return whichTypedArray(value) === 'Int16Array';
|
|
}
|
|
exports.isInt16Array = isInt16Array;
|
|
|
|
function isInt32Array(value) {
|
|
return whichTypedArray(value) === 'Int32Array';
|
|
}
|
|
exports.isInt32Array = isInt32Array;
|
|
|
|
function isFloat32Array(value) {
|
|
return whichTypedArray(value) === 'Float32Array';
|
|
}
|
|
exports.isFloat32Array = isFloat32Array;
|
|
|
|
function isFloat64Array(value) {
|
|
return whichTypedArray(value) === 'Float64Array';
|
|
}
|
|
exports.isFloat64Array = isFloat64Array;
|
|
|
|
function isBigInt64Array(value) {
|
|
return whichTypedArray(value) === 'BigInt64Array';
|
|
}
|
|
exports.isBigInt64Array = isBigInt64Array;
|
|
|
|
function isBigUint64Array(value) {
|
|
return whichTypedArray(value) === 'BigUint64Array';
|
|
}
|
|
exports.isBigUint64Array = isBigUint64Array;
|
|
|
|
function isMapToString(value) {
|
|
return ObjectToString(value) === '[object Map]';
|
|
}
|
|
isMapToString.working = (
|
|
typeof Map !== 'undefined' &&
|
|
isMapToString(new Map())
|
|
);
|
|
|
|
function isMap(value) {
|
|
if (typeof Map === 'undefined') {
|
|
return false;
|
|
}
|
|
|
|
return isMapToString.working
|
|
? isMapToString(value)
|
|
: value instanceof Map;
|
|
}
|
|
exports.isMap = isMap;
|
|
|
|
function isSetToString(value) {
|
|
return ObjectToString(value) === '[object Set]';
|
|
}
|
|
isSetToString.working = (
|
|
typeof Set !== 'undefined' &&
|
|
isSetToString(new Set())
|
|
);
|
|
function isSet(value) {
|
|
if (typeof Set === 'undefined') {
|
|
return false;
|
|
}
|
|
|
|
return isSetToString.working
|
|
? isSetToString(value)
|
|
: value instanceof Set;
|
|
}
|
|
exports.isSet = isSet;
|
|
|
|
function isWeakMapToString(value) {
|
|
return ObjectToString(value) === '[object WeakMap]';
|
|
}
|
|
isWeakMapToString.working = (
|
|
typeof WeakMap !== 'undefined' &&
|
|
isWeakMapToString(new WeakMap())
|
|
);
|
|
function isWeakMap(value) {
|
|
if (typeof WeakMap === 'undefined') {
|
|
return false;
|
|
}
|
|
|
|
return isWeakMapToString.working
|
|
? isWeakMapToString(value)
|
|
: value instanceof WeakMap;
|
|
}
|
|
exports.isWeakMap = isWeakMap;
|
|
|
|
function isWeakSetToString(value) {
|
|
return ObjectToString(value) === '[object WeakSet]';
|
|
}
|
|
isWeakSetToString.working = (
|
|
typeof WeakSet !== 'undefined' &&
|
|
isWeakSetToString(new WeakSet())
|
|
);
|
|
function isWeakSet(value) {
|
|
return isWeakSetToString(value);
|
|
}
|
|
exports.isWeakSet = isWeakSet;
|
|
|
|
function isArrayBufferToString(value) {
|
|
return ObjectToString(value) === '[object ArrayBuffer]';
|
|
}
|
|
isArrayBufferToString.working = (
|
|
typeof ArrayBuffer !== 'undefined' &&
|
|
isArrayBufferToString(new ArrayBuffer())
|
|
);
|
|
function isArrayBuffer(value) {
|
|
if (typeof ArrayBuffer === 'undefined') {
|
|
return false;
|
|
}
|
|
|
|
return isArrayBufferToString.working
|
|
? isArrayBufferToString(value)
|
|
: value instanceof ArrayBuffer;
|
|
}
|
|
exports.isArrayBuffer = isArrayBuffer;
|
|
|
|
function isDataViewToString(value) {
|
|
return ObjectToString(value) === '[object DataView]';
|
|
}
|
|
isDataViewToString.working = (
|
|
typeof ArrayBuffer !== 'undefined' &&
|
|
typeof DataView !== 'undefined' &&
|
|
isDataViewToString(new DataView(new ArrayBuffer(1), 0, 1))
|
|
);
|
|
function isDataView(value) {
|
|
if (typeof DataView === 'undefined') {
|
|
return false;
|
|
}
|
|
|
|
return isDataViewToString.working
|
|
? isDataViewToString(value)
|
|
: value instanceof DataView;
|
|
}
|
|
exports.isDataView = isDataView;
|
|
|
|
// Store a copy of SharedArrayBuffer in case it's deleted elsewhere
|
|
var SharedArrayBufferCopy = typeof SharedArrayBuffer !== 'undefined' ? SharedArrayBuffer : undefined;
|
|
function isSharedArrayBufferToString(value) {
|
|
return ObjectToString(value) === '[object SharedArrayBuffer]';
|
|
}
|
|
function isSharedArrayBuffer(value) {
|
|
if (typeof SharedArrayBufferCopy === 'undefined') {
|
|
return false;
|
|
}
|
|
|
|
if (typeof isSharedArrayBufferToString.working === 'undefined') {
|
|
isSharedArrayBufferToString.working = isSharedArrayBufferToString(new SharedArrayBufferCopy());
|
|
}
|
|
|
|
return isSharedArrayBufferToString.working
|
|
? isSharedArrayBufferToString(value)
|
|
: value instanceof SharedArrayBufferCopy;
|
|
}
|
|
exports.isSharedArrayBuffer = isSharedArrayBuffer;
|
|
|
|
function isAsyncFunction(value) {
|
|
return ObjectToString(value) === '[object AsyncFunction]';
|
|
}
|
|
exports.isAsyncFunction = isAsyncFunction;
|
|
|
|
function isMapIterator(value) {
|
|
return ObjectToString(value) === '[object Map Iterator]';
|
|
}
|
|
exports.isMapIterator = isMapIterator;
|
|
|
|
function isSetIterator(value) {
|
|
return ObjectToString(value) === '[object Set Iterator]';
|
|
}
|
|
exports.isSetIterator = isSetIterator;
|
|
|
|
function isGeneratorObject(value) {
|
|
return ObjectToString(value) === '[object Generator]';
|
|
}
|
|
exports.isGeneratorObject = isGeneratorObject;
|
|
|
|
function isWebAssemblyCompiledModule(value) {
|
|
return ObjectToString(value) === '[object WebAssembly.Module]';
|
|
}
|
|
exports.isWebAssemblyCompiledModule = isWebAssemblyCompiledModule;
|
|
|
|
function isNumberObject(value) {
|
|
return checkBoxedPrimitive(value, numberValue);
|
|
}
|
|
exports.isNumberObject = isNumberObject;
|
|
|
|
function isStringObject(value) {
|
|
return checkBoxedPrimitive(value, stringValue);
|
|
}
|
|
exports.isStringObject = isStringObject;
|
|
|
|
function isBooleanObject(value) {
|
|
return checkBoxedPrimitive(value, booleanValue);
|
|
}
|
|
exports.isBooleanObject = isBooleanObject;
|
|
|
|
function isBigIntObject(value) {
|
|
return BigIntSupported && checkBoxedPrimitive(value, bigIntValue);
|
|
}
|
|
exports.isBigIntObject = isBigIntObject;
|
|
|
|
function isSymbolObject(value) {
|
|
return SymbolSupported && checkBoxedPrimitive(value, symbolValue);
|
|
}
|
|
exports.isSymbolObject = isSymbolObject;
|
|
|
|
function isBoxedPrimitive(value) {
|
|
return (
|
|
isNumberObject(value) ||
|
|
isStringObject(value) ||
|
|
isBooleanObject(value) ||
|
|
isBigIntObject(value) ||
|
|
isSymbolObject(value)
|
|
);
|
|
}
|
|
exports.isBoxedPrimitive = isBoxedPrimitive;
|
|
|
|
function isAnyArrayBuffer(value) {
|
|
return typeof Uint8Array !== 'undefined' && (
|
|
isArrayBuffer(value) ||
|
|
isSharedArrayBuffer(value)
|
|
);
|
|
}
|
|
exports.isAnyArrayBuffer = isAnyArrayBuffer;
|
|
|
|
['isProxy', 'isExternal', 'isModuleNamespaceObject'].forEach(function(method) {
|
|
Object.defineProperty(exports, method, {
|
|
enumerable: false,
|
|
value: function() {
|
|
throw new Error(method + ' is not supported in userland');
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/util/util.js":
|
|
/*!***********************************!*\
|
|
!*** ./node_modules/util/util.js ***!
|
|
\***********************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors ||
|
|
function getOwnPropertyDescriptors(obj) {
|
|
var keys = Object.keys(obj);
|
|
var descriptors = {};
|
|
for (var i = 0; i < keys.length; i++) {
|
|
descriptors[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i]);
|
|
}
|
|
return descriptors;
|
|
};
|
|
|
|
var formatRegExp = /%[sdj%]/g;
|
|
exports.format = function(f) {
|
|
if (!isString(f)) {
|
|
var objects = [];
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
objects.push(inspect(arguments[i]));
|
|
}
|
|
return objects.join(' ');
|
|
}
|
|
|
|
var i = 1;
|
|
var args = arguments;
|
|
var len = args.length;
|
|
var str = String(f).replace(formatRegExp, function(x) {
|
|
if (x === '%%') return '%';
|
|
if (i >= len) return x;
|
|
switch (x) {
|
|
case '%s': return String(args[i++]);
|
|
case '%d': return Number(args[i++]);
|
|
case '%j':
|
|
try {
|
|
return JSON.stringify(args[i++]);
|
|
} catch (_) {
|
|
return '[Circular]';
|
|
}
|
|
default:
|
|
return x;
|
|
}
|
|
});
|
|
for (var x = args[i]; i < len; x = args[++i]) {
|
|
if (isNull(x) || !isObject(x)) {
|
|
str += ' ' + x;
|
|
} else {
|
|
str += ' ' + inspect(x);
|
|
}
|
|
}
|
|
return str;
|
|
};
|
|
|
|
|
|
// Mark that a method should not be used.
|
|
// Returns a modified function which warns once by default.
|
|
// If --no-deprecation is set, then it is a no-op.
|
|
exports.deprecate = function(fn, msg) {
|
|
if (typeof process !== 'undefined' && process.noDeprecation === true) {
|
|
return fn;
|
|
}
|
|
|
|
// Allow for deprecating things in the process of starting up.
|
|
if (typeof process === 'undefined') {
|
|
return function() {
|
|
return exports.deprecate(fn, msg).apply(this, arguments);
|
|
};
|
|
}
|
|
|
|
var warned = false;
|
|
function deprecated() {
|
|
if (!warned) {
|
|
if (process.throwDeprecation) {
|
|
throw new Error(msg);
|
|
} else if (process.traceDeprecation) {
|
|
console.trace(msg);
|
|
} else {
|
|
console.error(msg);
|
|
}
|
|
warned = true;
|
|
}
|
|
return fn.apply(this, arguments);
|
|
}
|
|
|
|
return deprecated;
|
|
};
|
|
|
|
|
|
var debugs = {};
|
|
var debugEnvRegex = /^$/;
|
|
|
|
if (process.env.NODE_DEBUG) {
|
|
var debugEnv = process.env.NODE_DEBUG;
|
|
debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&')
|
|
.replace(/\*/g, '.*')
|
|
.replace(/,/g, '$|^')
|
|
.toUpperCase();
|
|
debugEnvRegex = new RegExp('^' + debugEnv + '$', 'i');
|
|
}
|
|
exports.debuglog = function(set) {
|
|
set = set.toUpperCase();
|
|
if (!debugs[set]) {
|
|
if (debugEnvRegex.test(set)) {
|
|
var pid = process.pid;
|
|
debugs[set] = function() {
|
|
var msg = exports.format.apply(exports, arguments);
|
|
console.error('%s %d: %s', set, pid, msg);
|
|
};
|
|
} else {
|
|
debugs[set] = function() {};
|
|
}
|
|
}
|
|
return debugs[set];
|
|
};
|
|
|
|
|
|
/**
|
|
* Echos the value of a value. Trys to print the value out
|
|
* in the best way possible given the different types.
|
|
*
|
|
* @param {Object} obj The object to print out.
|
|
* @param {Object} opts Optional options object that alters the output.
|
|
*/
|
|
/* legacy: obj, showHidden, depth, colors*/
|
|
function inspect(obj, opts) {
|
|
// default options
|
|
var ctx = {
|
|
seen: [],
|
|
stylize: stylizeNoColor
|
|
};
|
|
// legacy...
|
|
if (arguments.length >= 3) ctx.depth = arguments[2];
|
|
if (arguments.length >= 4) ctx.colors = arguments[3];
|
|
if (isBoolean(opts)) {
|
|
// legacy...
|
|
ctx.showHidden = opts;
|
|
} else if (opts) {
|
|
// got an "options" object
|
|
exports._extend(ctx, opts);
|
|
}
|
|
// set default options
|
|
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
|
|
if (isUndefined(ctx.depth)) ctx.depth = 2;
|
|
if (isUndefined(ctx.colors)) ctx.colors = false;
|
|
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
|
|
if (ctx.colors) ctx.stylize = stylizeWithColor;
|
|
return formatValue(ctx, obj, ctx.depth);
|
|
}
|
|
exports.inspect = inspect;
|
|
|
|
|
|
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
|
inspect.colors = {
|
|
'bold' : [1, 22],
|
|
'italic' : [3, 23],
|
|
'underline' : [4, 24],
|
|
'inverse' : [7, 27],
|
|
'white' : [37, 39],
|
|
'grey' : [90, 39],
|
|
'black' : [30, 39],
|
|
'blue' : [34, 39],
|
|
'cyan' : [36, 39],
|
|
'green' : [32, 39],
|
|
'magenta' : [35, 39],
|
|
'red' : [31, 39],
|
|
'yellow' : [33, 39]
|
|
};
|
|
|
|
// Don't use 'blue' not visible on cmd.exe
|
|
inspect.styles = {
|
|
'special': 'cyan',
|
|
'number': 'yellow',
|
|
'boolean': 'yellow',
|
|
'undefined': 'grey',
|
|
'null': 'bold',
|
|
'string': 'green',
|
|
'date': 'magenta',
|
|
// "name": intentionally not styling
|
|
'regexp': 'red'
|
|
};
|
|
|
|
|
|
function stylizeWithColor(str, styleType) {
|
|
var style = inspect.styles[styleType];
|
|
|
|
if (style) {
|
|
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
|
|
'\u001b[' + inspect.colors[style][1] + 'm';
|
|
} else {
|
|
return str;
|
|
}
|
|
}
|
|
|
|
|
|
function stylizeNoColor(str, styleType) {
|
|
return str;
|
|
}
|
|
|
|
|
|
function arrayToHash(array) {
|
|
var hash = {};
|
|
|
|
array.forEach(function(val, idx) {
|
|
hash[val] = true;
|
|
});
|
|
|
|
return hash;
|
|
}
|
|
|
|
|
|
function formatValue(ctx, value, recurseTimes) {
|
|
// Provide a hook for user-specified inspect functions.
|
|
// Check that value is an object with an inspect function on it
|
|
if (ctx.customInspect &&
|
|
value &&
|
|
isFunction(value.inspect) &&
|
|
// Filter out the util module, it's inspect function is special
|
|
value.inspect !== exports.inspect &&
|
|
// Also filter out any prototype objects using the circular check.
|
|
!(value.constructor && value.constructor.prototype === value)) {
|
|
var ret = value.inspect(recurseTimes, ctx);
|
|
if (!isString(ret)) {
|
|
ret = formatValue(ctx, ret, recurseTimes);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Primitive types cannot have properties
|
|
var primitive = formatPrimitive(ctx, value);
|
|
if (primitive) {
|
|
return primitive;
|
|
}
|
|
|
|
// Look up the keys of the object.
|
|
var keys = Object.keys(value);
|
|
var visibleKeys = arrayToHash(keys);
|
|
|
|
if (ctx.showHidden) {
|
|
keys = Object.getOwnPropertyNames(value);
|
|
}
|
|
|
|
// IE doesn't make error fields non-enumerable
|
|
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
|
|
if (isError(value)
|
|
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
|
|
return formatError(value);
|
|
}
|
|
|
|
// Some type of object without properties can be shortcutted.
|
|
if (keys.length === 0) {
|
|
if (isFunction(value)) {
|
|
var name = value.name ? ': ' + value.name : '';
|
|
return ctx.stylize('[Function' + name + ']', 'special');
|
|
}
|
|
if (isRegExp(value)) {
|
|
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
|
}
|
|
if (isDate(value)) {
|
|
return ctx.stylize(Date.prototype.toString.call(value), 'date');
|
|
}
|
|
if (isError(value)) {
|
|
return formatError(value);
|
|
}
|
|
}
|
|
|
|
var base = '', array = false, braces = ['{', '}'];
|
|
|
|
// Make Array say that they are Array
|
|
if (isArray(value)) {
|
|
array = true;
|
|
braces = ['[', ']'];
|
|
}
|
|
|
|
// Make functions say that they are functions
|
|
if (isFunction(value)) {
|
|
var n = value.name ? ': ' + value.name : '';
|
|
base = ' [Function' + n + ']';
|
|
}
|
|
|
|
// Make RegExps say that they are RegExps
|
|
if (isRegExp(value)) {
|
|
base = ' ' + RegExp.prototype.toString.call(value);
|
|
}
|
|
|
|
// Make dates with properties first say the date
|
|
if (isDate(value)) {
|
|
base = ' ' + Date.prototype.toUTCString.call(value);
|
|
}
|
|
|
|
// Make error with message first say the error
|
|
if (isError(value)) {
|
|
base = ' ' + formatError(value);
|
|
}
|
|
|
|
if (keys.length === 0 && (!array || value.length == 0)) {
|
|
return braces[0] + base + braces[1];
|
|
}
|
|
|
|
if (recurseTimes < 0) {
|
|
if (isRegExp(value)) {
|
|
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
|
} else {
|
|
return ctx.stylize('[Object]', 'special');
|
|
}
|
|
}
|
|
|
|
ctx.seen.push(value);
|
|
|
|
var output;
|
|
if (array) {
|
|
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
|
} else {
|
|
output = keys.map(function(key) {
|
|
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
|
});
|
|
}
|
|
|
|
ctx.seen.pop();
|
|
|
|
return reduceToSingleString(output, base, braces);
|
|
}
|
|
|
|
|
|
function formatPrimitive(ctx, value) {
|
|
if (isUndefined(value))
|
|
return ctx.stylize('undefined', 'undefined');
|
|
if (isString(value)) {
|
|
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
|
.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"') + '\'';
|
|
return ctx.stylize(simple, 'string');
|
|
}
|
|
if (isNumber(value))
|
|
return ctx.stylize('' + value, 'number');
|
|
if (isBoolean(value))
|
|
return ctx.stylize('' + value, 'boolean');
|
|
// For some reason typeof null is "object", so special case here.
|
|
if (isNull(value))
|
|
return ctx.stylize('null', 'null');
|
|
}
|
|
|
|
|
|
function formatError(value) {
|
|
return '[' + Error.prototype.toString.call(value) + ']';
|
|
}
|
|
|
|
|
|
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
|
var output = [];
|
|
for (var i = 0, l = value.length; i < l; ++i) {
|
|
if (hasOwnProperty(value, String(i))) {
|
|
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
|
String(i), true));
|
|
} else {
|
|
output.push('');
|
|
}
|
|
}
|
|
keys.forEach(function(key) {
|
|
if (!key.match(/^\d+$/)) {
|
|
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
|
key, true));
|
|
}
|
|
});
|
|
return output;
|
|
}
|
|
|
|
|
|
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
|
var name, str, desc;
|
|
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
|
|
if (desc.get) {
|
|
if (desc.set) {
|
|
str = ctx.stylize('[Getter/Setter]', 'special');
|
|
} else {
|
|
str = ctx.stylize('[Getter]', 'special');
|
|
}
|
|
} else {
|
|
if (desc.set) {
|
|
str = ctx.stylize('[Setter]', 'special');
|
|
}
|
|
}
|
|
if (!hasOwnProperty(visibleKeys, key)) {
|
|
name = '[' + key + ']';
|
|
}
|
|
if (!str) {
|
|
if (ctx.seen.indexOf(desc.value) < 0) {
|
|
if (isNull(recurseTimes)) {
|
|
str = formatValue(ctx, desc.value, null);
|
|
} else {
|
|
str = formatValue(ctx, desc.value, recurseTimes - 1);
|
|
}
|
|
if (str.indexOf('\n') > -1) {
|
|
if (array) {
|
|
str = str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n').substr(2);
|
|
} else {
|
|
str = '\n' + str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n');
|
|
}
|
|
}
|
|
} else {
|
|
str = ctx.stylize('[Circular]', 'special');
|
|
}
|
|
}
|
|
if (isUndefined(name)) {
|
|
if (array && key.match(/^\d+$/)) {
|
|
return str;
|
|
}
|
|
name = JSON.stringify('' + key);
|
|
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
|
name = name.substr(1, name.length - 2);
|
|
name = ctx.stylize(name, 'name');
|
|
} else {
|
|
name = name.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"')
|
|
.replace(/(^"|"$)/g, "'");
|
|
name = ctx.stylize(name, 'string');
|
|
}
|
|
}
|
|
|
|
return name + ': ' + str;
|
|
}
|
|
|
|
|
|
function reduceToSingleString(output, base, braces) {
|
|
var numLinesEst = 0;
|
|
var length = output.reduce(function(prev, cur) {
|
|
numLinesEst++;
|
|
if (cur.indexOf('\n') >= 0) numLinesEst++;
|
|
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
|
|
}, 0);
|
|
|
|
if (length > 60) {
|
|
return braces[0] +
|
|
(base === '' ? '' : base + '\n ') +
|
|
' ' +
|
|
output.join(',\n ') +
|
|
' ' +
|
|
braces[1];
|
|
}
|
|
|
|
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
|
}
|
|
|
|
|
|
// NOTE: These type checking functions intentionally don't use `instanceof`
|
|
// because it is fragile and can be easily faked with `Object.create()`.
|
|
exports.types = __webpack_require__(/*! ./support/types */ "./node_modules/util/support/types.js");
|
|
|
|
function isArray(ar) {
|
|
return Array.isArray(ar);
|
|
}
|
|
exports.isArray = isArray;
|
|
|
|
function isBoolean(arg) {
|
|
return typeof arg === 'boolean';
|
|
}
|
|
exports.isBoolean = isBoolean;
|
|
|
|
function isNull(arg) {
|
|
return arg === null;
|
|
}
|
|
exports.isNull = isNull;
|
|
|
|
function isNullOrUndefined(arg) {
|
|
return arg == null;
|
|
}
|
|
exports.isNullOrUndefined = isNullOrUndefined;
|
|
|
|
function isNumber(arg) {
|
|
return typeof arg === 'number';
|
|
}
|
|
exports.isNumber = isNumber;
|
|
|
|
function isString(arg) {
|
|
return typeof arg === 'string';
|
|
}
|
|
exports.isString = isString;
|
|
|
|
function isSymbol(arg) {
|
|
return typeof arg === 'symbol';
|
|
}
|
|
exports.isSymbol = isSymbol;
|
|
|
|
function isUndefined(arg) {
|
|
return arg === void 0;
|
|
}
|
|
exports.isUndefined = isUndefined;
|
|
|
|
function isRegExp(re) {
|
|
return isObject(re) && objectToString(re) === '[object RegExp]';
|
|
}
|
|
exports.isRegExp = isRegExp;
|
|
exports.types.isRegExp = isRegExp;
|
|
|
|
function isObject(arg) {
|
|
return typeof arg === 'object' && arg !== null;
|
|
}
|
|
exports.isObject = isObject;
|
|
|
|
function isDate(d) {
|
|
return isObject(d) && objectToString(d) === '[object Date]';
|
|
}
|
|
exports.isDate = isDate;
|
|
exports.types.isDate = isDate;
|
|
|
|
function isError(e) {
|
|
return isObject(e) &&
|
|
(objectToString(e) === '[object Error]' || e instanceof Error);
|
|
}
|
|
exports.isError = isError;
|
|
exports.types.isNativeError = isError;
|
|
|
|
function isFunction(arg) {
|
|
return typeof arg === 'function';
|
|
}
|
|
exports.isFunction = isFunction;
|
|
|
|
function isPrimitive(arg) {
|
|
return arg === null ||
|
|
typeof arg === 'boolean' ||
|
|
typeof arg === 'number' ||
|
|
typeof arg === 'string' ||
|
|
typeof arg === 'symbol' || // ES6 symbol
|
|
typeof arg === 'undefined';
|
|
}
|
|
exports.isPrimitive = isPrimitive;
|
|
|
|
exports.isBuffer = __webpack_require__(/*! ./support/isBuffer */ "./node_modules/util/support/isBufferBrowser.js");
|
|
|
|
function objectToString(o) {
|
|
return Object.prototype.toString.call(o);
|
|
}
|
|
|
|
|
|
function pad(n) {
|
|
return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
|
}
|
|
|
|
|
|
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
|
'Oct', 'Nov', 'Dec'];
|
|
|
|
// 26 Feb 16:19:34
|
|
function timestamp() {
|
|
var d = new Date();
|
|
var time = [pad(d.getHours()),
|
|
pad(d.getMinutes()),
|
|
pad(d.getSeconds())].join(':');
|
|
return [d.getDate(), months[d.getMonth()], time].join(' ');
|
|
}
|
|
|
|
|
|
// log is just a thin wrapper to console.log that prepends a timestamp
|
|
exports.log = function() {
|
|
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
|
|
};
|
|
|
|
|
|
/**
|
|
* Inherit the prototype methods from one constructor into another.
|
|
*
|
|
* The Function.prototype.inherits from lang.js rewritten as a standalone
|
|
* function (not on Function.prototype). NOTE: If this file is to be loaded
|
|
* during bootstrapping this function needs to be rewritten using some native
|
|
* functions as prototype setup using normal JavaScript does not work as
|
|
* expected during bootstrapping (see mirror.js in r114903).
|
|
*
|
|
* @param {function} ctor Constructor function which needs to inherit the
|
|
* prototype.
|
|
* @param {function} superCtor Constructor function to inherit prototype from.
|
|
*/
|
|
exports.inherits = __webpack_require__(/*! inherits */ "./node_modules/inherits/inherits_browser.js");
|
|
|
|
exports._extend = function(origin, add) {
|
|
// Don't do anything if add isn't an object
|
|
if (!add || !isObject(add)) return origin;
|
|
|
|
var keys = Object.keys(add);
|
|
var i = keys.length;
|
|
while (i--) {
|
|
origin[keys[i]] = add[keys[i]];
|
|
}
|
|
return origin;
|
|
};
|
|
|
|
function hasOwnProperty(obj, prop) {
|
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
}
|
|
|
|
var kCustomPromisifiedSymbol = typeof Symbol !== 'undefined' ? Symbol('util.promisify.custom') : undefined;
|
|
|
|
exports.promisify = function promisify(original) {
|
|
if (typeof original !== 'function')
|
|
throw new TypeError('The "original" argument must be of type Function');
|
|
|
|
if (kCustomPromisifiedSymbol && original[kCustomPromisifiedSymbol]) {
|
|
var fn = original[kCustomPromisifiedSymbol];
|
|
if (typeof fn !== 'function') {
|
|
throw new TypeError('The "util.promisify.custom" argument must be of type Function');
|
|
}
|
|
Object.defineProperty(fn, kCustomPromisifiedSymbol, {
|
|
value: fn, enumerable: false, writable: false, configurable: true
|
|
});
|
|
return fn;
|
|
}
|
|
|
|
function fn() {
|
|
var promiseResolve, promiseReject;
|
|
var promise = new Promise(function (resolve, reject) {
|
|
promiseResolve = resolve;
|
|
promiseReject = reject;
|
|
});
|
|
|
|
var args = [];
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
args.push(arguments[i]);
|
|
}
|
|
args.push(function (err, value) {
|
|
if (err) {
|
|
promiseReject(err);
|
|
} else {
|
|
promiseResolve(value);
|
|
}
|
|
});
|
|
|
|
try {
|
|
original.apply(this, args);
|
|
} catch (err) {
|
|
promiseReject(err);
|
|
}
|
|
|
|
return promise;
|
|
}
|
|
|
|
Object.setPrototypeOf(fn, Object.getPrototypeOf(original));
|
|
|
|
if (kCustomPromisifiedSymbol) Object.defineProperty(fn, kCustomPromisifiedSymbol, {
|
|
value: fn, enumerable: false, writable: false, configurable: true
|
|
});
|
|
return Object.defineProperties(
|
|
fn,
|
|
getOwnPropertyDescriptors(original)
|
|
);
|
|
}
|
|
|
|
exports.promisify.custom = kCustomPromisifiedSymbol
|
|
|
|
function callbackifyOnRejected(reason, cb) {
|
|
// `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M).
|
|
// Because `null` is a special error value in callbacks which means "no error
|
|
// occurred", we error-wrap so the callback consumer can distinguish between
|
|
// "the promise rejected with null" or "the promise fulfilled with undefined".
|
|
if (!reason) {
|
|
var newReason = new Error('Promise was rejected with a falsy value');
|
|
newReason.reason = reason;
|
|
reason = newReason;
|
|
}
|
|
return cb(reason);
|
|
}
|
|
|
|
function callbackify(original) {
|
|
if (typeof original !== 'function') {
|
|
throw new TypeError('The "original" argument must be of type Function');
|
|
}
|
|
|
|
// We DO NOT return the promise as it gives the user a false sense that
|
|
// the promise is actually somehow related to the callback's execution
|
|
// and that the callback throwing will reject the promise.
|
|
function callbackified() {
|
|
var args = [];
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
args.push(arguments[i]);
|
|
}
|
|
|
|
var maybeCb = args.pop();
|
|
if (typeof maybeCb !== 'function') {
|
|
throw new TypeError('The last argument must be of type Function');
|
|
}
|
|
var self = this;
|
|
var cb = function() {
|
|
return maybeCb.apply(self, arguments);
|
|
};
|
|
// In true node style we process the callback on `nextTick` with all the
|
|
// implications (stack, `uncaughtException`, `async_hooks`)
|
|
original.apply(this, args)
|
|
.then(function(ret) { process.nextTick(cb.bind(null, null, ret)) },
|
|
function(rej) { process.nextTick(callbackifyOnRejected.bind(null, rej, cb)) });
|
|
}
|
|
|
|
Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original));
|
|
Object.defineProperties(callbackified,
|
|
getOwnPropertyDescriptors(original));
|
|
return callbackified;
|
|
}
|
|
exports.callbackify = callbackify;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/videostream/mp4-remuxer.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/videostream/mp4-remuxer.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
const bs = __webpack_require__(/*! binary-search */ "./node_modules/binary-search/index.js")
|
|
const EventEmitter = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
const mp4 = __webpack_require__(/*! mp4-stream */ "./node_modules/mp4-stream/index.js")
|
|
const Box = __webpack_require__(/*! mp4-box-encoding */ "./node_modules/mp4-box-encoding/index.js")
|
|
const RangeSliceStream = __webpack_require__(/*! range-slice-stream */ "./node_modules/range-slice-stream/index.js")
|
|
|
|
// if we want to ignore more than this many bytes, request a new stream.
|
|
// if we want to ignore fewer, just skip them.
|
|
const FIND_MOOV_SEEK_SIZE = 4096
|
|
|
|
class MP4Remuxer extends EventEmitter {
|
|
constructor (file) {
|
|
super()
|
|
|
|
this._tracks = []
|
|
this._file = file
|
|
this._decoder = null
|
|
this._findMoov(0)
|
|
}
|
|
|
|
_findMoov (offset) {
|
|
if (this._decoder) {
|
|
this._decoder.destroy()
|
|
}
|
|
|
|
let toSkip = 0
|
|
this._decoder = mp4.decode()
|
|
const fileStream = this._file.createReadStream({
|
|
start: offset
|
|
})
|
|
fileStream.pipe(this._decoder)
|
|
|
|
const boxHandler = headers => {
|
|
if (headers.type === 'moov') {
|
|
this._decoder.removeListener('box', boxHandler)
|
|
this._decoder.decode(moov => {
|
|
fileStream.destroy()
|
|
try {
|
|
this._processMoov(moov)
|
|
} catch (err) {
|
|
err.message = `Cannot parse mp4 file: ${err.message}`
|
|
this.emit('error', err)
|
|
}
|
|
})
|
|
} else if (headers.length < FIND_MOOV_SEEK_SIZE) {
|
|
toSkip += headers.length
|
|
this._decoder.ignore()
|
|
} else {
|
|
this._decoder.removeListener('box', boxHandler)
|
|
toSkip += headers.length
|
|
fileStream.destroy()
|
|
this._decoder.destroy()
|
|
this._findMoov(offset + toSkip)
|
|
}
|
|
}
|
|
this._decoder.on('box', boxHandler)
|
|
|
|
}
|
|
|
|
_processMoov (moov) {
|
|
const traks = moov.traks
|
|
this._tracks = []
|
|
this._hasVideo = false
|
|
this._hasAudio = false
|
|
for (let i = 0; i < traks.length; i++) {
|
|
const trak = traks[i]
|
|
const stbl = trak.mdia.minf.stbl
|
|
const stsdEntry = stbl.stsd.entries[0]
|
|
const handlerType = trak.mdia.hdlr.handlerType
|
|
let codec
|
|
let mime
|
|
if (handlerType === 'vide' && stsdEntry.type === 'avc1') {
|
|
if (this._hasVideo) {
|
|
continue
|
|
}
|
|
this._hasVideo = true
|
|
codec = 'avc1'
|
|
if (stsdEntry.avcC) {
|
|
codec += `.${stsdEntry.avcC.mimeCodec}`
|
|
}
|
|
mime = `video/mp4; codecs="${codec}"`
|
|
} else if (handlerType === 'soun' && stsdEntry.type === 'mp4a') {
|
|
if (this._hasAudio) {
|
|
continue
|
|
}
|
|
this._hasAudio = true
|
|
codec = 'mp4a'
|
|
if (stsdEntry.esds && stsdEntry.esds.mimeCodec) {
|
|
codec += `.${stsdEntry.esds.mimeCodec}`
|
|
}
|
|
mime = `audio/mp4; codecs="${codec}"`
|
|
} else {
|
|
continue
|
|
}
|
|
|
|
const samples = []
|
|
let sample = 0
|
|
|
|
// Chunk/position data
|
|
let sampleInChunk = 0
|
|
let chunk = 0
|
|
let offsetInChunk = 0
|
|
let sampleToChunkIndex = 0
|
|
|
|
// Time data
|
|
let dts = 0
|
|
const decodingTimeEntry = new RunLengthIndex(stbl.stts.entries)
|
|
let presentationOffsetEntry = null
|
|
if (stbl.ctts) {
|
|
presentationOffsetEntry = new RunLengthIndex(stbl.ctts.entries)
|
|
}
|
|
|
|
// Sync table index
|
|
let syncSampleIndex = 0
|
|
|
|
while (true) {
|
|
var currChunkEntry = stbl.stsc.entries[sampleToChunkIndex]
|
|
|
|
// Compute size
|
|
const size = stbl.stsz.entries[sample]
|
|
|
|
// Compute time data
|
|
const duration = decodingTimeEntry.value.duration
|
|
const presentationOffset = presentationOffsetEntry ? presentationOffsetEntry.value.compositionOffset : 0
|
|
|
|
// Compute sync
|
|
let sync = true
|
|
if (stbl.stss) {
|
|
sync = stbl.stss.entries[syncSampleIndex] === sample + 1
|
|
}
|
|
|
|
// Create new sample entry
|
|
const chunkOffsetTable = stbl.stco || stbl.co64
|
|
samples.push({
|
|
size,
|
|
duration,
|
|
dts,
|
|
presentationOffset,
|
|
sync,
|
|
offset: offsetInChunk + chunkOffsetTable.entries[chunk]
|
|
})
|
|
|
|
// Go to next sample
|
|
sample++
|
|
if (sample >= stbl.stsz.entries.length) {
|
|
break
|
|
}
|
|
|
|
// Move position/chunk
|
|
sampleInChunk++
|
|
offsetInChunk += size
|
|
if (sampleInChunk >= currChunkEntry.samplesPerChunk) {
|
|
// Move to new chunk
|
|
sampleInChunk = 0
|
|
offsetInChunk = 0
|
|
chunk++
|
|
// Move sample to chunk box index
|
|
const nextChunkEntry = stbl.stsc.entries[sampleToChunkIndex + 1]
|
|
if (nextChunkEntry && chunk + 1 >= nextChunkEntry.firstChunk) {
|
|
sampleToChunkIndex++
|
|
}
|
|
}
|
|
|
|
// Move time forward
|
|
dts += duration
|
|
decodingTimeEntry.inc()
|
|
presentationOffsetEntry && presentationOffsetEntry.inc()
|
|
|
|
// Move sync table index
|
|
if (sync) {
|
|
syncSampleIndex++
|
|
}
|
|
}
|
|
|
|
trak.mdia.mdhd.duration = 0
|
|
trak.tkhd.duration = 0
|
|
|
|
const defaultSampleDescriptionIndex = currChunkEntry.sampleDescriptionId
|
|
|
|
const trackMoov = {
|
|
type: 'moov',
|
|
mvhd: moov.mvhd,
|
|
traks: [{
|
|
tkhd: trak.tkhd,
|
|
mdia: {
|
|
mdhd: trak.mdia.mdhd,
|
|
hdlr: trak.mdia.hdlr,
|
|
elng: trak.mdia.elng,
|
|
minf: {
|
|
vmhd: trak.mdia.minf.vmhd,
|
|
smhd: trak.mdia.minf.smhd,
|
|
dinf: trak.mdia.minf.dinf,
|
|
stbl: {
|
|
stsd: stbl.stsd,
|
|
stts: empty(),
|
|
ctts: empty(),
|
|
stsc: empty(),
|
|
stsz: empty(),
|
|
stco: empty(),
|
|
stss: empty()
|
|
}
|
|
}
|
|
}
|
|
}],
|
|
mvex: {
|
|
mehd: {
|
|
fragmentDuration: moov.mvhd.duration
|
|
},
|
|
trexs: [{
|
|
trackId: trak.tkhd.trackId,
|
|
defaultSampleDescriptionIndex,
|
|
defaultSampleDuration: 0,
|
|
defaultSampleSize: 0,
|
|
defaultSampleFlags: 0
|
|
}]
|
|
}
|
|
}
|
|
|
|
this._tracks.push({
|
|
fragmentSequence: 1,
|
|
trackId: trak.tkhd.trackId,
|
|
timeScale: trak.mdia.mdhd.timeScale,
|
|
samples,
|
|
currSample: null,
|
|
currTime: null,
|
|
moov: trackMoov,
|
|
mime
|
|
})
|
|
}
|
|
|
|
if (this._tracks.length === 0) {
|
|
this.emit('error', new Error('no playable tracks'))
|
|
return
|
|
}
|
|
|
|
// Must be set last since this is used above
|
|
moov.mvhd.duration = 0
|
|
|
|
this._ftyp = {
|
|
type: 'ftyp',
|
|
brand: 'iso5',
|
|
brandVersion: 0,
|
|
compatibleBrands: [
|
|
'iso5'
|
|
]
|
|
}
|
|
|
|
const ftypBuf = Box.encode(this._ftyp)
|
|
const data = this._tracks.map(track => {
|
|
const moovBuf = Box.encode(track.moov)
|
|
return {
|
|
mime: track.mime,
|
|
init: Buffer.concat([ftypBuf, moovBuf])
|
|
}
|
|
})
|
|
|
|
this.emit('ready', data)
|
|
}
|
|
|
|
seek (time) {
|
|
if (!this._tracks) {
|
|
throw new Error('Not ready yet; wait for \'ready\' event')
|
|
}
|
|
|
|
if (this._fileStream) {
|
|
this._fileStream.destroy()
|
|
this._fileStream = null
|
|
}
|
|
|
|
let startOffset = -1
|
|
this._tracks.map((track, i) => {
|
|
// find the keyframe before the time
|
|
// stream from there
|
|
if (track.outStream) {
|
|
track.outStream.destroy()
|
|
}
|
|
if (track.inStream) {
|
|
track.inStream.destroy()
|
|
track.inStream = null
|
|
}
|
|
const outStream = track.outStream = mp4.encode()
|
|
const fragment = this._generateFragment(i, time)
|
|
if (!fragment) {
|
|
return outStream.finalize()
|
|
}
|
|
|
|
if (startOffset === -1 || fragment.ranges[0].start < startOffset) {
|
|
startOffset = fragment.ranges[0].start
|
|
}
|
|
|
|
const writeFragment = (frag) => {
|
|
if (outStream.destroyed) return
|
|
outStream.box(frag.moof, err => {
|
|
if (err) return this.emit('error', err)
|
|
if (outStream.destroyed) return
|
|
const slicedStream = track.inStream.slice(frag.ranges)
|
|
slicedStream.pipe(outStream.mediaData(frag.length, err => {
|
|
if (err) return this.emit('error', err)
|
|
if (outStream.destroyed) return
|
|
const nextFrag = this._generateFragment(i)
|
|
if (!nextFrag) {
|
|
return outStream.finalize()
|
|
}
|
|
writeFragment(nextFrag)
|
|
}))
|
|
})
|
|
}
|
|
writeFragment(fragment)
|
|
})
|
|
|
|
if (startOffset >= 0) {
|
|
const fileStream = this._fileStream = this._file.createReadStream({
|
|
start: startOffset
|
|
})
|
|
|
|
this._tracks.forEach(track => {
|
|
track.inStream = new RangeSliceStream(startOffset, {
|
|
// Allow up to a 10MB offset between audio and video,
|
|
// which should be fine for any reasonable interleaving
|
|
// interval and bitrate
|
|
highWaterMark: 10000000
|
|
})
|
|
fileStream.pipe(track.inStream)
|
|
})
|
|
}
|
|
|
|
return this._tracks.map(track => {
|
|
return track.outStream
|
|
})
|
|
}
|
|
|
|
_findSampleBefore (trackInd, time) {
|
|
const track = this._tracks[trackInd]
|
|
const scaledTime = Math.floor(track.timeScale * time)
|
|
let sample = bs(track.samples, scaledTime, (sample, t) => {
|
|
const pts = sample.dts + sample.presentationOffset// - track.editShift
|
|
return pts - t
|
|
})
|
|
if (sample === -1) {
|
|
sample = 0
|
|
} else if (sample < 0) {
|
|
sample = -sample - 2
|
|
}
|
|
// sample is now the last sample with dts <= time
|
|
// Find the preceeding sync sample
|
|
while (!track.samples[sample].sync) {
|
|
sample--
|
|
}
|
|
return sample
|
|
}
|
|
|
|
_generateFragment (track, time) {
|
|
/*
|
|
1. Find correct sample
|
|
2. Process backward until sync sample found
|
|
3. Process forward until next sync sample after MIN_FRAGMENT_DURATION found
|
|
*/
|
|
const currTrack = this._tracks[track]
|
|
let firstSample
|
|
if (time !== undefined) {
|
|
firstSample = this._findSampleBefore(track, time)
|
|
} else {
|
|
firstSample = currTrack.currSample
|
|
}
|
|
|
|
if (firstSample >= currTrack.samples.length) { return null }
|
|
|
|
const startDts = currTrack.samples[firstSample].dts
|
|
|
|
let totalLen = 0
|
|
const ranges = []
|
|
for (var currSample = firstSample; currSample < currTrack.samples.length; currSample++) {
|
|
const sample = currTrack.samples[currSample]
|
|
if (sample.sync && sample.dts - startDts >= currTrack.timeScale * MIN_FRAGMENT_DURATION) {
|
|
break // This is a reasonable place to end the fragment
|
|
}
|
|
|
|
totalLen += sample.size
|
|
const currRange = ranges.length - 1
|
|
if (currRange < 0 || ranges[currRange].end !== sample.offset) {
|
|
// Push a new range
|
|
ranges.push({
|
|
start: sample.offset,
|
|
end: sample.offset + sample.size
|
|
})
|
|
} else {
|
|
ranges[currRange].end += sample.size
|
|
}
|
|
}
|
|
|
|
currTrack.currSample = currSample
|
|
|
|
return {
|
|
moof: this._generateMoof(track, firstSample, currSample),
|
|
ranges,
|
|
length: totalLen
|
|
}
|
|
}
|
|
|
|
_generateMoof (track, firstSample, lastSample) {
|
|
const currTrack = this._tracks[track]
|
|
|
|
const entries = []
|
|
let trunVersion = 0
|
|
for (let j = firstSample; j < lastSample; j++) {
|
|
const currSample = currTrack.samples[j]
|
|
if (currSample.presentationOffset < 0) { trunVersion = 1 }
|
|
entries.push({
|
|
sampleDuration: currSample.duration,
|
|
sampleSize: currSample.size,
|
|
sampleFlags: currSample.sync ? 0x2000000 : 0x1010000,
|
|
sampleCompositionTimeOffset: currSample.presentationOffset
|
|
})
|
|
}
|
|
|
|
const moof = {
|
|
type: 'moof',
|
|
mfhd: {
|
|
sequenceNumber: currTrack.fragmentSequence++
|
|
},
|
|
trafs: [{
|
|
tfhd: {
|
|
flags: 0x20000, // default-base-is-moof
|
|
trackId: currTrack.trackId
|
|
},
|
|
tfdt: {
|
|
baseMediaDecodeTime: currTrack.samples[firstSample].dts
|
|
},
|
|
trun: {
|
|
flags: 0xf01,
|
|
dataOffset: 8, // The moof size has to be added to this later as well
|
|
entries,
|
|
version: trunVersion
|
|
}
|
|
}]
|
|
}
|
|
|
|
// Update the offset
|
|
moof.trafs[0].trun.dataOffset += Box.encodingLength(moof)
|
|
|
|
return moof
|
|
}
|
|
}
|
|
|
|
class RunLengthIndex {
|
|
constructor (entries, countName) {
|
|
this._entries = entries
|
|
this._countName = countName || 'count'
|
|
this._index = 0
|
|
this._offset = 0
|
|
|
|
this.value = this._entries[0]
|
|
}
|
|
|
|
inc () {
|
|
this._offset++
|
|
if (this._offset >= this._entries[this._index][this._countName]) {
|
|
this._index++
|
|
this._offset = 0
|
|
}
|
|
|
|
this.value = this._entries[this._index]
|
|
}
|
|
}
|
|
|
|
function empty () {
|
|
return {
|
|
version: 0,
|
|
flags: 0,
|
|
entries: []
|
|
}
|
|
}
|
|
|
|
const MIN_FRAGMENT_DURATION = 1 // second
|
|
|
|
module.exports = MP4Remuxer
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/videostream/videostream.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/videostream/videostream.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
const MediaElementWrapper = __webpack_require__(/*! mediasource */ "./node_modules/mediasource/index.js")
|
|
const pump = __webpack_require__(/*! pump */ "./node_modules/pump/index.js")
|
|
|
|
const MP4Remuxer = __webpack_require__(/*! ./mp4-remuxer */ "./node_modules/videostream/mp4-remuxer.js")
|
|
|
|
function VideoStream (file, mediaElem, opts = {}) {
|
|
if (!(this instanceof VideoStream)) {
|
|
console.warn("Don't invoke VideoStream without the 'new' keyword.")
|
|
return new VideoStream(file, mediaElem, opts)
|
|
}
|
|
|
|
this.detailedError = null
|
|
|
|
this._elem = mediaElem
|
|
this._elemWrapper = new MediaElementWrapper(mediaElem)
|
|
this._waitingFired = false
|
|
this._trackMeta = null
|
|
this._file = file
|
|
this._tracks = null
|
|
|
|
if (this._elem.preload !== 'none') {
|
|
this._createMuxer()
|
|
}
|
|
|
|
this._onError = () => {
|
|
this.detailedError = this._elemWrapper.detailedError
|
|
this.destroy() // don't pass err though so the user doesn't need to listen for errors
|
|
}
|
|
|
|
this._onWaiting = () => {
|
|
this._waitingFired = true
|
|
if (!this._muxer) {
|
|
this._createMuxer()
|
|
} else if (this._tracks) {
|
|
this._pump()
|
|
}
|
|
}
|
|
|
|
if (mediaElem.autoplay) { mediaElem.preload = 'auto' }
|
|
mediaElem.addEventListener('waiting', this._onWaiting)
|
|
mediaElem.addEventListener('error', this._onError)
|
|
}
|
|
|
|
VideoStream.prototype = {
|
|
_createMuxer () {
|
|
this._muxer = new MP4Remuxer(this._file)
|
|
this._muxer.on('ready', data => {
|
|
this._tracks = data.map(trackData => {
|
|
const mediaSource = this._elemWrapper.createWriteStream(trackData.mime)
|
|
mediaSource.on('error', err => {
|
|
this._elemWrapper.error(err)
|
|
})
|
|
const track = {
|
|
muxed: null,
|
|
mediaSource,
|
|
initFlushed: false,
|
|
onInitFlushed: null
|
|
}
|
|
mediaSource.write(trackData.init, err => {
|
|
track.initFlushed = true
|
|
if (track.onInitFlushed) {
|
|
track.onInitFlushed(err)
|
|
}
|
|
})
|
|
return track
|
|
})
|
|
|
|
if (this._waitingFired || this._elem.preload === 'auto') {
|
|
this._pump()
|
|
}
|
|
})
|
|
|
|
this._muxer.on('error', err => {
|
|
this._elemWrapper.error(err)
|
|
})
|
|
},
|
|
_pump () {
|
|
const muxed = this._muxer.seek(this._elem.currentTime, !this._tracks)
|
|
|
|
this._tracks.forEach((track, i) => {
|
|
const pumpTrack = () => {
|
|
if (track.muxed) {
|
|
track.muxed.destroy()
|
|
track.mediaSource = this._elemWrapper.createWriteStream(track.mediaSource)
|
|
track.mediaSource.on('error', err => {
|
|
this._elemWrapper.error(err)
|
|
})
|
|
}
|
|
track.muxed = muxed[i]
|
|
pump(track.muxed, track.mediaSource)
|
|
}
|
|
if (!track.initFlushed) {
|
|
track.onInitFlushed = err => {
|
|
if (err) {
|
|
this._elemWrapper.error(err)
|
|
return
|
|
}
|
|
pumpTrack()
|
|
}
|
|
} else {
|
|
pumpTrack()
|
|
}
|
|
})
|
|
},
|
|
destroy () {
|
|
if (this.destroyed) {
|
|
return
|
|
}
|
|
this.destroyed = true
|
|
|
|
this._elem.removeEventListener('waiting', this._onWaiting)
|
|
this._elem.removeEventListener('error', this._onError)
|
|
|
|
if (this._tracks) {
|
|
this._tracks.forEach(track => {
|
|
if (track.muxed) {
|
|
track.muxed.destroy()
|
|
}
|
|
})
|
|
}
|
|
|
|
this._elem.src = ''
|
|
}
|
|
}
|
|
|
|
module.exports = VideoStream
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webtorrent-player/index.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/webtorrent-player/index.js ***!
|
|
\*************************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "default": () => (/* binding */ WebTorrentPlayer)
|
|
/* harmony export */ });
|
|
/* harmony import */ var webtorrent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! webtorrent */ "./node_modules/webtorrent/index.js");
|
|
/* harmony import */ var webtorrent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(webtorrent__WEBPACK_IMPORTED_MODULE_0__);
|
|
/* harmony import */ var range_parser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! range-parser */ "./node_modules/range-parser/index.js");
|
|
/* harmony import */ var range_parser__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(range_parser__WEBPACK_IMPORTED_MODULE_1__);
|
|
/* harmony import */ var matroska_subtitles__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! matroska-subtitles */ "./node_modules/matroska-subtitles/dist/matroska-subtitles.module.js");
|
|
/* harmony import */ var hybrid_chunk_store__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! hybrid-chunk-store */ "./node_modules/hybrid-chunk-store/index.js");
|
|
/* harmony import */ var hybrid_chunk_store__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(hybrid_chunk_store__WEBPACK_IMPORTED_MODULE_3__);
|
|
/* harmony import */ var mime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! mime */ "./node_modules/mime/index.js");
|
|
/* harmony import */ var mime__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(mime__WEBPACK_IMPORTED_MODULE_4__);
|
|
/* harmony import */ var _lib_subtitles_octopus_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lib/subtitles-octopus.js */ "./node_modules/webtorrent-player/lib/subtitles-octopus.js");
|
|
/* harmony import */ var _lib_subtitles_octopus_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_lib_subtitles_octopus_js__WEBPACK_IMPORTED_MODULE_5__);
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
/* eslint-env browser */
|
|
/* global MediaMetadata, navNowPlaying */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const keepAliveTime = 20000
|
|
const units = [' B', ' kB', ' MB', ' GB', ' TB']
|
|
|
|
class WebTorrentPlayer extends (webtorrent__WEBPACK_IMPORTED_MODULE_0___default()) {
|
|
constructor (options = {}) {
|
|
super(options.WebTorrentOpts)
|
|
|
|
this.storeOpts = options.storeOpts || {}
|
|
|
|
this.scope = location.pathname.substr(0, location.pathname.lastIndexOf('/') + 1)
|
|
this.worker = navigator.serviceWorker.controller
|
|
if (!this.worker) {
|
|
navigator.serviceWorker.register('sw.js', { scope: this.scope }).then(reg => {
|
|
this.worker = reg.active || reg.waiting || reg.installing
|
|
}).catch(e => {
|
|
if (String(e) === 'InvalidStateError: Failed to register a ServiceWorker: The document is in an invalid state.') {
|
|
location.reload() // weird workaround for a weird bug
|
|
} else {
|
|
throw e
|
|
}
|
|
})
|
|
}
|
|
window.addEventListener('unload', () => {
|
|
this.cleanupTorrents()
|
|
this.cleanupVideo()
|
|
})
|
|
// kind of a fetch event from service worker but for the main thread.
|
|
navigator.serviceWorker.addEventListener('message', event => {
|
|
const { data } = event
|
|
if (!data.type || !data.type === 'webtorrent' || !data.url) return null
|
|
let [infoHash, ...filePath] = data.url.slice(data.url.indexOf(data.scope + 'webtorrent/') + 11 + data.scope.length).split('/')
|
|
filePath = decodeURI(filePath.join('/'))
|
|
|
|
if (!infoHash || !filePath) return null
|
|
|
|
const [port] = event.ports
|
|
const file = this.get(infoHash) && this.get(infoHash).files.find(file => file.path === filePath)
|
|
if (!file) return null
|
|
const [response, stream] = this.serveFile(file, data)
|
|
const asyncIterator = stream && stream[Symbol.asyncIterator]()
|
|
port.postMessage(response)
|
|
|
|
this.workerPortCount++
|
|
port.onmessage = async msg => {
|
|
if (msg.data) {
|
|
const chunk = (await asyncIterator.next()).value
|
|
port.postMessage(chunk)
|
|
if (!chunk) port.onmessage = null
|
|
if (!this.workerKeepAliveInterval) this.workerKeepAliveInterval = setInterval(() => fetch(`${this.worker.scriptURL.substr(0, this.worker.scriptURL.lastIndexOf('/') + 1).slice(window.location.origin.length)}webtorrent/keepalive/`), keepAliveTime)
|
|
} else {
|
|
stream.destroy()
|
|
port.onmessage = null
|
|
this.workerPortCount--
|
|
if (!this.workerPortCount) {
|
|
clearInterval(this.workerKeepAliveInterval)
|
|
this.workerKeepAliveInterval = null
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
this.video = options.video
|
|
this.controls = options.controls || {} // object of controls
|
|
// playPause, playNext, playLast, openPlaylist, toggleMute, setVolume, setProgress, selectCaptions, selectAudio, toggleTheatre, toggleFullscreen, togglePopout, forward, rewind
|
|
|
|
if (this.controls.setVolume) {
|
|
this.controls.setVolume.addEventListener('input', (e) => this.setVolume(e.target.value))
|
|
this.setVolume()
|
|
this.oldVolume = undefined
|
|
if ('audioTracks' in HTMLVideoElement.prototype && this.controls.audioButton) {
|
|
this.video.addEventListener('loadedmetadata', () => {
|
|
if (this.video.audioTracks.length > 1) {
|
|
this.controls.audioButton.removeAttribute('disabled')
|
|
for (const track of this.video.audioTracks) {
|
|
this.createRadioElement(track, 'audio')
|
|
}
|
|
} else {
|
|
this.controls.audioButton.setAttribute('disabled', '')
|
|
}
|
|
})
|
|
}
|
|
}
|
|
if (this.controls.ppToggle) {
|
|
this.controls.ppToggle.addEventListener('click', () => this.playPause())
|
|
this.controls.ppToggle.addEventListener('dblclick', () => this.toggleFullscreen())
|
|
}
|
|
|
|
if (this.controls.setProgress) {
|
|
this.controls.setProgress.addEventListener('input', e => this.setProgress(e.target.value))
|
|
this.controls.setProgress.addEventListener('mouseup', e => this.dragBarEnd(e.target.value))
|
|
this.controls.setProgress.addEventListener('touchend', e => this.dragBarEnd(e.target.value))
|
|
this.controls.setProgress.addEventListener('mousedown', e => this.dragBarStart(e.target.value))
|
|
this.video.addEventListener('timeupdate', e => {
|
|
if (this.immerseTimeout && document.location.hash === '#player' && !this.video.paused) this.setProgress(e.target.currentTime / e.target.duration * 100)
|
|
})
|
|
this.video.addEventListener('ended', () => this.setProgress(100))
|
|
}
|
|
|
|
this.video.addEventListener('loadedmetadata', () => this.findSubtitleFiles(this.currentFile))
|
|
this.subtitleData = {
|
|
fonts: [],
|
|
headers: [],
|
|
tracks: [],
|
|
current: undefined,
|
|
renderer: undefined,
|
|
stream: undefined,
|
|
parser: undefined,
|
|
parsed: undefined,
|
|
timeout: undefined,
|
|
defaultHeader: `[V4+ Styles]
|
|
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
|
|
Style: Default,${options.defaultSSAStyles || 'Roboto Medium,26,&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,1.3,0,2,20,20,23,1'}
|
|
[Events]
|
|
|
|
`
|
|
}
|
|
|
|
this.completed = false
|
|
this.video.addEventListener('timeupdate', () => this.checkCompletion())
|
|
|
|
this.nextTimeout = undefined
|
|
if (options.autoNext) this.video.addEventListener('ended', () => this.playNext())
|
|
|
|
this.resolveFileMedia = options.resolveFileMedia
|
|
this.currentFile = undefined
|
|
this.videoFile = undefined
|
|
|
|
if (this.controls.thumbnail) {
|
|
this.generateThumbnails = options.generateThumbnails
|
|
const thumbCanvas = document.createElement('canvas')
|
|
thumbCanvas.width = options.thumbnailWidth || 150
|
|
this.thumbnailData = {
|
|
thumbnails: [],
|
|
canvas: thumbCanvas,
|
|
context: thumbCanvas.getContext('2d'),
|
|
interval: undefined,
|
|
video: undefined
|
|
}
|
|
this.video.addEventListener('loadedmetadata', () => this.initThumbnail())
|
|
this.video.addEventListener('timeupdate', () => this.createThumbnail(this.video))
|
|
}
|
|
|
|
if (options.visibilityLossPause) {
|
|
document.addEventListener('visibilitychange', () => {
|
|
if (!this.video.ended) document.visibilityState === 'hidden' ? this.video.pause() : this.playPause()
|
|
})
|
|
}
|
|
|
|
this.onDone = undefined
|
|
|
|
this.destroyStore = options.destroyStore || true
|
|
|
|
this.immerseTimeout = undefined
|
|
this.immerseTime = options.immerseTime || 5
|
|
|
|
this.playerWrapper = options.playerWrapper
|
|
this.player = options.player
|
|
if (this.player) {
|
|
this.player.addEventListener('fullscreenchange', () => this.updateFullscreen())
|
|
this.player.addEventListener('mousemove', () => requestAnimationFrame(() => this.resetImmerse()))
|
|
this.player.addEventListener('touchmove', () => requestAnimationFrame(() => this.resetImmerse()))
|
|
this.player.addEventListener('keypress', () => requestAnimationFrame(() => this.resetImmerse()))
|
|
this.player.addEventListener('mouseleave', () => requestAnimationFrame(() => this.immersePlayer()))
|
|
|
|
this.doubleTapTimeout = undefined
|
|
this.player.addEventListener('touchend', e => {
|
|
if (this.doubleTapTimeout) {
|
|
e.preventDefault()
|
|
clearTimeout(this.doubleTapTimeout)
|
|
this.doubleTapTimeout = undefined
|
|
this.toggleFullscreen()
|
|
} else {
|
|
this.doubleTapTimeout = setTimeout(() => {
|
|
this.doubleTapTimeout = undefined
|
|
}, 200)
|
|
}
|
|
})
|
|
}
|
|
|
|
this.bufferTimeout = undefined
|
|
this.video.addEventListener('playing', () => this.hideBuffering())
|
|
this.video.addEventListener('canplay', () => this.hideBuffering())
|
|
this.video.addEventListener('loadeddata', () => this.hideBuffering())
|
|
this.video.addEventListener('waiting', () => this.showBuffering())
|
|
|
|
if ('pictureInPictureEnabled' in document) {
|
|
this.burnIn = options.burnIn
|
|
if (this.controls.togglePopout) this.controls.togglePopout.removeAttribute('disabled')
|
|
if (this.burnIn) this.video.addEventListener('enterpictureinpicture', () => { if (this.subtitleData.renderer) this.togglePopout() })
|
|
} else {
|
|
this.video.setAttribute('disablePictureInPicture', '')
|
|
if (this.controls.togglePopout) this.controls.togglePopout.setAttribute('disabled', '')
|
|
}
|
|
|
|
this.seekTime = options.seekTime || 5
|
|
if ('mediaSession' in navigator) {
|
|
navigator.mediaSession.setActionHandler('play', () => this.playPause())
|
|
navigator.mediaSession.setActionHandler('pause', () => this.playPause())
|
|
navigator.mediaSession.setActionHandler('seekbackward', () => this.seek(this.seekTime))
|
|
navigator.mediaSession.setActionHandler('seekforward', () => this.seek(this.seekTime))
|
|
navigator.mediaSession.setActionHandler('nexttrack', () => this.playNext())
|
|
}
|
|
if ('setPositionState' in navigator.mediaSession) this.video.addEventListener('timeupdate', () => this.updatePositionState())
|
|
|
|
this.subtitleExtensions = ['.srt', '.vtt', '.ass', '.ssa']
|
|
this.videoExtensions = ['.3g2', '.3gp', '.asf', '.avi', '.dv', '.flv', '.gxf', '.m2ts', '.m4a', '.m4b', '.m4p', '.m4r', '.m4v', '.mkv', '.mov', '.mp4', '.mpd', '.mpeg', '.mpg', '.mxf', '.nut', '.ogm', '.ogv', '.swf', '.ts', '.vob', '.webm', '.wmv', '.wtv']
|
|
this.videoFiles = undefined
|
|
|
|
this.updateDisplay()
|
|
this.offlineTorrents = JSON.parse(localStorage.getItem('offlineTorrents')) || {}
|
|
// adds all offline store torrents to the client
|
|
Object.values(this.offlineTorrents).forEach(torrentID => this.offlineDownload(new Blob([new Uint8Array(torrentID)])))
|
|
|
|
this.streamedDownload = options.streamedDownload
|
|
|
|
this.fps = 23.976
|
|
this.video.addEventListener('loadedmetadata', () => {
|
|
if (this.currentFile.name.endsWith('.mkv') && ('requestVideoFrameCallback' in HTMLVideoElement.prototype)) {
|
|
this.fps = new Promise(resolve => {
|
|
const resolveFps = () => {
|
|
this.video.removeEventListener('timeupdate', resolveFps)
|
|
if (!this.video.paused) {
|
|
setTimeout(() => this.video.requestVideoFrameCallback((now, metaData) => {
|
|
let duration = 0
|
|
for (let index = this.video.played.length; index--;) {
|
|
duration += this.video.played.end(index) - this.video.played.start(index)
|
|
}
|
|
const rawFPS = metaData.presentedFrames / duration
|
|
console.log(rawFPS, metaData)
|
|
if (rawFPS < 28) {
|
|
resolve(23.976)
|
|
} else if (rawFPS <= 35) {
|
|
resolve(29.97)
|
|
} else if (rawFPS <= 70) {
|
|
resolve(59.94)
|
|
} else {
|
|
resolve(23.976) // smth went VERY wrong
|
|
}
|
|
}), 2000)
|
|
}
|
|
}
|
|
this.video.addEventListener('timeupdate', resolveFps)
|
|
})
|
|
}
|
|
})
|
|
|
|
for (const [functionName, elements] of Object.entries(this.controls)) {
|
|
if (this[functionName]) {
|
|
if (elements.constructor === Array) {
|
|
for (const element of elements) {
|
|
element.addEventListener('click', e => {
|
|
this[functionName](e.target.value)
|
|
})
|
|
}
|
|
} else {
|
|
elements.addEventListener('click', e => {
|
|
this[functionName](e.target.value)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
document.addEventListener('keydown', a => {
|
|
if (a.key === 'F5') {
|
|
a.preventDefault()
|
|
}
|
|
if (location.hash === '#player') {
|
|
switch (a.key) {
|
|
case ' ':
|
|
this.playPause()
|
|
break
|
|
case 'n':
|
|
this.playNext()
|
|
break
|
|
case 'm':
|
|
this.toggleMute()
|
|
break
|
|
case 'p':
|
|
this.togglePopout()
|
|
break
|
|
case 't':
|
|
this.toggleTheatre()
|
|
break
|
|
case 'c':
|
|
this.captions()
|
|
break
|
|
case 'f':
|
|
this.toggleFullscreen()
|
|
break
|
|
case 's':
|
|
this.seek(85)
|
|
break
|
|
case 'ArrowLeft':
|
|
this.seek(-this.seekTime)
|
|
break
|
|
case 'ArrowRight':
|
|
this.seek(this.seekTime)
|
|
break
|
|
case 'ArrowUp':
|
|
this.setVolume(Number(this.controls.setVolume.value) + 5)
|
|
break
|
|
case 'ArrowDown':
|
|
this.setVolume(Number(this.controls.setVolume.value) - 5)
|
|
break
|
|
case 'Escape':
|
|
location.hash = '#home'
|
|
break
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
serveFile (file, req) {
|
|
const res = {
|
|
status: 200,
|
|
headers: {
|
|
// Support range-requests
|
|
'Accept-Ranges': 'bytes',
|
|
'Content-Type': mime__WEBPACK_IMPORTED_MODULE_4___default().getType(file.name),
|
|
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
|
|
Expires: '0'
|
|
},
|
|
body: req.method === 'HEAD' ? '' : 'STREAM'
|
|
}
|
|
// force the browser to download the file if if it's opened in a new tab
|
|
if (req.destination === 'document') {
|
|
res.headers['Content-Type'] = 'application/octet-stream'
|
|
res.headers['Content-Disposition'] = 'attachment'
|
|
res.body = 'DOWNLOAD'
|
|
}
|
|
|
|
// `rangeParser` returns an array of ranges, or an error code (number) if
|
|
// there was an error parsing the range.
|
|
let range = range_parser__WEBPACK_IMPORTED_MODULE_1___default()(file.length, req.headers.range || '')
|
|
|
|
if (range.constructor === Array) {
|
|
res.status = 206 // indicates that range-request was understood
|
|
|
|
// no support for multi-range request, just use the first range
|
|
range = range[0]
|
|
|
|
res.headers['Content-Range'] = `bytes ${range.start}-${range.end}/${file.length}`
|
|
res.headers['Content-Length'] = `${range.end - range.start + 1}`
|
|
} else {
|
|
res.headers['Content-Length'] = file.length
|
|
}
|
|
// parser is really a passthrough mkv stream now
|
|
const stream = file.createReadStream(range)
|
|
if (file.name.endsWith('.mkv') && !this.subtitleData.parsed) {
|
|
this.subtitleData.stream = new matroska_subtitles__WEBPACK_IMPORTED_MODULE_2__.SubtitleStream(this.subtitleData.stream)
|
|
this.handleSubtitleParser(this.subtitleData.stream)
|
|
stream.pipe(this.subtitleData.stream)
|
|
}
|
|
|
|
return [res, req.method === 'GET' && (this.subtitleData.stream || stream)]
|
|
}
|
|
|
|
async buildVideo (torrent, opts = {}) { // sets video source and creates a bunch of other media stuff
|
|
// play wanted episode from opts, or the 1st episode, or 1st file [batches: plays wanted episode, single: plays the only episode, manually added: plays first or only file]
|
|
this.cleanupVideo()
|
|
if (opts.file) {
|
|
this.currentFile = opts.file
|
|
} else if (this.videoFiles.length > 1) {
|
|
this.currentFile = this.videoFiles.filter(async file => await this.resolveFileMedia({ fileName: file.name }).then(FileMedia => (Number(FileMedia.episodeNumber) === Number(opts.episode || 1)) || (FileMedia === opts.media)))[0] || this.videoFiles[0]
|
|
} else {
|
|
this.currentFile = this.videoFiles[0]
|
|
}
|
|
await navigator.serviceWorker.ready
|
|
this.video.src = `${this.scope}webtorrent/${torrent.infoHash}/${encodeURI(this.currentFile.path)}`
|
|
this.video.load()
|
|
this.playVideo()
|
|
if (this.controls.downloadFile) this.controls.downloadFile.href = `${this.scope}webtorrent/${torrent.infoHash}/${encodeURI(this.currentFile.path)}`
|
|
|
|
if (this.currentFile.done) {
|
|
this.postDownload()
|
|
} else {
|
|
this.onDone = this.currentFile.on('done', () => {
|
|
this.postDownload()
|
|
})
|
|
}
|
|
// opts.media: mediaTitle, episodeNumber, episodeTitle, episodeThumbnail, mediaCover, name
|
|
this.nowPlaying = (opts.media && (this.videoFiles.length === 1 || (opts.forceMedia && opts.file))) ? opts.media : this.resolveFileMedia ? await this.resolveFileMedia({ fileName: this.currentFile.name, method: 'SearchName' }) : undefined
|
|
|
|
if (this.nowPlaying) {
|
|
if (navNowPlaying) navNowPlaying.classList.remove('d-none')
|
|
|
|
const episodeInfo = [this.nowPlaying.episodeNumber, this.nowPlaying.episodeTitle].filter(s => s).join(' - ')
|
|
|
|
if ('mediaSession' in navigator) {
|
|
navigator.mediaSession.metadata = new MediaMetadata({
|
|
title: this.nowPlaying.mediaTitle || this.nowPlaying.name || 'WebTorrentPlayer',
|
|
artist: 'Episode ' + episodeInfo,
|
|
album: this.nowPlaying.name || 'WebTorrentPlayer',
|
|
artwork: [{
|
|
src: this.nowPlaying.episodeThumbnail || this.nowPlaying.mediaCover || '',
|
|
sizes: '256x256',
|
|
type: 'image/jpg'
|
|
}]
|
|
})
|
|
}
|
|
if (this.nowPlaying.episodeThumbnail) this.video.poster = this.nowPlaying.episodeThumbnail
|
|
|
|
this.changeControlsIcon('nowPlaying', 'EP ' + episodeInfo)
|
|
document.title = [this.nowPlaying.mediaTitle, episodeInfo ? 'EP ' + episodeInfo : false, this.nowPlaying.name || 'WebTorrentPlayer'].filter(s => s).join(' - ')
|
|
}
|
|
}
|
|
|
|
cleanupVideo () { // cleans up objects, attemps to clear as much video caching as possible
|
|
if (this.subtitleData.renderer) this.subtitleData.renderer.dispose()
|
|
if (this.subtitleData.parser) this.subtitleData.parser.destroy()
|
|
if (this.subtitleData.fonts) this.subtitleData.fonts.forEach(file => URL.revokeObjectURL(file)) // ideally this should clean up after its been downloaded by the sw renderer, but oh well
|
|
if (this.controls.downloadFile) this.controls.downloadFile.href = ''
|
|
this.currentFile = undefined
|
|
this.video.poster = ''
|
|
// some attemt at cache clearing
|
|
this.video.pause()
|
|
this.video.src = ''
|
|
this.video.load()
|
|
this.onDone = undefined
|
|
document.title = this.nowPlaying?.name || 'WebTorrentPlayer'
|
|
this.setProgress(0)
|
|
// look for file and delete its store, idk how to do this
|
|
Object.assign(this.subtitleData, {
|
|
fonts: [],
|
|
headers: [],
|
|
tracks: [],
|
|
current: undefined,
|
|
renderer: undefined,
|
|
stream: undefined,
|
|
parser: undefined,
|
|
parsed: undefined,
|
|
timeout: undefined
|
|
})
|
|
|
|
if (this.controls.thumbnail) {
|
|
Object.assign(this.thumbnailData, {
|
|
thumbnails: [],
|
|
interval: undefined,
|
|
video: undefined
|
|
})
|
|
}
|
|
this.completed = false
|
|
this.changeControlsIcon('nowPlaying', '')
|
|
if (this.controls.captionsButton) this.controls.captionsButton.setAttribute('disabled', '')
|
|
this.changeControlsIcon('selectCaptions', '')
|
|
this.changeControlsIcon('selectAudio', '')
|
|
if (this.controls.openPlaylist) this.controls.openPlaylist.setAttribute('disabled', '')
|
|
if (navNowPlaying) navNowPlaying.classList.add('d-none')
|
|
if ('mediaSession' in navigator) navigator.mediaSession.metadata = undefined
|
|
this.fps = 23.976
|
|
}
|
|
|
|
changeControlsIcon (type, text) {
|
|
if (this.controls[type]) {
|
|
if (this.controls[type].constructor === Array) {
|
|
for (const element of this.controls[type]) {
|
|
element.textContent = text
|
|
}
|
|
} else {
|
|
this.controls[type].textContent = text
|
|
}
|
|
}
|
|
}
|
|
|
|
async playVideo () {
|
|
try {
|
|
await this.video.play()
|
|
this.changeControlsIcon('playPause', 'pause')
|
|
} catch (err) {
|
|
this.changeControlsIcon('playPause', 'play_arrow')
|
|
}
|
|
}
|
|
|
|
playPause () {
|
|
if (this.video.paused) {
|
|
this.playVideo()
|
|
} else {
|
|
this.changeControlsIcon('playPause', 'play_arrow')
|
|
this.video.pause()
|
|
}
|
|
}
|
|
|
|
setVolume (volume) {
|
|
const level = volume === undefined ? Number(this.controls.setVolume.value) : volume
|
|
this.controls.setVolume.value = level
|
|
this.controls.setVolume.style.setProperty('--volume-level', level + '%')
|
|
this.changeControlsIcon('toggleMute', level === 0 ? 'volume_off' : 'volume_up')
|
|
this.video.volume = level / 100
|
|
}
|
|
|
|
toggleMute () {
|
|
if (this.video.volume === 0) {
|
|
this.setVolume(this.oldVolume)
|
|
} else {
|
|
this.oldVolume = this.video.volume * 100
|
|
this.setVolume(0)
|
|
}
|
|
}
|
|
|
|
toggleTheatre () {
|
|
this.playerWrapper.classList.toggle('nav-hidden')
|
|
}
|
|
|
|
toggleFullscreen () {
|
|
document.fullscreenElement ? document.exitFullscreen() : this.player.requestFullscreen()
|
|
}
|
|
|
|
updateFullscreen () {
|
|
this.changeControlsIcon('toggleFullscreen', document.fullscreenElement ? 'fullscreen_exit' : 'fullscreen')
|
|
}
|
|
|
|
openPlaylist () {
|
|
this.emit('playlist', { files: this.videoFiles })
|
|
}
|
|
|
|
playNext () {
|
|
clearTimeout(this.nextTimeout)
|
|
this.nextTimeout = setTimeout(() => {
|
|
if (this.videoFiles?.indexOf(this.currentFile) < this.videoFiles?.length - 1) {
|
|
const nowPlaying = this.nowPlaying
|
|
nowPlaying.episodeNumber += 1
|
|
const torrent = this.currentFile._torrent
|
|
this.buildVideo(torrent, { media: nowPlaying, file: this.videoFiles[this.videoFiles.indexOf(this.currentFile) + 1] })
|
|
} else {
|
|
this.emit('next', { file: this.currentFile, filemedia: this.nowPlaying })
|
|
}
|
|
}, 200)
|
|
}
|
|
|
|
playLast () {
|
|
clearTimeout(this.nextTimeout)
|
|
this.nextTimeout = setTimeout(() => {
|
|
if (this.videoFiles?.indexOf(this.currentFile)) {
|
|
const nowPlaying = this.nowPlaying
|
|
nowPlaying.episodeNumber -= 1
|
|
const torrent = this.currentFile._torrent
|
|
this.buildVideo(torrent, { media: nowPlaying, file: this.videoFiles[this.videoFiles.indexOf(this.currentFile) - 1] })
|
|
} else {
|
|
this.emit('prev', { file: this.currentFile, filemedia: this.nowPlaying })
|
|
}
|
|
}, 200)
|
|
}
|
|
|
|
togglePopout () {
|
|
if (this.video.readyState) {
|
|
if (!(this.burnIn && this.subtitleData.renderer)) {
|
|
this.video !== document.pictureInPictureElement ? this.video.requestPictureInPicture() : document.exitPictureInPicture()
|
|
} else {
|
|
if (document.pictureInPictureElement && !document.pictureInPictureElement.id) { // only exit if pip is the custom one, else overwrite existing pip with custom
|
|
document.exitPictureInPicture()
|
|
} else {
|
|
const canvas = document.createElement('canvas')
|
|
const canvasVideo = document.createElement('video')
|
|
const context = canvas.getContext('2d', { alpha: false })
|
|
const subtitleCanvas = this.subtitleData.renderer.canvas
|
|
let running = true
|
|
canvas.width = this.video.videoWidth
|
|
canvas.height = this.video.videoHeight
|
|
|
|
const renderFrame = () => {
|
|
if (running === true) {
|
|
context.drawImage(this.video, 0, 0)
|
|
context.drawImage(subtitleCanvas, 0, 0, canvas.width, canvas.height)
|
|
requestAnimationFrame(renderFrame)
|
|
}
|
|
}
|
|
canvasVideo.srcObject = canvas.captureStream()
|
|
canvasVideo.onloadedmetadata = () => {
|
|
canvasVideo.play()
|
|
canvasVideo.requestPictureInPicture().then(
|
|
this.player.classList.add('pip')
|
|
).catch(e => {
|
|
console.warn('Failed To Burn In Subtitles ' + e)
|
|
running = false
|
|
canvasVideo.remove()
|
|
canvas.remove()
|
|
this.player.classList.remove('pip')
|
|
})
|
|
}
|
|
canvasVideo.onleavepictureinpicture = () => {
|
|
running = false
|
|
canvasVideo.remove()
|
|
canvas.remove()
|
|
this.player.classList.remove('pip')
|
|
}
|
|
requestAnimationFrame(renderFrame)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
toTS (sec, full) {
|
|
if (isNaN(sec) || sec < 0) {
|
|
return full ? '0:00:00.00' : '00:00'
|
|
}
|
|
const hours = Math.floor(sec / 3600)
|
|
let minutes = Math.floor(sec / 60) - (hours * 60)
|
|
let seconds = full ? (sec % 60).toFixed(2) : Math.floor(sec % 60)
|
|
if (minutes < 10) minutes = '0' + minutes
|
|
if (seconds < 10) seconds = '0' + seconds
|
|
return (hours > 0 || full) ? hours + ':' + minutes + ':' + seconds : minutes + ':' + seconds
|
|
}
|
|
|
|
prettyBytes (num) {
|
|
if (isNaN(num)) return '0 B'
|
|
if (num < 1) return num + ' B'
|
|
const exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), units.length - 1)
|
|
return Number((num / Math.pow(1000, exponent)).toFixed(2)) + units[exponent]
|
|
}
|
|
|
|
getBytes (str) {
|
|
const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'Bytes', 'KB', 'MB', 'GB', 'TB']
|
|
const split = str.split(' ')
|
|
return split[0] * 1024 ** (units.indexOf(split[1] || 'B') % 5) // this is so lazy
|
|
}
|
|
|
|
seek (time) {
|
|
if (time === 85 && this.video.currentTime < 10) {
|
|
this.video.currentTime = 90
|
|
} else if (time === 85 && (this.video.duration - this.video.currentTime) < 90) {
|
|
this.video.currentTime = this.video.duration
|
|
} else {
|
|
this.video.currentTime += time
|
|
}
|
|
this.setProgress(this.video.currentTime / this.video.duration * 100)
|
|
}
|
|
|
|
forward () {
|
|
this.seek(this.seekTime)
|
|
}
|
|
|
|
rewind () {
|
|
this.seek(-this.seekTime)
|
|
}
|
|
|
|
immersePlayer () {
|
|
this.player.classList.add('immersed')
|
|
this.immerseTimeout = undefined
|
|
}
|
|
|
|
resetImmerse () {
|
|
if (this.immerseTimeout) {
|
|
clearTimeout(this.immerseTimeout)
|
|
} else {
|
|
this.player.classList.remove('immersed')
|
|
}
|
|
this.immerseTimeout = setTimeout(() => this.immersePlayer(), this.immerseTime * 1000)
|
|
}
|
|
|
|
hideBuffering () {
|
|
if (this.bufferTimeout) {
|
|
clearTimeout(this.bufferTimeout)
|
|
this.bufferTimeout = undefined
|
|
this.player.classList.remove('buffering')
|
|
}
|
|
}
|
|
|
|
showBuffering () {
|
|
this.bufferTimeout = setTimeout(() => {
|
|
this.player.classList.add('buffering')
|
|
this.resetImmerse()
|
|
}, 150)
|
|
}
|
|
|
|
checkCompletion () {
|
|
if (!this.completed && this.video.duration - 180 < this.video.currentTime) {
|
|
this.completed = true
|
|
this.emit('watched', { file: this.currentFile, filemedia: this.nowPlaying })
|
|
}
|
|
}
|
|
|
|
updatePositionState () {
|
|
if (this.video.duration) {
|
|
navigator.mediaSession.setPositionState({
|
|
duration: this.video.duration || 0,
|
|
playbackRate: this.video.playbackRate || 0,
|
|
position: this.video.currentTime || 0
|
|
})
|
|
}
|
|
}
|
|
|
|
initThumbnail () {
|
|
const height = this.thumbnailData.canvas.width / (this.video.videoWidth / this.video.videoHeight)
|
|
this.thumbnailData.interval = this.video.duration / 300 < 5 ? 5 : this.video.duration / 300
|
|
this.thumbnailData.canvas.height = height
|
|
this.controls.thumbnail.style.setProperty('height', height + 'px')
|
|
}
|
|
|
|
createThumbnail (video) {
|
|
if (video?.readyState >= 2) {
|
|
const index = Math.floor(video.currentTime / this.thumbnailData.interval)
|
|
if (!this.thumbnailData.thumbnails[index]) {
|
|
this.thumbnailData.context.fillRect(0, 0, 150, this.thumbnailData.canvas.height)
|
|
this.thumbnailData.context.drawImage(video, 0, 0, 150, this.thumbnailData.canvas.height)
|
|
this.thumbnailData.thumbnails[index] = this.thumbnailData.canvas.toDataURL('image/jpeg')
|
|
}
|
|
}
|
|
}
|
|
|
|
finishThumbnails (src) {
|
|
const t0 = performance.now()
|
|
const video = document.createElement('video')
|
|
let index = 0
|
|
video.preload = 'none'
|
|
video.volume = 0
|
|
video.playbackRate = 0
|
|
video.addEventListener('loadeddata', () => loadTime())
|
|
video.addEventListener('canplay', () => {
|
|
this.createThumbnail(this.thumbnailData.video)
|
|
loadTime()
|
|
})
|
|
this.thumbnailData.video = video
|
|
const loadTime = () => {
|
|
while (this.thumbnailData.thumbnails[index] && index <= Math.floor(this.thumbnailData.video.duration / this.thumbnailData.interval)) { // only create thumbnails that are missing
|
|
index++
|
|
}
|
|
if (this.thumbnailData.video?.currentTime !== this.thumbnailData.video?.duration) {
|
|
this.thumbnailData.video.currentTime = index * this.thumbnailData.interval
|
|
} else {
|
|
this.thumbnailData.video?.removeAttribute('src')
|
|
this.thumbnailData.video?.load()
|
|
this.thumbnailData.video?.remove()
|
|
delete this.thumbnailData.video
|
|
console.log('Thumbnail creating finished', index, this.toTS((performance.now() - t0) / 1000))
|
|
}
|
|
index++
|
|
}
|
|
this.thumbnailData.video.src = src
|
|
this.thumbnailData.video.play()
|
|
console.log('Thumbnail creating started')
|
|
}
|
|
|
|
dragBarEnd (progressPercent) {
|
|
this.video.currentTime = this.video.duration * progressPercent / 100 || 0
|
|
this.playVideo()
|
|
}
|
|
|
|
dragBarStart (progressPercent) {
|
|
this.video.pause()
|
|
this.setProgress(progressPercent)
|
|
}
|
|
|
|
setProgress (progressPercent) {
|
|
progressPercent = progressPercent || 0
|
|
const currentTime = this.video.duration * progressPercent / 100 || 0
|
|
if (this.controls.progressWrapper) this.controls.progressWrapper.style.setProperty('--progress', progressPercent + '%')
|
|
if (this.controls.thumbnail) this.controls.thumbnail.src = this.thumbnailData.thumbnails[Math.floor(currentTime / this.thumbnailData.interval)] || ' '
|
|
if (this.controls.setProgress) {
|
|
this.controls.setProgress.dataset.elapsed = this.toTS(currentTime)
|
|
this.controls.setProgress.value = progressPercent
|
|
}
|
|
if (this.controls.progressWrapper) {
|
|
this.controls.progressWrapper.dataset.elapsed = this.toTS(currentTime)
|
|
this.controls.progressWrapper.dataset.remaining = this.toTS(this.video.duration - currentTime)
|
|
}
|
|
}
|
|
|
|
updateDisplay () {
|
|
if (this.currentFile && this.currentFile._torrent) {
|
|
if (this.player) this.player.style.setProperty('--download', this.currentFile.progress * 100 + '%')
|
|
if (this.controls.peers) this.controls.peers.dataset.value = this.currentFile._torrent.numPeers
|
|
if (this.controls.downSpeed) this.controls.downSpeed.dataset.value = this.prettyBytes(this.currentFile._torrent.downloadSpeed) + '/s'
|
|
if (this.controls.upSpeed) this.controls.upSpeed.dataset.value = this.prettyBytes(this.currentFile._torrent.uploadSpeed) + '/s'
|
|
}
|
|
setTimeout(() => requestAnimationFrame(() => this.updateDisplay()), 200)
|
|
}
|
|
|
|
createRadioElement (track, type) {
|
|
// type: captions audio
|
|
if ((type === 'captions' && this.controls.selectCaptions && this.controls.captionsButton) || (type === 'audio' && this.controls.selectAudio)) {
|
|
const frag = document.createDocumentFragment()
|
|
const input = document.createElement('input')
|
|
const label = document.createElement('label')
|
|
input.name = `${type}-radio-set`
|
|
input.type = 'radio'
|
|
input.id = type === 'captions' ? `${type}-${track ? track.number : 'off'}-radio` : `${type}-${track.id}-radio`
|
|
input.value = type === 'captions' ? track ? track.number : -1 : track.id
|
|
input.checked = type === 'captions' ? track?.number === this.subtitleData.current : track.enabled
|
|
label.htmlFor = type === 'captions' ? `${type}-${track ? track.number : 'off'}-radio` : `${type}-${track.id}-radio`
|
|
label.textContent = track
|
|
? type === 'captions'
|
|
? (track.language || (!Object.values(this.subtitleData.headers).some(header => header.language === 'eng' || header.language === 'en') ? 'eng' : track.type)) + (track.name ? ' - ' + track.name : '')
|
|
: (track.language || (!Object.values(this.video.audioTracks).some(track => track.language === 'eng' || track.language === 'en') ? 'eng' : track.label)) + (track.label ? ' - ' + track.label : '')
|
|
: 'OFF' // TODO: clean this up, TLDR assume english track if track lang is undefined || 'und' and there isnt an existing eng track already
|
|
frag.appendChild(input)
|
|
frag.appendChild(label)
|
|
if (type === 'captions') {
|
|
this.controls.selectCaptions.appendChild(frag)
|
|
this.controls.captionsButton.removeAttribute('disabled')
|
|
} else {
|
|
this.controls.selectAudio.appendChild(frag)
|
|
}
|
|
}
|
|
}
|
|
|
|
selectAudio (id) {
|
|
if (id !== undefined) {
|
|
for (const track of this.video.audioTracks) {
|
|
track.enabled = track.id === id
|
|
}
|
|
this.seek(-0.5) // stupid fix because video freezes up when chaging tracks
|
|
}
|
|
}
|
|
|
|
selectCaptions (trackNumber) {
|
|
if (trackNumber !== undefined) {
|
|
trackNumber = Number(trackNumber)
|
|
this.subtitleData.current = trackNumber
|
|
if (!this.subtitleData.timeout) {
|
|
this.subtitleData.timeout = setTimeout(() => {
|
|
this.subtitleData.timeout = undefined
|
|
if (this.subtitleData.renderer) {
|
|
this.subtitleData.renderer.setTrack(trackNumber !== -1 ? this.subtitleData.headers[trackNumber].header.slice(0, -1) + Array.from(this.subtitleData.tracks[trackNumber]).join('\n') : this.subtitleData.defaultHeader)
|
|
}
|
|
}, 1000)
|
|
}
|
|
}
|
|
}
|
|
|
|
constructSub (subtitle, isNotAss) {
|
|
if (isNotAss === true) { // converts VTT or other to SSA
|
|
const matches = subtitle.text.match(/<[^>]+>/g) // create array of all tags
|
|
if (matches) {
|
|
matches.forEach(match => {
|
|
if (/<\//.test(match)) { // check if its a closing tag
|
|
subtitle.text = subtitle.text.replace(match, match.replace('</', '{\\').replace('>', '0}'))
|
|
} else {
|
|
subtitle.text = subtitle.text.replace(match, match.replace('<', '{\\').replace('>', '1}'))
|
|
}
|
|
})
|
|
}
|
|
// replace all html special tags with normal ones
|
|
subtitle.text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/ /g, '\\h')
|
|
}
|
|
return 'Dialogue: ' +
|
|
(subtitle.layer || 0) + ',' +
|
|
this.toTS(subtitle.time / 1000, true) + ',' +
|
|
this.toTS((subtitle.time + subtitle.duration) / 1000, true) + ',' +
|
|
(subtitle.style || 'Default') + ',' +
|
|
(subtitle.name || '') + ',' +
|
|
(subtitle.marginL || '0') + ',' +
|
|
(subtitle.marginR || '0') + ',' +
|
|
(subtitle.marginV || '0') + ',' +
|
|
(subtitle.effect || '') + ',' +
|
|
subtitle.text || 0
|
|
}
|
|
|
|
parseSubtitles (file) { // parse subtitles fully after a download is finished
|
|
return new Promise((resolve) => {
|
|
if (file.name.endsWith('.mkv')) {
|
|
let parser = new matroska_subtitles__WEBPACK_IMPORTED_MODULE_2__.SubtitleParser()
|
|
this.handleSubtitleParser(parser, true)
|
|
parser.on('finish', () => {
|
|
console.log('Sub parsing finished', this.toTS((performance.now() - t0) / 1000))
|
|
this.subtitleData.parsed = true
|
|
this.subtitleData.stream = undefined
|
|
this.subtitleData.parser.destroy()
|
|
this.selectCaptions(this.subtitleData.current)
|
|
parser = undefined
|
|
if (!this.video.paused) {
|
|
this.video.pause()
|
|
this.playVideo()
|
|
}
|
|
resolve()
|
|
})
|
|
const t0 = performance.now()
|
|
console.log('Sub parsing started')
|
|
this.subtitleData.parser = file.createReadStream().pipe(parser)
|
|
} else {
|
|
resolve()
|
|
}
|
|
})
|
|
}
|
|
|
|
handleSubtitleParser (parser, skipFile) {
|
|
parser.once('tracks', tracks => {
|
|
tracks.forEach(track => {
|
|
if (!this.subtitleData.tracks[track.number]) {
|
|
// overwrite webvtt or other header with custom one
|
|
if (track.type !== 'ass') track.header = this.subtitleData.defaultHeader
|
|
if (!this.subtitleData.current) {
|
|
this.subtitleData.current = track.number
|
|
this.createRadioElement(undefined, 'captions')
|
|
}
|
|
this.subtitleData.tracks[track.number] = new Set()
|
|
this.subtitleData.headers[track.number] = track
|
|
this.createRadioElement(track, 'captions')
|
|
}
|
|
})
|
|
})
|
|
parser.on('subtitle', (subtitle, trackNumber) => {
|
|
if (!this.subtitleData.parsed) {
|
|
if (!this.subtitleData.renderer) this.initSubtitleRenderer()
|
|
this.subtitleData.tracks[trackNumber].add(this.constructSub(subtitle, this.subtitleData.headers[trackNumber].type !== 'ass'))
|
|
if (this.subtitleData.current === trackNumber) this.selectCaptions(trackNumber)
|
|
}
|
|
})
|
|
if (!skipFile) {
|
|
parser.on('file', file => {
|
|
if (file.mimetype === 'application/x-truetype-font' || file.mimetype === 'application/font-woff') {
|
|
this.subtitleData.fonts.push(URL.createObjectURL(new Blob([file.data], { type: file.mimetype })))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
async initSubtitleRenderer () {
|
|
if (!this.subtitleData.renderer) {
|
|
const options = {
|
|
video: this.video,
|
|
targetFps: await this.fps,
|
|
subContent: this.subtitleData.headers[this.subtitleData.current].header.slice(0, -1),
|
|
renderMode: 'offscreen',
|
|
fonts: this.subtitleData.fonts,
|
|
fallbackFont: 'https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc4.woff2',
|
|
workerUrl: 'lib/subtitles-octopus-worker.js',
|
|
timeOffset: 0.041,
|
|
onReady: () => { // weird hack for laggy subtitles, this is some issue in SO
|
|
if (!this.video.paused) {
|
|
this.video.pause()
|
|
this.playVideo()
|
|
}
|
|
}
|
|
}
|
|
if (!this.subtitleData.renderer) {
|
|
this.subtitleData.renderer = new (_lib_subtitles_octopus_js__WEBPACK_IMPORTED_MODULE_5___default())(options)
|
|
this.selectCaptions(this.subtitleData.current)
|
|
}
|
|
}
|
|
}
|
|
|
|
convertSubFile (file, isAss, callback) {
|
|
const regex = /(?:\d+\n)?(\S{9,12})\s?-->\s?(\S{9,12})(.*)\n([\s\S]*)$/i
|
|
file.getBuffer((_err, buffer) => {
|
|
const subtitles = isAss ? buffer.toString() : []
|
|
if (isAss) {
|
|
callback(subtitles)
|
|
} else {
|
|
for (const split of buffer.toString().split('\n\n')) {
|
|
const match = split.match(regex)
|
|
if (match) {
|
|
match[1] = match[1].match(/.*[.,]\d{2}/)[0]
|
|
match[2] = match[2].match(/.*[.,]\d{2}/)[0]
|
|
if (match[1].length === 9) {
|
|
match[1] = '0:' + match[1]
|
|
} else {
|
|
if (match[1][0] === '0') {
|
|
match[1] = match[1].substring(1)
|
|
}
|
|
}
|
|
match[1].replace(',', '.')
|
|
if (match[2].length === 9) {
|
|
match[2] = '0:' + match[2]
|
|
} else {
|
|
if (match[2][0] === '0') {
|
|
match[2] = match[2].substring(1)
|
|
}
|
|
}
|
|
match[2].replace(',', '.')
|
|
const matches = match[4].match(/<[^>]+>/g) // create array of all tags
|
|
if (matches) {
|
|
matches.forEach(matched => {
|
|
if (/<\//.test(matched)) { // check if its a closing tag
|
|
match[4] = match[4].replace(matched, matched.replace('</', '{\\').replace('>', '0}'))
|
|
} else {
|
|
match[4] = match[4].replace(matched, matched.replace('<', '{\\').replace('>', '1}'))
|
|
}
|
|
})
|
|
}
|
|
subtitles.push('Dialogue: 0,' + match[1].replace(',', '.') + ',' + match[2].replace(',', '.') + ',Default,,0,0,0,,' + match[4])
|
|
}
|
|
}
|
|
callback(subtitles)
|
|
}
|
|
})
|
|
}
|
|
|
|
findSubtitleFiles (targetFile) {
|
|
const path = targetFile.path.split(targetFile.name)[0]
|
|
// array of subtitle files that match video name, or all subtitle files when only 1 vid file
|
|
const subtitleFiles = targetFile._torrent.files.filter(file => {
|
|
return this.subtitleExtensions.some(ext => file.name.endsWith(ext)) && (this.videoFiles.length === 1 ? true : file.path.split(path).length === 2)
|
|
})
|
|
if (subtitleFiles.length) {
|
|
this.createRadioElement(undefined, 'captions')
|
|
this.subtitleData.parsed = true
|
|
this.subtitleData.current = 0
|
|
for (const [index, file] of subtitleFiles.entries()) {
|
|
const isAss = file.name.endsWith('.ass') || file.name.endsWith('.ssa')
|
|
const extension = /\.(\w+)$/
|
|
const name = file.name.replace(targetFile.name, '') === file.name
|
|
? file.name.replace(targetFile.name.replace(extension, ''), '').slice(0, -4).replace(/[,._-]/g, ' ').trim()
|
|
: file.name.replace(targetFile.name, '').slice(0, -4).replace(/[,._-]/g, ' ').trim()
|
|
const header = {
|
|
header: this.subtitleData.defaultHeader,
|
|
language: name,
|
|
number: index,
|
|
type: file.name.match(extension)[1]
|
|
}
|
|
this.subtitleData.headers.push(header)
|
|
this.subtitleData.tracks[index] = []
|
|
this.createRadioElement(header, 'captions')
|
|
this.convertSubFile(file, isAss, subtitles => {
|
|
if (isAss) {
|
|
this.subtitleData.headers[index].header = subtitles
|
|
} else {
|
|
this.subtitleData.tracks[index] = subtitles
|
|
}
|
|
if (this.subtitleData.current === index) this.selectCaptions(this.subtitleData.current)
|
|
})
|
|
this.initSubtitleRenderer()
|
|
}
|
|
}
|
|
}
|
|
|
|
postDownload () {
|
|
this.emit('download-done', { file: this.currentFile })
|
|
this.parseSubtitles(this.currentFile).then(() => {
|
|
if (this.generateThumbnails) {
|
|
this.finishThumbnails(this.video.src)
|
|
}
|
|
})
|
|
}
|
|
|
|
playTorrent (torrentID, opts = {}) { // TODO: clean this up
|
|
const handleTorrent = (torrent, opts) => {
|
|
torrent.on('noPeers', () => {
|
|
this.emit('no-peers', torrent)
|
|
})
|
|
if (this.streamedDownload) {
|
|
torrent.files.forEach(file => file.deselect())
|
|
torrent.deselect(0, torrent.pieces.length - 1, false)
|
|
}
|
|
this.videoFiles = torrent.files.filter(file => this.videoExtensions.some(ext => file.name.endsWith(ext)))
|
|
this.emit('video-files', { files: this.videoFiles, torrent: torrent })
|
|
if (this.videoFiles.length > 1) {
|
|
torrent.files.forEach(file => file.deselect())
|
|
}
|
|
if (this.videoFiles) {
|
|
this.buildVideo(torrent, opts)
|
|
} else {
|
|
this.emit('no-file', torrent)
|
|
this.cleanupTorrents()
|
|
}
|
|
}
|
|
document.location.hash = '#player'
|
|
this.cleanupVideo()
|
|
this.cleanupTorrents()
|
|
if (torrentID instanceof Object) {
|
|
handleTorrent(torrentID, opts)
|
|
} else if (this.get(torrentID)) {
|
|
handleTorrent(this.get(torrentID), opts)
|
|
} else {
|
|
this.add(torrentID, {
|
|
storeOpts: this.storeOpts,
|
|
store: (hybrid_chunk_store__WEBPACK_IMPORTED_MODULE_3___default()),
|
|
announce: this.tracker.announce || [
|
|
'wss://tracker.openwebtorrent.com',
|
|
'wss://tracker.sloppyta.co:443/announce',
|
|
'wss://hub.bugout.link:443/announce'
|
|
]
|
|
}, torrent => {
|
|
handleTorrent(torrent, opts)
|
|
})
|
|
}
|
|
}
|
|
|
|
// cleanup torrent and store
|
|
cleanupTorrents () {
|
|
// creates an array of all non-offline store torrents and removes them
|
|
this.torrents.filter(torrent => !this.offlineTorrents[torrent.infoHash]).forEach(torrent => torrent.destroy({ destroyStore: this.destroyStore }))
|
|
}
|
|
|
|
// add torrent for offline download
|
|
offlineDownload (torrentID) {
|
|
const torrent = this.add(torrentID, {
|
|
storeOpts: this.storeOpts,
|
|
store: (hybrid_chunk_store__WEBPACK_IMPORTED_MODULE_3___default()),
|
|
announce: this.tracker.announce || [
|
|
'wss://tracker.openwebtorrent.com',
|
|
'wss://tracker.sloppyta.co:443/announce',
|
|
'wss://hub.bugout.link:443/announce'
|
|
]
|
|
})
|
|
torrent.on('metadata', () => {
|
|
if (!this.offlineTorrents[torrent.infoHash]) {
|
|
this.offlineTorrents[torrent.infoHash] = Array.from(torrent.torrentFile)
|
|
localStorage.setItem('offlineTorrents', JSON.stringify(this.offlineTorrents))
|
|
}
|
|
this.emit('offline-torrent', torrent)
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webtorrent-player/lib/subtitles-octopus.js":
|
|
/*!*****************************************************************!*\
|
|
!*** ./node_modules/webtorrent-player/lib/subtitles-octopus.js ***!
|
|
\*****************************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
class SubtitlesOctopus {
|
|
constructor (options = {}) {
|
|
if (!window.Worker) {
|
|
this.workerError('worker not supported')
|
|
return
|
|
}
|
|
// opts
|
|
this.canvas = options.canvas // HTML canvas element (optional if video specified)
|
|
|
|
// choose best render mode based on browser support
|
|
this.renderMode = options.renderMode || 'fast'
|
|
if (typeof createImageBitmap === 'undefined') {
|
|
if (this.renderMode !== 'blend') this.renderMode = 'normal'
|
|
} else {
|
|
if (typeof OffscreenCanvas !== 'undefined') {
|
|
if (this.renderMode === 'fast') this.renderMode = 'offscreen'
|
|
} else if (this.renderMode !== 'blend') {
|
|
this.renderMode = 'fast'
|
|
}
|
|
}
|
|
|
|
// play with those when you need some speed, e.g. for slow devices
|
|
this.targetFps = options.targetFps || 23.976
|
|
this.prescaleTradeoff = options.prescaleTradeoff || null // render subtitles less than viewport when less than 1.0 to improve speed, render to more than 1.0 to improve quality; set to null to disable scaling
|
|
this.softHeightLimit = options.softHeightLimit || 1080 // don't apply prescaleTradeoff < 1 when viewport height is less that this limit
|
|
this.hardHeightLimit = options.hardHeightLimit || 2160 // don't ever go above this limit
|
|
this.resizeVariation = options.resizeVariation || 0.2 // by how many a size can vary before it would cause clearance of prerendered buffer
|
|
|
|
this.video = options.video // HTML video element (optional if canvas specified)
|
|
this.canvasParent = null // (internal) HTML canvas parent element
|
|
this.onReadyEvent = options.onReady // Function called when SubtitlesOctopus is ready (optional)
|
|
this.onErrorEvent = options.onError // Function called in case of critical error meaning sub wouldn't be shown and you should use alternative method (for instance it occurs if browser doesn't support web workers).
|
|
this.debug = !!options.debug // When debug enabled, some performance info printed in console.
|
|
this.lastRenderTime = 0 // (internal) Last time we got some frame from worker
|
|
|
|
this.timeOffset = options.timeOffset || 0 // Time offset would be applied to currentTime from video (option)
|
|
|
|
this.renderedItems = [] // used to store items rendered ahead when renderAhead > 0
|
|
// how many MiB to render ahead and store; 0 to disable (approximate)
|
|
this.renderAhead = (options.renderAhead || 0) * 1024 * 1024 * 0.9 // try to eat less than requested
|
|
this.oneshotState = {
|
|
eventStart: null,
|
|
eventOver: false,
|
|
iteration: 0,
|
|
renderRequested: false,
|
|
requestNextTimestamp: -1,
|
|
prevWidth: null,
|
|
prevHeight: null
|
|
}
|
|
|
|
this.renderFrameData = null
|
|
this.workerActive = false
|
|
this.frameId = 0
|
|
this.workerActive = false
|
|
|
|
// init worker
|
|
if (!this.worker) {
|
|
this.worker = new Worker(options.workerUrl || 'subtitles-octopus-worker.js')
|
|
this.worker.onmessage = event => this.onWorkerMessage(event)
|
|
this.worker.onerror = event => this.workerError(event)
|
|
}
|
|
|
|
this.createCanvas()
|
|
this.setVideo(options.video)
|
|
this.worker.postMessage({
|
|
target: 'worker-init',
|
|
width: this.canvas.width,
|
|
height: this.canvas.height,
|
|
URL: document.URL,
|
|
currentScript: options.workerUrl || 'subtitles-octopus-worker.js', // Link to WebAssembly worker
|
|
preMain: true,
|
|
renderMode: this.renderMode,
|
|
subUrl: options.subUrl, // Link to sub file (optional if subContent specified)
|
|
subContent: options.subContent || null, // Sub content (optional if subUrl specified)
|
|
fallbackFont: options.fallbackFont || null, // Override fallback font, for example, with a CJK one. Default fallback font is Liberation Sans
|
|
lazyFontLoading: options.lazyFontLoading || false, // Load fonts in a lazy way. Requires Access-Control-Expose-Headers for Accept-Ranges, Content-Length, and Content-Encoding. If Content-Encoding is compressed, file will be fully fetched instead of just a HEAD request.
|
|
fonts: options.fonts || [], // Array with links to fonts used in sub (optional)
|
|
availableFonts: options.availableFonts || [], // Object with all available fonts (optional). Key is font name in lower case, value is link: {"arial": "/font1.ttf"}
|
|
debug: this.debug,
|
|
targetFps: this.targetFps,
|
|
libassMemoryLimit: options.libassMemoryLimit || 0, // set libass bitmap cache memory limit in MiB (approximate)
|
|
libassGlyphLimit: options.libassGlyphLimit || 0, // set libass glyph cache memory limit in MiB (approximate)
|
|
renderOnDemand: this.renderAhead > 0,
|
|
dropAllAnimations: !!options.dropAllAnimations
|
|
})
|
|
if (this.renderMode === 'offscreen') this.pushOffscreenCanvas()
|
|
this.initDone = true
|
|
|
|
// test ImageData constructor
|
|
;(() => {
|
|
if (typeof ImageData.prototype.constructor === 'function') {
|
|
try {
|
|
// try actually calling ImageData, as on some browsers it's reported
|
|
// as existing but calling it errors out as "TypeError: Illegal constructor"
|
|
return new ImageData(new Uint8ClampedArray([0, 0, 0, 0]), 1, 1)
|
|
} catch (e) {
|
|
console.log('detected that ImageData is not constructable despite browser saying so')
|
|
}
|
|
}
|
|
|
|
const canvas = document.createElement('canvas')
|
|
const ctx = canvas.getContext('2d')
|
|
|
|
window.ImageData = () => {
|
|
let i = 0
|
|
let data
|
|
if (arguments[0] instanceof Uint8ClampedArray) data = arguments[i++]
|
|
const width = arguments[i++]
|
|
const height = arguments[i]
|
|
|
|
const imageData = ctx.createImageData(width, height)
|
|
if (data) imageData.data.set(data)
|
|
return imageData
|
|
}
|
|
})()
|
|
|
|
// test alpha bug
|
|
if (this.renderMode !== 'offscreen') {
|
|
this.ctx = this.canvas.getContext('2d')
|
|
this.bufferCanvas = document.createElement('canvas')
|
|
this.bufferCanvasCtx = this.bufferCanvas.getContext('2d')
|
|
|
|
// test for alpha bug, where e.g. WebKit can render a transparent pixel
|
|
// (with alpha == 0) as non-black which then leads to visual artifacts
|
|
this.bufferCanvas.width = 1
|
|
this.bufferCanvas.height = 1
|
|
const testBuf = new Uint8ClampedArray([0, 255, 0, 0])
|
|
const testImage = new ImageData(testBuf, 1, 1)
|
|
this.bufferCanvasCtx.clearRect(0, 0, 1, 1)
|
|
this.ctx.clearRect(0, 0, 1, 1)
|
|
const prePut = this.ctx.getImageData(0, 0, 1, 1).data
|
|
this.bufferCanvasCtx.putImageData(testImage, 0, 0)
|
|
this.ctx.drawImage(this.bufferCanvas, 0, 0)
|
|
const postPut = this.ctx.getImageData(0, 0, 1, 1).data
|
|
this.hasAlphaBug = prePut[1] !== postPut[1]
|
|
if (this.hasAlphaBug) console.log('Detected a browser having issue with transparent pixels, applying workaround')
|
|
}
|
|
}
|
|
|
|
workerError (error) {
|
|
console.error('Worker error: ', error)
|
|
if (this.onErrorEvent) this.onErrorEvent(error)
|
|
if (!this.debug) {
|
|
this.dispose()
|
|
throw new Error('Worker error: ' + error)
|
|
}
|
|
}
|
|
|
|
pushOffscreenCanvas () {
|
|
const canvasControl = this.canvas.transferControlToOffscreen()
|
|
this.worker.postMessage({
|
|
target: 'offscreenCanvas',
|
|
canvas: canvasControl
|
|
}, [canvasControl])
|
|
}
|
|
|
|
createCanvas () {
|
|
if (this.video) {
|
|
this.canvas = document.createElement('canvas')
|
|
this.canvas.className = 'subtitles-octopus-canvas'
|
|
this.canvas.style.display = 'none'
|
|
|
|
this.canvasParent = document.createElement('div')
|
|
this.canvasParent.className = 'subtitles-octopus-canvas-parent'
|
|
this.canvasParent.appendChild(this.canvas)
|
|
|
|
if (this.video.nextSibling) {
|
|
this.video.parentNode.insertBefore(this.canvasParent, this.video.nextSibling)
|
|
} else {
|
|
this.video.parentNode.appendChild(this.canvasParent)
|
|
}
|
|
} else {
|
|
if (!this.canvas) {
|
|
this.workerError('Don\'t know where to render: you should give video or canvas in options.')
|
|
}
|
|
}
|
|
}
|
|
|
|
setVideo (video) {
|
|
this.video = video
|
|
if (this.video) {
|
|
const timeupdate = () => {
|
|
this.setCurrentTime(video.paused, video.currentTime + this.timeOffset)
|
|
}
|
|
this.video.addEventListener('timeupdate', timeupdate, false)
|
|
this.video.addEventListener('progress', timeupdate, false)
|
|
|
|
this.video.addEventListener('pause', timeupdate, false)
|
|
|
|
this.video.addEventListener('seeking', () => {
|
|
this.video.removeEventListener('timeupdate', timeupdate)
|
|
}, false)
|
|
|
|
this.video.addEventListener('seeked', () => {
|
|
this.video.addEventListener('timeupdate', timeupdate, false)
|
|
this.setCurrentTime(video.currentTime + this.timeOffset)
|
|
if (this.renderAhead > 0) {
|
|
this._cleanPastRendered(video.currentTime + this.timeOffset, true)
|
|
}
|
|
}, false)
|
|
|
|
this.video.addEventListener('ratechange', () => {
|
|
this.setRate(video.playbackRate)
|
|
}, false)
|
|
|
|
this.video.addEventListener('waiting', () => {
|
|
this.setCurrentTime(true, video.currentTime + this.timeOffset)
|
|
}, false)
|
|
|
|
// Support Element Resize Observer
|
|
if (typeof ResizeObserver !== 'undefined') {
|
|
this.ro = new ResizeObserver(() => this.resize())
|
|
this.ro.observe(this.video)
|
|
}
|
|
|
|
if (this.video.videoWidth > 0) {
|
|
this.resize()
|
|
} else {
|
|
this.video.addEventListener('loadedmetadata', e => {
|
|
this.resize()
|
|
}, false)
|
|
}
|
|
}
|
|
}
|
|
|
|
getVideoPosition () {
|
|
const videoRatio = this.video.videoWidth / this.video.videoHeight
|
|
const { offsetWidth, offsetHeight } = this.video
|
|
const elementRatio = offsetWidth / offsetHeight
|
|
let width = offsetWidth
|
|
let height = offsetHeight
|
|
if (elementRatio > videoRatio) {
|
|
width = Math.floor(offsetHeight * videoRatio)
|
|
} else {
|
|
height = Math.floor(offsetWidth / videoRatio)
|
|
}
|
|
|
|
const x = (offsetWidth - width) / 2
|
|
const y = (offsetHeight - height) / 2
|
|
|
|
return { width, height, x, y }
|
|
}
|
|
|
|
_cleanPastRendered (currentTime, seekClean) {
|
|
let retainedItems = []
|
|
for (const item of this.renderedItems) {
|
|
if (item.emptyFinish < 0 || item.emptyFinish >= currentTime) {
|
|
// item is not yet finished, retain it
|
|
retainedItems.push(item)
|
|
}
|
|
}
|
|
|
|
if (seekClean && retainedItems.length > 0) {
|
|
// items are ordered by event start time when we push to this.renderedItems,
|
|
// so first item is the earliest
|
|
if (currentTime < retainedItems[0].eventStart) {
|
|
if (retainedItems[0].eventStart - currentTime > 60) {
|
|
console.info('seeked back too far, cleaning prerender buffer')
|
|
retainedItems = []
|
|
} else {
|
|
console.info('seeked backwards, need to free up some buffer')
|
|
let size = 0; const limit = this.renderAhead * 0.3 /* try to take no more than 1/3 of buffer */
|
|
const retain = []
|
|
for (const item of retainedItems) {
|
|
size += item.size
|
|
if (size >= limit) break
|
|
retain.push(item)
|
|
}
|
|
retainedItems = retain
|
|
}
|
|
}
|
|
}
|
|
|
|
const removed = retainedItems.length < this.renderedItems
|
|
this.renderedItems = retainedItems
|
|
return removed
|
|
}
|
|
|
|
// Oneshot stuff
|
|
processOneshot (data) {
|
|
if (data.iteration !== this.oneshotState.iteration) {
|
|
console.debug('received stale prerender, ignoring')
|
|
return
|
|
}
|
|
|
|
if (this.debug) {
|
|
console.info('oneshot received (start=' +
|
|
data.eventStart + ', empty=' + data.emptyFinish +
|
|
'), render: ' + Math.round(data.spentTime) + ' ms')
|
|
}
|
|
this.oneshotState.renderRequested = false
|
|
if (Math.abs(data.lastRenderedTime - this.oneshotState.requestNextTimestamp) < 0.01) {
|
|
this.oneshotState.requestNextTimestamp = -1
|
|
}
|
|
if (data.eventStart - data.lastRenderedTime > 0.01) {
|
|
// generate bogus empty element, so all timeline is covered anyway
|
|
this.renderedItems.push({
|
|
eventStart: data.lastRenderedTime,
|
|
eventFinish: data.lastRenderedTime - 0.001,
|
|
emptyFinish: data.eventStart,
|
|
viewport: data.viewport,
|
|
spentTime: 0,
|
|
blendTime: 0,
|
|
items: [],
|
|
animated: false,
|
|
size: 0
|
|
})
|
|
}
|
|
|
|
const items = []
|
|
let size = 0
|
|
for (const item of data.canvases) {
|
|
items.push({
|
|
...item,
|
|
image: new ImageData(new Uint8ClampedArray(item.buffer), item.w, item.h)
|
|
})
|
|
size += item.buffer.byteLength
|
|
}
|
|
|
|
let eventSplitted = false
|
|
if ((data.emptyFinish > 0 && data.emptyFinish - data.eventStart < 1.0 / this.targetFps) || data.animated) {
|
|
const newFinish = data.eventStart + 1.0 / this.targetFps
|
|
data.emptyFinish = newFinish
|
|
data.eventFinish = newFinish
|
|
eventSplitted = true
|
|
}
|
|
this.renderedItems.push({
|
|
...data,
|
|
items: items,
|
|
size: size
|
|
})
|
|
|
|
this.renderedItems.sort((a, b) => a.eventStart - b.eventStart)
|
|
|
|
if (this.oneshotState.requestNextTimestamp >= 0) {
|
|
// requesting an out of order event render
|
|
this.tryRequestOneshot(this.oneshotState.requestNextTimestamp, true)
|
|
} else if (data.eventStart < 0) {
|
|
console.info('oneshot received "end of frames" event')
|
|
} else if (data.emptyFinish >= 0) {
|
|
// there's some more event to render, try requesting next event
|
|
this.tryRequestOneshot(data.emptyFinish, eventSplitted)
|
|
} else {
|
|
console.info('there are no more events to prerender')
|
|
}
|
|
}
|
|
|
|
tryRequestOneshot (currentTime, renderNow) {
|
|
if (!this.renderAhead || this.renderAhead <= 0) return
|
|
if (this.oneshotState.renderRequested && !renderNow) return
|
|
|
|
if (typeof currentTime === 'undefined') {
|
|
if (!this.video) return
|
|
currentTime = this.video.currentTime + this.timeOffset
|
|
}
|
|
|
|
let size = 0
|
|
for (const item of this.renderedItems) {
|
|
if (item.emptyFinish < 0) {
|
|
console.info('oneshot already reached end-of-events')
|
|
return
|
|
}
|
|
if (currentTime >= item.eventStart && currentTime < item.emptyFinish) {
|
|
// an event for requested time already exists
|
|
console.debug('not requesting a render for ' + currentTime +
|
|
' as event already covering it exists (start=' +
|
|
item.eventStart + ', empty=' + item.emptyFinish + ')')
|
|
return
|
|
}
|
|
size += item.size
|
|
}
|
|
|
|
if (size <= this.renderAhead) {
|
|
const lastRendered = currentTime - (renderNow ? 0 : 0.001)
|
|
if (!this.oneshotState.renderRequested) {
|
|
this.oneshotState.renderRequested = true
|
|
this.worker.postMessage({
|
|
target: 'oneshot-render',
|
|
lastRendered: lastRendered,
|
|
renderNow: renderNow,
|
|
iteration: this.oneshotState.iteration
|
|
})
|
|
} else {
|
|
if (this.workerActive) console.info('worker busy, requesting to seek')
|
|
this.oneshotState.requestNextTimestamp = lastRendered
|
|
}
|
|
}
|
|
}
|
|
|
|
_renderSubtitleEvent (event, currentTime) {
|
|
const eventOver = event.eventFinish < currentTime
|
|
if (this.oneshotState.eventStart === event.eventStart && this.oneshotState.eventOver === eventOver) return
|
|
this.oneshotState.eventStart = event.eventStart
|
|
this.oneshotState.eventOver = eventOver
|
|
|
|
const beforeDrawTime = performance.now()
|
|
if (event.viewport.width !== this.canvas.width || event.viewport.height !== this.canvas.height) {
|
|
this.canvas.width = event.viewport.width
|
|
this.canvas.height = event.viewport.height
|
|
}
|
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
|
|
if (!eventOver) {
|
|
for (const image of event.items) {
|
|
this.bufferCanvas.width = image.w
|
|
this.bufferCanvas.height = image.h
|
|
this.bufferCanvasCtx.putImageData(image.image, 0, 0)
|
|
this.ctx.drawImage(this.bufferCanvas, image.x, image.y)
|
|
}
|
|
}
|
|
if (this.debug) {
|
|
const drawTime = Math.round(performance.now() - beforeDrawTime)
|
|
console.log('render: ' + Math.round(event.spentTime - event.blendTime) + ' ms, blend: ' + Math.round(event.blendTime) + ' ms, draw: ' + drawTime + ' ms')
|
|
}
|
|
}
|
|
|
|
oneshotRender () {
|
|
window.requestAnimationFrame(this.oneshotRender)
|
|
if (!this.video) return
|
|
|
|
const currentTime = this.video.currentTime + this.timeOffset
|
|
let finishTime = -1; let eventShown = false; let animated = false
|
|
for (const item of this.renderedItems) {
|
|
if (!eventShown && item.eventStart <= currentTime && (item.emptyFinish < 0 || item.emptyFinish > currentTime)) {
|
|
this._renderSubtitleEvent(item, currentTime)
|
|
eventShown = true
|
|
finishTime = item.emptyFinish
|
|
} else if (finishTime >= 0) {
|
|
// we've already found a known event, now find
|
|
// the farthest point of consequent events
|
|
// NOTE: this.renderedItems may have gaps due to seeking
|
|
if (item.eventStart - finishTime < 0.01) {
|
|
finishTime = item.emptyFinish
|
|
animated = item.animated
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!eventShown) {
|
|
if (Math.abs(this.oneshotState.requestNextTimestamp - currentTime) > 0.01) {
|
|
this._cleanPastRendered(currentTime)
|
|
this.tryRequestOneshot(currentTime, true)
|
|
}
|
|
} else if (this._cleanPastRendered(currentTime) && finishTime >= 0) {
|
|
this.tryRequestOneshot(finishTime, animated)
|
|
}
|
|
}
|
|
|
|
resetRenderAheadCache (isResizing) {
|
|
if (this.renderAhead > 0) {
|
|
const newCache = []
|
|
if (isResizing && this.oneshotState.prevHeight && this.oneshotState.prevWidth) {
|
|
if (this.oneshotState.prevHeight === this.canvas.height && this.oneshotState.prevWidth === this.canvas.width) return
|
|
let timeLimit = 10; let sizeLimit = this.renderAhead * 0.3
|
|
if (this.canvas.height >= this.oneshotState.prevHeight * (1.0 - this.resizeVariation) &&
|
|
this.canvas.height <= this.oneshotState.prevHeight * (1.0 + this.resizeVariation) &&
|
|
this.canvas.width >= this.oneshotState.prevWidth * (1.0 - this.resizeVariation) &&
|
|
this.canvas.width <= this.oneshotState.prevWidth * (1.0 + this.resizeVariation)) {
|
|
console.debug('viewport changes are small, leaving more of prerendered buffer')
|
|
timeLimit = 30
|
|
sizeLimit = this.renderAhead * 0.5
|
|
}
|
|
const stopTime = this.video.currentTime + this.timeOffset + timeLimit
|
|
let size = 0
|
|
for (const item of this.renderedItems) {
|
|
if (item.emptyFinish < 0 || item.emptyFinish >= stopTime) break
|
|
size += item.size
|
|
if (size >= sizeLimit) break
|
|
newCache.push(item)
|
|
}
|
|
}
|
|
|
|
console.info('resetting prerender cache')
|
|
this.renderedItems = newCache
|
|
this.oneshotState.eventStart = null
|
|
this.oneshotState.iteration++
|
|
this.oneshotState.renderRequested = false
|
|
this.oneshotState.prevHeight = this.canvas.height
|
|
this.oneshotState.prevWidth = this.canvas.width
|
|
|
|
window.requestAnimationFrame(this.oneshotRender)
|
|
this.tryRequestOneshot(undefined, true)
|
|
}
|
|
}
|
|
|
|
// Rendering
|
|
renderFrames (data) {
|
|
const beforeDrawTime = performance.now()
|
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
|
|
for (const image of data.canvases) {
|
|
this.bufferCanvas.width = image.w
|
|
this.bufferCanvas.height = image.h
|
|
const imageBuffer = new Uint8ClampedArray(image.buffer)
|
|
if (this.hasAlphaBug) {
|
|
for (let j = 3; j < imageBuffer.length; j += 4) {
|
|
imageBuffer[j] = (imageBuffer[j] >= 1) ? imageBuffer[j] : 1
|
|
}
|
|
}
|
|
const imageData = new ImageData(imageBuffer, image.w, image.h)
|
|
this.bufferCanvasCtx.putImageData(imageData, 0, 0)
|
|
this.ctx.drawImage(this.bufferCanvas, image.x, image.y)
|
|
}
|
|
if (this.debug) {
|
|
const drawTime = performance.now() - beforeDrawTime
|
|
const blendTime = data.blendTime
|
|
if (typeof blendTime !== 'undefined') {
|
|
console.log('render: ' + Math.round(data.spentTime - blendTime) + ' ms, blend: ' + Math.round(blendTime) + ' ms, draw: ' + drawTime + ' ms; TOTAL=' + Math.round(data.spentTime + drawTime) + ' ms')
|
|
} else {
|
|
console.log({ length: data.canvases.length, sum: data.libassTime + data.decodeTime + drawTime, libassTime: data.libassTime, decodeTime: data.decodeTime, drawTime })
|
|
}
|
|
this.renderStart = performance.now()
|
|
}
|
|
}
|
|
|
|
renderFastFrames (data) {
|
|
const beforeDrawTime = performance.now()
|
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
|
|
for (const image of data.bitmaps) {
|
|
this.ctx.drawImage(image.bitmap, image.x, image.y)
|
|
}
|
|
if (this.debug) {
|
|
const drawTime = performance.now() - beforeDrawTime
|
|
console.log({ length: data.bitmaps.length, sum: data.libassTime + data.decodeTime + drawTime, libassTime: data.libassTime, decodeTime: data.decodeTime, drawTime })
|
|
this.renderStart = performance.now()
|
|
}
|
|
}
|
|
|
|
_computeCanvasSize (width, height) {
|
|
if (this.prescaleTradeoff === null) {
|
|
if (height > this.hardHeightLimit) {
|
|
width = width * this.hardHeightLimit / height
|
|
height = this.hardHeightLimit
|
|
}
|
|
} else if (this.prescaleTradeoff > 1) {
|
|
if (height * this.prescaleTradeoff <= this.softHeightLimit) {
|
|
width *= this.prescaleTradeoff
|
|
height *= this.prescaleTradeoff
|
|
} else if (height < this.softHeightLimit) {
|
|
width = width * this.softHeightLimit / height
|
|
height = this.softHeightLimit
|
|
} else if (height >= this.hardHeightLimit) {
|
|
width = width * this.hardHeightLimit / height
|
|
height = this.hardHeightLimit
|
|
}
|
|
} else if (height >= this.softHeightLimit) {
|
|
if (height * this.prescaleTradeoff <= this.softHeightLimit) {
|
|
width = width * this.softHeightLimit / height
|
|
height = this.softHeightLimit
|
|
} else if (height * this.prescaleTradeoff <= this.hardHeightLimit) {
|
|
width *= this.prescaleTradeoff
|
|
height *= this.prescaleTradeoff
|
|
} else {
|
|
width = width * this.hardHeightLimit / height
|
|
height = this.hardHeightLimit
|
|
}
|
|
}
|
|
|
|
return { width, height }
|
|
}
|
|
|
|
resize (width = 0, height = 0, top = 0, left = 0) {
|
|
let videoSize = null
|
|
if ((!width || !height) && this.video) {
|
|
videoSize = this.getVideoPosition()
|
|
const newsize = this._computeCanvasSize(videoSize.width * (window.devicePixelRatio || 1), videoSize.height * (window.devicePixelRatio || 1))
|
|
width = newsize.width
|
|
height = newsize.height
|
|
const offset = this.canvasParent.getBoundingClientRect().top - this.video.getBoundingClientRect().top
|
|
top = videoSize.y - offset
|
|
left = videoSize.x
|
|
}
|
|
|
|
if (this.canvas.style.top !== top || this.canvas.style.left !== left) {
|
|
if (videoSize != null) {
|
|
this.canvasParent.style.position = 'relative'
|
|
this.canvas.style.display = 'block'
|
|
this.canvas.style.position = 'absolute'
|
|
this.canvas.style.top = top + 'px'
|
|
this.canvas.style.left = left + 'px'
|
|
this.canvas.style.pointerEvents = 'none'
|
|
}
|
|
if (!(this.canvas.width === width && this.canvas.height === height)) {
|
|
// only re-paint if dimensions actually changed
|
|
if (this.renderMode === 'offscreen' && this.initDone) {
|
|
this.canvasParent.remove()
|
|
this.canvasParent = undefined
|
|
this.createCanvas()
|
|
}
|
|
// dont spam re-paints like crazy when re-sizing with animations, but still update instantly without them
|
|
if (this.resizeTimeoutBuffer) {
|
|
clearTimeout(this.resizeTimeoutBuffer)
|
|
this.resizeTimeoutBuffer = setTimeout(() => {
|
|
this.resizeTimeoutBuffer = undefined
|
|
this.rePaint(width, height, top, left, videoSize)
|
|
}, 50)
|
|
} else {
|
|
this.rePaint(width, height, top, left, videoSize)
|
|
this.resizeTimeoutBuffer = setTimeout(() => {
|
|
this.resizeTimeoutBuffer = undefined
|
|
}, 50)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
rePaint (width = 0, height = 0, top = 0, left = 0, videoSize) {
|
|
if (this.renderMode === 'offscreen' && this.canvasParent && this.initDone) {
|
|
this.canvasParent.remove()
|
|
this.canvasParent = undefined
|
|
this.createCanvas()
|
|
}
|
|
this.canvas.width = width
|
|
this.canvas.height = height
|
|
|
|
if (videoSize != null) {
|
|
this.canvasParent.style.position = 'relative'
|
|
this.canvas.style.display = 'block'
|
|
this.canvas.style.position = 'absolute'
|
|
this.canvas.style.top = top + 'px'
|
|
this.canvas.style.left = left + 'px'
|
|
this.canvas.style.pointerEvents = 'none'
|
|
}
|
|
|
|
if (this.renderMode === 'offscreen' && this.initDone) {
|
|
this.pushOffscreenCanvas()
|
|
}
|
|
this.worker.postMessage({
|
|
target: 'canvas',
|
|
width: this.canvas.width,
|
|
height: this.canvas.height
|
|
})
|
|
this.resetRenderAheadCache(true)
|
|
}
|
|
|
|
// Message retardism
|
|
onWorkerMessage (event) {
|
|
if (!this.workerActive) {
|
|
this.workerActive = true
|
|
if (this.onReadyEvent) {
|
|
this.onReadyEvent()
|
|
}
|
|
}
|
|
const data = event.data
|
|
switch (data.target) {
|
|
case 'stdout': {
|
|
console.log(data.content)
|
|
break
|
|
}
|
|
case 'stderr': {
|
|
console.error(data.content)
|
|
break
|
|
}
|
|
case 'canvas': {
|
|
switch (data.op) {
|
|
case 'renderCanvas': {
|
|
if (this.lastRenderTime < data.time) {
|
|
this.lastRenderTime = data.time
|
|
window.requestAnimationFrame(() => this.renderFrames(data))
|
|
}
|
|
break
|
|
}
|
|
case 'renderFastCanvas': {
|
|
if (this.lastRenderTime < data.time) {
|
|
this.lastRenderTime = data.time
|
|
window.requestAnimationFrame(() => this.renderFastFrames(data))
|
|
}
|
|
break
|
|
}
|
|
case 'oneshot-result': {
|
|
this.processOneshot(data)
|
|
break
|
|
}
|
|
default:
|
|
throw data.target
|
|
}
|
|
break
|
|
}
|
|
case 'tick': {
|
|
this.frameId = data.id
|
|
this.worker.postMessage({
|
|
target: 'tock',
|
|
id: this.frameId
|
|
})
|
|
break
|
|
}
|
|
case 'custom': {
|
|
if (this.onCustomMessage) {
|
|
this.onCustomMessage(event)
|
|
} else {
|
|
console.error('Custom message received but client onCustomMessage not implemented.')
|
|
}
|
|
break
|
|
}
|
|
case 'ready': {
|
|
break
|
|
}
|
|
default:
|
|
console.log(data)
|
|
break
|
|
}
|
|
}
|
|
|
|
runBenchmark () {
|
|
this.worker.postMessage({
|
|
target: 'runBenchmark'
|
|
})
|
|
}
|
|
|
|
customMessage (data, options = {}) {
|
|
this.worker.postMessage({
|
|
target: 'custom',
|
|
userData: data,
|
|
preMain: options.preMain
|
|
})
|
|
}
|
|
|
|
setCurrentTime (isPaused, currentTime) {
|
|
this.worker.postMessage({
|
|
target: 'video',
|
|
isPaused: isPaused,
|
|
currentTime: currentTime
|
|
})
|
|
}
|
|
|
|
setTrackByUrl (url) {
|
|
this.worker.postMessage({
|
|
target: 'set-track-by-url',
|
|
url: url
|
|
})
|
|
this.resetRenderAheadCache(false)
|
|
}
|
|
|
|
setTrack (content) {
|
|
this.worker.postMessage({
|
|
target: 'set-track',
|
|
content: content
|
|
})
|
|
this.resetRenderAheadCache(false)
|
|
}
|
|
|
|
freeTrack () {
|
|
this.worker.postMessage({
|
|
target: 'free-track'
|
|
})
|
|
this.resetRenderAheadCache(false)
|
|
}
|
|
|
|
setRate (rate) {
|
|
this.worker.postMessage({
|
|
target: 'video',
|
|
rate: rate
|
|
})
|
|
}
|
|
|
|
dispose () {
|
|
this.worker.postMessage({
|
|
target: 'destroy'
|
|
})
|
|
|
|
this.worker.terminate()
|
|
this.workerActive = false
|
|
// Remove the canvas element to remove residual subtitles rendered on player
|
|
if (this.video) this.video.parentNode.removeChild(this.canvasParent)
|
|
}
|
|
|
|
createEvent (event) {
|
|
this.worker.postMessage({
|
|
target: 'create-event',
|
|
event: event
|
|
})
|
|
}
|
|
|
|
getEvents () {
|
|
this.worker.postMessage({
|
|
target: 'get-events'
|
|
})
|
|
}
|
|
|
|
setEvent (event, index) {
|
|
this.worker.postMessage({
|
|
target: 'set-event',
|
|
event: event,
|
|
index: index
|
|
})
|
|
}
|
|
|
|
removeEvent (index) {
|
|
this.worker.postMessage({
|
|
target: 'remove-event',
|
|
index: index
|
|
})
|
|
}
|
|
|
|
createStyle (style) {
|
|
this.worker.postMessage({
|
|
target: 'create-style',
|
|
style: style
|
|
})
|
|
}
|
|
|
|
getStyles () {
|
|
this.worker.postMessage({
|
|
target: 'get-styles'
|
|
})
|
|
}
|
|
|
|
setStyle (style, index) {
|
|
this.worker.postMessage({
|
|
target: 'set-style',
|
|
style: style,
|
|
index: index
|
|
})
|
|
}
|
|
|
|
removeStyle (index) {
|
|
this.worker.postMessage({
|
|
target: 'remove-style',
|
|
index: index
|
|
})
|
|
}
|
|
}
|
|
|
|
if (true) {
|
|
module.exports = SubtitlesOctopus
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webtorrent/index.js":
|
|
/*!******************************************!*\
|
|
!*** ./node_modules/webtorrent/index.js ***!
|
|
\******************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ "./node_modules/console-browserify/index.js");
|
|
/*! webtorrent. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */
|
|
/* global FileList */
|
|
|
|
const { EventEmitter } = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
const concat = __webpack_require__(/*! simple-concat */ "./node_modules/simple-concat/index.js")
|
|
const createTorrent = __webpack_require__(/*! create-torrent */ "./node_modules/create-torrent/index.js")
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('webtorrent')
|
|
const DHT = __webpack_require__(/*! bittorrent-dht/client */ "?4b99") // browser exclude
|
|
const loadIPSet = __webpack_require__(/*! load-ip-set */ "?ae1e") // browser exclude
|
|
const parallel = __webpack_require__(/*! run-parallel */ "./node_modules/run-parallel/index.js")
|
|
const parseTorrent = __webpack_require__(/*! parse-torrent */ "./node_modules/parse-torrent/index.js")
|
|
const path = __webpack_require__(/*! path */ "./node_modules/path-browserify/index.js")
|
|
const Peer = __webpack_require__(/*! simple-peer */ "./node_modules/simple-peer/index.js")
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
const randombytes = __webpack_require__(/*! randombytes */ "./node_modules/randombytes/browser.js")
|
|
const speedometer = __webpack_require__(/*! speedometer */ "./node_modules/speedometer/index.js")
|
|
const { ThrottleGroup } = __webpack_require__(/*! speed-limiter */ "./node_modules/speed-limiter/index.js")
|
|
|
|
const ConnPool = __webpack_require__(/*! ./lib/conn-pool */ "?6e41") // browser exclude
|
|
const Torrent = __webpack_require__(/*! ./lib/torrent */ "./node_modules/webtorrent/lib/torrent.js")
|
|
const VERSION = __webpack_require__(/*! ./package.json */ "./node_modules/webtorrent/package.json").version
|
|
|
|
/**
|
|
* Version number in Azureus-style. Generated from major and minor semver version.
|
|
* For example:
|
|
* '0.16.1' -> '0016'
|
|
* '1.2.5' -> '0102'
|
|
*/
|
|
const VERSION_STR = VERSION
|
|
.replace(/\d*./g, v => `0${v % 100}`.slice(-2))
|
|
.slice(0, 4)
|
|
|
|
/**
|
|
* Version prefix string (used in peer ID). WebTorrent uses the Azureus-style
|
|
* encoding: '-', two characters for client id ('WW'), four ascii digits for version
|
|
* number, '-', followed by random numbers.
|
|
* For example:
|
|
* '-WW0102-'...
|
|
*/
|
|
const VERSION_PREFIX = `-WW${VERSION_STR}-`
|
|
|
|
/**
|
|
* WebTorrent Client
|
|
* @param {Object=} opts
|
|
*/
|
|
class WebTorrent extends EventEmitter {
|
|
constructor (opts = {}) {
|
|
super()
|
|
|
|
if (typeof opts.peerId === 'string') {
|
|
this.peerId = opts.peerId
|
|
} else if (Buffer.isBuffer(opts.peerId)) {
|
|
this.peerId = opts.peerId.toString('hex')
|
|
} else {
|
|
this.peerId = Buffer.from(VERSION_PREFIX + randombytes(9).toString('base64')).toString('hex')
|
|
}
|
|
this.peerIdBuffer = Buffer.from(this.peerId, 'hex')
|
|
|
|
if (typeof opts.nodeId === 'string') {
|
|
this.nodeId = opts.nodeId
|
|
} else if (Buffer.isBuffer(opts.nodeId)) {
|
|
this.nodeId = opts.nodeId.toString('hex')
|
|
} else {
|
|
this.nodeId = randombytes(20).toString('hex')
|
|
}
|
|
this.nodeIdBuffer = Buffer.from(this.nodeId, 'hex')
|
|
|
|
this._debugId = this.peerId.toString('hex').substring(0, 7)
|
|
|
|
this.destroyed = false
|
|
this.listening = false
|
|
this.torrentPort = opts.torrentPort || 0
|
|
this.dhtPort = opts.dhtPort || 0
|
|
this.tracker = opts.tracker !== undefined ? opts.tracker : {}
|
|
this.lsd = opts.lsd !== false
|
|
this.torrents = []
|
|
this.maxConns = Number(opts.maxConns) || 55
|
|
this.utp = WebTorrent.UTP_SUPPORT && opts.utp !== false
|
|
|
|
this._downloadLimit = Math.max((typeof opts.downloadLimit === 'number') ? opts.downloadLimit : -1, -1)
|
|
this._uploadLimit = Math.max((typeof opts.uploadLimit === 'number') ? opts.uploadLimit : -1, -1)
|
|
|
|
this._debug(
|
|
'new webtorrent (peerId %s, nodeId %s, port %s)',
|
|
this.peerId, this.nodeId, this.torrentPort
|
|
)
|
|
|
|
this.throttleGroups = {
|
|
down: new ThrottleGroup({ rate: Math.max(this._downloadLimit, 0), enabled: this._downloadLimit >= 0 }),
|
|
up: new ThrottleGroup({ rate: Math.max(this._uploadLimit, 0), enabled: this._uploadLimit >= 0 })
|
|
}
|
|
|
|
if (this.tracker) {
|
|
if (typeof this.tracker !== 'object') this.tracker = {}
|
|
if (__webpack_require__.g.WRTC && !this.tracker.wrtc) this.tracker.wrtc = __webpack_require__.g.WRTC
|
|
}
|
|
|
|
if (typeof ConnPool === 'function') {
|
|
this._connPool = new ConnPool(this)
|
|
} else {
|
|
queueMicrotask(() => {
|
|
this._onListening()
|
|
})
|
|
}
|
|
|
|
// stats
|
|
this._downloadSpeed = speedometer()
|
|
this._uploadSpeed = speedometer()
|
|
|
|
if (opts.dht !== false && typeof DHT === 'function' /* browser exclude */) {
|
|
// use a single DHT instance for all torrents, so the routing table can be reused
|
|
this.dht = new DHT(Object.assign({}, { nodeId: this.nodeId }, opts.dht))
|
|
|
|
this.dht.once('error', err => {
|
|
this._destroy(err)
|
|
})
|
|
|
|
this.dht.once('listening', () => {
|
|
const address = this.dht.address()
|
|
if (address) this.dhtPort = address.port
|
|
})
|
|
|
|
// Ignore warning when there are > 10 torrents in the client
|
|
this.dht.setMaxListeners(0)
|
|
|
|
this.dht.listen(this.dhtPort)
|
|
} else {
|
|
this.dht = false
|
|
}
|
|
|
|
// Enable or disable BEP19 (Web Seeds). Enabled by default:
|
|
this.enableWebSeeds = opts.webSeeds !== false
|
|
|
|
const ready = () => {
|
|
if (this.destroyed) return
|
|
this.ready = true
|
|
this.emit('ready')
|
|
}
|
|
|
|
if (typeof loadIPSet === 'function' && opts.blocklist != null) {
|
|
loadIPSet(opts.blocklist, {
|
|
headers: {
|
|
'user-agent': `WebTorrent/${VERSION} (https://webtorrent.io)`
|
|
}
|
|
}, (err, ipSet) => {
|
|
if (err) return console.error(`Failed to load blocklist: ${err.message}`)
|
|
this.blocked = ipSet
|
|
ready()
|
|
})
|
|
} else {
|
|
queueMicrotask(ready)
|
|
}
|
|
}
|
|
|
|
get downloadSpeed () { return this._downloadSpeed() }
|
|
|
|
get uploadSpeed () { return this._uploadSpeed() }
|
|
|
|
get progress () {
|
|
const torrents = this.torrents.filter(torrent => torrent.progress !== 1)
|
|
const downloaded = torrents.reduce((total, torrent) => total + torrent.downloaded, 0)
|
|
const length = torrents.reduce((total, torrent) => total + (torrent.length || 0), 0) || 1
|
|
return downloaded / length
|
|
}
|
|
|
|
get ratio () {
|
|
const uploaded = this.torrents.reduce((total, torrent) => total + torrent.uploaded, 0)
|
|
const received = this.torrents.reduce((total, torrent) => total + torrent.received, 0) || 1
|
|
return uploaded / received
|
|
}
|
|
|
|
/**
|
|
* Returns the torrent with the given `torrentId`. Convenience method. Easier than
|
|
* searching through the `client.torrents` array. Returns `null` if no matching torrent
|
|
* found.
|
|
*
|
|
* @param {string|Buffer|Object|Torrent} torrentId
|
|
* @return {Torrent|null}
|
|
*/
|
|
get (torrentId) {
|
|
if (torrentId instanceof Torrent) {
|
|
if (this.torrents.includes(torrentId)) return torrentId
|
|
} else {
|
|
let parsed
|
|
try { parsed = parseTorrent(torrentId) } catch (err) {}
|
|
|
|
if (!parsed) return null
|
|
if (!parsed.infoHash) throw new Error('Invalid torrent identifier')
|
|
|
|
for (const torrent of this.torrents) {
|
|
if (torrent.infoHash === parsed.infoHash) return torrent
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Start downloading a new torrent. Aliased as `client.download`.
|
|
* @param {string|Buffer|Object} torrentId
|
|
* @param {Object} opts torrent-specific options
|
|
* @param {function=} ontorrent called when the torrent is ready (has metadata)
|
|
*/
|
|
add (torrentId, opts = {}, ontorrent = () => {}) {
|
|
if (this.destroyed) throw new Error('client is destroyed')
|
|
if (typeof opts === 'function') [opts, ontorrent] = [{}, opts]
|
|
|
|
const onInfoHash = () => {
|
|
if (this.destroyed) return
|
|
for (const t of this.torrents) {
|
|
if (t.infoHash === torrent.infoHash && t !== torrent) {
|
|
torrent._destroy(new Error(`Cannot add duplicate torrent ${torrent.infoHash}`))
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
const onReady = () => {
|
|
if (this.destroyed) return
|
|
ontorrent(torrent)
|
|
this.emit('torrent', torrent)
|
|
}
|
|
|
|
function onClose () {
|
|
torrent.removeListener('_infoHash', onInfoHash)
|
|
torrent.removeListener('ready', onReady)
|
|
torrent.removeListener('close', onClose)
|
|
}
|
|
|
|
this._debug('add')
|
|
opts = opts ? Object.assign({}, opts) : {}
|
|
|
|
const torrent = new Torrent(torrentId, this, opts)
|
|
this.torrents.push(torrent)
|
|
|
|
torrent.once('_infoHash', onInfoHash)
|
|
torrent.once('ready', onReady)
|
|
torrent.once('close', onClose)
|
|
|
|
return torrent
|
|
}
|
|
|
|
/**
|
|
* Start seeding a new file/folder.
|
|
* @param {string|File|FileList|Buffer|Array.<string|File|Buffer>} input
|
|
* @param {Object=} opts
|
|
* @param {function=} onseed called when torrent is seeding
|
|
*/
|
|
seed (input, opts, onseed) {
|
|
if (this.destroyed) throw new Error('client is destroyed')
|
|
if (typeof opts === 'function') [opts, onseed] = [{}, opts]
|
|
|
|
this._debug('seed')
|
|
opts = opts ? Object.assign({}, opts) : {}
|
|
|
|
// no need to verify the hashes we create
|
|
opts.skipVerify = true
|
|
|
|
const isFilePath = typeof input === 'string'
|
|
|
|
// When seeding from fs path, initialize store from that path to avoid a copy
|
|
if (isFilePath) opts.path = path.dirname(input)
|
|
if (!opts.createdBy) opts.createdBy = `WebTorrent/${VERSION_STR}`
|
|
|
|
const onTorrent = torrent => {
|
|
const tasks = [
|
|
cb => {
|
|
// when a filesystem path is specified or the store is preloaded, files are already in the FS store
|
|
if (isFilePath || opts.preloadedStore) return cb()
|
|
torrent.load(streams, cb)
|
|
}
|
|
]
|
|
if (this.dht) {
|
|
tasks.push(cb => {
|
|
torrent.once('dhtAnnounce', cb)
|
|
})
|
|
}
|
|
parallel(tasks, err => {
|
|
if (this.destroyed) return
|
|
if (err) return torrent._destroy(err)
|
|
_onseed(torrent)
|
|
})
|
|
}
|
|
|
|
const _onseed = torrent => {
|
|
this._debug('on seed')
|
|
if (typeof onseed === 'function') onseed(torrent)
|
|
torrent.emit('seed')
|
|
this.emit('seed', torrent)
|
|
}
|
|
|
|
const torrent = this.add(null, opts, onTorrent)
|
|
let streams
|
|
|
|
if (isFileList(input)) input = Array.from(input)
|
|
else if (!Array.isArray(input)) input = [input]
|
|
|
|
parallel(input.map(item => cb => {
|
|
if (!opts.preloadedStore && isReadable(item)) {
|
|
concat(item, (err, buf) => {
|
|
if (err) return cb(err)
|
|
buf.name = item.name
|
|
cb(null, buf)
|
|
})
|
|
} else {
|
|
cb(null, item)
|
|
}
|
|
}), (err, input) => {
|
|
if (this.destroyed) return
|
|
if (err) return torrent._destroy(err)
|
|
|
|
createTorrent.parseInput(input, opts, (err, files) => {
|
|
if (this.destroyed) return
|
|
if (err) return torrent._destroy(err)
|
|
|
|
streams = files.map(file => file.getStream)
|
|
|
|
createTorrent(input, opts, (err, torrentBuf) => {
|
|
if (this.destroyed) return
|
|
if (err) return torrent._destroy(err)
|
|
|
|
const existingTorrent = this.get(torrentBuf)
|
|
if (existingTorrent) {
|
|
torrent._destroy(new Error(`Cannot add duplicate torrent ${existingTorrent.infoHash}`))
|
|
} else {
|
|
torrent._onTorrentId(torrentBuf)
|
|
}
|
|
})
|
|
})
|
|
})
|
|
|
|
return torrent
|
|
}
|
|
|
|
/**
|
|
* Remove a torrent from the client.
|
|
* @param {string|Buffer|Torrent} torrentId
|
|
* @param {function} cb
|
|
*/
|
|
remove (torrentId, opts, cb) {
|
|
if (typeof opts === 'function') return this.remove(torrentId, null, opts)
|
|
|
|
this._debug('remove')
|
|
const torrent = this.get(torrentId)
|
|
if (!torrent) throw new Error(`No torrent with id ${torrentId}`)
|
|
this._remove(torrentId, opts, cb)
|
|
}
|
|
|
|
_remove (torrentId, opts, cb) {
|
|
if (typeof opts === 'function') return this._remove(torrentId, null, opts)
|
|
|
|
const torrent = this.get(torrentId)
|
|
if (!torrent) return
|
|
this.torrents.splice(this.torrents.indexOf(torrent), 1)
|
|
torrent.destroy(opts, cb)
|
|
}
|
|
|
|
address () {
|
|
if (!this.listening) return null
|
|
return this._connPool
|
|
? this._connPool.tcpServer.address()
|
|
: { address: '0.0.0.0', family: 'IPv4', port: 0 }
|
|
}
|
|
|
|
/**
|
|
* Set global download throttle rate.
|
|
* @param {Number} rate (must be bigger or equal than zero, or -1 to disable throttling)
|
|
*/
|
|
throttleDownload (rate) {
|
|
rate = Number(rate)
|
|
if (isNaN(rate) || !isFinite(rate) || rate < -1) return false
|
|
this._downloadLimit = rate
|
|
if (this._downloadLimit < 0) return this.throttleGroups.down.setEnabled(false)
|
|
this.throttleGroups.down.setEnabled(true)
|
|
this.throttleGroups.down.setRate(this._downloadLimit)
|
|
}
|
|
|
|
/**
|
|
* Set global upload throttle rate
|
|
* @param {Number} rate (must be bigger or equal than zero, or -1 to disable throttling)
|
|
*/
|
|
throttleUpload (rate) {
|
|
rate = Number(rate)
|
|
if (isNaN(rate) || !isFinite(rate) || rate < -1) return false
|
|
this._uploadLimit = rate
|
|
if (this._uploadLimit < 0) return this.throttleGroups.up.setEnabled(false)
|
|
this.throttleGroups.up.setEnabled(true)
|
|
this.throttleGroups.up.setRate(this._uploadLimit)
|
|
}
|
|
|
|
/**
|
|
* Destroy the client, including all torrents and connections to peers.
|
|
* @param {function} cb
|
|
*/
|
|
destroy (cb) {
|
|
if (this.destroyed) throw new Error('client already destroyed')
|
|
this._destroy(null, cb)
|
|
}
|
|
|
|
_destroy (err, cb) {
|
|
this._debug('client destroy')
|
|
this.destroyed = true
|
|
|
|
const tasks = this.torrents.map(torrent => cb => {
|
|
torrent.destroy(cb)
|
|
})
|
|
|
|
if (this._connPool) {
|
|
tasks.push(cb => {
|
|
this._connPool.destroy(cb)
|
|
})
|
|
}
|
|
|
|
if (this.dht) {
|
|
tasks.push(cb => {
|
|
this.dht.destroy(cb)
|
|
})
|
|
}
|
|
|
|
parallel(tasks, cb)
|
|
|
|
if (err) this.emit('error', err)
|
|
|
|
this.torrents = []
|
|
this._connPool = null
|
|
this.dht = null
|
|
|
|
this.throttleGroups.down.destroy()
|
|
this.throttleGroups.up.destroy()
|
|
}
|
|
|
|
_onListening () {
|
|
this._debug('listening')
|
|
this.listening = true
|
|
|
|
if (this._connPool) {
|
|
// Sometimes server.address() returns `null` in Docker.
|
|
const address = this._connPool.tcpServer.address()
|
|
if (address) this.torrentPort = address.port
|
|
}
|
|
|
|
this.emit('listening')
|
|
}
|
|
|
|
_debug () {
|
|
const args = [].slice.call(arguments)
|
|
args[0] = `[${this._debugId}] ${args[0]}`
|
|
debug(...args)
|
|
}
|
|
}
|
|
|
|
WebTorrent.WEBRTC_SUPPORT = Peer.WEBRTC_SUPPORT
|
|
WebTorrent.UTP_SUPPORT = ConnPool.UTP_SUPPORT
|
|
WebTorrent.VERSION = VERSION
|
|
|
|
/**
|
|
* Check if `obj` is a node Readable stream
|
|
* @param {*} obj
|
|
* @return {boolean}
|
|
*/
|
|
function isReadable (obj) {
|
|
return typeof obj === 'object' && obj != null && typeof obj.pipe === 'function'
|
|
}
|
|
|
|
/**
|
|
* Check if `obj` is a W3C `FileList` object
|
|
* @param {*} obj
|
|
* @return {boolean}
|
|
*/
|
|
function isFileList (obj) {
|
|
return typeof FileList !== 'undefined' && obj instanceof FileList
|
|
}
|
|
|
|
module.exports = WebTorrent
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webtorrent/lib/file-stream.js":
|
|
/*!****************************************************!*\
|
|
!*** ./node_modules/webtorrent/lib/file-stream.js ***!
|
|
\****************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('webtorrent:file-stream')
|
|
const stream = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
const eos = __webpack_require__(/*! end-of-stream */ "./node_modules/end-of-stream/index.js")
|
|
|
|
/**
|
|
* Readable stream of a torrent file
|
|
*
|
|
* @param {File} file
|
|
* @param {Object} opts
|
|
* @param {number} opts.start stream slice of file, starting from this byte (inclusive)
|
|
* @param {number} opts.end stream slice of file, ending with this byte (inclusive)
|
|
*/
|
|
class FileStream extends stream.Readable {
|
|
constructor (file, opts) {
|
|
super(opts)
|
|
|
|
this._torrent = file._torrent
|
|
|
|
const start = (opts && opts.start) || 0
|
|
const end = (opts && opts.end && opts.end < file.length)
|
|
? opts.end
|
|
: file.length - 1
|
|
|
|
const pieceLength = file._torrent.pieceLength
|
|
|
|
this._startPiece = (start + file.offset) / pieceLength | 0
|
|
this._endPiece = (end + file.offset) / pieceLength | 0
|
|
|
|
this._piece = this._startPiece
|
|
this._offset = (start + file.offset) - (this._startPiece * pieceLength)
|
|
|
|
this._missing = end - start + 1
|
|
this._reading = false
|
|
this._notifying = false
|
|
this._criticalLength = Math.min((1024 * 1024 / pieceLength) | 0, 2)
|
|
|
|
this._torrent.select(this._startPiece, this._endPiece, true, () => {
|
|
this._notify()
|
|
})
|
|
|
|
// Ensure that cleanup happens even if destroy() is never called (readable-stream v3 currently doesn't call it automaticallly)
|
|
eos(this, (err) => {
|
|
this.destroy(err)
|
|
})
|
|
}
|
|
|
|
_read () {
|
|
if (this._reading) return
|
|
this._reading = true
|
|
this._notify()
|
|
}
|
|
|
|
_notify () {
|
|
if (!this._reading || this._missing === 0) return
|
|
if (!this._torrent.bitfield.get(this._piece)) {
|
|
return this._torrent.critical(this._piece, this._piece + this._criticalLength)
|
|
}
|
|
|
|
if (this._notifying) return
|
|
this._notifying = true
|
|
|
|
if (this._torrent.destroyed) return this.destroy(new Error('Torrent removed'))
|
|
|
|
const p = this._piece
|
|
|
|
const getOpts = {}
|
|
// Specify length for the last piece in case it is zero-padded
|
|
if (p === this._torrent.pieces.length - 1) {
|
|
getOpts.length = this._torrent.lastPieceLength
|
|
}
|
|
this._torrent.store.get(p, getOpts, (err, buffer) => {
|
|
this._notifying = false
|
|
if (this.destroyed) return
|
|
debug('read %s (length %s) (err %s)', p, buffer && buffer.length, err && err.message)
|
|
|
|
if (err) return this.destroy(err)
|
|
|
|
if (this._offset) {
|
|
buffer = buffer.slice(this._offset)
|
|
this._offset = 0
|
|
}
|
|
|
|
if (this._missing < buffer.length) {
|
|
buffer = buffer.slice(0, this._missing)
|
|
}
|
|
this._missing -= buffer.length
|
|
|
|
debug('pushing buffer of length %s', buffer.length)
|
|
this._reading = false
|
|
this.push(buffer)
|
|
|
|
if (this._missing === 0) this.push(null)
|
|
})
|
|
this._piece += 1
|
|
}
|
|
|
|
_destroy (err, cb) {
|
|
if (!this._torrent.destroyed) {
|
|
this._torrent.deselect(this._startPiece, this._endPiece, true)
|
|
}
|
|
cb(err)
|
|
}
|
|
}
|
|
|
|
module.exports = FileStream
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webtorrent/lib/file.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/webtorrent/lib/file.js ***!
|
|
\*********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const { EventEmitter } = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
const { PassThrough } = __webpack_require__(/*! readable-stream */ "./node_modules/readable-stream/readable-browser.js")
|
|
const path = __webpack_require__(/*! path */ "./node_modules/path-browserify/index.js")
|
|
const render = __webpack_require__(/*! render-media */ "./node_modules/render-media/index.js")
|
|
const streamToBlob = __webpack_require__(/*! stream-to-blob */ "./node_modules/stream-to-blob/index.js")
|
|
const streamToBlobURL = __webpack_require__(/*! stream-to-blob-url */ "./node_modules/stream-to-blob-url/index.js")
|
|
const streamToBuffer = __webpack_require__(/*! stream-with-known-length-to-buffer */ "./node_modules/stream-with-known-length-to-buffer/index.js")
|
|
const FileStream = __webpack_require__(/*! ./file-stream */ "./node_modules/webtorrent/lib/file-stream.js")
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
|
|
class File extends EventEmitter {
|
|
constructor (torrent, file) {
|
|
super()
|
|
|
|
this._torrent = torrent
|
|
this._destroyed = false
|
|
this._fileStreams = new Set()
|
|
|
|
this.name = file.name
|
|
this.path = file.path
|
|
this.length = file.length
|
|
this.offset = file.offset
|
|
|
|
this.done = false
|
|
|
|
const start = file.offset
|
|
const end = start + file.length - 1
|
|
|
|
this._startPiece = start / this._torrent.pieceLength | 0
|
|
this._endPiece = end / this._torrent.pieceLength | 0
|
|
|
|
if (this.length === 0) {
|
|
this.done = true
|
|
this.emit('done')
|
|
}
|
|
}
|
|
|
|
get downloaded () {
|
|
if (this._destroyed || !this._torrent.bitfield) return 0
|
|
|
|
const { pieces, bitfield, pieceLength, lastPieceLength } = this._torrent
|
|
const { _startPiece: start, _endPiece: end } = this
|
|
|
|
const getPieceLength = (pieceIndex) => (
|
|
pieceIndex === pieces.length - 1 ? lastPieceLength : pieceLength
|
|
)
|
|
|
|
const getPieceDownloaded = (pieceIndex) => {
|
|
const len = pieceIndex === pieces.length - 1 ? lastPieceLength : pieceLength
|
|
if (bitfield.get(pieceIndex)) {
|
|
// verified data
|
|
return len
|
|
} else {
|
|
// "in progress" data
|
|
return len - pieces[pieceIndex].missing
|
|
}
|
|
}
|
|
|
|
let downloaded = 0
|
|
for (let index = start; index <= end; index += 1) {
|
|
const pieceDownloaded = getPieceDownloaded(index)
|
|
downloaded += pieceDownloaded
|
|
|
|
if (index === start) {
|
|
// First piece may have an offset, e.g. irrelevant bytes from the end of
|
|
// the previous file
|
|
const irrelevantFirstPieceBytes = this.offset % pieceLength
|
|
downloaded -= Math.min(irrelevantFirstPieceBytes, pieceDownloaded)
|
|
}
|
|
|
|
if (index === end) {
|
|
// Last piece may have an offset, e.g. irrelevant bytes from the start
|
|
// of the next file
|
|
const irrelevantLastPieceBytes = getPieceLength(end) - (this.offset + this.length) % pieceLength
|
|
downloaded -= Math.min(irrelevantLastPieceBytes, pieceDownloaded)
|
|
}
|
|
}
|
|
|
|
return downloaded
|
|
}
|
|
|
|
get progress () {
|
|
return this.length ? this.downloaded / this.length : 0
|
|
}
|
|
|
|
select (priority) {
|
|
if (this.length === 0) return
|
|
this._torrent.select(this._startPiece, this._endPiece, priority)
|
|
}
|
|
|
|
deselect () {
|
|
if (this.length === 0) return
|
|
this._torrent.deselect(this._startPiece, this._endPiece, false)
|
|
}
|
|
|
|
createReadStream (opts) {
|
|
if (this.length === 0) {
|
|
const empty = new PassThrough()
|
|
queueMicrotask(() => {
|
|
empty.end()
|
|
})
|
|
return empty
|
|
}
|
|
|
|
const fileStream = new FileStream(this, opts)
|
|
|
|
this._fileStreams.add(fileStream)
|
|
fileStream.once('close', () => {
|
|
this._fileStreams.delete(fileStream)
|
|
})
|
|
|
|
return fileStream
|
|
}
|
|
|
|
getBuffer (cb) {
|
|
streamToBuffer(this.createReadStream(), this.length, cb)
|
|
}
|
|
|
|
getBlob (cb) {
|
|
if (typeof window === 'undefined') throw new Error('browser-only method')
|
|
streamToBlob(this.createReadStream(), this._getMimeType())
|
|
.then(
|
|
blob => cb(null, blob),
|
|
err => cb(err)
|
|
)
|
|
}
|
|
|
|
getBlobURL (cb) {
|
|
if (typeof window === 'undefined') throw new Error('browser-only method')
|
|
streamToBlobURL(this.createReadStream(), this._getMimeType())
|
|
.then(
|
|
blobUrl => cb(null, blobUrl),
|
|
err => cb(err)
|
|
)
|
|
}
|
|
|
|
appendTo (elem, opts, cb) {
|
|
if (typeof window === 'undefined') throw new Error('browser-only method')
|
|
render.append(this, elem, opts, cb)
|
|
}
|
|
|
|
renderTo (elem, opts, cb) {
|
|
if (typeof window === 'undefined') throw new Error('browser-only method')
|
|
render.render(this, elem, opts, cb)
|
|
}
|
|
|
|
_getMimeType () {
|
|
return render.mime[path.extname(this.name).toLowerCase()]
|
|
}
|
|
|
|
_destroy () {
|
|
this._destroyed = true
|
|
this._torrent = null
|
|
|
|
for (const fileStream of this._fileStreams) {
|
|
fileStream.destroy()
|
|
}
|
|
this._fileStreams.clear()
|
|
}
|
|
}
|
|
|
|
module.exports = File
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webtorrent/lib/peer.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/webtorrent/lib/peer.js ***!
|
|
\*********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
const { EventEmitter } = __webpack_require__(/*! events */ "./node_modules/events/events.js")
|
|
const { Transform } = __webpack_require__(/*! stream */ "./node_modules/stream-browserify/index.js")
|
|
const arrayRemove = __webpack_require__(/*! unordered-array-remove */ "./node_modules/unordered-array-remove/index.js")
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('webtorrent:peer')
|
|
const Wire = __webpack_require__(/*! bittorrent-protocol */ "./node_modules/bittorrent-protocol/index.js")
|
|
|
|
const CONNECT_TIMEOUT_TCP = 5000
|
|
const CONNECT_TIMEOUT_UTP = 5000
|
|
const CONNECT_TIMEOUT_WEBRTC = 25000
|
|
const HANDSHAKE_TIMEOUT = 25000
|
|
|
|
/**
|
|
* WebRTC peer connections start out connected, because WebRTC peers require an
|
|
* "introduction" (i.e. WebRTC signaling), and there's no equivalent to an IP address
|
|
* that lets you refer to a WebRTC endpoint.
|
|
*/
|
|
exports.createWebRTCPeer = (conn, swarm, throttleGroups) => {
|
|
const peer = new Peer(conn.id, 'webrtc')
|
|
peer.conn = conn
|
|
peer.swarm = swarm
|
|
peer.throttleGroups = throttleGroups
|
|
|
|
if (peer.conn.connected) {
|
|
peer.onConnect()
|
|
} else {
|
|
const cleanup = () => {
|
|
peer.conn.removeListener('connect', onConnect)
|
|
peer.conn.removeListener('error', onError)
|
|
}
|
|
const onConnect = () => {
|
|
cleanup()
|
|
peer.onConnect()
|
|
}
|
|
const onError = err => {
|
|
cleanup()
|
|
peer.destroy(err)
|
|
}
|
|
peer.conn.once('connect', onConnect)
|
|
peer.conn.once('error', onError)
|
|
peer.startConnectTimeout()
|
|
}
|
|
|
|
return peer
|
|
}
|
|
|
|
/**
|
|
* Incoming TCP peers start out connected, because the remote peer connected to the
|
|
* listening port of the TCP server. Until the remote peer sends a handshake, we don't
|
|
* know what swarm the connection is intended for.
|
|
*/
|
|
exports.createTCPIncomingPeer = (conn, throttleGroups) => {
|
|
return _createIncomingPeer(conn, 'tcpIncoming', throttleGroups)
|
|
}
|
|
|
|
/**
|
|
* Incoming uTP peers start out connected, because the remote peer connected to the
|
|
* listening port of the uTP server. Until the remote peer sends a handshake, we don't
|
|
* know what swarm the connection is intended for.
|
|
*/
|
|
exports.createUTPIncomingPeer = (conn, throttleGroups) => {
|
|
return _createIncomingPeer(conn, 'utpIncoming', throttleGroups)
|
|
}
|
|
|
|
/**
|
|
* Outgoing TCP peers start out with just an IP address. At some point (when there is an
|
|
* available connection), the client can attempt to connect to the address.
|
|
*/
|
|
exports.createTCPOutgoingPeer = (addr, swarm, throttleGroups) => {
|
|
return _createOutgoingPeer(addr, swarm, 'tcpOutgoing', throttleGroups)
|
|
}
|
|
|
|
/**
|
|
* Outgoing uTP peers start out with just an IP address. At some point (when there is an
|
|
* available connection), the client can attempt to connect to the address.
|
|
*/
|
|
exports.createUTPOutgoingPeer = (addr, swarm, throttleGroups) => {
|
|
return _createOutgoingPeer(addr, swarm, 'utpOutgoing', throttleGroups)
|
|
}
|
|
|
|
const _createIncomingPeer = (conn, type, throttleGroups) => {
|
|
const addr = `${conn.remoteAddress}:${conn.remotePort}`
|
|
const peer = new Peer(addr, type)
|
|
peer.conn = conn
|
|
peer.addr = addr
|
|
peer.throttleGroups = throttleGroups
|
|
|
|
peer.onConnect()
|
|
|
|
return peer
|
|
}
|
|
|
|
const _createOutgoingPeer = (addr, swarm, type, throttleGroups) => {
|
|
const peer = new Peer(addr, type)
|
|
peer.addr = addr
|
|
peer.swarm = swarm
|
|
peer.throttleGroups = throttleGroups
|
|
|
|
return peer
|
|
}
|
|
|
|
/**
|
|
* Peer that represents a Web Seed (BEP17 / BEP19).
|
|
*/
|
|
exports.createWebSeedPeer = (conn, id, swarm, throttleGroups) => {
|
|
const peer = new Peer(id, 'webSeed')
|
|
peer.swarm = swarm
|
|
peer.conn = conn
|
|
peer.throttleGroups = throttleGroups
|
|
|
|
peer.onConnect()
|
|
|
|
return peer
|
|
}
|
|
|
|
/**
|
|
* Peer. Represents a peer in the torrent swarm.
|
|
*
|
|
* @param {string} id "ip:port" string, peer id (for WebRTC peers), or url (for Web Seeds)
|
|
* @param {string} type the type of the peer
|
|
*/
|
|
class Peer extends EventEmitter {
|
|
constructor (id, type) {
|
|
super()
|
|
|
|
this.id = id
|
|
this.type = type
|
|
|
|
debug('new %s Peer %s', type, id)
|
|
|
|
this.addr = null
|
|
this.conn = null
|
|
this.swarm = null
|
|
this.wire = null
|
|
|
|
this.connected = false
|
|
this.destroyed = false
|
|
this.timeout = null // handshake timeout
|
|
this.retries = 0 // outgoing TCP connection retry count
|
|
|
|
this.sentHandshake = false
|
|
}
|
|
|
|
/**
|
|
* Called once the peer is connected (i.e. fired 'connect' event)
|
|
* @param {Socket} conn
|
|
*/
|
|
onConnect () {
|
|
if (this.destroyed) return
|
|
this.connected = true
|
|
|
|
debug('Peer %s connected', this.id)
|
|
|
|
clearTimeout(this.connectTimeout)
|
|
|
|
const conn = this.conn
|
|
conn.once('end', () => {
|
|
this.destroy()
|
|
})
|
|
conn.once('close', () => {
|
|
this.destroy()
|
|
})
|
|
conn.once('finish', () => {
|
|
this.destroy()
|
|
})
|
|
conn.once('error', err => {
|
|
this.destroy(err)
|
|
})
|
|
|
|
const wire = this.wire = new Wire()
|
|
wire.type = this.type
|
|
wire.once('end', () => {
|
|
this.destroy()
|
|
})
|
|
wire.once('close', () => {
|
|
this.destroy()
|
|
})
|
|
wire.once('finish', () => {
|
|
this.destroy()
|
|
})
|
|
wire.once('error', err => {
|
|
this.destroy(err)
|
|
})
|
|
|
|
wire.once('handshake', (infoHash, peerId) => {
|
|
this.onHandshake(infoHash, peerId)
|
|
})
|
|
this.startHandshakeTimeout()
|
|
|
|
this.setThrottlePipes()
|
|
|
|
if (this.swarm && !this.sentHandshake) this.handshake()
|
|
}
|
|
|
|
clearPipes () {
|
|
this.conn.unpipe()
|
|
this.wire.unpipe()
|
|
}
|
|
|
|
setThrottlePipes () {
|
|
const self = this
|
|
this.conn
|
|
.pipe(this.throttleGroups.down.throttle())
|
|
.pipe(new Transform({
|
|
transform (chunk, _, callback) {
|
|
self.emit('download', chunk.length)
|
|
if (self.destroyed) return
|
|
callback(null, chunk)
|
|
}
|
|
}))
|
|
.pipe(this.wire)
|
|
.pipe(this.throttleGroups.up.throttle())
|
|
.pipe(new Transform({
|
|
transform (chunk, _, callback) {
|
|
self.emit('upload', chunk.length)
|
|
if (self.destroyed) return
|
|
callback(null, chunk)
|
|
}
|
|
}))
|
|
.pipe(this.conn)
|
|
}
|
|
|
|
/**
|
|
* Called when handshake is received from remote peer.
|
|
* @param {string} infoHash
|
|
* @param {string} peerId
|
|
*/
|
|
onHandshake (infoHash, peerId) {
|
|
if (!this.swarm) return // `this.swarm` not set yet, so do nothing
|
|
if (this.destroyed) return
|
|
|
|
if (this.swarm.destroyed) {
|
|
return this.destroy(new Error('swarm already destroyed'))
|
|
}
|
|
if (infoHash !== this.swarm.infoHash) {
|
|
return this.destroy(new Error('unexpected handshake info hash for this swarm'))
|
|
}
|
|
if (peerId === this.swarm.peerId) {
|
|
return this.destroy(new Error('refusing to connect to ourselves'))
|
|
}
|
|
|
|
debug('Peer %s got handshake %s', this.id, infoHash)
|
|
|
|
clearTimeout(this.handshakeTimeout)
|
|
|
|
this.retries = 0
|
|
|
|
let addr = this.addr
|
|
if (!addr && this.conn.remoteAddress && this.conn.remotePort) {
|
|
addr = `${this.conn.remoteAddress}:${this.conn.remotePort}`
|
|
}
|
|
this.swarm._onWire(this.wire, addr)
|
|
|
|
// swarm could be destroyed in user's 'wire' event handler
|
|
if (!this.swarm || this.swarm.destroyed) return
|
|
|
|
if (!this.sentHandshake) this.handshake()
|
|
}
|
|
|
|
handshake () {
|
|
const opts = {
|
|
dht: this.swarm.private ? false : !!this.swarm.client.dht
|
|
}
|
|
this.wire.handshake(this.swarm.infoHash, this.swarm.client.peerId, opts)
|
|
this.sentHandshake = true
|
|
}
|
|
|
|
startConnectTimeout () {
|
|
clearTimeout(this.connectTimeout)
|
|
|
|
const connectTimeoutValues = {
|
|
webrtc: CONNECT_TIMEOUT_WEBRTC,
|
|
tcpOutgoing: CONNECT_TIMEOUT_TCP,
|
|
utpOutgoing: CONNECT_TIMEOUT_UTP
|
|
}
|
|
|
|
this.connectTimeout = setTimeout(() => {
|
|
this.destroy(new Error('connect timeout'))
|
|
}, connectTimeoutValues[this.type])
|
|
if (this.connectTimeout.unref) this.connectTimeout.unref()
|
|
}
|
|
|
|
startHandshakeTimeout () {
|
|
clearTimeout(this.handshakeTimeout)
|
|
this.handshakeTimeout = setTimeout(() => {
|
|
this.destroy(new Error('handshake timeout'))
|
|
}, HANDSHAKE_TIMEOUT)
|
|
if (this.handshakeTimeout.unref) this.handshakeTimeout.unref()
|
|
}
|
|
|
|
destroy (err) {
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
this.connected = false
|
|
|
|
debug('destroy %s %s (error: %s)', this.type, this.id, err && (err.message || err))
|
|
|
|
clearTimeout(this.connectTimeout)
|
|
clearTimeout(this.handshakeTimeout)
|
|
|
|
const swarm = this.swarm
|
|
const conn = this.conn
|
|
const wire = this.wire
|
|
|
|
this.swarm = null
|
|
this.conn = null
|
|
this.wire = null
|
|
|
|
if (swarm && wire) {
|
|
arrayRemove(swarm.wires, swarm.wires.indexOf(wire))
|
|
}
|
|
if (conn) {
|
|
conn.on('error', () => {})
|
|
conn.destroy()
|
|
}
|
|
if (wire) wire.destroy()
|
|
if (swarm) swarm.removePeer(this.id)
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webtorrent/lib/rarity-map.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/webtorrent/lib/rarity-map.js ***!
|
|
\***************************************************/
|
|
/***/ ((module) => {
|
|
|
|
|
|
/**
|
|
* Mapping of torrent pieces to their respective availability in the torrent swarm. Used
|
|
* by the torrent manager for implementing the rarest piece first selection strategy.
|
|
*/
|
|
class RarityMap {
|
|
constructor (torrent) {
|
|
this._torrent = torrent
|
|
this._numPieces = torrent.pieces.length
|
|
this._pieces = new Array(this._numPieces)
|
|
|
|
this._onWire = wire => {
|
|
this.recalculate()
|
|
this._initWire(wire)
|
|
}
|
|
this._onWireHave = index => {
|
|
this._pieces[index] += 1
|
|
}
|
|
this._onWireBitfield = () => {
|
|
this.recalculate()
|
|
}
|
|
|
|
this._torrent.wires.forEach(wire => {
|
|
this._initWire(wire)
|
|
})
|
|
this._torrent.on('wire', this._onWire)
|
|
this.recalculate()
|
|
}
|
|
|
|
/**
|
|
* Get the index of the rarest piece. Optionally, pass a filter function to exclude
|
|
* certain pieces (for instance, those that we already have).
|
|
*
|
|
* @param {function} pieceFilterFunc
|
|
* @return {number} index of rarest piece, or -1
|
|
*/
|
|
getRarestPiece (pieceFilterFunc) {
|
|
let candidates = []
|
|
let min = Infinity
|
|
|
|
for (let i = 0; i < this._numPieces; ++i) {
|
|
if (pieceFilterFunc && !pieceFilterFunc(i)) continue
|
|
|
|
const availability = this._pieces[i]
|
|
if (availability === min) {
|
|
candidates.push(i)
|
|
} else if (availability < min) {
|
|
candidates = [i]
|
|
min = availability
|
|
}
|
|
}
|
|
|
|
if (candidates.length) {
|
|
// if there are multiple pieces with the same availability, choose one randomly
|
|
return candidates[Math.random() * candidates.length | 0]
|
|
} else {
|
|
return -1
|
|
}
|
|
}
|
|
|
|
destroy () {
|
|
this._torrent.removeListener('wire', this._onWire)
|
|
this._torrent.wires.forEach(wire => {
|
|
this._cleanupWireEvents(wire)
|
|
})
|
|
this._torrent = null
|
|
this._pieces = null
|
|
|
|
this._onWire = null
|
|
this._onWireHave = null
|
|
this._onWireBitfield = null
|
|
}
|
|
|
|
_initWire (wire) {
|
|
wire._onClose = () => {
|
|
this._cleanupWireEvents(wire)
|
|
for (let i = 0; i < this._numPieces; ++i) {
|
|
this._pieces[i] -= wire.peerPieces.get(i)
|
|
}
|
|
}
|
|
|
|
wire.on('have', this._onWireHave)
|
|
wire.on('bitfield', this._onWireBitfield)
|
|
wire.once('close', wire._onClose)
|
|
}
|
|
|
|
/**
|
|
* Recalculates piece availability across all peers in the torrent.
|
|
*/
|
|
recalculate () {
|
|
this._pieces.fill(0)
|
|
|
|
for (const wire of this._torrent.wires) {
|
|
for (let i = 0; i < this._numPieces; ++i) {
|
|
this._pieces[i] += wire.peerPieces.get(i)
|
|
}
|
|
}
|
|
}
|
|
|
|
_cleanupWireEvents (wire) {
|
|
wire.removeListener('have', this._onWireHave)
|
|
wire.removeListener('bitfield', this._onWireBitfield)
|
|
if (wire._onClose) wire.removeListener('close', wire._onClose)
|
|
wire._onClose = null
|
|
}
|
|
}
|
|
|
|
module.exports = RarityMap
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webtorrent/lib/torrent.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/webtorrent/lib/torrent.js ***!
|
|
\************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var process = __webpack_require__(/*! ./node_modules/process/browser.js */ "./node_modules/process/browser.js");
|
|
/* global Blob */
|
|
|
|
const addrToIPPort = __webpack_require__(/*! addr-to-ip-port */ "./node_modules/addr-to-ip-port/index.js")
|
|
const BitField = __webpack_require__(/*! bitfield */ "./node_modules/bitfield/lib/index.js").default
|
|
const CacheChunkStore = __webpack_require__(/*! cache-chunk-store */ "./node_modules/cache-chunk-store/index.js")
|
|
const ChunkStoreWriteStream = __webpack_require__(/*! chunk-store-stream/write */ "./node_modules/chunk-store-stream/write.js")
|
|
const cpus = __webpack_require__(/*! cpus */ "./node_modules/cpus/browser.js")
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('webtorrent:torrent')
|
|
const Discovery = __webpack_require__(/*! torrent-discovery */ "./node_modules/torrent-discovery/index.js")
|
|
const EventEmitter = __webpack_require__(/*! events */ "./node_modules/events/events.js").EventEmitter
|
|
const fs = __webpack_require__(/*! fs */ "?c172")
|
|
const FSChunkStore = __webpack_require__(/*! fs-chunk-store */ "./node_modules/memory-chunk-store/index.js") // browser: `memory-chunk-store`
|
|
const get = __webpack_require__(/*! simple-get */ "./node_modules/simple-get/index.js")
|
|
const ImmediateChunkStore = __webpack_require__(/*! immediate-chunk-store */ "./node_modules/immediate-chunk-store/index.js")
|
|
const ltDontHave = __webpack_require__(/*! lt_donthave */ "./node_modules/lt_donthave/index.js")
|
|
const MemoryChunkStore = __webpack_require__(/*! memory-chunk-store */ "./node_modules/memory-chunk-store/index.js")
|
|
const MultiStream = __webpack_require__(/*! multistream */ "./node_modules/multistream/index.js")
|
|
const net = __webpack_require__(/*! net */ "?c362") // browser exclude
|
|
const os = __webpack_require__(/*! os */ "?5efe") // browser exclude
|
|
const parallel = __webpack_require__(/*! run-parallel */ "./node_modules/run-parallel/index.js")
|
|
const parallelLimit = __webpack_require__(/*! run-parallel-limit */ "./node_modules/run-parallel-limit/index.js")
|
|
const parseTorrent = __webpack_require__(/*! parse-torrent */ "./node_modules/parse-torrent/index.js")
|
|
const path = __webpack_require__(/*! path */ "./node_modules/path-browserify/index.js")
|
|
const Piece = __webpack_require__(/*! torrent-piece */ "./node_modules/torrent-piece/index.js")
|
|
const pump = __webpack_require__(/*! pump */ "./node_modules/pump/index.js")
|
|
const queueMicrotask = __webpack_require__(/*! queue-microtask */ "./node_modules/queue-microtask/index.js")
|
|
const randomIterate = __webpack_require__(/*! random-iterate */ "./node_modules/random-iterate/index.js")
|
|
const sha1 = __webpack_require__(/*! simple-sha1 */ "./node_modules/simple-sha1/browser.js")
|
|
const speedometer = __webpack_require__(/*! speedometer */ "./node_modules/speedometer/index.js")
|
|
const utMetadata = __webpack_require__(/*! ut_metadata */ "./node_modules/ut_metadata/index.js")
|
|
const utPex = __webpack_require__(/*! ut_pex */ "?6dbd") // browser exclude
|
|
|
|
const File = __webpack_require__(/*! ./file */ "./node_modules/webtorrent/lib/file.js")
|
|
const Peer = __webpack_require__(/*! ./peer */ "./node_modules/webtorrent/lib/peer.js")
|
|
const RarityMap = __webpack_require__(/*! ./rarity-map */ "./node_modules/webtorrent/lib/rarity-map.js")
|
|
const Server = __webpack_require__(/*! ./server */ "?ea49") // browser exclude
|
|
const utp = __webpack_require__(/*! ./utp */ "?d41a") // browser exclude
|
|
const WebConn = __webpack_require__(/*! ./webconn */ "./node_modules/webtorrent/lib/webconn.js")
|
|
|
|
const MAX_BLOCK_LENGTH = 128 * 1024
|
|
const PIECE_TIMEOUT = 30000
|
|
const CHOKE_TIMEOUT = 5000
|
|
const SPEED_THRESHOLD = 3 * Piece.BLOCK_LENGTH
|
|
|
|
const PIPELINE_MIN_DURATION = 0.5
|
|
const PIPELINE_MAX_DURATION = 1
|
|
|
|
const RECHOKE_INTERVAL = 10000 // 10 seconds
|
|
const RECHOKE_OPTIMISTIC_DURATION = 2 // 30 seconds
|
|
|
|
// IndexedDB chunk stores used in the browser benefit from high concurrency
|
|
const FILESYSTEM_CONCURRENCY = process.browser ? cpus().length : 2
|
|
|
|
const RECONNECT_WAIT = [1000, 5000, 15000]
|
|
|
|
const VERSION = __webpack_require__(/*! ../package.json */ "./node_modules/webtorrent/package.json").version
|
|
const USER_AGENT = `WebTorrent/${VERSION} (https://webtorrent.io)`
|
|
|
|
let TMP
|
|
try {
|
|
TMP = path.join(fs.statSync('/tmp') && '/tmp', 'webtorrent')
|
|
} catch (err) {
|
|
TMP = path.join(typeof os.tmpdir === 'function' ? os.tmpdir() : '/', 'webtorrent')
|
|
}
|
|
|
|
class Torrent extends EventEmitter {
|
|
constructor (torrentId, client, opts) {
|
|
super()
|
|
|
|
this._debugId = 'unknown infohash'
|
|
this.client = client
|
|
|
|
this.announce = opts.announce
|
|
this.urlList = opts.urlList
|
|
|
|
this.path = opts.path
|
|
this.skipVerify = !!opts.skipVerify
|
|
this._store = opts.store || FSChunkStore
|
|
this._preloadedStore = opts.preloadedStore || null
|
|
this._storeCacheSlots = opts.storeCacheSlots !== undefined ? opts.storeCacheSlots : 20
|
|
this._destroyStoreOnDestroy = opts.destroyStoreOnDestroy || false
|
|
this._getAnnounceOpts = opts.getAnnounceOpts
|
|
|
|
// if defined, `opts.private` overrides default privacy of torrent
|
|
if (typeof opts.private === 'boolean') this.private = opts.private
|
|
|
|
this.strategy = opts.strategy || 'sequential'
|
|
|
|
this.maxWebConns = opts.maxWebConns || 4
|
|
|
|
this._rechokeNumSlots = (opts.uploads === false || opts.uploads === 0)
|
|
? 0
|
|
: (+opts.uploads || 10)
|
|
this._rechokeOptimisticWire = null
|
|
this._rechokeOptimisticTime = 0
|
|
this._rechokeIntervalId = null
|
|
|
|
this.ready = false
|
|
this.destroyed = false
|
|
this.paused = opts.paused || false
|
|
this.done = false
|
|
|
|
this.metadata = null
|
|
this.store = null
|
|
this.files = []
|
|
this.pieces = []
|
|
|
|
this._amInterested = false
|
|
this._selections = []
|
|
this._critical = []
|
|
|
|
this.wires = [] // open wires (added *after* handshake)
|
|
|
|
this._queue = [] // queue of outgoing tcp peers to connect to
|
|
this._peers = {} // connected peers (addr/peerId -> Peer)
|
|
this._peersLength = 0 // number of elements in `this._peers` (cache, for perf)
|
|
|
|
// stats
|
|
this.received = 0
|
|
this.uploaded = 0
|
|
this._downloadSpeed = speedometer()
|
|
this._uploadSpeed = speedometer()
|
|
|
|
// for cleanup
|
|
this._servers = []
|
|
this._xsRequests = []
|
|
|
|
// TODO: remove this and expose a hook instead
|
|
// optimization: don't recheck every file if it hasn't changed
|
|
this._fileModtimes = opts.fileModtimes
|
|
|
|
if (torrentId !== null) this._onTorrentId(torrentId)
|
|
|
|
this._debug('new torrent')
|
|
}
|
|
|
|
get timeRemaining () {
|
|
if (this.done) return 0
|
|
if (this.downloadSpeed === 0) return Infinity
|
|
return ((this.length - this.downloaded) / this.downloadSpeed) * 1000
|
|
}
|
|
|
|
get downloaded () {
|
|
if (!this.bitfield) return 0
|
|
let downloaded = 0
|
|
for (let index = 0, len = this.pieces.length; index < len; ++index) {
|
|
if (this.bitfield.get(index)) { // verified data
|
|
downloaded += (index === len - 1) ? this.lastPieceLength : this.pieceLength
|
|
} else { // "in progress" data
|
|
const piece = this.pieces[index]
|
|
downloaded += (piece.length - piece.missing)
|
|
}
|
|
}
|
|
return downloaded
|
|
}
|
|
|
|
// TODO: re-enable this. The number of missing pieces. Used to implement 'end game' mode.
|
|
// Object.defineProperty(Storage.prototype, 'numMissing', {
|
|
// get: function () {
|
|
// var self = this
|
|
// var numMissing = self.pieces.length
|
|
// for (var index = 0, len = self.pieces.length; index < len; index++) {
|
|
// numMissing -= self.bitfield.get(index)
|
|
// }
|
|
// return numMissing
|
|
// }
|
|
// })
|
|
|
|
get downloadSpeed () { return this._downloadSpeed() }
|
|
|
|
get uploadSpeed () { return this._uploadSpeed() }
|
|
|
|
get progress () { return this.length ? this.downloaded / this.length : 0 }
|
|
|
|
get ratio () { return this.uploaded / (this.received || this.length) }
|
|
|
|
get numPeers () { return this.wires.length }
|
|
|
|
get torrentFileBlobURL () {
|
|
if (typeof window === 'undefined') throw new Error('browser-only property')
|
|
if (!this.torrentFile) return null
|
|
return URL.createObjectURL(
|
|
new Blob([this.torrentFile], { type: 'application/x-bittorrent' })
|
|
)
|
|
}
|
|
|
|
get _numQueued () {
|
|
return this._queue.length + (this._peersLength - this._numConns)
|
|
}
|
|
|
|
get _numConns () {
|
|
let numConns = 0
|
|
for (const id in this._peers) {
|
|
if (this._peers[id].connected) numConns += 1
|
|
}
|
|
return numConns
|
|
}
|
|
|
|
_onTorrentId (torrentId) {
|
|
if (this.destroyed) return
|
|
|
|
let parsedTorrent
|
|
try { parsedTorrent = parseTorrent(torrentId) } catch (err) {}
|
|
if (parsedTorrent) {
|
|
// Attempt to set infoHash property synchronously
|
|
this.infoHash = parsedTorrent.infoHash
|
|
this._debugId = parsedTorrent.infoHash.toString('hex').substring(0, 7)
|
|
queueMicrotask(() => {
|
|
if (this.destroyed) return
|
|
this._onParsedTorrent(parsedTorrent)
|
|
})
|
|
} else {
|
|
// If torrentId failed to parse, it could be in a form that requires an async
|
|
// operation, i.e. http/https link, filesystem path, or Blob.
|
|
parseTorrent.remote(torrentId, (err, parsedTorrent) => {
|
|
if (this.destroyed) return
|
|
if (err) return this._destroy(err)
|
|
this._onParsedTorrent(parsedTorrent)
|
|
})
|
|
}
|
|
}
|
|
|
|
_onParsedTorrent (parsedTorrent) {
|
|
if (this.destroyed) return
|
|
|
|
this._processParsedTorrent(parsedTorrent)
|
|
|
|
if (!this.infoHash) {
|
|
return this._destroy(new Error('Malformed torrent data: No info hash'))
|
|
}
|
|
|
|
if (!this.path) this.path = path.join(TMP, this.infoHash)
|
|
|
|
this._rechokeIntervalId = setInterval(() => {
|
|
this._rechoke()
|
|
}, RECHOKE_INTERVAL)
|
|
if (this._rechokeIntervalId.unref) this._rechokeIntervalId.unref()
|
|
|
|
// Private 'infoHash' event allows client.add to check for duplicate torrents and
|
|
// destroy them before the normal 'infoHash' event is emitted. Prevents user
|
|
// applications from needing to deal with duplicate 'infoHash' events.
|
|
this.emit('_infoHash', this.infoHash)
|
|
if (this.destroyed) return
|
|
|
|
this.emit('infoHash', this.infoHash)
|
|
if (this.destroyed) return // user might destroy torrent in event handler
|
|
|
|
if (this.client.listening) {
|
|
this._onListening()
|
|
} else {
|
|
this.client.once('listening', () => {
|
|
this._onListening()
|
|
})
|
|
}
|
|
}
|
|
|
|
_processParsedTorrent (parsedTorrent) {
|
|
this._debugId = parsedTorrent.infoHash.toString('hex').substring(0, 7)
|
|
|
|
if (typeof this.private !== 'undefined') {
|
|
// `private` option overrides default, only if it's defined
|
|
parsedTorrent.private = this.private
|
|
}
|
|
|
|
if (this.announce) {
|
|
// Allow specifying trackers via `opts` parameter
|
|
parsedTorrent.announce = parsedTorrent.announce.concat(this.announce)
|
|
}
|
|
|
|
if (this.client.tracker && __webpack_require__.g.WEBTORRENT_ANNOUNCE && !parsedTorrent.private) {
|
|
// So `webtorrent-hybrid` can force specific trackers to be used
|
|
parsedTorrent.announce = parsedTorrent.announce.concat(__webpack_require__.g.WEBTORRENT_ANNOUNCE)
|
|
}
|
|
|
|
if (this.urlList) {
|
|
// Allow specifying web seeds via `opts` parameter
|
|
parsedTorrent.urlList = parsedTorrent.urlList.concat(this.urlList)
|
|
}
|
|
|
|
// remove duplicates by converting to Set and back
|
|
parsedTorrent.announce = Array.from(new Set(parsedTorrent.announce))
|
|
parsedTorrent.urlList = Array.from(new Set(parsedTorrent.urlList))
|
|
|
|
Object.assign(this, parsedTorrent)
|
|
|
|
this.magnetURI = parseTorrent.toMagnetURI(parsedTorrent)
|
|
this.torrentFile = parseTorrent.toTorrentFile(parsedTorrent)
|
|
}
|
|
|
|
_onListening () {
|
|
if (this.destroyed) return
|
|
|
|
if (this.info) {
|
|
// if full metadata was included in initial torrent id, use it immediately. Otherwise,
|
|
// wait for torrent-discovery to find peers and ut_metadata to get the metadata.
|
|
this._onMetadata(this)
|
|
} else {
|
|
if (this.xs) this._getMetadataFromServer()
|
|
this._startDiscovery()
|
|
}
|
|
}
|
|
|
|
_startDiscovery () {
|
|
if (this.discovery || this.destroyed) return
|
|
|
|
let trackerOpts = this.client.tracker
|
|
if (trackerOpts) {
|
|
trackerOpts = Object.assign({}, this.client.tracker, {
|
|
getAnnounceOpts: () => {
|
|
if (this.destroyed) return
|
|
|
|
const opts = {
|
|
uploaded: this.uploaded,
|
|
downloaded: this.downloaded,
|
|
left: Math.max(this.length - this.downloaded, 0)
|
|
}
|
|
if (this.client.tracker.getAnnounceOpts) {
|
|
Object.assign(opts, this.client.tracker.getAnnounceOpts())
|
|
}
|
|
if (this._getAnnounceOpts) {
|
|
// TODO: consider deprecating this, as it's redundant with the former case
|
|
Object.assign(opts, this._getAnnounceOpts())
|
|
}
|
|
return opts
|
|
}
|
|
})
|
|
}
|
|
|
|
// add BEP09 peer-address
|
|
if (this.peerAddresses) {
|
|
this.peerAddresses.forEach(peer => this.addPeer(peer))
|
|
}
|
|
|
|
// begin discovering peers via DHT and trackers
|
|
this.discovery = new Discovery({
|
|
infoHash: this.infoHash,
|
|
announce: this.announce,
|
|
peerId: this.client.peerId,
|
|
dht: !this.private && this.client.dht,
|
|
tracker: trackerOpts,
|
|
port: this.client.torrentPort,
|
|
userAgent: USER_AGENT,
|
|
lsd: this.client.lsd
|
|
})
|
|
|
|
this.discovery.on('error', (err) => {
|
|
this._destroy(err)
|
|
})
|
|
|
|
this.discovery.on('peer', (peer, source) => {
|
|
this._debug('peer %s discovered via %s', peer, source)
|
|
// Don't create new outgoing TCP connections when torrent is done
|
|
if (typeof peer === 'string' && this.done) return
|
|
this.addPeer(peer)
|
|
})
|
|
|
|
this.discovery.on('trackerAnnounce', () => {
|
|
this.emit('trackerAnnounce')
|
|
if (this.numPeers === 0) this.emit('noPeers', 'tracker')
|
|
})
|
|
|
|
this.discovery.on('dhtAnnounce', () => {
|
|
this.emit('dhtAnnounce')
|
|
if (this.numPeers === 0) this.emit('noPeers', 'dht')
|
|
})
|
|
|
|
this.discovery.on('warning', (err) => {
|
|
this.emit('warning', err)
|
|
})
|
|
}
|
|
|
|
_getMetadataFromServer () {
|
|
// to allow function hoisting
|
|
const self = this
|
|
|
|
const urls = Array.isArray(this.xs) ? this.xs : [this.xs]
|
|
|
|
const tasks = urls.map(url => cb => {
|
|
getMetadataFromURL(url, cb)
|
|
})
|
|
parallel(tasks)
|
|
|
|
function getMetadataFromURL (url, cb) {
|
|
if (url.indexOf('http://') !== 0 && url.indexOf('https://') !== 0) {
|
|
self.emit('warning', new Error(`skipping non-http xs param: ${url}`))
|
|
return cb(null)
|
|
}
|
|
|
|
const opts = {
|
|
url,
|
|
method: 'GET',
|
|
headers: {
|
|
'user-agent': USER_AGENT
|
|
}
|
|
}
|
|
let req
|
|
try {
|
|
req = get.concat(opts, onResponse)
|
|
} catch (err) {
|
|
self.emit('warning', new Error(`skipping invalid url xs param: ${url}`))
|
|
return cb(null)
|
|
}
|
|
|
|
self._xsRequests.push(req)
|
|
|
|
function onResponse (err, res, torrent) {
|
|
if (self.destroyed) return cb(null)
|
|
if (self.metadata) return cb(null)
|
|
|
|
if (err) {
|
|
self.emit('warning', new Error(`http error from xs param: ${url}`))
|
|
return cb(null)
|
|
}
|
|
if (res.statusCode !== 200) {
|
|
self.emit('warning', new Error(`non-200 status code ${res.statusCode} from xs param: ${url}`))
|
|
return cb(null)
|
|
}
|
|
|
|
let parsedTorrent
|
|
try {
|
|
parsedTorrent = parseTorrent(torrent)
|
|
} catch (err) {}
|
|
|
|
if (!parsedTorrent) {
|
|
self.emit('warning', new Error(`got invalid torrent file from xs param: ${url}`))
|
|
return cb(null)
|
|
}
|
|
|
|
if (parsedTorrent.infoHash !== self.infoHash) {
|
|
self.emit('warning', new Error(`got torrent file with incorrect info hash from xs param: ${url}`))
|
|
return cb(null)
|
|
}
|
|
|
|
self._onMetadata(parsedTorrent)
|
|
cb(null)
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when the full torrent metadata is received.
|
|
*/
|
|
_onMetadata (metadata) {
|
|
if (this.metadata || this.destroyed) return
|
|
this._debug('got metadata')
|
|
|
|
this._xsRequests.forEach(req => {
|
|
req.abort()
|
|
})
|
|
this._xsRequests = []
|
|
|
|
let parsedTorrent
|
|
if (metadata && metadata.infoHash) {
|
|
// `metadata` is a parsed torrent (from parse-torrent module)
|
|
parsedTorrent = metadata
|
|
} else {
|
|
try {
|
|
parsedTorrent = parseTorrent(metadata)
|
|
} catch (err) {
|
|
return this._destroy(err)
|
|
}
|
|
}
|
|
|
|
this._processParsedTorrent(parsedTorrent)
|
|
this.metadata = this.torrentFile
|
|
|
|
// add web seed urls (BEP19)
|
|
if (this.client.enableWebSeeds) {
|
|
this.urlList.forEach(url => {
|
|
this.addWebSeed(url)
|
|
})
|
|
}
|
|
|
|
this._rarityMap = new RarityMap(this)
|
|
|
|
let rawStore = this._preloadedStore
|
|
if (!rawStore) {
|
|
rawStore = new this._store(this.pieceLength, {
|
|
// opts.torrent is deprecated (replaced by the name property).
|
|
// it doesn't appear to be used by current versions of any stores on npm.
|
|
torrent: {
|
|
infoHash: this.infoHash
|
|
},
|
|
files: this.files.map(file => ({
|
|
path: path.join(this.path, file.path),
|
|
length: file.length,
|
|
offset: file.offset
|
|
})),
|
|
length: this.length,
|
|
name: this.infoHash
|
|
})
|
|
}
|
|
|
|
// don't use the cache if the store is already in memory
|
|
if (this._storeCacheSlots > 0 && !(rawStore instanceof MemoryChunkStore)) {
|
|
rawStore = new CacheChunkStore(rawStore, {
|
|
max: this._storeCacheSlots
|
|
})
|
|
}
|
|
|
|
this.store = new ImmediateChunkStore(
|
|
rawStore
|
|
)
|
|
|
|
this.files = this.files.map(file => new File(this, file))
|
|
|
|
// Select only specified files (BEP53) http://www.bittorrent.org/beps/bep_0053.html
|
|
if (this.so) {
|
|
this.files.forEach((v, i) => {
|
|
if (this.so.includes(i)) {
|
|
this.files[i].select()
|
|
} else {
|
|
this.files[i].deselect()
|
|
}
|
|
})
|
|
} else {
|
|
// start off selecting the entire torrent with low priority
|
|
if (this.pieces.length !== 0) {
|
|
this.select(0, this.pieces.length - 1, false)
|
|
}
|
|
}
|
|
|
|
this._hashes = this.pieces
|
|
|
|
this.pieces = this.pieces.map((hash, i) => {
|
|
const pieceLength = (i === this.pieces.length - 1)
|
|
? this.lastPieceLength
|
|
: this.pieceLength
|
|
return new Piece(pieceLength)
|
|
})
|
|
|
|
this._reservations = this.pieces.map(() => [])
|
|
|
|
this.bitfield = new BitField(this.pieces.length)
|
|
|
|
this.wires.forEach(wire => {
|
|
// If we didn't have the metadata at the time ut_metadata was initialized for this
|
|
// wire, we still want to make it available to the peer in case they request it.
|
|
if (wire.ut_metadata) wire.ut_metadata.setMetadata(this.metadata)
|
|
|
|
this._onWireWithMetadata(wire)
|
|
})
|
|
|
|
// Emit 'metadata' before 'ready' and 'done'
|
|
this.emit('metadata')
|
|
|
|
// User might destroy torrent in response to 'metadata' event
|
|
if (this.destroyed) return
|
|
|
|
if (this.skipVerify) {
|
|
// Skip verifying exisitng data and just assume it's correct
|
|
this._markAllVerified()
|
|
this._onStore()
|
|
} else {
|
|
const onPiecesVerified = (err) => {
|
|
if (err) return this._destroy(err)
|
|
this._debug('done verifying')
|
|
this._onStore()
|
|
}
|
|
|
|
this._debug('verifying existing torrent data')
|
|
if (this._fileModtimes && this._store === FSChunkStore) {
|
|
// don't verify if the files haven't been modified since we last checked
|
|
this.getFileModtimes((err, fileModtimes) => {
|
|
if (err) return this._destroy(err)
|
|
|
|
const unchanged = this.files.map((_, index) => fileModtimes[index] === this._fileModtimes[index]).every(x => x)
|
|
|
|
if (unchanged) {
|
|
this._markAllVerified()
|
|
this._onStore()
|
|
} else {
|
|
this._verifyPieces(onPiecesVerified)
|
|
}
|
|
})
|
|
} else {
|
|
this._verifyPieces(onPiecesVerified)
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* TODO: remove this
|
|
* Gets the last modified time of every file on disk for this torrent.
|
|
* Only valid in Node, not in the browser.
|
|
*/
|
|
getFileModtimes (cb) {
|
|
const ret = []
|
|
parallelLimit(this.files.map((file, index) => cb => {
|
|
fs.stat(path.join(this.path, file.path), (err, stat) => {
|
|
if (err && err.code !== 'ENOENT') return cb(err)
|
|
ret[index] = stat && stat.mtime.getTime()
|
|
cb(null)
|
|
})
|
|
}), FILESYSTEM_CONCURRENCY, err => {
|
|
this._debug('done getting file modtimes')
|
|
cb(err, ret)
|
|
})
|
|
}
|
|
|
|
_verifyPieces (cb) {
|
|
parallelLimit(this.pieces.map((piece, index) => cb => {
|
|
if (this.destroyed) return cb(new Error('torrent is destroyed'))
|
|
|
|
const getOpts = {}
|
|
// Specify length for the last piece in case it is zero-padded
|
|
if (index === this.pieces.length - 1) {
|
|
getOpts.length = this.lastPieceLength
|
|
}
|
|
this.store.get(index, getOpts, (err, buf) => {
|
|
if (this.destroyed) return cb(new Error('torrent is destroyed'))
|
|
|
|
if (err) return queueMicrotask(() => cb(null)) // ignore error
|
|
sha1(buf, hash => {
|
|
if (this.destroyed) return cb(new Error('torrent is destroyed'))
|
|
|
|
if (hash === this._hashes[index]) {
|
|
this._debug('piece verified %s', index)
|
|
this._markVerified(index)
|
|
} else {
|
|
this._debug('piece invalid %s', index)
|
|
}
|
|
cb(null)
|
|
})
|
|
})
|
|
}), FILESYSTEM_CONCURRENCY, cb)
|
|
}
|
|
|
|
rescanFiles (cb) {
|
|
if (this.destroyed) throw new Error('torrent is destroyed')
|
|
if (!cb) cb = noop
|
|
|
|
this._verifyPieces((err) => {
|
|
if (err) {
|
|
this._destroy(err)
|
|
return cb(err)
|
|
}
|
|
|
|
this._checkDone()
|
|
cb(null)
|
|
})
|
|
}
|
|
|
|
_markAllVerified () {
|
|
for (let index = 0; index < this.pieces.length; index++) {
|
|
this._markVerified(index)
|
|
}
|
|
}
|
|
|
|
_markVerified (index) {
|
|
this.pieces[index] = null
|
|
this._reservations[index] = null
|
|
this.bitfield.set(index, true)
|
|
}
|
|
|
|
/**
|
|
* Called when the metadata, listening server, and underlying chunk store is initialized.
|
|
*/
|
|
_onStore () {
|
|
if (this.destroyed) return
|
|
this._debug('on store')
|
|
|
|
// Start discovery before emitting 'ready'
|
|
this._startDiscovery()
|
|
|
|
this.ready = true
|
|
this.emit('ready')
|
|
|
|
// Files may start out done if the file was already in the store
|
|
this._checkDone()
|
|
|
|
// In case any selections were made before torrent was ready
|
|
this._updateSelections()
|
|
}
|
|
|
|
destroy (opts, cb) {
|
|
if (typeof opts === 'function') return this.destroy(null, opts)
|
|
|
|
this._destroy(null, opts, cb)
|
|
}
|
|
|
|
_destroy (err, opts, cb) {
|
|
if (typeof opts === 'function') return this._destroy(err, null, opts)
|
|
if (this.destroyed) return
|
|
this.destroyed = true
|
|
this._debug('destroy')
|
|
|
|
this.client._remove(this)
|
|
|
|
clearInterval(this._rechokeIntervalId)
|
|
|
|
this._xsRequests.forEach(req => {
|
|
req.abort()
|
|
})
|
|
|
|
if (this._rarityMap) {
|
|
this._rarityMap.destroy()
|
|
}
|
|
|
|
for (const id in this._peers) {
|
|
this.removePeer(id)
|
|
}
|
|
|
|
this.files.forEach(file => {
|
|
if (file instanceof File) file._destroy()
|
|
})
|
|
|
|
const tasks = this._servers.map(server => cb => {
|
|
server.destroy(cb)
|
|
})
|
|
|
|
if (this.discovery) {
|
|
tasks.push(cb => {
|
|
this.discovery.destroy(cb)
|
|
})
|
|
}
|
|
|
|
if (this.store) {
|
|
let destroyStore = this._destroyStoreOnDestroy
|
|
if (opts && opts.destroyStore !== undefined) {
|
|
destroyStore = opts.destroyStore
|
|
}
|
|
tasks.push(cb => {
|
|
if (destroyStore) {
|
|
this.store.destroy(cb)
|
|
} else {
|
|
this.store.close(cb)
|
|
}
|
|
})
|
|
}
|
|
|
|
parallel(tasks, cb)
|
|
|
|
if (err) {
|
|
// Torrent errors are emitted at `torrent.on('error')`. If there are no 'error'
|
|
// event handlers on the torrent instance, then the error will be emitted at
|
|
// `client.on('error')`. This prevents throwing an uncaught exception
|
|
// (unhandled 'error' event), but it makes it impossible to distinguish client
|
|
// errors versus torrent errors. Torrent errors are not fatal, and the client
|
|
// is still usable afterwards. Therefore, always listen for errors in both
|
|
// places (`client.on('error')` and `torrent.on('error')`).
|
|
if (this.listenerCount('error') === 0) {
|
|
this.client.emit('error', err)
|
|
} else {
|
|
this.emit('error', err)
|
|
}
|
|
}
|
|
|
|
this.emit('close')
|
|
|
|
this.client = null
|
|
this.files = []
|
|
this.discovery = null
|
|
this.store = null
|
|
this._rarityMap = null
|
|
this._peers = null
|
|
this._servers = null
|
|
this._xsRequests = null
|
|
}
|
|
|
|
addPeer (peer) {
|
|
if (this.destroyed) throw new Error('torrent is destroyed')
|
|
if (!this.infoHash) throw new Error('addPeer() must not be called before the `infoHash` event')
|
|
|
|
let host
|
|
|
|
if (this.client.blocked) {
|
|
if (typeof peer === 'string') {
|
|
let parts
|
|
try {
|
|
parts = addrToIPPort(peer)
|
|
} catch (e) {
|
|
this._debug('ignoring peer: invalid %s', peer)
|
|
this.emit('invalidPeer', peer)
|
|
return false
|
|
}
|
|
host = parts[0]
|
|
} else if (typeof peer.remoteAddress === 'string') {
|
|
host = peer.remoteAddress
|
|
}
|
|
|
|
if (host && this.client.blocked.contains(host)) {
|
|
this._debug('ignoring peer: blocked %s', peer)
|
|
if (typeof peer !== 'string') peer.destroy()
|
|
this.emit('blockedPeer', peer)
|
|
return false
|
|
}
|
|
}
|
|
|
|
// if the utp connection fails to connect, then it is replaced with a tcp connection to the same ip:port
|
|
|
|
const type = (this.client.utp && this._isIPv4(host)) ? 'utp' : 'tcp'
|
|
const wasAdded = !!this._addPeer(peer, type)
|
|
|
|
if (wasAdded) {
|
|
this.emit('peer', peer)
|
|
} else {
|
|
this.emit('invalidPeer', peer)
|
|
}
|
|
return wasAdded
|
|
}
|
|
|
|
_addPeer (peer, type) {
|
|
if (this.destroyed) {
|
|
if (typeof peer !== 'string') peer.destroy()
|
|
return null
|
|
}
|
|
if (typeof peer === 'string' && !this._validAddr(peer)) {
|
|
this._debug('ignoring peer: invalid %s', peer)
|
|
return null
|
|
}
|
|
|
|
const id = (peer && peer.id) || peer
|
|
if (this._peers[id]) {
|
|
this._debug('ignoring peer: duplicate (%s)', id)
|
|
if (typeof peer !== 'string') peer.destroy()
|
|
return null
|
|
}
|
|
|
|
if (this.paused) {
|
|
this._debug('ignoring peer: torrent is paused')
|
|
if (typeof peer !== 'string') peer.destroy()
|
|
return null
|
|
}
|
|
|
|
this._debug('add peer %s', id)
|
|
|
|
let newPeer
|
|
if (typeof peer === 'string') {
|
|
// `peer` is an addr ("ip:port" string)
|
|
newPeer = type === 'utp'
|
|
? Peer.createUTPOutgoingPeer(peer, this, this.client.throttleGroups)
|
|
: Peer.createTCPOutgoingPeer(peer, this, this.client.throttleGroups)
|
|
} else {
|
|
// `peer` is a WebRTC connection (simple-peer)
|
|
newPeer = Peer.createWebRTCPeer(peer, this, this.client.throttleGroups)
|
|
}
|
|
|
|
this._registerPeer(newPeer)
|
|
|
|
if (typeof peer === 'string') {
|
|
// `peer` is an addr ("ip:port" string)
|
|
this._queue.push(newPeer)
|
|
this._drain()
|
|
}
|
|
|
|
return newPeer
|
|
}
|
|
|
|
addWebSeed (urlOrConn) {
|
|
if (this.destroyed) throw new Error('torrent is destroyed')
|
|
|
|
let id
|
|
let conn
|
|
if (typeof urlOrConn === 'string') {
|
|
id = urlOrConn
|
|
|
|
if (!/^https?:\/\/.+/.test(id)) {
|
|
this.emit('warning', new Error(`ignoring invalid web seed: ${id}`))
|
|
this.emit('invalidPeer', id)
|
|
return
|
|
}
|
|
|
|
if (this._peers[id]) {
|
|
this.emit('warning', new Error(`ignoring duplicate web seed: ${id}`))
|
|
this.emit('invalidPeer', id)
|
|
return
|
|
}
|
|
|
|
conn = new WebConn(id, this)
|
|
} else if (urlOrConn && typeof urlOrConn.connId === 'string') {
|
|
conn = urlOrConn
|
|
id = conn.connId
|
|
|
|
if (this._peers[id]) {
|
|
this.emit('warning', new Error(`ignoring duplicate web seed: ${id}`))
|
|
this.emit('invalidPeer', id)
|
|
return
|
|
}
|
|
} else {
|
|
this.emit('warning', new Error('addWebSeed must be passed a string or connection object with id property'))
|
|
return
|
|
}
|
|
|
|
this._debug('add web seed %s', id)
|
|
|
|
const newPeer = Peer.createWebSeedPeer(conn, id, this, this.client.throttleGroups)
|
|
|
|
this._registerPeer(newPeer)
|
|
|
|
this.emit('peer', id)
|
|
}
|
|
|
|
/**
|
|
* Called whenever a new incoming TCP peer connects to this torrent swarm. Called with a
|
|
* peer that has already sent a handshake.
|
|
*/
|
|
_addIncomingPeer (peer) {
|
|
if (this.destroyed) return peer.destroy(new Error('torrent is destroyed'))
|
|
if (this.paused) return peer.destroy(new Error('torrent is paused'))
|
|
|
|
this._debug('add incoming peer %s', peer.id)
|
|
|
|
this._registerPeer(peer)
|
|
}
|
|
|
|
_registerPeer (newPeer) {
|
|
newPeer.on('download', downloaded => {
|
|
if (this.destroyed) return
|
|
this.received += downloaded
|
|
this._downloadSpeed(downloaded)
|
|
this.client._downloadSpeed(downloaded)
|
|
this.emit('download', downloaded)
|
|
if (this.destroyed) return
|
|
this.client.emit('download', downloaded)
|
|
})
|
|
|
|
newPeer.on('upload', uploaded => {
|
|
if (this.destroyed) return
|
|
this.uploaded += uploaded
|
|
this._uploadSpeed(uploaded)
|
|
this.client._uploadSpeed(uploaded)
|
|
this.emit('upload', uploaded)
|
|
if (this.destroyed) return
|
|
this.client.emit('upload', uploaded)
|
|
})
|
|
|
|
this._peers[newPeer.id] = newPeer
|
|
this._peersLength += 1
|
|
}
|
|
|
|
removePeer (peer) {
|
|
const id = (peer && peer.id) || peer
|
|
peer = this._peers[id]
|
|
|
|
if (!peer) return
|
|
|
|
this._debug('removePeer %s', id)
|
|
|
|
delete this._peers[id]
|
|
this._peersLength -= 1
|
|
|
|
peer.destroy()
|
|
|
|
// If torrent swarm was at capacity before, try to open a new connection now
|
|
this._drain()
|
|
}
|
|
|
|
select (start, end, priority, notify) {
|
|
if (this.destroyed) throw new Error('torrent is destroyed')
|
|
|
|
if (start < 0 || end < start || this.pieces.length <= end) {
|
|
throw new Error(`invalid selection ${start} : ${end}`)
|
|
}
|
|
priority = Number(priority) || 0
|
|
|
|
this._debug('select %s-%s (priority %s)', start, end, priority)
|
|
|
|
this._selections.push({
|
|
from: start,
|
|
to: end,
|
|
offset: 0,
|
|
priority,
|
|
notify: notify || noop
|
|
})
|
|
|
|
this._selections.sort((a, b) => b.priority - a.priority)
|
|
|
|
this._updateSelections()
|
|
}
|
|
|
|
deselect (start, end, priority) {
|
|
if (this.destroyed) throw new Error('torrent is destroyed')
|
|
|
|
priority = Number(priority) || 0
|
|
this._debug('deselect %s-%s (priority %s)', start, end, priority)
|
|
|
|
for (let i = 0; i < this._selections.length; ++i) {
|
|
const s = this._selections[i]
|
|
if (s.from === start && s.to === end && s.priority === priority) {
|
|
this._selections.splice(i, 1)
|
|
break
|
|
}
|
|
}
|
|
|
|
this._updateSelections()
|
|
}
|
|
|
|
critical (start, end) {
|
|
if (this.destroyed) throw new Error('torrent is destroyed')
|
|
|
|
this._debug('critical %s-%s', start, end)
|
|
|
|
for (let i = start; i <= end; ++i) {
|
|
this._critical[i] = true
|
|
}
|
|
|
|
this._updateSelections()
|
|
}
|
|
|
|
_onWire (wire, addr) {
|
|
this._debug('got wire %s (%s)', wire._debugId, addr || 'Unknown')
|
|
|
|
this.wires.push(wire)
|
|
|
|
if (addr) {
|
|
// Sometimes RTCPeerConnection.getStats() doesn't return an ip:port for peers
|
|
const parts = addrToIPPort(addr)
|
|
wire.remoteAddress = parts[0]
|
|
wire.remotePort = parts[1]
|
|
}
|
|
|
|
// When peer sends PORT message, add that DHT node to routing table
|
|
if (this.client.dht && this.client.dht.listening) {
|
|
wire.on('port', port => {
|
|
if (this.destroyed || this.client.dht.destroyed) {
|
|
return
|
|
}
|
|
if (!wire.remoteAddress) {
|
|
return this._debug('ignoring PORT from peer with no address')
|
|
}
|
|
if (port === 0 || port > 65536) {
|
|
return this._debug('ignoring invalid PORT from peer')
|
|
}
|
|
|
|
this._debug('port: %s (from %s)', port, addr)
|
|
this.client.dht.addNode({ host: wire.remoteAddress, port })
|
|
})
|
|
}
|
|
|
|
wire.on('timeout', () => {
|
|
this._debug('wire timeout (%s)', addr)
|
|
// TODO: this might be destroying wires too eagerly
|
|
wire.destroy()
|
|
})
|
|
|
|
// Timeout for piece requests to this peer
|
|
if (wire.type !== 'webSeed') { // webseeds always send 'unhave' on http timeout
|
|
wire.setTimeout(PIECE_TIMEOUT, true)
|
|
}
|
|
|
|
// Send KEEP-ALIVE (every 60s) so peers will not disconnect the wire
|
|
wire.setKeepAlive(true)
|
|
|
|
// use ut_metadata extension
|
|
wire.use(utMetadata(this.metadata))
|
|
|
|
wire.ut_metadata.on('warning', err => {
|
|
this._debug('ut_metadata warning: %s', err.message)
|
|
})
|
|
|
|
if (!this.metadata) {
|
|
wire.ut_metadata.on('metadata', metadata => {
|
|
this._debug('got metadata via ut_metadata')
|
|
this._onMetadata(metadata)
|
|
})
|
|
wire.ut_metadata.fetch()
|
|
}
|
|
|
|
// use ut_pex extension if the torrent is not flagged as private
|
|
if (typeof utPex === 'function' && !this.private) {
|
|
wire.use(utPex())
|
|
|
|
wire.ut_pex.on('peer', peer => {
|
|
// Only add potential new peers when we're not seeding
|
|
if (this.done) return
|
|
this._debug('ut_pex: got peer: %s (from %s)', peer, addr)
|
|
this.addPeer(peer)
|
|
})
|
|
|
|
wire.ut_pex.on('dropped', peer => {
|
|
// the remote peer believes a given peer has been dropped from the torrent swarm.
|
|
// if we're not currently connected to it, then remove it from the queue.
|
|
const peerObj = this._peers[peer]
|
|
if (peerObj && !peerObj.connected) {
|
|
this._debug('ut_pex: dropped peer: %s (from %s)', peer, addr)
|
|
this.removePeer(peer)
|
|
}
|
|
})
|
|
|
|
wire.once('close', () => {
|
|
// Stop sending updates to remote peer
|
|
wire.ut_pex.reset()
|
|
})
|
|
}
|
|
|
|
wire.use(ltDontHave())
|
|
|
|
// Hook to allow user-defined `bittorrent-protocol` extensions
|
|
// More info: https://github.com/webtorrent/bittorrent-protocol#extension-api
|
|
this.emit('wire', wire, addr)
|
|
|
|
if (this.metadata) {
|
|
queueMicrotask(() => {
|
|
// This allows wire.handshake() to be called (by Peer.onHandshake) before any
|
|
// messages get sent on the wire
|
|
this._onWireWithMetadata(wire)
|
|
})
|
|
}
|
|
}
|
|
|
|
_onWireWithMetadata (wire) {
|
|
let timeoutId = null
|
|
|
|
const onChokeTimeout = () => {
|
|
if (this.destroyed || wire.destroyed) return
|
|
|
|
if (this._numQueued > 2 * (this._numConns - this.numPeers) &&
|
|
wire.amInterested) {
|
|
wire.destroy()
|
|
} else {
|
|
timeoutId = setTimeout(onChokeTimeout, CHOKE_TIMEOUT)
|
|
if (timeoutId.unref) timeoutId.unref()
|
|
}
|
|
}
|
|
|
|
let i
|
|
const updateSeedStatus = () => {
|
|
if (wire.peerPieces.buffer.length !== this.bitfield.buffer.length) return
|
|
for (i = 0; i < this.pieces.length; ++i) {
|
|
if (!wire.peerPieces.get(i)) return
|
|
}
|
|
wire.isSeeder = true
|
|
wire.choke() // always choke seeders
|
|
}
|
|
|
|
wire.on('bitfield', () => {
|
|
updateSeedStatus()
|
|
this._update()
|
|
this._updateWireInterest(wire)
|
|
})
|
|
|
|
wire.on('have', () => {
|
|
updateSeedStatus()
|
|
this._update()
|
|
this._updateWireInterest(wire)
|
|
})
|
|
|
|
wire.lt_donthave.on('donthave', () => {
|
|
updateSeedStatus()
|
|
this._update()
|
|
this._updateWireInterest(wire)
|
|
})
|
|
|
|
wire.once('interested', () => {
|
|
wire.unchoke()
|
|
})
|
|
|
|
wire.once('close', () => {
|
|
clearTimeout(timeoutId)
|
|
})
|
|
|
|
wire.on('choke', () => {
|
|
clearTimeout(timeoutId)
|
|
timeoutId = setTimeout(onChokeTimeout, CHOKE_TIMEOUT)
|
|
if (timeoutId.unref) timeoutId.unref()
|
|
})
|
|
|
|
wire.on('unchoke', () => {
|
|
clearTimeout(timeoutId)
|
|
this._update()
|
|
})
|
|
|
|
wire.on('request', (index, offset, length, cb) => {
|
|
if (length > MAX_BLOCK_LENGTH) {
|
|
// Per spec, disconnect from peers that request >128KB
|
|
return wire.destroy()
|
|
}
|
|
if (this.pieces[index]) return
|
|
this.store.get(index, { offset, length }, cb)
|
|
})
|
|
|
|
wire.bitfield(this.bitfield) // always send bitfield (required)
|
|
|
|
// initialize interest in case bitfield message was already received before above handler was registered
|
|
this._updateWireInterest(wire)
|
|
|
|
// Send PORT message to peers that support DHT
|
|
if (wire.peerExtensions.dht && this.client.dht && this.client.dht.listening) {
|
|
wire.port(this.client.dht.address().port)
|
|
}
|
|
|
|
if (wire.type !== 'webSeed') { // do not choke on webseeds
|
|
timeoutId = setTimeout(onChokeTimeout, CHOKE_TIMEOUT)
|
|
if (timeoutId.unref) timeoutId.unref()
|
|
}
|
|
|
|
wire.isSeeder = false
|
|
updateSeedStatus()
|
|
}
|
|
|
|
/**
|
|
* Called on selection changes.
|
|
*/
|
|
_updateSelections () {
|
|
if (!this.ready || this.destroyed) return
|
|
|
|
queueMicrotask(() => {
|
|
this._gcSelections()
|
|
})
|
|
this._updateInterest()
|
|
this._update()
|
|
}
|
|
|
|
/**
|
|
* Garbage collect selections with respect to the store's current state.
|
|
*/
|
|
_gcSelections () {
|
|
for (let i = 0; i < this._selections.length; ++i) {
|
|
const s = this._selections[i]
|
|
const oldOffset = s.offset
|
|
|
|
// check for newly downloaded pieces in selection
|
|
while (this.bitfield.get(s.from + s.offset) && s.from + s.offset < s.to) {
|
|
s.offset += 1
|
|
}
|
|
|
|
if (oldOffset !== s.offset) s.notify()
|
|
if (s.to !== s.from + s.offset) continue
|
|
if (!this.bitfield.get(s.from + s.offset)) continue
|
|
|
|
this._selections.splice(i, 1) // remove fully downloaded selection
|
|
i -= 1 // decrement i to offset splice
|
|
|
|
s.notify()
|
|
this._updateInterest()
|
|
}
|
|
|
|
if (!this._selections.length) this.emit('idle')
|
|
}
|
|
|
|
/**
|
|
* Update interested status for all peers.
|
|
*/
|
|
_updateInterest () {
|
|
const prev = this._amInterested
|
|
this._amInterested = !!this._selections.length
|
|
|
|
this.wires.forEach(wire => this._updateWireInterest(wire))
|
|
|
|
if (prev === this._amInterested) return
|
|
if (this._amInterested) this.emit('interested')
|
|
else this.emit('uninterested')
|
|
}
|
|
|
|
_updateWireInterest (wire) {
|
|
let interested = false
|
|
for (let index = 0; index < this.pieces.length; ++index) {
|
|
if (this.pieces[index] && wire.peerPieces.get(index)) {
|
|
interested = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if (interested) wire.interested()
|
|
else wire.uninterested()
|
|
}
|
|
|
|
/**
|
|
* Heartbeat to update all peers and their requests.
|
|
*/
|
|
_update () {
|
|
if (this.destroyed) return
|
|
|
|
// update wires in random order for better request distribution
|
|
const ite = randomIterate(this.wires)
|
|
let wire
|
|
while ((wire = ite())) {
|
|
this._updateWireWrapper(wire)
|
|
}
|
|
}
|
|
|
|
_updateWireWrapper (wire) {
|
|
const self = this
|
|
|
|
if (typeof window !== 'undefined' && typeof window.requestIdleCallback === 'function') {
|
|
window.requestIdleCallback(() => { self._updateWire(wire) }, { timeout: 250 })
|
|
} else {
|
|
self._updateWire(wire)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attempts to update a peer's requests
|
|
*/
|
|
_updateWire (wire) {
|
|
// to allow function hoisting
|
|
const self = this
|
|
|
|
if (wire.peerChoking) return
|
|
if (!wire.downloaded) return validateWire()
|
|
|
|
const minOutstandingRequests = getBlockPipelineLength(wire, PIPELINE_MIN_DURATION)
|
|
if (wire.requests.length >= minOutstandingRequests) return
|
|
const maxOutstandingRequests = getBlockPipelineLength(wire, PIPELINE_MAX_DURATION)
|
|
|
|
trySelectWire(false) || trySelectWire(true)
|
|
|
|
function genPieceFilterFunc (start, end, tried, rank) {
|
|
return i => i >= start && i <= end && !(i in tried) && wire.peerPieces.get(i) && (!rank || rank(i))
|
|
}
|
|
|
|
// TODO: Do we need both validateWire and trySelectWire?
|
|
function validateWire () {
|
|
if (wire.requests.length) return
|
|
|
|
let i = self._selections.length
|
|
while (i--) {
|
|
const next = self._selections[i]
|
|
let piece
|
|
if (self.strategy === 'rarest') {
|
|
const start = next.from + next.offset
|
|
const end = next.to
|
|
const len = end - start + 1
|
|
const tried = {}
|
|
let tries = 0
|
|
const filter = genPieceFilterFunc(start, end, tried)
|
|
|
|
while (tries < len) {
|
|
piece = self._rarityMap.getRarestPiece(filter)
|
|
if (piece < 0) break
|
|
if (self._request(wire, piece, false)) return
|
|
tried[piece] = true
|
|
tries += 1
|
|
}
|
|
} else {
|
|
for (piece = next.to; piece >= next.from + next.offset; --piece) {
|
|
if (!wire.peerPieces.get(piece)) continue
|
|
if (self._request(wire, piece, false)) return
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: wire failed to validate as useful; should we close it?
|
|
// probably not, since 'have' and 'bitfield' messages might be coming
|
|
}
|
|
|
|
function speedRanker () {
|
|
const speed = wire.downloadSpeed() || 1
|
|
if (speed > SPEED_THRESHOLD) return () => true
|
|
|
|
const secs = Math.max(1, wire.requests.length) * Piece.BLOCK_LENGTH / speed
|
|
let tries = 10
|
|
let ptr = 0
|
|
|
|
return index => {
|
|
if (!tries || self.bitfield.get(index)) return true
|
|
|
|
let missing = self.pieces[index].missing
|
|
|
|
for (; ptr < self.wires.length; ptr++) {
|
|
const otherWire = self.wires[ptr]
|
|
const otherSpeed = otherWire.downloadSpeed()
|
|
|
|
if (otherSpeed < SPEED_THRESHOLD) continue
|
|
if (otherSpeed <= speed) continue
|
|
if (!otherWire.peerPieces.get(index)) continue
|
|
if ((missing -= otherSpeed * secs) > 0) continue
|
|
|
|
tries--
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
}
|
|
|
|
function shufflePriority (i) {
|
|
let last = i
|
|
for (let j = i; j < self._selections.length && self._selections[j].priority; j++) {
|
|
last = j
|
|
}
|
|
const tmp = self._selections[i]
|
|
self._selections[i] = self._selections[last]
|
|
self._selections[last] = tmp
|
|
}
|
|
|
|
function trySelectWire (hotswap) {
|
|
if (wire.requests.length >= maxOutstandingRequests) return true
|
|
const rank = speedRanker()
|
|
|
|
for (let i = 0; i < self._selections.length; i++) {
|
|
const next = self._selections[i]
|
|
|
|
let piece
|
|
if (self.strategy === 'rarest') {
|
|
const start = next.from + next.offset
|
|
const end = next.to
|
|
const len = end - start + 1
|
|
const tried = {}
|
|
let tries = 0
|
|
const filter = genPieceFilterFunc(start, end, tried, rank)
|
|
|
|
while (tries < len) {
|
|
piece = self._rarityMap.getRarestPiece(filter)
|
|
if (piece < 0) break
|
|
|
|
while (self._request(wire, piece, self._critical[piece] || hotswap)) {
|
|
// body intentionally empty
|
|
// request all non-reserved blocks in this piece
|
|
}
|
|
|
|
if (wire.requests.length < maxOutstandingRequests) {
|
|
tried[piece] = true
|
|
tries++
|
|
continue
|
|
}
|
|
|
|
if (next.priority) shufflePriority(i)
|
|
return true
|
|
}
|
|
} else {
|
|
for (piece = next.from + next.offset; piece <= next.to; piece++) {
|
|
if (!wire.peerPieces.get(piece) || !rank(piece)) continue
|
|
|
|
while (self._request(wire, piece, self._critical[piece] || hotswap)) {
|
|
// body intentionally empty
|
|
// request all non-reserved blocks in piece
|
|
}
|
|
|
|
if (wire.requests.length < maxOutstandingRequests) continue
|
|
|
|
if (next.priority) shufflePriority(i)
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called periodically to update the choked status of all peers, handling optimistic
|
|
* unchoking as described in BEP3.
|
|
*/
|
|
_rechoke () {
|
|
if (!this.ready) return
|
|
|
|
// wires in increasing order of quality (pop() gives next best peer)
|
|
const wireStack =
|
|
this.wires
|
|
.map(wire => ({ wire, random: Math.random() })) // insert a random seed for randomizing the sort
|
|
.sort((objA, objB) => {
|
|
const wireA = objA.wire
|
|
const wireB = objB.wire
|
|
|
|
// prefer peers that send us data faster
|
|
if (wireA.downloadSpeed() !== wireB.downloadSpeed()) {
|
|
return wireA.downloadSpeed() - wireB.downloadSpeed()
|
|
}
|
|
|
|
// then prefer peers that can download data from us faster
|
|
if (wireA.uploadSpeed() !== wireB.uploadSpeed()) {
|
|
return wireA.uploadSpeed() - wireB.uploadSpeed()
|
|
}
|
|
|
|
// then prefer already unchoked peers (to minimize fibrillation)
|
|
if (wireA.amChoking !== wireB.amChoking) {
|
|
return wireA.amChoking ? -1 : 1 // choking < unchoked
|
|
}
|
|
|
|
// otherwise random order
|
|
return objA.random - objB.random
|
|
})
|
|
.map(obj => obj.wire) // return array of wires (remove random seed)
|
|
|
|
if (this._rechokeOptimisticTime <= 0) {
|
|
// clear old optimistic peer, so it can be rechoked normally and then replaced
|
|
this._rechokeOptimisticWire = null
|
|
} else {
|
|
this._rechokeOptimisticTime -= 1
|
|
}
|
|
|
|
let numInterestedUnchoked = 0
|
|
// leave one rechoke slot open for optimistic unchoking
|
|
while (wireStack.length > 0 && numInterestedUnchoked < this._rechokeNumSlots - 1) {
|
|
const wire = wireStack.pop() // next best quality peer
|
|
|
|
if (wire.isSeeder || wire === this._rechokeOptimisticWire) {
|
|
continue
|
|
}
|
|
|
|
wire.unchoke()
|
|
|
|
// only stop unchoking once we fill the slots with interested peers that will actually download
|
|
if (wire.peerInterested) {
|
|
numInterestedUnchoked++
|
|
}
|
|
}
|
|
|
|
// fill optimistic unchoke slot if empty
|
|
if (this._rechokeOptimisticWire === null && this._rechokeNumSlots > 0) {
|
|
// don't optimistically unchoke uninterested peers
|
|
const remaining = wireStack.filter(wire => wire.peerInterested)
|
|
|
|
if (remaining.length > 0) {
|
|
// select random remaining (not yet unchoked) peer
|
|
const newOptimisticPeer = remaining[randomInt(remaining.length)]
|
|
|
|
newOptimisticPeer.unchoke()
|
|
|
|
this._rechokeOptimisticWire = newOptimisticPeer
|
|
|
|
this._rechokeOptimisticTime = RECHOKE_OPTIMISTIC_DURATION
|
|
}
|
|
}
|
|
|
|
// choke the rest
|
|
wireStack
|
|
.filter(wire => wire !== this._rechokeOptimisticWire) // except the optimistically unchoked peer
|
|
.forEach(wire => wire.choke())
|
|
}
|
|
|
|
/**
|
|
* Attempts to cancel a slow block request from another wire such that the
|
|
* given wire may effectively swap out the request for one of its own.
|
|
*/
|
|
_hotswap (wire, index) {
|
|
const speed = wire.downloadSpeed()
|
|
if (speed < Piece.BLOCK_LENGTH) return false
|
|
if (!this._reservations[index]) return false
|
|
|
|
const r = this._reservations[index]
|
|
if (!r) {
|
|
return false
|
|
}
|
|
|
|
let minSpeed = Infinity
|
|
let minWire
|
|
|
|
let i
|
|
for (i = 0; i < r.length; i++) {
|
|
const otherWire = r[i]
|
|
if (!otherWire || otherWire === wire) continue
|
|
|
|
const otherSpeed = otherWire.downloadSpeed()
|
|
if (otherSpeed >= SPEED_THRESHOLD) continue
|
|
if (2 * otherSpeed > speed || otherSpeed > minSpeed) continue
|
|
|
|
minWire = otherWire
|
|
minSpeed = otherSpeed
|
|
}
|
|
|
|
if (!minWire) return false
|
|
|
|
for (i = 0; i < r.length; i++) {
|
|
if (r[i] === minWire) r[i] = null
|
|
}
|
|
|
|
for (i = 0; i < minWire.requests.length; i++) {
|
|
const req = minWire.requests[i]
|
|
if (req.piece !== index) continue
|
|
|
|
this.pieces[index].cancel((req.offset / Piece.BLOCK_LENGTH) | 0)
|
|
}
|
|
|
|
this.emit('hotswap', minWire, wire, index)
|
|
return true
|
|
}
|
|
|
|
/**
|
|
* Attempts to request a block from the given wire.
|
|
*/
|
|
_request (wire, index, hotswap) {
|
|
const self = this
|
|
const numRequests = wire.requests.length
|
|
const isWebSeed = wire.type === 'webSeed'
|
|
|
|
if (self.bitfield.get(index)) return false
|
|
|
|
const maxOutstandingRequests = isWebSeed
|
|
? Math.min(
|
|
getPiecePipelineLength(wire, PIPELINE_MAX_DURATION, self.pieceLength),
|
|
self.maxWebConns
|
|
)
|
|
: getBlockPipelineLength(wire, PIPELINE_MAX_DURATION)
|
|
|
|
if (numRequests >= maxOutstandingRequests) return false
|
|
// var endGame = (wire.requests.length === 0 && self.store.numMissing < 30)
|
|
|
|
const piece = self.pieces[index]
|
|
let reservation = isWebSeed ? piece.reserveRemaining() : piece.reserve()
|
|
|
|
if (reservation === -1 && hotswap && self._hotswap(wire, index)) {
|
|
reservation = isWebSeed ? piece.reserveRemaining() : piece.reserve()
|
|
}
|
|
if (reservation === -1) return false
|
|
|
|
let r = self._reservations[index]
|
|
if (!r) r = self._reservations[index] = []
|
|
let i = r.indexOf(null)
|
|
if (i === -1) i = r.length
|
|
r[i] = wire
|
|
|
|
const chunkOffset = piece.chunkOffset(reservation)
|
|
const chunkLength = isWebSeed ? piece.chunkLengthRemaining(reservation) : piece.chunkLength(reservation)
|
|
|
|
wire.request(index, chunkOffset, chunkLength, function onChunk (err, chunk) {
|
|
if (self.destroyed) return
|
|
|
|
// TODO: what is this for?
|
|
if (!self.ready) return self.once('ready', () => { onChunk(err, chunk) })
|
|
|
|
if (r[i] === wire) r[i] = null
|
|
|
|
if (piece !== self.pieces[index]) return onUpdateTick()
|
|
|
|
if (err) {
|
|
self._debug(
|
|
'error getting piece %s (offset: %s length: %s) from %s: %s',
|
|
index, chunkOffset, chunkLength, `${wire.remoteAddress}:${wire.remotePort}`,
|
|
err.message
|
|
)
|
|
isWebSeed ? piece.cancelRemaining(reservation) : piece.cancel(reservation)
|
|
onUpdateTick()
|
|
return
|
|
}
|
|
|
|
self._debug(
|
|
'got piece %s (offset: %s length: %s) from %s',
|
|
index, chunkOffset, chunkLength, `${wire.remoteAddress}:${wire.remotePort}`
|
|
)
|
|
|
|
if (!piece.set(reservation, chunk, wire)) return onUpdateTick()
|
|
|
|
const buf = piece.flush()
|
|
|
|
// TODO: might need to set self.pieces[index] = null here since sha1 is async
|
|
|
|
sha1(buf, hash => {
|
|
if (self.destroyed) return
|
|
|
|
if (hash === self._hashes[index]) {
|
|
self._debug('piece verified %s', index)
|
|
|
|
self.store.put(index, buf, err => {
|
|
if (err) {
|
|
self._destroy(err)
|
|
return
|
|
} else {
|
|
self.pieces[index] = null
|
|
self._markVerified(index)
|
|
self.wires.forEach(wire => {
|
|
wire.have(index)
|
|
})
|
|
}
|
|
// We also check `self.destroyed` since `torrent.destroy()` could have been
|
|
// called in the `torrent.on('done')` handler, triggered by `_checkDone()`.
|
|
if (self._checkDone() && !self.destroyed) self.discovery.complete()
|
|
onUpdateTick()
|
|
})
|
|
} else {
|
|
self.pieces[index] = new Piece(piece.length)
|
|
self.emit('warning', new Error(`Piece ${index} failed verification`))
|
|
onUpdateTick()
|
|
}
|
|
})
|
|
})
|
|
|
|
function onUpdateTick () {
|
|
queueMicrotask(() => { self._update() })
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
_checkDone () {
|
|
if (this.destroyed) return
|
|
|
|
// are any new files done?
|
|
this.files.forEach(file => {
|
|
if (file.done) return
|
|
for (let i = file._startPiece; i <= file._endPiece; ++i) {
|
|
if (!this.bitfield.get(i)) return
|
|
}
|
|
file.done = true
|
|
file.emit('done')
|
|
this._debug(`file done: ${file.name}`)
|
|
})
|
|
|
|
// is the torrent done? (if all current selections are satisfied, or there are
|
|
// no selections, then torrent is done)
|
|
let done = true
|
|
|
|
for (const selection of this._selections) {
|
|
for (let piece = selection.from; piece <= selection.to; piece++) {
|
|
if (!this.bitfield.get(piece)) {
|
|
done = false
|
|
break
|
|
}
|
|
}
|
|
if (!done) break
|
|
}
|
|
|
|
if (!this.done && done) {
|
|
this.done = true
|
|
this._debug(`torrent done: ${this.infoHash}`)
|
|
this.emit('done')
|
|
}
|
|
this._gcSelections()
|
|
|
|
return done
|
|
}
|
|
|
|
load (streams, cb) {
|
|
if (this.destroyed) throw new Error('torrent is destroyed')
|
|
if (!this.ready) return this.once('ready', () => { this.load(streams, cb) })
|
|
|
|
if (!Array.isArray(streams)) streams = [streams]
|
|
if (!cb) cb = noop
|
|
|
|
const readable = new MultiStream(streams)
|
|
const writable = new ChunkStoreWriteStream(this.store, this.pieceLength)
|
|
|
|
pump(readable, writable, err => {
|
|
if (err) return cb(err)
|
|
this._markAllVerified()
|
|
this._checkDone()
|
|
cb(null)
|
|
})
|
|
}
|
|
|
|
createServer (requestListener) {
|
|
if (typeof Server !== 'function') throw new Error('node.js-only method')
|
|
if (this.destroyed) throw new Error('torrent is destroyed')
|
|
const server = new Server(this, requestListener)
|
|
this._servers.push(server)
|
|
return server
|
|
}
|
|
|
|
pause () {
|
|
if (this.destroyed) return
|
|
this._debug('pause')
|
|
this.paused = true
|
|
}
|
|
|
|
resume () {
|
|
if (this.destroyed) return
|
|
this._debug('resume')
|
|
this.paused = false
|
|
this._drain()
|
|
}
|
|
|
|
_debug () {
|
|
const args = [].slice.call(arguments)
|
|
args[0] = `[${this.client ? this.client._debugId : 'No Client'}] [${this._debugId}] ${args[0]}`
|
|
debug(...args)
|
|
}
|
|
|
|
/**
|
|
* Pop a peer off the FIFO queue and connect to it. When _drain() gets called,
|
|
* the queue will usually have only one peer in it, except when there are too
|
|
* many peers (over `this.maxConns`) in which case they will just sit in the
|
|
* queue until another connection closes.
|
|
*/
|
|
_drain () {
|
|
this._debug('_drain numConns %s maxConns %s', this._numConns, this.client.maxConns)
|
|
if (typeof net.connect !== 'function' || this.destroyed || this.paused ||
|
|
this._numConns >= this.client.maxConns) {
|
|
return
|
|
}
|
|
this._debug('drain (%s queued, %s/%s peers)', this._numQueued, this.numPeers, this.client.maxConns)
|
|
|
|
const peer = this._queue.shift()
|
|
if (!peer) return // queue could be empty
|
|
|
|
this._debug('%s connect attempt to %s', peer.type, peer.addr)
|
|
|
|
const parts = addrToIPPort(peer.addr)
|
|
const opts = {
|
|
host: parts[0],
|
|
port: parts[1]
|
|
}
|
|
|
|
if (this.client.utp && peer.type === 'utpOutgoing') {
|
|
peer.conn = utp.connect(opts.port, opts.host)
|
|
} else {
|
|
peer.conn = net.connect(opts)
|
|
}
|
|
|
|
const conn = peer.conn
|
|
|
|
conn.once('connect', () => { peer.onConnect() })
|
|
conn.once('error', err => { peer.destroy(err) })
|
|
peer.startConnectTimeout()
|
|
|
|
// When connection closes, attempt reconnect after timeout (with exponential backoff)
|
|
conn.on('close', () => {
|
|
if (this.destroyed) return
|
|
|
|
if (peer.retries >= RECONNECT_WAIT.length) {
|
|
if (this.client.utp) {
|
|
const newPeer = this._addPeer(peer.addr, 'tcp')
|
|
if (newPeer) newPeer.retries = 0
|
|
} else {
|
|
this._debug(
|
|
'conn %s closed: will not re-add (max %s attempts)',
|
|
peer.addr, RECONNECT_WAIT.length
|
|
)
|
|
}
|
|
return
|
|
}
|
|
|
|
const ms = RECONNECT_WAIT[peer.retries]
|
|
this._debug(
|
|
'conn %s closed: will re-add to queue in %sms (attempt %s)',
|
|
peer.addr, ms, peer.retries + 1
|
|
)
|
|
|
|
const reconnectTimeout = setTimeout(() => {
|
|
if (this.destroyed) return
|
|
const host = addrToIPPort(peer.addr)[0]
|
|
const type = (this.client.utp && this._isIPv4(host)) ? 'utp' : 'tcp'
|
|
const newPeer = this._addPeer(peer.addr, type)
|
|
if (newPeer) newPeer.retries = peer.retries + 1
|
|
}, ms)
|
|
if (reconnectTimeout.unref) reconnectTimeout.unref()
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Returns `true` if string is valid IPv4/6 address.
|
|
* @param {string} addr
|
|
* @return {boolean}
|
|
*/
|
|
_validAddr (addr) {
|
|
let parts
|
|
try {
|
|
parts = addrToIPPort(addr)
|
|
} catch (e) {
|
|
return false
|
|
}
|
|
const host = parts[0]
|
|
const port = parts[1]
|
|
return port > 0 && port < 65535 &&
|
|
!(host === '127.0.0.1' && port === this.client.torrentPort)
|
|
}
|
|
|
|
/**
|
|
* Return `true` if string is a valid IPv4 address.
|
|
* @param {string} addr
|
|
* @return {boolean}
|
|
*/
|
|
_isIPv4 (addr) {
|
|
const IPv4Pattern = /^((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/
|
|
return IPv4Pattern.test(addr)
|
|
}
|
|
}
|
|
|
|
function getBlockPipelineLength (wire, duration) {
|
|
return 2 + Math.ceil(duration * wire.downloadSpeed() / Piece.BLOCK_LENGTH)
|
|
}
|
|
|
|
function getPiecePipelineLength (wire, duration, pieceLength) {
|
|
return 1 + Math.ceil(duration * wire.downloadSpeed() / pieceLength)
|
|
}
|
|
|
|
/**
|
|
* Returns a random integer in [0,high)
|
|
*/
|
|
function randomInt (high) {
|
|
return Math.random() * high | 0
|
|
}
|
|
|
|
function noop () {}
|
|
|
|
module.exports = Torrent
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webtorrent/lib/webconn.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/webtorrent/lib/webconn.js ***!
|
|
\************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modules/buffer/index.js */ "./node_modules/buffer/index.js")["Buffer"];
|
|
const BitField = __webpack_require__(/*! bitfield */ "./node_modules/bitfield/lib/index.js").default
|
|
const debug = __webpack_require__(/*! debug */ "./node_modules/debug/src/browser.js")('webtorrent:webconn')
|
|
const get = __webpack_require__(/*! simple-get */ "./node_modules/simple-get/index.js")
|
|
const ltDontHave = __webpack_require__(/*! lt_donthave */ "./node_modules/lt_donthave/index.js")
|
|
const sha1 = __webpack_require__(/*! simple-sha1 */ "./node_modules/simple-sha1/browser.js")
|
|
const Wire = __webpack_require__(/*! bittorrent-protocol */ "./node_modules/bittorrent-protocol/index.js")
|
|
|
|
const VERSION = __webpack_require__(/*! ../package.json */ "./node_modules/webtorrent/package.json").version
|
|
|
|
const SOCKET_TIMEOUT = 60000
|
|
const RETRY_DELAY = 10000
|
|
|
|
/**
|
|
* Converts requests for torrent blocks into http range requests.
|
|
* @param {string} url web seed url
|
|
* @param {Object} torrent
|
|
*/
|
|
class WebConn extends Wire {
|
|
constructor (url, torrent) {
|
|
super()
|
|
|
|
this.url = url
|
|
this.connId = url // Unique id to deduplicate web seeds
|
|
this.webPeerId = sha1.sync(url) // Used as the peerId for this fake remote peer
|
|
this._torrent = torrent
|
|
|
|
this._init()
|
|
}
|
|
|
|
_init () {
|
|
this.setKeepAlive(true)
|
|
|
|
this.use(ltDontHave())
|
|
|
|
this.once('handshake', (infoHash, peerId) => {
|
|
if (this.destroyed) return
|
|
this.handshake(infoHash, this.webPeerId)
|
|
const numPieces = this._torrent.pieces.length
|
|
const bitfield = new BitField(numPieces)
|
|
for (let i = 0; i <= numPieces; i++) {
|
|
bitfield.set(i, true)
|
|
}
|
|
this.bitfield(bitfield)
|
|
})
|
|
|
|
this.once('interested', () => {
|
|
debug('interested')
|
|
this.unchoke()
|
|
})
|
|
|
|
this.on('uninterested', () => { debug('uninterested') })
|
|
this.on('choke', () => { debug('choke') })
|
|
this.on('unchoke', () => { debug('unchoke') })
|
|
this.on('bitfield', () => { debug('bitfield') })
|
|
this.lt_donthave.on('donthave', () => { debug('donthave') })
|
|
|
|
this.on('request', (pieceIndex, offset, length, callback) => {
|
|
debug('request pieceIndex=%d offset=%d length=%d', pieceIndex, offset, length)
|
|
this.httpRequest(pieceIndex, offset, length, (err, data) => {
|
|
if (err) {
|
|
// Cancel all in progress requests for this piece
|
|
this.lt_donthave.donthave(pieceIndex)
|
|
|
|
// Wait a little while before saying the webseed has the failed piece again
|
|
const retryTimeout = setTimeout(() => {
|
|
if (this.destroyed) return
|
|
|
|
this.have(pieceIndex)
|
|
}, RETRY_DELAY)
|
|
if (retryTimeout.unref) retryTimeout.unref()
|
|
}
|
|
|
|
callback(err, data)
|
|
})
|
|
})
|
|
}
|
|
|
|
httpRequest (pieceIndex, offset, length, cb) {
|
|
const pieceOffset = pieceIndex * this._torrent.pieceLength
|
|
const rangeStart = pieceOffset + offset /* offset within whole torrent */
|
|
const rangeEnd = rangeStart + length - 1
|
|
|
|
// Web seed URL format:
|
|
// For single-file torrents, make HTTP range requests directly to the web seed URL
|
|
// For multi-file torrents, add the torrent folder and file name to the URL
|
|
const files = this._torrent.files
|
|
let requests
|
|
if (files.length <= 1) {
|
|
requests = [{
|
|
url: this.url,
|
|
start: rangeStart,
|
|
end: rangeEnd
|
|
}]
|
|
} else {
|
|
const requestedFiles = files.filter(file => file.offset <= rangeEnd && (file.offset + file.length) > rangeStart)
|
|
if (requestedFiles.length < 1) {
|
|
return cb(new Error('Could not find file corresponding to web seed range request'))
|
|
}
|
|
|
|
requests = requestedFiles.map(requestedFile => {
|
|
const fileEnd = requestedFile.offset + requestedFile.length - 1
|
|
const url = this.url +
|
|
(this.url[this.url.length - 1] === '/' ? '' : '/') +
|
|
requestedFile.path
|
|
return {
|
|
url,
|
|
fileOffsetInRange: Math.max(requestedFile.offset - rangeStart, 0),
|
|
start: Math.max(rangeStart - requestedFile.offset, 0),
|
|
end: Math.min(fileEnd, rangeEnd - requestedFile.offset)
|
|
}
|
|
})
|
|
}
|
|
|
|
// Now make all the HTTP requests we need in order to load this piece
|
|
// Usually that's one requests, but sometimes it will be multiple
|
|
// Send requests in parallel and wait for them all to come back
|
|
let numRequestsSucceeded = 0
|
|
let hasError = false
|
|
|
|
let ret
|
|
if (requests.length > 1) {
|
|
ret = Buffer.alloc(length)
|
|
}
|
|
|
|
requests.forEach(request => {
|
|
const url = request.url
|
|
const start = request.start
|
|
const end = request.end
|
|
debug(
|
|
'Requesting url=%s pieceIndex=%d offset=%d length=%d start=%d end=%d',
|
|
url, pieceIndex, offset, length, start, end
|
|
)
|
|
const opts = {
|
|
url,
|
|
method: 'GET',
|
|
headers: {
|
|
'user-agent': `WebTorrent/${VERSION} (https://webtorrent.io)`,
|
|
range: `bytes=${start}-${end}`
|
|
},
|
|
timeout: SOCKET_TIMEOUT
|
|
}
|
|
function onResponse (res, data) {
|
|
if (res.statusCode < 200 || res.statusCode >= 300) {
|
|
if (hasError) return
|
|
hasError = true
|
|
return cb(new Error(`Unexpected HTTP status code ${res.statusCode}`))
|
|
}
|
|
debug('Got data of length %d', data.length)
|
|
|
|
if (requests.length === 1) {
|
|
// Common case: fetch piece in a single HTTP request, return directly
|
|
cb(null, data)
|
|
} else {
|
|
// Rare case: reconstruct multiple HTTP requests across 2+ files into one
|
|
// piece buffer
|
|
data.copy(ret, request.fileOffsetInRange)
|
|
if (++numRequestsSucceeded === requests.length) {
|
|
cb(null, ret)
|
|
}
|
|
}
|
|
}
|
|
get.concat(opts, (err, res, data) => {
|
|
if (hasError) return
|
|
if (err) {
|
|
// Browsers allow HTTP redirects for simple cross-origin
|
|
// requests but not for requests that require preflight.
|
|
// Use a simple request to unravel any redirects and get the
|
|
// final URL. Retry the original request with the new URL if
|
|
// it's different.
|
|
//
|
|
// This test is imperfect but it's simple and good for common
|
|
// cases. It catches all cross-origin cases but matches a few
|
|
// same-origin cases too.
|
|
if (typeof window === 'undefined' || url.startsWith(`${window.location.origin}/`)) {
|
|
hasError = true
|
|
return cb(err)
|
|
}
|
|
|
|
return get.head(url, (errHead, res) => {
|
|
if (hasError) return
|
|
if (errHead) {
|
|
hasError = true
|
|
return cb(errHead)
|
|
}
|
|
if (res.statusCode < 200 || res.statusCode >= 300) {
|
|
hasError = true
|
|
return cb(new Error(`Unexpected HTTP status code ${res.statusCode}`))
|
|
}
|
|
if (res.url === url) {
|
|
hasError = true
|
|
return cb(err)
|
|
}
|
|
|
|
opts.url = res.url
|
|
get.concat(opts, (err, res, data) => {
|
|
if (hasError) return
|
|
if (err) {
|
|
hasError = true
|
|
return cb(err)
|
|
}
|
|
onResponse(res, data)
|
|
})
|
|
})
|
|
}
|
|
onResponse(res, data)
|
|
})
|
|
})
|
|
}
|
|
|
|
destroy () {
|
|
super.destroy()
|
|
this._torrent = null
|
|
}
|
|
}
|
|
|
|
module.exports = WebConn
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webtorrent/package.json":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/webtorrent/package.json ***!
|
|
\**********************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = JSON.parse('{"name":"webtorrent","description":"Streaming torrent client","version":"1.3.3","author":{"name":"WebTorrent LLC","email":"feross@webtorrent.io","url":"https://webtorrent.io"},"browser":{"./lib/server.js":false,"./lib/conn-pool.js":false,"./lib/utp.js":false,"bittorrent-dht/client":false,"fs":false,"fs-chunk-store":"memory-chunk-store","load-ip-set":false,"net":false,"os":false,"ut_pex":false},"browserify":{"transform":["package-json-versionify"]},"bugs":{"url":"https://github.com/webtorrent/webtorrent/issues"},"chromeapp":{"./lib/utp.js":false,"fs-chunk-store":"memory-chunk-store","http":"http-node","load-ip-set":false,"net":"chrome-net","os":false},"dependencies":{"addr-to-ip-port":"^1.5.1","bitfield":"^4.0.0","bittorrent-dht":"^10.0.1","bittorrent-protocol":"^3.4.2","cache-chunk-store":"^3.2.2","chrome-net":"^3.3.4","chunk-store-stream":"^4.3.0","cpus":"^1.0.3","create-torrent":"^4.7.1","debug":"^4.3.2","end-of-stream":"^1.4.4","escape-html":"^1.0.3","fs-chunk-store":"^2.0.3","http-node":"github:feross/http-node#webtorrent","immediate-chunk-store":"^2.2.0","load-ip-set":"^2.2.1","lt_donthave":"^1.0.1","memory-chunk-store":"^1.3.5","mime":"^2.5.2","multistream":"^4.1.0","package-json-versionify":"^1.0.4","parse-torrent":"^9.1.3","pump":"^3.0.0","queue-microtask":"^1.2.3","random-iterate":"^1.0.1","randombytes":"^2.1.0","range-parser":"^1.2.1","readable-stream":"^3.6.0","render-media":"^4.1.0","run-parallel":"^1.2.0","run-parallel-limit":"^1.1.0","simple-concat":"^1.0.1","simple-get":"^4.0.0","simple-peer":"^9.11.0","simple-sha1":"^3.1.0","speed-limiter":"^1.0.2","speedometer":"^1.1.0","stream-to-blob":"^2.0.1","stream-to-blob-url":"^3.0.2","stream-with-known-length-to-buffer":"^1.0.4","torrent-discovery":"^9.4.0","torrent-piece":"^2.0.1","unordered-array-remove":"^1.0.2","ut_metadata":"^3.5.2","ut_pex":"^3.0.1"},"devDependencies":{"@webtorrent/semantic-release-config":"1.0.5","airtap":"4.0.3","airtap-manual":"1.0.0","airtap-sauce":"1.1.2","babel-minify":"0.5.1","bittorrent-tracker":"9.17.4","browserify":"17.0.0","disc":"1.3.3","finalhandler":"1.1.2","network-address":"1.1.2","run-series":"1.1.9","semantic-release":"17.4.4","serve-static":"1.14.1","standard":"*","tape":"5.2.2","webtorrent-fixtures":"1.7.3"},"optionalDependencies":{"utp-native":"^2.5.3"},"engines":{"node":">=12"},"funding":[{"type":"github","url":"https://github.com/sponsors/feross"},{"type":"patreon","url":"https://www.patreon.com/feross"},{"type":"consulting","url":"https://feross.org/support"}],"homepage":"https://webtorrent.io","keywords":["bittorrent","bittorrent client","download","mad science","p2p","peer-to-peer","peers","streaming","swarm","torrent","web torrent","webrtc","webrtc data","webtorrent"],"license":"MIT","main":"index.js","repository":{"type":"git","url":"git://github.com/webtorrent/webtorrent.git"},"scripts":{"build":"npm run build-js && npm run build-chromeapp","build-chromeapp":"browserify --browser-field=chromeapp --standalone WebTorrent . | minify --mangle=false > webtorrent.chromeapp.js","build-chromeapp-debug":"browserify --browser-field=chromeapp --standalone WebTorrent . > webtorrent.chromeapp.js","build-js":"browserify --standalone WebTorrent . | minify --mangle=false > webtorrent.min.js","build-js-debug":"browserify --standalone WebTorrent . > webtorrent.debug.js","prepublishOnly":"npm run build && npm run update-authors","preversion":"npm run build && npm run update-authors","size":"npm run size-js && npm run size-disc","size-disc":"browserify --full-paths . | discify --open","size-js":"npm run build && cat webtorrent.min.js | gzip | wc -c","test":"standard && npm run test-node && npm run test-browser","test-browser":"airtap --concurrency 1 -- test/*.js test/browser/*.js","test-browser-local":"airtap --preset local -- test/*.js test/browser/*.js","test-node":"tape test/*.js test/node/*.js","update-authors":"./scripts/update-authors.sh"},"standard":{"ignore":["webtorrent.min.js","webtorrent.chromeapp.js"]},"renovate":{"extends":["github>webtorrent/renovate-config"],"lockFileMaintenance":{"enabled":false},"rangeStrategy":"bump"},"release":{"extends":"@webtorrent/semantic-release-config"}}');
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/which-typed-array/index.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/which-typed-array/index.js ***!
|
|
\*************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
var forEach = __webpack_require__(/*! foreach */ "./node_modules/foreach/index.js");
|
|
var availableTypedArrays = __webpack_require__(/*! available-typed-arrays */ "./node_modules/available-typed-arrays/index.js");
|
|
var callBound = __webpack_require__(/*! call-bind/callBound */ "./node_modules/call-bind/callBound.js");
|
|
|
|
var $toString = callBound('Object.prototype.toString');
|
|
var hasSymbols = __webpack_require__(/*! has-symbols */ "./node_modules/has-symbols/index.js")();
|
|
var hasToStringTag = hasSymbols && typeof Symbol.toStringTag === 'symbol';
|
|
|
|
var typedArrays = availableTypedArrays();
|
|
|
|
var $slice = callBound('String.prototype.slice');
|
|
var toStrTags = {};
|
|
var gOPD = __webpack_require__(/*! es-abstract/helpers/getOwnPropertyDescriptor */ "./node_modules/es-abstract/helpers/getOwnPropertyDescriptor.js");
|
|
var getPrototypeOf = Object.getPrototypeOf; // require('getprototypeof');
|
|
if (hasToStringTag && gOPD && getPrototypeOf) {
|
|
forEach(typedArrays, function (typedArray) {
|
|
if (typeof __webpack_require__.g[typedArray] === 'function') {
|
|
var arr = new __webpack_require__.g[typedArray]();
|
|
if (!(Symbol.toStringTag in arr)) {
|
|
throw new EvalError('this engine has support for Symbol.toStringTag, but ' + typedArray + ' does not have the property! Please report this.');
|
|
}
|
|
var proto = getPrototypeOf(arr);
|
|
var descriptor = gOPD(proto, Symbol.toStringTag);
|
|
if (!descriptor) {
|
|
var superProto = getPrototypeOf(proto);
|
|
descriptor = gOPD(superProto, Symbol.toStringTag);
|
|
}
|
|
toStrTags[typedArray] = descriptor.get;
|
|
}
|
|
});
|
|
}
|
|
|
|
var tryTypedArrays = function tryAllTypedArrays(value) {
|
|
var foundName = false;
|
|
forEach(toStrTags, function (getter, typedArray) {
|
|
if (!foundName) {
|
|
try {
|
|
var name = getter.call(value);
|
|
if (name === typedArray) {
|
|
foundName = name;
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
});
|
|
return foundName;
|
|
};
|
|
|
|
var isTypedArray = __webpack_require__(/*! is-typed-array */ "./node_modules/is-typed-array/index.js");
|
|
|
|
module.exports = function whichTypedArray(value) {
|
|
if (!isTypedArray(value)) { return false; }
|
|
if (!hasToStringTag) { return $slice($toString(value), 8, -1); }
|
|
return tryTypedArrays(value);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/wrappy/wrappy.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/wrappy/wrappy.js ***!
|
|
\***************************************/
|
|
/***/ ((module) => {
|
|
|
|
// Returns a wrapper function that returns a wrapped callback
|
|
// The wrapper function should do some stuff, and return a
|
|
// presumably different callback function.
|
|
// This makes sure that own properties are retained, so that
|
|
// decorations and such are not lost along the way.
|
|
module.exports = wrappy
|
|
function wrappy (fn, cb) {
|
|
if (fn && cb) return wrappy(fn)(cb)
|
|
|
|
if (typeof fn !== 'function')
|
|
throw new TypeError('need wrapper function')
|
|
|
|
Object.keys(fn).forEach(function (k) {
|
|
wrapper[k] = fn[k]
|
|
})
|
|
|
|
return wrapper
|
|
|
|
function wrapper() {
|
|
var args = new Array(arguments.length)
|
|
for (var i = 0; i < args.length; i++) {
|
|
args[i] = arguments[i]
|
|
}
|
|
var ret = fn.apply(this, args)
|
|
var cb = args[args.length-1]
|
|
if (typeof ret === 'function' && ret !== cb) {
|
|
Object.keys(cb).forEach(function (k) {
|
|
ret[k] = cb[k]
|
|
})
|
|
}
|
|
return ret
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/xtend/immutable.js":
|
|
/*!*****************************************!*\
|
|
!*** ./node_modules/xtend/immutable.js ***!
|
|
\*****************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = extend
|
|
|
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
|
|
function extend() {
|
|
var target = {}
|
|
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
var source = arguments[i]
|
|
|
|
for (var key in source) {
|
|
if (hasOwnProperty.call(source, key)) {
|
|
target[key] = source[key]
|
|
}
|
|
}
|
|
}
|
|
|
|
return target
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "anitomyscript":
|
|
/*!********************************!*\
|
|
!*** external "anitomyscript" ***!
|
|
\********************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = anitomyscript;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "halfmoon":
|
|
/*!***************************!*\
|
|
!*** external "halfmoon" ***!
|
|
\***************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = halfmoon;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?d546":
|
|
/*!************************!*\
|
|
!*** buffer (ignored) ***!
|
|
\************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?5a06":
|
|
/*!*******************************!*\
|
|
!*** ./common-node (ignored) ***!
|
|
\*******************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?ed7a":
|
|
/*!*******************************************!*\
|
|
!*** ./lib/client/http-tracker (ignored) ***!
|
|
\*******************************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?5c78":
|
|
/*!******************************************!*\
|
|
!*** ./lib/client/udp-tracker (ignored) ***!
|
|
\******************************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?8131":
|
|
/*!************************!*\
|
|
!*** buffer (ignored) ***!
|
|
\************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?3fc0":
|
|
/*!************************!*\
|
|
!*** crypto (ignored) ***!
|
|
\************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?4068":
|
|
/*!************************!*\
|
|
!*** buffer (ignored) ***!
|
|
\************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?3b18":
|
|
/*!*****************************!*\
|
|
!*** ./get-files (ignored) ***!
|
|
\*****************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?f12c":
|
|
/*!*************************!*\
|
|
!*** is-file (ignored) ***!
|
|
\*************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?e7e4":
|
|
/*!************************!*\
|
|
!*** buffer (ignored) ***!
|
|
\************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?7bec":
|
|
/*!************************!*\
|
|
!*** buffer (ignored) ***!
|
|
\************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?0aec":
|
|
/*!************************!*\
|
|
!*** buffer (ignored) ***!
|
|
\************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?8539":
|
|
/*!********************!*\
|
|
!*** fs (ignored) ***!
|
|
\********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?fbf1":
|
|
/*!************************!*\
|
|
!*** buffer (ignored) ***!
|
|
\************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?7874":
|
|
/*!********************!*\
|
|
!*** fs (ignored) ***!
|
|
\********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?ed1b":
|
|
/*!**********************!*\
|
|
!*** util (ignored) ***!
|
|
\**********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?d17e":
|
|
/*!**********************!*\
|
|
!*** util (ignored) ***!
|
|
\**********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?45bd":
|
|
/*!*************************************!*\
|
|
!*** decompress-response (ignored) ***!
|
|
\*************************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?c33b":
|
|
/*!********************!*\
|
|
!*** ws (ignored) ***!
|
|
\********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?42e5":
|
|
/*!***************************************!*\
|
|
!*** bittorrent-dht/client (ignored) ***!
|
|
\***************************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?72f0":
|
|
/*!********************************!*\
|
|
!*** bittorrent-lsd (ignored) ***!
|
|
\********************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?ea49":
|
|
/*!**************************!*\
|
|
!*** ./server (ignored) ***!
|
|
\**************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?d41a":
|
|
/*!***********************!*\
|
|
!*** ./utp (ignored) ***!
|
|
\***********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?c172":
|
|
/*!********************!*\
|
|
!*** fs (ignored) ***!
|
|
\********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?c362":
|
|
/*!*********************!*\
|
|
!*** net (ignored) ***!
|
|
\*********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?5efe":
|
|
/*!********************!*\
|
|
!*** os (ignored) ***!
|
|
\********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?6dbd":
|
|
/*!************************!*\
|
|
!*** ut_pex (ignored) ***!
|
|
\************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?6e41":
|
|
/*!*********************************!*\
|
|
!*** ./lib/conn-pool (ignored) ***!
|
|
\*********************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?4b99":
|
|
/*!***************************************!*\
|
|
!*** bittorrent-dht/client (ignored) ***!
|
|
\***************************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?ae1e":
|
|
/*!*****************************!*\
|
|
!*** load-ip-set (ignored) ***!
|
|
\*****************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ })
|
|
|
|
/******/ });
|
|
/************************************************************************/
|
|
/******/ // The module cache
|
|
/******/ var __webpack_module_cache__ = {};
|
|
/******/
|
|
/******/ // The require function
|
|
/******/ function __webpack_require__(moduleId) {
|
|
/******/ // Check if module is in cache
|
|
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
/******/ if (cachedModule !== undefined) {
|
|
/******/ return cachedModule.exports;
|
|
/******/ }
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
/******/ id: moduleId,
|
|
/******/ loaded: false,
|
|
/******/ exports: {}
|
|
/******/ };
|
|
/******/
|
|
/******/ // Execute the module function
|
|
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
/******/
|
|
/******/ // Flag the module as loaded
|
|
/******/ module.loaded = true;
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/************************************************************************/
|
|
/******/ /* webpack/runtime/compat get default export */
|
|
/******/ (() => {
|
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
/******/ __webpack_require__.n = (module) => {
|
|
/******/ var getter = module && module.__esModule ?
|
|
/******/ () => (module['default']) :
|
|
/******/ () => (module);
|
|
/******/ __webpack_require__.d(getter, { a: getter });
|
|
/******/ return getter;
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/define property getters */
|
|
/******/ (() => {
|
|
/******/ // define getter functions for harmony exports
|
|
/******/ __webpack_require__.d = (exports, definition) => {
|
|
/******/ for(var key in definition) {
|
|
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
/******/ }
|
|
/******/ }
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/global */
|
|
/******/ (() => {
|
|
/******/ __webpack_require__.g = (function() {
|
|
/******/ if (typeof globalThis === 'object') return globalThis;
|
|
/******/ try {
|
|
/******/ return this || new Function('return this')();
|
|
/******/ } catch (e) {
|
|
/******/ if (typeof window === 'object') return window;
|
|
/******/ }
|
|
/******/ })();
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
/******/ (() => {
|
|
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/make namespace object */
|
|
/******/ (() => {
|
|
/******/ // define __esModule on exports
|
|
/******/ __webpack_require__.r = (exports) => {
|
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
/******/ }
|
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/node module decorator */
|
|
/******/ (() => {
|
|
/******/ __webpack_require__.nmd = (module) => {
|
|
/******/ module.paths = [];
|
|
/******/ if (!module.children) module.children = [];
|
|
/******/ return module;
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/************************************************************************/
|
|
/******/
|
|
/******/ // startup
|
|
/******/ // Load entry module and return exports
|
|
/******/ // This entry module is referenced by other modules so it can't be inlined
|
|
/******/ var __webpack_exports__ = __webpack_require__("./app/js/main.js");
|
|
/******/
|
|
/******/ })()
|
|
;
|
|
//# sourceMappingURL=bundle.js.map |