diff --git a/dist/image-sequencer-ui.js b/dist/image-sequencer-ui.js new file mode 100644 index 00000000..006a9e65 --- /dev/null +++ b/dist/image-sequencer-ui.js @@ -0,0 +1,50049 @@ +require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i { + this.ignoreFocusOpen = true; + setTimeout(() => { + // Trigger onFocus and open dropdown. + this.ignoreFocusOpen = false; + }, 50); + }); + }, + // Open dropdown after timeout of onClick. + onFocus: function () { + if (!this.ignoreFocusOpen) { + this.open(); + } + } + }; + + versionManagement.getLatestVersionNumber(function(versionNumber) { + console.log('The latest NPM version number for Image Sequencer (from GitHub) is v' + versionNumber); + }); + console.log('The local version number for Image Sequencer is v' + versionManagement.getLocalVersionNumber()); + + function displayVersionNumber() { + $('#version-number-text').text('Image Sequencer v' + versionManagement.getLocalVersionNumber()); + $('#version-number-top-right').text('v' + versionManagement.getLocalVersionNumber()); + } + displayVersionNumber(); + + function refreshOptions(options) { + // Default options if parameter is empty. + if (options == undefined) options = { sortField: 'text' }; + // Load information of all modules (Name, Inputs, Outputs) + var modulesInfo = sequencer.modulesInfo(); + + var addStepSelect = $('#addStep select'); + addStepSelect.html(''); + + // Add modules to the addStep dropdown + for (var m in modulesInfo) { + if (modulesInfo[m] && modulesInfo[m].name) + addStepSelect.append( + '' + ); + } + // Null option + addStepSelect.append(''); + addStepSelect.selectize(options); + } + refreshOptions(options); + + $(window).on('scroll', scrollFunction); + + /** + * @description Method to toggle the scroll-up arrow. + */ + function scrollFunction(A, B) { + var shouldDisplay = $('body').scrollTop() > 20 || $(':root').scrollTop() > 20; + + $('#move-up').css({ + display: shouldDisplay ? 'block' : 'none' + }); + } + + /** + * @description Method to scroll to the top of the page. + */ + function topFunction() { + $('body').animate({scrollTop: 0}); + $(':root').animate({scrollTop: 0}); + } + + $('#move-up').on('click', topFunction); + + + // UI for each step: + sequencer.setUI(DefaultHtmlStepUi(sequencer)); + + // UI for the overall demo: + var ui = defaultHtmlSequencerUi(sequencer); + + // Load image data from URL `src` parameter. + if (urlHash.getUrlHashParameter('src')) { + sequencer.loadImage(urlHash.getUrlHashParameter('src'), ui.onLoad); + } else { + sequencer.loadImage('images/tulips.png', ui.onLoad); + } + + var resetSequence = function () { + var r = confirm('Do you want to reset the sequence?'); + if (r) + { + window.location.hash = ''; + location.reload(); + } + }; + + $('#addStep select').on('change', ui.selectNewStepUi); + $('#addStep #add-step-btn').on('click', ui.addStepUi); + $('#resetButton').on('click', resetSequence); + + // Module Selector quick buttons click handler. + $('.radio-group .radio').on('click', function () { + $(this).parent().find('.radio').removeClass('selected'); + $(this).addClass('selected'); + newStep = $(this).attr('data-value'); + + $('#addStep select').val(newStep); + ui.selectNewStepUi(newStep); + ui.addStepUi(newStep); + $(this).removeClass('selected'); + }); + + /** + * @method displayMessageOnSaveSequence + * @description When a sequence is saved to a browser, notification is displayed. + * @returns {Null} + */ + function displayMessageOnSaveSequence() { + $('.savesequencemsg').fadeIn(); + setTimeout(function () { + $('.savesequencemsg').fadeOut(); + }, 3000); + } + + $('body').on('click', 'button.remove', ui.removeStepUi); + function saveSequence() { // 1. save seq + var result = window.prompt('Please give a name to your sequence... (Saved sequence will only be available in this browser).'); + if (result) { + result = result + ' (local)'; + sequencer.saveSequence(result, sequencer.toString()); // 1.a study saveSequence + sequencer.loadModules(); + displayMessageOnSaveSequence(); + refreshOptions(); + } + } + $('#saveButton').on('click', function () { + // Different handlers triggered for different dropdown options. + + let dropDownValue = $('#selectSaveOption option:selected').val(); + + if (dropDownValue == 'save-image') { + $('.download-btn:last()').trigger('click'); + } + else if (dropDownValue == 'save-gif') { + handleSavePNG(); + } + else if (dropDownValue == 'save-seq') { + saveSequence(); + } else if(dropDownValue == 'save-pdf') { + savePDF(getLastImage()); + } + else if (dropDownValue == 'save-to-publiclab.org' ){ + SaveToPubliclab(); + } + }); + + let isWorkingOnGifGeneration = false; + + $('.js-view-as-gif').on('click', function (event) { // GIF generation and display + if (isWorkingOnGifGeneration) return; // Prevent multiple button clicks + + isWorkingOnGifGeneration = true; + + var button = event.target; + button.disabled = true; + button.innerHTML = ''; + + try { + // Get GIF resources from previous steps + let options = getGifResources(); + + gifshot.createGIF(options, function (obj) { // GIF generation + if (!obj.error) { + // Final GIF encoded with base64 format + var image = obj.image; + var animatedImage = document.createElement('img'); + + animatedImage.id = 'gif_element'; + animatedImage.src = image; + + let modal = $('#js-download-gif-modal'); + + $('#js-download-as-gif-button').one('click', function () { + downloadGif(image); // Trigger GIF download + modal.modal('hide'); + }); + + var gifContainer = document.getElementById('js-download-modal-gif-container'); + + // Clear previous results + gifContainer.innerHTML = ''; + + // Insert image + gifContainer.appendChild(animatedImage); + + // Open modal + modal.modal(); + + button.disabled = false; + button.innerHTML = 'View GIF'; + isWorkingOnGifGeneration = false; + } + }); + } + catch (e) { + console.error(e); + button.disabled = false; + button.innerHTML = 'View GIF'; + isWorkingOnGifGeneration = false; + } + }); + + function getGifResources() { + // Returns an object with specific gif options + let imgs = document.getElementsByClassName('step-thumbnail'); + var imgSrcs = []; + + // Pushes image sources of all the modules in the DOM + for (var i = 0; i < imgs.length; i++) { + imgSrcs.push(imgs[i].src); + } + + var options = { // GIF frame options + 'gifWidth': imgs[0].width, + 'gifHeight': imgs[0].height, + 'images': imgSrcs, + 'frameDuration': 7, + }; + + return options; + } + + function handleSavePNG() { + let options = getGifResources(); + gifshot.createGIF(options, function(obj){ + + downloadGif(obj.image); + + }); + } + + /** + * Get the data URL for the last image in the sequence. + * @return {string} The data URL for the last image in the sequence. + */ + function getLastImage() { + // Get the image from the last step. + let imgs = document.getElementsByClassName('step-thumbnail'); + let lastStepImage = imgs[imgs.length - 1]; + return lastStepImage.getAttribute('src'); + } + + /** + * Download the given image URL as a PDF file. + * @param {string} imageDataURL - The data URL for the image. + */ + function savePDF(imageDataURL) { + sequencer.getImageDimensions(imageDataURL, function(dimensions) { + if (isGIF(imageDataURL)) { + // Get the dimensions of the image. + let pageWidth = dimensions.width; + let pageHeight = dimensions.height; + + // Create a new pdf with the same dimensions as the image. + const pdf = new jsPDF({ + orientation: pageHeight > pageWidth ? 'portrait' : 'landscape', + unit: 'px', + format: [pageHeight, pageWidth] + }); + + // Add the image to the pdf with dimensions equal to the internal dimensions of the page. + pdf.addImage(imageDataURL, 0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight()); + + // Save the pdf with the filename specified here: + pdf.save('index.pdf'); + } + else console.log('GIFs cannot be converted to PDF'); + }); + } + + + + function downloadGif(image) { + download(image, 'index.gif', 'image/gif'); // Downloadjs library function + } + + function SaveToPubliclab() { + function postToPL(imgSrc) { + var uniq = Date.now(); + $('body').append('
'); + f = $('#postToPL' + uniq)[0]; + f.datauri_main_image.value = imgSrc; + window.open('', 'postToPLWindow'); + f.submit(); + } + postToPL($('img')[sequencer.steps.length - 1].src); + } + + // Image selection and drag/drop handling from examples/lib/imageSelection.js + sequencer.setInputStep({ + dropZoneSelector: '#dropzone', + fileInputSelector: '#fileInput', + takePhotoSelector: '#take-photo', + onLoad: function onFileReaderLoad(progress) { + var reader = progress.target; + var step = sequencer.steps[0]; + var util = intermediateHtmlStepUi(sequencer); + step.output.src = reader.result; + sequencer.run({ index: 0 }); + if (typeof step.options !== 'undefined') + step.options.step.imgElement.src = reader.result; + else + step.imgElement.src = reader.result; + + insertPreview.updatePreviews(reader.result, document.querySelector('#addStep')); + DefaultHtmlStepUi(sequencer).updateDimensions(step); + }, + onTakePhoto: function (url) { + var step = sequencer.steps[0]; + step.output.src = url; + sequencer.run({ index: 0 }); + if (typeof step.options !== 'undefined') + step.options.step.imgElement.src = url; + else + step.imgElement.src = url; + insertPreview.updatePreviews(url, document.querySelector('#addStep')); + DefaultHtmlStepUi(sequencer).updateDimensions(step); + } + }); + + setupCache(); + + if (urlHash.getUrlHashParameter('src')) { // Gets the sequence from the URL + insertPreview.updatePreviews(urlHash.getUrlHashParameter('src'), document.querySelector('#addStep')); + } else { + insertPreview.updatePreviews('images/tulips.png', document.querySelector('#addStep')); + } +}; +},{"../src/util/isGif":172,"./lib/cache.js":2,"./lib/defaultHtmlSequencerUi.js":3,"./lib/defaultHtmlStepUi.js":4,"./lib/insertPreview.js":5,"./lib/intermediateHtmlStepUi.js":6,"./lib/urlHash.js":9,"./lib/versionManagement.js":10}],2:[function(require,module,exports){ +var setupCache = function() { + let newWorker; // When sw.js is changed, this is the new service worker generated. + + // Toggle a CSS class to display a popup prompting the user to fetch a new version. + function showUpdateModal() { + $('#update-prompt-modal').addClass('show'); + } + + /** + * When a new service worker has been loaded, the button in the update prompt + * modal should trigger the skipWaiting event to replace the current + * service worker with the new one. + */ + $('#reload').on('click', function() { + newWorker.postMessage({ action: 'skipWaiting' }); + }); + + if ('serviceWorker' in navigator) { + // Register the service worker. + navigator.serviceWorker.register('sw.js', { scope: '/examples/' }) + .then(function(registration) { + + return new Promise(function(resolve,reject){ + + registration.addEventListener('updatefound', () => { + // When sw.js has been changed, get a reference to the new service worker. + newWorker = registration.installing; + + if(!newWorker){ + return reject(new Error('error in installing service worker')); + } + + newWorker.addEventListener('statechange', () => { + // Check if service worker state has changed. + switch(newWorker.state) { + case 'installed': + if(navigator.serviceWorker.controller) { + // New service worker available; prompt the user to update. + showUpdateModal(); + $('#reload').on('click',(e) => { + e.preventDefault(); + console.log('New Service Worker Installed Successfully'); + location.reload(); + return resolve(); + }) + } + // No updates available; do nothing. + break; + + case 'redundant': + return reject(new Error('installing new service worker now became redundant')); + } + }) + }) + }) + }).catch(err => { + console.log('Failed In Registering Service Worker: ',err); + }); + + /** + * This is the event listener for when the service worker updates. + * When the service worker updates, reload the page. + */ + let refreshing; + navigator.serviceWorker.addEventListener('controllerchange', function() { + if(refreshing) return; + window.location.reload(); + refreshing = true; + }); + } + + if ('serviceWorker' in navigator) { + caches.keys().then(function(cacheNames) { + cacheNames.forEach(function(cacheName) { + $('#clear-cache').append(' ' + cacheName); + }); + }); + } + + const clearCache = () => { + if ('serviceWorker' in navigator) { + return caches.keys() + .then(function(cache) { + return Promise.all(cache.map(function(cacheItem) { + return caches.delete(cacheItem); + })); + }); + } + } + + $('#clear-cache').click(function() { + clearCache(); + location.reload(); + }); + +}; + +module.exports = setupCache; + +},{}],3:[function(require,module,exports){ +var urlHash = require('./urlHash.js'); + insertPreview = require('./insertPreview.js'); +function DefaultHtmlSequencerUi(_sequencer, options) { + + options = options || {}; + var addStepSel = options.addStepSel = options.addStepSel || '#addStep'; + var removeStepSel = options.removeStepSel = options.removeStepSel || 'button.remove'; + var selectStepSel = options.selectStepSel = options.selectStepSel || '#selectStep'; + + function onLoad() { + importStepsFromUrlHash(); + if ($('#selectStep').val() === 'none') + $(addStepSel + ' #add-step-btn').prop('disabled', true); + handleSaveSequence(); + } + + // look up needed steps from Url Hash: + function importStepsFromUrlHash() { + var hash = urlHash.getUrlHashParameter('steps'); + if (hash) { + _sequencer.importString(hash); + _sequencer.run({ index: 0 }); + } + urlHash.setUrlHashParameter('steps', sequencer.toString()); + } + + function selectNewStepUi() { + var m = $(addStepSel + ' select').val(); + if(m) $(addStepSel + ' .info').html(_sequencer.modulesInfo(m).description); + $(addStepSel + ' #add-step-btn').prop('disabled', false); + } + + function removeStepUi() { + var index = $(removeStepSel).index(this) + 1; + // If last step is removed. + if(sequencer.steps.length==index+1){ + console.log("inside") + insertPreview.updatePreviews(sequencer.steps[index-1].output.src, document.querySelector('#addStep')); + } + sequencer.removeSteps(index).run({ index: index - 1 }); + // remove from URL hash too + urlHash.setUrlHashParameter('steps', sequencer.toString()); + //disable save-sequence button if all steps are removed + handleSaveSequence(); + } + + function addStepUi() { + + if ($(addStepSel + ' select').val() == ''){ + alert('Please Select a Step to Proceed'); + return; + } + + var newStepName; + if(typeof arguments[0] !== 'string') + newStepName = $(addStepSel + ' select option').html().toLowerCase().split(' ').join('-'); + else newStepName = arguments[0]; + + + /* + * after adding the step we run the sequencer from defined step + * and since loadImage is not a part of the drawarray the step lies at current + * length - 2 of the drawarray + */ + var sequenceLength = 1; + if (sequencer.sequences[newStepName]) { + sequenceLength = sequencer.sequences[newStepName].length; + } else if (sequencer.modules[newStepName][1]['length']) { + sequenceLength = sequencer.modules[newStepName][1]['length']; + } + _sequencer + .addSteps(newStepName, options) + .run({ index: _sequencer.steps.length - sequenceLength - 1 }); + $(addStepSel + ' .info').html('Select a new module to add to your sequence.'); + $(addStepSel + ' select').val('none'); + + //enable save-sequence button if disabled initially + handleSaveSequence(); + + // add to URL hash too + urlHash.setUrlHashParameter('steps', _sequencer.toString()); + } + + function handleSaveSequence(){ + var stepCount = sequencer.steps.length; + if(stepCount < 2) + $(' #save-seq').prop('disabled', true); + else + $(' #save-seq').prop('disabled', false); + } + + return { + onLoad: onLoad, + importStepsFromUrlHash: importStepsFromUrlHash, + selectNewStepUi: selectNewStepUi, + removeStepUi: removeStepUi, + addStepUi: addStepUi + }; +} + +module.exports = DefaultHtmlSequencerUi; + + +},{"./insertPreview.js":5,"./urlHash.js":9}],4:[function(require,module,exports){ +// Set the UI in sequencer. This Will generate HTML based on +// Image Sequencer events : +// onSetup : Called every time a step is added +// onDraw : Called every time a step starts draw +// onComplete : Called every time a step finishes drawing +// onRemove : Called everytime a step is removed +// The variable 'step' stores useful data like input and +// output values, step information. +// See documetation for more details. + +const intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js'), + urlHash = require('./urlHash.js'), + _ = require('lodash'), + insertPreview = require('./insertPreview.js'); + mapHtmlTypes = require('./mapHtmltypes'), + scopeQuery = require('./scopeQuery'), + isGIF = require('../../src/util/isGif'); + +function DefaultHtmlStepUi(_sequencer, options) { + options = options || {}; + var stepsEl = options.stepsEl || document.querySelector('#steps'); + var selectStepSel = options.selectStepSel = options.selectStepSel || '#selectStep'; + + function onSetup(step, stepOptions) { + if (step.options && step.options.description) + step.description = step.options.description; + + let stepDocsLink = ''; + if (step.moduleInfo) stepDocsLink = step.moduleInfo['docs-link'] || ''; + + step.ui = // Basic UI markup for the step + '\ +
\ +
\ +
\ +
\ + \ + \ +
\ +

' + + '' + step.name + ' \ + \ +

\ +
\ +
\ +
\ +
\ +
\ + \ +
\ +
\ + \ +
\ + \ +
\ +
\ +
\ +
\ + \ +
\ +
\ +
'; + + var tools = + '
\ + \ +
'; + + var util = intermediateHtmlStepUi(_sequencer, step); + + var parser = new DOMParser(); + step.ui = parser.parseFromString(step.ui, 'text/html'); // Convert the markup string to a DOM node. + step.ui = step.ui.querySelector('div.container-fluid'); + + step.$step = scopeQuery.scopeSelector(step.ui); // Shorthand methods for scoped DOM queries. Read the docs [CONTRIBUTING.md](https://github.com/publiclab/image-sequencer/blob/main/CONTRIBUTING.md) for more info. + step.$stepAll = scopeQuery.scopeSelectorAll(step.ui); + let {$step, $stepAll} = step; + + step.linkElements = step.ui.querySelectorAll('a'); // All the anchor tags in the step UI + step.imgElement = $step('a img.img-thumbnail')[0]; // The output image + + if (_sequencer.modulesInfo().hasOwnProperty(step.name)) { + var inputs = _sequencer.modulesInfo(step.name).inputs; + var outputs = _sequencer.modulesInfo(step.name).outputs; + var merged = Object.assign(inputs, outputs); // Combine outputs with inputs + + for (var paramName in merged) { + var isInput = inputs.hasOwnProperty(paramName); + var html = ''; + var inputDesc = isInput ? mapHtmlTypes(inputs[paramName]) : {}; + if (!isInput) { + html += ''; + } + else if (inputDesc.type.toLowerCase() == 'select') { + + html += ''; + } + else { + let paramVal = step.options[paramName] || inputDesc.default; + + if (inputDesc.id == 'color-picker') { // Separate input field for color-picker + html += + '
' + + '' + '' + + '
'; + } + else if(inputDesc.type === 'button'){ + html = '
\ + click to select coordinates\ +
'; + } + else { // Non color-picker input types and other than a button + + html = + '' + '' + paramVal + ''; + + } + else html += '">'; + } + } + + var div = document.createElement('div'); + div.className = 'row'; + div.setAttribute('name', paramName); + var description = inputs[paramName].desc || paramName; + div.innerHTML = + '
\ + \ + ' + + html + + '\ +
'; + $step('div.details').append(div); + } + $step('div.panel-footer').append( // Save button + '
Press apply to see changes
' + ); + $step('div.panel-footer').prepend( // Markup for tools: download and insert step buttons + '\ + ' + ); + } + + if (step.name != 'load-image') { + $step('div.trash-container') + .prepend( + parser.parseFromString(tools, 'text/html').querySelector('div') + ); + + $stepAll('.remove').on('click', function() {notify('Step Removed', 'remove-notification');}); // Notification on removal of a step + $step('.insert-step').on('click', function() { util.insertStep(step.ID); }); // Insert a step in between the sequence + // Insert the step's UI in the right place + + if (stepOptions.index == _sequencer.steps.length) { + stepsEl.appendChild(step.ui); + $('#steps .step-container:nth-last-child(1) .insert-step').prop('disabled', true); + if($('#steps .step-container:nth-last-child(2)')) + $('#steps .step-container:nth-last-child(2) .insert-step').prop('disabled', false); + } + else { + stepsEl.insertBefore(step.ui, $(stepsEl).children()[stepOptions.index]); + } + + // Enable the load-image insert-step button when there are steps after load-image + // The logical operator is `> 0` because the number of steps is found before adding the step, actual logic is `steps.length + 1 > 1` which is later simplified. + if (_sequencer.steps.length > 0) $('#load-image .insert-step').prop('disabled', false); + else $('#load-image .insert-step').prop('disabled', true); + } + else { + $('#load-image').append(step.ui); // Default UI without extra tools for the first step(load image) + + $step('div.panel-footer').prepend( ` + ` + ); + + $step('.insert-step').on('click', function() { util.insertStep(step.ID); }); + } + $step('.toggle').on('click', () => { // Step container dropdown + $step('.toggleIcon').toggleClass('rotated'); + $stepAll('.cal').collapse('toggle'); + }); + + $(step.imgElement).on('mousemove', _.debounce(() => imageHover(step), 150)); // Shows the pixel coordinates on hover + $(step.imgElement).on('click', (e) => {e.preventDefault(); }); + $stepAll('#color-picker').colorpicker(); + + function saveOptions(e) { // 1. SAVE OPTIONS + e.preventDefault(); + if (optionsChanged){ + $step('div.details') + .find('input,select') + .each(function(i, input) { + $(input) + .data('initValue', $(input).val()) + .data('hasChangedBefore', false); + step.options[$(input).attr('name')] = $(input).val(); + }); + _sequencer.run({ index: step.index - 1 }); + + // Modify the URL hash + urlHash.setUrlHashParameter('steps', _sequencer.toString()); + // Disable the save button + $step('.btn-save').prop('disabled', true); + optionsChanged = false; + changedInputs = 0; + } + } + + /** + * @method handleInputValueChange + * @description Enables the save button on input change + * @param {*} currentValue The current value of the input + * @param {*} initValue The initial/old value of the input + * @param {Boolean} hasChangedBefore Whether the input was changed before + * @returns {Boolean} True if the value has changed + */ + function handleInputValueChange(currentValue, initValue, hasChangedBefore) { + var inputChanged = !(isNaN(initValue) || isNaN(currentValue) ? currentValue === initValue : currentValue - initValue === 0); + changedInputs += hasChangedBefore ? inputChanged ? 0 : -1 : inputChanged ? 1 : 0; + optionsChanged = changedInputs > 0; + + $step('.btn-save').prop('disabled', !optionsChanged); + return inputChanged; + } + + var + changedInputs = 0, + optionsChanged = false; + $step('.input-form').on('submit', saveOptions); + $stepAll('.target').each(function(i, input) { + $(input) + .data('initValue', $(input).val()) + .data('hasChangedBefore', false) + .on('input change', function() { + $(this) + .focus() + .data('hasChangedBefore', + handleInputValueChange( + $(this).val(), + $(this).data('initValue'), + $(this).data('hasChangedBefore') + ) + ); + }); + }); + + $stepAll('.color-picker-target').each(function(i, input) { + $(input) + .data('initValue', $(input).val()) + .data('hasChangedBefore', false) + .on('input change', function() { + $(this) + .data('hasChangedBefore', + handleInputValueChange( + $(this).val(), + $(this).data('initValue'), + $(this).data('hasChangedBefore') + ) + ); + }); + }); + + + $('input[type="range"]').on('input', function() { + $(this).next().html($(this).val()); + }); + } + + + function onDraw({$step, $stepAll}) { + $step('.load').show(); + $step('img').hide(); + $stepAll('.load-spin').show(); + } + + function onComplete(step) { + let {$step, $stepAll} = step; + $step('img').show(); + $stepAll('.load-spin').hide(); + $step('.load').hide(); + + $stepAll('.download-btn').off('click'); + + step.imgElement.src = (step.name == 'load-image') ? step.output.src : step.output; + var imgthumbnail = $step('.img-thumbnail').getDomElem(); + for (let index = 0; index < step.linkElements.length; index++) { + if (step.linkElements[index].contains(imgthumbnail)) + step.linkElements[index].href = step.imgElement.src; + } + + // TODO: use a generalized version of this. + function fileExtension(output) { + return output.split('/')[1].split(';')[0]; + } + + $stepAll('.download-btn').on('click', () => { + + function dataURLtoBlob(dataurl) { + let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], + bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); + while(n--){ + u8arr[n] = bstr.charCodeAt(n); + } + return new Blob([u8arr], {type:mime}); + } + + var element = document.createElement('a'); + + element.setAttribute('download', step.name + '.' + fileExtension(step.imgElement.src)); + element.style.display = 'none'; + document.body.appendChild(element); + var blob = dataURLtoBlob(step.output); + var objurl = URL.createObjectURL(blob); + element.setAttribute('href', objurl); + + element.click(); + }); + + // Fill inputs with stored step options + if (_sequencer.modulesInfo().hasOwnProperty(step.name)) { + var inputs = _sequencer.modulesInfo(step.name).inputs; + var outputs = _sequencer.modulesInfo(step.name).outputs; + for (var i in inputs) { + if (step.options[i] !== undefined) { + if (inputs[i].type.toLowerCase() === 'input') + $step('div[name="' + i + '"] input') + .val(step.options[i]) + .data('initValue', step.options[i]); + if (inputs[i].type.toLowerCase() === 'select') + $step('div[name="' + i + '"] select') + .val(String(step.options[i])) + .data('initValue', step.options[i]); + } + } + for (var i in outputs) { + if (step[i] !== undefined) + $step('div[name="' + i + '"] input') + .val(step[i]); + } + } + + $(function () { + $('[data-toggle="tooltip"]').tooltip(); + updateDimensions(step); + }); + + if (step.name === 'load-image') insertPreview.updatePreviews(step.output.src, document.querySelector('#addStep')); + else insertPreview.updatePreviews(step.output, document.querySelector('#addStep')); + + // Handle the wasm bolt display + + if (step.useWasm) { + if (step.wasmSuccess) $step('.wasm-tooltip').fadeIn(); + else $step('.wasm-tooltip').fadeOut(); + } + else $step('.wasm-tooltip').fadeOut(); + } + /** + * @description Updates Dimension of the image + * @param {Object} step - Current Step + * @returns {void} + * + */ + function updateDimensions(step){ + _sequencer.getImageDimensions(step.imgElement.src, function (dim) { + step.ui.querySelector('.' + step.name).attributes['data-original-title'].value = `

Image Width: ${dim.width}
Image Height: ${dim.height}
${isGIF(step.output) ? `Frames: ${dim.frames}` : ''}

`; + }); + } + + /** + * @method imageHover + * @description Handler to display image coordinates on hover. + * @param {Object} step Current step variable + * @returns {Null} + */ + function imageHover(step){ + + var img = $(step.imgElement); + + let customXCoord = '20'; //default x coordinate + let customYCoord = '20'; //default y coordinate + + const customButton = $('button[name="Custom-Coordinates"]'); + img.click(function(e) { + customXCoord = e.offsetX; + customYCoord = e.offsetY; + customButton.click(function() { + $('input[name="x"]').val(customXCoord); + $('input[name="y"]').val(customYCoord); + }) + }); + + img.mousemove(function(e) { + var canvas = document.createElement('canvas'); + canvas.width = img.width(); + canvas.height = img.height(); + var context = canvas.getContext('2d'); + context.drawImage(this, 0, 0); + + var offset = $(this).offset(); + var xPos = e.pageX - offset.left; + var yPos = e.pageY - offset.top; + var myData = context.getImageData(xPos, yPos, 1, 1); + img[0].title = 'rgb: ' + myData.data[0] + ',' + myData.data[1] + ',' + myData.data[2];//+ rgbdata; + }); + } + + function onRemove(step) { + step.ui.remove(); + $('#steps .step-container:nth-last-child(1) .insert-step').prop('disabled', true); + + // Enable the load-image insert-step button when there are steps after load-image + // The logical operator is `> 2` because the number of steps is found before removing the step, actual logic is `steps.length - 1 > 1` which is later simplified. + if (_sequencer.steps.length - 1 > 1) $('#load-image .insert-step').prop('disabled', false); + else $('#load-image .insert-step').prop('disabled', true); + + $(step.imgElement).imgAreaSelect({ + remove: true + }); + } + + function getPreview() { + return step.imgElement; + } + + /** + * @method notify + * @description General purpose DOM toast notification + * @param {String} msg Message to be displayed + * @param {String} id A unique identifier for the notification + * @returns {Null} + */ + function notify(msg, id){ + if ($('#' + id).length == 0) { + var notification = document.createElement('span'); + notification.innerHTML = ' ' + msg ; + notification.id = id; + notification.classList.add('notification'); + + $('body').append(notification); + } + + $('#' + id).fadeIn(500).delay(200).fadeOut(500); + } + + + return { + getPreview: getPreview, + onSetup: onSetup, + onComplete: onComplete, + onRemove: onRemove, + onDraw: onDraw, + notify: notify, + imageHover: imageHover, + updateDimensions: updateDimensions + }; +} + +if(typeof window === 'undefined'){ + module.exports = { + DefaultHtmlStepUi: DefaultHtmlStepUi + }; +} + +module.exports = DefaultHtmlStepUi; + +},{"../../src/util/isGif":172,"./insertPreview.js":5,"./intermediateHtmlStepUi.js":6,"./mapHtmltypes":7,"./scopeQuery":8,"./urlHash.js":9,"lodash":168}],5:[function(require,module,exports){ +// Generate downscaled preview images for quick buttons. +function generatePreview(previewStepName, customValues, path, DomNode) { + var previewSequencer = ImageSequencer(); + function insertPreview(src) { + var img = document.createElement('img'); + img.classList.add('img-thumbnail'); + img.classList.add('no-border'); + img.src = src; + $(img).css('max-width', '200%'); + $(img).css('transform', 'translateX(-20%)'); + $(DomNode.querySelector('.radio-group')).find('.radio').each(function() { + if ($(this).attr('data-value') === previewStepName) { + $(this).find('img').remove(); + $(this).append(img); + } + }); + } + + function loadPreview() { + if (previewStepName === 'crop') { + previewSequencer.addSteps(previewStepName, customValues).run(insertPreview); + } + else { + previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview); + } + } + if(previewStepName === 'resize') + insertPreview(path); + else + previewSequencer.loadImage(path, loadPreview); +} + +function updatePreviews(src, DomNode) { + $(DomNode).find('img').remove(); + + var previewSequencerSteps = { + 'resize': '125%', + 'brightness': '175', + 'saturation': '0.5', + 'rotate': 90, + 'contrast': 90, + 'crop': { + 'x': 0, + 'y': 0, + 'w': '50%', + 'h': '50%', + 'noUI': true + } + }; + + var img = new Image(); + + img.onload = function(){ + var height = img.height; + var width = img.width; + + let percentage = (80 / height) * 100; // Take the min resize value that fits the preview area => (new-width/orig_ht) - '80 as the preview area has 80*80 dimension. + percentage = Math.max((80 / width) * 100, percentage); // Make sure that one dimension doesn't resize greater, leading distorting preview-area fitting. + percentage = Math.ceil(percentage); + + var sequencer = ImageSequencer(); + + sequencer.loadImage(src, function(){ + this.addSteps('resize', {['resize']: percentage + '%'}); + this.run((src)=>{ + Object.keys(previewSequencerSteps).forEach(function (step, index) { + generatePreview(step, Object.values(previewSequencerSteps)[index], src, DomNode); + }); + }); + }); + }; + img.src = src; +} + + +module.exports = { + generatePreview : generatePreview, + updatePreviews : updatePreviews +}; +},{}],6:[function(require,module,exports){ +var urlHash = require('./urlHash.js'), + insertPreview = require('./insertPreview.js'); + +/** + * @method IntermediateHtmlStepUi + * @description Inserts a module selector in between the current sequence + * @param {Object} _sequencer Sequencer instance + * @param {Object} step Current step variable + * @param {Object} options Optional options Object + * @returns {Object} Object containing the insertStep function + */ +function IntermediateHtmlStepUi(_sequencer, step, options) { + function stepUI() { + // Basic markup for the selector + return '
\ +
\ + \ +
\ +
\ +

Select a new module to add to your sequence.

\ +
\ +
\ +
\ + \ +
\ +

Resize

\ +
\ +
\ +
\ + \ +
\ +

Brightness

\ +
\ +
\ +
\ + \ +
\ +

Contrast

\ +
\ +
\ +
\ + \ +
\ +

Saturation

\ +
\ +
\ +
\ + \ +
\ +

Rotate

\ +
\ +
\ +
\ + \ +
\ +

Crop

\ +
\ +
\ +
\ +
\ + \ +
\ +
\ + \ +
\ +
\ +
\ +
\ +
\ +
'; + } + + /** + * @method toggleDiv + * @description Toggles the module selector dropdown. + * @param {Object} $step $step util function + * @param {Fucntion} callback Optional callback function + * @returns {Null} + */ + var toggleDiv = function($step, callback = function(){}){ + $step('.insertDiv').collapse('toggle'); + if ($step('.insert-text').css('display') != 'none'){ + $step('.insert-text').fadeToggle(200, function(){$step('.no-insert-text').fadeToggle(200, callback);}); + } + else { + $step('.no-insert-text').fadeToggle(200, function(){$step('.insert-text').fadeToggle(200, callback);}); + } + }; + + /** + * @method insertStep + * @description Handler to insert selected module in the sequence + * @returns {Null} + */ + insertStep = function (id) { + const $step = step.$step, + $stepAll = step.$stepAll; + var modulesInfo = _sequencer.modulesInfo(); + var parser = new DOMParser(); + var addStepUI = stepUI(); + addStepUI = parser.parseFromString(addStepUI, 'text/html').querySelector('div'); + + if ($step('.insertDiv').length > 0){ + toggleDiv($step); + } + else { + step.ui + .querySelector('div.step') + .insertAdjacentElement('afterend', + addStepUI + ); + toggleDiv($step, function(){ + if (step.name === 'load-image') insertPreview.updatePreviews(step.output.src, $step('.insertDiv').getDomElem()); + else insertPreview.updatePreviews(step.output, $step('.insertDiv').getDomElem()); + }); + } + + + $step('.insertDiv .close-insert-box').off('click').on('click', function(){ + toggleDiv($step); + $step('.insertDiv').removeClass('insertDiv'); + }); + + var insertStepSelect = $step('.insert-step-select'); + insertStepSelect.html(''); + + // Add modules to the insertStep dropdown + for (var m in modulesInfo) { + if (modulesInfo[m] && modulesInfo[m].name) + insertStepSelect.append( + '' + ); + } + + insertStepSelect.selectize({ + sortField: 'text' + }); + + $('.insertDiv .radio-group .radio').on('click', function () { + var newStepName = $(this).attr('data-value'); // Get the name of the module to be inserted + id = $($step('.insertDiv').parents()[3]).prevAll().length; + insert(id, $step, newStepName); // Insert the selected module + }); + + $step('.insertDiv .add-step-btn').on('click', function () { + var newStepName = insertStepSelect.val(); + id = $($step('.insertDiv').parents()[3]).prevAll().length; + insert(id, $step, newStepName); }); + }; + + /** + * @method insert + * @description Inserts the specified step at the specified index in the sequence + * @param {Number} id Index of the step + * @param {Function} $step $step util function + * @param {String} newStepName Name of the new step + */ + function insert(id, $step, newStepName) { + toggleDiv($step); + $step('.insertDiv').removeClass('insertDiv'); + _sequencer.insertSteps(id + 1, newStepName).run({ index: id }); + urlHash.setUrlHashParameter('steps', _sequencer.toString()); + } + + return { + insertStep + }; +} +module.exports = IntermediateHtmlStepUi; + +},{"./insertPreview.js":5,"./urlHash.js":9}],7:[function(require,module,exports){ +/** + * @description Maps module input types to their respective html tag types. + * @param {Object} inputInfo Object containing the type and optionally min/max for range type inputs. + */ +function mapHtmlTypes(inputInfo){ + var htmlType; + switch(inputInfo.type.toLowerCase()){ + case 'integer': + htmlType = inputInfo.min != undefined ? 'range' : 'number'; + if (htmlType === 'range') inputInfo.step = inputInfo.step || 1; // default range step size for integer + break; + case 'string': + htmlType = 'text'; + break; + case 'select': + htmlType = 'select'; + break; + case 'percentage': + htmlType = 'number'; + break; + case 'float': + htmlType = inputInfo.min != undefined ? 'range' : 'text'; + if (htmlType === 'range') inputInfo.step = inputInfo.step || 0.1; // default range step size for float + break; + case 'coordinate-input': + htmlType = 'button'; + break; + default: + htmlType = 'text'; + break; + } + var response = Object.assign({}, inputInfo); + response.type = htmlType; + return response; +} + +module.exports = mapHtmlTypes; +},{}],8:[function(require,module,exports){ +/** + * @method $scope + * @param {"DOMNode"} scope A DOM Node as the scope + * @returns {Function} Constructor for the scopeSelector Object. + */ +function $scope(scope) { + return function(queryString){ + var element = $(scope.querySelector(queryString)); + + element.elem = function(queryString){ + return new $scope(scope)(queryString); + }; + element.elemAll = function(queryString){ + return new $scopeAll(scope)(queryString); + }; + element.getDomElem = function(i = 0){ + return element[i]; + }; + element.getScope = () => scope; + + return element; + }; +} + +/** + * @method $scopeAll + * @param {"DOMNode"} scope A DOM Node as the scope + * @returns {Function} Constructor for the scopeSelectorAll Object. + */ +function $scopeAll(scope){ + return function(queryString){ + var element = $(scope.querySelectorAll(queryString)); + + element.elem = function(queryString){ + return new $scope(scope)(queryString); + }; + element.elemAll = function(queryString){ + return new $scopeAll(scope)(queryString); + }; + element.getDomElem = function(i = 0){ + return element[i]; + }; + element.getScope = () => scope; + + return element; + }; +} + +/** + * @method scopeSelector + * @description A scoped jQuery selector + * @param {"DOMNode"} scope A DOM Node as the scope + * @returns {Function} + */ +function scopeSelector(scope){ + return $scope(scope); +} + +/** + * @method scopeSelectorAll + * @description A scoped jQuery multiple selector + * @param {"DOMNode} scope A DOM Node as the scope + * @returns {Function} + */ +function scopeSelectorAll(scope){ + return $scopeAll(scope); +} + +module.exports = { + scopeSelector, + scopeSelectorAll +}; +},{}],9:[function(require,module,exports){ +function getUrlHashParameter(param) { + + var params = getUrlHashParameters(); + return params[param]; + +} + +function getUrlHashParameters() { + + var sPageURL = window.location.hash; + if (sPageURL) sPageURL = sPageURL.split('#')[1]; + var pairs = sPageURL.split('&'); + var object = {}; + pairs.forEach(function(pair, i) { + pair = pair.split('='); + if (pair[0] != '') object[pair[0]] = pair[1]; + }); + return object; +} + +// accepts an object like { paramName: value, paramName1: value } +// and transforms to: url.com#paramName=value¶mName1=value +function setUrlHashParameters(params) { + + var keys = Object.keys(params); + var values = Object.values(params); + var pairs = []; + keys.forEach(function(key, i) { + if (key != '') pairs.push(keys[i] + '=' + values[i]); + }); + var hash = pairs.join('&'); + window.location.hash = hash; + +} + +function setUrlHashParameter(param, value) { + + var params = getUrlHashParameters(); + params[param] = value; + setUrlHashParameters(params); + +} + +module.exports = { + getUrlHashParameter: getUrlHashParameter, + setUrlHashParameter: setUrlHashParameter, + getUrlHashParameters: getUrlHashParameters, + setUrlHashParameters: setUrlHashParameters +}; + +},{}],10:[function(require,module,exports){ +/** + * Functions for getting version information. + * Note: these functions are not used by the service worker to check for updates; + * the service worker updates whenever sw.js has changed. + * sw.js is changed when grunt replace:version is run. This task is run during + * grunt build, serve, and productions tasks. + */ + +const package = require('../../package.json'); + +/** + * Get the current version number from package.json on the homepage. + * @param {function} callback The function that uses the version number. + */ +function getLatestVersionNumber(callback) { + // Get the homepage reference from the local package.json. + var homepage = package.homepage; + var request = new XMLHttpRequest(); + request.onreadystatechange = function() { + if (request.readyState == 4 && request.status == 200) { + var response = JSON.parse(this.responseText); + var latestVersionNumber = response.version; + + // Do something with the version number using a callback function. + if (callback) + callback(latestVersionNumber); + } + } + + // Get the package.json file from online using a GET request. + request.open("GET", homepage + "/package.json", true); + request.send(); +} + +// Get the version number from the local package.json file. +function getLocalVersionNumber() { + return package.version; +} + +module.exports = { + getLatestVersionNumber, + getLocalVersionNumber +} + +},{"../../package.json":171}],11:[function(require,module,exports){ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = global || self, factory(global.acorn = {})); +}(this, (function (exports) { 'use strict'; + + // Reserved word lists for various dialects of the language + + var reservedWords = { + 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", + 5: "class enum extends super const export import", + 6: "enum", + strict: "implements interface let package private protected public static yield", + strictBind: "eval arguments" + }; + + // And the keywords + + var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; + + var keywords = { + 5: ecma5AndLessKeywords, + "5module": ecma5AndLessKeywords + " export import", + 6: ecma5AndLessKeywords + " const class extends export import super" + }; + + var keywordRelationalOperator = /^in(stanceof)?$/; + + // ## Character categories + + // Big ugly regular expressions that match characters in the + // whitespace, identifier, and identifier-start categories. These + // are only applied when a character is found to actually have a + // code point above 128. + // Generated by `bin/generate-identifier-regex.js`. + var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; + var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf\u1ac0\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; + + var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); + var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); + + nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; + + // These are a run-length and offset encoded representation of the + // >0xffff code points that are a valid part of identifiers. The + // offset starts at 0x10000, and each pair of numbers represents an + // offset to the next range, and then a size of the range. They were + // generated by bin/generate-identifier-regex.js + + // eslint-disable-next-line comma-spacing + var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,349,41,7,1,79,28,11,0,9,21,107,20,28,22,13,52,76,44,33,24,27,35,30,0,3,0,9,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,21,2,31,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,7,3,0,3,7,2,1,2,23,16,0,2,0,95,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,190,0,80,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,1237,43,8,8952,286,50,2,18,3,9,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,2357,44,11,6,17,0,370,43,1301,196,60,67,8,0,1205,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42717,35,4148,12,221,3,5761,15,7472,3104,541,1507,4938]; + + // eslint-disable-next-line comma-spacing + var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,370,1,154,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,2,11,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,71,5,2,1,3,3,2,0,2,1,13,9,120,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1014,0,2,54,8,3,82,0,12,1,19628,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,262,6,10,9,419,13,1495,6,110,6,6,9,4759,9,787719,239]; + + // This has a complexity linear to the value of the code. The + // assumption is that looking up astral identifier characters is + // rare. + function isInAstralSet(code, set) { + var pos = 0x10000; + for (var i = 0; i < set.length; i += 2) { + pos += set[i]; + if (pos > code) { return false } + pos += set[i + 1]; + if (pos >= code) { return true } + } + } + + // Test whether a given character code starts an identifier. + + function isIdentifierStart(code, astral) { + if (code < 65) { return code === 36 } + if (code < 91) { return true } + if (code < 97) { return code === 95 } + if (code < 123) { return true } + if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } + if (astral === false) { return false } + return isInAstralSet(code, astralIdentifierStartCodes) + } + + // Test whether a given character is part of an identifier. + + function isIdentifierChar(code, astral) { + if (code < 48) { return code === 36 } + if (code < 58) { return true } + if (code < 65) { return false } + if (code < 91) { return true } + if (code < 97) { return code === 95 } + if (code < 123) { return true } + if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } + if (astral === false) { return false } + return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) + } + + // ## Token types + + // The assignment of fine-grained, information-carrying type objects + // allows the tokenizer to store the information it has about a + // token in a way that is very cheap for the parser to look up. + + // All token type variables start with an underscore, to make them + // easy to recognize. + + // The `beforeExpr` property is used to disambiguate between regular + // expressions and divisions. It is set on all token types that can + // be followed by an expression (thus, a slash after them would be a + // regular expression). + // + // The `startsExpr` property is used to check if the token ends a + // `yield` expression. It is set on all token types that either can + // directly start an expression (like a quotation mark) or can + // continue an expression (like the body of a string). + // + // `isLoop` marks a keyword as starting a loop, which is important + // to know when parsing a label, in order to allow or disallow + // continue jumps to that label. + + var TokenType = function TokenType(label, conf) { + if ( conf === void 0 ) conf = {}; + + this.label = label; + this.keyword = conf.keyword; + this.beforeExpr = !!conf.beforeExpr; + this.startsExpr = !!conf.startsExpr; + this.isLoop = !!conf.isLoop; + this.isAssign = !!conf.isAssign; + this.prefix = !!conf.prefix; + this.postfix = !!conf.postfix; + this.binop = conf.binop || null; + this.updateContext = null; + }; + + function binop(name, prec) { + return new TokenType(name, {beforeExpr: true, binop: prec}) + } + var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true}; + + // Map keyword names to token types. + + var keywords$1 = {}; + + // Succinct definitions of keyword token types + function kw(name, options) { + if ( options === void 0 ) options = {}; + + options.keyword = name; + return keywords$1[name] = new TokenType(name, options) + } + + var types = { + num: new TokenType("num", startsExpr), + regexp: new TokenType("regexp", startsExpr), + string: new TokenType("string", startsExpr), + name: new TokenType("name", startsExpr), + eof: new TokenType("eof"), + + // Punctuation token types. + bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), + bracketR: new TokenType("]"), + braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), + braceR: new TokenType("}"), + parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), + parenR: new TokenType(")"), + comma: new TokenType(",", beforeExpr), + semi: new TokenType(";", beforeExpr), + colon: new TokenType(":", beforeExpr), + dot: new TokenType("."), + question: new TokenType("?", beforeExpr), + questionDot: new TokenType("?."), + arrow: new TokenType("=>", beforeExpr), + template: new TokenType("template"), + invalidTemplate: new TokenType("invalidTemplate"), + ellipsis: new TokenType("...", beforeExpr), + backQuote: new TokenType("`", startsExpr), + dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), + + // Operators. These carry several kinds of properties to help the + // parser use them properly (the presence of these properties is + // what categorizes them as operators). + // + // `binop`, when present, specifies that this operator is a binary + // operator, and will refer to its precedence. + // + // `prefix` and `postfix` mark the operator as a prefix or postfix + // unary operator. + // + // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as + // binary operators with a very low precedence, that should result + // in AssignmentExpression nodes. + + eq: new TokenType("=", {beforeExpr: true, isAssign: true}), + assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), + incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), + prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), + logicalOR: binop("||", 1), + logicalAND: binop("&&", 2), + bitwiseOR: binop("|", 3), + bitwiseXOR: binop("^", 4), + bitwiseAND: binop("&", 5), + equality: binop("==/!=/===/!==", 6), + relational: binop("/<=/>=", 7), + bitShift: binop("<>/>>>", 8), + plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), + modulo: binop("%", 10), + star: binop("*", 10), + slash: binop("/", 10), + starstar: new TokenType("**", {beforeExpr: true}), + coalesce: binop("??", 1), + + // Keyword token types. + _break: kw("break"), + _case: kw("case", beforeExpr), + _catch: kw("catch"), + _continue: kw("continue"), + _debugger: kw("debugger"), + _default: kw("default", beforeExpr), + _do: kw("do", {isLoop: true, beforeExpr: true}), + _else: kw("else", beforeExpr), + _finally: kw("finally"), + _for: kw("for", {isLoop: true}), + _function: kw("function", startsExpr), + _if: kw("if"), + _return: kw("return", beforeExpr), + _switch: kw("switch"), + _throw: kw("throw", beforeExpr), + _try: kw("try"), + _var: kw("var"), + _const: kw("const"), + _while: kw("while", {isLoop: true}), + _with: kw("with"), + _new: kw("new", {beforeExpr: true, startsExpr: true}), + _this: kw("this", startsExpr), + _super: kw("super", startsExpr), + _class: kw("class", startsExpr), + _extends: kw("extends", beforeExpr), + _export: kw("export"), + _import: kw("import", startsExpr), + _null: kw("null", startsExpr), + _true: kw("true", startsExpr), + _false: kw("false", startsExpr), + _in: kw("in", {beforeExpr: true, binop: 7}), + _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), + _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), + _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), + _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) + }; + + // Matches a whole line break (where CRLF is considered a single + // line break). Used to count lines. + + var lineBreak = /\r\n?|\n|\u2028|\u2029/; + var lineBreakG = new RegExp(lineBreak.source, "g"); + + function isNewLine(code, ecma2019String) { + return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029)) + } + + var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/; + + var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; + + var ref = Object.prototype; + var hasOwnProperty = ref.hasOwnProperty; + var toString = ref.toString; + + // Checks if an object has a property. + + function has(obj, propName) { + return hasOwnProperty.call(obj, propName) + } + + var isArray = Array.isArray || (function (obj) { return ( + toString.call(obj) === "[object Array]" + ); }); + + function wordsRegexp(words) { + return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") + } + + // These are used when `options.locations` is on, for the + // `startLoc` and `endLoc` properties. + + var Position = function Position(line, col) { + this.line = line; + this.column = col; + }; + + Position.prototype.offset = function offset (n) { + return new Position(this.line, this.column + n) + }; + + var SourceLocation = function SourceLocation(p, start, end) { + this.start = start; + this.end = end; + if (p.sourceFile !== null) { this.source = p.sourceFile; } + }; + + // The `getLineInfo` function is mostly useful when the + // `locations` option is off (for performance reasons) and you + // want to find the line/column position for a given character + // offset. `input` should be the code string that the offset refers + // into. + + function getLineInfo(input, offset) { + for (var line = 1, cur = 0;;) { + lineBreakG.lastIndex = cur; + var match = lineBreakG.exec(input); + if (match && match.index < offset) { + ++line; + cur = match.index + match[0].length; + } else { + return new Position(line, offset - cur) + } + } + } + + // A second optional argument can be given to further configure + // the parser process. These options are recognized: + + var defaultOptions = { + // `ecmaVersion` indicates the ECMAScript version to parse. Must be + // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10 + // (2019). This influences support for strict mode, the set of + // reserved words, and support for new syntax features. The default + // is 10. + ecmaVersion: 10, + // `sourceType` indicates the mode the code should be parsed in. + // Can be either `"script"` or `"module"`. This influences global + // strict mode and parsing of `import` and `export` declarations. + sourceType: "script", + // `onInsertedSemicolon` can be a callback that will be called + // when a semicolon is automatically inserted. It will be passed + // the position of the comma as an offset, and if `locations` is + // enabled, it is given the location as a `{line, column}` object + // as second argument. + onInsertedSemicolon: null, + // `onTrailingComma` is similar to `onInsertedSemicolon`, but for + // trailing commas. + onTrailingComma: null, + // By default, reserved words are only enforced if ecmaVersion >= 5. + // Set `allowReserved` to a boolean value to explicitly turn this on + // an off. When this option has the value "never", reserved words + // and keywords can also not be used as property names. + allowReserved: null, + // When enabled, a return at the top level is not considered an + // error. + allowReturnOutsideFunction: false, + // When enabled, import/export statements are not constrained to + // appearing at the top of the program. + allowImportExportEverywhere: false, + // When enabled, await identifiers are allowed to appear at the top-level scope, + // but they are still not allowed in non-async functions. + allowAwaitOutsideFunction: false, + // When enabled, hashbang directive in the beginning of file + // is allowed and treated as a line comment. + allowHashBang: false, + // When `locations` is on, `loc` properties holding objects with + // `start` and `end` properties in `{line, column}` form (with + // line being 1-based and column 0-based) will be attached to the + // nodes. + locations: false, + // A function can be passed as `onToken` option, which will + // cause Acorn to call that function with object in the same + // format as tokens returned from `tokenizer().getToken()`. Note + // that you are not allowed to call the parser from the + // callback—that will corrupt its internal state. + onToken: null, + // A function can be passed as `onComment` option, which will + // cause Acorn to call that function with `(block, text, start, + // end)` parameters whenever a comment is skipped. `block` is a + // boolean indicating whether this is a block (`/* */`) comment, + // `text` is the content of the comment, and `start` and `end` are + // character offsets that denote the start and end of the comment. + // When the `locations` option is on, two more parameters are + // passed, the full `{line, column}` locations of the start and + // end of the comments. Note that you are not allowed to call the + // parser from the callback—that will corrupt its internal state. + onComment: null, + // Nodes have their start and end characters offsets recorded in + // `start` and `end` properties (directly on the node, rather than + // the `loc` object, which holds line/column data. To also add a + // [semi-standardized][range] `range` property holding a `[start, + // end]` array with the same numbers, set the `ranges` option to + // `true`. + // + // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + ranges: false, + // It is possible to parse multiple files into a single AST by + // passing the tree produced by parsing the first file as + // `program` option in subsequent parses. This will add the + // toplevel forms of the parsed file to the `Program` (top) node + // of an existing parse tree. + program: null, + // When `locations` is on, you can pass this to record the source + // file in every node's `loc` object. + sourceFile: null, + // This value, if given, is stored in every node, whether + // `locations` is on or off. + directSourceFile: null, + // When enabled, parenthesized expressions are represented by + // (non-standard) ParenthesizedExpression nodes + preserveParens: false + }; + + // Interpret and default an options object + + function getOptions(opts) { + var options = {}; + + for (var opt in defaultOptions) + { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; } + + if (options.ecmaVersion >= 2015) + { options.ecmaVersion -= 2009; } + + if (options.allowReserved == null) + { options.allowReserved = options.ecmaVersion < 5; } + + if (isArray(options.onToken)) { + var tokens = options.onToken; + options.onToken = function (token) { return tokens.push(token); }; + } + if (isArray(options.onComment)) + { options.onComment = pushComment(options, options.onComment); } + + return options + } + + function pushComment(options, array) { + return function(block, text, start, end, startLoc, endLoc) { + var comment = { + type: block ? "Block" : "Line", + value: text, + start: start, + end: end + }; + if (options.locations) + { comment.loc = new SourceLocation(this, startLoc, endLoc); } + if (options.ranges) + { comment.range = [start, end]; } + array.push(comment); + } + } + + // Each scope gets a bitset that may contain these flags + var + SCOPE_TOP = 1, + SCOPE_FUNCTION = 2, + SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION, + SCOPE_ASYNC = 4, + SCOPE_GENERATOR = 8, + SCOPE_ARROW = 16, + SCOPE_SIMPLE_CATCH = 32, + SCOPE_SUPER = 64, + SCOPE_DIRECT_SUPER = 128; + + function functionFlags(async, generator) { + return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0) + } + + // Used in checkLVal and declareName to determine the type of a binding + var + BIND_NONE = 0, // Not a binding + BIND_VAR = 1, // Var-style binding + BIND_LEXICAL = 2, // Let- or const-style binding + BIND_FUNCTION = 3, // Function declaration + BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding + BIND_OUTSIDE = 5; // Special case for function names as bound inside the function + + var Parser = function Parser(options, input, startPos) { + this.options = options = getOptions(options); + this.sourceFile = options.sourceFile; + this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]); + var reserved = ""; + if (options.allowReserved !== true) { + for (var v = options.ecmaVersion;; v--) + { if (reserved = reservedWords[v]) { break } } + if (options.sourceType === "module") { reserved += " await"; } + } + this.reservedWords = wordsRegexp(reserved); + var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; + this.reservedWordsStrict = wordsRegexp(reservedStrict); + this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind); + this.input = String(input); + + // Used to signal to callers of `readWord1` whether the word + // contained any escape sequences. This is needed because words with + // escape sequences must not be interpreted as keywords. + this.containsEsc = false; + + // Set up token state + + // The current position of the tokenizer in the input. + if (startPos) { + this.pos = startPos; + this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; + this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; + } else { + this.pos = this.lineStart = 0; + this.curLine = 1; + } + + // Properties of the current token: + // Its type + this.type = types.eof; + // For tokens that include more information than their type, the value + this.value = null; + // Its start and end offset + this.start = this.end = this.pos; + // And, if locations are used, the {line, column} object + // corresponding to those offsets + this.startLoc = this.endLoc = this.curPosition(); + + // Position information for the previous token + this.lastTokEndLoc = this.lastTokStartLoc = null; + this.lastTokStart = this.lastTokEnd = this.pos; + + // The context stack is used to superficially track syntactic + // context to predict whether a regular expression is allowed in a + // given position. + this.context = this.initialContext(); + this.exprAllowed = true; + + // Figure out if it's a module code. + this.inModule = options.sourceType === "module"; + this.strict = this.inModule || this.strictDirective(this.pos); + + // Used to signify the start of a potential arrow function + this.potentialArrowAt = -1; + + // Positions to delayed-check that yield/await does not exist in default parameters. + this.yieldPos = this.awaitPos = this.awaitIdentPos = 0; + // Labels in scope. + this.labels = []; + // Thus-far undefined exports. + this.undefinedExports = {}; + + // If enabled, skip leading hashbang line. + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") + { this.skipLineComment(2); } + + // Scope tracking for duplicate variable names (see scope.js) + this.scopeStack = []; + this.enterScope(SCOPE_TOP); + + // For RegExp validation + this.regexpState = null; + }; + + var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true } }; + + Parser.prototype.parse = function parse () { + var node = this.options.program || this.startNode(); + this.nextToken(); + return this.parseTopLevel(node) + }; + + prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }; + prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 }; + prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 }; + prototypeAccessors.allowSuper.get = function () { return (this.currentThisScope().flags & SCOPE_SUPER) > 0 }; + prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 }; + prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) }; + + // Switch to a getter for 7.0.0. + Parser.prototype.inNonArrowFunction = function inNonArrowFunction () { return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0 }; + + Parser.extend = function extend () { + var plugins = [], len = arguments.length; + while ( len-- ) plugins[ len ] = arguments[ len ]; + + var cls = this; + for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } + return cls + }; + + Parser.parse = function parse (input, options) { + return new this(options, input).parse() + }; + + Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) { + var parser = new this(options, input, pos); + parser.nextToken(); + return parser.parseExpression() + }; + + Parser.tokenizer = function tokenizer (input, options) { + return new this(options, input) + }; + + Object.defineProperties( Parser.prototype, prototypeAccessors ); + + var pp = Parser.prototype; + + // ## Parser utilities + + var literal = /^(?:'((?:\\.|[^'\\])*?)'|"((?:\\.|[^"\\])*?)")/; + pp.strictDirective = function(start) { + for (;;) { + // Try to find string literal. + skipWhiteSpace.lastIndex = start; + start += skipWhiteSpace.exec(this.input)[0].length; + var match = literal.exec(this.input.slice(start)); + if (!match) { return false } + if ((match[1] || match[2]) === "use strict") { + skipWhiteSpace.lastIndex = start + match[0].length; + var spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length; + var next = this.input.charAt(end); + return next === ";" || next === "}" || + (lineBreak.test(spaceAfter[0]) && + !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "=")) + } + start += match[0].length; + + // Skip semicolon, if any. + skipWhiteSpace.lastIndex = start; + start += skipWhiteSpace.exec(this.input)[0].length; + if (this.input[start] === ";") + { start++; } + } + }; + + // Predicate that tests whether the next token is of the given + // type, and if yes, consumes it as a side effect. + + pp.eat = function(type) { + if (this.type === type) { + this.next(); + return true + } else { + return false + } + }; + + // Tests whether parsed token is a contextual keyword. + + pp.isContextual = function(name) { + return this.type === types.name && this.value === name && !this.containsEsc + }; + + // Consumes contextual keyword if possible. + + pp.eatContextual = function(name) { + if (!this.isContextual(name)) { return false } + this.next(); + return true + }; + + // Asserts that following token is given contextual keyword. + + pp.expectContextual = function(name) { + if (!this.eatContextual(name)) { this.unexpected(); } + }; + + // Test whether a semicolon can be inserted at the current position. + + pp.canInsertSemicolon = function() { + return this.type === types.eof || + this.type === types.braceR || + lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) + }; + + pp.insertSemicolon = function() { + if (this.canInsertSemicolon()) { + if (this.options.onInsertedSemicolon) + { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } + return true + } + }; + + // Consume a semicolon, or, failing that, see if we are allowed to + // pretend that there is a semicolon at this position. + + pp.semicolon = function() { + if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); } + }; + + pp.afterTrailingComma = function(tokType, notNext) { + if (this.type === tokType) { + if (this.options.onTrailingComma) + { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } + if (!notNext) + { this.next(); } + return true + } + }; + + // Expect a token of a given type. If found, consume it, otherwise, + // raise an unexpected token error. + + pp.expect = function(type) { + this.eat(type) || this.unexpected(); + }; + + // Raise an unexpected token error. + + pp.unexpected = function(pos) { + this.raise(pos != null ? pos : this.start, "Unexpected token"); + }; + + function DestructuringErrors() { + this.shorthandAssign = + this.trailingComma = + this.parenthesizedAssign = + this.parenthesizedBind = + this.doubleProto = + -1; + } + + pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { + if (!refDestructuringErrors) { return } + if (refDestructuringErrors.trailingComma > -1) + { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } + var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; + if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); } + }; + + pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { + if (!refDestructuringErrors) { return false } + var shorthandAssign = refDestructuringErrors.shorthandAssign; + var doubleProto = refDestructuringErrors.doubleProto; + if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } + if (shorthandAssign >= 0) + { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } + if (doubleProto >= 0) + { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } + }; + + pp.checkYieldAwaitInDefaultParams = function() { + if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) + { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } + if (this.awaitPos) + { this.raise(this.awaitPos, "Await expression cannot be a default value"); } + }; + + pp.isSimpleAssignTarget = function(expr) { + if (expr.type === "ParenthesizedExpression") + { return this.isSimpleAssignTarget(expr.expression) } + return expr.type === "Identifier" || expr.type === "MemberExpression" + }; + + var pp$1 = Parser.prototype; + + // ### Statement parsing + + // Parse a program. Initializes the parser, reads any number of + // statements, and wraps them in a Program node. Optionally takes a + // `program` argument. If present, the statements will be appended + // to its body instead of creating a new node. + + pp$1.parseTopLevel = function(node) { + var exports = {}; + if (!node.body) { node.body = []; } + while (this.type !== types.eof) { + var stmt = this.parseStatement(null, true, exports); + node.body.push(stmt); + } + if (this.inModule) + { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1) + { + var name = list[i]; + + this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined")); + } } + this.adaptDirectivePrologue(node.body); + this.next(); + node.sourceType = this.options.sourceType; + return this.finishNode(node, "Program") + }; + + var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}; + + pp$1.isLet = function(context) { + if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); + // For ambiguous cases, determine if a LexicalDeclaration (or only a + // Statement) is allowed here. If context is not empty then only a Statement + // is allowed. However, `let [` is an explicit negative lookahead for + // ExpressionStatement, so special-case it first. + if (nextCh === 91) { return true } // '[' + if (context) { return false } + + if (nextCh === 123) { return true } // '{' + if (isIdentifierStart(nextCh, true)) { + var pos = next + 1; + while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; } + var ident = this.input.slice(next, pos); + if (!keywordRelationalOperator.test(ident)) { return true } + } + return false + }; + + // check 'async [no LineTerminator here] function' + // - 'async /*foo*/ function' is OK. + // - 'async /*\n*/ function' is invalid. + pp$1.isAsyncFunction = function() { + if (this.options.ecmaVersion < 8 || !this.isContextual("async")) + { return false } + + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length; + return !lineBreak.test(this.input.slice(this.pos, next)) && + this.input.slice(next, next + 8) === "function" && + (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) + }; + + // Parse a single statement. + // + // If expecting a statement and finding a slash operator, parse a + // regular expression literal. This is to handle cases like + // `if (foo) /blah/.exec(foo)`, where looking at the previous token + // does not help. + + pp$1.parseStatement = function(context, topLevel, exports) { + var starttype = this.type, node = this.startNode(), kind; + + if (this.isLet(context)) { + starttype = types._var; + kind = "let"; + } + + // Most types of statements are recognized by the keyword they + // start with. Many are trivial to parse, some require a bit of + // complexity. + + switch (starttype) { + case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword) + case types._debugger: return this.parseDebuggerStatement(node) + case types._do: return this.parseDoStatement(node) + case types._for: return this.parseForStatement(node) + case types._function: + // Function as sole body of either an if statement or a labeled statement + // works, but not when it is part of a labeled statement that is the sole + // body of an if statement. + if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); } + return this.parseFunctionStatement(node, false, !context) + case types._class: + if (context) { this.unexpected(); } + return this.parseClass(node, true) + case types._if: return this.parseIfStatement(node) + case types._return: return this.parseReturnStatement(node) + case types._switch: return this.parseSwitchStatement(node) + case types._throw: return this.parseThrowStatement(node) + case types._try: return this.parseTryStatement(node) + case types._const: case types._var: + kind = kind || this.value; + if (context && kind !== "var") { this.unexpected(); } + return this.parseVarStatement(node, kind) + case types._while: return this.parseWhileStatement(node) + case types._with: return this.parseWithStatement(node) + case types.braceL: return this.parseBlock(true, node) + case types.semi: return this.parseEmptyStatement(node) + case types._export: + case types._import: + if (this.options.ecmaVersion > 10 && starttype === types._import) { + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); + if (nextCh === 40 || nextCh === 46) // '(' or '.' + { return this.parseExpressionStatement(node, this.parseExpression()) } + } + + if (!this.options.allowImportExportEverywhere) { + if (!topLevel) + { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } + if (!this.inModule) + { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } + } + return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports) + + // If the statement does not start with a statement keyword or a + // brace, it's an ExpressionStatement or LabeledStatement. We + // simply start parsing an expression, and afterwards, if the + // next token is a colon and the expression was a simple + // Identifier node, we switch to interpreting it as a label. + default: + if (this.isAsyncFunction()) { + if (context) { this.unexpected(); } + this.next(); + return this.parseFunctionStatement(node, true, !context) + } + + var maybeName = this.value, expr = this.parseExpression(); + if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) + { return this.parseLabeledStatement(node, maybeName, expr, context) } + else { return this.parseExpressionStatement(node, expr) } + } + }; + + pp$1.parseBreakContinueStatement = function(node, keyword) { + var isBreak = keyword === "break"; + this.next(); + if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; } + else if (this.type !== types.name) { this.unexpected(); } + else { + node.label = this.parseIdent(); + this.semicolon(); + } + + // Verify that there is an actual destination to break or + // continue to. + var i = 0; + for (; i < this.labels.length; ++i) { + var lab = this.labels[i]; + if (node.label == null || lab.name === node.label.name) { + if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } + if (node.label && isBreak) { break } + } + } + if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } + return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") + }; + + pp$1.parseDebuggerStatement = function(node) { + this.next(); + this.semicolon(); + return this.finishNode(node, "DebuggerStatement") + }; + + pp$1.parseDoStatement = function(node) { + this.next(); + this.labels.push(loopLabel); + node.body = this.parseStatement("do"); + this.labels.pop(); + this.expect(types._while); + node.test = this.parseParenExpression(); + if (this.options.ecmaVersion >= 6) + { this.eat(types.semi); } + else + { this.semicolon(); } + return this.finishNode(node, "DoWhileStatement") + }; + + // Disambiguating between a `for` and a `for`/`in` or `for`/`of` + // loop is non-trivial. Basically, we have to parse the init `var` + // statement or expression, disallowing the `in` operator (see + // the second parameter to `parseExpression`), and then check + // whether the next token is `in` or `of`. When there is no init + // part (semicolon immediately after the opening parenthesis), it + // is a regular `for` loop. + + pp$1.parseForStatement = function(node) { + this.next(); + var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1; + this.labels.push(loopLabel); + this.enterScope(0); + this.expect(types.parenL); + if (this.type === types.semi) { + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, null) + } + var isLet = this.isLet(); + if (this.type === types._var || this.type === types._const || isLet) { + var init$1 = this.startNode(), kind = isLet ? "let" : this.value; + this.next(); + this.parseVar(init$1, true, kind); + this.finishNode(init$1, "VariableDeclaration"); + if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1) { + if (this.options.ecmaVersion >= 9) { + if (this.type === types._in) { + if (awaitAt > -1) { this.unexpected(awaitAt); } + } else { node.await = awaitAt > -1; } + } + return this.parseForIn(node, init$1) + } + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, init$1) + } + var refDestructuringErrors = new DestructuringErrors; + var init = this.parseExpression(true, refDestructuringErrors); + if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { + if (this.options.ecmaVersion >= 9) { + if (this.type === types._in) { + if (awaitAt > -1) { this.unexpected(awaitAt); } + } else { node.await = awaitAt > -1; } + } + this.toAssignable(init, false, refDestructuringErrors); + this.checkLVal(init); + return this.parseForIn(node, init) + } else { + this.checkExpressionErrors(refDestructuringErrors, true); + } + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, init) + }; + + pp$1.parseFunctionStatement = function(node, isAsync, declarationPosition) { + this.next(); + return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync) + }; + + pp$1.parseIfStatement = function(node) { + this.next(); + node.test = this.parseParenExpression(); + // allow function declarations in branches, but only in non-strict mode + node.consequent = this.parseStatement("if"); + node.alternate = this.eat(types._else) ? this.parseStatement("if") : null; + return this.finishNode(node, "IfStatement") + }; + + pp$1.parseReturnStatement = function(node) { + if (!this.inFunction && !this.options.allowReturnOutsideFunction) + { this.raise(this.start, "'return' outside of function"); } + this.next(); + + // In `return` (and `break`/`continue`), the keywords with + // optional arguments, we eagerly look for a semicolon or the + // possibility to insert one. + + if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; } + else { node.argument = this.parseExpression(); this.semicolon(); } + return this.finishNode(node, "ReturnStatement") + }; + + pp$1.parseSwitchStatement = function(node) { + this.next(); + node.discriminant = this.parseParenExpression(); + node.cases = []; + this.expect(types.braceL); + this.labels.push(switchLabel); + this.enterScope(0); + + // Statements under must be grouped (by label) in SwitchCase + // nodes. `cur` is used to keep the node that we are currently + // adding statements to. + + var cur; + for (var sawDefault = false; this.type !== types.braceR;) { + if (this.type === types._case || this.type === types._default) { + var isCase = this.type === types._case; + if (cur) { this.finishNode(cur, "SwitchCase"); } + node.cases.push(cur = this.startNode()); + cur.consequent = []; + this.next(); + if (isCase) { + cur.test = this.parseExpression(); + } else { + if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); } + sawDefault = true; + cur.test = null; + } + this.expect(types.colon); + } else { + if (!cur) { this.unexpected(); } + cur.consequent.push(this.parseStatement(null)); + } + } + this.exitScope(); + if (cur) { this.finishNode(cur, "SwitchCase"); } + this.next(); // Closing brace + this.labels.pop(); + return this.finishNode(node, "SwitchStatement") + }; + + pp$1.parseThrowStatement = function(node) { + this.next(); + if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) + { this.raise(this.lastTokEnd, "Illegal newline after throw"); } + node.argument = this.parseExpression(); + this.semicolon(); + return this.finishNode(node, "ThrowStatement") + }; + + // Reused empty array added for node fields that are always empty. + + var empty = []; + + pp$1.parseTryStatement = function(node) { + this.next(); + node.block = this.parseBlock(); + node.handler = null; + if (this.type === types._catch) { + var clause = this.startNode(); + this.next(); + if (this.eat(types.parenL)) { + clause.param = this.parseBindingAtom(); + var simple = clause.param.type === "Identifier"; + this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0); + this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL); + this.expect(types.parenR); + } else { + if (this.options.ecmaVersion < 10) { this.unexpected(); } + clause.param = null; + this.enterScope(0); + } + clause.body = this.parseBlock(false); + this.exitScope(); + node.handler = this.finishNode(clause, "CatchClause"); + } + node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; + if (!node.handler && !node.finalizer) + { this.raise(node.start, "Missing catch or finally clause"); } + return this.finishNode(node, "TryStatement") + }; + + pp$1.parseVarStatement = function(node, kind) { + this.next(); + this.parseVar(node, false, kind); + this.semicolon(); + return this.finishNode(node, "VariableDeclaration") + }; + + pp$1.parseWhileStatement = function(node) { + this.next(); + node.test = this.parseParenExpression(); + this.labels.push(loopLabel); + node.body = this.parseStatement("while"); + this.labels.pop(); + return this.finishNode(node, "WhileStatement") + }; + + pp$1.parseWithStatement = function(node) { + if (this.strict) { this.raise(this.start, "'with' in strict mode"); } + this.next(); + node.object = this.parseParenExpression(); + node.body = this.parseStatement("with"); + return this.finishNode(node, "WithStatement") + }; + + pp$1.parseEmptyStatement = function(node) { + this.next(); + return this.finishNode(node, "EmptyStatement") + }; + + pp$1.parseLabeledStatement = function(node, maybeName, expr, context) { + for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1) + { + var label = list[i$1]; + + if (label.name === maybeName) + { this.raise(expr.start, "Label '" + maybeName + "' is already declared"); + } } + var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null; + for (var i = this.labels.length - 1; i >= 0; i--) { + var label$1 = this.labels[i]; + if (label$1.statementStart === node.start) { + // Update information about previous labels on this node + label$1.statementStart = this.start; + label$1.kind = kind; + } else { break } + } + this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); + node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label"); + this.labels.pop(); + node.label = expr; + return this.finishNode(node, "LabeledStatement") + }; + + pp$1.parseExpressionStatement = function(node, expr) { + node.expression = expr; + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") + }; + + // Parse a semicolon-enclosed block of statements, handling `"use + // strict"` declarations when `allowStrict` is true (used for + // function bodies). + + pp$1.parseBlock = function(createNewLexicalScope, node, exitStrict) { + if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; + if ( node === void 0 ) node = this.startNode(); + + node.body = []; + this.expect(types.braceL); + if (createNewLexicalScope) { this.enterScope(0); } + while (this.type !== types.braceR) { + var stmt = this.parseStatement(null); + node.body.push(stmt); + } + if (exitStrict) { this.strict = false; } + this.next(); + if (createNewLexicalScope) { this.exitScope(); } + return this.finishNode(node, "BlockStatement") + }; + + // Parse a regular `for` loop. The disambiguation code in + // `parseStatement` will already have parsed the init statement or + // expression. + + pp$1.parseFor = function(node, init) { + node.init = init; + this.expect(types.semi); + node.test = this.type === types.semi ? null : this.parseExpression(); + this.expect(types.semi); + node.update = this.type === types.parenR ? null : this.parseExpression(); + this.expect(types.parenR); + node.body = this.parseStatement("for"); + this.exitScope(); + this.labels.pop(); + return this.finishNode(node, "ForStatement") + }; + + // Parse a `for`/`in` and `for`/`of` loop, which are almost + // same from parser's perspective. + + pp$1.parseForIn = function(node, init) { + var isForIn = this.type === types._in; + this.next(); + + if ( + init.type === "VariableDeclaration" && + init.declarations[0].init != null && + ( + !isForIn || + this.options.ecmaVersion < 8 || + this.strict || + init.kind !== "var" || + init.declarations[0].id.type !== "Identifier" + ) + ) { + this.raise( + init.start, + ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer") + ); + } else if (init.type === "AssignmentPattern") { + this.raise(init.start, "Invalid left-hand side in for-loop"); + } + node.left = init; + node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign(); + this.expect(types.parenR); + node.body = this.parseStatement("for"); + this.exitScope(); + this.labels.pop(); + return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement") + }; + + // Parse a list of variable declarations. + + pp$1.parseVar = function(node, isFor, kind) { + node.declarations = []; + node.kind = kind; + for (;;) { + var decl = this.startNode(); + this.parseVarId(decl, kind); + if (this.eat(types.eq)) { + decl.init = this.parseMaybeAssign(isFor); + } else if (kind === "const" && !(this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { + this.unexpected(); + } else if (decl.id.type !== "Identifier" && !(isFor && (this.type === types._in || this.isContextual("of")))) { + this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); + } else { + decl.init = null; + } + node.declarations.push(this.finishNode(decl, "VariableDeclarator")); + if (!this.eat(types.comma)) { break } + } + return node + }; + + pp$1.parseVarId = function(decl, kind) { + decl.id = this.parseBindingAtom(); + this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false); + }; + + var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4; + + // Parse a function declaration or literal (depending on the + // `statement & FUNC_STATEMENT`). + + // Remove `allowExpressionBody` for 7.0.0, as it is only called with false + pp$1.parseFunction = function(node, statement, allowExpressionBody, isAsync) { + this.initFunction(node); + if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) { + if (this.type === types.star && (statement & FUNC_HANGING_STATEMENT)) + { this.unexpected(); } + node.generator = this.eat(types.star); + } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + + if (statement & FUNC_STATEMENT) { + node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name ? null : this.parseIdent(); + if (node.id && !(statement & FUNC_HANGING_STATEMENT)) + // If it is a regular function declaration in sloppy mode, then it is + // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding + // mode depends on properties of the current scope (see + // treatFunctionsAsVar). + { this.checkLVal(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); } + } + + var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + this.enterScope(functionFlags(node.async, node.generator)); + + if (!(statement & FUNC_STATEMENT)) + { node.id = this.type === types.name ? this.parseIdent() : null; } + + this.parseFunctionParams(node); + this.parseFunctionBody(node, allowExpressionBody, false); + + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression") + }; + + pp$1.parseFunctionParams = function(node) { + this.expect(types.parenL); + node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); + }; + + // Parse a class declaration or literal (depending on the + // `isStatement` parameter). + + pp$1.parseClass = function(node, isStatement) { + this.next(); + + // ecma-262 14.6 Class Definitions + // A class definition is always strict mode code. + var oldStrict = this.strict; + this.strict = true; + + this.parseClassId(node, isStatement); + this.parseClassSuper(node); + var classBody = this.startNode(); + var hadConstructor = false; + classBody.body = []; + this.expect(types.braceL); + while (this.type !== types.braceR) { + var element = this.parseClassElement(node.superClass !== null); + if (element) { + classBody.body.push(element); + if (element.type === "MethodDefinition" && element.kind === "constructor") { + if (hadConstructor) { this.raise(element.start, "Duplicate constructor in the same class"); } + hadConstructor = true; + } + } + } + this.strict = oldStrict; + this.next(); + node.body = this.finishNode(classBody, "ClassBody"); + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") + }; + + pp$1.parseClassElement = function(constructorAllowsSuper) { + var this$1 = this; + + if (this.eat(types.semi)) { return null } + + var method = this.startNode(); + var tryContextual = function (k, noLineBreak) { + if ( noLineBreak === void 0 ) noLineBreak = false; + + var start = this$1.start, startLoc = this$1.startLoc; + if (!this$1.eatContextual(k)) { return false } + if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true } + if (method.key) { this$1.unexpected(); } + method.computed = false; + method.key = this$1.startNodeAt(start, startLoc); + method.key.name = k; + this$1.finishNode(method.key, "Identifier"); + return false + }; + + method.kind = "method"; + method.static = tryContextual("static"); + var isGenerator = this.eat(types.star); + var isAsync = false; + if (!isGenerator) { + if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); + } else if (tryContextual("get")) { + method.kind = "get"; + } else if (tryContextual("set")) { + method.kind = "set"; + } + } + if (!method.key) { this.parsePropertyName(method); } + var key = method.key; + var allowsDirectSuper = false; + if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || + key.type === "Literal" && key.value === "constructor")) { + if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); } + if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } + if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } + method.kind = "constructor"; + allowsDirectSuper = constructorAllowsSuper; + } else if (method.static && key.type === "Identifier" && key.name === "prototype") { + this.raise(key.start, "Classes may not have a static property named prototype"); + } + this.parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper); + if (method.kind === "get" && method.value.params.length !== 0) + { this.raiseRecoverable(method.value.start, "getter should have no params"); } + if (method.kind === "set" && method.value.params.length !== 1) + { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); } + if (method.kind === "set" && method.value.params[0].type === "RestElement") + { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); } + return method + }; + + pp$1.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) { + method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper); + return this.finishNode(method, "MethodDefinition") + }; + + pp$1.parseClassId = function(node, isStatement) { + if (this.type === types.name) { + node.id = this.parseIdent(); + if (isStatement) + { this.checkLVal(node.id, BIND_LEXICAL, false); } + } else { + if (isStatement === true) + { this.unexpected(); } + node.id = null; + } + }; + + pp$1.parseClassSuper = function(node) { + node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; + }; + + // Parses module export declaration. + + pp$1.parseExport = function(node, exports) { + this.next(); + // export * from '...' + if (this.eat(types.star)) { + if (this.options.ecmaVersion >= 11) { + if (this.eatContextual("as")) { + node.exported = this.parseIdent(true); + this.checkExport(exports, node.exported.name, this.lastTokStart); + } else { + node.exported = null; + } + } + this.expectContextual("from"); + if (this.type !== types.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(types._default)) { // export default ... + this.checkExport(exports, "default", this.lastTokStart); + var isAsync; + if (this.type === types._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { this.next(); } + node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync); + } else if (this.type === types._class) { + var cNode = this.startNode(); + node.declaration = this.parseClass(cNode, "nullableID"); + } else { + node.declaration = this.parseMaybeAssign(); + this.semicolon(); + } + return this.finishNode(node, "ExportDefaultDeclaration") + } + // export var|const|let|function|class ... + if (this.shouldParseExportStatement()) { + node.declaration = this.parseStatement(null); + if (node.declaration.type === "VariableDeclaration") + { this.checkVariableExport(exports, node.declaration.declarations); } + else + { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } + node.specifiers = []; + node.source = null; + } else { // export { x, y as z } [from '...'] + node.declaration = null; + node.specifiers = this.parseExportSpecifiers(exports); + if (this.eatContextual("from")) { + if (this.type !== types.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + } else { + for (var i = 0, list = node.specifiers; i < list.length; i += 1) { + // check for keywords used as local names + var spec = list[i]; + + this.checkUnreserved(spec.local); + // check if export is defined + this.checkLocalExport(spec.local); + } + + node.source = null; + } + this.semicolon(); + } + return this.finishNode(node, "ExportNamedDeclaration") + }; + + pp$1.checkExport = function(exports, name, pos) { + if (!exports) { return } + if (has(exports, name)) + { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } + exports[name] = true; + }; + + pp$1.checkPatternExport = function(exports, pat) { + var type = pat.type; + if (type === "Identifier") + { this.checkExport(exports, pat.name, pat.start); } + else if (type === "ObjectPattern") + { for (var i = 0, list = pat.properties; i < list.length; i += 1) + { + var prop = list[i]; + + this.checkPatternExport(exports, prop); + } } + else if (type === "ArrayPattern") + { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { + var elt = list$1[i$1]; + + if (elt) { this.checkPatternExport(exports, elt); } + } } + else if (type === "Property") + { this.checkPatternExport(exports, pat.value); } + else if (type === "AssignmentPattern") + { this.checkPatternExport(exports, pat.left); } + else if (type === "RestElement") + { this.checkPatternExport(exports, pat.argument); } + else if (type === "ParenthesizedExpression") + { this.checkPatternExport(exports, pat.expression); } + }; + + pp$1.checkVariableExport = function(exports, decls) { + if (!exports) { return } + for (var i = 0, list = decls; i < list.length; i += 1) + { + var decl = list[i]; + + this.checkPatternExport(exports, decl.id); + } + }; + + pp$1.shouldParseExportStatement = function() { + return this.type.keyword === "var" || + this.type.keyword === "const" || + this.type.keyword === "class" || + this.type.keyword === "function" || + this.isLet() || + this.isAsyncFunction() + }; + + // Parses a comma-separated list of module exports. + + pp$1.parseExportSpecifiers = function(exports) { + var nodes = [], first = true; + // export { x, y as z } [from '...'] + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + if (!first) { + this.expect(types.comma); + if (this.afterTrailingComma(types.braceR)) { break } + } else { first = false; } + + var node = this.startNode(); + node.local = this.parseIdent(true); + node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local; + this.checkExport(exports, node.exported.name, node.exported.start); + nodes.push(this.finishNode(node, "ExportSpecifier")); + } + return nodes + }; + + // Parses import declaration. + + pp$1.parseImport = function(node) { + this.next(); + // import '...' + if (this.type === types.string) { + node.specifiers = empty; + node.source = this.parseExprAtom(); + } else { + node.specifiers = this.parseImportSpecifiers(); + this.expectContextual("from"); + node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); + } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration") + }; + + // Parses a comma-separated list of module imports. + + pp$1.parseImportSpecifiers = function() { + var nodes = [], first = true; + if (this.type === types.name) { + // import defaultObj, { x, y as z } from '...' + var node = this.startNode(); + node.local = this.parseIdent(); + this.checkLVal(node.local, BIND_LEXICAL); + nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); + if (!this.eat(types.comma)) { return nodes } + } + if (this.type === types.star) { + var node$1 = this.startNode(); + this.next(); + this.expectContextual("as"); + node$1.local = this.parseIdent(); + this.checkLVal(node$1.local, BIND_LEXICAL); + nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); + return nodes + } + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + if (!first) { + this.expect(types.comma); + if (this.afterTrailingComma(types.braceR)) { break } + } else { first = false; } + + var node$2 = this.startNode(); + node$2.imported = this.parseIdent(true); + if (this.eatContextual("as")) { + node$2.local = this.parseIdent(); + } else { + this.checkUnreserved(node$2.imported); + node$2.local = node$2.imported; + } + this.checkLVal(node$2.local, BIND_LEXICAL); + nodes.push(this.finishNode(node$2, "ImportSpecifier")); + } + return nodes + }; + + // Set `ExpressionStatement#directive` property for directive prologues. + pp$1.adaptDirectivePrologue = function(statements) { + for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { + statements[i].directive = statements[i].expression.raw.slice(1, -1); + } + }; + pp$1.isDirectiveCandidate = function(statement) { + return ( + statement.type === "ExpressionStatement" && + statement.expression.type === "Literal" && + typeof statement.expression.value === "string" && + // Reject parenthesized strings. + (this.input[statement.start] === "\"" || this.input[statement.start] === "'") + ) + }; + + var pp$2 = Parser.prototype; + + // Convert existing expression atom to assignable pattern + // if possible. + + pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) { + if (this.options.ecmaVersion >= 6 && node) { + switch (node.type) { + case "Identifier": + if (this.inAsync && node.name === "await") + { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); } + break + + case "ObjectPattern": + case "ArrayPattern": + case "RestElement": + break + + case "ObjectExpression": + node.type = "ObjectPattern"; + if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + for (var i = 0, list = node.properties; i < list.length; i += 1) { + var prop = list[i]; + + this.toAssignable(prop, isBinding); + // Early error: + // AssignmentRestProperty[Yield, Await] : + // `...` DestructuringAssignmentTarget[Yield, Await] + // + // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. + if ( + prop.type === "RestElement" && + (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") + ) { + this.raise(prop.argument.start, "Unexpected token"); + } + } + break + + case "Property": + // AssignmentProperty has type === "Property" + if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } + this.toAssignable(node.value, isBinding); + break + + case "ArrayExpression": + node.type = "ArrayPattern"; + if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + this.toAssignableList(node.elements, isBinding); + break + + case "SpreadElement": + node.type = "RestElement"; + this.toAssignable(node.argument, isBinding); + if (node.argument.type === "AssignmentPattern") + { this.raise(node.argument.start, "Rest elements cannot have a default value"); } + break + + case "AssignmentExpression": + if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } + node.type = "AssignmentPattern"; + delete node.operator; + this.toAssignable(node.left, isBinding); + // falls through to AssignmentPattern + + case "AssignmentPattern": + break + + case "ParenthesizedExpression": + this.toAssignable(node.expression, isBinding, refDestructuringErrors); + break + + case "ChainExpression": + this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side"); + break + + case "MemberExpression": + if (!isBinding) { break } + + default: + this.raise(node.start, "Assigning to rvalue"); + } + } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + return node + }; + + // Convert list of expression atoms to binding list. + + pp$2.toAssignableList = function(exprList, isBinding) { + var end = exprList.length; + for (var i = 0; i < end; i++) { + var elt = exprList[i]; + if (elt) { this.toAssignable(elt, isBinding); } + } + if (end) { + var last = exprList[end - 1]; + if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") + { this.unexpected(last.argument.start); } + } + return exprList + }; + + // Parses spread element. + + pp$2.parseSpread = function(refDestructuringErrors) { + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeAssign(false, refDestructuringErrors); + return this.finishNode(node, "SpreadElement") + }; + + pp$2.parseRestBinding = function() { + var node = this.startNode(); + this.next(); + + // RestElement inside of a function parameter must be an identifier + if (this.options.ecmaVersion === 6 && this.type !== types.name) + { this.unexpected(); } + + node.argument = this.parseBindingAtom(); + + return this.finishNode(node, "RestElement") + }; + + // Parses lvalue (assignable) atom. + + pp$2.parseBindingAtom = function() { + if (this.options.ecmaVersion >= 6) { + switch (this.type) { + case types.bracketL: + var node = this.startNode(); + this.next(); + node.elements = this.parseBindingList(types.bracketR, true, true); + return this.finishNode(node, "ArrayPattern") + + case types.braceL: + return this.parseObj(true) + } + } + return this.parseIdent() + }; + + pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) { + var elts = [], first = true; + while (!this.eat(close)) { + if (first) { first = false; } + else { this.expect(types.comma); } + if (allowEmpty && this.type === types.comma) { + elts.push(null); + } else if (allowTrailingComma && this.afterTrailingComma(close)) { + break + } else if (this.type === types.ellipsis) { + var rest = this.parseRestBinding(); + this.parseBindingListItem(rest); + elts.push(rest); + if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); } + this.expect(close); + break + } else { + var elem = this.parseMaybeDefault(this.start, this.startLoc); + this.parseBindingListItem(elem); + elts.push(elem); + } + } + return elts + }; + + pp$2.parseBindingListItem = function(param) { + return param + }; + + // Parses assignment pattern around given atom if possible. + + pp$2.parseMaybeDefault = function(startPos, startLoc, left) { + left = left || this.parseBindingAtom(); + if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left } + var node = this.startNodeAt(startPos, startLoc); + node.left = left; + node.right = this.parseMaybeAssign(); + return this.finishNode(node, "AssignmentPattern") + }; + + // Verify that a node is an lval — something that can be assigned + // to. + // bindingType can be either: + // 'var' indicating that the lval creates a 'var' binding + // 'let' indicating that the lval creates a lexical ('let' or 'const') binding + // 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references + + pp$2.checkLVal = function(expr, bindingType, checkClashes) { + if ( bindingType === void 0 ) bindingType = BIND_NONE; + + switch (expr.type) { + case "Identifier": + if (bindingType === BIND_LEXICAL && expr.name === "let") + { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); } + if (this.strict && this.reservedWordsStrictBind.test(expr.name)) + { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } + if (checkClashes) { + if (has(checkClashes, expr.name)) + { this.raiseRecoverable(expr.start, "Argument name clash"); } + checkClashes[expr.name] = true; + } + if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); } + break + + case "ChainExpression": + this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side"); + break + + case "MemberExpression": + if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); } + break + + case "ObjectPattern": + for (var i = 0, list = expr.properties; i < list.length; i += 1) + { + var prop = list[i]; + + this.checkLVal(prop, bindingType, checkClashes); + } + break + + case "Property": + // AssignmentProperty has type === "Property" + this.checkLVal(expr.value, bindingType, checkClashes); + break + + case "ArrayPattern": + for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { + var elem = list$1[i$1]; + + if (elem) { this.checkLVal(elem, bindingType, checkClashes); } + } + break + + case "AssignmentPattern": + this.checkLVal(expr.left, bindingType, checkClashes); + break + + case "RestElement": + this.checkLVal(expr.argument, bindingType, checkClashes); + break + + case "ParenthesizedExpression": + this.checkLVal(expr.expression, bindingType, checkClashes); + break + + default: + this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue"); + } + }; + + // A recursive descent parser operates by defining functions for all + + var pp$3 = Parser.prototype; + + // Check if property name clashes with already added. + // Object/class getters and setters are not allowed to clash — + // either with each other or with an init property — and in + // strict mode, init properties are also not allowed to be repeated. + + pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) { + if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") + { return } + if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) + { return } + var key = prop.key; + var name; + switch (key.type) { + case "Identifier": name = key.name; break + case "Literal": name = String(key.value); break + default: return + } + var kind = prop.kind; + if (this.options.ecmaVersion >= 6) { + if (name === "__proto__" && kind === "init") { + if (propHash.proto) { + if (refDestructuringErrors) { + if (refDestructuringErrors.doubleProto < 0) + { refDestructuringErrors.doubleProto = key.start; } + // Backwards-compat kludge. Can be removed in version 6.0 + } else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); } + } + propHash.proto = true; + } + return + } + name = "$" + name; + var other = propHash[name]; + if (other) { + var redefinition; + if (kind === "init") { + redefinition = this.strict && other.init || other.get || other.set; + } else { + redefinition = other.init || other[kind]; + } + if (redefinition) + { this.raiseRecoverable(key.start, "Redefinition of property"); } + } else { + other = propHash[name] = { + init: false, + get: false, + set: false + }; + } + other[kind] = true; + }; + + // ### Expression parsing + + // These nest, from the most general expression type at the top to + // 'atomic', nondivisible expression types at the bottom. Most of + // the functions will simply let the function(s) below them parse, + // and, *if* the syntactic construct they handle is present, wrap + // the AST node that the inner parser gave them in another node. + + // Parse a full expression. The optional arguments are used to + // forbid the `in` operator (in for loops initalization expressions) + // and provide reference for storing '=' operator inside shorthand + // property assignment in contexts where both object expression + // and object pattern might appear (so it's possible to raise + // delayed syntax error at correct position). + + pp$3.parseExpression = function(noIn, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); + if (this.type === types.comma) { + var node = this.startNodeAt(startPos, startLoc); + node.expressions = [expr]; + while (this.eat(types.comma)) { node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); } + return this.finishNode(node, "SequenceExpression") + } + return expr + }; + + // Parse an assignment expression. This includes applications of + // operators like `+=`. + + pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { + if (this.isContextual("yield")) { + if (this.inGenerator) { return this.parseYield(noIn) } + // The tokenizer will assume an expression is allowed after + // `yield`, but this isn't that kind of yield + else { this.exprAllowed = false; } + } + + var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1; + if (refDestructuringErrors) { + oldParenAssign = refDestructuringErrors.parenthesizedAssign; + oldTrailingComma = refDestructuringErrors.trailingComma; + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; + } else { + refDestructuringErrors = new DestructuringErrors; + ownDestructuringErrors = true; + } + + var startPos = this.start, startLoc = this.startLoc; + if (this.type === types.parenL || this.type === types.name) + { this.potentialArrowAt = this.start; } + var left = this.parseMaybeConditional(noIn, refDestructuringErrors); + if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } + if (this.type.isAssign) { + var node = this.startNodeAt(startPos, startLoc); + node.operator = this.value; + node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left; + if (!ownDestructuringErrors) { + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1; + } + if (refDestructuringErrors.shorthandAssign >= node.left.start) + { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly + this.checkLVal(left); + this.next(); + node.right = this.parseMaybeAssign(noIn); + return this.finishNode(node, "AssignmentExpression") + } else { + if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } + } + if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } + if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } + return left + }; + + // Parse a ternary conditional (`?:`) operator. + + pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseExprOps(noIn, refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + if (this.eat(types.question)) { + var node = this.startNodeAt(startPos, startLoc); + node.test = expr; + node.consequent = this.parseMaybeAssign(); + this.expect(types.colon); + node.alternate = this.parseMaybeAssign(noIn); + return this.finishNode(node, "ConditionalExpression") + } + return expr + }; + + // Start the precedence parser. + + pp$3.parseExprOps = function(noIn, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseMaybeUnary(refDestructuringErrors, false); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) + }; + + // Parse binary operators with the operator precedence parsing + // algorithm. `left` is the left-hand side of the operator. + // `minPrec` provides context that allows the function to stop and + // defer further parser to one of its callers when it encounters an + // operator that has a lower precedence than the set it is parsing. + + pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { + var prec = this.type.binop; + if (prec != null && (!noIn || this.type !== types._in)) { + if (prec > minPrec) { + var logical = this.type === types.logicalOR || this.type === types.logicalAND; + var coalesce = this.type === types.coalesce; + if (coalesce) { + // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions. + // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error. + prec = types.logicalAND.binop; + } + var op = this.value; + this.next(); + var startPos = this.start, startLoc = this.startLoc; + var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn); + var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce); + if ((logical && this.type === types.coalesce) || (coalesce && (this.type === types.logicalOR || this.type === types.logicalAND))) { + this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses"); + } + return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) + } + } + return left + }; + + pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) { + var node = this.startNodeAt(startPos, startLoc); + node.left = left; + node.operator = op; + node.right = right; + return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") + }; + + // Parse unary operators, both prefix and postfix. + + pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { + var startPos = this.start, startLoc = this.startLoc, expr; + if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) { + expr = this.parseAwait(); + sawUnary = true; + } else if (this.type.prefix) { + var node = this.startNode(), update = this.type === types.incDec; + node.operator = this.value; + node.prefix = true; + this.next(); + node.argument = this.parseMaybeUnary(null, true); + this.checkExpressionErrors(refDestructuringErrors, true); + if (update) { this.checkLVal(node.argument); } + else if (this.strict && node.operator === "delete" && + node.argument.type === "Identifier") + { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } + else { sawUnary = true; } + expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); + } else { + expr = this.parseExprSubscripts(refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + while (this.type.postfix && !this.canInsertSemicolon()) { + var node$1 = this.startNodeAt(startPos, startLoc); + node$1.operator = this.value; + node$1.prefix = false; + node$1.argument = expr; + this.checkLVal(expr); + this.next(); + expr = this.finishNode(node$1, "UpdateExpression"); + } + } + + if (!sawUnary && this.eat(types.starstar)) + { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) } + else + { return expr } + }; + + // Parse call, dot, and `[]`-subscript expressions. + + pp$3.parseExprSubscripts = function(refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseExprAtom(refDestructuringErrors); + if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")") + { return expr } + var result = this.parseSubscripts(expr, startPos, startLoc); + if (refDestructuringErrors && result.type === "MemberExpression") { + if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } + if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } + } + return result + }; + + pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { + var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && + this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && + this.potentialArrowAt === base.start; + var optionalChained = false; + + while (true) { + var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained); + + if (element.optional) { optionalChained = true; } + if (element === base || element.type === "ArrowFunctionExpression") { + if (optionalChained) { + var chainNode = this.startNodeAt(startPos, startLoc); + chainNode.expression = element; + element = this.finishNode(chainNode, "ChainExpression"); + } + return element + } + + base = element; + } + }; + + pp$3.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained) { + var optionalSupported = this.options.ecmaVersion >= 11; + var optional = optionalSupported && this.eat(types.questionDot); + if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); } + + var computed = this.eat(types.bracketL); + if (computed || (optional && this.type !== types.parenL && this.type !== types.backQuote) || this.eat(types.dot)) { + var node = this.startNodeAt(startPos, startLoc); + node.object = base; + node.property = computed ? this.parseExpression() : this.parseIdent(this.options.allowReserved !== "never"); + node.computed = !!computed; + if (computed) { this.expect(types.bracketR); } + if (optionalSupported) { + node.optional = optional; + } + base = this.finishNode(node, "MemberExpression"); + } else if (!noCalls && this.eat(types.parenL)) { + var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + var exprList = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors); + if (maybeAsyncArrow && !optional && !this.canInsertSemicolon() && this.eat(types.arrow)) { + this.checkPatternErrors(refDestructuringErrors, false); + this.checkYieldAwaitInDefaultParams(); + if (this.awaitIdentPos > 0) + { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); } + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true) + } + this.checkExpressionErrors(refDestructuringErrors, true); + this.yieldPos = oldYieldPos || this.yieldPos; + this.awaitPos = oldAwaitPos || this.awaitPos; + this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos; + var node$1 = this.startNodeAt(startPos, startLoc); + node$1.callee = base; + node$1.arguments = exprList; + if (optionalSupported) { + node$1.optional = optional; + } + base = this.finishNode(node$1, "CallExpression"); + } else if (this.type === types.backQuote) { + if (optional || optionalChained) { + this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions"); + } + var node$2 = this.startNodeAt(startPos, startLoc); + node$2.tag = base; + node$2.quasi = this.parseTemplate({isTagged: true}); + base = this.finishNode(node$2, "TaggedTemplateExpression"); + } + return base + }; + + // Parse an atomic expression — either a single token that is an + // expression, an expression started by a keyword like `function` or + // `new`, or an expression wrapped in punctuation like `()`, `[]`, + // or `{}`. + + pp$3.parseExprAtom = function(refDestructuringErrors) { + // If a division operator appears in an expression position, the + // tokenizer got confused, and we force it to read a regexp instead. + if (this.type === types.slash) { this.readRegexp(); } + + var node, canBeArrow = this.potentialArrowAt === this.start; + switch (this.type) { + case types._super: + if (!this.allowSuper) + { this.raise(this.start, "'super' keyword outside a method"); } + node = this.startNode(); + this.next(); + if (this.type === types.parenL && !this.allowDirectSuper) + { this.raise(node.start, "super() call outside constructor of a subclass"); } + // The `super` keyword can appear at below: + // SuperProperty: + // super [ Expression ] + // super . IdentifierName + // SuperCall: + // super ( Arguments ) + if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL) + { this.unexpected(); } + return this.finishNode(node, "Super") + + case types._this: + node = this.startNode(); + this.next(); + return this.finishNode(node, "ThisExpression") + + case types.name: + var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; + var id = this.parseIdent(false); + if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function)) + { return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) } + if (canBeArrow && !this.canInsertSemicolon()) { + if (this.eat(types.arrow)) + { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) } + if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) { + id = this.parseIdent(false); + if (this.canInsertSemicolon() || !this.eat(types.arrow)) + { this.unexpected(); } + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) + } + } + return id + + case types.regexp: + var value = this.value; + node = this.parseLiteral(value.value); + node.regex = {pattern: value.pattern, flags: value.flags}; + return node + + case types.num: case types.string: + return this.parseLiteral(this.value) + + case types._null: case types._true: case types._false: + node = this.startNode(); + node.value = this.type === types._null ? null : this.type === types._true; + node.raw = this.type.keyword; + this.next(); + return this.finishNode(node, "Literal") + + case types.parenL: + var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow); + if (refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) + { refDestructuringErrors.parenthesizedAssign = start; } + if (refDestructuringErrors.parenthesizedBind < 0) + { refDestructuringErrors.parenthesizedBind = start; } + } + return expr + + case types.bracketL: + node = this.startNode(); + this.next(); + node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors); + return this.finishNode(node, "ArrayExpression") + + case types.braceL: + return this.parseObj(false, refDestructuringErrors) + + case types._function: + node = this.startNode(); + this.next(); + return this.parseFunction(node, 0) + + case types._class: + return this.parseClass(this.startNode(), false) + + case types._new: + return this.parseNew() + + case types.backQuote: + return this.parseTemplate() + + case types._import: + if (this.options.ecmaVersion >= 11) { + return this.parseExprImport() + } else { + return this.unexpected() + } + + default: + this.unexpected(); + } + }; + + pp$3.parseExprImport = function() { + var node = this.startNode(); + + // Consume `import` as an identifier for `import.meta`. + // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`. + if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); } + var meta = this.parseIdent(true); + + switch (this.type) { + case types.parenL: + return this.parseDynamicImport(node) + case types.dot: + node.meta = meta; + return this.parseImportMeta(node) + default: + this.unexpected(); + } + }; + + pp$3.parseDynamicImport = function(node) { + this.next(); // skip `(` + + // Parse node.source. + node.source = this.parseMaybeAssign(); + + // Verify ending. + if (!this.eat(types.parenR)) { + var errorPos = this.start; + if (this.eat(types.comma) && this.eat(types.parenR)) { + this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()"); + } else { + this.unexpected(errorPos); + } + } + + return this.finishNode(node, "ImportExpression") + }; + + pp$3.parseImportMeta = function(node) { + this.next(); // skip `.` + + var containsEsc = this.containsEsc; + node.property = this.parseIdent(true); + + if (node.property.name !== "meta") + { this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); } + if (containsEsc) + { this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); } + if (this.options.sourceType !== "module") + { this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); } + + return this.finishNode(node, "MetaProperty") + }; + + pp$3.parseLiteral = function(value) { + var node = this.startNode(); + node.value = value; + node.raw = this.input.slice(this.start, this.end); + if (node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1).replace(/_/g, ""); } + this.next(); + return this.finishNode(node, "Literal") + }; + + pp$3.parseParenExpression = function() { + this.expect(types.parenL); + var val = this.parseExpression(); + this.expect(types.parenR); + return val + }; + + pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { + var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; + if (this.options.ecmaVersion >= 6) { + this.next(); + + var innerStartPos = this.start, innerStartLoc = this.startLoc; + var exprList = [], first = true, lastIsComma = false; + var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; + this.yieldPos = 0; + this.awaitPos = 0; + // Do not save awaitIdentPos to allow checking awaits nested in parameters + while (this.type !== types.parenR) { + first ? first = false : this.expect(types.comma); + if (allowTrailingComma && this.afterTrailingComma(types.parenR, true)) { + lastIsComma = true; + break + } else if (this.type === types.ellipsis) { + spreadStart = this.start; + exprList.push(this.parseParenItem(this.parseRestBinding())); + if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); } + break + } else { + exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); + } + } + var innerEndPos = this.start, innerEndLoc = this.startLoc; + this.expect(types.parenR); + + if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { + this.checkPatternErrors(refDestructuringErrors, false); + this.checkYieldAwaitInDefaultParams(); + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + return this.parseParenArrowList(startPos, startLoc, exprList) + } + + if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } + if (spreadStart) { this.unexpected(spreadStart); } + this.checkExpressionErrors(refDestructuringErrors, true); + this.yieldPos = oldYieldPos || this.yieldPos; + this.awaitPos = oldAwaitPos || this.awaitPos; + + if (exprList.length > 1) { + val = this.startNodeAt(innerStartPos, innerStartLoc); + val.expressions = exprList; + this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); + } else { + val = exprList[0]; + } + } else { + val = this.parseParenExpression(); + } + + if (this.options.preserveParens) { + var par = this.startNodeAt(startPos, startLoc); + par.expression = val; + return this.finishNode(par, "ParenthesizedExpression") + } else { + return val + } + }; + + pp$3.parseParenItem = function(item) { + return item + }; + + pp$3.parseParenArrowList = function(startPos, startLoc, exprList) { + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) + }; + + // New's precedence is slightly tricky. It must allow its argument to + // be a `[]` or dot subscript expression, but not a call — at least, + // not without wrapping it in parentheses. Thus, it uses the noCalls + // argument to parseSubscripts to prevent it from consuming the + // argument list. + + var empty$1 = []; + + pp$3.parseNew = function() { + if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); } + var node = this.startNode(); + var meta = this.parseIdent(true); + if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) { + node.meta = meta; + var containsEsc = this.containsEsc; + node.property = this.parseIdent(true); + if (node.property.name !== "target") + { this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); } + if (containsEsc) + { this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); } + if (!this.inNonArrowFunction()) + { this.raiseRecoverable(node.start, "'new.target' can only be used in functions"); } + return this.finishNode(node, "MetaProperty") + } + var startPos = this.start, startLoc = this.startLoc, isImport = this.type === types._import; + node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); + if (isImport && node.callee.type === "ImportExpression") { + this.raise(startPos, "Cannot use new with import()"); + } + if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); } + else { node.arguments = empty$1; } + return this.finishNode(node, "NewExpression") + }; + + // Parse template expression. + + pp$3.parseTemplateElement = function(ref) { + var isTagged = ref.isTagged; + + var elem = this.startNode(); + if (this.type === types.invalidTemplate) { + if (!isTagged) { + this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); + } + elem.value = { + raw: this.value, + cooked: null + }; + } else { + elem.value = { + raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), + cooked: this.value + }; + } + this.next(); + elem.tail = this.type === types.backQuote; + return this.finishNode(elem, "TemplateElement") + }; + + pp$3.parseTemplate = function(ref) { + if ( ref === void 0 ) ref = {}; + var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; + + var node = this.startNode(); + this.next(); + node.expressions = []; + var curElt = this.parseTemplateElement({isTagged: isTagged}); + node.quasis = [curElt]; + while (!curElt.tail) { + if (this.type === types.eof) { this.raise(this.pos, "Unterminated template literal"); } + this.expect(types.dollarBraceL); + node.expressions.push(this.parseExpression()); + this.expect(types.braceR); + node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged})); + } + this.next(); + return this.finishNode(node, "TemplateLiteral") + }; + + pp$3.isAsyncProp = function(prop) { + return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && + (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) && + !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) + }; + + // Parse an object literal or binding pattern. + + pp$3.parseObj = function(isPattern, refDestructuringErrors) { + var node = this.startNode(), first = true, propHash = {}; + node.properties = []; + this.next(); + while (!this.eat(types.braceR)) { + if (!first) { + this.expect(types.comma); + if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types.braceR)) { break } + } else { first = false; } + + var prop = this.parseProperty(isPattern, refDestructuringErrors); + if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); } + node.properties.push(prop); + } + return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") + }; + + pp$3.parseProperty = function(isPattern, refDestructuringErrors) { + var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; + if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) { + if (isPattern) { + prop.argument = this.parseIdent(false); + if (this.type === types.comma) { + this.raise(this.start, "Comma is not permitted after the rest element"); + } + return this.finishNode(prop, "RestElement") + } + // To disallow parenthesized identifier via `this.toAssignable()`. + if (this.type === types.parenL && refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0) { + refDestructuringErrors.parenthesizedAssign = this.start; + } + if (refDestructuringErrors.parenthesizedBind < 0) { + refDestructuringErrors.parenthesizedBind = this.start; + } + } + // Parse argument. + prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); + // To disallow trailing comma via `this.toAssignable()`. + if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { + refDestructuringErrors.trailingComma = this.start; + } + // Finish + return this.finishNode(prop, "SpreadElement") + } + if (this.options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; + if (isPattern || refDestructuringErrors) { + startPos = this.start; + startLoc = this.startLoc; + } + if (!isPattern) + { isGenerator = this.eat(types.star); } + } + var containsEsc = this.containsEsc; + this.parsePropertyName(prop); + if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); + this.parsePropertyName(prop, refDestructuringErrors); + } else { + isAsync = false; + } + this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); + return this.finishNode(prop, "Property") + }; + + pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { + if ((isGenerator || isAsync) && this.type === types.colon) + { this.unexpected(); } + + if (this.eat(types.colon)) { + prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); + prop.kind = "init"; + } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) { + if (isPattern) { this.unexpected(); } + prop.kind = "init"; + prop.method = true; + prop.value = this.parseMethod(isGenerator, isAsync); + } else if (!isPattern && !containsEsc && + this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && + (prop.key.name === "get" || prop.key.name === "set") && + (this.type !== types.comma && this.type !== types.braceR && this.type !== types.eq)) { + if (isGenerator || isAsync) { this.unexpected(); } + prop.kind = prop.key.name; + this.parsePropertyName(prop); + prop.value = this.parseMethod(false); + var paramCount = prop.kind === "get" ? 0 : 1; + if (prop.value.params.length !== paramCount) { + var start = prop.value.start; + if (prop.kind === "get") + { this.raiseRecoverable(start, "getter should have no params"); } + else + { this.raiseRecoverable(start, "setter should have exactly one param"); } + } else { + if (prop.kind === "set" && prop.value.params[0].type === "RestElement") + { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } + } + } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { + if (isGenerator || isAsync) { this.unexpected(); } + this.checkUnreserved(prop.key); + if (prop.key.name === "await" && !this.awaitIdentPos) + { this.awaitIdentPos = startPos; } + prop.kind = "init"; + if (isPattern) { + prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); + } else if (this.type === types.eq && refDestructuringErrors) { + if (refDestructuringErrors.shorthandAssign < 0) + { refDestructuringErrors.shorthandAssign = this.start; } + prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); + } else { + prop.value = prop.key; + } + prop.shorthand = true; + } else { this.unexpected(); } + }; + + pp$3.parsePropertyName = function(prop) { + if (this.options.ecmaVersion >= 6) { + if (this.eat(types.bracketL)) { + prop.computed = true; + prop.key = this.parseMaybeAssign(); + this.expect(types.bracketR); + return prop.key + } else { + prop.computed = false; + } + } + return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never") + }; + + // Initialize empty function node. + + pp$3.initFunction = function(node) { + node.id = null; + if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; } + if (this.options.ecmaVersion >= 8) { node.async = false; } + }; + + // Parse object or class method. + + pp$3.parseMethod = function(isGenerator, isAsync, allowDirectSuper) { + var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + + this.initFunction(node); + if (this.options.ecmaVersion >= 6) + { node.generator = isGenerator; } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0)); + + this.expect(types.parenL); + node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); + this.parseFunctionBody(node, false, true); + + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.finishNode(node, "FunctionExpression") + }; + + // Parse arrow function expression with given parameters. + + pp$3.parseArrowExpression = function(node, params, isAsync) { + var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + + this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW); + this.initFunction(node); + if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } + + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + + node.params = this.toAssignableList(params, true); + this.parseFunctionBody(node, true, false); + + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.finishNode(node, "ArrowFunctionExpression") + }; + + // Parse function body and check parameters. + + pp$3.parseFunctionBody = function(node, isArrowFunction, isMethod) { + var isExpression = isArrowFunction && this.type !== types.braceL; + var oldStrict = this.strict, useStrict = false; + + if (isExpression) { + node.body = this.parseMaybeAssign(); + node.expression = true; + this.checkParams(node, false); + } else { + var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); + if (!oldStrict || nonSimple) { + useStrict = this.strictDirective(this.end); + // If this is a strict mode function, verify that argument names + // are not repeated, and it does not try to bind the words `eval` + // or `arguments`. + if (useStrict && nonSimple) + { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } + } + // Start a new scope with regard to labels and the `inFunction` + // flag (restore them to their old value afterwards). + var oldLabels = this.labels; + this.labels = []; + if (useStrict) { this.strict = true; } + + // Add the params to varDeclaredNames to ensure that an error is thrown + // if a let/const declaration in the function clashes with one of the params. + this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)); + // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' + if (this.strict && node.id) { this.checkLVal(node.id, BIND_OUTSIDE); } + node.body = this.parseBlock(false, undefined, useStrict && !oldStrict); + node.expression = false; + this.adaptDirectivePrologue(node.body.body); + this.labels = oldLabels; + } + this.exitScope(); + }; + + pp$3.isSimpleParamList = function(params) { + for (var i = 0, list = params; i < list.length; i += 1) + { + var param = list[i]; + + if (param.type !== "Identifier") { return false + } } + return true + }; + + // Checks function params for various disallowed patterns such as using "eval" + // or "arguments" and duplicate parameters. + + pp$3.checkParams = function(node, allowDuplicates) { + var nameHash = {}; + for (var i = 0, list = node.params; i < list.length; i += 1) + { + var param = list[i]; + + this.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash); + } + }; + + // Parses a comma-separated list of expressions, and returns them as + // an array. `close` is the token type that ends the list, and + // `allowEmpty` can be turned on to allow subsequent commas with + // nothing in between them to be parsed as `null` (which is needed + // for array literals). + + pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { + var elts = [], first = true; + while (!this.eat(close)) { + if (!first) { + this.expect(types.comma); + if (allowTrailingComma && this.afterTrailingComma(close)) { break } + } else { first = false; } + + var elt = (void 0); + if (allowEmpty && this.type === types.comma) + { elt = null; } + else if (this.type === types.ellipsis) { + elt = this.parseSpread(refDestructuringErrors); + if (refDestructuringErrors && this.type === types.comma && refDestructuringErrors.trailingComma < 0) + { refDestructuringErrors.trailingComma = this.start; } + } else { + elt = this.parseMaybeAssign(false, refDestructuringErrors); + } + elts.push(elt); + } + return elts + }; + + pp$3.checkUnreserved = function(ref) { + var start = ref.start; + var end = ref.end; + var name = ref.name; + + if (this.inGenerator && name === "yield") + { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); } + if (this.inAsync && name === "await") + { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); } + if (this.keywords.test(name)) + { this.raise(start, ("Unexpected keyword '" + name + "'")); } + if (this.options.ecmaVersion < 6 && + this.input.slice(start, end).indexOf("\\") !== -1) { return } + var re = this.strict ? this.reservedWordsStrict : this.reservedWords; + if (re.test(name)) { + if (!this.inAsync && name === "await") + { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); } + this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); + } + }; + + // Parse the next token as an identifier. If `liberal` is true (used + // when parsing properties), it will also convert keywords into + // identifiers. + + pp$3.parseIdent = function(liberal, isBinding) { + var node = this.startNode(); + if (this.type === types.name) { + node.name = this.value; + } else if (this.type.keyword) { + node.name = this.type.keyword; + + // To fix https://github.com/acornjs/acorn/issues/575 + // `class` and `function` keywords push new context into this.context. + // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. + // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword + if ((node.name === "class" || node.name === "function") && + (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { + this.context.pop(); + } + } else { + this.unexpected(); + } + this.next(!!liberal); + this.finishNode(node, "Identifier"); + if (!liberal) { + this.checkUnreserved(node); + if (node.name === "await" && !this.awaitIdentPos) + { this.awaitIdentPos = node.start; } + } + return node + }; + + // Parses yield expression inside generator. + + pp$3.parseYield = function(noIn) { + if (!this.yieldPos) { this.yieldPos = this.start; } + + var node = this.startNode(); + this.next(); + if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) { + node.delegate = false; + node.argument = null; + } else { + node.delegate = this.eat(types.star); + node.argument = this.parseMaybeAssign(noIn); + } + return this.finishNode(node, "YieldExpression") + }; + + pp$3.parseAwait = function() { + if (!this.awaitPos) { this.awaitPos = this.start; } + + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeUnary(null, false); + return this.finishNode(node, "AwaitExpression") + }; + + var pp$4 = Parser.prototype; + + // This function is used to raise exceptions on parse errors. It + // takes an offset integer (into the current `input`) to indicate + // the location of the error, attaches the position to the end + // of the error message, and then raises a `SyntaxError` with that + // message. + + pp$4.raise = function(pos, message) { + var loc = getLineInfo(this.input, pos); + message += " (" + loc.line + ":" + loc.column + ")"; + var err = new SyntaxError(message); + err.pos = pos; err.loc = loc; err.raisedAt = this.pos; + throw err + }; + + pp$4.raiseRecoverable = pp$4.raise; + + pp$4.curPosition = function() { + if (this.options.locations) { + return new Position(this.curLine, this.pos - this.lineStart) + } + }; + + var pp$5 = Parser.prototype; + + var Scope = function Scope(flags) { + this.flags = flags; + // A list of var-declared names in the current lexical scope + this.var = []; + // A list of lexically-declared names in the current lexical scope + this.lexical = []; + // A list of lexically-declared FunctionDeclaration names in the current lexical scope + this.functions = []; + }; + + // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. + + pp$5.enterScope = function(flags) { + this.scopeStack.push(new Scope(flags)); + }; + + pp$5.exitScope = function() { + this.scopeStack.pop(); + }; + + // The spec says: + // > At the top level of a function, or script, function declarations are + // > treated like var declarations rather than like lexical declarations. + pp$5.treatFunctionsAsVarInScope = function(scope) { + return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP) + }; + + pp$5.declareName = function(name, bindingType, pos) { + var redeclared = false; + if (bindingType === BIND_LEXICAL) { + var scope = this.currentScope(); + redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1; + scope.lexical.push(name); + if (this.inModule && (scope.flags & SCOPE_TOP)) + { delete this.undefinedExports[name]; } + } else if (bindingType === BIND_SIMPLE_CATCH) { + var scope$1 = this.currentScope(); + scope$1.lexical.push(name); + } else if (bindingType === BIND_FUNCTION) { + var scope$2 = this.currentScope(); + if (this.treatFunctionsAsVar) + { redeclared = scope$2.lexical.indexOf(name) > -1; } + else + { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; } + scope$2.functions.push(name); + } else { + for (var i = this.scopeStack.length - 1; i >= 0; --i) { + var scope$3 = this.scopeStack[i]; + if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) || + !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) { + redeclared = true; + break + } + scope$3.var.push(name); + if (this.inModule && (scope$3.flags & SCOPE_TOP)) + { delete this.undefinedExports[name]; } + if (scope$3.flags & SCOPE_VAR) { break } + } + } + if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); } + }; + + pp$5.checkLocalExport = function(id) { + // scope.functions must be empty as Module code is always strict. + if (this.scopeStack[0].lexical.indexOf(id.name) === -1 && + this.scopeStack[0].var.indexOf(id.name) === -1) { + this.undefinedExports[id.name] = id; + } + }; + + pp$5.currentScope = function() { + return this.scopeStack[this.scopeStack.length - 1] + }; + + pp$5.currentVarScope = function() { + for (var i = this.scopeStack.length - 1;; i--) { + var scope = this.scopeStack[i]; + if (scope.flags & SCOPE_VAR) { return scope } + } + }; + + // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`. + pp$5.currentThisScope = function() { + for (var i = this.scopeStack.length - 1;; i--) { + var scope = this.scopeStack[i]; + if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) { return scope } + } + }; + + var Node = function Node(parser, pos, loc) { + this.type = ""; + this.start = pos; + this.end = 0; + if (parser.options.locations) + { this.loc = new SourceLocation(parser, loc); } + if (parser.options.directSourceFile) + { this.sourceFile = parser.options.directSourceFile; } + if (parser.options.ranges) + { this.range = [pos, 0]; } + }; + + // Start an AST node, attaching a start offset. + + var pp$6 = Parser.prototype; + + pp$6.startNode = function() { + return new Node(this, this.start, this.startLoc) + }; + + pp$6.startNodeAt = function(pos, loc) { + return new Node(this, pos, loc) + }; + + // Finish an AST node, adding `type` and `end` properties. + + function finishNodeAt(node, type, pos, loc) { + node.type = type; + node.end = pos; + if (this.options.locations) + { node.loc.end = loc; } + if (this.options.ranges) + { node.range[1] = pos; } + return node + } + + pp$6.finishNode = function(node, type) { + return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) + }; + + // Finish node at given position + + pp$6.finishNodeAt = function(node, type, pos, loc) { + return finishNodeAt.call(this, node, type, pos, loc) + }; + + // The algorithm used to determine whether a regexp can appear at a + + var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { + this.token = token; + this.isExpr = !!isExpr; + this.preserveSpace = !!preserveSpace; + this.override = override; + this.generator = !!generator; + }; + + var types$1 = { + b_stat: new TokContext("{", false), + b_expr: new TokContext("{", true), + b_tmpl: new TokContext("${", false), + p_stat: new TokContext("(", false), + p_expr: new TokContext("(", true), + q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), + f_stat: new TokContext("function", false), + f_expr: new TokContext("function", true), + f_expr_gen: new TokContext("function", true, false, null, true), + f_gen: new TokContext("function", false, false, null, true) + }; + + var pp$7 = Parser.prototype; + + pp$7.initialContext = function() { + return [types$1.b_stat] + }; + + pp$7.braceIsBlock = function(prevType) { + var parent = this.curContext(); + if (parent === types$1.f_expr || parent === types$1.f_stat) + { return true } + if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr)) + { return !parent.isExpr } + + // The check for `tt.name && exprAllowed` detects whether we are + // after a `yield` or `of` construct. See the `updateContext` for + // `tt.name`. + if (prevType === types._return || prevType === types.name && this.exprAllowed) + { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } + if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow) + { return true } + if (prevType === types.braceL) + { return parent === types$1.b_stat } + if (prevType === types._var || prevType === types._const || prevType === types.name) + { return false } + return !this.exprAllowed + }; + + pp$7.inGeneratorContext = function() { + for (var i = this.context.length - 1; i >= 1; i--) { + var context = this.context[i]; + if (context.token === "function") + { return context.generator } + } + return false + }; + + pp$7.updateContext = function(prevType) { + var update, type = this.type; + if (type.keyword && prevType === types.dot) + { this.exprAllowed = false; } + else if (update = type.updateContext) + { update.call(this, prevType); } + else + { this.exprAllowed = type.beforeExpr; } + }; + + // Token-specific context update code + + types.parenR.updateContext = types.braceR.updateContext = function() { + if (this.context.length === 1) { + this.exprAllowed = true; + return + } + var out = this.context.pop(); + if (out === types$1.b_stat && this.curContext().token === "function") { + out = this.context.pop(); + } + this.exprAllowed = !out.isExpr; + }; + + types.braceL.updateContext = function(prevType) { + this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr); + this.exprAllowed = true; + }; + + types.dollarBraceL.updateContext = function() { + this.context.push(types$1.b_tmpl); + this.exprAllowed = true; + }; + + types.parenL.updateContext = function(prevType) { + var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; + this.context.push(statementParens ? types$1.p_stat : types$1.p_expr); + this.exprAllowed = true; + }; + + types.incDec.updateContext = function() { + // tokExprAllowed stays unchanged + }; + + types._function.updateContext = types._class.updateContext = function(prevType) { + if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else && + !(prevType === types._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) && + !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat)) + { this.context.push(types$1.f_expr); } + else + { this.context.push(types$1.f_stat); } + this.exprAllowed = false; + }; + + types.backQuote.updateContext = function() { + if (this.curContext() === types$1.q_tmpl) + { this.context.pop(); } + else + { this.context.push(types$1.q_tmpl); } + this.exprAllowed = false; + }; + + types.star.updateContext = function(prevType) { + if (prevType === types._function) { + var index = this.context.length - 1; + if (this.context[index] === types$1.f_expr) + { this.context[index] = types$1.f_expr_gen; } + else + { this.context[index] = types$1.f_gen; } + } + this.exprAllowed = true; + }; + + types.name.updateContext = function(prevType) { + var allowed = false; + if (this.options.ecmaVersion >= 6 && prevType !== types.dot) { + if (this.value === "of" && !this.exprAllowed || + this.value === "yield" && this.inGeneratorContext()) + { allowed = true; } + } + this.exprAllowed = allowed; + }; + + // This file contains Unicode properties extracted from the ECMAScript + // specification. The lists are extracted like so: + // $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText) + + // #table-binary-unicode-properties + var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS"; + var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic"; + var ecma11BinaryProperties = ecma10BinaryProperties; + var unicodeBinaryProperties = { + 9: ecma9BinaryProperties, + 10: ecma10BinaryProperties, + 11: ecma11BinaryProperties + }; + + // #table-unicode-general-category-values + var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu"; + + // #table-unicode-script-values + var ecma9ScriptValues = "Adlam Adlm Ahom Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb"; + var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd"; + var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho"; + var unicodeScriptValues = { + 9: ecma9ScriptValues, + 10: ecma10ScriptValues, + 11: ecma11ScriptValues + }; + + var data = {}; + function buildUnicodeData(ecmaVersion) { + var d = data[ecmaVersion] = { + binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues), + nonBinary: { + General_Category: wordsRegexp(unicodeGeneralCategoryValues), + Script: wordsRegexp(unicodeScriptValues[ecmaVersion]) + } + }; + d.nonBinary.Script_Extensions = d.nonBinary.Script; + + d.nonBinary.gc = d.nonBinary.General_Category; + d.nonBinary.sc = d.nonBinary.Script; + d.nonBinary.scx = d.nonBinary.Script_Extensions; + } + buildUnicodeData(9); + buildUnicodeData(10); + buildUnicodeData(11); + + var pp$8 = Parser.prototype; + + var RegExpValidationState = function RegExpValidationState(parser) { + this.parser = parser; + this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : ""); + this.unicodeProperties = data[parser.options.ecmaVersion >= 11 ? 11 : parser.options.ecmaVersion]; + this.source = ""; + this.flags = ""; + this.start = 0; + this.switchU = false; + this.switchN = false; + this.pos = 0; + this.lastIntValue = 0; + this.lastStringValue = ""; + this.lastAssertionIsQuantifiable = false; + this.numCapturingParens = 0; + this.maxBackReference = 0; + this.groupNames = []; + this.backReferenceNames = []; + }; + + RegExpValidationState.prototype.reset = function reset (start, pattern, flags) { + var unicode = flags.indexOf("u") !== -1; + this.start = start | 0; + this.source = pattern + ""; + this.flags = flags; + this.switchU = unicode && this.parser.options.ecmaVersion >= 6; + this.switchN = unicode && this.parser.options.ecmaVersion >= 9; + }; + + RegExpValidationState.prototype.raise = function raise (message) { + this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message)); + }; + + // If u flag is given, this returns the code point at the index (it combines a surrogate pair). + // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair). + RegExpValidationState.prototype.at = function at (i, forceU) { + if ( forceU === void 0 ) forceU = false; + + var s = this.source; + var l = s.length; + if (i >= l) { + return -1 + } + var c = s.charCodeAt(i); + if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { + return c + } + var next = s.charCodeAt(i + 1); + return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c + }; + + RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) { + if ( forceU === void 0 ) forceU = false; + + var s = this.source; + var l = s.length; + if (i >= l) { + return l + } + var c = s.charCodeAt(i), next; + if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || + (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) { + return i + 1 + } + return i + 2 + }; + + RegExpValidationState.prototype.current = function current (forceU) { + if ( forceU === void 0 ) forceU = false; + + return this.at(this.pos, forceU) + }; + + RegExpValidationState.prototype.lookahead = function lookahead (forceU) { + if ( forceU === void 0 ) forceU = false; + + return this.at(this.nextIndex(this.pos, forceU), forceU) + }; + + RegExpValidationState.prototype.advance = function advance (forceU) { + if ( forceU === void 0 ) forceU = false; + + this.pos = this.nextIndex(this.pos, forceU); + }; + + RegExpValidationState.prototype.eat = function eat (ch, forceU) { + if ( forceU === void 0 ) forceU = false; + + if (this.current(forceU) === ch) { + this.advance(forceU); + return true + } + return false + }; + + function codePointToString(ch) { + if (ch <= 0xFFFF) { return String.fromCharCode(ch) } + ch -= 0x10000; + return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00) + } + + /** + * Validate the flags part of a given RegExpLiteral. + * + * @param {RegExpValidationState} state The state to validate RegExp. + * @returns {void} + */ + pp$8.validateRegExpFlags = function(state) { + var validFlags = state.validFlags; + var flags = state.flags; + + for (var i = 0; i < flags.length; i++) { + var flag = flags.charAt(i); + if (validFlags.indexOf(flag) === -1) { + this.raise(state.start, "Invalid regular expression flag"); + } + if (flags.indexOf(flag, i + 1) > -1) { + this.raise(state.start, "Duplicate regular expression flag"); + } + } + }; + + /** + * Validate the pattern part of a given RegExpLiteral. + * + * @param {RegExpValidationState} state The state to validate RegExp. + * @returns {void} + */ + pp$8.validateRegExpPattern = function(state) { + this.regexp_pattern(state); + + // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of + // parsing contains a |GroupName|, reparse with the goal symbol + // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* + // exception if _P_ did not conform to the grammar, if any elements of _P_ + // were not matched by the parse, or if any Early Error conditions exist. + if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) { + state.switchN = true; + this.regexp_pattern(state); + } + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern + pp$8.regexp_pattern = function(state) { + state.pos = 0; + state.lastIntValue = 0; + state.lastStringValue = ""; + state.lastAssertionIsQuantifiable = false; + state.numCapturingParens = 0; + state.maxBackReference = 0; + state.groupNames.length = 0; + state.backReferenceNames.length = 0; + + this.regexp_disjunction(state); + + if (state.pos !== state.source.length) { + // Make the same messages as V8. + if (state.eat(0x29 /* ) */)) { + state.raise("Unmatched ')'"); + } + if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) { + state.raise("Lone quantifier brackets"); + } + } + if (state.maxBackReference > state.numCapturingParens) { + state.raise("Invalid escape"); + } + for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) { + var name = list[i]; + + if (state.groupNames.indexOf(name) === -1) { + state.raise("Invalid named capture referenced"); + } + } + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction + pp$8.regexp_disjunction = function(state) { + this.regexp_alternative(state); + while (state.eat(0x7C /* | */)) { + this.regexp_alternative(state); + } + + // Make the same message as V8. + if (this.regexp_eatQuantifier(state, true)) { + state.raise("Nothing to repeat"); + } + if (state.eat(0x7B /* { */)) { + state.raise("Lone quantifier brackets"); + } + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative + pp$8.regexp_alternative = function(state) { + while (state.pos < state.source.length && this.regexp_eatTerm(state)) + { } + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term + pp$8.regexp_eatTerm = function(state) { + if (this.regexp_eatAssertion(state)) { + // Handle `QuantifiableAssertion Quantifier` alternative. + // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion + // is a QuantifiableAssertion. + if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { + // Make the same message as V8. + if (state.switchU) { + state.raise("Invalid quantifier"); + } + } + return true + } + + if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { + this.regexp_eatQuantifier(state); + return true + } + + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion + pp$8.regexp_eatAssertion = function(state) { + var start = state.pos; + state.lastAssertionIsQuantifiable = false; + + // ^, $ + if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) { + return true + } + + // \b \B + if (state.eat(0x5C /* \ */)) { + if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) { + return true + } + state.pos = start; + } + + // Lookahead / Lookbehind + if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) { + var lookbehind = false; + if (this.options.ecmaVersion >= 9) { + lookbehind = state.eat(0x3C /* < */); + } + if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) { + this.regexp_disjunction(state); + if (!state.eat(0x29 /* ) */)) { + state.raise("Unterminated group"); + } + state.lastAssertionIsQuantifiable = !lookbehind; + return true + } + } + + state.pos = start; + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier + pp$8.regexp_eatQuantifier = function(state, noError) { + if ( noError === void 0 ) noError = false; + + if (this.regexp_eatQuantifierPrefix(state, noError)) { + state.eat(0x3F /* ? */); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix + pp$8.regexp_eatQuantifierPrefix = function(state, noError) { + return ( + state.eat(0x2A /* * */) || + state.eat(0x2B /* + */) || + state.eat(0x3F /* ? */) || + this.regexp_eatBracedQuantifier(state, noError) + ) + }; + pp$8.regexp_eatBracedQuantifier = function(state, noError) { + var start = state.pos; + if (state.eat(0x7B /* { */)) { + var min = 0, max = -1; + if (this.regexp_eatDecimalDigits(state)) { + min = state.lastIntValue; + if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) { + max = state.lastIntValue; + } + if (state.eat(0x7D /* } */)) { + // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term + if (max !== -1 && max < min && !noError) { + state.raise("numbers out of order in {} quantifier"); + } + return true + } + } + if (state.switchU && !noError) { + state.raise("Incomplete quantifier"); + } + state.pos = start; + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom + pp$8.regexp_eatAtom = function(state) { + return ( + this.regexp_eatPatternCharacters(state) || + state.eat(0x2E /* . */) || + this.regexp_eatReverseSolidusAtomEscape(state) || + this.regexp_eatCharacterClass(state) || + this.regexp_eatUncapturingGroup(state) || + this.regexp_eatCapturingGroup(state) + ) + }; + pp$8.regexp_eatReverseSolidusAtomEscape = function(state) { + var start = state.pos; + if (state.eat(0x5C /* \ */)) { + if (this.regexp_eatAtomEscape(state)) { + return true + } + state.pos = start; + } + return false + }; + pp$8.regexp_eatUncapturingGroup = function(state) { + var start = state.pos; + if (state.eat(0x28 /* ( */)) { + if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) { + this.regexp_disjunction(state); + if (state.eat(0x29 /* ) */)) { + return true + } + state.raise("Unterminated group"); + } + state.pos = start; + } + return false + }; + pp$8.regexp_eatCapturingGroup = function(state) { + if (state.eat(0x28 /* ( */)) { + if (this.options.ecmaVersion >= 9) { + this.regexp_groupSpecifier(state); + } else if (state.current() === 0x3F /* ? */) { + state.raise("Invalid group"); + } + this.regexp_disjunction(state); + if (state.eat(0x29 /* ) */)) { + state.numCapturingParens += 1; + return true + } + state.raise("Unterminated group"); + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom + pp$8.regexp_eatExtendedAtom = function(state) { + return ( + state.eat(0x2E /* . */) || + this.regexp_eatReverseSolidusAtomEscape(state) || + this.regexp_eatCharacterClass(state) || + this.regexp_eatUncapturingGroup(state) || + this.regexp_eatCapturingGroup(state) || + this.regexp_eatInvalidBracedQuantifier(state) || + this.regexp_eatExtendedPatternCharacter(state) + ) + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier + pp$8.regexp_eatInvalidBracedQuantifier = function(state) { + if (this.regexp_eatBracedQuantifier(state, true)) { + state.raise("Nothing to repeat"); + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter + pp$8.regexp_eatSyntaxCharacter = function(state) { + var ch = state.current(); + if (isSyntaxCharacter(ch)) { + state.lastIntValue = ch; + state.advance(); + return true + } + return false + }; + function isSyntaxCharacter(ch) { + return ( + ch === 0x24 /* $ */ || + ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ || + ch === 0x2E /* . */ || + ch === 0x3F /* ? */ || + ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ || + ch >= 0x7B /* { */ && ch <= 0x7D /* } */ + ) + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter + // But eat eager. + pp$8.regexp_eatPatternCharacters = function(state) { + var start = state.pos; + var ch = 0; + while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { + state.advance(); + } + return state.pos !== start + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter + pp$8.regexp_eatExtendedPatternCharacter = function(state) { + var ch = state.current(); + if ( + ch !== -1 && + ch !== 0x24 /* $ */ && + !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) && + ch !== 0x2E /* . */ && + ch !== 0x3F /* ? */ && + ch !== 0x5B /* [ */ && + ch !== 0x5E /* ^ */ && + ch !== 0x7C /* | */ + ) { + state.advance(); + return true + } + return false + }; + + // GroupSpecifier :: + // [empty] + // `?` GroupName + pp$8.regexp_groupSpecifier = function(state) { + if (state.eat(0x3F /* ? */)) { + if (this.regexp_eatGroupName(state)) { + if (state.groupNames.indexOf(state.lastStringValue) !== -1) { + state.raise("Duplicate capture group name"); + } + state.groupNames.push(state.lastStringValue); + return + } + state.raise("Invalid group"); + } + }; + + // GroupName :: + // `<` RegExpIdentifierName `>` + // Note: this updates `state.lastStringValue` property with the eaten name. + pp$8.regexp_eatGroupName = function(state) { + state.lastStringValue = ""; + if (state.eat(0x3C /* < */)) { + if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) { + return true + } + state.raise("Invalid capture group name"); + } + return false + }; + + // RegExpIdentifierName :: + // RegExpIdentifierStart + // RegExpIdentifierName RegExpIdentifierPart + // Note: this updates `state.lastStringValue` property with the eaten name. + pp$8.regexp_eatRegExpIdentifierName = function(state) { + state.lastStringValue = ""; + if (this.regexp_eatRegExpIdentifierStart(state)) { + state.lastStringValue += codePointToString(state.lastIntValue); + while (this.regexp_eatRegExpIdentifierPart(state)) { + state.lastStringValue += codePointToString(state.lastIntValue); + } + return true + } + return false + }; + + // RegExpIdentifierStart :: + // UnicodeIDStart + // `$` + // `_` + // `\` RegExpUnicodeEscapeSequence[+U] + pp$8.regexp_eatRegExpIdentifierStart = function(state) { + var start = state.pos; + var forceU = this.options.ecmaVersion >= 11; + var ch = state.current(forceU); + state.advance(forceU); + + if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { + ch = state.lastIntValue; + } + if (isRegExpIdentifierStart(ch)) { + state.lastIntValue = ch; + return true + } + + state.pos = start; + return false + }; + function isRegExpIdentifierStart(ch) { + return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ + } + + // RegExpIdentifierPart :: + // UnicodeIDContinue + // `$` + // `_` + // `\` RegExpUnicodeEscapeSequence[+U] + // + // + pp$8.regexp_eatRegExpIdentifierPart = function(state) { + var start = state.pos; + var forceU = this.options.ecmaVersion >= 11; + var ch = state.current(forceU); + state.advance(forceU); + + if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { + ch = state.lastIntValue; + } + if (isRegExpIdentifierPart(ch)) { + state.lastIntValue = ch; + return true + } + + state.pos = start; + return false + }; + function isRegExpIdentifierPart(ch) { + return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* */ || ch === 0x200D /* */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape + pp$8.regexp_eatAtomEscape = function(state) { + if ( + this.regexp_eatBackReference(state) || + this.regexp_eatCharacterClassEscape(state) || + this.regexp_eatCharacterEscape(state) || + (state.switchN && this.regexp_eatKGroupName(state)) + ) { + return true + } + if (state.switchU) { + // Make the same message as V8. + if (state.current() === 0x63 /* c */) { + state.raise("Invalid unicode escape"); + } + state.raise("Invalid escape"); + } + return false + }; + pp$8.regexp_eatBackReference = function(state) { + var start = state.pos; + if (this.regexp_eatDecimalEscape(state)) { + var n = state.lastIntValue; + if (state.switchU) { + // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape + if (n > state.maxBackReference) { + state.maxBackReference = n; + } + return true + } + if (n <= state.numCapturingParens) { + return true + } + state.pos = start; + } + return false + }; + pp$8.regexp_eatKGroupName = function(state) { + if (state.eat(0x6B /* k */)) { + if (this.regexp_eatGroupName(state)) { + state.backReferenceNames.push(state.lastStringValue); + return true + } + state.raise("Invalid named reference"); + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape + pp$8.regexp_eatCharacterEscape = function(state) { + return ( + this.regexp_eatControlEscape(state) || + this.regexp_eatCControlLetter(state) || + this.regexp_eatZero(state) || + this.regexp_eatHexEscapeSequence(state) || + this.regexp_eatRegExpUnicodeEscapeSequence(state, false) || + (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || + this.regexp_eatIdentityEscape(state) + ) + }; + pp$8.regexp_eatCControlLetter = function(state) { + var start = state.pos; + if (state.eat(0x63 /* c */)) { + if (this.regexp_eatControlLetter(state)) { + return true + } + state.pos = start; + } + return false + }; + pp$8.regexp_eatZero = function(state) { + if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) { + state.lastIntValue = 0; + state.advance(); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape + pp$8.regexp_eatControlEscape = function(state) { + var ch = state.current(); + if (ch === 0x74 /* t */) { + state.lastIntValue = 0x09; /* \t */ + state.advance(); + return true + } + if (ch === 0x6E /* n */) { + state.lastIntValue = 0x0A; /* \n */ + state.advance(); + return true + } + if (ch === 0x76 /* v */) { + state.lastIntValue = 0x0B; /* \v */ + state.advance(); + return true + } + if (ch === 0x66 /* f */) { + state.lastIntValue = 0x0C; /* \f */ + state.advance(); + return true + } + if (ch === 0x72 /* r */) { + state.lastIntValue = 0x0D; /* \r */ + state.advance(); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter + pp$8.regexp_eatControlLetter = function(state) { + var ch = state.current(); + if (isControlLetter(ch)) { + state.lastIntValue = ch % 0x20; + state.advance(); + return true + } + return false + }; + function isControlLetter(ch) { + return ( + (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) || + (ch >= 0x61 /* a */ && ch <= 0x7A /* z */) + ) + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence + pp$8.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) { + if ( forceU === void 0 ) forceU = false; + + var start = state.pos; + var switchU = forceU || state.switchU; + + if (state.eat(0x75 /* u */)) { + if (this.regexp_eatFixedHexDigits(state, 4)) { + var lead = state.lastIntValue; + if (switchU && lead >= 0xD800 && lead <= 0xDBFF) { + var leadSurrogateEnd = state.pos; + if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) { + var trail = state.lastIntValue; + if (trail >= 0xDC00 && trail <= 0xDFFF) { + state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; + return true + } + } + state.pos = leadSurrogateEnd; + state.lastIntValue = lead; + } + return true + } + if ( + switchU && + state.eat(0x7B /* { */) && + this.regexp_eatHexDigits(state) && + state.eat(0x7D /* } */) && + isValidUnicode(state.lastIntValue) + ) { + return true + } + if (switchU) { + state.raise("Invalid unicode escape"); + } + state.pos = start; + } + + return false + }; + function isValidUnicode(ch) { + return ch >= 0 && ch <= 0x10FFFF + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape + pp$8.regexp_eatIdentityEscape = function(state) { + if (state.switchU) { + if (this.regexp_eatSyntaxCharacter(state)) { + return true + } + if (state.eat(0x2F /* / */)) { + state.lastIntValue = 0x2F; /* / */ + return true + } + return false + } + + var ch = state.current(); + if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) { + state.lastIntValue = ch; + state.advance(); + return true + } + + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape + pp$8.regexp_eatDecimalEscape = function(state) { + state.lastIntValue = 0; + var ch = state.current(); + if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) { + do { + state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); + state.advance(); + } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape + pp$8.regexp_eatCharacterClassEscape = function(state) { + var ch = state.current(); + + if (isCharacterClassEscape(ch)) { + state.lastIntValue = -1; + state.advance(); + return true + } + + if ( + state.switchU && + this.options.ecmaVersion >= 9 && + (ch === 0x50 /* P */ || ch === 0x70 /* p */) + ) { + state.lastIntValue = -1; + state.advance(); + if ( + state.eat(0x7B /* { */) && + this.regexp_eatUnicodePropertyValueExpression(state) && + state.eat(0x7D /* } */) + ) { + return true + } + state.raise("Invalid property name"); + } + + return false + }; + function isCharacterClassEscape(ch) { + return ( + ch === 0x64 /* d */ || + ch === 0x44 /* D */ || + ch === 0x73 /* s */ || + ch === 0x53 /* S */ || + ch === 0x77 /* w */ || + ch === 0x57 /* W */ + ) + } + + // UnicodePropertyValueExpression :: + // UnicodePropertyName `=` UnicodePropertyValue + // LoneUnicodePropertyNameOrValue + pp$8.regexp_eatUnicodePropertyValueExpression = function(state) { + var start = state.pos; + + // UnicodePropertyName `=` UnicodePropertyValue + if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) { + var name = state.lastStringValue; + if (this.regexp_eatUnicodePropertyValue(state)) { + var value = state.lastStringValue; + this.regexp_validateUnicodePropertyNameAndValue(state, name, value); + return true + } + } + state.pos = start; + + // LoneUnicodePropertyNameOrValue + if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { + var nameOrValue = state.lastStringValue; + this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue); + return true + } + return false + }; + pp$8.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { + if (!has(state.unicodeProperties.nonBinary, name)) + { state.raise("Invalid property name"); } + if (!state.unicodeProperties.nonBinary[name].test(value)) + { state.raise("Invalid property value"); } + }; + pp$8.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { + if (!state.unicodeProperties.binary.test(nameOrValue)) + { state.raise("Invalid property name"); } + }; + + // UnicodePropertyName :: + // UnicodePropertyNameCharacters + pp$8.regexp_eatUnicodePropertyName = function(state) { + var ch = 0; + state.lastStringValue = ""; + while (isUnicodePropertyNameCharacter(ch = state.current())) { + state.lastStringValue += codePointToString(ch); + state.advance(); + } + return state.lastStringValue !== "" + }; + function isUnicodePropertyNameCharacter(ch) { + return isControlLetter(ch) || ch === 0x5F /* _ */ + } + + // UnicodePropertyValue :: + // UnicodePropertyValueCharacters + pp$8.regexp_eatUnicodePropertyValue = function(state) { + var ch = 0; + state.lastStringValue = ""; + while (isUnicodePropertyValueCharacter(ch = state.current())) { + state.lastStringValue += codePointToString(ch); + state.advance(); + } + return state.lastStringValue !== "" + }; + function isUnicodePropertyValueCharacter(ch) { + return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) + } + + // LoneUnicodePropertyNameOrValue :: + // UnicodePropertyValueCharacters + pp$8.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { + return this.regexp_eatUnicodePropertyValue(state) + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass + pp$8.regexp_eatCharacterClass = function(state) { + if (state.eat(0x5B /* [ */)) { + state.eat(0x5E /* ^ */); + this.regexp_classRanges(state); + if (state.eat(0x5D /* ] */)) { + return true + } + // Unreachable since it threw "unterminated regular expression" error before. + state.raise("Unterminated character class"); + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges + // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges + // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash + pp$8.regexp_classRanges = function(state) { + while (this.regexp_eatClassAtom(state)) { + var left = state.lastIntValue; + if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) { + var right = state.lastIntValue; + if (state.switchU && (left === -1 || right === -1)) { + state.raise("Invalid character class"); + } + if (left !== -1 && right !== -1 && left > right) { + state.raise("Range out of order in character class"); + } + } + } + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash + pp$8.regexp_eatClassAtom = function(state) { + var start = state.pos; + + if (state.eat(0x5C /* \ */)) { + if (this.regexp_eatClassEscape(state)) { + return true + } + if (state.switchU) { + // Make the same message as V8. + var ch$1 = state.current(); + if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) { + state.raise("Invalid class escape"); + } + state.raise("Invalid escape"); + } + state.pos = start; + } + + var ch = state.current(); + if (ch !== 0x5D /* ] */) { + state.lastIntValue = ch; + state.advance(); + return true + } + + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape + pp$8.regexp_eatClassEscape = function(state) { + var start = state.pos; + + if (state.eat(0x62 /* b */)) { + state.lastIntValue = 0x08; /* */ + return true + } + + if (state.switchU && state.eat(0x2D /* - */)) { + state.lastIntValue = 0x2D; /* - */ + return true + } + + if (!state.switchU && state.eat(0x63 /* c */)) { + if (this.regexp_eatClassControlLetter(state)) { + return true + } + state.pos = start; + } + + return ( + this.regexp_eatCharacterClassEscape(state) || + this.regexp_eatCharacterEscape(state) + ) + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter + pp$8.regexp_eatClassControlLetter = function(state) { + var ch = state.current(); + if (isDecimalDigit(ch) || ch === 0x5F /* _ */) { + state.lastIntValue = ch % 0x20; + state.advance(); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence + pp$8.regexp_eatHexEscapeSequence = function(state) { + var start = state.pos; + if (state.eat(0x78 /* x */)) { + if (this.regexp_eatFixedHexDigits(state, 2)) { + return true + } + if (state.switchU) { + state.raise("Invalid escape"); + } + state.pos = start; + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits + pp$8.regexp_eatDecimalDigits = function(state) { + var start = state.pos; + var ch = 0; + state.lastIntValue = 0; + while (isDecimalDigit(ch = state.current())) { + state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); + state.advance(); + } + return state.pos !== start + }; + function isDecimalDigit(ch) { + return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits + pp$8.regexp_eatHexDigits = function(state) { + var start = state.pos; + var ch = 0; + state.lastIntValue = 0; + while (isHexDigit(ch = state.current())) { + state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); + state.advance(); + } + return state.pos !== start + }; + function isHexDigit(ch) { + return ( + (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) || + (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) || + (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) + ) + } + function hexToInt(ch) { + if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) { + return 10 + (ch - 0x41 /* A */) + } + if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) { + return 10 + (ch - 0x61 /* a */) + } + return ch - 0x30 /* 0 */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence + // Allows only 0-377(octal) i.e. 0-255(decimal). + pp$8.regexp_eatLegacyOctalEscapeSequence = function(state) { + if (this.regexp_eatOctalDigit(state)) { + var n1 = state.lastIntValue; + if (this.regexp_eatOctalDigit(state)) { + var n2 = state.lastIntValue; + if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { + state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue; + } else { + state.lastIntValue = n1 * 8 + n2; + } + } else { + state.lastIntValue = n1; + } + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit + pp$8.regexp_eatOctalDigit = function(state) { + var ch = state.current(); + if (isOctalDigit(ch)) { + state.lastIntValue = ch - 0x30; /* 0 */ + state.advance(); + return true + } + state.lastIntValue = 0; + return false + }; + function isOctalDigit(ch) { + return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit + // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence + pp$8.regexp_eatFixedHexDigits = function(state, length) { + var start = state.pos; + state.lastIntValue = 0; + for (var i = 0; i < length; ++i) { + var ch = state.current(); + if (!isHexDigit(ch)) { + state.pos = start; + return false + } + state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); + state.advance(); + } + return true + }; + + // Object type used to represent tokens. Note that normally, tokens + // simply exist as properties on the parser object. This is only + // used for the onToken callback and the external tokenizer. + + var Token = function Token(p) { + this.type = p.type; + this.value = p.value; + this.start = p.start; + this.end = p.end; + if (p.options.locations) + { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } + if (p.options.ranges) + { this.range = [p.start, p.end]; } + }; + + // ## Tokenizer + + var pp$9 = Parser.prototype; + + // Move to the next token + + pp$9.next = function(ignoreEscapeSequenceInKeyword) { + if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc) + { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); } + if (this.options.onToken) + { this.options.onToken(new Token(this)); } + + this.lastTokEnd = this.end; + this.lastTokStart = this.start; + this.lastTokEndLoc = this.endLoc; + this.lastTokStartLoc = this.startLoc; + this.nextToken(); + }; + + pp$9.getToken = function() { + this.next(); + return new Token(this) + }; + + // If we're in an ES6 environment, make parsers iterable + if (typeof Symbol !== "undefined") + { pp$9[Symbol.iterator] = function() { + var this$1 = this; + + return { + next: function () { + var token = this$1.getToken(); + return { + done: token.type === types.eof, + value: token + } + } + } + }; } + + // Toggle strict mode. Re-reads the next number or string to please + // pedantic tests (`"use strict"; 010;` should fail). + + pp$9.curContext = function() { + return this.context[this.context.length - 1] + }; + + // Read a single token, updating the parser object's token-related + // properties. + + pp$9.nextToken = function() { + var curContext = this.curContext(); + if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } + + this.start = this.pos; + if (this.options.locations) { this.startLoc = this.curPosition(); } + if (this.pos >= this.input.length) { return this.finishToken(types.eof) } + + if (curContext.override) { return curContext.override(this) } + else { this.readToken(this.fullCharCodeAtPos()); } + }; + + pp$9.readToken = function(code) { + // Identifier or keyword. '\uXXXX' sequences are allowed in + // identifiers, so '\' also dispatches to that. + if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) + { return this.readWord() } + + return this.getTokenFromCode(code) + }; + + pp$9.fullCharCodeAtPos = function() { + var code = this.input.charCodeAt(this.pos); + if (code <= 0xd7ff || code >= 0xe000) { return code } + var next = this.input.charCodeAt(this.pos + 1); + return (code << 10) + next - 0x35fdc00 + }; + + pp$9.skipBlockComment = function() { + var startLoc = this.options.onComment && this.curPosition(); + var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); + if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } + this.pos = end + 2; + if (this.options.locations) { + lineBreakG.lastIndex = start; + var match; + while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { + ++this.curLine; + this.lineStart = match.index + match[0].length; + } + } + if (this.options.onComment) + { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, + startLoc, this.curPosition()); } + }; + + pp$9.skipLineComment = function(startSkip) { + var start = this.pos; + var startLoc = this.options.onComment && this.curPosition(); + var ch = this.input.charCodeAt(this.pos += startSkip); + while (this.pos < this.input.length && !isNewLine(ch)) { + ch = this.input.charCodeAt(++this.pos); + } + if (this.options.onComment) + { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, + startLoc, this.curPosition()); } + }; + + // Called at the start of the parse and after every token. Skips + // whitespace and comments, and. + + pp$9.skipSpace = function() { + loop: while (this.pos < this.input.length) { + var ch = this.input.charCodeAt(this.pos); + switch (ch) { + case 32: case 160: // ' ' + ++this.pos; + break + case 13: + if (this.input.charCodeAt(this.pos + 1) === 10) { + ++this.pos; + } + case 10: case 8232: case 8233: + ++this.pos; + if (this.options.locations) { + ++this.curLine; + this.lineStart = this.pos; + } + break + case 47: // '/' + switch (this.input.charCodeAt(this.pos + 1)) { + case 42: // '*' + this.skipBlockComment(); + break + case 47: + this.skipLineComment(2); + break + default: + break loop + } + break + default: + if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++this.pos; + } else { + break loop + } + } + } + }; + + // Called at the end of every token. Sets `end`, `val`, and + // maintains `context` and `exprAllowed`, and skips the space after + // the token, so that the next one's `start` will point at the + // right position. + + pp$9.finishToken = function(type, val) { + this.end = this.pos; + if (this.options.locations) { this.endLoc = this.curPosition(); } + var prevType = this.type; + this.type = type; + this.value = val; + + this.updateContext(prevType); + }; + + // ### Token reading + + // This is the function that is called to fetch the next token. It + // is somewhat obscure, because it works in character codes rather + // than characters, and because operator parsing has been inlined + // into it. + // + // All in the name of speed. + // + pp$9.readToken_dot = function() { + var next = this.input.charCodeAt(this.pos + 1); + if (next >= 48 && next <= 57) { return this.readNumber(true) } + var next2 = this.input.charCodeAt(this.pos + 2); + if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' + this.pos += 3; + return this.finishToken(types.ellipsis) + } else { + ++this.pos; + return this.finishToken(types.dot) + } + }; + + pp$9.readToken_slash = function() { // '/' + var next = this.input.charCodeAt(this.pos + 1); + if (this.exprAllowed) { ++this.pos; return this.readRegexp() } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.slash, 1) + }; + + pp$9.readToken_mult_modulo_exp = function(code) { // '%*' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + var tokentype = code === 42 ? types.star : types.modulo; + + // exponentiation operator ** and **= + if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) { + ++size; + tokentype = types.starstar; + next = this.input.charCodeAt(this.pos + 2); + } + + if (next === 61) { return this.finishOp(types.assign, size + 1) } + return this.finishOp(tokentype, size) + }; + + pp$9.readToken_pipe_amp = function(code) { // '|&' + var next = this.input.charCodeAt(this.pos + 1); + if (next === code) { + if (this.options.ecmaVersion >= 12) { + var next2 = this.input.charCodeAt(this.pos + 2); + if (next2 === 61) { return this.finishOp(types.assign, 3) } + } + return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) + } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1) + }; + + pp$9.readToken_caret = function() { // '^' + var next = this.input.charCodeAt(this.pos + 1); + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.bitwiseXOR, 1) + }; + + pp$9.readToken_plus_min = function(code) { // '+-' + var next = this.input.charCodeAt(this.pos + 1); + if (next === code) { + if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && + (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { + // A `-->` line comment + this.skipLineComment(3); + this.skipSpace(); + return this.nextToken() + } + return this.finishOp(types.incDec, 2) + } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.plusMin, 1) + }; + + pp$9.readToken_lt_gt = function(code) { // '<>' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + if (next === code) { + size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; + if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) } + return this.finishOp(types.bitShift, size) + } + if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && + this.input.charCodeAt(this.pos + 3) === 45) { + // `` line comment + this.skipLineComment(3); + this.skipSpace(); + return this.nextToken() + } + return this.finishOp(types.incDec, 2) + } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.plusMin, 1) + }; + + pp$9.readToken_lt_gt = function(code) { // '<>' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + if (next === code) { + size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; + if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) } + return this.finishOp(types.bitShift, size) + } + if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && + this.input.charCodeAt(this.pos + 3) === 45) { + // `0;) {") + code.push("if (!(" + shapeConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same shape!')") + code.push("}") + } + // Process scalar arguments + for(var i=0; i + * All rights reserved + * + * Licensed under the MIT license. + * + * http://www.opensource.org/licenses/mit-license.php + * + * 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 dijkstra = { + single_source_shortest_paths: function(graph, s, d) { + // Predecessor map for each node that has been encountered. + // node ID => predecessor node ID + var predecessors = {}; + + // Costs of shortest paths from s to all nodes encountered. + // node ID => cost + var costs = {}; + costs[s] = 0; + + // Costs of shortest paths from s to all nodes encountered; differs from + // `costs` in that it provides easy access to the node that currently has + // the known shortest path from s. + // XXX: Do we actually need both `costs` and `open`? + var open = dijkstra.PriorityQueue.make(); + open.push(s, 0); + + var closest, + u, v, + cost_of_s_to_u, + adjacent_nodes, + cost_of_e, + cost_of_s_to_u_plus_cost_of_e, + cost_of_s_to_v, + first_visit; + while (!open.empty()) { + // In the nodes remaining in graph that have a known cost from s, + // find the node, u, that currently has the shortest path from s. + closest = open.pop(); + u = closest.value; + cost_of_s_to_u = closest.cost; + + // Get nodes adjacent to u... + adjacent_nodes = graph[u] || {}; + + // ...and explore the edges that connect u to those nodes, updating + // the cost of the shortest paths to any or all of those nodes as + // necessary. v is the node across the current edge from u. + for (v in adjacent_nodes) { + if (adjacent_nodes.hasOwnProperty(v)) { + // Get the cost of the edge running from u to v. + cost_of_e = adjacent_nodes[v]; + + // Cost of s to u plus the cost of u to v across e--this is *a* + // cost from s to v that may or may not be less than the current + // known cost to v. + cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e; + + // If we haven't visited v yet OR if the current known cost from s to + // v is greater than the new cost we just found (cost of s to u plus + // cost of u to v across e), update v's cost in the cost list and + // update v's predecessor in the predecessor list (it's now u). + cost_of_s_to_v = costs[v]; + first_visit = (typeof costs[v] === 'undefined'); + if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) { + costs[v] = cost_of_s_to_u_plus_cost_of_e; + open.push(v, cost_of_s_to_u_plus_cost_of_e); + predecessors[v] = u; + } + } + } + } + + if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') { + var msg = ['Could not find a path from ', s, ' to ', d, '.'].join(''); + throw new Error(msg); + } + + return predecessors; + }, + + extract_shortest_path_from_predecessor_list: function(predecessors, d) { + var nodes = []; + var u = d; + var predecessor; + while (u) { + nodes.push(u); + predecessor = predecessors[u]; + u = predecessors[u]; + } + nodes.reverse(); + return nodes; + }, + + find_path: function(graph, s, d) { + var predecessors = dijkstra.single_source_shortest_paths(graph, s, d); + return dijkstra.extract_shortest_path_from_predecessor_list( + predecessors, d); + }, + + /** + * A very naive priority queue implementation. + */ + PriorityQueue: { + make: function (opts) { + var T = dijkstra.PriorityQueue, + t = {}, + key; + opts = opts || {}; + for (key in T) { + if (T.hasOwnProperty(key)) { + t[key] = T[key]; + } + } + t.queue = []; + t.sorter = opts.sorter || T.default_sorter; + return t; + }, + + default_sorter: function (a, b) { + return a.cost - b.cost; + }, + + /** + * Add a new item to the queue and ensure the highest priority element + * is at the front of the queue. + */ + push: function (value, cost) { + var item = {value: value, cost: cost}; + this.queue.push(item); + this.queue.sort(this.sorter); + }, + + /** + * Return the highest priority element in the queue. + */ + pop: function () { + return this.queue.shift(); + }, + + empty: function () { + return this.queue.length === 0; + } + } +}; + + +// node.js module exports +if (typeof module !== 'undefined') { + module.exports = dijkstra; +} + +},{}],53:[function(require,module,exports){ +(function (process){ +'use strict'; +const path = require('path'); +const pathType = require('path-type'); + +const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; + +const getPath = (filepath, cwd) => { + const pth = filepath[0] === '!' ? filepath.slice(1) : filepath; + return path.isAbsolute(pth) ? pth : path.join(cwd, pth); +}; + +const addExtensions = (file, extensions) => { + if (path.extname(file)) { + return `**/${file}`; + } + + return `**/${file}.${getExtensions(extensions)}`; +}; + +const getGlob = (directory, options) => { + if (options.files && !Array.isArray(options.files)) { + throw new TypeError(`Expected \`files\` to be of type \`Array\` but received type \`${typeof options.files}\``); + } + + if (options.extensions && !Array.isArray(options.extensions)) { + throw new TypeError(`Expected \`extensions\` to be of type \`Array\` but received type \`${typeof options.extensions}\``); + } + + if (options.files && options.extensions) { + return options.files.map(x => path.posix.join(directory, addExtensions(x, options.extensions))); + } + + if (options.files) { + return options.files.map(x => path.posix.join(directory, `**/${x}`)); + } + + if (options.extensions) { + return [path.posix.join(directory, `**/*.${getExtensions(options.extensions)}`)]; + } + + return [path.posix.join(directory, '**')]; +}; + +module.exports = async (input, options) => { + options = { + cwd: process.cwd(), + ...options + }; + + if (typeof options.cwd !== 'string') { + throw new TypeError(`Expected \`cwd\` to be of type \`string\` but received type \`${typeof options.cwd}\``); + } + + const globs = await Promise.all([].concat(input).map(async x => { + const isDirectory = await pathType.isDirectory(getPath(x, options.cwd)); + return isDirectory ? getGlob(x, options) : x; + })); + + return [].concat.apply([], globs); // eslint-disable-line prefer-spread +}; + +module.exports.sync = (input, options) => { + options = { + cwd: process.cwd(), + ...options + }; + + if (typeof options.cwd !== 'string') { + throw new TypeError(`Expected \`cwd\` to be of type \`string\` but received type \`${typeof options.cwd}\``); + } + + const globs = [].concat(input).map(x => pathType.isDirectorySync(getPath(x, options.cwd)) ? getGlob(x, options) : x); + + return [].concat.apply([], globs); // eslint-disable-line prefer-spread +}; + +}).call(this,require('_process')) +},{"_process":437,"path":404,"path-type":54}],54:[function(require,module,exports){ +'use strict'; +const {promisify} = require('util'); +const fs = require('fs'); + +async function isType(fsStatType, statsMethodName, filePath) { + if (typeof filePath !== 'string') { + throw new TypeError(`Expected a string, got ${typeof filePath}`); + } + + try { + const stats = await promisify(fs[fsStatType])(filePath); + return stats[statsMethodName](); + } catch (error) { + if (error.code === 'ENOENT') { + return false; + } + + throw error; + } +} + +function isTypeSync(fsStatType, statsMethodName, filePath) { + if (typeof filePath !== 'string') { + throw new TypeError(`Expected a string, got ${typeof filePath}`); + } + + try { + return fs[fsStatType](filePath)[statsMethodName](); + } catch (error) { + if (error.code === 'ENOENT') { + return false; + } + + throw error; + } +} + +exports.isFile = isType.bind(null, 'stat', 'isFile'); +exports.isDirectory = isType.bind(null, 'stat', 'isDirectory'); +exports.isSymlink = isType.bind(null, 'lstat', 'isSymbolicLink'); +exports.isFileSync = isTypeSync.bind(null, 'statSync', 'isFile'); +exports.isDirectorySync = isTypeSync.bind(null, 'statSync', 'isDirectory'); +exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); + +},{"fs":298,"util":523}],55:[function(require,module,exports){ +'use strict' + +module.exports = function encodeUtf8 (input) { + var result = [] + var size = input.length + + for (var index = 0; index < size; index++) { + var point = input.charCodeAt(index) + + if (point >= 0xD800 && point <= 0xDBFF && size > index + 1) { + var second = input.charCodeAt(index + 1) + + if (second >= 0xDC00 && second <= 0xDFFF) { + // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + point = (point - 0xD800) * 0x400 + second - 0xDC00 + 0x10000 + index += 1 + } + } + + // US-ASCII + if (point < 0x80) { + result.push(point) + continue + } + + // 2-byte UTF-8 + if (point < 0x800) { + result.push((point >> 6) | 192) + result.push((point & 63) | 128) + continue + } + + // 3-byte UTF-8 + if (point < 0xD800 || (point >= 0xE000 && point < 0x10000)) { + result.push((point >> 12) | 224) + result.push(((point >> 6) & 63) | 128) + result.push((point & 63) | 128) + continue + } + + // 4-byte UTF-8 + if (point >= 0x10000 && point <= 0x10FFFF) { + result.push((point >> 18) | 240) + result.push(((point >> 12) & 63) | 128) + result.push(((point >> 6) & 63) | 128) + result.push((point & 63) | 128) + continue + } + + // Invalid character + result.push(0xEF, 0xBF, 0xBD) + } + + return new Uint8Array(result).buffer +} + +},{}],56:[function(require,module,exports){ +var once = require('once'); + +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 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() { + if (readable && !(rs && rs.ended)) return callback.call(stream, new Error('premature close')); + if (writable && !(ws && ws.ended)) 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() { + 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; + +},{"once":399}],57:[function(require,module,exports){ +(function (Buffer){ +'use strict'; +const fs = require('fs'); +const execa = require('execa'); +const pFinally = require('p-finally'); +const pify = require('pify'); +const rimraf = require('rimraf'); +const tempfile = require('tempfile'); + +const fsP = pify(fs); +const rmP = pify(rimraf); +const input = Symbol('inputPath'); +const output = Symbol('outputPath'); + +module.exports = opts => { + opts = Object.assign({}, opts); + + if (!Buffer.isBuffer(opts.input)) { + return Promise.reject(new Error('Input is required')); + } + + if (typeof opts.bin !== 'string') { + return Promise.reject(new Error('Binary is required')); + } + + if (!Array.isArray(opts.args)) { + return Promise.reject(new Error('Arguments are required')); + } + + const inputPath = opts.inputPath || tempfile(); + const outputPath = opts.outputPath || tempfile(); + + opts.args = opts.args.map(x => x === input ? inputPath : x === output ? outputPath : x); + + const promise = fsP.writeFile(inputPath, opts.input) + .then(() => execa(opts.bin, opts.args)) + .then(() => fsP.readFile(outputPath)); + + return pFinally(promise, () => Promise.all([ + rmP(inputPath), + rmP(outputPath) + ])); +}; + +module.exports.input = input; +module.exports.output = output; + +}).call(this,{"isBuffer":require("../is-buffer/index.js")}) +},{"../is-buffer/index.js":361,"execa":66,"fs":298,"p-finally":402,"pify":71,"rimraf":493,"tempfile":512}],58:[function(require,module,exports){ +'use strict'; + +var cp = require('child_process'); +var parse = require('./lib/parse'); +var enoent = require('./lib/enoent'); + +var cpSpawnSync = cp.spawnSync; + +function spawn(command, args, options) { + var parsed; + var spawned; + + // Parse the arguments + parsed = parse(command, args, options); + + // Spawn the child process + spawned = cp.spawn(parsed.command, parsed.args, parsed.options); + + // Hook into child process "exit" event to emit an error if the command + // does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + enoent.hookChildProcess(spawned, parsed); + + return spawned; +} + +function spawnSync(command, args, options) { + var parsed; + var result; + + if (!cpSpawnSync) { + try { + cpSpawnSync = require('spawn-sync'); // eslint-disable-line global-require + } catch (ex) { + throw new Error( + 'In order to use spawnSync on node 0.10 or older, you must ' + + 'install spawn-sync:\n\n' + + ' npm install spawn-sync --save' + ); + } + } + + // Parse the arguments + parsed = parse(command, args, options); + + // Spawn the child process + result = cpSpawnSync(parsed.command, parsed.args, parsed.options); + + // Analyze if the command does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); + + return result; +} + +module.exports = spawn; +module.exports.spawn = spawn; +module.exports.sync = spawnSync; + +module.exports._parse = parse; +module.exports._enoent = enoent; + +},{"./lib/enoent":59,"./lib/parse":60,"child_process":298,"spawn-sync":502}],59:[function(require,module,exports){ +(function (process){ +'use strict'; + +var isWin = process.platform === 'win32'; +var resolveCommand = require('./util/resolveCommand'); + +var isNode10 = process.version.indexOf('v0.10.') === 0; + +function notFoundError(command, syscall) { + var err; + + err = new Error(syscall + ' ' + command + ' ENOENT'); + err.code = err.errno = 'ENOENT'; + err.syscall = syscall + ' ' + command; + + return err; +} + +function hookChildProcess(cp, parsed) { + var originalEmit; + + if (!isWin) { + return; + } + + originalEmit = cp.emit; + cp.emit = function (name, arg1) { + var err; + + // If emitting "exit" event and exit code is 1, we need to check if + // the command exists and emit an "error" instead + // See: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + if (name === 'exit') { + err = verifyENOENT(arg1, parsed, 'spawn'); + + if (err) { + return originalEmit.call(cp, 'error', err); + } + } + + return originalEmit.apply(cp, arguments); + }; +} + +function verifyENOENT(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawn'); + } + + return null; +} + +function verifyENOENTSync(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawnSync'); + } + + // If we are in node 10, then we are using spawn-sync; if it exited + // with -1 it probably means that the command does not exist + if (isNode10 && status === -1) { + parsed.file = isWin ? parsed.file : resolveCommand(parsed.original); + + if (!parsed.file) { + return notFoundError(parsed.original, 'spawnSync'); + } + } + + return null; +} + +module.exports.hookChildProcess = hookChildProcess; +module.exports.verifyENOENT = verifyENOENT; +module.exports.verifyENOENTSync = verifyENOENTSync; +module.exports.notFoundError = notFoundError; + +}).call(this,require('_process')) +},{"./util/resolveCommand":65,"_process":437}],60:[function(require,module,exports){ +(function (process){ +'use strict'; + +var resolveCommand = require('./util/resolveCommand'); +var hasEmptyArgumentBug = require('./util/hasEmptyArgumentBug'); +var escapeArgument = require('./util/escapeArgument'); +var escapeCommand = require('./util/escapeCommand'); +var readShebang = require('./util/readShebang'); + +var isWin = process.platform === 'win32'; +var skipShellRegExp = /\.(?:com|exe)$/i; + +// Supported in Node >= 6 and >= 4.8 +var supportsShellOption = parseInt(process.version.substr(1).split('.')[0], 10) >= 6 || + parseInt(process.version.substr(1).split('.')[0], 10) === 4 && parseInt(process.version.substr(1).split('.')[1], 10) >= 8; + +function parseNonShell(parsed) { + var shebang; + var needsShell; + var applyQuotes; + + if (!isWin) { + return parsed; + } + + // Detect & add support for shebangs + parsed.file = resolveCommand(parsed.command); + parsed.file = parsed.file || resolveCommand(parsed.command, true); + shebang = parsed.file && readShebang(parsed.file); + + if (shebang) { + parsed.args.unshift(parsed.file); + parsed.command = shebang; + needsShell = hasEmptyArgumentBug || !skipShellRegExp.test(resolveCommand(shebang) || resolveCommand(shebang, true)); + } else { + needsShell = hasEmptyArgumentBug || !skipShellRegExp.test(parsed.file); + } + + // If a shell is required, use cmd.exe and take care of escaping everything correctly + if (needsShell) { + // Escape command & arguments + applyQuotes = (parsed.command !== 'echo'); // Do not quote arguments for the special "echo" command + parsed.command = escapeCommand(parsed.command); + parsed.args = parsed.args.map(function (arg) { + return escapeArgument(arg, applyQuotes); + }); + + // Make use of cmd.exe + parsed.args = ['/d', '/s', '/c', '"' + parsed.command + (parsed.args.length ? ' ' + parsed.args.join(' ') : '') + '"']; + parsed.command = process.env.comspec || 'cmd.exe'; + parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped + } + + return parsed; +} + +function parseShell(parsed) { + var shellCommand; + + // If node supports the shell option, there's no need to mimic its behavior + if (supportsShellOption) { + return parsed; + } + + // Mimic node shell option, see: https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335 + shellCommand = [parsed.command].concat(parsed.args).join(' '); + + if (isWin) { + parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe'; + parsed.args = ['/d', '/s', '/c', '"' + shellCommand + '"']; + parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped + } else { + if (typeof parsed.options.shell === 'string') { + parsed.command = parsed.options.shell; + } else if (process.platform === 'android') { + parsed.command = '/system/bin/sh'; + } else { + parsed.command = '/bin/sh'; + } + + parsed.args = ['-c', shellCommand]; + } + + return parsed; +} + +// ------------------------------------------------ + +function parse(command, args, options) { + var parsed; + + // Normalize arguments, similar to nodejs + if (args && !Array.isArray(args)) { + options = args; + args = null; + } + + args = args ? args.slice(0) : []; // Clone array to avoid changing the original + options = options || {}; + + // Build our parsed object + parsed = { + command: command, + args: args, + options: options, + file: undefined, + original: command, + }; + + // Delegate further parsing to shell or non-shell + return options.shell ? parseShell(parsed) : parseNonShell(parsed); +} + +module.exports = parse; + +}).call(this,require('_process')) +},{"./util/escapeArgument":61,"./util/escapeCommand":62,"./util/hasEmptyArgumentBug":63,"./util/readShebang":64,"./util/resolveCommand":65,"_process":437}],61:[function(require,module,exports){ +'use strict'; + +function escapeArgument(arg, quote) { + // Convert to string + arg = '' + arg; + + // If we are not going to quote the argument, + // escape shell metacharacters, including double and single quotes: + if (!quote) { + arg = arg.replace(/([()%!^<>&|;,"'\s])/g, '^$1'); + } else { + // Sequence of backslashes followed by a double quote: + // double up all the backslashes and escape the double quote + arg = arg.replace(/(\\*)"/g, '$1$1\\"'); + + // Sequence of backslashes followed by the end of the string + // (which will become a double quote later): + // double up all the backslashes + arg = arg.replace(/(\\*)$/, '$1$1'); + + // All other backslashes occur literally + + // Quote the whole thing: + arg = '"' + arg + '"'; + } + + return arg; +} + +module.exports = escapeArgument; + +},{}],62:[function(require,module,exports){ +'use strict'; + +var escapeArgument = require('./escapeArgument'); + +function escapeCommand(command) { + // Do not escape if this command is not dangerous.. + // We do this so that commands like "echo" or "ifconfig" work + // Quoting them, will make them unaccessible + return /^[a-z0-9_-]+$/i.test(command) ? command : escapeArgument(command, true); +} + +module.exports = escapeCommand; + +},{"./escapeArgument":61}],63:[function(require,module,exports){ +(function (process){ +'use strict'; + +// See: https://github.com/IndigoUnited/node-cross-spawn/pull/34#issuecomment-221623455 +function hasEmptyArgumentBug() { + var nodeVer; + + if (process.platform !== 'win32') { + return false; + } + + nodeVer = process.version.substr(1).split('.').map(function (num) { + return parseInt(num, 10); + }); + + return (nodeVer[0] === 0 && nodeVer[1] < 12); +} + +module.exports = hasEmptyArgumentBug(); + +}).call(this,require('_process')) +},{"_process":437}],64:[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +var fs = require('fs'); +var LRU = require('lru-cache'); +var shebangCommand = require('shebang-command'); + +var shebangCache = new LRU({ max: 50, maxAge: 30 * 1000 }); // Cache just for 30sec + +function readShebang(command) { + var buffer; + var fd; + var shebang; + + // Check if it is in the cache first + if (shebangCache.has(command)) { + return shebangCache.get(command); + } + + // Read the first 150 bytes from the file + buffer = new Buffer(150); + + try { + fd = fs.openSync(command, 'r'); + fs.readSync(fd, buffer, 0, 150, 0); + fs.closeSync(fd); + } catch (e) { /* empty */ } + + // Attempt to extract shebang (null is returned if not a shebang) + shebang = shebangCommand(buffer.toString()); + + // Store the shebang in the cache + shebangCache.set(command, shebang); + + return shebang; +} + +module.exports = readShebang; + +}).call(this,require("buffer").Buffer) +},{"buffer":299,"fs":298,"lru-cache":377,"shebang-command":497}],65:[function(require,module,exports){ +(function (process){ +'use strict'; + +var path = require('path'); +var which = require('which'); +var LRU = require('lru-cache'); + +var commandCache = new LRU({ max: 50, maxAge: 30 * 1000 }); // Cache just for 30sec + +function resolveCommand(command, noExtension) { + var resolved; + + noExtension = !!noExtension; + resolved = commandCache.get(command + '!' + noExtension); + + // Check if its resolved in the cache + if (commandCache.has(command)) { + return commandCache.get(command); + } + + try { + resolved = !noExtension ? + which.sync(command) : + which.sync(command, { pathExt: path.delimiter + (process.env.PATHEXT || '') }); + } catch (e) { /* empty */ } + + commandCache.set(command + '!' + noExtension, resolved); + + return resolved; +} + +module.exports = resolveCommand; + +}).call(this,require('_process')) +},{"_process":437,"lru-cache":377,"path":404,"which":530}],66:[function(require,module,exports){ +(function (process){ +'use strict'; +const childProcess = require('child_process'); +const util = require('util'); +const crossSpawn = require('cross-spawn'); +const stripEof = require('strip-eof'); +const npmRunPath = require('npm-run-path'); +const isStream = require('is-stream'); +const _getStream = require('get-stream'); +const pFinally = require('p-finally'); +const onExit = require('signal-exit'); +const errname = require('./lib/errname'); +const stdio = require('./lib/stdio'); + +const TEN_MEGABYTES = 1000 * 1000 * 10; + +function handleArgs(cmd, args, opts) { + let parsed; + + if (opts && opts.env && opts.extendEnv !== false) { + opts.env = Object.assign({}, process.env, opts.env); + } + + if (opts && opts.__winShell === true) { + delete opts.__winShell; + parsed = { + command: cmd, + args, + options: opts, + file: cmd, + original: cmd + }; + } else { + parsed = crossSpawn._parse(cmd, args, opts); + } + + opts = Object.assign({ + maxBuffer: TEN_MEGABYTES, + stripEof: true, + preferLocal: true, + localDir: parsed.options.cwd || process.cwd(), + encoding: 'utf8', + reject: true, + cleanup: true + }, parsed.options); + + opts.stdio = stdio(opts); + + if (opts.preferLocal) { + opts.env = npmRunPath.env(Object.assign({}, opts, {cwd: opts.localDir})); + } + + return { + cmd: parsed.command, + args: parsed.args, + opts, + parsed + }; +} + +function handleInput(spawned, opts) { + const input = opts.input; + + if (input === null || input === undefined) { + return; + } + + if (isStream(input)) { + input.pipe(spawned.stdin); + } else { + spawned.stdin.end(input); + } +} + +function handleOutput(opts, val) { + if (val && opts.stripEof) { + val = stripEof(val); + } + + return val; +} + +function handleShell(fn, cmd, opts) { + let file = '/bin/sh'; + let args = ['-c', cmd]; + + opts = Object.assign({}, opts); + + if (process.platform === 'win32') { + opts.__winShell = true; + file = process.env.comspec || 'cmd.exe'; + args = ['/s', '/c', `"${cmd}"`]; + opts.windowsVerbatimArguments = true; + } + + if (opts.shell) { + file = opts.shell; + delete opts.shell; + } + + return fn(file, args, opts); +} + +function getStream(process, stream, encoding, maxBuffer) { + if (!process[stream]) { + return null; + } + + let ret; + + if (encoding) { + ret = _getStream(process[stream], { + encoding, + maxBuffer + }); + } else { + ret = _getStream.buffer(process[stream], {maxBuffer}); + } + + return ret.catch(err => { + err.stream = stream; + err.message = `${stream} ${err.message}`; + throw err; + }); +} + +module.exports = (cmd, args, opts) => { + let joinedCmd = cmd; + + if (Array.isArray(args) && args.length > 0) { + joinedCmd += ' ' + args.join(' '); + } + + const parsed = handleArgs(cmd, args, opts); + const encoding = parsed.opts.encoding; + const maxBuffer = parsed.opts.maxBuffer; + + let spawned; + try { + spawned = childProcess.spawn(parsed.cmd, parsed.args, parsed.opts); + } catch (err) { + return Promise.reject(err); + } + + let removeExitHandler; + if (parsed.opts.cleanup) { + removeExitHandler = onExit(() => { + spawned.kill(); + }); + } + + let timeoutId = null; + let timedOut = false; + + const cleanupTimeout = () => { + if (timeoutId) { + clearTimeout(timeoutId); + timeoutId = null; + } + }; + + if (parsed.opts.timeout > 0) { + timeoutId = setTimeout(() => { + timeoutId = null; + timedOut = true; + spawned.kill(parsed.opts.killSignal); + }, parsed.opts.timeout); + } + + const processDone = new Promise(resolve => { + spawned.on('exit', (code, signal) => { + cleanupTimeout(); + resolve({code, signal}); + }); + + spawned.on('error', err => { + cleanupTimeout(); + resolve({err}); + }); + + if (spawned.stdin) { + spawned.stdin.on('error', err => { + cleanupTimeout(); + resolve({err}); + }); + } + }); + + function destroy() { + if (spawned.stdout) { + spawned.stdout.destroy(); + } + + if (spawned.stderr) { + spawned.stderr.destroy(); + } + } + + const promise = pFinally(Promise.all([ + processDone, + getStream(spawned, 'stdout', encoding, maxBuffer), + getStream(spawned, 'stderr', encoding, maxBuffer) + ]).then(arr => { + const result = arr[0]; + const stdout = arr[1]; + const stderr = arr[2]; + + let err = result.err; + const code = result.code; + const signal = result.signal; + + if (removeExitHandler) { + removeExitHandler(); + } + + if (err || code !== 0 || signal !== null) { + if (!err) { + let output = ''; + + if (Array.isArray(parsed.opts.stdio)) { + if (parsed.opts.stdio[2] !== 'inherit') { + output += output.length > 0 ? stderr : `\n${stderr}`; + } + + if (parsed.opts.stdio[1] !== 'inherit') { + output += `\n${stdout}`; + } + } else if (parsed.opts.stdio !== 'inherit') { + output = `\n${stderr}${stdout}`; + } + + err = new Error(`Command failed: ${joinedCmd}${output}`); + err.code = code < 0 ? errname(code) : code; + } + + // TODO: missing some timeout logic for killed + // https://github.com/nodejs/node/blob/master/lib/child_process.js#L203 + // err.killed = spawned.killed || killed; + err.killed = err.killed || spawned.killed; + + err.stdout = stdout; + err.stderr = stderr; + err.failed = true; + err.signal = signal || null; + err.cmd = joinedCmd; + err.timedOut = timedOut; + + if (!parsed.opts.reject) { + return err; + } + + throw err; + } + + return { + stdout: handleOutput(parsed.opts, stdout), + stderr: handleOutput(parsed.opts, stderr), + code: 0, + failed: false, + killed: false, + signal: null, + cmd: joinedCmd, + timedOut: false + }; + }), destroy); + + crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed); + + handleInput(spawned, parsed.opts); + + spawned.then = promise.then.bind(promise); + spawned.catch = promise.catch.bind(promise); + + return spawned; +}; + +module.exports.stdout = function () { + // TODO: set `stderr: 'ignore'` when that option is implemented + return module.exports.apply(null, arguments).then(x => x.stdout); +}; + +module.exports.stderr = function () { + // TODO: set `stdout: 'ignore'` when that option is implemented + return module.exports.apply(null, arguments).then(x => x.stderr); +}; + +module.exports.shell = (cmd, opts) => handleShell(module.exports, cmd, opts); + +module.exports.sync = (cmd, args, opts) => { + const parsed = handleArgs(cmd, args, opts); + + if (isStream(parsed.opts.input)) { + throw new TypeError('The `input` option cannot be a stream in sync mode'); + } + + const result = childProcess.spawnSync(parsed.cmd, parsed.args, parsed.opts); + + if (result.error || result.status !== 0) { + throw (result.error || new Error(result.stderr === '' ? result.stdout : result.stderr)); + } + + result.stdout = handleOutput(parsed.opts, result.stdout); + result.stderr = handleOutput(parsed.opts, result.stderr); + + return result; +}; + +module.exports.shellSync = (cmd, opts) => handleShell(module.exports.sync, cmd, opts); + +module.exports.spawn = util.deprecate(module.exports, 'execa.spawn() is deprecated. Use execa() instead.'); + +}).call(this,require('_process')) +},{"./lib/errname":67,"./lib/stdio":68,"_process":437,"child_process":298,"cross-spawn":58,"get-stream":70,"is-stream":366,"npm-run-path":397,"p-finally":402,"signal-exit":499,"strip-eof":509,"util":523}],67:[function(require,module,exports){ +(function (process){ +'use strict'; +// The Node team wants to deprecate `process.bind(...)`. +// https://github.com/nodejs/node/pull/2768 +// +// However, we need the 'uv' binding for errname support. +// This is a defensive wrapper around it so `execa` will not fail entirely if it stops working someday. +// +// If this ever stops working. See: https://github.com/sindresorhus/execa/issues/31#issuecomment-215939939 for another possible solution. +let uv; + +try { + uv = process.binding('uv'); + + if (typeof uv.errname !== 'function') { + throw new TypeError('uv.errname is not a function'); + } +} catch (err) { + console.error('execa/lib/errname: unable to establish process.binding(\'uv\')', err); + uv = null; +} + +function errname(uv, code) { + if (uv) { + return uv.errname(code); + } + + if (!(code < 0)) { + throw new Error('err >= 0'); + } + + return `Unknown system error ${code}`; +} + +module.exports = code => errname(uv, code); + +// Used for testing the fallback behavior +module.exports.__test__ = errname; + +}).call(this,require('_process')) +},{"_process":437}],68:[function(require,module,exports){ +'use strict'; +const alias = ['stdin', 'stdout', 'stderr']; + +const hasAlias = opts => alias.some(x => Boolean(opts[x])); + +module.exports = opts => { + if (!opts) { + return null; + } + + if (opts.stdio && hasAlias(opts)) { + throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${alias.map(x => `\`${x}\``).join(', ')}`); + } + + if (typeof opts.stdio === 'string') { + return opts.stdio; + } + + const stdio = opts.stdio || []; + + if (!Array.isArray(stdio)) { + throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); + } + + const result = []; + const len = Math.max(stdio.length, alias.length); + + for (let i = 0; i < len; i++) { + let value = null; + + if (stdio[i] !== undefined) { + value = stdio[i]; + } else if (opts[alias[i]] !== undefined) { + value = opts[alias[i]]; + } + + result[i] = value; + } + + return result; +}; + +},{}],69:[function(require,module,exports){ +(function (Buffer){ +'use strict'; +const PassThrough = require('stream').PassThrough; + +module.exports = opts => { + opts = Object.assign({}, opts); + + const array = opts.array; + let encoding = opts.encoding; + const buffer = encoding === 'buffer'; + let objectMode = false; + + if (array) { + objectMode = !(encoding || buffer); + } else { + encoding = encoding || 'utf8'; + } + + if (buffer) { + encoding = null; + } + + let len = 0; + const ret = []; + const stream = new PassThrough({objectMode}); + + if (encoding) { + stream.setEncoding(encoding); + } + + stream.on('data', chunk => { + ret.push(chunk); + + if (objectMode) { + len = ret.length; + } else { + len += chunk.length; + } + }); + + stream.getBufferedValue = () => { + if (array) { + return ret; + } + + return buffer ? Buffer.concat(ret, len) : ret.join(''); + }; + + stream.getBufferedLength = () => len; + + return stream; +}; + +}).call(this,require("buffer").Buffer) +},{"buffer":299,"stream":503}],70:[function(require,module,exports){ +'use strict'; +const bufferStream = require('./buffer-stream'); + +function getStream(inputStream, opts) { + if (!inputStream) { + return Promise.reject(new Error('Expected a stream')); + } + + opts = Object.assign({maxBuffer: Infinity}, opts); + + const maxBuffer = opts.maxBuffer; + let stream; + let clean; + + const p = new Promise((resolve, reject) => { + const error = err => { + if (err) { // null check + err.bufferedData = stream.getBufferedValue(); + } + + reject(err); + }; + + stream = bufferStream(opts); + inputStream.once('error', error); + inputStream.pipe(stream); + + stream.on('data', () => { + if (stream.getBufferedLength() > maxBuffer) { + reject(new Error('maxBuffer exceeded')); + } + }); + stream.once('error', error); + stream.on('end', resolve); + + clean = () => { + // some streams doesn't implement the `stream.Readable` interface correctly + if (inputStream.unpipe) { + inputStream.unpipe(stream); + } + }; + }); + + p.then(clean, clean); + + return p.then(() => stream.getBufferedValue()); +} + +module.exports = getStream; +module.exports.buffer = (stream, opts) => getStream(stream, Object.assign({}, opts, {encoding: 'buffer'})); +module.exports.array = (stream, opts) => getStream(stream, Object.assign({}, opts, {array: true})); + +},{"./buffer-stream":69}],71:[function(require,module,exports){ +'use strict'; + +const processFn = (fn, opts) => function () { + const P = opts.promiseModule; + const args = new Array(arguments.length); + + for (let i = 0; i < arguments.length; i++) { + args[i] = arguments[i]; + } + + return new P((resolve, reject) => { + if (opts.errorFirst) { + args.push(function (err, result) { + if (opts.multiArgs) { + const results = new Array(arguments.length - 1); + + for (let i = 1; i < arguments.length; i++) { + results[i - 1] = arguments[i]; + } + + if (err) { + results.unshift(err); + reject(results); + } else { + resolve(results); + } + } else if (err) { + reject(err); + } else { + resolve(result); + } + }); + } else { + args.push(function (result) { + if (opts.multiArgs) { + const results = new Array(arguments.length - 1); + + for (let i = 0; i < arguments.length; i++) { + results[i] = arguments[i]; + } + + resolve(results); + } else { + resolve(result); + } + }); + } + + fn.apply(this, args); + }); +}; + +module.exports = (obj, opts) => { + opts = Object.assign({ + exclude: [/.+(Sync|Stream)$/], + errorFirst: true, + promiseModule: Promise + }, opts); + + const filter = key => { + const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); + return opts.include ? opts.include.some(match) : !opts.exclude.some(match); + }; + + let ret; + if (typeof obj === 'function') { + ret = function () { + if (opts.excludeMain) { + return obj.apply(this, arguments); + } + + return processFn(obj, opts).apply(this, arguments); + }; + } else { + ret = Object.create(Object.getPrototypeOf(obj)); + } + + for (const key in obj) { // eslint-disable-line guard-for-in + const x = obj[key]; + ret[key] = typeof x === 'function' && filter(key) ? processFn(x, opts) : x; + } + + return ret; +}; + +},{}],72:[function(require,module,exports){ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = global || self, factory(global.exprEval = {})); +}(this, function (exports) { 'use strict'; + + var INUMBER = 'INUMBER'; + var IOP1 = 'IOP1'; + var IOP2 = 'IOP2'; + var IOP3 = 'IOP3'; + var IVAR = 'IVAR'; + var IVARNAME = 'IVARNAME'; + var IFUNCALL = 'IFUNCALL'; + var IFUNDEF = 'IFUNDEF'; + var IEXPR = 'IEXPR'; + var IEXPREVAL = 'IEXPREVAL'; + var IMEMBER = 'IMEMBER'; + var IENDSTATEMENT = 'IENDSTATEMENT'; + var IARRAY = 'IARRAY'; + + function Instruction(type, value) { + this.type = type; + this.value = (value !== undefined && value !== null) ? value : 0; + } + + Instruction.prototype.toString = function () { + switch (this.type) { + case INUMBER: + case IOP1: + case IOP2: + case IOP3: + case IVAR: + case IVARNAME: + case IENDSTATEMENT: + return this.value; + case IFUNCALL: + return 'CALL ' + this.value; + case IFUNDEF: + return 'DEF ' + this.value; + case IARRAY: + return 'ARRAY ' + this.value; + case IMEMBER: + return '.' + this.value; + default: + return 'Invalid Instruction'; + } + }; + + function unaryInstruction(value) { + return new Instruction(IOP1, value); + } + + function binaryInstruction(value) { + return new Instruction(IOP2, value); + } + + function ternaryInstruction(value) { + return new Instruction(IOP3, value); + } + + function simplify(tokens, unaryOps, binaryOps, ternaryOps, values) { + var nstack = []; + var newexpression = []; + var n1, n2, n3; + var f; + for (var i = 0; i < tokens.length; i++) { + var item = tokens[i]; + var type = item.type; + if (type === INUMBER || type === IVARNAME) { + if (Array.isArray(item.value)) { + nstack.push.apply(nstack, simplify(item.value.map(function (x) { + return new Instruction(INUMBER, x); + }).concat(new Instruction(IARRAY, item.value.length)), unaryOps, binaryOps, ternaryOps, values)); + } else { + nstack.push(item); + } + } else if (type === IVAR && values.hasOwnProperty(item.value)) { + item = new Instruction(INUMBER, values[item.value]); + nstack.push(item); + } else if (type === IOP2 && nstack.length > 1) { + n2 = nstack.pop(); + n1 = nstack.pop(); + f = binaryOps[item.value]; + item = new Instruction(INUMBER, f(n1.value, n2.value)); + nstack.push(item); + } else if (type === IOP3 && nstack.length > 2) { + n3 = nstack.pop(); + n2 = nstack.pop(); + n1 = nstack.pop(); + if (item.value === '?') { + nstack.push(n1.value ? n2.value : n3.value); + } else { + f = ternaryOps[item.value]; + item = new Instruction(INUMBER, f(n1.value, n2.value, n3.value)); + nstack.push(item); + } + } else if (type === IOP1 && nstack.length > 0) { + n1 = nstack.pop(); + f = unaryOps[item.value]; + item = new Instruction(INUMBER, f(n1.value)); + nstack.push(item); + } else if (type === IEXPR) { + while (nstack.length > 0) { + newexpression.push(nstack.shift()); + } + newexpression.push(new Instruction(IEXPR, simplify(item.value, unaryOps, binaryOps, ternaryOps, values))); + } else if (type === IMEMBER && nstack.length > 0) { + n1 = nstack.pop(); + nstack.push(new Instruction(INUMBER, n1.value[item.value])); + } /* else if (type === IARRAY && nstack.length >= item.value) { + var length = item.value; + while (length-- > 0) { + newexpression.push(nstack.pop()); + } + newexpression.push(new Instruction(IARRAY, item.value)); + } */ else { + while (nstack.length > 0) { + newexpression.push(nstack.shift()); + } + newexpression.push(item); + } + } + while (nstack.length > 0) { + newexpression.push(nstack.shift()); + } + return newexpression; + } + + function substitute(tokens, variable, expr) { + var newexpression = []; + for (var i = 0; i < tokens.length; i++) { + var item = tokens[i]; + var type = item.type; + if (type === IVAR && item.value === variable) { + for (var j = 0; j < expr.tokens.length; j++) { + var expritem = expr.tokens[j]; + var replitem; + if (expritem.type === IOP1) { + replitem = unaryInstruction(expritem.value); + } else if (expritem.type === IOP2) { + replitem = binaryInstruction(expritem.value); + } else if (expritem.type === IOP3) { + replitem = ternaryInstruction(expritem.value); + } else { + replitem = new Instruction(expritem.type, expritem.value); + } + newexpression.push(replitem); + } + } else if (type === IEXPR) { + newexpression.push(new Instruction(IEXPR, substitute(item.value, variable, expr))); + } else { + newexpression.push(item); + } + } + return newexpression; + } + + function evaluate(tokens, expr, values) { + var nstack = []; + var n1, n2, n3; + var f, args, argCount; + + if (isExpressionEvaluator(tokens)) { + return resolveExpression(tokens, values); + } + + var numTokens = tokens.length; + + for (var i = 0; i < numTokens; i++) { + var item = tokens[i]; + var type = item.type; + if (type === INUMBER || type === IVARNAME) { + nstack.push(item.value); + } else if (type === IOP2) { + n2 = nstack.pop(); + n1 = nstack.pop(); + if (item.value === 'and') { + nstack.push(n1 ? !!evaluate(n2, expr, values) : false); + } else if (item.value === 'or') { + nstack.push(n1 ? true : !!evaluate(n2, expr, values)); + } else if (item.value === '=') { + f = expr.binaryOps[item.value]; + nstack.push(f(n1, evaluate(n2, expr, values), values)); + } else { + f = expr.binaryOps[item.value]; + nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values))); + } + } else if (type === IOP3) { + n3 = nstack.pop(); + n2 = nstack.pop(); + n1 = nstack.pop(); + if (item.value === '?') { + nstack.push(evaluate(n1 ? n2 : n3, expr, values)); + } else { + f = expr.ternaryOps[item.value]; + nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values), resolveExpression(n3, values))); + } + } else if (type === IVAR) { + if (item.value in expr.functions) { + nstack.push(expr.functions[item.value]); + } else if (item.value in expr.unaryOps && expr.parser.isOperatorEnabled(item.value)) { + nstack.push(expr.unaryOps[item.value]); + } else { + var v = values[item.value]; + if (v !== undefined) { + nstack.push(v); + } else { + throw new Error('undefined variable: ' + item.value); + } + } + } else if (type === IOP1) { + n1 = nstack.pop(); + f = expr.unaryOps[item.value]; + nstack.push(f(resolveExpression(n1, values))); + } else if (type === IFUNCALL) { + argCount = item.value; + args = []; + while (argCount-- > 0) { + args.unshift(resolveExpression(nstack.pop(), values)); + } + f = nstack.pop(); + if (f.apply && f.call) { + nstack.push(f.apply(undefined, args)); + } else { + throw new Error(f + ' is not a function'); + } + } else if (type === IFUNDEF) { + // Create closure to keep references to arguments and expression + nstack.push((function () { + var n2 = nstack.pop(); + var args = []; + var argCount = item.value; + while (argCount-- > 0) { + args.unshift(nstack.pop()); + } + var n1 = nstack.pop(); + var f = function () { + var scope = Object.assign({}, values); + for (var i = 0, len = args.length; i < len; i++) { + scope[args[i]] = arguments[i]; + } + return evaluate(n2, expr, scope); + }; + // f.name = n1 + Object.defineProperty(f, 'name', { + value: n1, + writable: false + }); + values[n1] = f; + return f; + })()); + } else if (type === IEXPR) { + nstack.push(createExpressionEvaluator(item, expr)); + } else if (type === IEXPREVAL) { + nstack.push(item); + } else if (type === IMEMBER) { + n1 = nstack.pop(); + nstack.push(n1[item.value]); + } else if (type === IENDSTATEMENT) { + nstack.pop(); + } else if (type === IARRAY) { + argCount = item.value; + args = []; + while (argCount-- > 0) { + args.unshift(nstack.pop()); + } + nstack.push(args); + } else { + throw new Error('invalid Expression'); + } + } + if (nstack.length > 1) { + throw new Error('invalid Expression (parity)'); + } + // Explicitly return zero to avoid test issues caused by -0 + return nstack[0] === 0 ? 0 : resolveExpression(nstack[0], values); + } + + function createExpressionEvaluator(token, expr, values) { + if (isExpressionEvaluator(token)) return token; + return { + type: IEXPREVAL, + value: function (scope) { + return evaluate(token.value, expr, scope); + } + }; + } + + function isExpressionEvaluator(n) { + return n && n.type === IEXPREVAL; + } + + function resolveExpression(n, values) { + return isExpressionEvaluator(n) ? n.value(values) : n; + } + + function expressionToString(tokens, toJS) { + var nstack = []; + var n1, n2, n3; + var f, args, argCount; + for (var i = 0; i < tokens.length; i++) { + var item = tokens[i]; + var type = item.type; + if (type === INUMBER) { + if (typeof item.value === 'number' && item.value < 0) { + nstack.push('(' + item.value + ')'); + } else if (Array.isArray(item.value)) { + nstack.push('[' + item.value.map(escapeValue).join(', ') + ']'); + } else { + nstack.push(escapeValue(item.value)); + } + } else if (type === IOP2) { + n2 = nstack.pop(); + n1 = nstack.pop(); + f = item.value; + if (toJS) { + if (f === '^') { + nstack.push('Math.pow(' + n1 + ', ' + n2 + ')'); + } else if (f === 'and') { + nstack.push('(!!' + n1 + ' && !!' + n2 + ')'); + } else if (f === 'or') { + nstack.push('(!!' + n1 + ' || !!' + n2 + ')'); + } else if (f === '||') { + nstack.push('(function(a,b){ return Array.isArray(a) && Array.isArray(b) ? a.concat(b) : String(a) + String(b); }((' + n1 + '),(' + n2 + ')))'); + } else if (f === '==') { + nstack.push('(' + n1 + ' === ' + n2 + ')'); + } else if (f === '!=') { + nstack.push('(' + n1 + ' !== ' + n2 + ')'); + } else if (f === '[') { + nstack.push(n1 + '[(' + n2 + ') | 0]'); + } else { + nstack.push('(' + n1 + ' ' + f + ' ' + n2 + ')'); + } + } else { + if (f === '[') { + nstack.push(n1 + '[' + n2 + ']'); + } else { + nstack.push('(' + n1 + ' ' + f + ' ' + n2 + ')'); + } + } + } else if (type === IOP3) { + n3 = nstack.pop(); + n2 = nstack.pop(); + n1 = nstack.pop(); + f = item.value; + if (f === '?') { + nstack.push('(' + n1 + ' ? ' + n2 + ' : ' + n3 + ')'); + } else { + throw new Error('invalid Expression'); + } + } else if (type === IVAR || type === IVARNAME) { + nstack.push(item.value); + } else if (type === IOP1) { + n1 = nstack.pop(); + f = item.value; + if (f === '-' || f === '+') { + nstack.push('(' + f + n1 + ')'); + } else if (toJS) { + if (f === 'not') { + nstack.push('(' + '!' + n1 + ')'); + } else if (f === '!') { + nstack.push('fac(' + n1 + ')'); + } else { + nstack.push(f + '(' + n1 + ')'); + } + } else if (f === '!') { + nstack.push('(' + n1 + '!)'); + } else { + nstack.push('(' + f + ' ' + n1 + ')'); + } + } else if (type === IFUNCALL) { + argCount = item.value; + args = []; + while (argCount-- > 0) { + args.unshift(nstack.pop()); + } + f = nstack.pop(); + nstack.push(f + '(' + args.join(', ') + ')'); + } else if (type === IFUNDEF) { + n2 = nstack.pop(); + argCount = item.value; + args = []; + while (argCount-- > 0) { + args.unshift(nstack.pop()); + } + n1 = nstack.pop(); + if (toJS) { + nstack.push('(' + n1 + ' = function(' + args.join(', ') + ') { return ' + n2 + ' })'); + } else { + nstack.push('(' + n1 + '(' + args.join(', ') + ') = ' + n2 + ')'); + } + } else if (type === IMEMBER) { + n1 = nstack.pop(); + nstack.push(n1 + '.' + item.value); + } else if (type === IARRAY) { + argCount = item.value; + args = []; + while (argCount-- > 0) { + args.unshift(nstack.pop()); + } + nstack.push('[' + args.join(', ') + ']'); + } else if (type === IEXPR) { + nstack.push('(' + expressionToString(item.value, toJS) + ')'); + } else if (type === IENDSTATEMENT) ; else { + throw new Error('invalid Expression'); + } + } + if (nstack.length > 1) { + if (toJS) { + nstack = [ nstack.join(',') ]; + } else { + nstack = [ nstack.join(';') ]; + } + } + return String(nstack[0]); + } + + function escapeValue(v) { + if (typeof v === 'string') { + return JSON.stringify(v).replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029'); + } + return v; + } + + function contains(array, obj) { + for (var i = 0; i < array.length; i++) { + if (array[i] === obj) { + return true; + } + } + return false; + } + + function getSymbols(tokens, symbols, options) { + options = options || {}; + var withMembers = !!options.withMembers; + var prevVar = null; + + for (var i = 0; i < tokens.length; i++) { + var item = tokens[i]; + if (item.type === IVAR || item.type === IVARNAME) { + if (!withMembers && !contains(symbols, item.value)) { + symbols.push(item.value); + } else if (prevVar !== null) { + if (!contains(symbols, prevVar)) { + symbols.push(prevVar); + } + prevVar = item.value; + } else { + prevVar = item.value; + } + } else if (item.type === IMEMBER && withMembers && prevVar !== null) { + prevVar += '.' + item.value; + } else if (item.type === IEXPR) { + getSymbols(item.value, symbols, options); + } else if (prevVar !== null) { + if (!contains(symbols, prevVar)) { + symbols.push(prevVar); + } + prevVar = null; + } + } + + if (prevVar !== null && !contains(symbols, prevVar)) { + symbols.push(prevVar); + } + } + + function Expression(tokens, parser) { + this.tokens = tokens; + this.parser = parser; + this.unaryOps = parser.unaryOps; + this.binaryOps = parser.binaryOps; + this.ternaryOps = parser.ternaryOps; + this.functions = parser.functions; + } + + Expression.prototype.simplify = function (values) { + values = values || {}; + return new Expression(simplify(this.tokens, this.unaryOps, this.binaryOps, this.ternaryOps, values), this.parser); + }; + + Expression.prototype.substitute = function (variable, expr) { + if (!(expr instanceof Expression)) { + expr = this.parser.parse(String(expr)); + } + + return new Expression(substitute(this.tokens, variable, expr), this.parser); + }; + + Expression.prototype.evaluate = function (values) { + values = values || {}; + return evaluate(this.tokens, this, values); + }; + + Expression.prototype.toString = function () { + return expressionToString(this.tokens, false); + }; + + Expression.prototype.symbols = function (options) { + options = options || {}; + var vars = []; + getSymbols(this.tokens, vars, options); + return vars; + }; + + Expression.prototype.variables = function (options) { + options = options || {}; + var vars = []; + getSymbols(this.tokens, vars, options); + var functions = this.functions; + return vars.filter(function (name) { + return !(name in functions); + }); + }; + + Expression.prototype.toJSFunction = function (param, variables) { + var expr = this; + var f = new Function(param, 'with(this.functions) with (this.ternaryOps) with (this.binaryOps) with (this.unaryOps) { return ' + expressionToString(this.simplify(variables).tokens, true) + '; }'); // eslint-disable-line no-new-func + return function () { + return f.apply(expr, arguments); + }; + }; + + var TEOF = 'TEOF'; + var TOP = 'TOP'; + var TNUMBER = 'TNUMBER'; + var TSTRING = 'TSTRING'; + var TPAREN = 'TPAREN'; + var TBRACKET = 'TBRACKET'; + var TCOMMA = 'TCOMMA'; + var TNAME = 'TNAME'; + var TSEMICOLON = 'TSEMICOLON'; + + function Token(type, value, index) { + this.type = type; + this.value = value; + this.index = index; + } + + Token.prototype.toString = function () { + return this.type + ': ' + this.value; + }; + + function TokenStream(parser, expression) { + this.pos = 0; + this.current = null; + this.unaryOps = parser.unaryOps; + this.binaryOps = parser.binaryOps; + this.ternaryOps = parser.ternaryOps; + this.consts = parser.consts; + this.expression = expression; + this.savedPosition = 0; + this.savedCurrent = null; + this.options = parser.options; + this.parser = parser; + } + + TokenStream.prototype.newToken = function (type, value, pos) { + return new Token(type, value, pos != null ? pos : this.pos); + }; + + TokenStream.prototype.save = function () { + this.savedPosition = this.pos; + this.savedCurrent = this.current; + }; + + TokenStream.prototype.restore = function () { + this.pos = this.savedPosition; + this.current = this.savedCurrent; + }; + + TokenStream.prototype.next = function () { + if (this.pos >= this.expression.length) { + return this.newToken(TEOF, 'EOF'); + } + + if (this.isWhitespace() || this.isComment()) { + return this.next(); + } else if (this.isRadixInteger() || + this.isNumber() || + this.isOperator() || + this.isString() || + this.isParen() || + this.isBracket() || + this.isComma() || + this.isSemicolon() || + this.isNamedOp() || + this.isConst() || + this.isName()) { + return this.current; + } else { + this.parseError('Unknown character "' + this.expression.charAt(this.pos) + '"'); + } + }; + + TokenStream.prototype.isString = function () { + var r = false; + var startPos = this.pos; + var quote = this.expression.charAt(startPos); + + if (quote === '\'' || quote === '"') { + var index = this.expression.indexOf(quote, startPos + 1); + while (index >= 0 && this.pos < this.expression.length) { + this.pos = index + 1; + if (this.expression.charAt(index - 1) !== '\\') { + var rawString = this.expression.substring(startPos + 1, index); + this.current = this.newToken(TSTRING, this.unescape(rawString), startPos); + r = true; + break; + } + index = this.expression.indexOf(quote, index + 1); + } + } + return r; + }; + + TokenStream.prototype.isParen = function () { + var c = this.expression.charAt(this.pos); + if (c === '(' || c === ')') { + this.current = this.newToken(TPAREN, c); + this.pos++; + return true; + } + return false; + }; + + TokenStream.prototype.isBracket = function () { + var c = this.expression.charAt(this.pos); + if ((c === '[' || c === ']') && this.isOperatorEnabled('[')) { + this.current = this.newToken(TBRACKET, c); + this.pos++; + return true; + } + return false; + }; + + TokenStream.prototype.isComma = function () { + var c = this.expression.charAt(this.pos); + if (c === ',') { + this.current = this.newToken(TCOMMA, ','); + this.pos++; + return true; + } + return false; + }; + + TokenStream.prototype.isSemicolon = function () { + var c = this.expression.charAt(this.pos); + if (c === ';') { + this.current = this.newToken(TSEMICOLON, ';'); + this.pos++; + return true; + } + return false; + }; + + TokenStream.prototype.isConst = function () { + var startPos = this.pos; + var i = startPos; + for (; i < this.expression.length; i++) { + var c = this.expression.charAt(i); + if (c.toUpperCase() === c.toLowerCase()) { + if (i === this.pos || (c !== '_' && c !== '.' && (c < '0' || c > '9'))) { + break; + } + } + } + if (i > startPos) { + var str = this.expression.substring(startPos, i); + if (str in this.consts) { + this.current = this.newToken(TNUMBER, this.consts[str]); + this.pos += str.length; + return true; + } + } + return false; + }; + + TokenStream.prototype.isNamedOp = function () { + var startPos = this.pos; + var i = startPos; + for (; i < this.expression.length; i++) { + var c = this.expression.charAt(i); + if (c.toUpperCase() === c.toLowerCase()) { + if (i === this.pos || (c !== '_' && (c < '0' || c > '9'))) { + break; + } + } + } + if (i > startPos) { + var str = this.expression.substring(startPos, i); + if (this.isOperatorEnabled(str) && (str in this.binaryOps || str in this.unaryOps || str in this.ternaryOps)) { + this.current = this.newToken(TOP, str); + this.pos += str.length; + return true; + } + } + return false; + }; + + TokenStream.prototype.isName = function () { + var startPos = this.pos; + var i = startPos; + var hasLetter = false; + for (; i < this.expression.length; i++) { + var c = this.expression.charAt(i); + if (c.toUpperCase() === c.toLowerCase()) { + if (i === this.pos && (c === '$' || c === '_')) { + if (c === '_') { + hasLetter = true; + } + continue; + } else if (i === this.pos || !hasLetter || (c !== '_' && (c < '0' || c > '9'))) { + break; + } + } else { + hasLetter = true; + } + } + if (hasLetter) { + var str = this.expression.substring(startPos, i); + this.current = this.newToken(TNAME, str); + this.pos += str.length; + return true; + } + return false; + }; + + TokenStream.prototype.isWhitespace = function () { + var r = false; + var c = this.expression.charAt(this.pos); + while (c === ' ' || c === '\t' || c === '\n' || c === '\r') { + r = true; + this.pos++; + if (this.pos >= this.expression.length) { + break; + } + c = this.expression.charAt(this.pos); + } + return r; + }; + + var codePointPattern = /^[0-9a-f]{4}$/i; + + TokenStream.prototype.unescape = function (v) { + var index = v.indexOf('\\'); + if (index < 0) { + return v; + } + + var buffer = v.substring(0, index); + while (index >= 0) { + var c = v.charAt(++index); + switch (c) { + case '\'': + buffer += '\''; + break; + case '"': + buffer += '"'; + break; + case '\\': + buffer += '\\'; + break; + case '/': + buffer += '/'; + break; + case 'b': + buffer += '\b'; + break; + case 'f': + buffer += '\f'; + break; + case 'n': + buffer += '\n'; + break; + case 'r': + buffer += '\r'; + break; + case 't': + buffer += '\t'; + break; + case 'u': + // interpret the following 4 characters as the hex of the unicode code point + var codePoint = v.substring(index + 1, index + 5); + if (!codePointPattern.test(codePoint)) { + this.parseError('Illegal escape sequence: \\u' + codePoint); + } + buffer += String.fromCharCode(parseInt(codePoint, 16)); + index += 4; + break; + default: + throw this.parseError('Illegal escape sequence: "\\' + c + '"'); + } + ++index; + var backslash = v.indexOf('\\', index); + buffer += v.substring(index, backslash < 0 ? v.length : backslash); + index = backslash; + } + + return buffer; + }; + + TokenStream.prototype.isComment = function () { + var c = this.expression.charAt(this.pos); + if (c === '/' && this.expression.charAt(this.pos + 1) === '*') { + this.pos = this.expression.indexOf('*/', this.pos) + 2; + if (this.pos === 1) { + this.pos = this.expression.length; + } + return true; + } + return false; + }; + + TokenStream.prototype.isRadixInteger = function () { + var pos = this.pos; + + if (pos >= this.expression.length - 2 || this.expression.charAt(pos) !== '0') { + return false; + } + ++pos; + + var radix; + var validDigit; + if (this.expression.charAt(pos) === 'x') { + radix = 16; + validDigit = /^[0-9a-f]$/i; + ++pos; + } else if (this.expression.charAt(pos) === 'b') { + radix = 2; + validDigit = /^[01]$/i; + ++pos; + } else { + return false; + } + + var valid = false; + var startPos = pos; + + while (pos < this.expression.length) { + var c = this.expression.charAt(pos); + if (validDigit.test(c)) { + pos++; + valid = true; + } else { + break; + } + } + + if (valid) { + this.current = this.newToken(TNUMBER, parseInt(this.expression.substring(startPos, pos), radix)); + this.pos = pos; + } + return valid; + }; + + TokenStream.prototype.isNumber = function () { + var valid = false; + var pos = this.pos; + var startPos = pos; + var resetPos = pos; + var foundDot = false; + var foundDigits = false; + var c; + + while (pos < this.expression.length) { + c = this.expression.charAt(pos); + if ((c >= '0' && c <= '9') || (!foundDot && c === '.')) { + if (c === '.') { + foundDot = true; + } else { + foundDigits = true; + } + pos++; + valid = foundDigits; + } else { + break; + } + } + + if (valid) { + resetPos = pos; + } + + if (c === 'e' || c === 'E') { + pos++; + var acceptSign = true; + var validExponent = false; + while (pos < this.expression.length) { + c = this.expression.charAt(pos); + if (acceptSign && (c === '+' || c === '-')) { + acceptSign = false; + } else if (c >= '0' && c <= '9') { + validExponent = true; + acceptSign = false; + } else { + break; + } + pos++; + } + + if (!validExponent) { + pos = resetPos; + } + } + + if (valid) { + this.current = this.newToken(TNUMBER, parseFloat(this.expression.substring(startPos, pos))); + this.pos = pos; + } else { + this.pos = resetPos; + } + return valid; + }; + + TokenStream.prototype.isOperator = function () { + var startPos = this.pos; + var c = this.expression.charAt(this.pos); + + if (c === '+' || c === '-' || c === '*' || c === '/' || c === '%' || c === '^' || c === '?' || c === ':' || c === '.') { + this.current = this.newToken(TOP, c); + } else if (c === '∙' || c === '•') { + this.current = this.newToken(TOP, '*'); + } else if (c === '>') { + if (this.expression.charAt(this.pos + 1) === '=') { + this.current = this.newToken(TOP, '>='); + this.pos++; + } else { + this.current = this.newToken(TOP, '>'); + } + } else if (c === '<') { + if (this.expression.charAt(this.pos + 1) === '=') { + this.current = this.newToken(TOP, '<='); + this.pos++; + } else { + this.current = this.newToken(TOP, '<'); + } + } else if (c === '|') { + if (this.expression.charAt(this.pos + 1) === '|') { + this.current = this.newToken(TOP, '||'); + this.pos++; + } else { + return false; + } + } else if (c === '=') { + if (this.expression.charAt(this.pos + 1) === '=') { + this.current = this.newToken(TOP, '=='); + this.pos++; + } else { + this.current = this.newToken(TOP, c); + } + } else if (c === '!') { + if (this.expression.charAt(this.pos + 1) === '=') { + this.current = this.newToken(TOP, '!='); + this.pos++; + } else { + this.current = this.newToken(TOP, c); + } + } else { + return false; + } + this.pos++; + + if (this.isOperatorEnabled(this.current.value)) { + return true; + } else { + this.pos = startPos; + return false; + } + }; + + TokenStream.prototype.isOperatorEnabled = function (op) { + return this.parser.isOperatorEnabled(op); + }; + + TokenStream.prototype.getCoordinates = function () { + var line = 0; + var column; + var newline = -1; + do { + line++; + column = this.pos - newline; + newline = this.expression.indexOf('\n', newline + 1); + } while (newline >= 0 && newline < this.pos); + + return { + line: line, + column: column + }; + }; + + TokenStream.prototype.parseError = function (msg) { + var coords = this.getCoordinates(); + throw new Error('parse error [' + coords.line + ':' + coords.column + ']: ' + msg); + }; + + function ParserState(parser, tokenStream, options) { + this.parser = parser; + this.tokens = tokenStream; + this.current = null; + this.nextToken = null; + this.next(); + this.savedCurrent = null; + this.savedNextToken = null; + this.allowMemberAccess = options.allowMemberAccess !== false; + } + + ParserState.prototype.next = function () { + this.current = this.nextToken; + return (this.nextToken = this.tokens.next()); + }; + + ParserState.prototype.tokenMatches = function (token, value) { + if (typeof value === 'undefined') { + return true; + } else if (Array.isArray(value)) { + return contains(value, token.value); + } else if (typeof value === 'function') { + return value(token); + } else { + return token.value === value; + } + }; + + ParserState.prototype.save = function () { + this.savedCurrent = this.current; + this.savedNextToken = this.nextToken; + this.tokens.save(); + }; + + ParserState.prototype.restore = function () { + this.tokens.restore(); + this.current = this.savedCurrent; + this.nextToken = this.savedNextToken; + }; + + ParserState.prototype.accept = function (type, value) { + if (this.nextToken.type === type && this.tokenMatches(this.nextToken, value)) { + this.next(); + return true; + } + return false; + }; + + ParserState.prototype.expect = function (type, value) { + if (!this.accept(type, value)) { + var coords = this.tokens.getCoordinates(); + throw new Error('parse error [' + coords.line + ':' + coords.column + ']: Expected ' + (value || type)); + } + }; + + ParserState.prototype.parseAtom = function (instr) { + var unaryOps = this.tokens.unaryOps; + function isPrefixOperator(token) { + return token.value in unaryOps; + } + + if (this.accept(TNAME) || this.accept(TOP, isPrefixOperator)) { + instr.push(new Instruction(IVAR, this.current.value)); + } else if (this.accept(TNUMBER)) { + instr.push(new Instruction(INUMBER, this.current.value)); + } else if (this.accept(TSTRING)) { + instr.push(new Instruction(INUMBER, this.current.value)); + } else if (this.accept(TPAREN, '(')) { + this.parseExpression(instr); + this.expect(TPAREN, ')'); + } else if (this.accept(TBRACKET, '[')) { + if (this.accept(TBRACKET, ']')) { + instr.push(new Instruction(IARRAY, 0)); + } else { + var argCount = this.parseArrayList(instr); + instr.push(new Instruction(IARRAY, argCount)); + } + } else { + throw new Error('unexpected ' + this.nextToken); + } + }; + + ParserState.prototype.parseExpression = function (instr) { + var exprInstr = []; + if (this.parseUntilEndStatement(instr, exprInstr)) { + return; + } + this.parseVariableAssignmentExpression(exprInstr); + if (this.parseUntilEndStatement(instr, exprInstr)) { + return; + } + this.pushExpression(instr, exprInstr); + }; + + ParserState.prototype.pushExpression = function (instr, exprInstr) { + for (var i = 0, len = exprInstr.length; i < len; i++) { + instr.push(exprInstr[i]); + } + }; + + ParserState.prototype.parseUntilEndStatement = function (instr, exprInstr) { + if (!this.accept(TSEMICOLON)) return false; + if (this.nextToken && this.nextToken.type !== TEOF && !(this.nextToken.type === TPAREN && this.nextToken.value === ')')) { + exprInstr.push(new Instruction(IENDSTATEMENT)); + } + if (this.nextToken.type !== TEOF) { + this.parseExpression(exprInstr); + } + instr.push(new Instruction(IEXPR, exprInstr)); + return true; + }; + + ParserState.prototype.parseArrayList = function (instr) { + var argCount = 0; + + while (!this.accept(TBRACKET, ']')) { + this.parseExpression(instr); + ++argCount; + while (this.accept(TCOMMA)) { + this.parseExpression(instr); + ++argCount; + } + } + + return argCount; + }; + + ParserState.prototype.parseVariableAssignmentExpression = function (instr) { + this.parseConditionalExpression(instr); + while (this.accept(TOP, '=')) { + var varName = instr.pop(); + var varValue = []; + var lastInstrIndex = instr.length - 1; + if (varName.type === IFUNCALL) { + if (!this.tokens.isOperatorEnabled('()=')) { + throw new Error('function definition is not permitted'); + } + for (var i = 0, len = varName.value + 1; i < len; i++) { + var index = lastInstrIndex - i; + if (instr[index].type === IVAR) { + instr[index] = new Instruction(IVARNAME, instr[index].value); + } + } + this.parseVariableAssignmentExpression(varValue); + instr.push(new Instruction(IEXPR, varValue)); + instr.push(new Instruction(IFUNDEF, varName.value)); + continue; + } + if (varName.type !== IVAR && varName.type !== IMEMBER) { + throw new Error('expected variable for assignment'); + } + this.parseVariableAssignmentExpression(varValue); + instr.push(new Instruction(IVARNAME, varName.value)); + instr.push(new Instruction(IEXPR, varValue)); + instr.push(binaryInstruction('=')); + } + }; + + ParserState.prototype.parseConditionalExpression = function (instr) { + this.parseOrExpression(instr); + while (this.accept(TOP, '?')) { + var trueBranch = []; + var falseBranch = []; + this.parseConditionalExpression(trueBranch); + this.expect(TOP, ':'); + this.parseConditionalExpression(falseBranch); + instr.push(new Instruction(IEXPR, trueBranch)); + instr.push(new Instruction(IEXPR, falseBranch)); + instr.push(ternaryInstruction('?')); + } + }; + + ParserState.prototype.parseOrExpression = function (instr) { + this.parseAndExpression(instr); + while (this.accept(TOP, 'or')) { + var falseBranch = []; + this.parseAndExpression(falseBranch); + instr.push(new Instruction(IEXPR, falseBranch)); + instr.push(binaryInstruction('or')); + } + }; + + ParserState.prototype.parseAndExpression = function (instr) { + this.parseComparison(instr); + while (this.accept(TOP, 'and')) { + var trueBranch = []; + this.parseComparison(trueBranch); + instr.push(new Instruction(IEXPR, trueBranch)); + instr.push(binaryInstruction('and')); + } + }; + + var COMPARISON_OPERATORS = ['==', '!=', '<', '<=', '>=', '>', 'in']; + + ParserState.prototype.parseComparison = function (instr) { + this.parseAddSub(instr); + while (this.accept(TOP, COMPARISON_OPERATORS)) { + var op = this.current; + this.parseAddSub(instr); + instr.push(binaryInstruction(op.value)); + } + }; + + var ADD_SUB_OPERATORS = ['+', '-', '||']; + + ParserState.prototype.parseAddSub = function (instr) { + this.parseTerm(instr); + while (this.accept(TOP, ADD_SUB_OPERATORS)) { + var op = this.current; + this.parseTerm(instr); + instr.push(binaryInstruction(op.value)); + } + }; + + var TERM_OPERATORS = ['*', '/', '%']; + + ParserState.prototype.parseTerm = function (instr) { + this.parseFactor(instr); + while (this.accept(TOP, TERM_OPERATORS)) { + var op = this.current; + this.parseFactor(instr); + instr.push(binaryInstruction(op.value)); + } + }; + + ParserState.prototype.parseFactor = function (instr) { + var unaryOps = this.tokens.unaryOps; + function isPrefixOperator(token) { + return token.value in unaryOps; + } + + this.save(); + if (this.accept(TOP, isPrefixOperator)) { + if (this.current.value !== '-' && this.current.value !== '+') { + if (this.nextToken.type === TPAREN && this.nextToken.value === '(') { + this.restore(); + this.parseExponential(instr); + return; + } else if (this.nextToken.type === TSEMICOLON || this.nextToken.type === TCOMMA || this.nextToken.type === TEOF || (this.nextToken.type === TPAREN && this.nextToken.value === ')')) { + this.restore(); + this.parseAtom(instr); + return; + } + } + + var op = this.current; + this.parseFactor(instr); + instr.push(unaryInstruction(op.value)); + } else { + this.parseExponential(instr); + } + }; + + ParserState.prototype.parseExponential = function (instr) { + this.parsePostfixExpression(instr); + while (this.accept(TOP, '^')) { + this.parseFactor(instr); + instr.push(binaryInstruction('^')); + } + }; + + ParserState.prototype.parsePostfixExpression = function (instr) { + this.parseFunctionCall(instr); + while (this.accept(TOP, '!')) { + instr.push(unaryInstruction('!')); + } + }; + + ParserState.prototype.parseFunctionCall = function (instr) { + var unaryOps = this.tokens.unaryOps; + function isPrefixOperator(token) { + return token.value in unaryOps; + } + + if (this.accept(TOP, isPrefixOperator)) { + var op = this.current; + this.parseAtom(instr); + instr.push(unaryInstruction(op.value)); + } else { + this.parseMemberExpression(instr); + while (this.accept(TPAREN, '(')) { + if (this.accept(TPAREN, ')')) { + instr.push(new Instruction(IFUNCALL, 0)); + } else { + var argCount = this.parseArgumentList(instr); + instr.push(new Instruction(IFUNCALL, argCount)); + } + } + } + }; + + ParserState.prototype.parseArgumentList = function (instr) { + var argCount = 0; + + while (!this.accept(TPAREN, ')')) { + this.parseExpression(instr); + ++argCount; + while (this.accept(TCOMMA)) { + this.parseExpression(instr); + ++argCount; + } + } + + return argCount; + }; + + ParserState.prototype.parseMemberExpression = function (instr) { + this.parseAtom(instr); + while (this.accept(TOP, '.') || this.accept(TBRACKET, '[')) { + var op = this.current; + + if (op.value === '.') { + if (!this.allowMemberAccess) { + throw new Error('unexpected ".", member access is not permitted'); + } + + this.expect(TNAME); + instr.push(new Instruction(IMEMBER, this.current.value)); + } else if (op.value === '[') { + if (!this.tokens.isOperatorEnabled('[')) { + throw new Error('unexpected "[]", arrays are disabled'); + } + + this.parseExpression(instr); + this.expect(TBRACKET, ']'); + instr.push(binaryInstruction('[')); + } else { + throw new Error('unexpected symbol: ' + op.value); + } + } + }; + + function add(a, b) { + return Number(a) + Number(b); + } + + function sub(a, b) { + return a - b; + } + + function mul(a, b) { + return a * b; + } + + function div(a, b) { + return a / b; + } + + function mod(a, b) { + return a % b; + } + + function concat(a, b) { + if (Array.isArray(a) && Array.isArray(b)) { + return a.concat(b); + } + return '' + a + b; + } + + function equal(a, b) { + return a === b; + } + + function notEqual(a, b) { + return a !== b; + } + + function greaterThan(a, b) { + return a > b; + } + + function lessThan(a, b) { + return a < b; + } + + function greaterThanEqual(a, b) { + return a >= b; + } + + function lessThanEqual(a, b) { + return a <= b; + } + + function andOperator(a, b) { + return Boolean(a && b); + } + + function orOperator(a, b) { + return Boolean(a || b); + } + + function inOperator(a, b) { + return contains(b, a); + } + + function sinh(a) { + return ((Math.exp(a) - Math.exp(-a)) / 2); + } + + function cosh(a) { + return ((Math.exp(a) + Math.exp(-a)) / 2); + } + + function tanh(a) { + if (a === Infinity) return 1; + if (a === -Infinity) return -1; + return (Math.exp(a) - Math.exp(-a)) / (Math.exp(a) + Math.exp(-a)); + } + + function asinh(a) { + if (a === -Infinity) return a; + return Math.log(a + Math.sqrt((a * a) + 1)); + } + + function acosh(a) { + return Math.log(a + Math.sqrt((a * a) - 1)); + } + + function atanh(a) { + return (Math.log((1 + a) / (1 - a)) / 2); + } + + function log10(a) { + return Math.log(a) * Math.LOG10E; + } + + function neg(a) { + return -a; + } + + function not(a) { + return !a; + } + + function trunc(a) { + return a < 0 ? Math.ceil(a) : Math.floor(a); + } + + function random(a) { + return Math.random() * (a || 1); + } + + function factorial(a) { // a! + return gamma(a + 1); + } + + function isInteger(value) { + return isFinite(value) && (value === Math.round(value)); + } + + var GAMMA_G = 4.7421875; + var GAMMA_P = [ + 0.99999999999999709182, + 57.156235665862923517, -59.597960355475491248, + 14.136097974741747174, -0.49191381609762019978, + 0.33994649984811888699e-4, + 0.46523628927048575665e-4, -0.98374475304879564677e-4, + 0.15808870322491248884e-3, -0.21026444172410488319e-3, + 0.21743961811521264320e-3, -0.16431810653676389022e-3, + 0.84418223983852743293e-4, -0.26190838401581408670e-4, + 0.36899182659531622704e-5 + ]; + + // Gamma function from math.js + function gamma(n) { + var t, x; + + if (isInteger(n)) { + if (n <= 0) { + return isFinite(n) ? Infinity : NaN; + } + + if (n > 171) { + return Infinity; // Will overflow + } + + var value = n - 2; + var res = n - 1; + while (value > 1) { + res *= value; + value--; + } + + if (res === 0) { + res = 1; // 0! is per definition 1 + } + + return res; + } + + if (n < 0.5) { + return Math.PI / (Math.sin(Math.PI * n) * gamma(1 - n)); + } + + if (n >= 171.35) { + return Infinity; // will overflow + } + + if (n > 85.0) { // Extended Stirling Approx + var twoN = n * n; + var threeN = twoN * n; + var fourN = threeN * n; + var fiveN = fourN * n; + return Math.sqrt(2 * Math.PI / n) * Math.pow((n / Math.E), n) * + (1 + (1 / (12 * n)) + (1 / (288 * twoN)) - (139 / (51840 * threeN)) - + (571 / (2488320 * fourN)) + (163879 / (209018880 * fiveN)) + + (5246819 / (75246796800 * fiveN * n))); + } + + --n; + x = GAMMA_P[0]; + for (var i = 1; i < GAMMA_P.length; ++i) { + x += GAMMA_P[i] / (n + i); + } + + t = n + GAMMA_G + 0.5; + return Math.sqrt(2 * Math.PI) * Math.pow(t, n + 0.5) * Math.exp(-t) * x; + } + + function stringOrArrayLength(s) { + if (Array.isArray(s)) { + return s.length; + } + return String(s).length; + } + + function hypot() { + var sum = 0; + var larg = 0; + for (var i = 0; i < arguments.length; i++) { + var arg = Math.abs(arguments[i]); + var div; + if (larg < arg) { + div = larg / arg; + sum = (sum * div * div) + 1; + larg = arg; + } else if (arg > 0) { + div = arg / larg; + sum += div * div; + } else { + sum += arg; + } + } + return larg === Infinity ? Infinity : larg * Math.sqrt(sum); + } + + function condition(cond, yep, nope) { + return cond ? yep : nope; + } + + /** + * Decimal adjustment of a number. + * From @escopecz. + * + * @param {Number} value The number. + * @param {Integer} exp The exponent (the 10 logarithm of the adjustment base). + * @return {Number} The adjusted value. + */ + function roundTo(value, exp) { + // If the exp is undefined or zero... + if (typeof exp === 'undefined' || +exp === 0) { + return Math.round(value); + } + value = +value; + exp = -(+exp); + // If the value is not a number or the exp is not an integer... + if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) { + return NaN; + } + // Shift + value = value.toString().split('e'); + value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp))); + // Shift back + value = value.toString().split('e'); + return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)); + } + + function setVar(name, value, variables) { + if (variables) variables[name] = value; + return value; + } + + function arrayIndex(array, index) { + return array[index | 0]; + } + + function max(array) { + if (arguments.length === 1 && Array.isArray(array)) { + return Math.max.apply(Math, array); + } else { + return Math.max.apply(Math, arguments); + } + } + + function min(array) { + if (arguments.length === 1 && Array.isArray(array)) { + return Math.min.apply(Math, array); + } else { + return Math.min.apply(Math, arguments); + } + } + + function arrayMap(f, a) { + if (typeof f !== 'function') { + throw new Error('First argument to map is not a function'); + } + if (!Array.isArray(a)) { + throw new Error('Second argument to map is not an array'); + } + return a.map(function (x, i) { + return f(x, i); + }); + } + + function arrayFold(f, init, a) { + if (typeof f !== 'function') { + throw new Error('First argument to fold is not a function'); + } + if (!Array.isArray(a)) { + throw new Error('Second argument to fold is not an array'); + } + return a.reduce(function (acc, x, i) { + return f(acc, x, i); + }, init); + } + + function arrayFilter(f, a) { + if (typeof f !== 'function') { + throw new Error('First argument to filter is not a function'); + } + if (!Array.isArray(a)) { + throw new Error('Second argument to filter is not an array'); + } + return a.filter(function (x, i) { + return f(x, i); + }); + } + + function stringOrArrayIndexOf(target, s) { + if (!(Array.isArray(s) || typeof s === 'string')) { + throw new Error('Second argument to indexOf is not a string or array'); + } + + return s.indexOf(target); + } + + function arrayJoin(sep, a) { + if (!Array.isArray(a)) { + throw new Error('Second argument to join is not an array'); + } + + return a.join(sep); + } + + function sign(x) { + return ((x > 0) - (x < 0)) || +x; + } + + var ONE_THIRD = 1/3; + function cbrt(x) { + return x < 0 ? -Math.pow(-x, ONE_THIRD) : Math.pow(x, ONE_THIRD); + } + + function expm1(x) { + return Math.exp(x) - 1; + } + + function log1p(x) { + return Math.log(1 + x); + } + + function log2(x) { + return Math.log(x) / Math.LN2; + } + + function Parser(options) { + this.options = options || {}; + this.unaryOps = { + sin: Math.sin, + cos: Math.cos, + tan: Math.tan, + asin: Math.asin, + acos: Math.acos, + atan: Math.atan, + sinh: Math.sinh || sinh, + cosh: Math.cosh || cosh, + tanh: Math.tanh || tanh, + asinh: Math.asinh || asinh, + acosh: Math.acosh || acosh, + atanh: Math.atanh || atanh, + sqrt: Math.sqrt, + cbrt: Math.cbrt || cbrt, + log: Math.log, + log2: Math.log2 || log2, + ln: Math.log, + lg: Math.log10 || log10, + log10: Math.log10 || log10, + expm1: Math.expm1 || expm1, + log1p: Math.log1p || log1p, + abs: Math.abs, + ceil: Math.ceil, + floor: Math.floor, + round: Math.round, + trunc: Math.trunc || trunc, + '-': neg, + '+': Number, + exp: Math.exp, + not: not, + length: stringOrArrayLength, + '!': factorial, + sign: Math.sign || sign + }; + + this.binaryOps = { + '+': add, + '-': sub, + '*': mul, + '/': div, + '%': mod, + '^': Math.pow, + '||': concat, + '==': equal, + '!=': notEqual, + '>': greaterThan, + '<': lessThan, + '>=': greaterThanEqual, + '<=': lessThanEqual, + and: andOperator, + or: orOperator, + 'in': inOperator, + '=': setVar, + '[': arrayIndex + }; + + this.ternaryOps = { + '?': condition + }; + + this.functions = { + random: random, + fac: factorial, + min: min, + max: max, + hypot: Math.hypot || hypot, + pyt: Math.hypot || hypot, // backward compat + pow: Math.pow, + atan2: Math.atan2, + 'if': condition, + gamma: gamma, + roundTo: roundTo, + map: arrayMap, + fold: arrayFold, + filter: arrayFilter, + indexOf: stringOrArrayIndexOf, + join: arrayJoin + }; + + this.consts = { + E: Math.E, + PI: Math.PI, + 'true': true, + 'false': false + }; + } + + Parser.prototype.parse = function (expr) { + var instr = []; + var parserState = new ParserState( + this, + new TokenStream(this, expr), + { allowMemberAccess: this.options.allowMemberAccess } + ); + + parserState.parseExpression(instr); + parserState.expect(TEOF, 'EOF'); + + return new Expression(instr, this); + }; + + Parser.prototype.evaluate = function (expr, variables) { + return this.parse(expr).evaluate(variables); + }; + + var sharedParser = new Parser(); + + Parser.parse = function (expr) { + return sharedParser.parse(expr); + }; + + Parser.evaluate = function (expr, variables) { + return sharedParser.parse(expr).evaluate(variables); + }; + + var optionNameMap = { + '+': 'add', + '-': 'subtract', + '*': 'multiply', + '/': 'divide', + '%': 'remainder', + '^': 'power', + '!': 'factorial', + '<': 'comparison', + '>': 'comparison', + '<=': 'comparison', + '>=': 'comparison', + '==': 'comparison', + '!=': 'comparison', + '||': 'concatenate', + 'and': 'logical', + 'or': 'logical', + 'not': 'logical', + '?': 'conditional', + ':': 'conditional', + '=': 'assignment', + '[': 'array', + '()=': 'fndef' + }; + + function getOptionName(op) { + return optionNameMap.hasOwnProperty(op) ? optionNameMap[op] : op; + } + + Parser.prototype.isOperatorEnabled = function (op) { + var optionName = getOptionName(op); + var operators = this.options.operators || {}; + + return !(optionName in operators) || !!operators[optionName]; + }; + + /*! + Based on ndef.parser, by Raphael Graf(r@undefined.ch) + http://www.undefined.ch/mparser/index.html + + Ported to JavaScript and modified by Matthew Crumley (email@matthewcrumley.com, http://silentmatt.com/) + + You are free to use and modify this code in anyway you find useful. Please leave this comment in the code + to acknowledge its original source. If you feel like it, I enjoy hearing about projects that use my code, + but don't feel like you have to let me know or ask permission. + */ + + // Backwards compatibility + var index = { + Parser: Parser, + Expression: Expression + }; + + exports.Expression = Expression; + exports.Parser = Parser; + exports.default = index; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); + +},{}],73:[function(require,module,exports){ +'use strict'; + +const stringify = require('./lib/stringify'); +const compile = require('./lib/compile'); +const expand = require('./lib/expand'); +const parse = require('./lib/parse'); + +/** + * Expand the given pattern or create a regex-compatible string. + * + * ```js + * const braces = require('braces'); + * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] + * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] + * ``` + * @param {String} `str` + * @param {Object} `options` + * @return {String} + * @api public + */ + +const braces = (input, options = {}) => { + let output = []; + + if (Array.isArray(input)) { + for (let pattern of input) { + let result = braces.create(pattern, options); + if (Array.isArray(result)) { + output.push(...result); + } else { + output.push(result); + } + } + } else { + output = [].concat(braces.create(input, options)); + } + + if (options && options.expand === true && options.nodupes === true) { + output = [...new Set(output)]; + } + return output; +}; + +/** + * Parse the given `str` with the given `options`. + * + * ```js + * // braces.parse(pattern, [, options]); + * const ast = braces.parse('a/{b,c}/d'); + * console.log(ast); + * ``` + * @param {String} pattern Brace pattern to parse + * @param {Object} options + * @return {Object} Returns an AST + * @api public + */ + +braces.parse = (input, options = {}) => parse(input, options); + +/** + * Creates a braces string from an AST, or an AST node. + * + * ```js + * const braces = require('braces'); + * let ast = braces.parse('foo/{a,b}/bar'); + * console.log(stringify(ast.nodes[2])); //=> '{a,b}' + * ``` + * @param {String} `input` Brace pattern or AST. + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.stringify = (input, options = {}) => { + if (typeof input === 'string') { + return stringify(braces.parse(input, options), options); + } + return stringify(input, options); +}; + +/** + * Compiles a brace pattern into a regex-compatible, optimized string. + * This method is called by the main [braces](#braces) function by default. + * + * ```js + * const braces = require('braces'); + * console.log(braces.compile('a/{b,c}/d')); + * //=> ['a/(b|c)/d'] + * ``` + * @param {String} `input` Brace pattern or AST. + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.compile = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); + } + return compile(input, options); +}; + +/** + * Expands a brace pattern into an array. This method is called by the + * main [braces](#braces) function when `options.expand` is true. Before + * using this method it's recommended that you read the [performance notes](#performance)) + * and advantages of using [.compile](#compile) instead. + * + * ```js + * const braces = require('braces'); + * console.log(braces.expand('a/{b,c}/d')); + * //=> ['a/b/d', 'a/c/d']; + * ``` + * @param {String} `pattern` Brace pattern + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.expand = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); + } + + let result = expand(input, options); + + // filter out empty strings if specified + if (options.noempty === true) { + result = result.filter(Boolean); + } + + // filter out duplicates if specified + if (options.nodupes === true) { + result = [...new Set(result)]; + } + + return result; +}; + +/** + * Processes a brace pattern and returns either an expanded array + * (if `options.expand` is true), a highly optimized regex-compatible string. + * This method is called by the main [braces](#braces) function. + * + * ```js + * const braces = require('braces'); + * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) + * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' + * ``` + * @param {String} `pattern` Brace pattern + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.create = (input, options = {}) => { + if (input === '' || input.length < 3) { + return [input]; + } + + return options.expand !== true + ? braces.compile(input, options) + : braces.expand(input, options); +}; + +/** + * Expose "braces" + */ + +module.exports = braces; + +},{"./lib/compile":74,"./lib/expand":76,"./lib/parse":77,"./lib/stringify":78}],74:[function(require,module,exports){ +'use strict'; + +const fill = require('fill-range'); +const utils = require('./utils'); + +const compile = (ast, options = {}) => { + let walk = (node, parent = {}) => { + let invalidBlock = utils.isInvalidBrace(parent); + let invalidNode = node.invalid === true && options.escapeInvalid === true; + let invalid = invalidBlock === true || invalidNode === true; + let prefix = options.escapeInvalid === true ? '\\' : ''; + let output = ''; + + if (node.isOpen === true) { + return prefix + node.value; + } + if (node.isClose === true) { + return prefix + node.value; + } + + if (node.type === 'open') { + return invalid ? (prefix + node.value) : '('; + } + + if (node.type === 'close') { + return invalid ? (prefix + node.value) : ')'; + } + + if (node.type === 'comma') { + return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|'); + } + + if (node.value) { + return node.value; + } + + if (node.nodes && node.ranges > 0) { + let args = utils.reduce(node.nodes); + let range = fill(...args, { ...options, wrap: false, toRegex: true }); + + if (range.length !== 0) { + return args.length > 1 && range.length > 1 ? `(${range})` : range; + } + } + + if (node.nodes) { + for (let child of node.nodes) { + output += walk(child, node); + } + } + return output; + }; + + return walk(ast); +}; + +module.exports = compile; + +},{"./utils":79,"fill-range":80}],75:[function(require,module,exports){ +'use strict'; + +module.exports = { + MAX_LENGTH: 1024 * 64, + + // Digits + CHAR_0: '0', /* 0 */ + CHAR_9: '9', /* 9 */ + + // Alphabet chars. + CHAR_UPPERCASE_A: 'A', /* A */ + CHAR_LOWERCASE_A: 'a', /* a */ + CHAR_UPPERCASE_Z: 'Z', /* Z */ + CHAR_LOWERCASE_Z: 'z', /* z */ + + CHAR_LEFT_PARENTHESES: '(', /* ( */ + CHAR_RIGHT_PARENTHESES: ')', /* ) */ + + CHAR_ASTERISK: '*', /* * */ + + // Non-alphabetic chars. + CHAR_AMPERSAND: '&', /* & */ + CHAR_AT: '@', /* @ */ + CHAR_BACKSLASH: '\\', /* \ */ + CHAR_BACKTICK: '`', /* ` */ + CHAR_CARRIAGE_RETURN: '\r', /* \r */ + CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ + CHAR_COLON: ':', /* : */ + CHAR_COMMA: ',', /* , */ + CHAR_DOLLAR: '$', /* . */ + CHAR_DOT: '.', /* . */ + CHAR_DOUBLE_QUOTE: '"', /* " */ + CHAR_EQUAL: '=', /* = */ + CHAR_EXCLAMATION_MARK: '!', /* ! */ + CHAR_FORM_FEED: '\f', /* \f */ + CHAR_FORWARD_SLASH: '/', /* / */ + CHAR_HASH: '#', /* # */ + CHAR_HYPHEN_MINUS: '-', /* - */ + CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ + CHAR_LEFT_CURLY_BRACE: '{', /* { */ + CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ + CHAR_LINE_FEED: '\n', /* \n */ + CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ + CHAR_PERCENT: '%', /* % */ + CHAR_PLUS: '+', /* + */ + CHAR_QUESTION_MARK: '?', /* ? */ + CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ + CHAR_RIGHT_CURLY_BRACE: '}', /* } */ + CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ + CHAR_SEMICOLON: ';', /* ; */ + CHAR_SINGLE_QUOTE: '\'', /* ' */ + CHAR_SPACE: ' ', /* */ + CHAR_TAB: '\t', /* \t */ + CHAR_UNDERSCORE: '_', /* _ */ + CHAR_VERTICAL_LINE: '|', /* | */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ +}; + +},{}],76:[function(require,module,exports){ +'use strict'; + +const fill = require('fill-range'); +const stringify = require('./stringify'); +const utils = require('./utils'); + +const append = (queue = '', stash = '', enclose = false) => { + let result = []; + + queue = [].concat(queue); + stash = [].concat(stash); + + if (!stash.length) return queue; + if (!queue.length) { + return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; + } + + for (let item of queue) { + if (Array.isArray(item)) { + for (let value of item) { + result.push(append(value, stash, enclose)); + } + } else { + for (let ele of stash) { + if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; + result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele)); + } + } + } + return utils.flatten(result); +}; + +const expand = (ast, options = {}) => { + let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit; + + let walk = (node, parent = {}) => { + node.queue = []; + + let p = parent; + let q = parent.queue; + + while (p.type !== 'brace' && p.type !== 'root' && p.parent) { + p = p.parent; + q = p.queue; + } + + if (node.invalid || node.dollar) { + q.push(append(q.pop(), stringify(node, options))); + return; + } + + if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { + q.push(append(q.pop(), ['{}'])); + return; + } + + if (node.nodes && node.ranges > 0) { + let args = utils.reduce(node.nodes); + + if (utils.exceedsLimit(...args, options.step, rangeLimit)) { + throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); + } + + let range = fill(...args, options); + if (range.length === 0) { + range = stringify(node, options); + } + + q.push(append(q.pop(), range)); + node.nodes = []; + return; + } + + let enclose = utils.encloseBrace(node); + let queue = node.queue; + let block = node; + + while (block.type !== 'brace' && block.type !== 'root' && block.parent) { + block = block.parent; + queue = block.queue; + } + + for (let i = 0; i < node.nodes.length; i++) { + let child = node.nodes[i]; + + if (child.type === 'comma' && node.type === 'brace') { + if (i === 1) queue.push(''); + queue.push(''); + continue; + } + + if (child.type === 'close') { + q.push(append(q.pop(), queue, enclose)); + continue; + } + + if (child.value && child.type !== 'open') { + queue.push(append(queue.pop(), child.value)); + continue; + } + + if (child.nodes) { + walk(child, node); + } + } + + return queue; + }; + + return utils.flatten(walk(ast)); +}; + +module.exports = expand; + +},{"./stringify":78,"./utils":79,"fill-range":80}],77:[function(require,module,exports){ +'use strict'; + +const stringify = require('./stringify'); + +/** + * Constants + */ + +const { + MAX_LENGTH, + CHAR_BACKSLASH, /* \ */ + CHAR_BACKTICK, /* ` */ + CHAR_COMMA, /* , */ + CHAR_DOT, /* . */ + CHAR_LEFT_PARENTHESES, /* ( */ + CHAR_RIGHT_PARENTHESES, /* ) */ + CHAR_LEFT_CURLY_BRACE, /* { */ + CHAR_RIGHT_CURLY_BRACE, /* } */ + CHAR_LEFT_SQUARE_BRACKET, /* [ */ + CHAR_RIGHT_SQUARE_BRACKET, /* ] */ + CHAR_DOUBLE_QUOTE, /* " */ + CHAR_SINGLE_QUOTE, /* ' */ + CHAR_NO_BREAK_SPACE, + CHAR_ZERO_WIDTH_NOBREAK_SPACE +} = require('./constants'); + +/** + * parse + */ + +const parse = (input, options = {}) => { + if (typeof input !== 'string') { + throw new TypeError('Expected a string'); + } + + let opts = options || {}; + let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + if (input.length > max) { + throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); + } + + let ast = { type: 'root', input, nodes: [] }; + let stack = [ast]; + let block = ast; + let prev = ast; + let brackets = 0; + let length = input.length; + let index = 0; + let depth = 0; + let value; + let memo = {}; + + /** + * Helpers + */ + + const advance = () => input[index++]; + const push = node => { + if (node.type === 'text' && prev.type === 'dot') { + prev.type = 'text'; + } + + if (prev && prev.type === 'text' && node.type === 'text') { + prev.value += node.value; + return; + } + + block.nodes.push(node); + node.parent = block; + node.prev = prev; + prev = node; + return node; + }; + + push({ type: 'bos' }); + + while (index < length) { + block = stack[stack.length - 1]; + value = advance(); + + /** + * Invalid chars + */ + + if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { + continue; + } + + /** + * Escaped chars + */ + + if (value === CHAR_BACKSLASH) { + push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); + continue; + } + + /** + * Right square bracket (literal): ']' + */ + + if (value === CHAR_RIGHT_SQUARE_BRACKET) { + push({ type: 'text', value: '\\' + value }); + continue; + } + + /** + * Left square bracket: '[' + */ + + if (value === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + + let closed = true; + let next; + + while (index < length && (next = advance())) { + value += next; + + if (next === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + continue; + } + + if (next === CHAR_BACKSLASH) { + value += advance(); + continue; + } + + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + brackets--; + + if (brackets === 0) { + break; + } + } + } + + push({ type: 'text', value }); + continue; + } + + /** + * Parentheses + */ + + if (value === CHAR_LEFT_PARENTHESES) { + block = push({ type: 'paren', nodes: [] }); + stack.push(block); + push({ type: 'text', value }); + continue; + } + + if (value === CHAR_RIGHT_PARENTHESES) { + if (block.type !== 'paren') { + push({ type: 'text', value }); + continue; + } + block = stack.pop(); + push({ type: 'text', value }); + block = stack[stack.length - 1]; + continue; + } + + /** + * Quotes: '|"|` + */ + + if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { + let open = value; + let next; + + if (options.keepQuotes !== true) { + value = ''; + } + + while (index < length && (next = advance())) { + if (next === CHAR_BACKSLASH) { + value += next + advance(); + continue; + } + + if (next === open) { + if (options.keepQuotes === true) value += next; + break; + } + + value += next; + } + + push({ type: 'text', value }); + continue; + } + + /** + * Left curly brace: '{' + */ + + if (value === CHAR_LEFT_CURLY_BRACE) { + depth++; + + let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; + let brace = { + type: 'brace', + open: true, + close: false, + dollar, + depth, + commas: 0, + ranges: 0, + nodes: [] + }; + + block = push(brace); + stack.push(block); + push({ type: 'open', value }); + continue; + } + + /** + * Right curly brace: '}' + */ + + if (value === CHAR_RIGHT_CURLY_BRACE) { + if (block.type !== 'brace') { + push({ type: 'text', value }); + continue; + } + + let type = 'close'; + block = stack.pop(); + block.close = true; + + push({ type, value }); + depth--; + + block = stack[stack.length - 1]; + continue; + } + + /** + * Comma: ',' + */ + + if (value === CHAR_COMMA && depth > 0) { + if (block.ranges > 0) { + block.ranges = 0; + let open = block.nodes.shift(); + block.nodes = [open, { type: 'text', value: stringify(block) }]; + } + + push({ type: 'comma', value }); + block.commas++; + continue; + } + + /** + * Dot: '.' + */ + + if (value === CHAR_DOT && depth > 0 && block.commas === 0) { + let siblings = block.nodes; + + if (depth === 0 || siblings.length === 0) { + push({ type: 'text', value }); + continue; + } + + if (prev.type === 'dot') { + block.range = []; + prev.value += value; + prev.type = 'range'; + + if (block.nodes.length !== 3 && block.nodes.length !== 5) { + block.invalid = true; + block.ranges = 0; + prev.type = 'text'; + continue; + } + + block.ranges++; + block.args = []; + continue; + } + + if (prev.type === 'range') { + siblings.pop(); + + let before = siblings[siblings.length - 1]; + before.value += prev.value + value; + prev = before; + block.ranges--; + continue; + } + + push({ type: 'dot', value }); + continue; + } + + /** + * Text + */ + + push({ type: 'text', value }); + } + + // Mark imbalanced braces and brackets as invalid + do { + block = stack.pop(); + + if (block.type !== 'root') { + block.nodes.forEach(node => { + if (!node.nodes) { + if (node.type === 'open') node.isOpen = true; + if (node.type === 'close') node.isClose = true; + if (!node.nodes) node.type = 'text'; + node.invalid = true; + } + }); + + // get the location of the block on parent.nodes (block's siblings) + let parent = stack[stack.length - 1]; + let index = parent.nodes.indexOf(block); + // replace the (invalid) block with it's nodes + parent.nodes.splice(index, 1, ...block.nodes); + } + } while (stack.length > 0); + + push({ type: 'eos' }); + return ast; +}; + +module.exports = parse; + +},{"./constants":75,"./stringify":78}],78:[function(require,module,exports){ +'use strict'; + +const utils = require('./utils'); + +module.exports = (ast, options = {}) => { + let stringify = (node, parent = {}) => { + let invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent); + let invalidNode = node.invalid === true && options.escapeInvalid === true; + let output = ''; + + if (node.value) { + if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) { + return '\\' + node.value; + } + return node.value; + } + + if (node.value) { + return node.value; + } + + if (node.nodes) { + for (let child of node.nodes) { + output += stringify(child); + } + } + return output; + }; + + return stringify(ast); +}; + + +},{"./utils":79}],79:[function(require,module,exports){ +'use strict'; + +exports.isInteger = num => { + if (typeof num === 'number') { + return Number.isInteger(num); + } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isInteger(Number(num)); + } + return false; +}; + +/** + * Find a node of the given type + */ + +exports.find = (node, type) => node.nodes.find(node => node.type === type); + +/** + * Find a node of the given type + */ + +exports.exceedsLimit = (min, max, step = 1, limit) => { + if (limit === false) return false; + if (!exports.isInteger(min) || !exports.isInteger(max)) return false; + return ((Number(max) - Number(min)) / Number(step)) >= limit; +}; + +/** + * Escape the given node with '\\' before node.value + */ + +exports.escapeNode = (block, n = 0, type) => { + let node = block.nodes[n]; + if (!node) return; + + if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { + if (node.escaped !== true) { + node.value = '\\' + node.value; + node.escaped = true; + } + } +}; + +/** + * Returns true if the given brace node should be enclosed in literal braces + */ + +exports.encloseBrace = node => { + if (node.type !== 'brace') return false; + if ((node.commas >> 0 + node.ranges >> 0) === 0) { + node.invalid = true; + return true; + } + return false; +}; + +/** + * Returns true if a brace node is invalid. + */ + +exports.isInvalidBrace = block => { + if (block.type !== 'brace') return false; + if (block.invalid === true || block.dollar) return true; + if ((block.commas >> 0 + block.ranges >> 0) === 0) { + block.invalid = true; + return true; + } + if (block.open !== true || block.close !== true) { + block.invalid = true; + return true; + } + return false; +}; + +/** + * Returns true if a node is an open or close node + */ + +exports.isOpenOrClose = node => { + if (node.type === 'open' || node.type === 'close') { + return true; + } + return node.open === true || node.close === true; +}; + +/** + * Reduce an array of text nodes. + */ + +exports.reduce = nodes => nodes.reduce((acc, node) => { + if (node.type === 'text') acc.push(node.value); + if (node.type === 'range') node.type = 'text'; + return acc; +}, []); + +/** + * Flatten an array + */ + +exports.flatten = (...args) => { + const result = []; + const flat = arr => { + for (let i = 0; i < arr.length; i++) { + let ele = arr[i]; + Array.isArray(ele) ? flat(ele, result) : ele !== void 0 && result.push(ele); + } + return result; + }; + flat(args); + return result; +}; + +},{}],80:[function(require,module,exports){ +/*! + * fill-range + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +const util = require('util'); +const toRegexRange = require('to-regex-range'); + +const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); + +const transform = toNumber => { + return value => toNumber === true ? Number(value) : String(value); +}; + +const isValidValue = value => { + return typeof value === 'number' || (typeof value === 'string' && value !== ''); +}; + +const isNumber = num => Number.isInteger(+num); + +const zeros = input => { + let value = `${input}`; + let index = -1; + if (value[0] === '-') value = value.slice(1); + if (value === '0') return false; + while (value[++index] === '0'); + return index > 0; +}; + +const stringify = (start, end, options) => { + if (typeof start === 'string' || typeof end === 'string') { + return true; + } + return options.stringify === true; +}; + +const pad = (input, maxLength, toNumber) => { + if (maxLength > 0) { + let dash = input[0] === '-' ? '-' : ''; + if (dash) input = input.slice(1); + input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0')); + } + if (toNumber === false) { + return String(input); + } + return input; +}; + +const toMaxLen = (input, maxLength) => { + let negative = input[0] === '-' ? '-' : ''; + if (negative) { + input = input.slice(1); + maxLength--; + } + while (input.length < maxLength) input = '0' + input; + return negative ? ('-' + input) : input; +}; + +const toSequence = (parts, options) => { + parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); + parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); + + let prefix = options.capture ? '' : '?:'; + let positives = ''; + let negatives = ''; + let result; + + if (parts.positives.length) { + positives = parts.positives.join('|'); + } + + if (parts.negatives.length) { + negatives = `-(${prefix}${parts.negatives.join('|')})`; + } + + if (positives && negatives) { + result = `${positives}|${negatives}`; + } else { + result = positives || negatives; + } + + if (options.wrap) { + return `(${prefix}${result})`; + } + + return result; +}; + +const toRange = (a, b, isNumbers, options) => { + if (isNumbers) { + return toRegexRange(a, b, { wrap: false, ...options }); + } + + let start = String.fromCharCode(a); + if (a === b) return start; + + let stop = String.fromCharCode(b); + return `[${start}-${stop}]`; +}; + +const toRegex = (start, end, options) => { + if (Array.isArray(start)) { + let wrap = options.wrap === true; + let prefix = options.capture ? '' : '?:'; + return wrap ? `(${prefix}${start.join('|')})` : start.join('|'); + } + return toRegexRange(start, end, options); +}; + +const rangeError = (...args) => { + return new RangeError('Invalid range arguments: ' + util.inspect(...args)); +}; + +const invalidRange = (start, end, options) => { + if (options.strictRanges === true) throw rangeError([start, end]); + return []; +}; + +const invalidStep = (step, options) => { + if (options.strictRanges === true) { + throw new TypeError(`Expected step "${step}" to be a number`); + } + return []; +}; + +const fillNumbers = (start, end, step = 1, options = {}) => { + let a = Number(start); + let b = Number(end); + + if (!Number.isInteger(a) || !Number.isInteger(b)) { + if (options.strictRanges === true) throw rangeError([start, end]); + return []; + } + + // fix negative zero + if (a === 0) a = 0; + if (b === 0) b = 0; + + let descending = a > b; + let startString = String(start); + let endString = String(end); + let stepString = String(step); + step = Math.max(Math.abs(step), 1); + + let padded = zeros(startString) || zeros(endString) || zeros(stepString); + let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0; + let toNumber = padded === false && stringify(start, end, options) === false; + let format = options.transform || transform(toNumber); + + if (options.toRegex && step === 1) { + return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options); + } + + let parts = { negatives: [], positives: [] }; + let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num)); + let range = []; + let index = 0; + + while (descending ? a >= b : a <= b) { + if (options.toRegex === true && step > 1) { + push(a); + } else { + range.push(pad(format(a, index), maxLen, toNumber)); + } + a = descending ? a - step : a + step; + index++; + } + + if (options.toRegex === true) { + return step > 1 + ? toSequence(parts, options) + : toRegex(range, null, { wrap: false, ...options }); + } + + return range; +}; + +const fillLetters = (start, end, step = 1, options = {}) => { + if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) { + return invalidRange(start, end, options); + } + + + let format = options.transform || (val => String.fromCharCode(val)); + let a = `${start}`.charCodeAt(0); + let b = `${end}`.charCodeAt(0); + + let descending = a > b; + let min = Math.min(a, b); + let max = Math.max(a, b); + + if (options.toRegex && step === 1) { + return toRange(min, max, false, options); + } + + let range = []; + let index = 0; + + while (descending ? a >= b : a <= b) { + range.push(format(a, index)); + a = descending ? a - step : a + step; + index++; + } + + if (options.toRegex === true) { + return toRegex(range, null, { wrap: false, options }); + } + + return range; +}; + +const fill = (start, end, step, options = {}) => { + if (end == null && isValidValue(start)) { + return [start]; + } + + if (!isValidValue(start) || !isValidValue(end)) { + return invalidRange(start, end, options); + } + + if (typeof step === 'function') { + return fill(start, end, 1, { transform: step }); + } + + if (isObject(step)) { + return fill(start, end, 0, step); + } + + let opts = { ...options }; + if (opts.capture === true) opts.wrap = true; + step = step || opts.step || 1; + + if (!isNumber(step)) { + if (step != null && !isObject(step)) return invalidStep(step, opts); + return fill(start, end, 1, step); + } + + if (isNumber(start) && isNumber(end)) { + return fillNumbers(start, end, step, opts); + } + + return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); +}; + +module.exports = fill; + +},{"to-regex-range":84,"util":523}],81:[function(require,module,exports){ +'use strict'; + +var isGlob = require('is-glob'); +var pathPosixDirname = require('path').posix.dirname; +var isWin32 = require('os').platform() === 'win32'; + +var slash = '/'; +var backslash = /\\/g; +var enclosure = /[\{\[].*[\/]*.*[\}\]]$/; +var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; +var escaped = /\\([\*\?\|\[\]\(\)\{\}])/g; + +module.exports = function globParent(str) { + // flip windows path separators + if (isWin32 && str.indexOf(slash) < 0) { + str = str.replace(backslash, slash); + } + + // special case for strings ending in enclosure containing path separator + if (enclosure.test(str)) { + str += slash; + } + + // preserves full path in case of trailing path separator + str += 'a'; + + // remove path parts that are globby + do { + str = pathPosixDirname(str); + } while (isGlob(str) || globby.test(str)); + + // remove escape chars and return result + return str.replace(escaped, '$1'); +}; + +},{"is-glob":363,"os":301,"path":404}],82:[function(require,module,exports){ +/*! + * is-number + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +module.exports = function(num) { + if (typeof num === 'number') { + return num - num === 0; + } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); + } + return false; +}; + +},{}],83:[function(require,module,exports){ +'use strict'; + +const util = require('util'); +const braces = require('braces'); +const picomatch = require('picomatch'); +const utils = require('picomatch/lib/utils'); +const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); + +/** + * Returns an array of strings that match one or more glob patterns. + * + * ```js + * const mm = require('micromatch'); + * // mm(list, patterns[, options]); + * + * console.log(mm(['a.js', 'a.txt'], ['*.js'])); + * //=> [ 'a.js' ] + * ``` + * @param {String|Array} list List of strings to match. + * @param {String|Array} patterns One or more glob patterns to use for matching. + * @param {Object} options See available [options](#options) + * @return {Array} Returns an array of matches + * @summary false + * @api public + */ + +const micromatch = (list, patterns, options) => { + patterns = [].concat(patterns); + list = [].concat(list); + + let omit = new Set(); + let keep = new Set(); + let items = new Set(); + let negatives = 0; + + let onResult = state => { + items.add(state.output); + if (options && options.onResult) { + options.onResult(state); + } + }; + + for (let i = 0; i < patterns.length; i++) { + let isMatch = picomatch(String(patterns[i]), { ...options, onResult }, true); + let negated = isMatch.state.negated || isMatch.state.negatedExtglob; + if (negated) negatives++; + + for (let item of list) { + let matched = isMatch(item, true); + + let match = negated ? !matched.isMatch : matched.isMatch; + if (!match) continue; + + if (negated) { + omit.add(matched.output); + } else { + omit.delete(matched.output); + keep.add(matched.output); + } + } + } + + let result = negatives === patterns.length ? [...items] : [...keep]; + let matches = result.filter(item => !omit.has(item)); + + if (options && matches.length === 0) { + if (options.failglob === true) { + throw new Error(`No matches found for "${patterns.join(', ')}"`); + } + + if (options.nonull === true || options.nullglob === true) { + return options.unescape ? patterns.map(p => p.replace(/\\/g, '')) : patterns; + } + } + + return matches; +}; + +/** + * Backwards compatibility + */ + +micromatch.match = micromatch; + +/** + * Returns a matcher function from the given glob `pattern` and `options`. + * The returned function takes a string to match as its only argument and returns + * true if the string is a match. + * + * ```js + * const mm = require('micromatch'); + * // mm.matcher(pattern[, options]); + * + * const isMatch = mm.matcher('*.!(*a)'); + * console.log(isMatch('a.a')); //=> false + * console.log(isMatch('a.b')); //=> true + * ``` + * @param {String} `pattern` Glob pattern + * @param {Object} `options` + * @return {Function} Returns a matcher function. + * @api public + */ + +micromatch.matcher = (pattern, options) => picomatch(pattern, options); + +/** + * Returns true if **any** of the given glob `patterns` match the specified `string`. + * + * ```js + * const mm = require('micromatch'); + * // mm.isMatch(string, patterns[, options]); + * + * console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true + * console.log(mm.isMatch('a.a', 'b.*')); //=> false + * ``` + * @param {String} str The string to test. + * @param {String|Array} patterns One or more glob patterns to use for matching. + * @param {Object} [options] See available [options](#options). + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ + +micromatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); + +/** + * Backwards compatibility + */ + +micromatch.any = micromatch.isMatch; + +/** + * Returns a list of strings that _**do not match any**_ of the given `patterns`. + * + * ```js + * const mm = require('micromatch'); + * // mm.not(list, patterns[, options]); + * + * console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a')); + * //=> ['b.b', 'c.c'] + * ``` + * @param {Array} `list` Array of strings to match. + * @param {String|Array} `patterns` One or more glob pattern to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Array} Returns an array of strings that **do not match** the given patterns. + * @api public + */ + +micromatch.not = (list, patterns, options = {}) => { + patterns = [].concat(patterns).map(String); + let result = new Set(); + let items = []; + + let onResult = state => { + if (options.onResult) options.onResult(state); + items.push(state.output); + }; + + let matches = micromatch(list, patterns, { ...options, onResult }); + + for (let item of items) { + if (!matches.includes(item)) { + result.add(item); + } + } + return [...result]; +}; + +/** + * Returns true if the given `string` contains the given pattern. Similar + * to [.isMatch](#isMatch) but the pattern can match any part of the string. + * + * ```js + * var mm = require('micromatch'); + * // mm.contains(string, pattern[, options]); + * + * console.log(mm.contains('aa/bb/cc', '*b')); + * //=> true + * console.log(mm.contains('aa/bb/cc', '*d')); + * //=> false + * ``` + * @param {String} `str` The string to match. + * @param {String|Array} `patterns` Glob pattern to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if the patter matches any part of `str`. + * @api public + */ + +micromatch.contains = (str, pattern, options) => { + if (typeof str !== 'string') { + throw new TypeError(`Expected a string: "${util.inspect(str)}"`); + } + + if (Array.isArray(pattern)) { + return pattern.some(p => micromatch.contains(str, p, options)); + } + + if (typeof pattern === 'string') { + if (isEmptyString(str) || isEmptyString(pattern)) { + return false; + } + + if (str.includes(pattern) || (str.startsWith('./') && str.slice(2).includes(pattern))) { + return true; + } + } + + return micromatch.isMatch(str, pattern, { ...options, contains: true }); +}; + +/** + * Filter the keys of the given object with the given `glob` pattern + * and `options`. Does not attempt to match nested keys. If you need this feature, + * use [glob-object][] instead. + * + * ```js + * const mm = require('micromatch'); + * // mm.matchKeys(object, patterns[, options]); + * + * const obj = { aa: 'a', ab: 'b', ac: 'c' }; + * console.log(mm.matchKeys(obj, '*b')); + * //=> { ab: 'b' } + * ``` + * @param {Object} `object` The object with keys to filter. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Object} Returns an object with only keys that match the given patterns. + * @api public + */ + +micromatch.matchKeys = (obj, patterns, options) => { + if (!utils.isObject(obj)) { + throw new TypeError('Expected the first argument to be an object'); + } + let keys = micromatch(Object.keys(obj), patterns, options); + let res = {}; + for (let key of keys) res[key] = obj[key]; + return res; +}; + +/** + * Returns true if some of the strings in the given `list` match any of the given glob `patterns`. + * + * ```js + * const mm = require('micromatch'); + * // mm.some(list, patterns[, options]); + * + * console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); + * // true + * console.log(mm.some(['foo.js'], ['*.js', '!foo.js'])); + * // false + * ``` + * @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ + +micromatch.some = (list, patterns, options) => { + let items = [].concat(list); + + for (let pattern of [].concat(patterns)) { + let isMatch = picomatch(String(pattern), options); + if (items.some(item => isMatch(item))) { + return true; + } + } + return false; +}; + +/** + * Returns true if every string in the given `list` matches + * any of the given glob `patterns`. + * + * ```js + * const mm = require('micromatch'); + * // mm.every(list, patterns[, options]); + * + * console.log(mm.every('foo.js', ['foo.js'])); + * // true + * console.log(mm.every(['foo.js', 'bar.js'], ['*.js'])); + * // true + * console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); + * // false + * console.log(mm.every(['foo.js'], ['*.js', '!foo.js'])); + * // false + * ``` + * @param {String|Array} `list` The string or array of strings to test. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ + +micromatch.every = (list, patterns, options) => { + let items = [].concat(list); + + for (let pattern of [].concat(patterns)) { + let isMatch = picomatch(String(pattern), options); + if (!items.every(item => isMatch(item))) { + return false; + } + } + return true; +}; + +/** + * Returns true if **all** of the given `patterns` match + * the specified string. + * + * ```js + * const mm = require('micromatch'); + * // mm.all(string, patterns[, options]); + * + * console.log(mm.all('foo.js', ['foo.js'])); + * // true + * + * console.log(mm.all('foo.js', ['*.js', '!foo.js'])); + * // false + * + * console.log(mm.all('foo.js', ['*.js', 'foo.js'])); + * // true + * + * console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js'])); + * // true + * ``` + * @param {String|Array} `str` The string to test. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ + +micromatch.all = (str, patterns, options) => { + if (typeof str !== 'string') { + throw new TypeError(`Expected a string: "${util.inspect(str)}"`); + } + + return [].concat(patterns).every(p => picomatch(p, options)(str)); +}; + +/** + * Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match. + * + * ```js + * const mm = require('micromatch'); + * // mm.capture(pattern, string[, options]); + * + * console.log(mm.capture('test/*.js', 'test/foo.js')); + * //=> ['foo'] + * console.log(mm.capture('test/*.js', 'foo/bar.css')); + * //=> null + * ``` + * @param {String} `glob` Glob pattern to use for matching. + * @param {String} `input` String to match + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns an array of captures if the input matches the glob pattern, otherwise `null`. + * @api public + */ + +micromatch.capture = (glob, input, options) => { + let posix = utils.isWindows(options); + let regex = picomatch.makeRe(String(glob), { ...options, capture: true }); + let match = regex.exec(posix ? utils.toPosixSlashes(input) : input); + + if (match) { + return match.slice(1).map(v => v === void 0 ? '' : v); + } +}; + +/** + * Create a regular expression from the given glob `pattern`. + * + * ```js + * const mm = require('micromatch'); + * // mm.makeRe(pattern[, options]); + * + * console.log(mm.makeRe('*.js')); + * //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/ + * ``` + * @param {String} `pattern` A glob pattern to convert to regex. + * @param {Object} `options` + * @return {RegExp} Returns a regex created from the given pattern. + * @api public + */ + +micromatch.makeRe = (...args) => picomatch.makeRe(...args); + +/** + * Scan a glob pattern to separate the pattern into segments. Used + * by the [split](#split) method. + * + * ```js + * const mm = require('micromatch'); + * const state = mm.scan(pattern[, options]); + * ``` + * @param {String} `pattern` + * @param {Object} `options` + * @return {Object} Returns an object with + * @api public + */ + +micromatch.scan = (...args) => picomatch.scan(...args); + +/** + * Parse a glob pattern to create the source string for a regular + * expression. + * + * ```js + * const mm = require('micromatch'); + * const state = mm(pattern[, options]); + * ``` + * @param {String} `glob` + * @param {Object} `options` + * @return {Object} Returns an object with useful properties and output to be used as regex source string. + * @api public + */ + +micromatch.parse = (patterns, options) => { + let res = []; + for (let pattern of [].concat(patterns || [])) { + for (let str of braces(String(pattern), options)) { + res.push(picomatch.parse(str, options)); + } + } + return res; +}; + +/** + * Process the given brace `pattern`. + * + * ```js + * const { braces } = require('micromatch'); + * console.log(braces('foo/{a,b,c}/bar')); + * //=> [ 'foo/(a|b|c)/bar' ] + * + * console.log(braces('foo/{a,b,c}/bar', { expand: true })); + * //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ] + * ``` + * @param {String} `pattern` String with brace pattern to process. + * @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options. + * @return {Array} + * @api public + */ + +micromatch.braces = (pattern, options) => { + if (typeof pattern !== 'string') throw new TypeError('Expected a string'); + if ((options && options.nobrace === true) || !/\{.*\}/.test(pattern)) { + return [pattern]; + } + return braces(pattern, options); +}; + +/** + * Expand braces + */ + +micromatch.braceExpand = (pattern, options) => { + if (typeof pattern !== 'string') throw new TypeError('Expected a string'); + return micromatch.braces(pattern, { ...options, expand: true }); +}; + +/** + * Expose micromatch + */ + +module.exports = micromatch; + +},{"braces":73,"picomatch":407,"picomatch/lib/utils":412,"util":523}],84:[function(require,module,exports){ +/*! + * to-regex-range + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +const isNumber = require('is-number'); + +const toRegexRange = (min, max, options) => { + if (isNumber(min) === false) { + throw new TypeError('toRegexRange: expected the first argument to be a number'); + } + + if (max === void 0 || min === max) { + return String(min); + } + + if (isNumber(max) === false) { + throw new TypeError('toRegexRange: expected the second argument to be a number.'); + } + + let opts = { relaxZeros: true, ...options }; + if (typeof opts.strictZeros === 'boolean') { + opts.relaxZeros = opts.strictZeros === false; + } + + let relax = String(opts.relaxZeros); + let shorthand = String(opts.shorthand); + let capture = String(opts.capture); + let wrap = String(opts.wrap); + let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; + + if (toRegexRange.cache.hasOwnProperty(cacheKey)) { + return toRegexRange.cache[cacheKey].result; + } + + let a = Math.min(min, max); + let b = Math.max(min, max); + + if (Math.abs(a - b) === 1) { + let result = min + '|' + max; + if (opts.capture) { + return `(${result})`; + } + if (opts.wrap === false) { + return result; + } + return `(?:${result})`; + } + + let isPadded = hasPadding(min) || hasPadding(max); + let state = { min, max, a, b }; + let positives = []; + let negatives = []; + + if (isPadded) { + state.isPadded = isPadded; + state.maxLen = String(state.max).length; + } + + if (a < 0) { + let newMin = b < 0 ? Math.abs(b) : 1; + negatives = splitToPatterns(newMin, Math.abs(a), state, opts); + a = state.a = 0; + } + + if (b >= 0) { + positives = splitToPatterns(a, b, state, opts); + } + + state.negatives = negatives; + state.positives = positives; + state.result = collatePatterns(negatives, positives, opts); + + if (opts.capture === true) { + state.result = `(${state.result})`; + } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { + state.result = `(?:${state.result})`; + } + + toRegexRange.cache[cacheKey] = state; + return state.result; +}; + +function collatePatterns(neg, pos, options) { + let onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; + let onlyPositive = filterPatterns(pos, neg, '', false, options) || []; + let intersected = filterPatterns(neg, pos, '-?', true, options) || []; + let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); + return subpatterns.join('|'); +} + +function splitToRanges(min, max) { + let nines = 1; + let zeros = 1; + + let stop = countNines(min, nines); + let stops = new Set([max]); + + while (min <= stop && stop <= max) { + stops.add(stop); + nines += 1; + stop = countNines(min, nines); + } + + stop = countZeros(max + 1, zeros) - 1; + + while (min < stop && stop <= max) { + stops.add(stop); + zeros += 1; + stop = countZeros(max + 1, zeros) - 1; + } + + stops = [...stops]; + stops.sort(compare); + return stops; +} + +/** + * Convert a range to a regex pattern + * @param {Number} `start` + * @param {Number} `stop` + * @return {String} + */ + +function rangeToPattern(start, stop, options) { + if (start === stop) { + return { pattern: start, count: [], digits: 0 }; + } + + let zipped = zip(start, stop); + let digits = zipped.length; + let pattern = ''; + let count = 0; + + for (let i = 0; i < digits; i++) { + let [startDigit, stopDigit] = zipped[i]; + + if (startDigit === stopDigit) { + pattern += startDigit; + + } else if (startDigit !== '0' || stopDigit !== '9') { + pattern += toCharacterClass(startDigit, stopDigit, options); + + } else { + count++; + } + } + + if (count) { + pattern += options.shorthand === true ? '\\d' : '[0-9]'; + } + + return { pattern, count: [count], digits }; +} + +function splitToPatterns(min, max, tok, options) { + let ranges = splitToRanges(min, max); + let tokens = []; + let start = min; + let prev; + + for (let i = 0; i < ranges.length; i++) { + let max = ranges[i]; + let obj = rangeToPattern(String(start), String(max), options); + let zeros = ''; + + if (!tok.isPadded && prev && prev.pattern === obj.pattern) { + if (prev.count.length > 1) { + prev.count.pop(); + } + + prev.count.push(obj.count[0]); + prev.string = prev.pattern + toQuantifier(prev.count); + start = max + 1; + continue; + } + + if (tok.isPadded) { + zeros = padZeros(max, tok, options); + } + + obj.string = zeros + obj.pattern + toQuantifier(obj.count); + tokens.push(obj); + start = max + 1; + prev = obj; + } + + return tokens; +} + +function filterPatterns(arr, comparison, prefix, intersection, options) { + let result = []; + + for (let ele of arr) { + let { string } = ele; + + // only push if _both_ are negative... + if (!intersection && !contains(comparison, 'string', string)) { + result.push(prefix + string); + } + + // or _both_ are positive + if (intersection && contains(comparison, 'string', string)) { + result.push(prefix + string); + } + } + return result; +} + +/** + * Zip strings + */ + +function zip(a, b) { + let arr = []; + for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); + return arr; +} + +function compare(a, b) { + return a > b ? 1 : b > a ? -1 : 0; +} + +function contains(arr, key, val) { + return arr.some(ele => ele[key] === val); +} + +function countNines(min, len) { + return Number(String(min).slice(0, -len) + '9'.repeat(len)); +} + +function countZeros(integer, zeros) { + return integer - (integer % Math.pow(10, zeros)); +} + +function toQuantifier(digits) { + let [start = 0, stop = ''] = digits; + if (stop || start > 1) { + return `{${start + (stop ? ',' + stop : '')}}`; + } + return ''; +} + +function toCharacterClass(a, b, options) { + return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; +} + +function hasPadding(str) { + return /^-?(0+)\d/.test(str); +} + +function padZeros(value, tok, options) { + if (!tok.isPadded) { + return value; + } + + let diff = Math.abs(tok.maxLen - String(value).length); + let relax = options.relaxZeros !== false; + + switch (diff) { + case 0: + return ''; + case 1: + return relax ? '0?' : '0'; + case 2: + return relax ? '0{0,2}' : '00'; + default: { + return relax ? `0{0,${diff}}` : `0{${diff}}`; + } + } +} + +/** + * Cache + */ + +toRegexRange.cache = {}; +toRegexRange.clearCache = () => (toRegexRange.cache = {}); + +/** + * Expose `toRegexRange` + */ + +module.exports = toRegexRange; + +},{"is-number":82}],85:[function(require,module,exports){ +"use strict"; +const taskManager = require("./managers/tasks"); +const async_1 = require("./providers/async"); +const stream_1 = require("./providers/stream"); +const sync_1 = require("./providers/sync"); +const settings_1 = require("./settings"); +const utils = require("./utils/index"); +function FastGlob(source, options) { + try { + assertPatternsInput(source); + } + catch (error) { + return Promise.reject(error); + } + const works = getWorks(source, async_1.default, options); + return Promise.all(works).then(utils.array.flatten); +} +(function (FastGlob) { + function sync(source, options) { + assertPatternsInput(source); + const works = getWorks(source, sync_1.default, options); + return utils.array.flatten(works); + } + FastGlob.sync = sync; + function stream(source, options) { + assertPatternsInput(source); + const works = getWorks(source, stream_1.default, options); + /** + * The stream returned by the provider cannot work with an asynchronous iterator. + * To support asynchronous iterators, regardless of the number of tasks, we always multiplex streams. + * This affects performance (+25%). I don't see best solution right now. + */ + return utils.stream.merge(works); + } + FastGlob.stream = stream; + function generateTasks(source, options) { + assertPatternsInput(source); + const patterns = [].concat(source); + const settings = new settings_1.default(options); + return taskManager.generate(patterns, settings); + } + FastGlob.generateTasks = generateTasks; +})(FastGlob || (FastGlob = {})); +function getWorks(source, _Provider, options) { + const patterns = [].concat(source); + const settings = new settings_1.default(options); + const tasks = taskManager.generate(patterns, settings); + const provider = new _Provider(settings); + return tasks.map(provider.read, provider); +} +function assertPatternsInput(source) { + if ([].concat(source).every(isString)) { + return; + } + throw new TypeError('Patterns must be a string or an array of strings'); +} +function isString(source) { + /* tslint:disable-next-line strict-type-predicates */ + return typeof source === 'string'; +} +module.exports = FastGlob; + +},{"./managers/tasks":86,"./providers/async":87,"./providers/stream":92,"./providers/sync":93,"./settings":98,"./utils/index":102}],86:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = require("../utils/index"); +function generate(patterns, settings) { + const positivePatterns = getPositivePatterns(patterns); + const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); + /** + * When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check + * filepath directly (without read directory). + */ + const staticPatterns = !settings.caseSensitiveMatch ? [] : positivePatterns.filter(utils.pattern.isStaticPattern); + const dynamicPatterns = !settings.caseSensitiveMatch ? positivePatterns : positivePatterns.filter(utils.pattern.isDynamicPattern); + const staticTasks = convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false); + const dynamicTasks = convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true); + return staticTasks.concat(dynamicTasks); +} +exports.generate = generate; +function convertPatternsToTasks(positive, negative, dynamic) { + const positivePatternsGroup = groupPatternsByBaseDirectory(positive); + // When we have a global group – there is no reason to divide the patterns into independent tasks. + // In this case, the global task covers the rest. + if ('.' in positivePatternsGroup) { + const task = convertPatternGroupToTask('.', positive, negative, dynamic); + return [task]; + } + return convertPatternGroupsToTasks(positivePatternsGroup, negative, dynamic); +} +exports.convertPatternsToTasks = convertPatternsToTasks; +function getPositivePatterns(patterns) { + return utils.pattern.getPositivePatterns(patterns); +} +exports.getPositivePatterns = getPositivePatterns; +function getNegativePatternsAsPositive(patterns, ignore) { + const negative = utils.pattern.getNegativePatterns(patterns).concat(ignore); + const positive = negative.map(utils.pattern.convertToPositivePattern); + return positive; +} +exports.getNegativePatternsAsPositive = getNegativePatternsAsPositive; +function groupPatternsByBaseDirectory(patterns) { + return patterns.reduce((collection, pattern) => { + const base = utils.pattern.getBaseDirectory(pattern); + if (base in collection) { + collection[base].push(pattern); + } + else { + collection[base] = [pattern]; + } + return collection; + }, {}); +} +exports.groupPatternsByBaseDirectory = groupPatternsByBaseDirectory; +function convertPatternGroupsToTasks(positive, negative, dynamic) { + return Object.keys(positive).map((base) => { + return convertPatternGroupToTask(base, positive[base], negative, dynamic); + }); +} +exports.convertPatternGroupsToTasks = convertPatternGroupsToTasks; +function convertPatternGroupToTask(base, positive, negative, dynamic) { + return { + dynamic, + positive, + negative, + base, + patterns: [].concat(positive, negative.map(utils.pattern.convertToNegativePattern)) + }; +} +exports.convertPatternGroupToTask = convertPatternGroupToTask; + +},{"../utils/index":102}],87:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = require("../readers/stream"); +const provider_1 = require("./provider"); +class ProviderAsync extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new stream_1.default(this._settings); + } + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const entries = []; + return new Promise((resolve, reject) => { + const stream = this.api(root, task, options); + stream.once('error', reject); + stream.on('data', (entry) => entries.push(options.transform(entry))); + stream.once('end', () => resolve(entries)); + }); + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); + } +} +exports.default = ProviderAsync; + +},{"../readers/stream":96,"./provider":91}],88:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = require("../../utils/index"); +class DeepFilter { + constructor(_settings, _micromatchOptions) { + this._settings = _settings; + this._micromatchOptions = _micromatchOptions; + } + getFilter(basePath, positive, negative) { + const maxPatternDepth = this._getMaxPatternDepth(positive); + const negativeRe = this._getNegativePatternsRe(negative); + return (entry) => this._filter(basePath, entry, negativeRe, maxPatternDepth); + } + _getMaxPatternDepth(patterns) { + const globstar = patterns.some(utils.pattern.hasGlobStar); + return globstar ? Infinity : utils.pattern.getMaxNaivePatternsDepth(patterns); + } + _getNegativePatternsRe(patterns) { + const affectDepthOfReadingPatterns = patterns.filter(utils.pattern.isAffectDepthOfReadingPattern); + return utils.pattern.convertPatternsToRe(affectDepthOfReadingPatterns, this._micromatchOptions); + } + _filter(basePath, entry, negativeRe, maxPatternDepth) { + const depth = this._getEntryDepth(basePath, entry.path); + if (this._isSkippedByDeep(depth)) { + return false; + } + if (this._isSkippedByMaxPatternDepth(depth, maxPatternDepth)) { + return false; + } + if (this._isSkippedSymbolicLink(entry)) { + return false; + } + if (this._isSkippedDotDirectory(entry)) { + return false; + } + return this._isSkippedByNegativePatterns(entry, negativeRe); + } + _getEntryDepth(basePath, entryPath) { + const basePathDepth = basePath.split('/').length; + const entryPathDepth = entryPath.split('/').length; + return entryPathDepth - (basePath === '' ? 0 : basePathDepth); + } + _isSkippedByDeep(entryDepth) { + return entryDepth >= this._settings.deep; + } + _isSkippedByMaxPatternDepth(entryDepth, maxPatternDepth) { + return !this._settings.baseNameMatch && maxPatternDepth !== Infinity && entryDepth > maxPatternDepth; + } + _isSkippedSymbolicLink(entry) { + return !this._settings.followSymbolicLinks && entry.dirent.isSymbolicLink(); + } + _isSkippedDotDirectory(entry) { + return !this._settings.dot && entry.name.startsWith('.'); + } + _isSkippedByNegativePatterns(entry, negativeRe) { + return !utils.pattern.matchAny(entry.path, negativeRe); + } +} +exports.default = DeepFilter; + +},{"../../utils/index":102}],89:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = require("../../utils/index"); +class EntryFilter { + constructor(_settings, _micromatchOptions) { + this._settings = _settings; + this._micromatchOptions = _micromatchOptions; + this.index = new Map(); + } + getFilter(positive, negative) { + const positiveRe = utils.pattern.convertPatternsToRe(positive, this._micromatchOptions); + const negativeRe = utils.pattern.convertPatternsToRe(negative, this._micromatchOptions); + return (entry) => this._filter(entry, positiveRe, negativeRe); + } + _filter(entry, positiveRe, negativeRe) { + if (this._settings.unique) { + if (this._isDuplicateEntry(entry)) { + return false; + } + this._createIndexRecord(entry); + } + if (this._onlyFileFilter(entry) || this._onlyDirectoryFilter(entry)) { + return false; + } + if (this._isSkippedByAbsoluteNegativePatterns(entry, negativeRe)) { + return false; + } + const filepath = this._settings.baseNameMatch ? entry.name : entry.path; + return this._isMatchToPatterns(filepath, positiveRe) && !this._isMatchToPatterns(entry.path, negativeRe); + } + _isDuplicateEntry(entry) { + return this.index.has(entry.path); + } + _createIndexRecord(entry) { + this.index.set(entry.path, undefined); + } + _onlyFileFilter(entry) { + return this._settings.onlyFiles && !entry.dirent.isFile(); + } + _onlyDirectoryFilter(entry) { + return this._settings.onlyDirectories && !entry.dirent.isDirectory(); + } + _isSkippedByAbsoluteNegativePatterns(entry, negativeRe) { + if (!this._settings.absolute) { + return false; + } + const fullpath = utils.path.makeAbsolute(this._settings.cwd, entry.path); + return this._isMatchToPatterns(fullpath, negativeRe); + } + _isMatchToPatterns(filepath, patternsRe) { + return utils.pattern.matchAny(filepath, patternsRe); + } +} +exports.default = EntryFilter; + +},{"../../utils/index":102}],90:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = require("../../utils/index"); +class ErrorFilter { + constructor(_settings) { + this._settings = _settings; + } + getFilter() { + return (error) => this._isNonFatalError(error); + } + _isNonFatalError(error) { + return utils.errno.isEnoentCodeError(error) || this._settings.suppressErrors; + } +} +exports.default = ErrorFilter; + +},{"../../utils/index":102}],91:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const path = require("path"); +const deep_1 = require("./filters/deep"); +const entry_1 = require("./filters/entry"); +const error_1 = require("./filters/error"); +const entry_2 = require("./transformers/entry"); +class Provider { + constructor(_settings) { + this._settings = _settings; + this.errorFilter = new error_1.default(this._settings); + this.entryFilter = new entry_1.default(this._settings, this._getMicromatchOptions()); + this.deepFilter = new deep_1.default(this._settings, this._getMicromatchOptions()); + this.entryTransformer = new entry_2.default(this._settings); + } + _getRootDirectory(task) { + return path.resolve(this._settings.cwd, task.base); + } + _getReaderOptions(task) { + const basePath = task.base === '.' ? '' : task.base; + return { + basePath, + pathSegmentSeparator: '/', + concurrency: this._settings.concurrency, + deepFilter: this.deepFilter.getFilter(basePath, task.positive, task.negative), + entryFilter: this.entryFilter.getFilter(task.positive, task.negative), + errorFilter: this.errorFilter.getFilter(), + followSymbolicLinks: this._settings.followSymbolicLinks, + fs: this._settings.fs, + stats: this._settings.stats, + throwErrorOnBrokenSymbolicLink: this._settings.throwErrorOnBrokenSymbolicLink, + transform: this.entryTransformer.getTransformer() + }; + } + _getMicromatchOptions() { + return { + dot: this._settings.dot, + matchBase: this._settings.baseNameMatch, + nobrace: !this._settings.braceExpansion, + nocase: !this._settings.caseSensitiveMatch, + noext: !this._settings.extglob, + noglobstar: !this._settings.globstar, + posix: true + }; + } +} +exports.default = Provider; + +},{"./filters/deep":88,"./filters/entry":89,"./filters/error":90,"./transformers/entry":94,"path":404}],92:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = require("stream"); +const stream_2 = require("../readers/stream"); +const provider_1 = require("./provider"); +class ProviderStream extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new stream_2.default(this._settings); + } + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const source = this.api(root, task, options); + const dest = new stream_1.Readable({ objectMode: true, read: () => { } }); + source + .once('error', (error) => dest.emit('error', error)) + .on('data', (entry) => dest.emit('data', options.transform(entry))) + .once('end', () => dest.emit('end')); + return dest; + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); + } +} +exports.default = ProviderStream; + +},{"../readers/stream":96,"./provider":91,"stream":503}],93:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const sync_1 = require("../readers/sync"); +const provider_1 = require("./provider"); +class ProviderSync extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new sync_1.default(this._settings); + } + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const entries = this.api(root, task, options); + return entries.map(options.transform); + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); + } +} +exports.default = ProviderSync; + +},{"../readers/sync":97,"./provider":91}],94:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = require("../../utils/index"); +class EntryTransformer { + constructor(_settings) { + this._settings = _settings; + } + getTransformer() { + return (entry) => this._transform(entry); + } + _transform(entry) { + let filepath = entry.path; + if (this._settings.absolute) { + filepath = utils.path.makeAbsolute(this._settings.cwd, filepath); + filepath = utils.path.unixify(filepath); + } + if (this._settings.markDirectories && entry.dirent.isDirectory()) { + filepath += '/'; + } + if (!this._settings.objectMode) { + return filepath; + } + return Object.assign({}, entry, { path: filepath }); + } +} +exports.default = EntryTransformer; + +},{"../../utils/index":102}],95:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const path = require("path"); +const fsStat = require("@nodelib/fs.stat"); +const utils = require("../utils/index"); +class Reader { + constructor(_settings) { + this._settings = _settings; + this._fsStatSettings = new fsStat.Settings({ + followSymbolicLink: this._settings.followSymbolicLinks, + fs: this._settings.fs, + throwErrorOnBrokenSymbolicLink: this._settings.followSymbolicLinks + }); + } + _getFullEntryPath(filepath) { + return path.resolve(this._settings.cwd, filepath); + } + _makeEntry(stats, pattern) { + const entry = { + name: pattern, + path: pattern, + dirent: utils.fs.createDirentFromStats(pattern, stats) + }; + if (this._settings.stats) { + entry.stats = stats; + } + return entry; + } + _isFatalError(error) { + return !utils.errno.isEnoentCodeError(error) && !this._settings.suppressErrors; + } +} +exports.default = Reader; + +},{"../utils/index":102,"@nodelib/fs.stat":10,"path":404}],96:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = require("stream"); +const fsStat = require("@nodelib/fs.stat"); +const fsWalk = require("@nodelib/fs.walk"); +const reader_1 = require("./reader"); +class ReaderStream extends reader_1.default { + constructor() { + super(...arguments); + this._walkStream = fsWalk.walkStream; + this._stat = fsStat.stat; + } + dynamic(root, options) { + return this._walkStream(root, options); + } + static(patterns, options) { + const filepaths = patterns.map(this._getFullEntryPath, this); + const stream = new stream_1.PassThrough({ objectMode: true }); + stream._write = (index, _enc, done) => { + return this._getEntry(filepaths[index], patterns[index], options) + .then((entry) => { + if (entry !== null && options.entryFilter(entry)) { + stream.push(entry); + } + if (index === filepaths.length - 1) { + stream.end(); + } + done(); + }) + .catch(done); + }; + for (let i = 0; i < filepaths.length; i++) { + stream.write(i); + } + return stream; + } + _getEntry(filepath, pattern, options) { + return this._getStat(filepath) + .then((stats) => this._makeEntry(stats, pattern)) + .catch((error) => { + if (options.errorFilter(error)) { + return null; + } + throw error; + }); + } + _getStat(filepath) { + return new Promise((resolve, reject) => { + this._stat(filepath, this._fsStatSettings, (error, stats) => { + error ? reject(error) : resolve(stats); + }); + }); + } +} +exports.default = ReaderStream; + +},{"./reader":95,"@nodelib/fs.stat":10,"@nodelib/fs.walk":14,"stream":503}],97:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const fsStat = require("@nodelib/fs.stat"); +const fsWalk = require("@nodelib/fs.walk"); +const reader_1 = require("./reader"); +class ReaderSync extends reader_1.default { + constructor() { + super(...arguments); + this._walkSync = fsWalk.walkSync; + this._statSync = fsStat.statSync; + } + dynamic(root, options) { + return this._walkSync(root, options); + } + static(patterns, options) { + const entries = []; + for (const pattern of patterns) { + const filepath = this._getFullEntryPath(pattern); + const entry = this._getEntry(filepath, pattern, options); + if (entry === null || !options.entryFilter(entry)) { + continue; + } + entries.push(entry); + } + return entries; + } + _getEntry(filepath, pattern, options) { + try { + const stats = this._getStat(filepath); + return this._makeEntry(stats, pattern); + } + catch (error) { + if (options.errorFilter(error)) { + return null; + } + throw error; + } + } + _getStat(filepath) { + return this._statSync(filepath, this._fsStatSettings); + } +} +exports.default = ReaderSync; + +},{"./reader":95,"@nodelib/fs.stat":10,"@nodelib/fs.walk":14}],98:[function(require,module,exports){ +(function (process){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = require("fs"); +const os = require("os"); +const CPU_COUNT = os.cpus().length; +exports.DEFAULT_FILE_SYSTEM_ADAPTER = { + lstat: fs.lstat, + lstatSync: fs.lstatSync, + stat: fs.stat, + statSync: fs.statSync, + readdir: fs.readdir, + readdirSync: fs.readdirSync +}; +// tslint:enable no-redundant-jsdoc +class Settings { + constructor(_options = {}) { + this._options = _options; + this.absolute = this._getValue(this._options.absolute, false); + this.baseNameMatch = this._getValue(this._options.baseNameMatch, false); + this.braceExpansion = this._getValue(this._options.braceExpansion, true); + this.caseSensitiveMatch = this._getValue(this._options.caseSensitiveMatch, true); + this.concurrency = this._getValue(this._options.concurrency, CPU_COUNT); + this.cwd = this._getValue(this._options.cwd, process.cwd()); + this.deep = this._getValue(this._options.deep, Infinity); + this.dot = this._getValue(this._options.dot, false); + this.extglob = this._getValue(this._options.extglob, true); + this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, true); + this.fs = this._getFileSystemMethods(this._options.fs); + this.globstar = this._getValue(this._options.globstar, true); + this.ignore = this._getValue(this._options.ignore, []); + this.markDirectories = this._getValue(this._options.markDirectories, false); + this.objectMode = this._getValue(this._options.objectMode, false); + this.onlyDirectories = this._getValue(this._options.onlyDirectories, false); + this.onlyFiles = this._getValue(this._options.onlyFiles, true); + this.stats = this._getValue(this._options.stats, false); + this.suppressErrors = this._getValue(this._options.suppressErrors, false); + this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, false); + this.unique = this._getValue(this._options.unique, true); + if (this.onlyDirectories) { + this.onlyFiles = false; + } + if (this.stats) { + this.objectMode = true; + } + } + _getValue(option, value) { + return option === undefined ? value : option; + } + _getFileSystemMethods(methods = {}) { + return Object.assign({}, exports.DEFAULT_FILE_SYSTEM_ADAPTER, methods); + } +} +exports.default = Settings; + +}).call(this,require('_process')) +},{"_process":437,"fs":298,"os":301}],99:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function flatten(items) { + return items.reduce((collection, item) => [].concat(collection, item), []); +} +exports.flatten = flatten; + +},{}],100:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function isEnoentCodeError(error) { + return error.code === 'ENOENT'; +} +exports.isEnoentCodeError = isEnoentCodeError; + +},{}],101:[function(require,module,exports){ +arguments[4][7][0].apply(exports,arguments) +},{"dup":7}],102:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const array = require("./array"); +exports.array = array; +const errno = require("./errno"); +exports.errno = errno; +const fs = require("./fs"); +exports.fs = fs; +const path = require("./path"); +exports.path = path; +const pattern = require("./pattern"); +exports.pattern = pattern; +const stream = require("./stream"); +exports.stream = stream; + +},{"./array":99,"./errno":100,"./fs":101,"./path":103,"./pattern":104,"./stream":105}],103:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const path = require("path"); +/** + * Designed to work only with simple paths: `dir\\file`. + */ +function unixify(filepath) { + return filepath.replace(/\\/g, '/'); +} +exports.unixify = unixify; +function makeAbsolute(cwd, filepath) { + return path.resolve(cwd, filepath); +} +exports.makeAbsolute = makeAbsolute; + +},{"path":404}],104:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const path = require("path"); +const globParent = require("glob-parent"); +const isGlob = require("is-glob"); +const micromatch = require("micromatch"); +const GLOBSTAR = '**'; +function isStaticPattern(pattern) { + return !isDynamicPattern(pattern); +} +exports.isStaticPattern = isStaticPattern; +function isDynamicPattern(pattern) { + return isGlob(pattern, { strict: false }); +} +exports.isDynamicPattern = isDynamicPattern; +function convertToPositivePattern(pattern) { + return isNegativePattern(pattern) ? pattern.slice(1) : pattern; +} +exports.convertToPositivePattern = convertToPositivePattern; +function convertToNegativePattern(pattern) { + return '!' + pattern; +} +exports.convertToNegativePattern = convertToNegativePattern; +function isNegativePattern(pattern) { + return pattern.startsWith('!') && pattern[1] !== '('; +} +exports.isNegativePattern = isNegativePattern; +function isPositivePattern(pattern) { + return !isNegativePattern(pattern); +} +exports.isPositivePattern = isPositivePattern; +function getNegativePatterns(patterns) { + return patterns.filter(isNegativePattern); +} +exports.getNegativePatterns = getNegativePatterns; +function getPositivePatterns(patterns) { + return patterns.filter(isPositivePattern); +} +exports.getPositivePatterns = getPositivePatterns; +function getBaseDirectory(pattern) { + return globParent(pattern); +} +exports.getBaseDirectory = getBaseDirectory; +function hasGlobStar(pattern) { + return pattern.indexOf(GLOBSTAR) !== -1; +} +exports.hasGlobStar = hasGlobStar; +function endsWithSlashGlobStar(pattern) { + return pattern.endsWith('/' + GLOBSTAR); +} +exports.endsWithSlashGlobStar = endsWithSlashGlobStar; +function isAffectDepthOfReadingPattern(pattern) { + const basename = path.basename(pattern); + return endsWithSlashGlobStar(pattern) || isStaticPattern(basename); +} +exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern; +function getNaiveDepth(pattern) { + const base = getBaseDirectory(pattern); + const patternDepth = pattern.split('/').length; + const patternBaseDepth = base.split('/').length; + /** + * This is a hack for pattern that has no base directory. + * + * This is related to the `*\something\*` pattern. + */ + if (base === '.') { + return patternDepth - patternBaseDepth; + } + return patternDepth - patternBaseDepth - 1; +} +exports.getNaiveDepth = getNaiveDepth; +function getMaxNaivePatternsDepth(patterns) { + return patterns.reduce((max, pattern) => { + const depth = getNaiveDepth(pattern); + return depth > max ? depth : max; + }, 0); +} +exports.getMaxNaivePatternsDepth = getMaxNaivePatternsDepth; +function makeRe(pattern, options) { + return micromatch.makeRe(pattern, options); +} +exports.makeRe = makeRe; +function convertPatternsToRe(patterns, options) { + return patterns.map((pattern) => makeRe(pattern, options)); +} +exports.convertPatternsToRe = convertPatternsToRe; +function matchAny(entry, patternsRe) { + const filepath = entry.replace(/^\.[\\\/]/, ''); + return patternsRe.some((patternRe) => patternRe.test(filepath)); +} +exports.matchAny = matchAny; + +},{"glob-parent":81,"is-glob":363,"micromatch":83,"path":404}],105:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const merge2 = require("merge2"); +function merge(streams) { + const mergedStream = merge2(streams); + streams.forEach((stream) => { + stream.once('error', (err) => mergedStream.emit('error', err)); + }); + return mergedStream; +} +exports.merge = merge; + +},{"merge2":381}],106:[function(require,module,exports){ +'use strict' + +var reusify = require('reusify') + +function fastqueue (context, worker, concurrency) { + if (typeof context === 'function') { + concurrency = worker + worker = context + context = null + } + + var cache = reusify(Task) + var queueHead = null + var queueTail = null + var _running = 0 + + var self = { + push: push, + drain: noop, + saturated: noop, + pause: pause, + paused: false, + concurrency: concurrency, + running: running, + resume: resume, + idle: idle, + length: length, + unshift: unshift, + empty: noop, + kill: kill, + killAndDrain: killAndDrain + } + + return self + + function running () { + return _running + } + + function pause () { + self.paused = true + } + + function length () { + var current = queueHead + var counter = 0 + + while (current) { + current = current.next + counter++ + } + + return counter + } + + function resume () { + if (!self.paused) return + self.paused = false + for (var i = 0; i < self.concurrency; i++) { + _running++ + release() + } + } + + function idle () { + return _running === 0 && self.length() === 0 + } + + function push (value, done) { + var current = cache.get() + + current.context = context + current.release = release + current.value = value + current.callback = done || noop + + if (_running === self.concurrency || self.paused) { + if (queueTail) { + queueTail.next = current + queueTail = current + } else { + queueHead = current + queueTail = current + self.saturated() + } + } else { + _running++ + worker.call(context, current.value, current.worked) + } + } + + function unshift (value, done) { + var current = cache.get() + + current.context = context + current.release = release + current.value = value + current.callback = done || noop + + if (_running === self.concurrency || self.paused) { + if (queueHead) { + current.next = queueHead + queueHead = current + } else { + queueHead = current + queueTail = current + self.saturated() + } + } else { + _running++ + worker.call(context, current.value, current.worked) + } + } + + function release (holder) { + if (holder) { + cache.release(holder) + } + var next = queueHead + if (next) { + if (!self.paused) { + if (queueTail === queueHead) { + queueTail = null + } + queueHead = next.next + next.next = null + worker.call(context, next.value, next.worked) + if (queueTail === null) { + self.empty() + } + } else { + _running-- + } + } else if (--_running === 0) { + self.drain() + } + } + + function kill () { + queueHead = null + queueTail = null + self.drain = noop + } + + function killAndDrain () { + queueHead = null + queueTail = null + self.drain() + self.drain = noop + } +} + +function noop () {} + +function Task () { + this.value = null + this.callback = noop + this.next = null + this.release = noop + this.context = null + + var self = this + + this.worked = function worked (err, result) { + var callback = self.callback + self.value = null + self.callback = noop + callback.call(self.context, err, result) + self.release(self) + } +} + +module.exports = fastqueue + +},{"reusify":489}],107:[function(require,module,exports){ +var util = require('utils-extend'); +/** + * @description + * @example + * `**\/*` match all files + * `*.js` only match current dir files + * '**\/*.js' match all js files + * 'path/*.js' match js files in path + * '!*.js' exclude js files + */ +function fileMatch(filter, ignore) { + if (filter === null) { + return function() { + return true; + }; + } else if (filter === '' || (util.isArray(filter) && !filter.length)) { + return function() { + return false; + }; + } + + if (util.isString(filter)) { + filter = [filter]; + } + + var match = []; + var negate = []; + var isIgnore = ignore ? 'i' : ''; + + filter.forEach(function(item) { + var isNegate = item.indexOf('!') === 0; + item = item + .replace(/^!/, '') + .replace(/\*(?![\/*])/, '[^/]*?') + .replace('**\/', '([^/]+\/)*') + .replace(/\{([^\}]+)\}/g, function($1, $2) { + var collection = $2.split(','); + var length = collection.length; + var result = '(?:'; + + collection.forEach(function(item, index) { + result += '(' + item.trim() + ')'; + + if (index + 1 !== length) { + result += '|'; + } + }); + + result += ')'; + + return result; + }) + .replace(/([\/\.])/g, '\\$1'); + + item = '(^' + item + '$)'; + + if (isNegate) { + negate.push(item); + } else { + match.push(item); + } + }); + + match = match.length ? new RegExp(match.join('|'), isIgnore) : null; + negate = negate.length ? new RegExp(negate.join('|'), isIgnore) : null; + + return function(filepath) { + // Normalize \\ paths to / paths. + filepath = util.path.unixifyPath(filepath); + + if (negate && negate.test(filepath)) { + return false; + } + + if (match && match.test(filepath)) { + return true; + } + + return false; + }; +} + +module.exports = fileMatch; +},{"utils-extend":524}],108:[function(require,module,exports){ +/** + * @fileoverview Strengthen the ability of file system + * @author wliao + */ +var fs = require('fs'); +var util = require('utils-extend'); +var path = require('path'); +var fileMatch = require('file-match'); + +function checkCbAndOpts(options, callback) { + if (util.isFunction(options)) { + return { + options: null, + callback: options + }; + } else if (util.isObject(options)) { + return { + options: options, + callback: callback + }; + } else { + return { + options: null, + callback: util.noop + }; + } +} + +function getExists(filepath) { + var exists = fs.existsSync(filepath); + + if (exists) { + return filepath; + } else { + return getExists(path.dirname(filepath)); + } +} + +util.extend(exports, fs); + +/** + * @description + * Assign node origin methods to fs + */ +exports.fs = fs; + +exports.fileMatch = fileMatch; + +/** + * @description + * Create dir, if dir exist, it will only invoke callback. + * + * @example + * ```js + * fs.mkdir('1/2/3/4/5', 511); + * fs.mkdir('path/2/3', function() {}); + * ``` + */ +exports.mkdir = function(filepath, mode, callback) { + var root = getExists(filepath); + var children = path.relative(root, filepath); + + if (util.isFunction(mode)) { + callback = mode; + mode = null; + } + + if (!util.isFunction(callback)) { + callback = util.noop; + } + + mode = mode || 511; + + if (!children) return callback(); + + children = children.split(path.sep); + + function create(filepath) { + if (create.count === children.length) { + return callback(); + } + + filepath = path.join(filepath, children[create.count]); + + fs.mkdir(filepath, mode, function(err) { + create.count++; + create(filepath); + }); + } + + create.count = 0; + create(root); +}; + +/** + * @description + * Same as mkdir, but it is synchronous + */ +exports.mkdirSync = function(filepath, mode) { + var root = getExists(filepath); + var children = path.relative(root, filepath); + + if (!children) return; + + children = children.split(path.sep); + + children.forEach(function(item) { + root = path.join(root, item); + fs.mkdirSync(root, mode); + }); +}; + +/** + * @description + * Create file, if path don't exists, it will not throw error. + * And will mkdir for path, it is asynchronous + * + * @example + * ```js + * fs.writeFile('path/filename.txt', 'something') + * fs.writeFile('path/filename.txt', 'something', {}) + * ``` + */ +exports.writeFile = function(filename, data, options, callback) { + var result = checkCbAndOpts(options, callback); + var dirname = path.dirname(filename); + options = result.options; + callback = result.callback; + + // Create dir first + exports.mkdir(dirname, function() { + fs.writeFile(filename, data, options, callback); + }); +}; + +/** + * @description + * Same as writeFile, but it is synchronous + */ +exports.writeFileSync = function(filename, data, options) { + var dirname = path.dirname(filename); + + exports.mkdirSync(dirname); + fs.writeFileSync(filename, data, options); +}; + +/** + * @description + * Asynchronously copy a file + * @example + * file.copyFile('demo.txt', 'demo.dest.txt', { done: function(err) { }}) + */ +exports.copyFile = function(srcpath, destpath, options) { + options = util.extend({ + encoding: 'utf8', + done: util.noop + }, options || {}); + + if (!options.process) { + options.encoding = null; + } + + fs.readFile(srcpath, { + encoding: options.encoding + }, function(err, contents) { + if (err) return options.done(err); + + if (options.process) { + contents = options.process(contents); + } + + exports.writeFile(destpath, contents, options, options.done); + }); +}; + +/** + * @description + * Copy file to dest, if no process options, it will only copy file to dest + * @example + * file.copyFileSync('demo.txt', 'demo.dest.txt' { process: function(contents) { }}); + * file.copyFileSync('demo.png', 'dest.png'); + */ +exports.copyFileSync = function(srcpath, destpath, options) { + options = util.extend({ + encoding: 'utf8' + }, options || {}); + var contents; + + if (options.process) { + contents = fs.readFileSync(srcpath, options); + contents = options.process(contents, srcpath, options.relative); + + if (util.isObject(contents) && contents.filepath) { + destpath = contents.filepath; + contents = contents.contents; + } + + exports.writeFileSync(destpath, contents, options); + } else { + contents = fs.readFileSync(srcpath); + exports.writeFileSync(destpath, contents); + } +}; + +/** + * @description + * Recurse into a directory, executing callback for each file and folder + * if the filename is undefiend, the callback is for folder, otherwise for file. + * and it is asynchronous + * @example + * file.recurse('path', function(filepath, filename) { }); + * file.recurse('path', ['*.js', 'path/**\/*.html'], function(filepath, relative, filename) { }); + */ +exports.recurse = function(dirpath, filter, callback) { + if (util.isFunction(filter)) { + callback = filter; + filter = null; + } + var filterCb = fileMatch(filter); + var rootpath = dirpath; + + function recurse(dirpath) { + fs.readdir(dirpath, function(err, files) { + if (err) return callback(err); + + files.forEach(function(filename) { + var filepath = path.join(dirpath, filename); + + fs.stat(filepath, function(err, stats) { + var relative = path.relative(rootpath, filepath); + var flag = filterCb(relative); + + if (stats.isDirectory()) { + recurse(filepath); + if (flag) callback(filepath, relative); + } else { + if (flag) callback(filepath, relative, filename); + } + }); + }); + }); + } + + recurse(dirpath); +}; + +/** + * @description + * Same as recurse, but it is synchronous + * @example + * file.recurseSync('path', function(filepath, filename) {}); + * file.recurseSync('path', ['*.js', 'path/**\/*.html'], function(filepath, relative, filename) {}); + */ +exports.recurseSync = function(dirpath, filter, callback) { + if (util.isFunction(filter)) { + callback = filter; + filter = null; + } + var filterCb = fileMatch(filter); + var rootpath = dirpath; + + function recurse(dirpath) { + fs.readdirSync(dirpath).forEach(function(filename) { + var filepath = path.join(dirpath, filename); + var stats = fs.statSync(filepath); + var relative = path.relative(rootpath, filepath); + var flag = filterCb(relative); + + if (stats.isDirectory()) { + recurse(filepath); + if (flag) callback(filepath, relative); + } else { + if (flag) callback(filepath, relative, filename); + } + }); + } + + recurse(dirpath); +}; + +/** + * @description + * Remove folder and files in folder, but it's synchronous + * @example + * file.rmdirSync('path'); + */ +exports.rmdirSync = function(dirpath) { + exports.recurseSync(dirpath, function(filepath, relative, filename) { + // it is file, otherwise it's folder + if (filename) { + fs.unlinkSync(filepath); + } else { + fs.rmdirSync(filepath); + } + }); + + fs.rmdirSync(dirpath); +}; + +/** + * @description + * Copy dirpath to destpath, pass process callback for each file hanlder + * if you want to change the dest filepath, process callback return { contents: '', filepath: ''} + * otherwise only change contents + * @example + * file.copySync('path', 'dest'); + * file.copySync('src', 'dest/src'); + * file.copySync('path', 'dest', { process: function(contents, filepath) {} }); + * file.copySync('path', 'dest', { process: function(contents, filepath) {} }, noProcess: ['']); + */ +exports.copySync = function(dirpath, destpath, options) { + options = util.extend({ + encoding: 'utf8', + filter: null, + noProcess: '' + }, options || {}); + var noProcessCb = fileMatch(options.noProcess); + + // Make sure dest root + exports.mkdirSync(destpath); + exports.recurseSync(dirpath, options.filter, function(filepath, relative, filename) { + if (!filename) return; + var newpath = path.join(destpath, relative); + var opts = { + relative: relative + }; + + if (options.process && !noProcessCb(relative)) { + opts.encoding = options.encoding; + opts.process = options.process; + } + + exports.copyFileSync(filepath, newpath, opts); + }); +}; +},{"file-match":107,"fs":298,"path":404,"utils-extend":524}],109:[function(require,module,exports){ +(function (Buffer){ +'use strict'; +const { + multiByteIndexOf, + stringToBytes, + readUInt64LE, + tarHeaderChecksumMatches, + uint8ArrayUtf8ByteString +} = require('./util'); +const supported = require('./supported'); + +const xpiZipFilename = stringToBytes('META-INF/mozilla.rsa'); +const oxmlContentTypes = stringToBytes('[Content_Types].xml'); +const oxmlRels = stringToBytes('_rels/.rels'); + +const fileType = input => { + if (!(input instanceof Uint8Array || input instanceof ArrayBuffer || Buffer.isBuffer(input))) { + throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`Buffer\` or \`ArrayBuffer\`, got \`${typeof input}\``); + } + + const buffer = input instanceof Uint8Array ? input : new Uint8Array(input); + + if (!(buffer && buffer.length > 1)) { + return; + } + + const check = (header, options) => { + options = { + offset: 0, + ...options + }; + + for (let i = 0; i < header.length; i++) { + // If a bitmask is set + if (options.mask) { + // If header doesn't equal `buf` with bits masked off + if (header[i] !== (options.mask[i] & buffer[i + options.offset])) { + return false; + } + } else if (header[i] !== buffer[i + options.offset]) { + return false; + } + } + + return true; + }; + + const checkString = (header, options) => check(stringToBytes(header), options); + + if (check([0xFF, 0xD8, 0xFF])) { + return { + ext: 'jpg', + mime: 'image/jpeg' + }; + } + + if (check([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])) { + // APNG format (https://wiki.mozilla.org/APNG_Specification) + // 1. Find the first IDAT (image data) chunk (49 44 41 54) + // 2. Check if there is an "acTL" chunk before the IDAT one (61 63 54 4C) + + // Offset calculated as follows: + // - 8 bytes: PNG signature + // - 4 (length) + 4 (chunk type) + 13 (chunk data) + 4 (CRC): IHDR chunk + const startIndex = 33; + const firstImageDataChunkIndex = buffer.findIndex((el, i) => i >= startIndex && buffer[i] === 0x49 && buffer[i + 1] === 0x44 && buffer[i + 2] === 0x41 && buffer[i + 3] === 0x54); + const sliced = buffer.subarray(startIndex, firstImageDataChunkIndex); + + if (sliced.findIndex((el, i) => sliced[i] === 0x61 && sliced[i + 1] === 0x63 && sliced[i + 2] === 0x54 && sliced[i + 3] === 0x4C) >= 0) { + return { + ext: 'apng', + mime: 'image/apng' + }; + } + + return { + ext: 'png', + mime: 'image/png' + }; + } + + if (check([0x47, 0x49, 0x46])) { + return { + ext: 'gif', + mime: 'image/gif' + }; + } + + if (check([0x57, 0x45, 0x42, 0x50], {offset: 8})) { + return { + ext: 'webp', + mime: 'image/webp' + }; + } + + if (check([0x46, 0x4C, 0x49, 0x46])) { + return { + ext: 'flif', + mime: 'image/flif' + }; + } + + // `cr2`, `orf`, and `arw` need to be before `tif` check + if ( + (check([0x49, 0x49, 0x2A, 0x0]) || check([0x4D, 0x4D, 0x0, 0x2A])) && + check([0x43, 0x52], {offset: 8}) + ) { + return { + ext: 'cr2', + mime: 'image/x-canon-cr2' + }; + } + + if (check([0x49, 0x49, 0x52, 0x4F, 0x08, 0x00, 0x00, 0x00, 0x18])) { + return { + ext: 'orf', + mime: 'image/x-olympus-orf' + }; + } + + if ( + check([0x49, 0x49, 0x2A, 0x00]) && + (check([0x10, 0xFB, 0x86, 0x01], {offset: 4}) || check([0x08, 0x00, 0x00, 0x00], {offset: 4})) && + // This pattern differentiates ARW from other TIFF-ish file types: + check([0x00, 0xFE, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x01], {offset: 9}) + ) { + return { + ext: 'arw', + mime: 'image/x-sony-arw' + }; + } + + if ( + check([0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00]) && + (check([0x2D, 0x00, 0xFE, 0x00], {offset: 8}) || + check([0x27, 0x00, 0xFE, 0x00], {offset: 8})) + ) { + return { + ext: 'dng', + mime: 'image/x-adobe-dng' + }; + } + + if ( + check([0x49, 0x49, 0x2A, 0x00]) && + check([0x1C, 0x00, 0xFE, 0x00], {offset: 8}) + ) { + return { + ext: 'nef', + mime: 'image/x-nikon-nef' + }; + } + + if (check([0x49, 0x49, 0x55, 0x00, 0x18, 0x00, 0x00, 0x00, 0x88, 0xE7, 0x74, 0xD8])) { + return { + ext: 'rw2', + mime: 'image/x-panasonic-rw2' + }; + } + + // `raf` is here just to keep all the raw image detectors together. + if (checkString('FUJIFILMCCD-RAW')) { + return { + ext: 'raf', + mime: 'image/x-fujifilm-raf' + }; + } + + if ( + check([0x49, 0x49, 0x2A, 0x0]) || + check([0x4D, 0x4D, 0x0, 0x2A]) + ) { + return { + ext: 'tif', + mime: 'image/tiff' + }; + } + + if (check([0x42, 0x4D])) { + return { + ext: 'bmp', + mime: 'image/bmp' + }; + } + + if (check([0x49, 0x49, 0xBC])) { + return { + ext: 'jxr', + mime: 'image/vnd.ms-photo' + }; + } + + if (check([0x38, 0x42, 0x50, 0x53])) { + return { + ext: 'psd', + mime: 'image/vnd.adobe.photoshop' + }; + } + + // Zip-based file formats + // Need to be before the `zip` check + const zipHeader = [0x50, 0x4B, 0x3, 0x4]; + if (check(zipHeader)) { + if ( + check([0x6D, 0x69, 0x6D, 0x65, 0x74, 0x79, 0x70, 0x65, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x65, 0x70, 0x75, 0x62, 0x2B, 0x7A, 0x69, 0x70], {offset: 30}) + ) { + return { + ext: 'epub', + mime: 'application/epub+zip' + }; + } + + // Assumes signed `.xpi` from addons.mozilla.org + if (check(xpiZipFilename, {offset: 30})) { + return { + ext: 'xpi', + mime: 'application/x-xpinstall' + }; + } + + if (checkString('mimetypeapplication/vnd.oasis.opendocument.text', {offset: 30})) { + return { + ext: 'odt', + mime: 'application/vnd.oasis.opendocument.text' + }; + } + + if (checkString('mimetypeapplication/vnd.oasis.opendocument.spreadsheet', {offset: 30})) { + return { + ext: 'ods', + mime: 'application/vnd.oasis.opendocument.spreadsheet' + }; + } + + if (checkString('mimetypeapplication/vnd.oasis.opendocument.presentation', {offset: 30})) { + return { + ext: 'odp', + mime: 'application/vnd.oasis.opendocument.presentation' + }; + } + + // The docx, xlsx and pptx file types extend the Office Open XML file format: + // https://en.wikipedia.org/wiki/Office_Open_XML_file_formats + // We look for: + // - one entry named '[Content_Types].xml' or '_rels/.rels', + // - one entry indicating specific type of file. + // MS Office, OpenOffice and LibreOffice may put the parts in different order, so the check should not rely on it. + let zipHeaderIndex = 0; // The first zip header was already found at index 0 + let oxmlFound = false; + let type; + + do { + const offset = zipHeaderIndex + 30; + + if (!oxmlFound) { + oxmlFound = (check(oxmlContentTypes, {offset}) || check(oxmlRels, {offset})); + } + + if (!type) { + if (checkString('word/', {offset})) { + type = { + ext: 'docx', + mime: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + }; + } else if (checkString('ppt/', {offset})) { + type = { + ext: 'pptx', + mime: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' + }; + } else if (checkString('xl/', {offset})) { + type = { + ext: 'xlsx', + mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + }; + } + } + + if (oxmlFound && type) { + return type; + } + + zipHeaderIndex = multiByteIndexOf(buffer, zipHeader, offset); + } while (zipHeaderIndex >= 0); + + // No more zip parts available in the buffer, but maybe we are almost certain about the type? + if (type) { + return type; + } + } + + if ( + check([0x50, 0x4B]) && + (buffer[2] === 0x3 || buffer[2] === 0x5 || buffer[2] === 0x7) && + (buffer[3] === 0x4 || buffer[3] === 0x6 || buffer[3] === 0x8) + ) { + return { + ext: 'zip', + mime: 'application/zip' + }; + } + + if ( + check([0x30, 0x30, 0x30, 0x30, 0x30, 0x30], {offset: 148, mask: [0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8]}) && // Valid tar checksum + tarHeaderChecksumMatches(buffer) + ) { + return { + ext: 'tar', + mime: 'application/x-tar' + }; + } + + if ( + check([0x52, 0x61, 0x72, 0x21, 0x1A, 0x7]) && + (buffer[6] === 0x0 || buffer[6] === 0x1) + ) { + return { + ext: 'rar', + mime: 'application/x-rar-compressed' + }; + } + + if (check([0x1F, 0x8B, 0x8])) { + return { + ext: 'gz', + mime: 'application/gzip' + }; + } + + if (check([0x42, 0x5A, 0x68])) { + return { + ext: 'bz2', + mime: 'application/x-bzip2' + }; + } + + if (check([0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C])) { + return { + ext: '7z', + mime: 'application/x-7z-compressed' + }; + } + + if (check([0x78, 0x01])) { + return { + ext: 'dmg', + mime: 'application/x-apple-diskimage' + }; + } + + // `mov` format variants + if ( + check([0x66, 0x72, 0x65, 0x65], {offset: 4}) || // `free` + check([0x6D, 0x64, 0x61, 0x74], {offset: 4}) || // `mdat` MJPEG + check([0x6D, 0x6F, 0x6F, 0x76], {offset: 4}) || // `moov` + check([0x77, 0x69, 0x64, 0x65], {offset: 4}) // `wide` + ) { + return { + ext: 'mov', + mime: 'video/quicktime' + }; + } + + // File Type Box (https://en.wikipedia.org/wiki/ISO_base_media_file_format) + // It's not required to be first, but it's recommended to be. Almost all ISO base media files start with `ftyp` box. + // `ftyp` box must contain a brand major identifier, which must consist of ISO 8859-1 printable characters. + // Here we check for 8859-1 printable characters (for simplicity, it's a mask which also catches one non-printable character). + if ( + checkString('ftyp', {offset: 4}) && + (buffer[8] & 0x60) !== 0x00 // Brand major, first character ASCII? + ) { + // They all can have MIME `video/mp4` except `application/mp4` special-case which is hard to detect. + // For some cases, we're specific, everything else falls to `video/mp4` with `mp4` extension. + const brandMajor = uint8ArrayUtf8ByteString(buffer, 8, 12).replace('\0', ' ').trim(); + switch (brandMajor) { + case 'mif1': + return {ext: 'heic', mime: 'image/heif'}; + case 'msf1': + return {ext: 'heic', mime: 'image/heif-sequence'}; + case 'heic': case 'heix': + return {ext: 'heic', mime: 'image/heic'}; + case 'hevc': case 'hevx': + return {ext: 'heic', mime: 'image/heic-sequence'}; + case 'qt': + return {ext: 'mov', mime: 'video/quicktime'}; + case 'M4V': case 'M4VH': case 'M4VP': + return {ext: 'm4v', mime: 'video/x-m4v'}; + case 'M4P': + return {ext: 'm4p', mime: 'video/mp4'}; + case 'M4B': + return {ext: 'm4b', mime: 'audio/mp4'}; + case 'M4A': + return {ext: 'm4a', mime: 'audio/x-m4a'}; + case 'F4V': + return {ext: 'f4v', mime: 'video/mp4'}; + case 'F4P': + return {ext: 'f4p', mime: 'video/mp4'}; + case 'F4A': + return {ext: 'f4a', mime: 'audio/mp4'}; + case 'F4B': + return {ext: 'f4b', mime: 'audio/mp4'}; + default: + if (brandMajor.startsWith('3g')) { + if (brandMajor.startsWith('3g2')) { + return {ext: '3g2', mime: 'video/3gpp2'}; + } + + return {ext: '3gp', mime: 'video/3gpp'}; + } + + return {ext: 'mp4', mime: 'video/mp4'}; + } + } + + if (check([0x4D, 0x54, 0x68, 0x64])) { + return { + ext: 'mid', + mime: 'audio/midi' + }; + } + + // https://github.com/threatstack/libmagic/blob/master/magic/Magdir/matroska + if (check([0x1A, 0x45, 0xDF, 0xA3])) { + const sliced = buffer.subarray(4, 4 + 4096); + const idPos = sliced.findIndex((el, i, arr) => arr[i] === 0x42 && arr[i + 1] === 0x82); + + if (idPos !== -1) { + const docTypePos = idPos + 3; + const findDocType = type => [...type].every((c, i) => sliced[docTypePos + i] === c.charCodeAt(0)); + + if (findDocType('matroska')) { + return { + ext: 'mkv', + mime: 'video/x-matroska' + }; + } + + if (findDocType('webm')) { + return { + ext: 'webm', + mime: 'video/webm' + }; + } + } + } + + // RIFF file format which might be AVI, WAV, QCP, etc + if (check([0x52, 0x49, 0x46, 0x46])) { + if (check([0x41, 0x56, 0x49], {offset: 8})) { + return { + ext: 'avi', + mime: 'video/vnd.avi' + }; + } + + if (check([0x57, 0x41, 0x56, 0x45], {offset: 8})) { + return { + ext: 'wav', + mime: 'audio/vnd.wave' + }; + } + + // QLCM, QCP file + if (check([0x51, 0x4C, 0x43, 0x4D], {offset: 8})) { + return { + ext: 'qcp', + mime: 'audio/qcelp' + }; + } + } + + // ASF_Header_Object first 80 bytes + if (check([0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9])) { + // Search for header should be in first 1KB of file. + + let offset = 30; + do { + const objectSize = readUInt64LE(buffer, offset + 16); + if (check([0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65], {offset})) { + // Sync on Stream-Properties-Object (B7DC0791-A9B7-11CF-8EE6-00C00C205365) + if (check([0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B], {offset: offset + 24})) { + // Found audio: + return { + ext: 'wma', + mime: 'audio/x-ms-wma' + }; + } + + if (check([0xC0, 0xEF, 0x19, 0xBC, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B], {offset: offset + 24})) { + // Found video: + return { + ext: 'wmv', + mime: 'video/x-ms-asf' + }; + } + + break; + } + + offset += objectSize; + } while (offset + 24 <= buffer.length); + + // Default to ASF generic extension + return { + ext: 'asf', + mime: 'application/vnd.ms-asf' + }; + } + + if ( + check([0x0, 0x0, 0x1, 0xBA]) || + check([0x0, 0x0, 0x1, 0xB3]) + ) { + return { + ext: 'mpg', + mime: 'video/mpeg' + }; + } + + // Check for MPEG header at different starting offsets + for (let start = 0; start < 2 && start < (buffer.length - 16); start++) { + if ( + check([0x49, 0x44, 0x33], {offset: start}) || // ID3 header + check([0xFF, 0xE2], {offset: start, mask: [0xFF, 0xE6]}) // MPEG 1 or 2 Layer 3 header + ) { + return { + ext: 'mp3', + mime: 'audio/mpeg' + }; + } + + if ( + check([0xFF, 0xE4], {offset: start, mask: [0xFF, 0xE6]}) // MPEG 1 or 2 Layer 2 header + ) { + return { + ext: 'mp2', + mime: 'audio/mpeg' + }; + } + + if ( + check([0xFF, 0xF8], {offset: start, mask: [0xFF, 0xFC]}) // MPEG 2 layer 0 using ADTS + ) { + return { + ext: 'mp2', + mime: 'audio/mpeg' + }; + } + + if ( + check([0xFF, 0xF0], {offset: start, mask: [0xFF, 0xFC]}) // MPEG 4 layer 0 using ADTS + ) { + return { + ext: 'mp4', + mime: 'audio/mpeg' + }; + } + } + + // Needs to be before `ogg` check + if (check([0x4F, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64], {offset: 28})) { + return { + ext: 'opus', + mime: 'audio/opus' + }; + } + + // If 'OggS' in first bytes, then OGG container + if (check([0x4F, 0x67, 0x67, 0x53])) { + // This is a OGG container + + // If ' theora' in header. + if (check([0x80, 0x74, 0x68, 0x65, 0x6F, 0x72, 0x61], {offset: 28})) { + return { + ext: 'ogv', + mime: 'video/ogg' + }; + } + + // If '\x01video' in header. + if (check([0x01, 0x76, 0x69, 0x64, 0x65, 0x6F, 0x00], {offset: 28})) { + return { + ext: 'ogm', + mime: 'video/ogg' + }; + } + + // If ' FLAC' in header https://xiph.org/flac/faq.html + if (check([0x7F, 0x46, 0x4C, 0x41, 0x43], {offset: 28})) { + return { + ext: 'oga', + mime: 'audio/ogg' + }; + } + + // 'Speex ' in header https://en.wikipedia.org/wiki/Speex + if (check([0x53, 0x70, 0x65, 0x65, 0x78, 0x20, 0x20], {offset: 28})) { + return { + ext: 'spx', + mime: 'audio/ogg' + }; + } + + // If '\x01vorbis' in header + if (check([0x01, 0x76, 0x6F, 0x72, 0x62, 0x69, 0x73], {offset: 28})) { + return { + ext: 'ogg', + mime: 'audio/ogg' + }; + } + + // Default OGG container https://www.iana.org/assignments/media-types/application/ogg + return { + ext: 'ogx', + mime: 'application/ogg' + }; + } + + if (check([0x66, 0x4C, 0x61, 0x43])) { + return { + ext: 'flac', + mime: 'audio/x-flac' + }; + } + + if (check([0x4D, 0x41, 0x43, 0x20])) { // 'MAC ' + return { + ext: 'ape', + mime: 'audio/ape' + }; + } + + if (check([0x77, 0x76, 0x70, 0x6B])) { // 'wvpk' + return { + ext: 'wv', + mime: 'audio/wavpack' + }; + } + + if (check([0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A])) { + return { + ext: 'amr', + mime: 'audio/amr' + }; + } + + if (check([0x25, 0x50, 0x44, 0x46])) { + return { + ext: 'pdf', + mime: 'application/pdf' + }; + } + + if (check([0x4D, 0x5A])) { + return { + ext: 'exe', + mime: 'application/x-msdownload' + }; + } + + if ( + (buffer[0] === 0x43 || buffer[0] === 0x46) && + check([0x57, 0x53], {offset: 1}) + ) { + return { + ext: 'swf', + mime: 'application/x-shockwave-flash' + }; + } + + if (check([0x7B, 0x5C, 0x72, 0x74, 0x66])) { + return { + ext: 'rtf', + mime: 'application/rtf' + }; + } + + if (check([0x00, 0x61, 0x73, 0x6D])) { + return { + ext: 'wasm', + mime: 'application/wasm' + }; + } + + if ( + check([0x77, 0x4F, 0x46, 0x46]) && + ( + check([0x00, 0x01, 0x00, 0x00], {offset: 4}) || + check([0x4F, 0x54, 0x54, 0x4F], {offset: 4}) + ) + ) { + return { + ext: 'woff', + mime: 'font/woff' + }; + } + + if ( + check([0x77, 0x4F, 0x46, 0x32]) && + ( + check([0x00, 0x01, 0x00, 0x00], {offset: 4}) || + check([0x4F, 0x54, 0x54, 0x4F], {offset: 4}) + ) + ) { + return { + ext: 'woff2', + mime: 'font/woff2' + }; + } + + if ( + check([0x4C, 0x50], {offset: 34}) && + ( + check([0x00, 0x00, 0x01], {offset: 8}) || + check([0x01, 0x00, 0x02], {offset: 8}) || + check([0x02, 0x00, 0x02], {offset: 8}) + ) + ) { + return { + ext: 'eot', + mime: 'application/vnd.ms-fontobject' + }; + } + + if (check([0x00, 0x01, 0x00, 0x00, 0x00])) { + return { + ext: 'ttf', + mime: 'font/ttf' + }; + } + + if (check([0x4F, 0x54, 0x54, 0x4F, 0x00])) { + return { + ext: 'otf', + mime: 'font/otf' + }; + } + + if (check([0x00, 0x00, 0x01, 0x00])) { + return { + ext: 'ico', + mime: 'image/x-icon' + }; + } + + if (check([0x00, 0x00, 0x02, 0x00])) { + return { + ext: 'cur', + mime: 'image/x-icon' + }; + } + + if (check([0x46, 0x4C, 0x56, 0x01])) { + return { + ext: 'flv', + mime: 'video/x-flv' + }; + } + + if (check([0x25, 0x21])) { + return { + ext: 'ps', + mime: 'application/postscript' + }; + } + + if (check([0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00])) { + return { + ext: 'xz', + mime: 'application/x-xz' + }; + } + + if (check([0x53, 0x51, 0x4C, 0x69])) { + return { + ext: 'sqlite', + mime: 'application/x-sqlite3' + }; + } + + if (check([0x4E, 0x45, 0x53, 0x1A])) { + return { + ext: 'nes', + mime: 'application/x-nintendo-nes-rom' + }; + } + + if (check([0x43, 0x72, 0x32, 0x34])) { + return { + ext: 'crx', + mime: 'application/x-google-chrome-extension' + }; + } + + if ( + check([0x4D, 0x53, 0x43, 0x46]) || + check([0x49, 0x53, 0x63, 0x28]) + ) { + return { + ext: 'cab', + mime: 'application/vnd.ms-cab-compressed' + }; + } + + // Needs to be before `ar` check + if (check([0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E, 0x0A, 0x64, 0x65, 0x62, 0x69, 0x61, 0x6E, 0x2D, 0x62, 0x69, 0x6E, 0x61, 0x72, 0x79])) { + return { + ext: 'deb', + mime: 'application/x-deb' + }; + } + + if (check([0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E])) { + return { + ext: 'ar', + mime: 'application/x-unix-archive' + }; + } + + if (check([0xED, 0xAB, 0xEE, 0xDB])) { + return { + ext: 'rpm', + mime: 'application/x-rpm' + }; + } + + if ( + check([0x1F, 0xA0]) || + check([0x1F, 0x9D]) + ) { + return { + ext: 'Z', + mime: 'application/x-compress' + }; + } + + if (check([0x4C, 0x5A, 0x49, 0x50])) { + return { + ext: 'lz', + mime: 'application/x-lzip' + }; + } + + if (check([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E])) { + return { + ext: 'msi', + mime: 'application/x-msi' + }; + } + + if (check([0x06, 0x0E, 0x2B, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0D, 0x01, 0x02, 0x01, 0x01, 0x02])) { + return { + ext: 'mxf', + mime: 'application/mxf' + }; + } + + if (check([0x47], {offset: 4}) && (check([0x47], {offset: 192}) || check([0x47], {offset: 196}))) { + return { + ext: 'mts', + mime: 'video/mp2t' + }; + } + + if (check([0x42, 0x4C, 0x45, 0x4E, 0x44, 0x45, 0x52])) { + return { + ext: 'blend', + mime: 'application/x-blender' + }; + } + + if (check([0x42, 0x50, 0x47, 0xFB])) { + return { + ext: 'bpg', + mime: 'image/bpg' + }; + } + + if (check([0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A])) { + // JPEG-2000 family + + if (check([0x6A, 0x70, 0x32, 0x20], {offset: 20})) { + return { + ext: 'jp2', + mime: 'image/jp2' + }; + } + + if (check([0x6A, 0x70, 0x78, 0x20], {offset: 20})) { + return { + ext: 'jpx', + mime: 'image/jpx' + }; + } + + if (check([0x6A, 0x70, 0x6D, 0x20], {offset: 20})) { + return { + ext: 'jpm', + mime: 'image/jpm' + }; + } + + if (check([0x6D, 0x6A, 0x70, 0x32], {offset: 20})) { + return { + ext: 'mj2', + mime: 'image/mj2' + }; + } + } + + if (check([0x46, 0x4F, 0x52, 0x4D])) { + return { + ext: 'aif', + mime: 'audio/aiff' + }; + } + + if (checkString(' new Promise((resolve, reject) => { + // Using `eval` to work around issues when bundling with Webpack + const stream = eval('require')('stream'); // eslint-disable-line no-eval + + readableStream.on('error', reject); + readableStream.once('readable', () => { + const pass = new stream.PassThrough(); + const chunk = readableStream.read(module.exports.minimumBytes) || readableStream.read(); + try { + pass.fileType = fileType(chunk); + } catch (error) { + reject(error); + } + + readableStream.unshift(chunk); + + if (stream.pipeline) { + resolve(stream.pipeline(readableStream, pass, () => {})); + } else { + resolve(readableStream.pipe(pass)); + } + }); +}); + +Object.defineProperty(fileType, 'extensions', { + get() { + return new Set(supported.extensions); + } +}); + +Object.defineProperty(fileType, 'mimeTypes', { + get() { + return new Set(supported.mimeTypes); + } +}); + +}).call(this,{"isBuffer":require("../is-buffer/index.js")}) +},{"../is-buffer/index.js":361,"./supported":110,"./util":111}],110:[function(require,module,exports){ +'use strict'; + +module.exports = { + extensions: [ + 'jpg', + 'png', + 'apng', + 'gif', + 'webp', + 'flif', + 'cr2', + 'orf', + 'arw', + 'dng', + 'nef', + 'rw2', + 'raf', + 'tif', + 'bmp', + 'jxr', + 'psd', + 'zip', + 'tar', + 'rar', + 'gz', + 'bz2', + '7z', + 'dmg', + 'mp4', + 'mid', + 'mkv', + 'webm', + 'mov', + 'avi', + 'mpg', + 'mp2', + 'mp3', + 'm4a', + 'oga', + 'ogg', + 'ogv', + 'opus', + 'flac', + 'wav', + 'spx', + 'amr', + 'pdf', + 'epub', + 'exe', + 'swf', + 'rtf', + 'wasm', + 'woff', + 'woff2', + 'eot', + 'ttf', + 'otf', + 'ico', + 'flv', + 'ps', + 'xz', + 'sqlite', + 'nes', + 'crx', + 'xpi', + 'cab', + 'deb', + 'ar', + 'rpm', + 'Z', + 'lz', + 'msi', + 'mxf', + 'mts', + 'blend', + 'bpg', + 'docx', + 'pptx', + 'xlsx', + '3gp', + '3g2', + 'jp2', + 'jpm', + 'jpx', + 'mj2', + 'aif', + 'qcp', + 'odt', + 'ods', + 'odp', + 'xml', + 'mobi', + 'heic', + 'cur', + 'ktx', + 'ape', + 'wv', + 'wmv', + 'wma', + 'dcm', + 'ics', + 'glb', + 'pcap', + 'dsf', + 'lnk', + 'alias', + 'voc', + 'ac3', + 'm4v', + 'm4p', + 'm4b', + 'f4v', + 'f4p', + 'f4b', + 'f4a', + 'mie', + 'asf', + 'ogm', + 'ogx', + 'mpc', + 'arrow', + 'shp' + ], + mimeTypes: [ + 'image/jpeg', + 'image/png', + 'image/gif', + 'image/webp', + 'image/flif', + 'image/x-canon-cr2', + 'image/tiff', + 'image/bmp', + 'image/vnd.ms-photo', + 'image/vnd.adobe.photoshop', + 'application/epub+zip', + 'application/x-xpinstall', + 'application/vnd.oasis.opendocument.text', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/vnd.oasis.opendocument.presentation', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/zip', + 'application/x-tar', + 'application/x-rar-compressed', + 'application/gzip', + 'application/x-bzip2', + 'application/x-7z-compressed', + 'application/x-apple-diskimage', + 'application/x-apache-arrow', + 'video/mp4', + 'audio/midi', + 'video/x-matroska', + 'video/webm', + 'video/quicktime', + 'video/vnd.avi', + 'audio/vnd.wave', + 'audio/qcelp', + 'audio/x-ms-wma', + 'video/x-ms-asf', + 'application/vnd.ms-asf', + 'video/mpeg', + 'video/3gpp', + 'audio/mpeg', + 'audio/mp4', // RFC 4337 + 'audio/opus', + 'video/ogg', + 'audio/ogg', + 'application/ogg', + 'audio/x-flac', + 'audio/ape', + 'audio/wavpack', + 'audio/amr', + 'application/pdf', + 'application/x-msdownload', + 'application/x-shockwave-flash', + 'application/rtf', + 'application/wasm', + 'font/woff', + 'font/woff2', + 'application/vnd.ms-fontobject', + 'font/ttf', + 'font/otf', + 'image/x-icon', + 'video/x-flv', + 'application/postscript', + 'application/x-xz', + 'application/x-sqlite3', + 'application/x-nintendo-nes-rom', + 'application/x-google-chrome-extension', + 'application/vnd.ms-cab-compressed', + 'application/x-deb', + 'application/x-unix-archive', + 'application/x-rpm', + 'application/x-compress', + 'application/x-lzip', + 'application/x-msi', + 'application/x-mie', + 'application/mxf', + 'video/mp2t', + 'application/x-blender', + 'image/bpg', + 'image/jp2', + 'image/jpx', + 'image/jpm', + 'image/mj2', + 'audio/aiff', + 'application/xml', + 'application/x-mobipocket-ebook', + 'image/heif', + 'image/heif-sequence', + 'image/heic', + 'image/heic-sequence', + 'image/ktx', + 'application/dicom', + 'audio/x-musepack', + 'text/calendar', + 'model/gltf-binary', + 'application/vnd.tcpdump.pcap', + 'audio/x-dsf', // Non-standard + 'application/x.ms.shortcut', // Invented by us + 'application/x.apple.alias', // Invented by us + 'audio/x-voc', + 'audio/vnd.dolby.dd-raw', + 'audio/x-m4a', + 'image/apng', + 'image/x-olympus-orf', + 'image/x-sony-arw', + 'image/x-adobe-dng', + 'image/x-nikon-nef', + 'image/x-panasonic-rw2', + 'image/x-fujifilm-raf', + 'video/x-m4v', + 'video/3gpp2', + 'application/x-esri-shape' + ] +}; + +},{}],111:[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +exports.stringToBytes = string => [...string].map(character => character.charCodeAt(0)); + +const uint8ArrayUtf8ByteString = (array, start, end) => { + return String.fromCharCode(...array.slice(start, end)); +}; + +exports.readUInt64LE = (buffer, offset = 0) => { + let n = buffer[offset]; + let mul = 1; + let i = 0; + + while (++i < 8) { + mul *= 0x100; + n += buffer[offset + i] * mul; + } + + return n; +}; + +exports.tarHeaderChecksumMatches = buffer => { // Does not check if checksum field characters are valid + if (buffer.length < 512) { // `tar` header size, cannot compute checksum without it + return false; + } + + const MASK_8TH_BIT = 0x80; + + let sum = 256; // Intitalize sum, with 256 as sum of 8 spaces in checksum field + let signedBitSum = 0; // Initialize signed bit sum + + for (let i = 0; i < 148; i++) { + const byte = buffer[i]; + sum += byte; + signedBitSum += byte & MASK_8TH_BIT; // Add signed bit to signed bit sum + } + + // Skip checksum field + + for (let i = 156; i < 512; i++) { + const byte = buffer[i]; + sum += byte; + signedBitSum += byte & MASK_8TH_BIT; // Add signed bit to signed bit sum + } + + const readSum = parseInt(uint8ArrayUtf8ByteString(buffer, 148, 154), 8); // Read sum in header + + // Some implementations compute checksum incorrectly using signed bytes + return ( + // Checksum in header equals the sum we calculated + readSum === sum || + + // Checksum in header equals sum we calculated plus signed-to-unsigned delta + readSum === (sum - (signedBitSum << 1)) + ); +}; + +exports.multiByteIndexOf = (buffer, bytesToSearch, startAt = 0) => { + // `Buffer#indexOf()` can search for multiple bytes + if (Buffer && Buffer.isBuffer(buffer)) { + return buffer.indexOf(Buffer.from(bytesToSearch), startAt); + } + + const nextBytesMatch = (buffer, bytes, startIndex) => { + for (let i = 1; i < bytes.length; i++) { + if (bytes[i] !== buffer[startIndex + i]) { + return false; + } + } + + return true; + }; + + // `Uint8Array#indexOf()` can search for only a single byte + let index = buffer.indexOf(bytesToSearch[0], startAt); + while (index >= 0) { + if (nextBytesMatch(buffer, bytesToSearch, index)) { + return index; + } + + index = buffer.indexOf(bytesToSearch[0], index + 1); + } + + return -1; +}; + +exports.uint8ArrayUtf8ByteString = uint8ArrayUtf8ByteString; + +}).call(this,require("buffer").Buffer) +},{"buffer":299}],112:[function(require,module,exports){ + +/** + * Module dependencies. + */ + +var sep = require('path').sep || '/'; + +/** + * Module exports. + */ + +module.exports = fileUriToPath; + +/** + * File URI to Path function. + * + * @param {String} uri + * @return {String} path + * @api public + */ + +function fileUriToPath (uri) { + if ('string' != typeof uri || + uri.length <= 7 || + 'file://' != uri.substring(0, 7)) { + throw new TypeError('must pass in a file:// URI to convert to a file path'); + } + + var rest = decodeURI(uri.substring(7)); + var firstSlash = rest.indexOf('/'); + var host = rest.substring(0, firstSlash); + var path = rest.substring(firstSlash + 1); + + // 2. Scheme Definition + // As a special case, can be the string "localhost" or the empty + // string; this is interpreted as "the machine from which the URL is + // being interpreted". + if ('localhost' == host) host = ''; + + if (host) { + host = sep + sep + host; + } + + // 3.2 Drives, drive letters, mount points, file system root + // Drive letters are mapped into the top of a file URI in various ways, + // depending on the implementation; some applications substitute + // vertical bar ("|") for the colon after the drive letter, yielding + // "file:///c|/tmp/test.txt". In some cases, the colon is left + // unchanged, as in "file:///c:/tmp/test.txt". In other cases, the + // colon is simply omitted, as in "file:///c/tmp/test.txt". + path = path.replace(/^(.+)\|/, '$1:'); + + // for Windows, we need to invert the path separators from what a URI uses + if (sep == '\\') { + path = path.replace(/\//g, '\\'); + } + + if (/^.+\:/.test(path)) { + // has Windows drive at beginning of path + } else { + // unix path… + path = sep + path; + } + + return host + path; +} + +},{"path":404}],113:[function(require,module,exports){ +var FisheyeGl = function FisheyeGl(options){ + + // Defaults: + options = options || {}; + + options.width = options.width || 800; + options.height = options.height || 600; + + var model = options.model || { + vertex :[ + -1.0, -1.0, 0.0, + 1.0, -1.0, 0.0, + 1.0, 1.0, 0.0, + -1.0, 1.0, 0.0 + ], + indices :[ + 0, 1, 2, + 0, 2, 3, + 2, 1, 0, + 3, 2, 0 + ], + textureCoords : [ + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 + ] + }; + + var lens = options.lens || { + a : 1.0, + b : 1.0, + Fx : 0.0, + Fy : 0.0, + scale : 1.5 + }; + var fov = options.fov || { + x : 1.0, + y : 1.0 + } + var image = options.image || "images/barrel-distortion.png"; + + var selector = options.selector || "#canvas"; + var gl = getGLContext(selector); + + var shaders = require('./shaders'); + + var vertexSrc = loadFile(options.vertexSrc || "vertex"); + var fragmentSrc = loadFile(options.fragmentSrc || "fragment3"); + + var program = compileShader(gl, vertexSrc, fragmentSrc) + gl.useProgram(program); + + var aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); + var aTextureCoord = gl.getAttribLocation(program, "aTextureCoord"); + var uSampler = gl.getUniformLocation(program, "uSampler"); + var uLensS = gl.getUniformLocation(program, "uLensS"); + var uLensF = gl.getUniformLocation(program, "uLensF"); + var uFov = gl.getUniformLocation(program, "uFov"); + + var vertexBuffer, + indexBuffer, + textureBuffer; + + function createBuffers() { + + vertexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(model.vertex), gl.STATIC_DRAW); + gl.bindBuffer(gl.ARRAY_BUFFER, null); + + indexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(model.indices), gl.STATIC_DRAW); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + + textureBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(model.textureCoords), gl.STATIC_DRAW); + gl.bindBuffer(gl.ARRAY_BUFFER, null); + + } + + createBuffers(); + + function getGLContext(selector){ + var canvas = document.querySelector(selector); + + if(canvas == null){ + throw new Error("there is no canvas on this page"); + } + + var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"]; + for (var i = 0; i < names.length; ++i) { + var gl; + try { + gl = canvas.getContext(names[i], { preserveDrawingBuffer: true }); + } catch(e) { + continue; + } + if (gl) return gl; + } + + throw new Error("WebGL is not supported!"); + } + + function compileShader(gl, vertexSrc, fragmentSrc){ + var vertexShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertexShader, vertexSrc); + gl.compileShader(vertexShader); + + _checkCompile(vertexShader); + + var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragmentShader, fragmentSrc); + gl.compileShader(fragmentShader); + + _checkCompile(fragmentShader); + + var program = gl.createProgram(); + + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + + gl.linkProgram(program); + + return program; + + function _checkCompile(shader){ + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + throw new Error(gl.getShaderInfoLog(shader)); + } + } + } + + function loadFile(url, callback){ + + if(shaders.hasOwnProperty(url)) { + return shaders[url]; + } + + var ajax = new XMLHttpRequest(); + + if(callback) { + ajax.addEventListener("readystatechange", on) + ajax.open("GET", url, true); + ajax.send(null); + } else { + ajax.open("GET", url, false); + ajax.send(null); + + if(ajax.status == 200){ + return ajax.responseText; + } + } + + function on(){ + if(ajax.readyState === 4){ + //complete requset + if(ajax.status === 200){ + //not error + callback(null, ajax.responseText); + } else { + callback(new Error("fail to load!")); + } + } + } + } + + function loadImage(gl, img, callback, texture){ + texture = texture || gl.createTexture(); + + gl.bindTexture(gl.TEXTURE_2D, texture); + + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); //gl.NEAREST is also allowed, instead of gl.LINEAR, as neither mipmap. + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); //Prevents s-coordinate wrapping (repeating). + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); //Prevents t-coordinate wrapping (repeating). + //gl.generateMipmap(gl.TEXTURE_2D); + gl.bindTexture(gl.TEXTURE_2D, null); + + if(callback) callback(null, texture); + return texture; + } + + function loadImageFromUrl(gl, url, callback){ + var texture = gl.createTexture(); + var img = new Image(); + img.addEventListener("load", function onload(){ + loadImage(gl, img, callback, texture); + options.width = img.width; + options.height = img.height; + resize( + options.width, + options.height + ) + }); + img.src = url; + return texture; + } + + function run(animate, callback){ + var f = window.requestAnimationFrame || window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; + + // ugh + if(animate === true){ + if(f){ + f(on); + } else { + throw new Error("do not support 'requestAnimationFram'"); + } + } else { + f(on); + } + + var current = null; + function on(t){ + if(!current) current = t; + var dt = t - current; + current = t; + options.runner(dt); + if (callback) callback(); + if (animate === true) f(on); + } + } + + function resize(w, h) { + gl.viewport(0, 0, w, h); + gl.canvas.width = w; + gl.canvas.height = h; + } + + options.runner = options.runner|| function runner(dt){ + + gl.clearColor(0.0, 0.0, 0.0, 1.0); + gl.enable(gl.DEPTH_TEST); + + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + gl.enableVertexAttribArray(aVertexPosition); + + gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); + gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0); + + gl.enableVertexAttribArray(aTextureCoord); + + gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer); + gl.vertexAttribPointer(aTextureCoord, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.uniform1i(uSampler, 0); + + gl.uniform3fv(uLensS, [lens.a, lens.b, lens.scale]); + gl.uniform2fv(uLensF, [lens.Fx, lens.Fy]); + gl.uniform2fv(uFov, [fov.x, fov.y]); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); + gl.drawElements(gl.TRIANGLES, model.indices.length, gl.UNSIGNED_SHORT, 0); + } + + var texture; + + function setImage(imageUrl, callback) { + texture = loadImageFromUrl(gl, imageUrl, function onImageLoad() { + + run(options.animate, callback); + + }); + } + + setImage(image); + + // asynchronous! + function getImage(format) { + + var img = new Image(); + + img.src = gl.canvas.toDataURL(format || 'image/jpeg'); + + return img; + + } + + // external API: + var distorter = { + options: options, + gl: gl, + lens: lens, + fov: fov, + run: run, + getImage: getImage, + setImage: setImage + } + + return distorter; + +} + +if (typeof(document) != 'undefined') + window.FisheyeGl = FisheyeGl; +else + module.exports = FisheyeGl; + +},{"./shaders":114}],114:[function(require,module,exports){ +module.exports = { + fragment: require('./shaders/fragment.glfs'), + fragment2: require('./shaders/fragment2.glfs'), + fragment3: require('./shaders/fragment3.glfs'), + method1: require('./shaders/method1.glfs'), + method2: require('./shaders/method2.glfs'), + vertex: require('./shaders/vertex.glvs') +}; + +},{"./shaders/fragment.glfs":115,"./shaders/fragment2.glfs":116,"./shaders/fragment3.glfs":117,"./shaders/method1.glfs":118,"./shaders/method2.glfs":119,"./shaders/vertex.glvs":120}],115:[function(require,module,exports){ +module.exports = "\ +#ifdef GL_ES\n\ +precision highp float;\n\ +#endif\n\ +uniform vec4 uLens;\n\ +uniform vec2 uFov;\n\ +uniform sampler2D uSampler;\n\ +varying vec3 vPosition;\n\ +varying vec2 vTextureCoord;\n\ +vec2 GLCoord2TextureCoord(vec2 glCoord) {\n\ + return glCoord * vec2(1.0, -1.0)/ 2.0 + vec2(0.5, 0.5);\n\ +}\n\ +void main(void){\n\ + float scale = uLens.w;\n\ + float F = uLens.z;\n\ + \n\ + float L = length(vec3(vPosition.xy/scale, F));\n\ + vec2 vMapping = vPosition.xy * F / L;\n\ + vMapping = vMapping * uLens.xy;\n\ + vMapping = GLCoord2TextureCoord(vMapping/scale);\n\ + vec4 texture = texture2D(uSampler, vMapping);\n\ + if(vMapping.x > 0.99 || vMapping.x < 0.01 || vMapping.y > 0.99 || vMapping.y < 0.01){\n\ + texture = vec4(0.0, 0.0, 0.0, 1.0);\n\ + } \n\ + gl_FragColor = texture;\n\ +}\n\ +"; +},{}],116:[function(require,module,exports){ +module.exports = "\ +#ifdef GL_ES\n\ +precision highp float;\n\ +#endif\n\ +uniform vec4 uLens;\n\ +uniform vec2 uFov;\n\ +uniform sampler2D uSampler;\n\ +varying vec3 vPosition;\n\ +varying vec2 vTextureCoord;\n\ +vec2 TextureCoord2GLCoord(vec2 textureCoord) {\n\ + return (textureCoord - vec2(0.5, 0.5)) * 2.0;\n\ +}\n\ +vec2 GLCoord2TextureCoord(vec2 glCoord) {\n\ + return glCoord / 2.0 + vec2(0.5, 0.5);\n\ +}\n\ +void main(void){\n\ + float correctionRadius = 0.5;\n\ + float distance = sqrt(vPosition.x * vPosition.x + vPosition.y * vPosition.y) / correctionRadius;\n\ + float theta = 1.0;\n\ + if(distance != 0.0){\n\ + theta = atan(distance);\n\ + }\n\ + vec2 vMapping = theta * vPosition.xy;\n\ + vMapping = GLCoord2TextureCoord(vMapping);\n\ + \n\ + vec4 texture = texture2D(uSampler, vMapping);\n\ + if(vMapping.x > 0.99 || vMapping.x < 0.01 || vMapping.y > 0.99 || vMapping.y < 0.01){\n\ + texture = vec4(0.0, 0.0, 0.0, 1.0);\n\ + } \n\ + gl_FragColor = texture;\n\ +}\n\ +"; +},{}],117:[function(require,module,exports){ +module.exports = "\ +#ifdef GL_ES\n\ +precision highp float;\n\ +#endif\n\ +uniform vec3 uLensS;\n\ +uniform vec2 uLensF;\n\ +uniform vec2 uFov;\n\ +uniform sampler2D uSampler;\n\ +varying vec3 vPosition;\n\ +varying vec2 vTextureCoord;\n\ +vec2 GLCoord2TextureCoord(vec2 glCoord) {\n\ + return glCoord * vec2(1.0, -1.0)/ 2.0 + vec2(0.5, 0.5);\n\ +}\n\ +void main(void){\n\ + float scale = uLensS.z;\n\ + vec3 vPos = vPosition;\n\ + float Fx = uLensF.x;\n\ + float Fy = uLensF.y;\n\ + vec2 vMapping = vPos.xy;\n\ + vMapping.x = vMapping.x + ((pow(vPos.y, 2.0)/scale)*vPos.x/scale)*-Fx;\n\ + vMapping.y = vMapping.y + ((pow(vPos.x, 2.0)/scale)*vPos.y/scale)*-Fy;\n\ + vMapping = vMapping * uLensS.xy;\n\ + vMapping = GLCoord2TextureCoord(vMapping/scale);\n\ + vec4 texture = texture2D(uSampler, vMapping);\n\ + if(vMapping.x > 0.99 || vMapping.x < 0.01 || vMapping.y > 0.99 || vMapping.y < 0.01){\n\ + texture = vec4(0.0, 0.0, 0.0, 1.0);\n\ + }\n\ + gl_FragColor = texture;\n\ +}\n\ +"; +},{}],118:[function(require,module,exports){ +module.exports = "\ +#ifdef GL_ES\n\ +precision highp float;\n\ +#endif\n\ +uniform vec4 uLens;\n\ +uniform vec2 uFov;\n\ +uniform sampler2D uSampler;\n\ +varying vec3 vPosition;\n\ +varying vec2 vTextureCoord;\n\ +vec2 TextureCoord2GLCoord(vec2 textureCoord) {\n\ + return (textureCoord - vec2(0.5, 0.5)) * 2.0;\n\ +}\n\ +vec2 GLCoord2TextureCoord(vec2 glCoord) {\n\ + return glCoord / 2.0 + vec2(0.5, 0.5);\n\ +}\n\ +void main(void){\n\ + vec2 vMapping = vec2(vTextureCoord.x, 1.0 - vTextureCoord.y);\n\ + vMapping = TextureCoord2GLCoord(vMapping);\n\ + //TODO insert Code\n\ + float F = uLens.x/ uLens.w;\n\ + float seta = length(vMapping) / F;\n\ + vMapping = sin(seta) * F / length(vMapping) * vMapping;\n\ + vMapping *= uLens.w * 1.414;\n\ + vMapping = GLCoord2TextureCoord(vMapping);\n\ + vec4 texture = texture2D(uSampler, vMapping);\n\ + if(vMapping.x > 0.99 || vMapping.x < 0.01 || vMapping.y > 0.99 || vMapping.y < 0.01){\n\ + texture = vec4(0.0, 0.0, 0.0, 1.0);\n\ + } \n\ + gl_FragColor = texture;\n\ +}\n\ +"; +},{}],119:[function(require,module,exports){ +module.exports = "\ +#ifdef GL_ES\n\ +precision highp float;\n\ +#endif\n\ +uniform vec4 uLens;\n\ +uniform vec2 uFov;\n\ +uniform sampler2D uSampler;\n\ +varying vec3 vPosition;\n\ +varying vec2 vTextureCoord;\n\ +vec2 TextureCoord2GLCoord(vec2 textureCoord) {\n\ + return (textureCoord - vec2(0.5, 0.5)) * 2.0;\n\ +}\n\ +vec2 GLCoord2TextureCoord(vec2 glCoord) {\n\ + return glCoord / 2.0 + vec2(0.5, 0.5);\n\ +}\n\ +void main(void){\n\ + vec2 vMapping = vec2(vTextureCoord.x, 1.0 - vTextureCoord.y);\n\ + vMapping = TextureCoord2GLCoord(vMapping);\n\ + //TOD insert Code\n\ + float F = uLens.x/ uLens.w;\n\ + float seta = length(vMapping) / F;\n\ + vMapping = sin(seta) * F / length(vMapping) * vMapping;\n\ + vMapping *= uLens.w * 1.414;\n\ + vMapping = GLCoord2TextureCoord(vMapping);\n\ + vec4 texture = texture2D(uSampler, vMapping);\n\ + if(vMapping.x > 0.99 || vMapping.x < 0.01 || vMapping.y > 0.99 || vMapping.y < 0.01){\n\ + texture = vec4(0.0, 0.0, 0.0, 1.0);\n\ + } \n\ + gl_FragColor = texture;\n\ +}\n\ +"; +},{}],120:[function(require,module,exports){ +module.exports = "\ +#ifdef GL_ES\n\ +precision highp float;\n\ +#endif\n\ +attribute vec3 aVertexPosition;\n\ +attribute vec2 aTextureCoord;\n\ +varying vec3 vPosition;\n\ +varying vec2 vTextureCoord;\n\ +void main(void){\n\ + vPosition = aVertexPosition;\n\ + vTextureCoord = aTextureCoord;\n\ + gl_Position = vec4(vPosition,1.0);\n\ +}\n\ +"; +},{}],121:[function(require,module,exports){ +(function (process){ +module.exports = realpath +realpath.realpath = realpath +realpath.sync = realpathSync +realpath.realpathSync = realpathSync +realpath.monkeypatch = monkeypatch +realpath.unmonkeypatch = unmonkeypatch + +var fs = require('fs') +var origRealpath = fs.realpath +var origRealpathSync = fs.realpathSync + +var version = process.version +var ok = /^v[0-5]\./.test(version) +var old = require('./old.js') + +function newError (er) { + return er && er.syscall === 'realpath' && ( + er.code === 'ELOOP' || + er.code === 'ENOMEM' || + er.code === 'ENAMETOOLONG' + ) +} + +function realpath (p, cache, cb) { + if (ok) { + return origRealpath(p, cache, cb) + } + + if (typeof cache === 'function') { + cb = cache + cache = null + } + origRealpath(p, cache, function (er, result) { + if (newError(er)) { + old.realpath(p, cache, cb) + } else { + cb(er, result) + } + }) +} + +function realpathSync (p, cache) { + if (ok) { + return origRealpathSync(p, cache) + } + + try { + return origRealpathSync(p, cache) + } catch (er) { + if (newError(er)) { + return old.realpathSync(p, cache) + } else { + throw er + } + } +} + +function monkeypatch () { + fs.realpath = realpath + fs.realpathSync = realpathSync +} + +function unmonkeypatch () { + fs.realpath = origRealpath + fs.realpathSync = origRealpathSync +} + +}).call(this,require('_process')) +},{"./old.js":122,"_process":437,"fs":298}],122:[function(require,module,exports){ +(function (process){ +// 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 pathModule = require('path'); +var isWindows = process.platform === 'win32'; +var fs = require('fs'); + +// JavaScript implementation of realpath, ported from node pre-v6 + +var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); + +function rethrow() { + // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and + // is fairly slow to generate. + var callback; + if (DEBUG) { + var backtrace = new Error; + callback = debugCallback; + } else + callback = missingCallback; + + return callback; + + function debugCallback(err) { + if (err) { + backtrace.message = err.message; + err = backtrace; + missingCallback(err); + } + } + + function missingCallback(err) { + if (err) { + if (process.throwDeprecation) + throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs + else if (!process.noDeprecation) { + var msg = 'fs: missing callback ' + (err.stack || err.message); + if (process.traceDeprecation) + console.trace(msg); + else + console.error(msg); + } + } + } +} + +function maybeCallback(cb) { + return typeof cb === 'function' ? cb : rethrow(); +} + +var normalize = pathModule.normalize; + +// Regexp that finds the next partion of a (partial) path +// result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] +if (isWindows) { + var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; +} else { + var nextPartRe = /(.*?)(?:[\/]+|$)/g; +} + +// Regex to find the device root, including trailing slash. E.g. 'c:\\'. +if (isWindows) { + var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; +} else { + var splitRootRe = /^[\/]*/; +} + +exports.realpathSync = function realpathSync(p, cache) { + // make p is absolute + p = pathModule.resolve(p); + + if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { + return cache[p]; + } + + var original = p, + seenLinks = {}, + knownHard = {}; + + // current character position in p + var pos; + // the partial path so far, including a trailing slash if any + var current; + // the partial path without a trailing slash (except when pointing at a root) + var base; + // the partial path scanned in the previous round, with slash + var previous; + + start(); + + function start() { + // Skip over roots + var m = splitRootRe.exec(p); + pos = m[0].length; + current = m[0]; + base = m[0]; + previous = ''; + + // On windows, check that the root exists. On unix there is no need. + if (isWindows && !knownHard[base]) { + fs.lstatSync(base); + knownHard[base] = true; + } + } + + // walk down the path, swapping out linked pathparts for their real + // values + // NB: p.length changes. + while (pos < p.length) { + // find the next part + nextPartRe.lastIndex = pos; + var result = nextPartRe.exec(p); + previous = current; + current += result[0]; + base = previous + result[1]; + pos = nextPartRe.lastIndex; + + // continue if not a symlink + if (knownHard[base] || (cache && cache[base] === base)) { + continue; + } + + var resolvedLink; + if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { + // some known symbolic link. no need to stat again. + resolvedLink = cache[base]; + } else { + var stat = fs.lstatSync(base); + if (!stat.isSymbolicLink()) { + knownHard[base] = true; + if (cache) cache[base] = base; + continue; + } + + // read the link if it wasn't read before + // dev/ino always return 0 on windows, so skip the check. + var linkTarget = null; + if (!isWindows) { + var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); + if (seenLinks.hasOwnProperty(id)) { + linkTarget = seenLinks[id]; + } + } + if (linkTarget === null) { + fs.statSync(base); + linkTarget = fs.readlinkSync(base); + } + resolvedLink = pathModule.resolve(previous, linkTarget); + // track this, if given a cache. + if (cache) cache[base] = resolvedLink; + if (!isWindows) seenLinks[id] = linkTarget; + } + + // resolve the link, then start over + p = pathModule.resolve(resolvedLink, p.slice(pos)); + start(); + } + + if (cache) cache[original] = p; + + return p; +}; + + +exports.realpath = function realpath(p, cache, cb) { + if (typeof cb !== 'function') { + cb = maybeCallback(cache); + cache = null; + } + + // make p is absolute + p = pathModule.resolve(p); + + if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { + return process.nextTick(cb.bind(null, null, cache[p])); + } + + var original = p, + seenLinks = {}, + knownHard = {}; + + // current character position in p + var pos; + // the partial path so far, including a trailing slash if any + var current; + // the partial path without a trailing slash (except when pointing at a root) + var base; + // the partial path scanned in the previous round, with slash + var previous; + + start(); + + function start() { + // Skip over roots + var m = splitRootRe.exec(p); + pos = m[0].length; + current = m[0]; + base = m[0]; + previous = ''; + + // On windows, check that the root exists. On unix there is no need. + if (isWindows && !knownHard[base]) { + fs.lstat(base, function(err) { + if (err) return cb(err); + knownHard[base] = true; + LOOP(); + }); + } else { + process.nextTick(LOOP); + } + } + + // walk down the path, swapping out linked pathparts for their real + // values + function LOOP() { + // stop if scanned past end of path + if (pos >= p.length) { + if (cache) cache[original] = p; + return cb(null, p); + } + + // find the next part + nextPartRe.lastIndex = pos; + var result = nextPartRe.exec(p); + previous = current; + current += result[0]; + base = previous + result[1]; + pos = nextPartRe.lastIndex; + + // continue if not a symlink + if (knownHard[base] || (cache && cache[base] === base)) { + return process.nextTick(LOOP); + } + + if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { + // known symbolic link. no need to stat again. + return gotResolvedLink(cache[base]); + } + + return fs.lstat(base, gotStat); + } + + function gotStat(err, stat) { + if (err) return cb(err); + + // if not a symlink, skip to the next path part + if (!stat.isSymbolicLink()) { + knownHard[base] = true; + if (cache) cache[base] = base; + return process.nextTick(LOOP); + } + + // stat & read the link if not read before + // call gotTarget as soon as the link target is known + // dev/ino always return 0 on windows, so skip the check. + if (!isWindows) { + var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); + if (seenLinks.hasOwnProperty(id)) { + return gotTarget(null, seenLinks[id], base); + } + } + fs.stat(base, function(err) { + if (err) return cb(err); + + fs.readlink(base, function(err, target) { + if (!isWindows) seenLinks[id] = target; + gotTarget(err, target); + }); + }); + } + + function gotTarget(err, target, base) { + if (err) return cb(err); + + var resolvedLink = pathModule.resolve(previous, target); + if (cache) cache[base] = resolvedLink; + gotResolvedLink(resolvedLink); + } + + function gotResolvedLink(resolvedLink) { + // resolve the link, then start over + p = pathModule.resolve(resolvedLink, p.slice(pos)); + start(); + } +}; + +}).call(this,require('_process')) +},{"_process":437,"fs":298,"path":404}],123:[function(require,module,exports){ +(function (Buffer,process){ +'use strict' + +var path = require('path') +var ndarray = require('ndarray') +var GifReader = require('omggif').GifReader +var pack = require('ndarray-pack') +var through = require('through') +var parseDataURI = require('data-uri-to-buffer') + +function defaultImage(url, cb) { + var img = new Image() + img.crossOrigin = "Anonymous" + img.onload = function() { + var canvas = document.createElement('canvas') + canvas.width = img.width + canvas.height = img.height + var context = canvas.getContext('2d') + context.drawImage(img, 0, 0) + var pixels = context.getImageData(0, 0, img.width, img.height) + cb(null, ndarray(new Uint8Array(pixels.data), [img.width, img.height, 4], [4, 4*img.width, 1], 0)) + } + img.onerror = function(err) { + cb(err) + } + img.src = url +} + +//Animated gif loading +function handleGif(data, cb) { + var reader + try { + reader = new GifReader(data) + } catch(err) { + cb(err) + return + } + if(reader.numFrames() > 0) { + var nshape = [reader.numFrames(), reader.height, reader.width, 4] + var ndata = new Uint8Array(nshape[0] * nshape[1] * nshape[2] * nshape[3]) + var result = ndarray(ndata, nshape) + try { + for(var i=0; i= 0) this.dispose = disposalCode; +}; + +/* + Sets the number of times the set of GIF frames should be played. + + -1 = play once + 0 = repeat indefinitely + + Default is -1 + + Must be invoked before the first image is added +*/ + +GIFEncoder.prototype.setRepeat = function(repeat) { + this.repeat = repeat; +}; + +/* + Sets the transparent color for the last added frame and any subsequent + frames. Since all colors are subject to modification in the quantization + process, the color in the final palette for each frame closest to the given + color becomes the transparent color for that frame. May be set to null to + indicate no transparent color. +*/ +GIFEncoder.prototype.setTransparent = function(color) { + this.transparent = color; +}; + +// Custom methods for performance hacks around streaming GIF data pieces without re-analyzing/loading +GIFEncoder.prototype.analyzeImage = function (imageData) { + // convert to correct format if necessary + this.setImagePixels(this.removeAlphaChannel(imageData)); + this.analyzePixels(); // build color table & map pixels +}; + +GIFEncoder.prototype.writeImageInfo = function () { + if (this.firstFrame) { + this.writeLSD(); // logical screen descriptior + this.writePalette(); // global color table + if (this.repeat >= 0) { + // use NS app extension to indicate reps + this.writeNetscapeExt(); + } + } + + this.writeGraphicCtrlExt(); // write graphic control extension + this.writeImageDesc(); // image descriptor + if (!this.firstFrame) this.writePalette(); // local color table + + // DEV: This was originally after outputImage but it does not affect order it seems + this.firstFrame = false; +}; + +GIFEncoder.prototype.outputImage = function () { + this.writePixels(); // encode and write pixel data +}; + +/* + Adds next GIF frame. The frame is not written immediately, but is + actually deferred until the next frame is received so that timing + data can be inserted. Invoking finish() flushes all frames. +*/ +GIFEncoder.prototype.addFrame = function(imageData) { + this.emit('frame#start'); + + this.analyzeImage(imageData); + this.writeImageInfo(); + this.outputImage(); + + this.emit('frame#stop'); +}; + +/* + Adds final trailer to the GIF stream, if you don't call the finish method + the GIF stream will not be valid. +*/ +GIFEncoder.prototype.finish = function() { + this.emit('finish#start'); + this.writeByte(0x3b); // gif trailer + this.emit('finish#stop'); +}; + +/* + Sets quality of color quantization (conversion of images to the maximum 256 + colors allowed by the GIF specification). Lower values (minimum = 1) + produce better colors, but slow processing significantly. 10 is the + default, and produces good color mapping at reasonable speeds. Values + greater than 20 do not yield significant improvements in speed. +*/ +GIFEncoder.prototype.setQuality = function(quality) { + if (quality < 1) quality = 1; + this.sample = quality; +}; + +/* + Writes GIF file header +*/ +GIFEncoder.prototype.writeHeader = function() { + this.emit('writeHeader#start'); + this.writeUTFBytes("GIF89a"); + this.emit('writeHeader#stop'); +}; + +/* + Analyzes current frame colors and creates color map. +*/ +GIFEncoder.prototype.analyzePixels = function() { + var len = this.pixels.length; + var nPix = len / 3; + + // TODO: Re-use indexedPixels + this.indexedPixels = new Uint8Array(nPix); + + var imgq = new NeuQuant(this.pixels, this.sample); + imgq.buildColormap(); // create reduced palette + this.colorTab = imgq.getColormap(); + + // map image pixels to new palette + var k = 0; + for (var j = 0; j < nPix; j++) { + var index = imgq.lookupRGB( + this.pixels[k++] & 0xff, + this.pixels[k++] & 0xff, + this.pixels[k++] & 0xff + ); + this.usedEntry[index] = true; + this.indexedPixels[j] = index; + } + + this.pixels = null; + this.colorDepth = 8; + this.palSize = 7; + + // get closest match to transparent color if specified + if (this.transparent !== null) { + this.transIndex = this.findClosest(this.transparent); + } +}; + +/* + Returns index of palette color closest to c +*/ +GIFEncoder.prototype.findClosest = function(c) { + if (this.colorTab === null) return -1; + + var r = (c & 0xFF0000) >> 16; + var g = (c & 0x00FF00) >> 8; + var b = (c & 0x0000FF); + var minpos = 0; + var dmin = 256 * 256 * 256; + var len = this.colorTab.length; + + for (var i = 0; i < len;) { + var dr = r - (this.colorTab[i++] & 0xff); + var dg = g - (this.colorTab[i++] & 0xff); + var db = b - (this.colorTab[i] & 0xff); + var d = dr * dr + dg * dg + db * db; + var index = i / 3; + if (this.usedEntry[index] && (d < dmin)) { + dmin = d; + minpos = index; + } + i++; + } + + return minpos; +}; + +/* + Extracts image pixels into byte array pixels + (removes alphachannel from canvas imagedata) +*/ +GIFEncoder.prototype.removeAlphaChannel = function (data) { + var w = this.width; + var h = this.height; + var pixels = new Uint8Array(w * h * 3); + + var count = 0; + + for (var i = 0; i < h; i++) { + for (var j = 0; j < w; j++) { + var b = (i * w * 4) + j * 4; + pixels[count++] = data[b]; + pixels[count++] = data[b+1]; + pixels[count++] = data[b+2]; + } + } + + return pixels; +}; + +GIFEncoder.prototype.setImagePixels = function(pixels) { + this.pixels = pixels; +}; + +/* + Writes Graphic Control Extension +*/ +GIFEncoder.prototype.writeGraphicCtrlExt = function() { + this.writeByte(0x21); // extension introducer + this.writeByte(0xf9); // GCE label + this.writeByte(4); // data block size + + var transp, disp; + if (this.transparent === null) { + transp = 0; + disp = 0; // dispose = no action + } else { + transp = 1; + disp = 2; // force clear if using transparent color + } + + if (this.dispose >= 0) { + disp = dispose & 7; // user override + } + disp <<= 2; + + // packed fields + this.writeByte( + 0 | // 1:3 reserved + disp | // 4:6 disposal + 0 | // 7 user input - 0 = none + transp // 8 transparency flag + ); + + this.writeShort(this.delay); // delay x 1/100 sec + this.writeByte(this.transIndex); // transparent color index + this.writeByte(0); // block terminator +}; + +/* + Writes Image Descriptor +*/ +GIFEncoder.prototype.writeImageDesc = function() { + this.writeByte(0x2c); // image separator + this.writeShort(0); // image position x,y = 0,0 + this.writeShort(0); + this.writeShort(this.width); // image size + this.writeShort(this.height); + + // packed fields + if (this.firstFrame) { + // no LCT - GCT is used for first (or only) frame + this.writeByte(0); + } else { + // specify normal LCT + this.writeByte( + 0x80 | // 1 local color table 1=yes + 0 | // 2 interlace - 0=no + 0 | // 3 sorted - 0=no + 0 | // 4-5 reserved + this.palSize // 6-8 size of color table + ); + } +}; + +/* + Writes Logical Screen Descriptor +*/ +GIFEncoder.prototype.writeLSD = function() { + // logical screen size + this.writeShort(this.width); + this.writeShort(this.height); + + // packed fields + this.writeByte( + 0x80 | // 1 : global color table flag = 1 (gct used) + 0x70 | // 2-4 : color resolution = 7 + 0x00 | // 5 : gct sort flag = 0 + this.palSize // 6-8 : gct size + ); + + this.writeByte(0); // background color index + this.writeByte(0); // pixel aspect ratio - assume 1:1 +}; + +/* + Writes Netscape application extension to define repeat count. +*/ +GIFEncoder.prototype.writeNetscapeExt = function() { + this.writeByte(0x21); // extension introducer + this.writeByte(0xff); // app extension label + this.writeByte(11); // block size + this.writeUTFBytes('NETSCAPE2.0'); // app id + auth code + this.writeByte(3); // sub-block size + this.writeByte(1); // loop sub-block id + this.writeShort(this.repeat); // loop count (extra iterations, 0=repeat forever) + this.writeByte(0); // block terminator +}; + +/* + Writes color table +*/ +GIFEncoder.prototype.writePalette = function() { + this.writeBytes(this.colorTab); + var n = (3 * 256) - this.colorTab.length; + for (var i = 0; i < n; i++) + this.writeByte(0); +}; + +GIFEncoder.prototype.writeShort = function(pValue) { + this.writeByte(pValue & 0xFF); + this.writeByte((pValue >> 8) & 0xFF); +}; + +/* + Encodes and writes pixel data +*/ +GIFEncoder.prototype.writePixels = function() { + var enc = new LZWEncoder(this.width, this.height, this.indexedPixels, this.colorDepth); + enc.encode(this); +}; + +/* + Retrieves the GIF stream +*/ +GIFEncoder.prototype.stream = function() { + return this; +}; + +GIFEncoder.ByteCapacitor = ByteCapacitor; + +module.exports = GIFEncoder; + +}).call(this,require("buffer").Buffer) +},{"./LZWEncoder.js":126,"./TypedNeuQuant.js":127,"assert":292,"buffer":299,"events":300,"readable-stream":133,"util":523}],126:[function(require,module,exports){ +/* + LZWEncoder.js + + Authors + Kevin Weiner (original Java version - kweiner@fmsware.com) + Thibault Imbert (AS3 version - bytearray.org) + Johan Nordberg (JS version - code@johan-nordberg.com) + + Acknowledgements + GIFCOMPR.C - GIF Image compression routines + Lempel-Ziv compression based on 'compress'. GIF modifications by + David Rowley (mgardi@watdcsu.waterloo.edu) + GIF Image compression - modified 'compress' + Based on: compress.c - File compression ala IEEE Computer, June 1984. + By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) + Jim McKie (decvax!mcvax!jim) + Steve Davies (decvax!vax135!petsd!peora!srd) + Ken Turkowski (decvax!decwrl!turtlevax!ken) + James A. Woods (decvax!ihnp4!ames!jaw) + Joe Orost (decvax!vax135!petsd!joe) +*/ + +var EOF = -1; +var BITS = 12; +var HSIZE = 5003; // 80% occupancy +var masks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, + 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, + 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF]; + +function LZWEncoder(width, height, pixels, colorDepth) { + var initCodeSize = Math.max(2, colorDepth); + + var accum = new Uint8Array(256); + var htab = new Int32Array(HSIZE); + var codetab = new Int32Array(HSIZE); + + var cur_accum, cur_bits = 0; + var a_count; + var free_ent = 0; // first unused entry + var maxcode; + var remaining; + var curPixel; + var n_bits; + + // block compression parameters -- after all codes are used up, + // and compression rate changes, start over. + var clear_flg = false; + + // Algorithm: use open addressing double hashing (no chaining) on the + // prefix code / next character combination. We do a variant of Knuth's + // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime + // secondary probe. Here, the modular division first probe is gives way + // to a faster exclusive-or manipulation. Also do block compression with + // an adaptive reset, whereby the code table is cleared when the compression + // ratio decreases, but after the table fills. The variable-length output + // codes are re-sized at this point, and a special CLEAR code is generated + // for the decompressor. Late addition: construct the table according to + // file size for noticeable speed improvement on small files. Please direct + // questions about this implementation to ames!jaw. + var g_init_bits, ClearCode, EOFCode; + + // Add a character to the end of the current packet, and if it is 254 + // characters, flush the packet to disk. + function char_out(c, outs) { + accum[a_count++] = c; + if (a_count >= 254) flush_char(outs); + } + + // Clear out the hash table + // table clear for block compress + function cl_block(outs) { + cl_hash(HSIZE); + free_ent = ClearCode + 2; + clear_flg = true; + output(ClearCode, outs); + } + + // Reset code table + function cl_hash(hsize) { + for (var i = 0; i < hsize; ++i) htab[i] = -1; + } + + function compress(init_bits, outs) { + var fcode, c, i, ent, disp, hsize_reg, hshift; + + // Set up the globals: g_init_bits - initial number of bits + g_init_bits = init_bits; + + // Set up the necessary values + clear_flg = false; + n_bits = g_init_bits; + maxcode = MAXCODE(n_bits); + + ClearCode = 1 << (init_bits - 1); + EOFCode = ClearCode + 1; + free_ent = ClearCode + 2; + + a_count = 0; // clear packet + + ent = nextPixel(); + + hshift = 0; + for (fcode = HSIZE; fcode < 65536; fcode *= 2) ++hshift; + hshift = 8 - hshift; // set hash code range bound + hsize_reg = HSIZE; + cl_hash(hsize_reg); // clear hash table + + output(ClearCode, outs); + + outer_loop: while ((c = nextPixel()) != EOF) { + fcode = (c << BITS) + ent; + i = (c << hshift) ^ ent; // xor hashing + if (htab[i] === fcode) { + ent = codetab[i]; + continue; + } else if (htab[i] >= 0) { // non-empty slot + disp = hsize_reg - i; // secondary hash (after G. Knott) + if (i === 0) disp = 1; + do { + if ((i -= disp) < 0) i += hsize_reg; + if (htab[i] === fcode) { + ent = codetab[i]; + continue outer_loop; + } + } while (htab[i] >= 0); + } + output(ent, outs); + ent = c; + if (free_ent < 1 << BITS) { + codetab[i] = free_ent++; // code -> hashtable + htab[i] = fcode; + } else { + cl_block(outs); + } + } + + // Put out the final code. + output(ent, outs); + output(EOFCode, outs); + } + + function encode(outs) { + outs.writeByte(initCodeSize); // write "initial code size" byte + remaining = width * height; // reset navigation variables + curPixel = 0; + compress(initCodeSize + 1, outs); // compress and write the pixel data + outs.writeByte(0); // write block terminator + } + + // Flush the packet to disk, and reset the accumulator + function flush_char(outs) { + if (a_count > 0) { + outs.writeByte(a_count); + outs.writeBytes(accum, 0, a_count); + a_count = 0; + } + } + + function MAXCODE(n_bits) { + return (1 << n_bits) - 1; + } + + // Return the next pixel from the image + function nextPixel() { + if (remaining === 0) return EOF; + --remaining; + var pix = pixels[curPixel++]; + return pix & 0xff; + } + + function output(code, outs) { + cur_accum &= masks[cur_bits]; + + if (cur_bits > 0) cur_accum |= (code << cur_bits); + else cur_accum = code; + + cur_bits += n_bits; + + while (cur_bits >= 8) { + char_out((cur_accum & 0xff), outs); + cur_accum >>= 8; + cur_bits -= 8; + } + + // If the next entry is going to be too big for the code size, + // then increase it, if possible. + if (free_ent > maxcode || clear_flg) { + if (clear_flg) { + maxcode = MAXCODE(n_bits = g_init_bits); + clear_flg = false; + } else { + ++n_bits; + if (n_bits == BITS) maxcode = 1 << BITS; + else maxcode = MAXCODE(n_bits); + } + } + + if (code == EOFCode) { + // At EOF, write the rest of the buffer. + while (cur_bits > 0) { + char_out((cur_accum & 0xff), outs); + cur_accum >>= 8; + cur_bits -= 8; + } + flush_char(outs); + } + } + + this.encode = encode; +} + +module.exports = LZWEncoder; + +},{}],127:[function(require,module,exports){ +/* NeuQuant Neural-Net Quantization Algorithm + * ------------------------------------------ + * + * Copyright (c) 1994 Anthony Dekker + * + * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. + * See "Kohonen neural networks for optimal colour quantization" + * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367. + * for a discussion of the algorithm. + * See also http://members.ozemail.com.au/~dekker/NEUQUANT.HTML + * + * Any party obtaining a copy of these files from the author, directly or + * indirectly, is granted, free of charge, a full and unrestricted irrevocable, + * world-wide, paid up, royalty-free, nonexclusive right and license to deal + * in this software and documentation files (the "Software"), including without + * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons who receive + * copies from any such party to do so, with the only requirement being + * that this copyright notice remain intact. + * + * (JavaScript port 2012 by Johan Nordberg) + */ + +var ncycles = 100; // number of learning cycles +var netsize = 256; // number of colors used +var maxnetpos = netsize - 1; + +// defs for freq and bias +var netbiasshift = 4; // bias for colour values +var intbiasshift = 16; // bias for fractions +var intbias = (1 << intbiasshift); +var gammashift = 10; +var gamma = (1 << gammashift); +var betashift = 10; +var beta = (intbias >> betashift); /* beta = 1/1024 */ +var betagamma = (intbias << (gammashift - betashift)); + +// defs for decreasing radius factor +var initrad = (netsize >> 3); // for 256 cols, radius starts +var radiusbiasshift = 6; // at 32.0 biased by 6 bits +var radiusbias = (1 << radiusbiasshift); +var initradius = (initrad * radiusbias); //and decreases by a +var radiusdec = 30; // factor of 1/30 each cycle + +// defs for decreasing alpha factor +var alphabiasshift = 10; // alpha starts at 1.0 +var initalpha = (1 << alphabiasshift); +var alphadec; // biased by 10 bits + +/* radbias and alpharadbias used for radpower calculation */ +var radbiasshift = 8; +var radbias = (1 << radbiasshift); +var alpharadbshift = (alphabiasshift + radbiasshift); +var alpharadbias = (1 << alpharadbshift); + +// four primes near 500 - assume no image has a length so large that it is +// divisible by all four primes +var prime1 = 499; +var prime2 = 491; +var prime3 = 487; +var prime4 = 503; +var minpicturebytes = (3 * prime4); + +/* + Constructor: NeuQuant + + Arguments: + + pixels - array of pixels in RGB format + samplefac - sampling factor 1 to 30 where lower is better quality + + > + > pixels = [r, g, b, r, g, b, r, g, b, ..] + > +*/ +function NeuQuant(pixels, samplefac) { + var network; // int[netsize][4] + var netindex; // for network lookup - really 256 + + // bias and freq arrays for learning + var bias; + var freq; + var radpower; + + /* + Private Method: init + + sets up arrays + */ + function init() { + network = []; + netindex = new Int32Array(256); + bias = new Int32Array(netsize); + freq = new Int32Array(netsize); + radpower = new Int32Array(netsize >> 3); + + var i, v; + for (i = 0; i < netsize; i++) { + v = (i << (netbiasshift + 8)) / netsize; + network[i] = new Float64Array([v, v, v, 0]); + //network[i] = [v, v, v, 0] + freq[i] = intbias / netsize; + bias[i] = 0; + } + } + + /* + Private Method: unbiasnet + + unbiases network to give byte values 0..255 and record position i to prepare for sort + */ + function unbiasnet() { + for (var i = 0; i < netsize; i++) { + network[i][0] >>= netbiasshift; + network[i][1] >>= netbiasshift; + network[i][2] >>= netbiasshift; + network[i][3] = i; // record color number + } + } + + /* + Private Method: altersingle + + moves neuron *i* towards biased (b,g,r) by factor *alpha* + */ + function altersingle(alpha, i, b, g, r) { + network[i][0] -= (alpha * (network[i][0] - b)) / initalpha; + network[i][1] -= (alpha * (network[i][1] - g)) / initalpha; + network[i][2] -= (alpha * (network[i][2] - r)) / initalpha; + } + + /* + Private Method: alterneigh + + moves neurons in *radius* around index *i* towards biased (b,g,r) by factor *alpha* + */ + function alterneigh(radius, i, b, g, r) { + var lo = Math.abs(i - radius); + var hi = Math.min(i + radius, netsize); + + var j = i + 1; + var k = i - 1; + var m = 1; + + var p, a; + while ((j < hi) || (k > lo)) { + a = radpower[m++]; + + if (j < hi) { + p = network[j++]; + p[0] -= (a * (p[0] - b)) / alpharadbias; + p[1] -= (a * (p[1] - g)) / alpharadbias; + p[2] -= (a * (p[2] - r)) / alpharadbias; + } + + if (k > lo) { + p = network[k--]; + p[0] -= (a * (p[0] - b)) / alpharadbias; + p[1] -= (a * (p[1] - g)) / alpharadbias; + p[2] -= (a * (p[2] - r)) / alpharadbias; + } + } + } + + /* + Private Method: contest + + searches for biased BGR values + */ + function contest(b, g, r) { + /* + finds closest neuron (min dist) and updates freq + finds best neuron (min dist-bias) and returns position + for frequently chosen neurons, freq[i] is high and bias[i] is negative + bias[i] = gamma * ((1 / netsize) - freq[i]) + */ + + var bestd = ~(1 << 31); + var bestbiasd = bestd; + var bestpos = -1; + var bestbiaspos = bestpos; + + var i, n, dist, biasdist, betafreq; + for (i = 0; i < netsize; i++) { + n = network[i]; + + dist = Math.abs(n[0] - b) + Math.abs(n[1] - g) + Math.abs(n[2] - r); + if (dist < bestd) { + bestd = dist; + bestpos = i; + } + + biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift)); + if (biasdist < bestbiasd) { + bestbiasd = biasdist; + bestbiaspos = i; + } + + betafreq = (freq[i] >> betashift); + freq[i] -= betafreq; + bias[i] += (betafreq << gammashift); + } + + freq[bestpos] += beta; + bias[bestpos] -= betagamma; + + return bestbiaspos; + } + + /* + Private Method: inxbuild + + sorts network and builds netindex[0..255] + */ + function inxbuild() { + var i, j, p, q, smallpos, smallval, previouscol = 0, startpos = 0; + for (i = 0; i < netsize; i++) { + p = network[i]; + smallpos = i; + smallval = p[1]; // index on g + // find smallest in i..netsize-1 + for (j = i + 1; j < netsize; j++) { + q = network[j]; + if (q[1] < smallval) { // index on g + smallpos = j; + smallval = q[1]; // index on g + } + } + q = network[smallpos]; + // swap p (i) and q (smallpos) entries + if (i != smallpos) { + j = q[0]; q[0] = p[0]; p[0] = j; + j = q[1]; q[1] = p[1]; p[1] = j; + j = q[2]; q[2] = p[2]; p[2] = j; + j = q[3]; q[3] = p[3]; p[3] = j; + } + // smallval entry is now in position i + + if (smallval != previouscol) { + netindex[previouscol] = (startpos + i) >> 1; + for (j = previouscol + 1; j < smallval; j++) + netindex[j] = i; + previouscol = smallval; + startpos = i; + } + } + netindex[previouscol] = (startpos + maxnetpos) >> 1; + for (j = previouscol + 1; j < 256; j++) + netindex[j] = maxnetpos; // really 256 + } + + /* + Private Method: inxsearch + + searches for BGR values 0..255 and returns a color index + */ + function inxsearch(b, g, r) { + var a, p, dist; + + var bestd = 1000; // biggest possible dist is 256*3 + var best = -1; + + var i = netindex[g]; // index on g + var j = i - 1; // start at netindex[g] and work outwards + + while ((i < netsize) || (j >= 0)) { + if (i < netsize) { + p = network[i]; + dist = p[1] - g; // inx key + if (dist >= bestd) i = netsize; // stop iter + else { + i++; + if (dist < 0) dist = -dist; + a = p[0] - b; if (a < 0) a = -a; + dist += a; + if (dist < bestd) { + a = p[2] - r; if (a < 0) a = -a; + dist += a; + if (dist < bestd) { + bestd = dist; + best = p[3]; + } + } + } + } + if (j >= 0) { + p = network[j]; + dist = g - p[1]; // inx key - reverse dif + if (dist >= bestd) j = -1; // stop iter + else { + j--; + if (dist < 0) dist = -dist; + a = p[0] - b; if (a < 0) a = -a; + dist += a; + if (dist < bestd) { + a = p[2] - r; if (a < 0) a = -a; + dist += a; + if (dist < bestd) { + bestd = dist; + best = p[3]; + } + } + } + } + } + + return best; + } + + /* + Private Method: learn + + "Main Learning Loop" + */ + function learn() { + var i; + + var lengthcount = pixels.length; + var alphadec = 30 + ((samplefac - 1) / 3); + var samplepixels = lengthcount / (3 * samplefac); + var delta = ~~(samplepixels / ncycles); + var alpha = initalpha; + var radius = initradius; + + var rad = radius >> radiusbiasshift; + + if (rad <= 1) rad = 0; + for (i = 0; i < rad; i++) + radpower[i] = alpha * (((rad * rad - i * i) * radbias) / (rad * rad)); + + var step; + if (lengthcount < minpicturebytes) { + samplefac = 1; + step = 3; + } else if ((lengthcount % prime1) !== 0) { + step = 3 * prime1; + } else if ((lengthcount % prime2) !== 0) { + step = 3 * prime2; + } else if ((lengthcount % prime3) !== 0) { + step = 3 * prime3; + } else { + step = 3 * prime4; + } + + var b, g, r, j; + var pix = 0; // current pixel + + i = 0; + while (i < samplepixels) { + b = (pixels[pix] & 0xff) << netbiasshift; + g = (pixels[pix + 1] & 0xff) << netbiasshift; + r = (pixels[pix + 2] & 0xff) << netbiasshift; + + j = contest(b, g, r); + + altersingle(alpha, j, b, g, r); + if (rad !== 0) alterneigh(rad, j, b, g, r); // alter neighbours + + pix += step; + if (pix >= lengthcount) pix -= lengthcount; + + i++; + + if (delta === 0) delta = 1; + if (i % delta === 0) { + alpha -= alpha / alphadec; + radius -= radius / radiusdec; + rad = radius >> radiusbiasshift; + + if (rad <= 1) rad = 0; + for (j = 0; j < rad; j++) + radpower[j] = alpha * (((rad * rad - j * j) * radbias) / (rad * rad)); + } + } + } + + /* + Method: buildColormap + + 1. initializes network + 2. trains it + 3. removes misconceptions + 4. builds colorindex + */ + function buildColormap() { + init(); + learn(); + unbiasnet(); + inxbuild(); + } + this.buildColormap = buildColormap; + + /* + Method: getColormap + + builds colormap from the index + + returns array in the format: + + > + > [r, g, b, r, g, b, r, g, b, ..] + > + */ + function getColormap() { + var map = []; + var index = []; + + for (var i = 0; i < netsize; i++) + index[network[i][3]] = i; + + var k = 0; + for (var l = 0; l < netsize; l++) { + var j = index[l]; + map[k++] = (network[j][0]); + map[k++] = (network[j][1]); + map[k++] = (network[j][2]); + } + return map; + } + this.getColormap = getColormap; + + /* + Method: lookupRGB + + looks for the closest *r*, *g*, *b* color in the map and + returns its index + */ + this.lookupRGB = inxsearch; +} + +module.exports = NeuQuant; + +},{}],128:[function(require,module,exports){ +arguments[4][41][0].apply(exports,arguments) +},{"./_stream_readable":130,"./_stream_writable":132,"_process":437,"core-util-is":47,"dup":41,"inherits":359}],129:[function(require,module,exports){ +arguments[4][42][0].apply(exports,arguments) +},{"./_stream_transform":131,"core-util-is":47,"dup":42,"inherits":359}],130:[function(require,module,exports){ +(function (process){ +// 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; + +/**/ +var isArray = require('isarray'); +/**/ + + +/**/ +var Buffer = require('buffer').Buffer; +/**/ + +Readable.ReadableState = ReadableState; + +var EE = require('events').EventEmitter; + +/**/ +if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +var Stream = require('stream'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var StringDecoder; + + +/**/ +var debug = require('util'); +if (debug && debug.debuglog) { + debug = debug.debuglog('stream'); +} else { + debug = function () {}; +} +/**/ + + +util.inherits(Readable, Stream); + +function ReadableState(options, stream) { + var Duplex = require('./_stream_duplex'); + + options = options || {}; + + // 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" + var hwm = options.highWaterMark; + var defaultHwm = options.objectMode ? 16 : 16 * 1024; + this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.buffer = []; + 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 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; + + // 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; + + + // 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 (stream instanceof Duplex) + this.objectMode = this.objectMode || !!options.readableObjectMode; + + // 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'; + + // when piping, we only care about 'readable' events that happen + // after read()ing all the bytes and not getting any pushback. + this.ranOut = false; + + // 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 = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + var Duplex = require('./_stream_duplex'); + + if (!(this instanceof Readable)) + return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + Stream.call(this); +} + +// 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; + + if (util.isString(chunk) && !state.objectMode) { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = new Buffer(chunk, encoding); + encoding = ''; + } + } + + return readableAddChunk(this, state, chunk, encoding, false); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function(chunk) { + var state = this._readableState; + return readableAddChunk(this, state, chunk, '', true); +}; + +function readableAddChunk(stream, state, chunk, encoding, addToFront) { + var er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (util.isNullOrUndefined(chunk)) { + state.reading = false; + if (!state.ended) + onEofChunk(stream, state); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (state.ended && !addToFront) { + var e = new Error('stream.push() after EOF'); + stream.emit('error', e); + } else if (state.endEmitted && addToFront) { + var e = new Error('stream.unshift() after end event'); + stream.emit('error', e); + } else { + if (state.decoder && !addToFront && !encoding) + chunk = state.decoder.write(chunk); + + if (!addToFront) + state.reading = false; + + // if we want the data now, just emit it. + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } 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); + } + } else if (!addToFront) { + state.reading = false; + } + + return needMoreData(state); +} + + + +// if it's past the high water mark, we can push in some more. +// 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. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && + (state.needReadable || + state.length < state.highWaterMark || + state.length === 0); +} + +// backwards compatibility. +Readable.prototype.setEncoding = function(enc) { + if (!StringDecoder) + StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 128MB +var MAX_HWM = 0x800000; +function roundUpToNextPowerOf2(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 + n--; + for (var p = 1; p < 32; p <<= 1) n |= n >> p; + n++; + } + return n; +} + +function howMuchToRead(n, state) { + if (state.length === 0 && state.ended) + return 0; + + if (state.objectMode) + return n === 0 ? 0 : 1; + + if (isNaN(n) || util.isNull(n)) { + // only flow one buffer at a time + if (state.flowing && state.buffer.length) + return state.buffer[0].length; + else + return state.length; + } + + if (n <= 0) + return 0; + + // If we're asking for more than the target buffer level, + // then raise the water mark. Bump up to the next highest + // power of 2, to prevent increasing it excessively in tiny + // amounts. + if (n > state.highWaterMark) + state.highWaterMark = roundUpToNextPowerOf2(n); + + // don't have that much. return null, unless we've ended. + if (n > state.length) { + if (!state.ended) { + state.needReadable = true; + return 0; + } else + return state.length; + } + + return n; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function(n) { + debug('read', n); + var state = this._readableState; + var nOrig = n; + + if (!util.isNumber(n) || 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.length >= state.highWaterMark || 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); + } + + 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 (doRead && !state.reading) + n = howMuchToRead(nOrig, state); + + var ret; + if (n > 0) + ret = fromList(n, state); + else + ret = null; + + if (util.isNull(ret)) { + state.needReadable = true; + n = 0; + } + + state.length -= n; + + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (state.length === 0 && !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 && state.length === 0) + endReadable(this); + + if (!util.isNull(ret)) + this.emit('data', ret); + + return ret; +}; + +function chunkInvalid(state, chunk) { + var er = null; + if (!util.isBuffer(chunk) && + !util.isString(chunk) && + !util.isNullOrUndefined(chunk) && + !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + + +function onEofChunk(stream, state) { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + 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; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) + process.nextTick(function() { + emitReadable_(stream); + }); + else + emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + 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(function() { + maybeReadMore_(stream, state); + }); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && + state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + else + len = state.length; + } + 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) { + this.emit('error', new Error('not implemented')); +}; + +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 : cleanup; + if (state.endEmitted) + process.nextTick(endFn); + else + src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable) { + debug('onunpipe'); + if (readable === src) { + 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); + + 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', cleanup); + src.removeListener('data', ondata); + + // 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); + if (false === ret) { + debug('false write response, pause', + src._readableState.awaitDrain); + src._readableState.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 (EE.listenerCount(dest, 'error') === 0) + dest.emit('error', er); + } + // This is a brutally ugly hack to make sure that our error handler + // is attached before any userland ones. NEVER DO THIS. + if (!dest._events || !dest._events.error) + dest.on('error', onerror); + else if (isArray(dest._events.error)) + dest._events.error.unshift(onerror); + else + dest._events.error = [onerror, dest._events.error]; + + + + // 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() { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) + state.awaitDrain--; + if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + + +Readable.prototype.unpipe = function(dest) { + var state = this._readableState; + + // 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); + 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); + return this; + } + + // try to find the right one. + var i = indexOf(state.pipes, dest); + if (i === -1) + return this; + + state.pipes.splice(i, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) + state.pipes = state.pipes[0]; + + dest.emit('unpipe', this); + + 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); + + // If listening to data, and it has not explicitly been paused, + // then call resume to start the flow of data on the next tick. + if (ev === 'data' && false !== this._readableState.flowing) { + this.resume(); + } + + if (ev === 'readable' && this.readable) { + var state = this._readableState; + if (!state.readableListening) { + state.readableListening = true; + state.emittedReadable = false; + state.needReadable = true; + if (!state.reading) { + var self = this; + process.nextTick(function() { + debug('readable nexttick read 0'); + self.read(0); + }); + } else if (state.length) { + emitReadable(this, state); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +// 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'); + state.flowing = true; + if (!state.reading) { + debug('resume read 0'); + this.read(0); + } + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + process.nextTick(function() { + resume_(stream, state); + }); + } +} + +function resume_(stream, state) { + 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 (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + if (state.flowing) { + do { + var chunk = stream.read(); + } while (null !== chunk && state.flowing); + } +} + +// 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 state = this._readableState; + var paused = false; + + var self = this; + stream.on('end', function() { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) + self.push(chunk); + } + + self.push(null); + }); + + stream.on('data', function(chunk) { + debug('wrapped data'); + if (state.decoder) + chunk = state.decoder.write(chunk); + if (!chunk || !state.objectMode && !chunk.length) + return; + + var ret = self.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 (util.isFunction(stream[i]) && util.isUndefined(this[i])) { + this[i] = function(method) { return function() { + return stream[method].apply(stream, arguments); + }}(i); + } + } + + // proxy certain important events. + var events = ['error', 'close', 'destroy', 'pause', 'resume']; + forEach(events, function(ev) { + stream.on(ev, self.emit.bind(self, ev)); + }); + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + self._read = function(n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return self; +}; + + + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +function fromList(n, state) { + var list = state.buffer; + var length = state.length; + var stringMode = !!state.decoder; + var objectMode = !!state.objectMode; + var ret; + + // nothing in the list, definitely empty. + if (list.length === 0) + return null; + + if (length === 0) + ret = null; + else if (objectMode) + ret = list.shift(); + else if (!n || n >= length) { + // read it all, truncate the array. + if (stringMode) + ret = list.join(''); + else + ret = Buffer.concat(list, length); + list.length = 0; + } else { + // read just some of it. + if (n < list[0].length) { + // just take a part of the first list item. + // slice is the same for buffers and strings. + var buf = list[0]; + ret = buf.slice(0, n); + list[0] = buf.slice(n); + } else if (n === list[0].length) { + // first list is a perfect match + ret = list.shift(); + } else { + // complex case. + // we have enough to cover it, but it spans past the first buffer. + if (stringMode) + ret = ''; + else + ret = new Buffer(n); + + var c = 0; + for (var i = 0, l = list.length; i < l && c < n; i++) { + var buf = list[0]; + var cpy = Math.min(n - c, buf.length); + + if (stringMode) + ret += buf.slice(0, cpy); + else + buf.copy(ret, c, 0, cpy); + + if (cpy < buf.length) + list[0] = buf.slice(cpy); + else + list.shift(); + + c += cpy; + } + } + } + + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) + throw new Error('endReadable called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + process.nextTick(function() { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } + }); + } +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +function indexOf (xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} + +}).call(this,require('_process')) +},{"./_stream_duplex":128,"_process":437,"buffer":299,"core-util-is":47,"events":300,"inherits":359,"isarray":367,"stream":503,"string_decoder/":508,"util":35}],131:[function(require,module,exports){ +// 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 Duplex = require('./_stream_duplex'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + + +function TransformState(options, stream) { + this.afterTransform = function(er, data) { + return afterTransform(stream, er, data); + }; + + this.needTransform = false; + this.transforming = false; + this.writecb = null; + this.writechunk = null; +} + +function afterTransform(stream, er, data) { + var ts = stream._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) + return stream.emit('error', new Error('no writecb in Transform class')); + + ts.writechunk = null; + ts.writecb = null; + + if (!util.isNullOrUndefined(data)) + stream.push(data); + + if (cb) + cb(er); + + var rs = stream._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + stream._read(rs.highWaterMark); + } +} + + +function Transform(options) { + if (!(this instanceof Transform)) + return new Transform(options); + + Duplex.call(this, options); + + this._transformState = new TransformState(options, this); + + // when the writable side finishes, then flush out anything remaining. + var stream = this; + + // 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; + + this.once('prefinish', function() { + if (util.isFunction(this._flush)) + this._flush(function(er) { + done(stream, er); + }); + else + done(stream); + }); +} + +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) { + throw new Error('not implemented'); +}; + +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 (!util.isNull(ts.writechunk) && ts.writecb && !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; + } +}; + + +function done(stream, er) { + if (er) + return stream.emit('error', er); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + var ws = stream._writableState; + var ts = stream._transformState; + + if (ws.length) + throw new Error('calling transform done when ws.length != 0'); + + if (ts.transforming) + throw new Error('calling transform done when still transforming'); + + return stream.push(null); +} + +},{"./_stream_duplex":128,"core-util-is":47,"inherits":359}],132:[function(require,module,exports){ +(function (process){ +// 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, cb), and it'll handle all +// the drain event emission and buffering. + +module.exports = Writable; + +/**/ +var Buffer = require('buffer').Buffer; +/**/ + +Writable.WritableState = WritableState; + + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var Stream = require('stream'); + +util.inherits(Writable, Stream); + +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; +} + +function WritableState(options, stream) { + var Duplex = require('./_stream_duplex'); + + options = options || {}; + + // 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() + var hwm = options.highWaterMark; + var defaultHwm = options.objectMode ? 16 : 16 * 1024; + this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (stream instanceof Duplex) + this.objectMode = this.objectMode || !!options.writableObjectMode; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + 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; + + // 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.buffer = []; + + // 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; +} + +function Writable(options) { + var Duplex = require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, though they're not + // instanceof Writable, they're instanceof Readable. + if (!(this instanceof Writable) && !(this instanceof Duplex)) + return new Writable(options); + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function() { + this.emit('error', new Error('Cannot pipe. Not readable.')); +}; + + +function writeAfterEnd(stream, state, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); +} + +// If we get something that is not a buffer, string, null, or undefined, +// and we're not in objectMode, then that's an error. +// Otherwise stream chunks are all considered to be of length=1, and the +// watermarks determine how many objects to keep in the buffer, rather than +// how many bytes or characters. +function validChunk(stream, state, chunk, cb) { + var valid = true; + if (!util.isBuffer(chunk) && + !util.isString(chunk) && + !util.isNullOrUndefined(chunk) && + !state.objectMode) { + var er = new TypeError('Invalid non-string/buffer chunk'); + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); + valid = false; + } + return valid; +} + +Writable.prototype.write = function(chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + + if (util.isFunction(encoding)) { + cb = encoding; + encoding = null; + } + + if (util.isBuffer(chunk)) + encoding = 'buffer'; + else if (!encoding) + encoding = state.defaultEncoding; + + if (!util.isFunction(cb)) + cb = function() {}; + + if (state.ended) + writeAfterEnd(this, state, cb); + else if (validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function() { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function() { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && + !state.corked && + !state.finished && + !state.bufferProcessing && + state.buffer.length) + clearBuffer(this, state); + } +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && + state.decodeStrings !== false && + util.isString(chunk)) { + chunk = new Buffer(chunk, encoding); + } + return chunk; +} + +// 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, chunk, encoding, cb) { + chunk = decodeChunk(state, chunk, encoding); + if (util.isBuffer(chunk)) + encoding = 'buffer'; + 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) + state.buffer.push(new WriteReq(chunk, encoding, cb)); + 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 (writev) + stream._writev(chunk, state.onwrite); + else + stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + if (sync) + process.nextTick(function() { + state.pendingcb--; + cb(er); + }); + else { + state.pendingcb--; + cb(er); + } + + stream._writableState.errorEmitted = true; + stream.emit('error', er); +} + +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; + + 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(stream, state); + + if (!finished && + !state.corked && + !state.bufferProcessing && + state.buffer.length) { + clearBuffer(stream, state); + } + + if (sync) { + process.nextTick(function() { + 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; + + if (stream._writev && state.buffer.length > 1) { + // Fast case, write everything using _writev() + var cbs = []; + for (var c = 0; c < state.buffer.length; c++) + cbs.push(state.buffer[c].callback); + + // count the one we are adding, as well. + // TODO(isaacs) clean this up + state.pendingcb++; + doWrite(stream, state, true, state.length, state.buffer, '', function(err) { + for (var i = 0; i < cbs.length; i++) { + state.pendingcb--; + cbs[i](err); + } + }); + + // Clear buffer + state.buffer = []; + } else { + // Slow case, write chunks one-by-one + for (var c = 0; c < state.buffer.length; c++) { + var entry = state.buffer[c]; + 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); + + // 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) { + c++; + break; + } + } + + if (c < state.buffer.length) + state.buffer = state.buffer.slice(c); + else + state.buffer.length = 0; + } + + state.bufferProcessing = false; +} + +Writable.prototype._write = function(chunk, encoding, cb) { + cb(new Error('not implemented')); + +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function(chunk, encoding, cb) { + var state = this._writableState; + + if (util.isFunction(chunk)) { + cb = chunk; + chunk = null; + encoding = null; + } else if (util.isFunction(encoding)) { + cb = encoding; + encoding = null; + } + + if (!util.isNullOrUndefined(chunk)) + this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) + endWritable(this, state, cb); +}; + + +function needFinish(stream, state) { + return (state.ending && + state.length === 0 && + !state.finished && + !state.writing); +} + +function prefinish(stream, state) { + if (!state.prefinished) { + state.prefinished = true; + stream.emit('prefinish'); + } +} + +function finishMaybe(stream, state) { + var need = needFinish(stream, state); + if (need) { + if (state.pendingcb === 0) { + prefinish(stream, state); + state.finished = true; + stream.emit('finish'); + } else + prefinish(stream, state); + } + 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; +} + +}).call(this,require('_process')) +},{"./_stream_duplex":128,"_process":437,"buffer":299,"core-util-is":47,"inherits":359,"stream":503}],133:[function(require,module,exports){ +(function (process){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = require('stream'); +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); +if (!process.browser && process.env.READABLE_STREAM === 'disable') { + module.exports = require('stream'); +} + +}).call(this,require('_process')) +},{"./lib/_stream_duplex.js":128,"./lib/_stream_passthrough.js":129,"./lib/_stream_readable.js":130,"./lib/_stream_transform.js":131,"./lib/_stream_writable.js":132,"_process":437,"stream":503}],134:[function(require,module,exports){ +/*Copyrights for code authored by Yahoo Inc. is licensed under the following terms: +MIT License +Copyright 2017 Yahoo Inc. +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(window, document, navigator, undefined) { +"use strict"; + +/* + utils.js + ======== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +var utils = { + URL: window.URL || window.webkitURL || window.mozURL || window.msURL, + getUserMedia: function () { + var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; + + return getUserMedia ? getUserMedia.bind(navigator) : getUserMedia; + }(), + requestAnimFrame: window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame, + requestTimeout: function requestTimeout(callback, delay) { + callback = callback || utils.noop; + delay = delay || 0; + + if (!utils.requestAnimFrame) { + return setTimeout(callback, delay); + } + + var start = new Date().getTime(); + var handle = new Object(); + var requestAnimFrame = utils.requestAnimFrame; + + var loop = function loop() { + var current = new Date().getTime(); + var delta = current - start; + + delta >= delay ? callback.call() : handle.value = requestAnimFrame(loop); + }; + + handle.value = requestAnimFrame(loop); + + return handle; + }, + Blob: window.Blob || window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder, + btoa: function () { + var btoa = window.btoa || function (input) { + var output = ''; + var i = 0; + var l = input.length; + var key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + var chr1 = void 0; + var chr2 = void 0; + var chr3 = void 0; + var enc1 = void 0; + var enc2 = void 0; + var enc3 = void 0; + var enc4 = void 0; + + while (i < l) { + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + enc1 = chr1 >> 2; + enc2 = (chr1 & 3) << 4 | chr2 >> 4; + enc3 = (chr2 & 15) << 2 | chr3 >> 6; + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output = output + key.charAt(enc1) + key.charAt(enc2) + key.charAt(enc3) + key.charAt(enc4); + } + + return output; + }; + + return btoa ? btoa.bind(window) : utils.noop; + }(), + isObject: function isObject(obj) { + return obj && Object.prototype.toString.call(obj) === '[object Object]'; + }, + isEmptyObject: function isEmptyObject(obj) { + return utils.isObject(obj) && !Object.keys(obj).length; + }, + isArray: function isArray(arr) { + return arr && Array.isArray(arr); + }, + isFunction: function isFunction(func) { + return func && typeof func === 'function'; + }, + isElement: function isElement(elem) { + return elem && elem.nodeType === 1; + }, + isString: function isString(value) { + return typeof value === 'string' || Object.prototype.toString.call(value) === '[object String]'; + }, + isSupported: { + canvas: function canvas() { + var el = document.createElement('canvas'); + + return el && el.getContext && el.getContext('2d'); + }, + webworkers: function webworkers() { + return window.Worker; + }, + blob: function blob() { + return utils.Blob; + }, + Uint8Array: function Uint8Array() { + return window.Uint8Array; + }, + Uint32Array: function Uint32Array() { + return window.Uint32Array; + }, + videoCodecs: function () { + var testEl = document.createElement('video'); + var supportObj = { + 'mp4': false, + 'h264': false, + 'ogv': false, + 'ogg': false, + 'webm': false + }; + + try { + if (testEl && testEl.canPlayType) { + // Check for MPEG-4 support + supportObj.mp4 = testEl.canPlayType('video/mp4; codecs="mp4v.20.8"') !== ''; + + // Check for h264 support + supportObj.h264 = (testEl.canPlayType('video/mp4; codecs="avc1.42E01E"') || testEl.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) !== ''; + + // Check for Ogv support + supportObj.ogv = testEl.canPlayType('video/ogg; codecs="theora"') !== ''; + + // Check for Ogg support + supportObj.ogg = testEl.canPlayType('video/ogg; codecs="theora"') !== ''; + + // Check for Webm support + supportObj.webm = testEl.canPlayType('video/webm; codecs="vp8, vorbis"') !== -1; + } + } catch (e) {} + + return supportObj; + }() + }, + noop: function noop() {}, + each: function each(collection, callback) { + var x = void 0; + var len = void 0; + + if (utils.isArray(collection)) { + x = -1; + len = collection.length; + + while (++x < len) { + if (callback(x, collection[x]) === false) { + break; + } + } + } else if (utils.isObject(collection)) { + for (x in collection) { + if (collection.hasOwnProperty(x)) { + if (callback(x, collection[x]) === false) { + break; + } + } + } + } + }, + mergeOptions: function mergeOptions(defaultOptions, userOptions) { + if (!utils.isObject(defaultOptions) || !utils.isObject(userOptions) || !Object.keys) { + return; + } + + var newObj = {}; + + utils.each(defaultOptions, function (key, val) { + newObj[key] = defaultOptions[key]; + }); + + utils.each(userOptions, function (key, val) { + var currentUserOption = userOptions[key]; + + if (!utils.isObject(currentUserOption)) { + newObj[key] = currentUserOption; + } else { + if (!defaultOptions[key]) { + newObj[key] = currentUserOption; + } else { + newObj[key] = utils.mergeOptions(defaultOptions[key], currentUserOption); + } + } + }); + + return newObj; + }, + setCSSAttr: function setCSSAttr(elem, attr, val) { + if (!utils.isElement(elem)) { + return; + } + + if (utils.isString(attr) && utils.isString(val)) { + elem.style[attr] = val; + } else if (utils.isObject(attr)) { + utils.each(attr, function (key, val) { + elem.style[key] = val; + }); + } + }, + removeElement: function removeElement(node) { + if (!utils.isElement(node)) { + return; + } + if (node.parentNode) { + node.parentNode.removeChild(node); + } + }, + createWebWorker: function createWebWorker(content) { + if (!utils.isString(content)) { + return {}; + } + + try { + var blob = new utils.Blob([content], { + 'type': 'text/javascript' + }); + var objectUrl = utils.URL.createObjectURL(blob); + var worker = new Worker(objectUrl); + + return { + 'objectUrl': objectUrl, + 'worker': worker + }; + } catch (e) { + return '' + e; + } + }, + getExtension: function getExtension(src) { + return src.substr(src.lastIndexOf('.') + 1, src.length); + }, + getFontSize: function getFontSize() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + if (!document.body || options.resizeFont === false) { + return options.fontSize; + } + + var text = options.text; + var containerWidth = options.gifWidth; + var fontSize = parseInt(options.fontSize, 10); + var minFontSize = parseInt(options.minFontSize, 10); + var div = document.createElement('div'); + var span = document.createElement('span'); + + div.setAttribute('width', containerWidth); + div.appendChild(span); + + span.innerHTML = text; + span.style.fontSize = fontSize + 'px'; + span.style.textIndent = '-9999px'; + span.style.visibility = 'hidden'; + + document.body.appendChild(span); + + while (span.offsetWidth > containerWidth && fontSize >= minFontSize) { + span.style.fontSize = --fontSize + 'px'; + } + + document.body.removeChild(span); + + return fontSize + 'px'; + }, + webWorkerError: false +}; + + + +var utils$2 = Object.freeze({ + default: utils +}); + +/* + error.js + ======== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +var error = { + validate: function validate(skipObj) { + skipObj = utils.isObject(skipObj) ? skipObj : {}; + + var errorObj = {}; + + utils.each(error.validators, function (indece, currentValidator) { + var errorCode = currentValidator.errorCode; + + if (!skipObj[errorCode] && !currentValidator.condition) { + errorObj = currentValidator; + errorObj.error = true; + + return false; + } + }); + + delete errorObj.condition; + + return errorObj; + }, + isValid: function isValid(skipObj) { + var errorObj = error.validate(skipObj); + var isValid = errorObj.error !== true ? true : false; + + return isValid; + }, + validators: [{ + condition: utils.isFunction(utils.getUserMedia), + errorCode: 'getUserMedia', + errorMsg: 'The getUserMedia API is not supported in your browser' + }, { + condition: utils.isSupported.canvas(), + errorCode: 'canvas', + errorMsg: 'Canvas elements are not supported in your browser' + }, { + condition: utils.isSupported.webworkers(), + errorCode: 'webworkers', + errorMsg: 'The Web Workers API is not supported in your browser' + }, { + condition: utils.isFunction(utils.URL), + errorCode: 'window.URL', + errorMsg: 'The window.URL API is not supported in your browser' + }, { + condition: utils.isSupported.blob(), + errorCode: 'window.Blob', + errorMsg: 'The window.Blob File API is not supported in your browser' + }, { + condition: utils.isSupported.Uint8Array(), + errorCode: 'window.Uint8Array', + errorMsg: 'The window.Uint8Array function constructor is not supported in your browser' + }, { + condition: utils.isSupported.Uint32Array(), + errorCode: 'window.Uint32Array', + errorMsg: 'The window.Uint32Array function constructor is not supported in your browser' + }], + messages: { + videoCodecs: { + errorCode: 'videocodec', + errorMsg: 'The video codec you are trying to use is not supported in your browser' + } + } +}; + + + +var error$2 = Object.freeze({ + default: error +}); + +/* + defaultOptions.js + ================= +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Helpers +var noop = function noop() {}; + +var defaultOptions = { + sampleInterval: 10, + numWorkers: 2, + filter: '', + gifWidth: 200, + gifHeight: 200, + interval: 0.1, + numFrames: 10, + frameDuration: 1, + keepCameraOn: false, + images: [], + video: null, + webcamVideoElement: null, + cameraStream: null, + text: '', + fontWeight: 'normal', + fontSize: '16px', + minFontSize: '10px', + resizeFont: false, + fontFamily: 'sans-serif', + fontColor: '#ffffff', + textAlign: 'center', + textBaseline: 'bottom', + textXCoordinate: null, + textYCoordinate: null, + progressCallback: noop, + completeCallback: noop, + saveRenderingContexts: false, + savedRenderingContexts: [], + crossOrigin: 'Anonymous' +}; + + + +var defaultOptions$2 = Object.freeze({ + default: defaultOptions +}); + +/* + isSupported.js + ============== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +function isSupported() { + return error.isValid(); +} + +/* + isWebCamGIFSupported.js + ======================= +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +function isWebCamGIFSupported() { + return error.isValid(); +} + +/* + isSupported.js + ============== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +function isSupported$1() { + var options = { + getUserMedia: true + }; + + return error.isValid(options); +} + +/* + isExistingVideoGIFSupported.js + ============================== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +function isExistingVideoGIFSupported(codecs) { + var hasValidCodec = false; + + if (utils.isArray(codecs) && codecs.length) { + utils.each(codecs, function (indece, currentCodec) { + if (utils.isSupported.videoCodecs[currentCodec]) { + hasValidCodec = true; + } + }); + + if (!hasValidCodec) { + return false; + } + } else if (utils.isString(codecs) && codecs.length) { + if (!utils.isSupported.videoCodecs[codecs]) { + return false; + } + } + + return error.isValid({ + 'getUserMedia': true + }); +} + +/* + NeuQuant.js + =========== +*/ + +/* + * NeuQuant Neural-Net Quantization Algorithm + * ------------------------------------------ + * + * Copyright (c) 1994 Anthony Dekker + * + * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See + * "Kohonen neural networks for optimal colour quantization" in "Network: + * Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of + * the algorithm. + * + * Any party obtaining a copy of these files from the author, directly or + * indirectly, is granted, free of charge, a full and unrestricted irrevocable, + * world-wide, paid up, royalty-free, nonexclusive right and license to deal in + * this software and documentation files (the "Software"), including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons who + * receive copies from any such party to do so, with the only requirement being + * that this copyright notice remain intact. + */ + +/* + * This class handles Neural-Net quantization algorithm + * @author Kevin Weiner (original Java version - kweiner@fmsware.com) + * @author Thibault Imbert (AS3 version - bytearray.org) + * @version 0.1 AS3 implementation + * @version 0.2 JS->AS3 "translation" by antimatter15 + * @version 0.3 JS clean up + using modern JS idioms by sole - http://soledadpenades.com + * Also implement fix in color conversion described at http://stackoverflow.com/questions/16371712/neuquant-js-javascript-color-quantization-hidden-bug-in-js-conversion + */ + +function NeuQuant() { + var netsize = 256; // number of colours used + + // four primes near 500 - assume no image has a length so large + // that it is divisible by all four primes + var prime1 = 499; + var prime2 = 491; + var prime3 = 487; + var prime4 = 503; + + // minimum size for input image + var minpicturebytes = 3 * prime4; + + // Network Definitions + + var maxnetpos = netsize - 1; + var netbiasshift = 4; // bias for colour values + var ncycles = 100; // no. of learning cycles + + // defs for freq and bias + var intbiasshift = 16; // bias for fractions + var intbias = 1 << intbiasshift; + var gammashift = 10; // gamma = 1024 + var gamma = 1 << gammashift; + var betashift = 10; + var beta = intbias >> betashift; // beta = 1/1024 + var betagamma = intbias << gammashift - betashift; + + // defs for decreasing radius factor + // For 256 colors, radius starts at 32.0 biased by 6 bits + // and decreases by a factor of 1/30 each cycle + var initrad = netsize >> 3; + var radiusbiasshift = 6; + var radiusbias = 1 << radiusbiasshift; + var initradius = initrad * radiusbias; + var radiusdec = 30; + + // defs for decreasing alpha factor + // Alpha starts at 1.0 biased by 10 bits + var alphabiasshift = 10; + var initalpha = 1 << alphabiasshift; + var alphadec; + + // radbias and alpharadbias used for radpower calculation + var radbiasshift = 8; + var radbias = 1 << radbiasshift; + var alpharadbshift = alphabiasshift + radbiasshift; + var alpharadbias = 1 << alpharadbshift; + + // Input image + var thepicture; + // Height * Width * 3 + var lengthcount; + // Sampling factor 1..30 + var samplefac; + + // The network itself + var network; + var netindex = []; + + // for network lookup - really 256 + var bias = []; + + // bias and freq arrays for learning + var freq = []; + var radpower = []; + + function NeuQuantConstructor(thepic, len, sample) { + + var i; + var p; + + thepicture = thepic; + lengthcount = len; + samplefac = sample; + + network = new Array(netsize); + + for (i = 0; i < netsize; i++) { + network[i] = new Array(4); + p = network[i]; + p[0] = p[1] = p[2] = (i << netbiasshift + 8) / netsize | 0; + freq[i] = intbias / netsize | 0; // 1 / netsize + bias[i] = 0; + } + } + + function colorMap() { + var map = []; + var index = new Array(netsize); + for (var i = 0; i < netsize; i++) { + index[network[i][3]] = i; + }var k = 0; + for (var l = 0; l < netsize; l++) { + var j = index[l]; + map[k++] = network[j][0]; + map[k++] = network[j][1]; + map[k++] = network[j][2]; + } + return map; + } + + // Insertion sort of network and building of netindex[0..255] + // (to do after unbias) + function inxbuild() { + var i; + var j; + var smallpos; + var smallval; + var p; + var q; + var previouscol; + var startpos; + + previouscol = 0; + startpos = 0; + + for (i = 0; i < netsize; i++) { + + p = network[i]; + smallpos = i; + smallval = p[1]; // index on g + // find smallest in i..netsize-1 + for (j = i + 1; j < netsize; j++) { + + q = network[j]; + + if (q[1] < smallval) { + // index on g + smallpos = j; + smallval = q[1]; // index on g + } + } + + q = network[smallpos]; + + // swap p (i) and q (smallpos) entries + if (i != smallpos) { + j = q[0]; + q[0] = p[0]; + p[0] = j; + j = q[1]; + q[1] = p[1]; + p[1] = j; + j = q[2]; + q[2] = p[2]; + p[2] = j; + j = q[3]; + q[3] = p[3]; + p[3] = j; + } + + // smallval entry is now in position i + if (smallval != previouscol) { + + netindex[previouscol] = startpos + i >> 1; + + for (j = previouscol + 1; j < smallval; j++) { + netindex[j] = i; + } + + previouscol = smallval; + startpos = i; + } + } + + netindex[previouscol] = startpos + maxnetpos >> 1; + for (j = previouscol + 1; j < 256; j++) { + netindex[j] = maxnetpos; // really 256 + } + } + + // Main Learning Loop + + function learn() { + var i; + var j; + var b; + var g; + var r; + var radius; + var rad; + var alpha; + var step; + var delta; + var samplepixels; + var p; + var pix; + var lim; + + if (lengthcount < minpicturebytes) { + samplefac = 1; + } + + alphadec = 30 + (samplefac - 1) / 3; + p = thepicture; + pix = 0; + lim = lengthcount; + samplepixels = lengthcount / (3 * samplefac); + delta = samplepixels / ncycles | 0; + alpha = initalpha; + radius = initradius; + + rad = radius >> radiusbiasshift; + if (rad <= 1) { + rad = 0; + } + + for (i = 0; i < rad; i++) { + radpower[i] = alpha * ((rad * rad - i * i) * radbias / (rad * rad)); + } + + if (lengthcount < minpicturebytes) { + step = 3; + } else if (lengthcount % prime1 !== 0) { + step = 3 * prime1; + } else { + + if (lengthcount % prime2 !== 0) { + step = 3 * prime2; + } else { + if (lengthcount % prime3 !== 0) { + step = 3 * prime3; + } else { + step = 3 * prime4; + } + } + } + + i = 0; + + while (i < samplepixels) { + + b = (p[pix + 0] & 0xff) << netbiasshift; + g = (p[pix + 1] & 0xff) << netbiasshift; + r = (p[pix + 2] & 0xff) << netbiasshift; + j = contest(b, g, r); + + altersingle(alpha, j, b, g, r); + + if (rad !== 0) { + // Alter neighbours + alterneigh(rad, j, b, g, r); + } + + pix += step; + + if (pix >= lim) { + pix -= lengthcount; + } + + i++; + + if (delta === 0) { + delta = 1; + } + + if (i % delta === 0) { + alpha -= alpha / alphadec; + radius -= radius / radiusdec; + rad = radius >> radiusbiasshift; + + if (rad <= 1) { + rad = 0; + } + + for (j = 0; j < rad; j++) { + radpower[j] = alpha * ((rad * rad - j * j) * radbias / (rad * rad)); + } + } + } + } + + // Search for BGR values 0..255 (after net is unbiased) and return colour index + function map(b, g, r) { + var i; + var j; + var dist; + var a; + var bestd; + var p; + var best; + + // Biggest possible distance is 256 * 3 + bestd = 1000; + best = -1; + i = netindex[g]; // index on g + j = i - 1; // start at netindex[g] and work outwards + + while (i < netsize || j >= 0) { + + if (i < netsize) { + + p = network[i]; + + dist = p[1] - g; // inx key + + if (dist >= bestd) { + i = netsize; // stop iter + } else { + + i++; + + if (dist < 0) { + dist = -dist; + } + + a = p[0] - b; + + if (a < 0) { + a = -a; + } + + dist += a; + + if (dist < bestd) { + a = p[2] - r; + + if (a < 0) { + a = -a; + } + + dist += a; + + if (dist < bestd) { + bestd = dist; + best = p[3]; + } + } + } + } + + if (j >= 0) { + + p = network[j]; + + dist = g - p[1]; // inx key - reverse dif + + if (dist >= bestd) { + j = -1; // stop iter + } else { + + j--; + if (dist < 0) { + dist = -dist; + } + a = p[0] - b; + if (a < 0) { + a = -a; + } + dist += a; + + if (dist < bestd) { + a = p[2] - r; + if (a < 0) { + a = -a; + } + dist += a; + if (dist < bestd) { + bestd = dist; + best = p[3]; + } + } + } + } + } + + return best; + } + + function process() { + learn(); + unbiasnet(); + inxbuild(); + return colorMap(); + } + + // Unbias network to give byte values 0..255 and record position i + // to prepare for sort + function unbiasnet() { + var i; + var j; + + for (i = 0; i < netsize; i++) { + network[i][0] >>= netbiasshift; + network[i][1] >>= netbiasshift; + network[i][2] >>= netbiasshift; + network[i][3] = i; // record colour no + } + } + + // Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) + // in radpower[|i-j|] + function alterneigh(rad, i, b, g, r) { + + var j; + var k; + var lo; + var hi; + var a; + var m; + + var p; + + lo = i - rad; + if (lo < -1) { + lo = -1; + } + + hi = i + rad; + + if (hi > netsize) { + hi = netsize; + } + + j = i + 1; + k = i - 1; + m = 1; + + while (j < hi || k > lo) { + + a = radpower[m++]; + + if (j < hi) { + + p = network[j++]; + + try { + + p[0] -= a * (p[0] - b) / alpharadbias | 0; + p[1] -= a * (p[1] - g) / alpharadbias | 0; + p[2] -= a * (p[2] - r) / alpharadbias | 0; + } catch (e) {} + } + + if (k > lo) { + + p = network[k--]; + + try { + + p[0] -= a * (p[0] - b) / alpharadbias | 0; + p[1] -= a * (p[1] - g) / alpharadbias | 0; + p[2] -= a * (p[2] - r) / alpharadbias | 0; + } catch (e) {} + } + } + } + + // Move neuron i towards biased (b,g,r) by factor alpha + function altersingle(alpha, i, b, g, r) { + + // alter hit neuron + var n = network[i]; + var alphaMult = alpha / initalpha; + n[0] -= alphaMult * (n[0] - b) | 0; + n[1] -= alphaMult * (n[1] - g) | 0; + n[2] -= alphaMult * (n[2] - r) | 0; + } + + // Search for biased BGR values + function contest(b, g, r) { + + // finds closest neuron (min dist) and updates freq + // finds best neuron (min dist-bias) and returns position + // for frequently chosen neurons, freq[i] is high and bias[i] is negative + // bias[i] = gamma*((1/netsize)-freq[i]) + + var i; + var dist; + var a; + var biasdist; + var betafreq; + var bestpos; + var bestbiaspos; + var bestd; + var bestbiasd; + var n; + + bestd = ~(1 << 31); + bestbiasd = bestd; + bestpos = -1; + bestbiaspos = bestpos; + + for (i = 0; i < netsize; i++) { + + n = network[i]; + dist = n[0] - b; + + if (dist < 0) { + dist = -dist; + } + + a = n[1] - g; + + if (a < 0) { + a = -a; + } + + dist += a; + + a = n[2] - r; + + if (a < 0) { + a = -a; + } + + dist += a; + + if (dist < bestd) { + bestd = dist; + bestpos = i; + } + + biasdist = dist - (bias[i] >> intbiasshift - netbiasshift); + + if (biasdist < bestbiasd) { + bestbiasd = biasdist; + bestbiaspos = i; + } + + betafreq = freq[i] >> betashift; + freq[i] -= betafreq; + bias[i] += betafreq << gammashift; + } + + freq[bestpos] += beta; + bias[bestpos] -= betagamma; + return bestbiaspos; + } + + NeuQuantConstructor.apply(this, arguments); + + var exports = {}; + exports.map = map; + exports.process = process; + + return exports; +} + +/* + processFrameWorker.js + ===================== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +function workerCode() { + var self = this; + + try { + self.onmessage = function (ev) { + var data = ev.data || {}; + var response; + + if (data.gifshot) { + response = workerMethods.run(data); + postMessage(response); + } + }; + } catch (e) {} + + var workerMethods = { + dataToRGB: function dataToRGB(data, width, height) { + var length = width * height * 4; + var i = 0; + var rgb = []; + + while (i < length) { + rgb.push(data[i++]); + rgb.push(data[i++]); + rgb.push(data[i++]); + i++; // for the alpha channel which we don't care about + } + + return rgb; + }, + componentizedPaletteToArray: function componentizedPaletteToArray(paletteRGB) { + paletteRGB = paletteRGB || []; + + var paletteArray = []; + + for (var i = 0; i < paletteRGB.length; i += 3) { + var r = paletteRGB[i]; + var g = paletteRGB[i + 1]; + var b = paletteRGB[i + 2]; + + paletteArray.push(r << 16 | g << 8 | b); + } + + return paletteArray; + }, + // This is the "traditional" Animated_GIF style of going from RGBA to indexed color frames + 'processFrameWithQuantizer': function processFrameWithQuantizer(imageData, width, height, sampleInterval) { + var rgbComponents = this.dataToRGB(imageData, width, height); + var nq = new NeuQuant(rgbComponents, rgbComponents.length, sampleInterval); + var paletteRGB = nq.process(); + var paletteArray = new Uint32Array(this.componentizedPaletteToArray(paletteRGB)); + var numberPixels = width * height; + var indexedPixels = new Uint8Array(numberPixels); + var k = 0; + + for (var i = 0; i < numberPixels; i++) { + var r = rgbComponents[k++]; + var g = rgbComponents[k++]; + var b = rgbComponents[k++]; + + indexedPixels[i] = nq.map(r, g, b); + } + + return { + pixels: indexedPixels, + palette: paletteArray + }; + }, + 'run': function run(frame) { + frame = frame || {}; + + var _frame = frame, + height = _frame.height, + palette = _frame.palette, + sampleInterval = _frame.sampleInterval, + width = _frame.width; + + var imageData = frame.data; + + return this.processFrameWithQuantizer(imageData, width, height, sampleInterval); + } + }; + + return workerMethods; +} + +/* + gifWriter.js + ============ +*/ + +// (c) Dean McNamee , 2013. +// +// https://github.com/deanm/omggif +// +// 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. +// +// omggif is a JavaScript implementation of a GIF 89a encoder and decoder, +// including animation and compression. It does not rely on any specific +// underlying system, so should run in the browser, Node, or Plask. + +function gifWriter(buf, width, height, gopts) { + var p = 0; + + gopts = gopts === undefined ? {} : gopts; + var loop_count = gopts.loop === undefined ? null : gopts.loop; + var global_palette = gopts.palette === undefined ? null : gopts.palette; + + if (width <= 0 || height <= 0 || width > 65535 || height > 65535) throw "Width/Height invalid."; + + function check_palette_and_num_colors(palette) { + var num_colors = palette.length; + + if (num_colors < 2 || num_colors > 256 || num_colors & num_colors - 1) throw "Invalid code/color length, must be power of 2 and 2 .. 256."; + return num_colors; + } + + // - Header. + buf[p++] = 0x47; + buf[p++] = 0x49; + buf[p++] = 0x46; // GIF + buf[p++] = 0x38; + buf[p++] = 0x39; + buf[p++] = 0x61; // 89a + + // Handling of Global Color Table (palette) and background index. + var gp_num_colors_pow2 = 0; + var background = 0; + + // - Logical Screen Descriptor. + // NOTE(deanm): w/h apparently ignored by implementations, but set anyway. + buf[p++] = width & 0xff; + buf[p++] = width >> 8 & 0xff; + buf[p++] = height & 0xff; + buf[p++] = height >> 8 & 0xff; + // NOTE: Indicates 0-bpp original color resolution (unused?). + buf[p++] = (global_palette !== null ? 0x80 : 0) | // Global Color Table Flag. + gp_num_colors_pow2; // NOTE: No sort flag (unused?). + buf[p++] = background; // Background Color Index. + buf[p++] = 0; // Pixel aspect ratio (unused?). + + if (loop_count !== null) { + // Netscape block for looping. + if (loop_count < 0 || loop_count > 65535) throw "Loop count invalid."; + + // Extension code, label, and length. + buf[p++] = 0x21; + buf[p++] = 0xff; + buf[p++] = 0x0b; + // NETSCAPE2.0 + buf[p++] = 0x4e; + buf[p++] = 0x45; + buf[p++] = 0x54; + buf[p++] = 0x53; + buf[p++] = 0x43; + buf[p++] = 0x41; + buf[p++] = 0x50; + buf[p++] = 0x45; + buf[p++] = 0x32; + buf[p++] = 0x2e; + buf[p++] = 0x30; + // Sub-block + buf[p++] = 0x03; + buf[p++] = 0x01; + buf[p++] = loop_count & 0xff; + buf[p++] = loop_count >> 8 & 0xff; + buf[p++] = 0x00; // Terminator. + } + + var ended = false; + + this.addFrame = function (x, y, w, h, indexed_pixels, opts) { + if (ended === true) { + --p; + ended = false; + } // Un-end. + + opts = opts === undefined ? {} : opts; + + // TODO(deanm): Bounds check x, y. Do they need to be within the virtual + // canvas width/height, I imagine? + if (x < 0 || y < 0 || x > 65535 || y > 65535) throw "x/y invalid."; + + if (w <= 0 || h <= 0 || w > 65535 || h > 65535) throw "Width/Height invalid."; + + if (indexed_pixels.length < w * h) throw "Not enough pixels for the frame size."; + + var using_local_palette = true; + var palette = opts.palette; + if (palette === undefined || palette === null) { + using_local_palette = false; + palette = global_palette; + } + + if (palette === undefined || palette === null) throw "Must supply either a local or global palette."; + + var num_colors = check_palette_and_num_colors(palette); + + // Compute the min_code_size (power of 2), destroying num_colors. + var min_code_size = 0; + while (num_colors >>= 1) { + ++min_code_size; + }num_colors = 1 << min_code_size; // Now we can easily get it back. + + var delay = opts.delay === undefined ? 0 : opts.delay; + + // From the spec: + // 0 - No disposal specified. The decoder is + // not required to take any action. + // 1 - Do not dispose. The graphic is to be left + // in place. + // 2 - Restore to background color. The area used by the + // graphic must be restored to the background color. + // 3 - Restore to previous. The decoder is required to + // restore the area overwritten by the graphic with + // what was there prior to rendering the graphic. + // 4-7 - To be defined. + // NOTE(deanm): Dispose background doesn't really work, apparently most + // browsers ignore the background palette index and clear to transparency. + var disposal = opts.disposal === undefined ? 0 : opts.disposal; + if (disposal < 0 || disposal > 3) // 4-7 is reserved. + throw "Disposal out of range."; + + var use_transparency = false; + var transparent_index = 0; + if (opts.transparent !== undefined && opts.transparent !== null) { + use_transparency = true; + transparent_index = opts.transparent; + if (transparent_index < 0 || transparent_index >= num_colors) throw "Transparent color index."; + } + + if (disposal !== 0 || use_transparency || delay !== 0) { + // - Graphics Control Extension + buf[p++] = 0x21; + buf[p++] = 0xf9; // Extension / Label. + buf[p++] = 4; // Byte size. + + buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0); + buf[p++] = delay & 0xff; + buf[p++] = delay >> 8 & 0xff; + buf[p++] = transparent_index; // Transparent color index. + buf[p++] = 0; // Block Terminator. + } + + // - Image Descriptor + buf[p++] = 0x2c; // Image Seperator. + buf[p++] = x & 0xff; + buf[p++] = x >> 8 & 0xff; // Left. + buf[p++] = y & 0xff; + buf[p++] = y >> 8 & 0xff; // Top. + buf[p++] = w & 0xff; + buf[p++] = w >> 8 & 0xff; + buf[p++] = h & 0xff; + buf[p++] = h >> 8 & 0xff; + // NOTE: No sort flag (unused?). + // TODO(deanm): Support interlace. + buf[p++] = using_local_palette === true ? 0x80 | min_code_size - 1 : 0; + + // - Local Color Table + if (using_local_palette === true) { + for (var i = 0, il = palette.length; i < il; ++i) { + var rgb = palette[i]; + buf[p++] = rgb >> 16 & 0xff; + buf[p++] = rgb >> 8 & 0xff; + buf[p++] = rgb & 0xff; + } + } + + p = GifWriterOutputLZWCodeStream(buf, p, min_code_size < 2 ? 2 : min_code_size, indexed_pixels); + }; + + this.end = function () { + if (ended === false) { + buf[p++] = 0x3b; // Trailer. + ended = true; + } + return p; + }; + + // Main compression routine, palette indexes -> LZW code stream. + // |index_stream| must have at least one entry. + function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) { + buf[p++] = min_code_size; + var cur_subblock = p++; // Pointing at the length field. + + var clear_code = 1 << min_code_size; + var code_mask = clear_code - 1; + var eoi_code = clear_code + 1; + var next_code = eoi_code + 1; + + var cur_code_size = min_code_size + 1; // Number of bits per code. + var cur_shift = 0; + // We have at most 12-bit codes, so we should have to hold a max of 19 + // bits here (and then we would write out). + var cur = 0; + + function emit_bytes_to_buffer(bit_block_size) { + while (cur_shift >= bit_block_size) { + buf[p++] = cur & 0xff; + cur >>= 8; + cur_shift -= 8; + if (p === cur_subblock + 256) { + // Finished a subblock. + buf[cur_subblock] = 255; + cur_subblock = p++; + } + } + } + + function emit_code(c) { + cur |= c << cur_shift; + cur_shift += cur_code_size; + emit_bytes_to_buffer(8); + } + + // I am not an expert on the topic, and I don't want to write a thesis. + // However, it is good to outline here the basic algorithm and the few data + // structures and optimizations here that make this implementation fast. + // The basic idea behind LZW is to build a table of previously seen runs + // addressed by a short id (herein called output code). All data is + // referenced by a code, which represents one or more values from the + // original input stream. All input bytes can be referenced as the same + // value as an output code. So if you didn't want any compression, you + // could more or less just output the original bytes as codes (there are + // some details to this, but it is the idea). In order to achieve + // compression, values greater then the input range (codes can be up to + // 12-bit while input only 8-bit) represent a sequence of previously seen + // inputs. The decompressor is able to build the same mapping while + // decoding, so there is always a shared common knowledge between the + // encoding and decoder, which is also important for "timing" aspects like + // how to handle variable bit width code encoding. + // + // One obvious but very important consequence of the table system is there + // is always a unique id (at most 12-bits) to map the runs. 'A' might be + // 4, then 'AA' might be 10, 'AAA' 11, 'AAAA' 12, etc. This relationship + // can be used for an effecient lookup strategy for the code mapping. We + // need to know if a run has been seen before, and be able to map that run + // to the output code. Since we start with known unique ids (input bytes), + // and then from those build more unique ids (table entries), we can + // continue this chain (almost like a linked list) to always have small + // integer values that represent the current byte chains in the encoder. + // This means instead of tracking the input bytes (AAAABCD) to know our + // current state, we can track the table entry for AAAABC (it is guaranteed + // to exist by the nature of the algorithm) and the next character D. + // Therefor the tuple of (table_entry, byte) is guaranteed to also be + // unique. This allows us to create a simple lookup key for mapping input + // sequences to codes (table indices) without having to store or search + // any of the code sequences. So if 'AAAA' has a table entry of 12, the + // tuple of ('AAAA', K) for any input byte K will be unique, and can be our + // key. This leads to a integer value at most 20-bits, which can always + // fit in an SMI value and be used as a fast sparse array / object key. + + // Output code for the current contents of the index buffer. + var ib_code = index_stream[0] & code_mask; // Load first input index. + var code_table = {}; // Key'd on our 20-bit "tuple". + + emit_code(clear_code); // Spec says first code should be a clear code. + + // First index already loaded, process the rest of the stream. + for (var i = 1, il = index_stream.length; i < il; ++i) { + var k = index_stream[i] & code_mask; + var cur_key = ib_code << 8 | k; // (prev, k) unique tuple. + var cur_code = code_table[cur_key]; // buffer + k. + + // Check if we have to create a new code table entry. + if (cur_code === undefined) { + // We don't have buffer + k. + // Emit index buffer (without k). + // This is an inline version of emit_code, because this is the core + // writing routine of the compressor (and V8 cannot inline emit_code + // because it is a closure here in a different context). Additionally + // we can call emit_byte_to_buffer less often, because we can have + // 30-bits (from our 31-bit signed SMI), and we know our codes will only + // be 12-bits, so can safely have 18-bits there without overflow. + // emit_code(ib_code); + cur |= ib_code << cur_shift; + cur_shift += cur_code_size; + while (cur_shift >= 8) { + buf[p++] = cur & 0xff; + cur >>= 8; + cur_shift -= 8; + if (p === cur_subblock + 256) { + // Finished a subblock. + buf[cur_subblock] = 255; + cur_subblock = p++; + } + } + + if (next_code === 4096) { + // Table full, need a clear. + emit_code(clear_code); + next_code = eoi_code + 1; + cur_code_size = min_code_size + 1; + code_table = {}; + } else { + // Table not full, insert a new entry. + // Increase our variable bit code sizes if necessary. This is a bit + // tricky as it is based on "timing" between the encoding and + // decoder. From the encoders perspective this should happen after + // we've already emitted the index buffer and are about to create the + // first table entry that would overflow our current code bit size. + if (next_code >= 1 << cur_code_size) ++cur_code_size; + code_table[cur_key] = next_code++; // Insert into code table. + } + + ib_code = k; // Index buffer to single input k. + } else { + ib_code = cur_code; // Index buffer to sequence in code table. + } + } + + emit_code(ib_code); // There will still be something in the index buffer. + emit_code(eoi_code); // End Of Information. + + // Flush / finalize the sub-blocks stream to the buffer. + emit_bytes_to_buffer(1); + + // Finish the sub-blocks, writing out any unfinished lengths and + // terminating with a sub-block of length 0. If we have already started + // but not yet used a sub-block it can just become the terminator. + if (cur_subblock + 1 === p) { + // Started but unused. + buf[cur_subblock] = 0; + } else { + // Started and used, write length and additional terminator block. + buf[cur_subblock] = p - cur_subblock - 1; + buf[p++] = 0; + } + return p; + } +} + +/* + animatedGIF.js + ============== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +// Helpers +var noop$2 = function noop() {}; + +var AnimatedGIF = function AnimatedGIF(options) { + this.canvas = null; + this.ctx = null; + this.repeat = 0; + this.frames = []; + this.numRenderedFrames = 0; + this.onRenderCompleteCallback = noop$2; + this.onRenderProgressCallback = noop$2; + this.workers = []; + this.availableWorkers = []; + this.generatingGIF = false; + this.options = options; + + // Constructs and initializes the the web workers appropriately + this.initializeWebWorkers(options); +}; + +AnimatedGIF.prototype = { + 'workerMethods': workerCode(), + 'initializeWebWorkers': function initializeWebWorkers(options) { + var self = this; + var processFrameWorkerCode = NeuQuant.toString() + '(' + workerCode.toString() + '());'; + var webWorkerObj = void 0; + var objectUrl = void 0; + var webWorker = void 0; + var numWorkers = void 0; + var x = -1; + var workerError = ''; + + numWorkers = options.numWorkers; + + while (++x < numWorkers) { + webWorkerObj = utils.createWebWorker(processFrameWorkerCode); + + if (utils.isObject(webWorkerObj)) { + objectUrl = webWorkerObj.objectUrl; + webWorker = webWorkerObj.worker; + + self.workers.push({ + worker: webWorker, + objectUrl: objectUrl + }); + + self.availableWorkers.push(webWorker); + } else { + workerError = webWorkerObj; + utils.webWorkerError = !!webWorkerObj; + } + } + + this.workerError = workerError; + this.canvas = document.createElement('canvas'); + this.canvas.width = options.gifWidth; + this.canvas.height = options.gifHeight; + this.ctx = this.canvas.getContext('2d'); + this.frames = []; + }, + // Return a worker for processing a frame + getWorker: function getWorker() { + return this.availableWorkers.pop(); + }, + // Restores a worker to the pool + freeWorker: function freeWorker(worker) { + this.availableWorkers.push(worker); + }, + byteMap: function () { + var byteMap = []; + + for (var i = 0; i < 256; i++) { + byteMap[i] = String.fromCharCode(i); + } + + return byteMap; + }(), + bufferToString: function bufferToString(buffer) { + var numberValues = buffer.length; + var str = ''; + var x = -1; + + while (++x < numberValues) { + str += this.byteMap[buffer[x]]; + } + + return str; + }, + onFrameFinished: function onFrameFinished(progressCallback) { + // The GIF is not written until we're done with all the frames + // because they might not be processed in the same order + var self = this; + var frames = self.frames; + var options = self.options; + var hasExistingImages = !!(options.images || []).length; + var allDone = frames.every(function (frame) { + return !frame.beingProcessed && frame.done; + }); + + self.numRenderedFrames++; + + if (hasExistingImages) { + progressCallback(self.numRenderedFrames / frames.length); + } + + self.onRenderProgressCallback(self.numRenderedFrames * 0.75 / frames.length); + + if (allDone) { + if (!self.generatingGIF) { + self.generateGIF(frames, self.onRenderCompleteCallback); + } + } else { + utils.requestTimeout(function () { + self.processNextFrame(); + }, 1); + } + }, + processFrame: function processFrame(position) { + var AnimatedGifContext = this; + var options = this.options; + var _options = this.options, + progressCallback = _options.progressCallback, + sampleInterval = _options.sampleInterval; + + var frames = this.frames; + var frame = void 0; + var worker = void 0; + var done = function done() { + var ev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var data = ev.data; + + // Delete original data, and free memory + delete frame.data; + + frame.pixels = Array.prototype.slice.call(data.pixels); + frame.palette = Array.prototype.slice.call(data.palette); + frame.done = true; + frame.beingProcessed = false; + + AnimatedGifContext.freeWorker(worker); + + AnimatedGifContext.onFrameFinished(progressCallback); + }; + + frame = frames[position]; + + if (frame.beingProcessed || frame.done) { + this.onFrameFinished(); + + return; + } + + frame.sampleInterval = sampleInterval; + frame.beingProcessed = true; + frame.gifshot = true; + + worker = this.getWorker(); + + if (worker) { + // Process the frame in a web worker + worker.onmessage = done; + worker.postMessage(frame); + } else { + // Process the frame in the current thread + done({ + 'data': AnimatedGifContext.workerMethods.run(frame) + }); + } + }, + startRendering: function startRendering(completeCallback) { + this.onRenderCompleteCallback = completeCallback; + + for (var i = 0; i < this.options.numWorkers && i < this.frames.length; i++) { + this.processFrame(i); + } + }, + processNextFrame: function processNextFrame() { + var position = -1; + + for (var i = 0; i < this.frames.length; i++) { + var frame = this.frames[i]; + + if (!frame.done && !frame.beingProcessed) { + position = i; + break; + } + } + + if (position >= 0) { + this.processFrame(position); + } + }, + // Takes the already processed data in frames and feeds it to a new + // GifWriter instance in order to get the binary GIF file + generateGIF: function generateGIF(frames, callback) { + // TODO: Weird: using a simple JS array instead of a typed array, + // the files are WAY smaller o_o. Patches/explanations welcome! + var buffer = []; // new Uint8Array(width * height * frames.length * 5); + var gifOptions = { + loop: this.repeat + }; + var options = this.options; + var interval = options.interval; + + var frameDuration = options.frameDuration; + var existingImages = options.images; + var hasExistingImages = !!existingImages.length; + var height = options.gifHeight; + var width = options.gifWidth; + var gifWriter$$1 = new gifWriter(buffer, width, height, gifOptions); + var onRenderProgressCallback = this.onRenderProgressCallback; + var delay = hasExistingImages ? interval * 100 : 0; + var bufferToString = void 0; + var gif = void 0; + + this.generatingGIF = true; + + utils.each(frames, function (iterator, frame) { + var framePalette = frame.palette; + + onRenderProgressCallback(0.75 + 0.25 * frame.position * 1.0 / frames.length); + + for (var i = 0; i < frameDuration; i++) { + gifWriter$$1.addFrame(0, 0, width, height, frame.pixels, { + palette: framePalette, + delay: delay + }); + } + }); + + gifWriter$$1.end(); + + onRenderProgressCallback(1.0); + + this.frames = []; + + this.generatingGIF = false; + + if (utils.isFunction(callback)) { + bufferToString = this.bufferToString(buffer); + gif = 'data:image/gif;base64,' + utils.btoa(bufferToString); + + callback(gif); + } + }, + // From GIF: 0 = loop forever, null = not looping, n > 0 = loop n times and stop + setRepeat: function setRepeat(r) { + this.repeat = r; + }, + addFrame: function addFrame(element, gifshotOptions) { + gifshotOptions = utils.isObject(gifshotOptions) ? gifshotOptions : {}; + + var self = this; + var ctx = self.ctx; + var options = self.options; + var width = options.gifWidth; + var height = options.gifHeight; + var fontSize = utils.getFontSize(gifshotOptions); + var _gifshotOptions = gifshotOptions, + filter = _gifshotOptions.filter, + fontColor = _gifshotOptions.fontColor, + fontFamily = _gifshotOptions.fontFamily, + fontWeight = _gifshotOptions.fontWeight, + gifHeight = _gifshotOptions.gifHeight, + gifWidth = _gifshotOptions.gifWidth, + text = _gifshotOptions.text, + textAlign = _gifshotOptions.textAlign, + textBaseline = _gifshotOptions.textBaseline; + + var textXCoordinate = gifshotOptions.textXCoordinate ? gifshotOptions.textXCoordinate : textAlign === 'left' ? 1 : textAlign === 'right' ? width : width / 2; + var textYCoordinate = gifshotOptions.textYCoordinate ? gifshotOptions.textYCoordinate : textBaseline === 'top' ? 1 : textBaseline === 'center' ? height / 2 : height; + var font = fontWeight + ' ' + fontSize + ' ' + fontFamily; + var imageData = void 0; + + try { + ctx.filter = filter; + + ctx.drawImage(element, 0, 0, width, height); + + if (text) { + ctx.font = font; + ctx.fillStyle = fontColor; + ctx.textAlign = textAlign; + ctx.textBaseline = textBaseline; + ctx.fillText(text, textXCoordinate, textYCoordinate); + } + + imageData = ctx.getImageData(0, 0, width, height); + + self.addFrameImageData(imageData); + } catch (e) { + return '' + e; + } + }, + addFrameImageData: function addFrameImageData() { + var imageData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var frames = this.frames; + var imageDataArray = imageData.data; + + this.frames.push({ + 'data': imageDataArray, + 'width': imageData.width, + 'height': imageData.height, + 'palette': null, + 'dithering': null, + 'done': false, + 'beingProcessed': false, + 'position': frames.length + }); + }, + onRenderProgress: function onRenderProgress(callback) { + this.onRenderProgressCallback = callback; + }, + isRendering: function isRendering() { + return this.generatingGIF; + }, + getBase64GIF: function getBase64GIF(completeCallback) { + var self = this; + var onRenderComplete = function onRenderComplete(gif) { + self.destroyWorkers(); + + utils.requestTimeout(function () { + completeCallback(gif); + }, 0); + }; + + self.startRendering(onRenderComplete); + }, + destroyWorkers: function destroyWorkers() { + if (this.workerError) { + return; + } + + var workers = this.workers; + + // Explicitly ask web workers to die so they are explicitly GC'ed + utils.each(workers, function (iterator, workerObj) { + var worker = workerObj.worker; + var objectUrl = workerObj.objectUrl; + + worker.terminate(); + utils.URL.revokeObjectURL(objectUrl); + }); + } +}; + +/* + getBase64GIF.js + =============== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +function getBase64GIF(animatedGifInstance, callback) { + // This is asynchronous, rendered with WebWorkers + animatedGifInstance.getBase64GIF(function (image) { + callback({ + error: false, + errorCode: '', + errorMsg: '', + image: image + }); + }); +} + +/* + existingImages.js + ================= +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +function existingImages() { + var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var self = this; + var callback = obj.callback, + images = obj.images, + options = obj.options; + + var imagesLength = obj.imagesLength; + var skipObj = { + 'getUserMedia': true, + 'window.URL': true + }; + var errorObj = error.validate(skipObj); + var loadedImages = []; + var loadedImagesLength = 0; + var tempImage = void 0; + var ag = void 0; + + if (errorObj.error) { + return callback(errorObj); + } + + // change workerPath to point to where Animated_GIF.worker.js is + ag = new AnimatedGIF(options); + + utils.each(images, function (index, image) { + var currentImage = image; + + if (image.src) { + currentImage = currentImage.src; + } + if (utils.isElement(currentImage)) { + if (options.crossOrigin) { + currentImage.crossOrigin = options.crossOrigin; + } + + loadedImages[index] = currentImage; + loadedImagesLength += 1; + + if (loadedImagesLength === imagesLength) { + addLoadedImagesToGif(); + } + } else if (utils.isString(currentImage)) { + tempImage = new Image(); + + if (options.crossOrigin) { + tempImage.crossOrigin = options.crossOrigin; + } + + (function (tempImage) { + if (image.text) { + tempImage.text = image.text; + } + + tempImage.onerror = function (e) { + var obj = void 0; + + --imagesLength; // skips over images that error out + + if (imagesLength === 0) { + obj = {}; + obj.error = 'None of the requested images was capable of being retrieved'; + + return callback(obj); + } + }; + + tempImage.onload = function (e) { + if (image.text) { + loadedImages[index] = { + img: tempImage, + text: tempImage.text + }; + } else { + loadedImages[index] = tempImage; + } + + loadedImagesLength += 1; + + if (loadedImagesLength === imagesLength) { + addLoadedImagesToGif(); + } + + utils.removeElement(tempImage); + }; + + tempImage.src = currentImage; + })(tempImage); + + utils.setCSSAttr(tempImage, { + position: 'fixed', + opacity: '0' + }); + + document.body.appendChild(tempImage); + } + }); + + function addLoadedImagesToGif() { + utils.each(loadedImages, function (index, loadedImage) { + if (loadedImage) { + if (loadedImage.text) { + ag.addFrame(loadedImage.img, options, loadedImage.text); + } else { + ag.addFrame(loadedImage, options); + } + } + }); + + getBase64GIF(ag, callback); + } +} + +/* + screenShot.js + ============= +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +// Helpers +var noop$3 = function noop() {}; + +var screenShot = { + getGIF: function getGIF() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var callback = arguments[1]; + + callback = utils.isFunction(callback) ? callback : noop$3; + + var canvas = document.createElement('canvas'); + var context = void 0; + var existingImages = options.images; + var hasExistingImages = !!existingImages.length; + var cameraStream = options.cameraStream, + crop = options.crop, + filter = options.filter, + fontColor = options.fontColor, + fontFamily = options.fontFamily, + fontWeight = options.fontWeight, + keepCameraOn = options.keepCameraOn, + numWorkers = options.numWorkers, + progressCallback = options.progressCallback, + saveRenderingContexts = options.saveRenderingContexts, + savedRenderingContexts = options.savedRenderingContexts, + text = options.text, + textAlign = options.textAlign, + textBaseline = options.textBaseline, + videoElement = options.videoElement, + videoHeight = options.videoHeight, + videoWidth = options.videoWidth, + webcamVideoElement = options.webcamVideoElement; + + var gifWidth = Number(options.gifWidth); + var gifHeight = Number(options.gifHeight); + var interval = Number(options.interval); + var sampleInterval = Number(options.sampleInterval); + var waitBetweenFrames = hasExistingImages ? 0 : interval * 1000; + var renderingContextsToSave = []; + var numFrames = savedRenderingContexts.length ? savedRenderingContexts.length : options.numFrames; + var pendingFrames = numFrames; + var ag = new AnimatedGIF(options); + var fontSize = utils.getFontSize(options); + var textXCoordinate = options.textXCoordinate ? options.textXCoordinate : textAlign === 'left' ? 1 : textAlign === 'right' ? gifWidth : gifWidth / 2; + var textYCoordinate = options.textYCoordinate ? options.textYCoordinate : textBaseline === 'top' ? 1 : textBaseline === 'center' ? gifHeight / 2 : gifHeight; + var font = fontWeight + ' ' + fontSize + ' ' + fontFamily; + var sourceX = crop ? Math.floor(crop.scaledWidth / 2) : 0; + var sourceWidth = crop ? videoWidth - crop.scaledWidth : 0; + var sourceY = crop ? Math.floor(crop.scaledHeight / 2) : 0; + var sourceHeight = crop ? videoHeight - crop.scaledHeight : 0; + var captureFrames = function captureSingleFrame() { + var framesLeft = pendingFrames - 1; + + if (savedRenderingContexts.length) { + context.putImageData(savedRenderingContexts[numFrames - pendingFrames], 0, 0); + + finishCapture(); + } else { + drawVideo(); + } + + function drawVideo() { + try { + // Makes sure the canvas video heights/widths are in bounds + if (sourceWidth > videoWidth) { + sourceWidth = videoWidth; + } + + if (sourceHeight > videoHeight) { + sourceHeight = videoHeight; + } + + if (sourceX < 0) { + sourceX = 0; + } + + if (sourceY < 0) { + sourceY = 0; + } + + context.filter = filter; + + context.drawImage(videoElement, sourceX, sourceY, sourceWidth, sourceHeight, 0, 0, gifWidth, gifHeight); + + finishCapture(); + } catch (e) { + // There is a Firefox bug that sometimes throws NS_ERROR_NOT_AVAILABLE and + // and IndexSizeError errors when drawing a video element to the canvas + if (e.name === 'NS_ERROR_NOT_AVAILABLE') { + // Wait 100ms before trying again + utils.requestTimeout(drawVideo, 100); + } else { + throw e; + } + } + } + + function finishCapture() { + var imageData = void 0; + + if (saveRenderingContexts) { + renderingContextsToSave.push(context.getImageData(0, 0, gifWidth, gifHeight)); + } + + // If there is text to display, make sure to display it on the canvas after the image is drawn + if (text) { + context.font = font; + context.fillStyle = fontColor; + context.textAlign = textAlign; + context.textBaseline = textBaseline; + context.fillText(text, textXCoordinate, textYCoordinate); + } + + imageData = context.getImageData(0, 0, gifWidth, gifHeight); + + ag.addFrameImageData(imageData); + + pendingFrames = framesLeft; + + // Call back with an r value indicating how far along we are in capture + progressCallback((numFrames - pendingFrames) / numFrames); + + if (framesLeft > 0) { + // test + utils.requestTimeout(captureSingleFrame, waitBetweenFrames); + } + + if (!pendingFrames) { + ag.getBase64GIF(function (image) { + callback({ + 'error': false, + 'errorCode': '', + 'errorMsg': '', + 'image': image, + 'cameraStream': cameraStream, + 'videoElement': videoElement, + 'webcamVideoElement': webcamVideoElement, + 'savedRenderingContexts': renderingContextsToSave, + 'keepCameraOn': keepCameraOn + }); + }); + } + } + }; + + numFrames = numFrames !== undefined ? numFrames : 10; + interval = interval !== undefined ? interval : 0.1; // In seconds + + canvas.width = gifWidth; + canvas.height = gifHeight; + context = canvas.getContext('2d'); + + (function capture() { + if (!savedRenderingContexts.length && videoElement.currentTime === 0) { + utils.requestTimeout(capture, 100); + + return; + } + + captureFrames(); + })(); + }, + getCropDimensions: function getCropDimensions() { + var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + var width = obj.videoWidth; + var height = obj.videoHeight; + var gifWidth = obj.gifWidth; + var gifHeight = obj.gifHeight; + var result = { + width: 0, + height: 0, + scaledWidth: 0, + scaledHeight: 0 + }; + + if (width > height) { + result.width = Math.round(width * (gifHeight / height)) - gifWidth; + result.scaledWidth = Math.round(result.width * (height / gifHeight)); + } else { + result.height = Math.round(height * (gifWidth / width)) - gifHeight; + result.scaledHeight = Math.round(result.height * (width / gifWidth)); + } + + return result; + } +}; + +/* + videoStream.js + ============== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +var videoStream = { + loadedData: false, + defaultVideoDimensions: { + width: 640, + height: 480 + }, + findVideoSize: function findVideoSizeMethod(obj) { + findVideoSizeMethod.attempts = findVideoSizeMethod.attempts || 0; + + var cameraStream = obj.cameraStream, + completedCallback = obj.completedCallback, + videoElement = obj.videoElement; + + + if (!videoElement) { + return; + } + + if (videoElement.videoWidth > 0 && videoElement.videoHeight > 0) { + videoElement.removeEventListener('loadeddata', videoStream.findVideoSize); + + completedCallback({ + videoElement: videoElement, + cameraStream: cameraStream, + videoWidth: videoElement.videoWidth, + videoHeight: videoElement.videoHeight + }); + } else { + if (findVideoSizeMethod.attempts < 10) { + findVideoSizeMethod.attempts += 1; + + utils.requestTimeout(function () { + videoStream.findVideoSize(obj); + }, 400); + } else { + completedCallback({ + videoElement: videoElement, + cameraStream: cameraStream, + videoWidth: videoStream.defaultVideoDimensions.width, + videoHeight: videoStream.defaultVideoDimensions.height + }); + } + } + }, + onStreamingTimeout: function onStreamingTimeout(callback) { + if (utils.isFunction(callback)) { + callback({ + error: true, + errorCode: 'getUserMedia', + errorMsg: 'There was an issue with the getUserMedia API - Timed out while trying to start streaming', + image: null, + cameraStream: {} + }); + } + }, + stream: function stream(obj) { + var existingVideo = utils.isArray(obj.existingVideo) ? obj.existingVideo[0] : obj.existingVideo; + var cameraStream = obj.cameraStream, + completedCallback = obj.completedCallback, + streamedCallback = obj.streamedCallback, + videoElement = obj.videoElement; + + + if (utils.isFunction(streamedCallback)) { + streamedCallback(); + } + + if (existingVideo) { + if (utils.isString(existingVideo)) { + videoElement.src = existingVideo; + videoElement.innerHTML = ''; + } else if (existingVideo instanceof Blob) { + try { + videoElement.src = utils.URL.createObjectURL(existingVideo); + } catch (e) {} + + videoElement.innerHTML = ''; + } + } else if (videoElement.mozSrcObject) { + videoElement.mozSrcObject = cameraStream; + } else if (utils.URL) { + try { + videoElement.srcObject = cameraStream; + videoElement.src = utils.URL.createObjectURL(cameraStream); + } catch (e) { + videoElement.srcObject = cameraStream; + } + } + + videoElement.play(); + + utils.requestTimeout(function checkLoadedData() { + checkLoadedData.count = checkLoadedData.count || 0; + + if (videoStream.loadedData === true) { + videoStream.findVideoSize({ + videoElement: videoElement, + cameraStream: cameraStream, + completedCallback: completedCallback + }); + + videoStream.loadedData = false; + } else { + checkLoadedData.count += 1; + + if (checkLoadedData.count > 10) { + videoStream.findVideoSize({ + videoElement: videoElement, + cameraStream: cameraStream, + completedCallback: completedCallback + }); + } else { + checkLoadedData(); + } + } + }, 0); + }, + startStreaming: function startStreaming(obj) { + var errorCallback = utils.isFunction(obj.error) ? obj.error : utils.noop; + var streamedCallback = utils.isFunction(obj.streamed) ? obj.streamed : utils.noop; + var completedCallback = utils.isFunction(obj.completed) ? obj.completed : utils.noop; + var crossOrigin = obj.crossOrigin, + existingVideo = obj.existingVideo, + lastCameraStream = obj.lastCameraStream, + options = obj.options, + webcamVideoElement = obj.webcamVideoElement; + + var videoElement = utils.isElement(existingVideo) ? existingVideo : webcamVideoElement ? webcamVideoElement : document.createElement('video'); + var cameraStream = void 0; + + if (crossOrigin) { + videoElement.crossOrigin = options.crossOrigin; + } + + videoElement.autoplay = true; + videoElement.loop = true; + videoElement.muted = true; + videoElement.addEventListener('loadeddata', function (event) { + videoStream.loadedData = true; + if (options.offset) { + videoElement.currentTime = options.offset; + } + }); + + if (existingVideo) { + videoStream.stream({ + videoElement: videoElement, + existingVideo: existingVideo, + completedCallback: completedCallback + }); + } else if (lastCameraStream) { + videoStream.stream({ + videoElement: videoElement, + cameraStream: lastCameraStream, + streamedCallback: streamedCallback, + completedCallback: completedCallback + }); + } else { + utils.getUserMedia({ + video: true + }, function (stream) { + videoStream.stream({ + videoElement: videoElement, + cameraStream: stream, + streamedCallback: streamedCallback, + completedCallback: completedCallback + }); + }, errorCallback); + } + }, + startVideoStreaming: function startVideoStreaming(callback) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var timeoutLength = options.timeout !== undefined ? options.timeout : 0; + var originalCallback = options.callback; + var webcamVideoElement = options.webcamVideoElement; + var noGetUserMediaSupportTimeout = void 0; + + // Some browsers apparently have support for video streaming because of the + // presence of the getUserMedia function, but then do not answer our + // calls for streaming. + // So we'll set up this timeout and if nothing happens after a while, we'll + // conclude that there's no actual getUserMedia support. + if (timeoutLength > 0) { + noGetUserMediaSupportTimeout = utils.requestTimeout(function () { + videoStream.onStreamingTimeout(originalCallback); + }, 10000); + } + + videoStream.startStreaming({ + error: function error() { + originalCallback({ + error: true, + errorCode: 'getUserMedia', + errorMsg: 'There was an issue with the getUserMedia API - the user probably denied permission', + image: null, + cameraStream: {} + }); + }, + streamed: function streamed() { + // The streaming started somehow, so we can assume there is getUserMedia support + clearTimeout(noGetUserMediaSupportTimeout); + }, + completed: function completed() { + var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var cameraStream = obj.cameraStream, + videoElement = obj.videoElement, + videoHeight = obj.videoHeight, + videoWidth = obj.videoWidth; + + + callback({ + cameraStream: cameraStream, + videoElement: videoElement, + videoHeight: videoHeight, + videoWidth: videoWidth + }); + }, + lastCameraStream: options.lastCameraStream, + webcamVideoElement: webcamVideoElement, + crossOrigin: options.crossOrigin, + options: options + }); + }, + stopVideoStreaming: function stopVideoStreaming(obj) { + obj = utils.isObject(obj) ? obj : {}; + + var _obj = obj, + keepCameraOn = _obj.keepCameraOn, + videoElement = _obj.videoElement, + webcamVideoElement = _obj.webcamVideoElement; + + var cameraStream = obj.cameraStream || {}; + var cameraStreamTracks = cameraStream.getTracks ? cameraStream.getTracks() || [] : []; + var hasCameraStreamTracks = !!cameraStreamTracks.length; + var firstCameraStreamTrack = cameraStreamTracks[0]; + + if (!keepCameraOn && hasCameraStreamTracks) { + if (utils.isFunction(firstCameraStreamTrack.stop)) { + // Stops the camera stream + firstCameraStreamTrack.stop(); + } + } + + if (utils.isElement(videoElement) && !webcamVideoElement) { + // Pauses the video, revokes the object URL (freeing up memory), and remove the video element + videoElement.pause(); + + // Destroys the object url + if (utils.isFunction(utils.URL.revokeObjectURL) && !utils.webWorkerError) { + if (videoElement.src) { + utils.URL.revokeObjectURL(videoElement.src); + } + } + + // Removes the video element from the DOM + utils.removeElement(videoElement); + } + } +}; + +/* + stopVideoStreaming.js + ===================== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +function stopVideoStreaming(options) { + options = utils.isObject(options) ? options : {}; + + videoStream.stopVideoStreaming(options); +} + +/* + createAndGetGIF.js + ================== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +function createAndGetGIF(obj, callback) { + var options = obj.options || {}; + + var images = options.images, + video = options.video; + + var gifWidth = Number(options.gifWidth); + var gifHeight = Number(options.gifHeight); + var numFrames = Number(options.numFrames); + var cameraStream = obj.cameraStream, + videoElement = obj.videoElement, + videoWidth = obj.videoWidth, + videoHeight = obj.videoHeight; + + var cropDimensions = screenShot.getCropDimensions({ + videoWidth: videoWidth, + videoHeight: videoHeight, + gifHeight: gifHeight, + gifWidth: gifWidth + }); + var completeCallback = callback; + + options.crop = cropDimensions; + options.videoElement = videoElement; + options.videoWidth = videoWidth; + options.videoHeight = videoHeight; + options.cameraStream = cameraStream; + + if (!utils.isElement(videoElement)) { + return; + } + + videoElement.width = gifWidth + cropDimensions.width; + videoElement.height = gifHeight + cropDimensions.height; + + if (!options.webcamVideoElement) { + utils.setCSSAttr(videoElement, { + position: 'fixed', + opacity: '0' + }); + + document.body.appendChild(videoElement); + } + + // Firefox doesn't seem to obey autoplay if the element is not in the DOM when the content + // is loaded, so we must manually trigger play after adding it, or the video will be frozen + videoElement.play(); + + screenShot.getGIF(options, function (obj) { + if ((!images || !images.length) && (!video || !video.length)) { + stopVideoStreaming(obj); + } + + completeCallback(obj); + }); +} + +/* + existingVideo.js + ================ +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +function existingVideo() { + var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var callback = obj.callback, + existingVideo = obj.existingVideo, + options = obj.options; + + var skipObj = { + getUserMedia: true, + 'window.URL': true + }; + var errorObj = error.validate(skipObj); + var loadedImages = 0; + var videoType = void 0; + var videoSrc = void 0; + var tempImage = void 0; + var ag = void 0; + + if (errorObj.error) { + return callback(errorObj); + } + + if (utils.isElement(existingVideo) && existingVideo.src) { + videoSrc = existingVideo.src; + videoType = utils.getExtension(videoSrc); + + if (!utils.isSupported.videoCodecs[videoType]) { + return callback(error.messages.videoCodecs); + } + } else if (utils.isArray(existingVideo)) { + utils.each(existingVideo, function (iterator, videoSrc) { + if (videoSrc instanceof Blob) { + videoType = videoSrc.type.substr(videoSrc.type.lastIndexOf('/') + 1, videoSrc.length); + } else { + videoType = videoSrc.substr(videoSrc.lastIndexOf('.') + 1, videoSrc.length); + } + + if (utils.isSupported.videoCodecs[videoType]) { + existingVideo = videoSrc; + + return false; + } + }); + } + + videoStream.startStreaming({ + completed: function completed(obj) { + obj.options = options || {}; + + createAndGetGIF(obj, callback); + }, + existingVideo: existingVideo, + crossOrigin: options.crossOrigin, + options: options + }); +} + +/* + existingWebcam.js + ================= +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +function existingWebcam() { + var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var callback = obj.callback, + lastCameraStream = obj.lastCameraStream, + options = obj.options, + webcamVideoElement = obj.webcamVideoElement; + + + if (!isWebCamGIFSupported()) { + return callback(error.validate()); + } + + if (options.savedRenderingContexts.length) { + screenShot.getGIF(options, function (obj) { + callback(obj); + }); + + return; + } + + videoStream.startVideoStreaming(function () { + var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + obj.options = options || {}; + + createAndGetGIF(obj, callback); + }, { + lastCameraStream: lastCameraStream, + callback: callback, + webcamVideoElement: webcamVideoElement, + crossOrigin: options.crossOrigin + }); +} + +/* + createGIF.js + ============ +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +function createGIF(userOptions, callback) { + callback = utils.isFunction(userOptions) ? userOptions : callback; + userOptions = utils.isObject(userOptions) ? userOptions : {}; + + if (!utils.isFunction(callback)) { + return; + } + + var options = utils.mergeOptions(defaultOptions, userOptions) || {}; + var lastCameraStream = userOptions.cameraStream; + var images = options.images; + var imagesLength = images ? images.length : 0; + var video = options.video; + var webcamVideoElement = options.webcamVideoElement; + + options = utils.mergeOptions(options, { + 'gifWidth': Math.floor(options.gifWidth), + 'gifHeight': Math.floor(options.gifHeight) + }); + + // If the user would like to create a GIF from an existing image(s) + if (imagesLength) { + existingImages({ + 'images': images, + 'imagesLength': imagesLength, + 'callback': callback, + 'options': options + }); + } else if (video) { + // If the user would like to create a GIF from an existing HTML5 video + existingVideo({ + 'existingVideo': video, + callback: callback, + options: options + }); + } else { + // If the user would like to create a GIF from a webcam stream + existingWebcam({ + lastCameraStream: lastCameraStream, + callback: callback, + webcamVideoElement: webcamVideoElement, + options: options + }); + } +} + +/* + takeSnapShot.js + =============== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +function takeSnapShot(userOptions, callback) { + callback = utils.isFunction(userOptions) ? userOptions : callback; + userOptions = utils.isObject(userOptions) ? userOptions : {}; + + if (!utils.isFunction(callback)) { + return; + } + + var mergedOptions = utils.mergeOptions(defaultOptions, userOptions); + var options = utils.mergeOptions(mergedOptions, { + 'interval': .1, + 'numFrames': 1, + 'gifWidth': Math.floor(mergedOptions.gifWidth), + 'gifHeight': Math.floor(mergedOptions.gifHeight) + }); + + createGIF(options, callback); +} + +/* + API.js + ====== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. +*/ + +// Dependencies +var API = { + 'utils': utils$2, + 'error': error$2, + 'defaultOptions': defaultOptions$2, + 'createGIF': createGIF, + 'takeSnapShot': takeSnapShot, + 'stopVideoStreaming': stopVideoStreaming, + 'isSupported': isSupported, + 'isWebCamGIFSupported': isWebCamGIFSupported, + 'isExistingVideoGIFSupported': isExistingVideoGIFSupported, + 'isExistingImagesGIFSupported': isSupported$1, + 'VERSION': '0.4.5' +}; + +/* + index.js + ======== +*/ + +/* Copyright 2017 Yahoo Inc. + * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms. + */ + +// Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, and plain browser loading +if (typeof define === 'function' && define.amd) { + define([], function () { + return API; + }); +} else if (typeof exports !== 'undefined') { + module.exports = API; +} else { + window.gifshot = API; +} +}(typeof window !== "undefined" ? window : {}, typeof document !== "undefined" ? document : { createElement: function() {} }, typeof window !== "undefined" ? window.navigator : {})); + +},{}],135:[function(require,module,exports){ +/** + * + * @param {WebGLRenderingContext} gl + * @param {IGLWiretapOptions} [options] + * @returns {GLWiretapProxy} + */ +function glWiretap(gl, options = {}) { + const { + contextName = 'gl', + throwGetError, + useTrackablePrimitives, + readPixelsFile, + recording = [], + variables = {}, + onReadPixels, + onUnrecognizedArgumentLookup, + } = options; + const proxy = new Proxy(gl, { get: listen }); + const contextVariables = []; + const entityNames = {}; + let imageCount = 0; + let indent = ''; + let readPixelsVariableName; + return proxy; + function listen(obj, property) { + switch (property) { + case 'addComment': return addComment; + case 'checkThrowError': return checkThrowError; + case 'getReadPixelsVariableName': return readPixelsVariableName; + case 'insertVariable': return insertVariable; + case 'reset': return reset; + case 'setIndent': return setIndent; + case 'toString': return toString; + case 'getContextVariableName': return getContextVariableName; + } + if (typeof gl[property] === 'function') { + return function() { // need arguments from this, fyi + switch (property) { + case 'getError': + if (throwGetError) { + recording.push(`${indent}if (${contextName}.getError() !== ${contextName}.NONE) throw new Error('error');`); + } else { + recording.push(`${indent}${contextName}.getError();`); // flush out errors + } + return gl.getError(); + case 'getExtension': { + const variableName = `${contextName}Variables${contextVariables.length}`; + recording.push(`${indent}const ${variableName} = ${contextName}.getExtension('${arguments[0]}');`); + const extension = gl.getExtension(arguments[0]); + if (extension && typeof extension === 'object') { + const tappedExtension = glExtensionWiretap(extension, { + getEntity, + useTrackablePrimitives, + recording, + contextName: variableName, + contextVariables, + variables, + indent, + onUnrecognizedArgumentLookup, + }); + contextVariables.push(tappedExtension); + return tappedExtension; + } else { + contextVariables.push(null); + } + return extension; + } + case 'readPixels': + const i = contextVariables.indexOf(arguments[6]); + let targetVariableName; + if (i === -1) { + const variableName = getVariableName(arguments[6]); + if (variableName) { + targetVariableName = variableName; + recording.push(`${indent}${variableName}`); + } else { + targetVariableName = `${contextName}Variable${contextVariables.length}`; + contextVariables.push(arguments[6]); + recording.push(`${indent}const ${targetVariableName} = new ${arguments[6].constructor.name}(${arguments[6].length});`); + } + } else { + targetVariableName = `${contextName}Variable${i}`; + } + readPixelsVariableName = targetVariableName; + const argumentAsStrings = [ + arguments[0], + arguments[1], + arguments[2], + arguments[3], + getEntity(arguments[4]), + getEntity(arguments[5]), + targetVariableName + ]; + recording.push(`${indent}${contextName}.readPixels(${argumentAsStrings.join(', ')});`); + if (readPixelsFile) { + writePPM(arguments[2], arguments[3]); + } + if (onReadPixels) { + onReadPixels(targetVariableName, argumentAsStrings); + } + return gl.readPixels.apply(gl, arguments); + case 'drawBuffers': + recording.push(`${indent}${contextName}.drawBuffers([${argumentsToString(arguments[0], { contextName, contextVariables, getEntity, addVariable, variables, onUnrecognizedArgumentLookup } )}]);`); + return gl.drawBuffers(arguments[0]); + } + let result = gl[property].apply(gl, arguments); + switch (typeof result) { + case 'undefined': + recording.push(`${indent}${methodCallToString(property, arguments)};`); + return; + case 'number': + case 'boolean': + if (useTrackablePrimitives && contextVariables.indexOf(trackablePrimitive(result)) === -1) { + recording.push(`${indent}const ${contextName}Variable${contextVariables.length} = ${methodCallToString(property, arguments)};`); + contextVariables.push(result = trackablePrimitive(result)); + break; + } + default: + if (result === null) { + recording.push(`${methodCallToString(property, arguments)};`); + } else { + recording.push(`${indent}const ${contextName}Variable${contextVariables.length} = ${methodCallToString(property, arguments)};`); + } + + contextVariables.push(result); + } + return result; + } + } + entityNames[gl[property]] = property; + return gl[property]; + } + function toString() { + return recording.join('\n'); + } + function reset() { + while (recording.length > 0) { + recording.pop(); + } + } + function insertVariable(name, value) { + variables[name] = value; + } + function getEntity(value) { + const name = entityNames[value]; + if (name) { + return contextName + '.' + name; + } + return value; + } + function setIndent(spaces) { + indent = ' '.repeat(spaces); + } + function addVariable(value, source) { + const variableName = `${contextName}Variable${contextVariables.length}`; + recording.push(`${indent}const ${variableName} = ${source};`); + contextVariables.push(value); + return variableName; + } + function writePPM(width, height) { + const sourceVariable = `${contextName}Variable${contextVariables.length}`; + const imageVariable = `imageDatum${imageCount}`; + recording.push(`${indent}let ${imageVariable} = ["P3\\n# ${readPixelsFile}.ppm\\n", ${width}, ' ', ${height}, "\\n255\\n"].join("");`); + recording.push(`${indent}for (let i = 0; i < ${imageVariable}.length; i += 4) {`); + recording.push(`${indent} ${imageVariable} += ${sourceVariable}[i] + ' ' + ${sourceVariable}[i + 1] + ' ' + ${sourceVariable}[i + 2] + ' ';`); + recording.push(`${indent}}`); + recording.push(`${indent}if (typeof require !== "undefined") {`); + recording.push(`${indent} require('fs').writeFileSync('./${readPixelsFile}.ppm', ${imageVariable});`); + recording.push(`${indent}}`); + imageCount++; + } + function addComment(value) { + recording.push(`${indent}// ${value}`); + } + function checkThrowError() { + recording.push(`${indent}(() => { +${indent}const error = ${contextName}.getError(); +${indent}if (error !== ${contextName}.NONE) { +${indent} const names = Object.getOwnPropertyNames(gl); +${indent} for (let i = 0; i < names.length; i++) { +${indent} const name = names[i]; +${indent} if (${contextName}[name] === error) { +${indent} throw new Error('${contextName} threw ' + name); +${indent} } +${indent} } +${indent}} +${indent}})();`); + } + function methodCallToString(method, args) { + return `${contextName}.${method}(${argumentsToString(args, { contextName, contextVariables, getEntity, addVariable, variables, onUnrecognizedArgumentLookup })})`; + } + + function getVariableName(value) { + if (variables) { + for (const name in variables) { + if (variables[name] === value) { + return name; + } + } + } + return null; + } + + function getContextVariableName(value) { + const i = contextVariables.indexOf(value); + if (i !== -1) { + return `${contextName}Variable${i}`; + } + return null; + } +} + +/** + * + * @param extension + * @param {IGLExtensionWiretapOptions} options + * @returns {*} + */ +function glExtensionWiretap(extension, options) { + const proxy = new Proxy(extension, { get: listen }); + const extensionEntityNames = {}; + const { + contextName, + contextVariables, + getEntity, + useTrackablePrimitives, + recording, + variables, + indent, + onUnrecognizedArgumentLookup, + } = options; + return proxy; + function listen(obj, property) { + if (typeof obj[property] === 'function') { + return function() { + switch (property) { + case 'drawBuffersWEBGL': + recording.push(`${indent}${contextName}.drawBuffersWEBGL([${argumentsToString(arguments[0], { contextName, contextVariables, getEntity: getExtensionEntity, addVariable, variables, onUnrecognizedArgumentLookup })}]);`); + return extension.drawBuffersWEBGL(arguments[0]); + } + let result = extension[property].apply(extension, arguments); + switch (typeof result) { + case 'undefined': + recording.push(`${indent}${methodCallToString(property, arguments)};`); + return; + case 'number': + case 'boolean': + if (useTrackablePrimitives && contextVariables.indexOf(trackablePrimitive(result)) === -1) { + recording.push(`${indent}const ${contextName}Variable${contextVariables.length} = ${methodCallToString(property, arguments)};`); + contextVariables.push(result = trackablePrimitive(result)); + } else { + recording.push(`${indent}const ${contextName}Variable${contextVariables.length} = ${methodCallToString(property, arguments)};`); + contextVariables.push(result); + } + break; + default: + if (result === null) { + recording.push(`${methodCallToString(property, arguments)};`); + } else { + recording.push(`${indent}const ${contextName}Variable${contextVariables.length} = ${methodCallToString(property, arguments)};`); + } + contextVariables.push(result); + } + return result; + }; + } + extensionEntityNames[extension[property]] = property; + return extension[property]; + } + + function getExtensionEntity(value) { + if (extensionEntityNames.hasOwnProperty(value)) { + return `${contextName}.${extensionEntityNames[value]}`; + } + return getEntity(value); + } + + function methodCallToString(method, args) { + return `${contextName}.${method}(${argumentsToString(args, { contextName, contextVariables, getEntity: getExtensionEntity, addVariable, variables, onUnrecognizedArgumentLookup })})`; + } + + function addVariable(value, source) { + const variableName = `${contextName}Variable${contextVariables.length}`; + contextVariables.push(value); + recording.push(`${indent}const ${variableName} = ${source};`); + return variableName; + } +} + +function argumentsToString(args, options) { + const { variables, onUnrecognizedArgumentLookup } = options; + return (Array.from(args).map((arg) => { + const variableName = getVariableName(arg); + if (variableName) { + return variableName; + } + return argumentToString(arg, options); + }).join(', ')); + + function getVariableName(value) { + if (variables) { + for (const name in variables) { + if (!variables.hasOwnProperty(name)) continue; + if (variables[name] === value) { + return name; + } + } + } + if (onUnrecognizedArgumentLookup) { + return onUnrecognizedArgumentLookup(value); + } + return null; + } +} + +function argumentToString(arg, options) { + const { contextName, contextVariables, getEntity, addVariable, onUnrecognizedArgumentLookup } = options; + if (typeof arg === 'undefined') { + return 'undefined'; + } + if (arg === null) { + return 'null'; + } + const i = contextVariables.indexOf(arg); + if (i > -1) { + return `${contextName}Variable${i}`; + } + switch (arg.constructor.name) { + case 'String': + const hasLines = /\n/.test(arg); + const hasSingleQuotes = /'/.test(arg); + const hasDoubleQuotes = /"/.test(arg); + if (hasLines) { + return '`' + arg + '`'; + } else if (hasSingleQuotes && !hasDoubleQuotes) { + return '"' + arg + '"'; + } else if (!hasSingleQuotes && hasDoubleQuotes) { + return "'" + arg + "'"; + } else { + return '\'' + arg + '\''; + } + case 'Number': return getEntity(arg); + case 'Boolean': return getEntity(arg); + case 'Array': + return addVariable(arg, `new ${arg.constructor.name}([${Array.from(arg).join(',')}])`); + case 'Float32Array': + case 'Uint8Array': + case 'Uint16Array': + case 'Int32Array': + return addVariable(arg, `new ${arg.constructor.name}(${JSON.stringify(Array.from(arg))})`); + default: + if (onUnrecognizedArgumentLookup) { + const instantiationString = onUnrecognizedArgumentLookup(arg); + if (instantiationString) { + return instantiationString; + } + } + throw new Error(`unrecognized argument type ${arg.constructor.name}`); + } +} + +function trackablePrimitive(value) { + // wrapped in object, so track-able + return new value.constructor(value); +} + +if (typeof module !== 'undefined') { + module.exports = { glWiretap, glExtensionWiretap }; +} + +if (typeof window !== 'undefined') { + glWiretap.glExtensionWiretap = glExtensionWiretap; + window.glWiretap = glWiretap; +} + +},{}],136:[function(require,module,exports){ +if (typeof WebGLRenderingContext !== 'undefined') { + module.exports = require('./src/javascript/browser-index') +} else { + module.exports = require('./src/javascript/node-index') +} + +},{"./src/javascript/browser-index":138,"./src/javascript/node-index":152}],137:[function(require,module,exports){ +module.exports={ + "name": "gl", + "version": "4.9.0", + "description": "Creates a WebGL context without a window", + "main": "index.js", + "directories": { + "test": "test" + }, + "browser": "browser_index.js", + "engines": { + "node": ">=8.0.0" + }, + "scripts": { + "test": "standard | snazzy && tape test/*.js | faucet", + "rebuild": "node-gyp rebuild --verbose", + "prebuild": "prebuild --all --strip", + "install": "prebuild-install || node-gyp rebuild" + }, + "dependencies": { + "bindings": "^1.5.0", + "bit-twiddle": "^1.0.2", + "glsl-tokenizer": "^2.0.2", + "nan": "^2.14.1", + "node-abi": "^2.18.0", + "node-gyp": "^7.1.0", + "prebuild-install": "^5.3.5" + }, + "devDependencies": { + "angle-normals": "^1.0.0", + "bunny": "^1.0.1", + "faucet": "0.0.1", + "gl-conformance": "^2.0.9", + "prebuild": "^10.0.1", + "snazzy": "^8.0.0", + "standard": "^14.3.4", + "tape": "^5.0.1" + }, + "repository": { + "type": "git", + "url": "git://github.com/stackgl/headless-gl.git" + }, + "keywords": [ + "webgl", + "opengl", + "gl", + "headless", + "server", + "gpgpu" + ], + "author": "Mikola Lysenko", + "license": "BSD-2-Clause", + "gypfile": true +} + +},{}],138:[function(require,module,exports){ +function createContext (width, height, options) { + width = width | 0 + height = height | 0 + if (!(width > 0 && height > 0)) { + return null + } + + const canvas = document.createElement('canvas') + if (!canvas) { + return null + } + let gl + canvas.width = width + canvas.height = height + + try { + gl = canvas.getContext('webgl', options) + } catch (e) { + try { + gl = canvas.getContext('experimental-webgl', options) + } catch (e) { + return null + } + } + + const _getExtension = gl.getExtension + const extDestroy = { + destroy: function () { + const loseContext = _getExtension.call(gl, 'WEBGL_lose_context') + if (loseContext) { + loseContext.loseContext() + } + } + } + + const extResize = { + resize: function (w, h) { + canvas.width = w + canvas.height = h + } + } + + const _supportedExtensions = gl.getSupportedExtensions().slice() + _supportedExtensions.push( + 'STACKGL_destroy_context', + 'STACKGL_resize_drawingbuffer') + gl.getSupportedExtensions = function () { + return _supportedExtensions.slice() + } + + gl.getExtension = function (extName) { + const name = extName.toLowerCase() + if (name === 'stackgl_resize_drawingbuffer') { + return extResize + } + if (name === 'stackgl_destroy_context') { + return extDestroy + } + return _getExtension.call(gl, extName) + } + + return gl || null +} + +module.exports = createContext + +},{}],139:[function(require,module,exports){ +const { gl } = require('../native-gl') +const { vertexCount } = require('../utils') + +class ANGLEInstancedArrays { + constructor (ctx) { + this.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88fe + this.ctx = ctx + + this._drawArraysInstanced = gl._drawArraysInstanced.bind(ctx) + this._drawElementsInstanced = gl._drawElementsInstanced.bind(ctx) + this._vertexAttribDivisor = gl._vertexAttribDivisor.bind(ctx) + } + + drawArraysInstancedANGLE (mode, first, count, primCount) { + const { ctx } = this + mode |= 0 + first |= 0 + count |= 0 + primCount |= 0 + if (first < 0 || count < 0 || primCount < 0) { + ctx.setError(gl.INVALID_VALUE) + return + } + if (!ctx._checkStencilState()) { + return + } + const reducedCount = vertexCount(mode, count) + if (reducedCount < 0) { + ctx.setError(gl.INVALID_ENUM) + return + } + if (!ctx._framebufferOk()) { + return + } + if (count === 0 || primCount === 0) { + return + } + let maxIndex = first + if (count > 0) { + maxIndex = (count + first - 1) >>> 0 + } + if (this.checkInstancedVertexAttribState(maxIndex, primCount)) { + return this._drawArraysInstanced(mode, first, reducedCount, primCount) + } + } + + drawElementsInstancedANGLE (mode, count, type, ioffset, primCount) { + const { ctx } = this + mode |= 0 + count |= 0 + type |= 0 + ioffset |= 0 + primCount |= 0 + + if (count < 0 || ioffset < 0 || primCount < 0) { + ctx.setError(gl.INVALID_VALUE) + return + } + + if (!ctx._checkStencilState()) { + return + } + + const elementBuffer = ctx._vertexObjectState._elementArrayBufferBinding + if (!elementBuffer) { + ctx.setError(gl.INVALID_OPERATION) + return + } + + // Unpack element data + let elementData = null + let offset = ioffset + if (type === gl.UNSIGNED_SHORT) { + if (offset % 2) { + ctx.setError(gl.INVALID_OPERATION) + return + } + offset >>= 1 + elementData = new Uint16Array(elementBuffer._elements.buffer) + } else if (ctx._extensions.oes_element_index_uint && type === gl.UNSIGNED_INT) { + if (offset % 4) { + ctx.setError(gl.INVALID_OPERATION) + return + } + offset >>= 2 + elementData = new Uint32Array(elementBuffer._elements.buffer) + } else if (type === gl.UNSIGNED_BYTE) { + elementData = elementBuffer._elements + } else { + ctx.setError(gl.INVALID_ENUM) + return + } + + let reducedCount = count + switch (mode) { + case gl.TRIANGLES: + if (count % 3) { + reducedCount -= (count % 3) + } + break + case gl.LINES: + if (count % 2) { + reducedCount -= (count % 2) + } + break + case gl.POINTS: + break + case gl.LINE_LOOP: + case gl.LINE_STRIP: + if (count < 2) { + ctx.setError(gl.INVALID_OPERATION) + return + } + break + case gl.TRIANGLE_FAN: + case gl.TRIANGLE_STRIP: + if (count < 3) { + ctx.setError(gl.INVALID_OPERATION) + return + } + break + default: + ctx.setError(gl.INVALID_ENUM) + return + } + + if (!ctx._framebufferOk()) { + return + } + + if (count === 0 || primCount === 0) { + this.checkInstancedVertexAttribState(0, 0) + return + } + + if ((count + offset) >>> 0 > elementData.length) { + ctx.setError(gl.INVALID_OPERATION) + return + } + + // Compute max index + let maxIndex = -1 + for (let i = offset; i < offset + count; ++i) { + maxIndex = Math.max(maxIndex, elementData[i]) + } + + if (maxIndex < 0) { + this.checkInstancedVertexAttribState(0, 0) + return + } + + if (this.checkInstancedVertexAttribState(maxIndex, primCount)) { + if (reducedCount > 0) { + this._drawElementsInstanced(mode, reducedCount, type, ioffset, primCount) + } + } + } + + vertexAttribDivisorANGLE (index, divisor) { + const { ctx } = this + index |= 0 + divisor |= 0 + if (divisor < 0 || + index < 0 || index >= ctx._vertexObjectState._attribs.length) { + ctx.setError(gl.INVALID_VALUE) + return + } + const attrib = ctx._vertexObjectState._attribs[index] + attrib._divisor = divisor + this._vertexAttribDivisor(index, divisor) + } + + checkInstancedVertexAttribState (maxIndex, primCount) { + const { ctx } = this + const program = ctx._activeProgram + if (!program) { + ctx.setError(gl.INVALID_OPERATION) + return false + } + + const attribs = ctx._vertexObjectState._attribs + let hasZero = false + for (let i = 0; i < attribs.length; ++i) { + const attrib = attribs[i] + if (attrib._isPointer) { + const buffer = attrib._pointerBuffer + if (program._attributes.indexOf(i) >= 0) { + if (!buffer) { + ctx.setError(gl.INVALID_OPERATION) + return false + } + let maxByte = 0 + if (attrib._divisor === 0) { + hasZero = true + maxByte = attrib._pointerStride * maxIndex + + attrib._pointerSize + + attrib._pointerOffset + } else { + maxByte = attrib._pointerStride * (Math.ceil(primCount / attrib._divisor) - 1) + + attrib._pointerSize + + attrib._pointerOffset + } + if (maxByte > buffer._size) { + ctx.setError(gl.INVALID_OPERATION) + return false + } + } + } + } + + if (!hasZero) { + ctx.setError(gl.INVALID_OPERATION) + return false + } + + return true + } +} + +function getANGLEInstancedArrays (ctx) { + return new ANGLEInstancedArrays(ctx) +} + +module.exports = { ANGLEInstancedArrays, getANGLEInstancedArrays } + +},{"../native-gl":151,"../utils":153}],140:[function(require,module,exports){ +class EXTBlendMinMax { + constructor () { + this.MIN_EXT = 0x8007 + this.MAX_EXT = 0x8008 + } +} + +function getEXTBlendMinMax (context) { + let result = null + const exts = context.getSupportedExtensions() + + if (exts && exts.indexOf('EXT_blend_minmax') >= 0) { + result = new EXTBlendMinMax() + } + + return result +} + +module.exports = { getEXTBlendMinMax, EXTBlendMinMax } + +},{}],141:[function(require,module,exports){ +class EXTTextureFilterAnisotropic { + constructor () { + this.TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE + this.MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF + } +} + +function getEXTTextureFilterAnisotropic (context) { + let result = null + const exts = context.getSupportedExtensions() + + if (exts && exts.indexOf('EXT_texture_filter_anisotropic') >= 0) { + result = new EXTTextureFilterAnisotropic() + } + + return result +} + +module.exports = { getEXTTextureFilterAnisotropic, EXTTextureFilterAnisotropic } + +},{}],142:[function(require,module,exports){ +class OESElementIndexUint {} + +function getOESElementIndexUint (context) { + let result = null + const exts = context.getSupportedExtensions() + + if (exts && exts.indexOf('OES_element_index_uint') >= 0) { + result = new OESElementIndexUint() + } + + return result +} + +module.exports = { getOESElementIndexUint, OESElementIndexUint } + +},{}],143:[function(require,module,exports){ +class OESStandardDerivatives { + constructor () { + this.FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B + } +} + +function getOESStandardDerivatives (context) { + let result = null + const exts = context.getSupportedExtensions() + + if (exts && exts.indexOf('OES_standard_derivatives') >= 0) { + result = new OESStandardDerivatives() + } + + return result +} + +module.exports = { getOESStandardDerivatives, OESStandardDerivatives } + +},{}],144:[function(require,module,exports){ +class OESTextureFloatLinear {} + +function getOESTextureFloatLinear (context) { + let result = null + const exts = context.getSupportedExtensions() + + if (exts && exts.indexOf('OES_texture_float_linear') >= 0) { + result = new OESTextureFloatLinear() + } + + return result +} + +module.exports = { getOESTextureFloatLinear, OESTextureFloatLinear } + +},{}],145:[function(require,module,exports){ +class OESTextureFloat {} + +function getOESTextureFloat (context) { + let result = null + const exts = context.getSupportedExtensions() + + if (exts && exts.indexOf('OES_texture_float') >= 0) { + result = new OESTextureFloat() + } + + return result +} + +module.exports = { getOESTextureFloat, OESTextureFloat } + +},{}],146:[function(require,module,exports){ +const { Linkable } = require('../linkable') +const { gl } = require('../native-gl') +const { checkObject } = require('../utils') +const { WebGLVertexArrayObjectState } = require('../webgl-vertex-attribute') + +class WebGLVertexArrayObjectOES extends Linkable { + constructor (_, ctx, ext) { + super(_) + this._ctx = ctx + this._ext = ext + this._vertexState = new WebGLVertexArrayObjectState(ctx) + } + + _performDelete () { + // Clean up the vertex state to release references to buffers. + this._vertexState.cleanUp() + + delete this._vertexState + delete this._ext._vaos[this._] + gl.deleteVertexArrayOES.call(this._ctx, this._ | 0) + } +} + +class OESVertexArrayObject { + constructor (ctx) { + this.VERTEX_ARRAY_BINDING_OES = 0x85B5 + + this._ctx = ctx + this._vaos = {} + this._activeVertexArrayObject = null + } + + createVertexArrayOES () { + const { _ctx: ctx } = this + const arrayId = gl.createVertexArrayOES.call(ctx) + if (arrayId <= 0) return null + const array = new WebGLVertexArrayObjectOES(arrayId, ctx, this) + this._vaos[arrayId] = array + return array + } + + deleteVertexArrayOES (array) { + const { _ctx: ctx } = this + if (!checkObject(array)) { + throw new TypeError('deleteVertexArrayOES(WebGLVertexArrayObjectOES)') + } + + if (!(array instanceof WebGLVertexArrayObjectOES && + ctx._checkOwns(array))) { + ctx.setError(gl.INVALID_OPERATION) + return + } + + if (array._pendingDelete) { + return + } + + if (this._activeVertexArrayObject === array) { + this.bindVertexArrayOES(null) + } + + array._pendingDelete = true + array._checkDelete() + } + + bindVertexArrayOES (array) { + const { _ctx: ctx, _activeVertexArrayObject: activeVertexArrayObject } = this + if (!checkObject(array)) { + throw new TypeError('bindVertexArrayOES(WebGLVertexArrayObjectOES)') + } + + if (!array) { + array = null + gl.bindVertexArrayOES.call(ctx, null) + } else if (array instanceof WebGLVertexArrayObjectOES && + array._pendingDelete) { + ctx.setError(gl.INVALID_OPERATION) + return + } else if (ctx._checkWrapper(array, WebGLVertexArrayObjectOES)) { + gl.bindVertexArrayOES.call(ctx, array._) + } else { + return + } + + if (activeVertexArrayObject !== array) { + if (activeVertexArrayObject) { + activeVertexArrayObject._refCount -= 1 + activeVertexArrayObject._checkDelete() + } + if (array) { + array._refCount += 1 + } + } + + if (array === null) { + ctx._vertexObjectState = ctx._defaultVertexObjectState + } else { + ctx._vertexObjectState = array._vertexState + } + + // Update the active vertex array object. + this._activeVertexArrayObject = array + } + + isVertexArrayOES (object) { + const { _ctx: ctx } = this + if (!ctx._isObject(object, 'isVertexArrayOES', WebGLVertexArrayObjectOES)) return false + return gl.isVertexArrayOES.call(ctx, object._ | 0) + } +} + +function getOESVertexArrayObject (ctx) { + const exts = ctx.getSupportedExtensions() + + if (exts && exts.indexOf('OES_vertex_array_object') >= 0) { + return new OESVertexArrayObject(ctx) + } else { + return null + } +} + +module.exports = { + WebGLVertexArrayObjectOES, + OESVertexArrayObject, + getOESVertexArrayObject +} + +},{"../linkable":150,"../native-gl":151,"../utils":153,"../webgl-vertex-attribute":167}],147:[function(require,module,exports){ +class STACKGLDestroyContext { + constructor (ctx) { + this.destroy = ctx.destroy.bind(ctx) + } +} + +function getSTACKGLDestroyContext (ctx) { + return new STACKGLDestroyContext(ctx) +} + +module.exports = { getSTACKGLDestroyContext, STACKGLDestroyContext } + +},{}],148:[function(require,module,exports){ +class STACKGLResizeDrawingBuffer { + constructor (ctx) { + this.resize = ctx.resize.bind(ctx) + } +} + +function getSTACKGLResizeDrawingBuffer (ctx) { + return new STACKGLResizeDrawingBuffer(ctx) +} + +module.exports = { getSTACKGLResizeDrawingBuffer, STACKGLResizeDrawingBuffer } + +},{}],149:[function(require,module,exports){ +const { gl } = require('../native-gl') + +class WebGLDrawBuffers { + constructor (ctx) { + this.ctx = ctx + const exts = ctx.getSupportedExtensions() + + if (exts && exts.indexOf('WEBGL_draw_buffers') >= 0) { + Object.assign(this, ctx.extWEBGL_draw_buffers()) + this._buffersState = [ctx.BACK] + this._maxDrawBuffers = ctx._getParameterDirect(this.MAX_DRAW_BUFFERS_WEBGL) + this._ALL_ATTACHMENTS = [] + this._ALL_COLOR_ATTACHMENTS = [] + const allColorAttachments = [ + this.COLOR_ATTACHMENT0_WEBGL, + this.COLOR_ATTACHMENT1_WEBGL, + this.COLOR_ATTACHMENT2_WEBGL, + this.COLOR_ATTACHMENT3_WEBGL, + this.COLOR_ATTACHMENT4_WEBGL, + this.COLOR_ATTACHMENT5_WEBGL, + this.COLOR_ATTACHMENT6_WEBGL, + this.COLOR_ATTACHMENT7_WEBGL, + this.COLOR_ATTACHMENT8_WEBGL, + this.COLOR_ATTACHMENT9_WEBGL, + this.COLOR_ATTACHMENT10_WEBGL, + this.COLOR_ATTACHMENT11_WEBGL, + this.COLOR_ATTACHMENT12_WEBGL, + this.COLOR_ATTACHMENT13_WEBGL, + this.COLOR_ATTACHMENT14_WEBGL, + this.COLOR_ATTACHMENT15_WEBGL + ] + while (this._ALL_ATTACHMENTS.length < this._maxDrawBuffers) { + const colorAttachment = allColorAttachments.shift() + this._ALL_ATTACHMENTS.push(colorAttachment) + this._ALL_COLOR_ATTACHMENTS.push(colorAttachment) + } + this._ALL_ATTACHMENTS.push( + gl.DEPTH_ATTACHMENT, + gl.STENCIL_ATTACHMENT, + gl.DEPTH_STENCIL_ATTACHMENT + ) + } + } + + drawBuffersWEBGL (buffers) { + const { ctx } = this + if (buffers.length < 1) { + ctx.setError(gl.INVALID_OPERATION) + return + } + if (buffers.length === 1 && buffers[0] === gl.BACK) { + this._buffersState = buffers + ctx.drawBuffersWEBGL([this.COLOR_ATTACHMENT0_WEBGL]) + return + } else if (!ctx._activeFramebuffer) { + if (buffers.length > 1) { + ctx.setError(gl.INVALID_OPERATION) + return + } + for (let i = 0; i < buffers.length; i++) { + if (buffers[i] > gl.NONE) { + ctx.setError(gl.INVALID_OPERATION) + return + } + } + } + this._buffersState = buffers + ctx.drawBuffersWEBGL(buffers) + } +} + +function getWebGLDrawBuffers (ctx) { + const exts = ctx.getSupportedExtensions() + + if (exts && exts.indexOf('WEBGL_draw_buffers') >= 0) { + return new WebGLDrawBuffers(ctx) + } else { + return null + } +} + +module.exports = { + getWebGLDrawBuffers, + WebGLDrawBuffers +} + +},{"../native-gl":151}],150:[function(require,module,exports){ +class Linkable { + constructor (_) { + this._ = _ + this._references = [] + this._refCount = 0 + this._pendingDelete = false + this._binding = 0 + } + + _link (b) { + this._references.push(b) + b._refCount += 1 + return true + } + + _unlink (b) { + let idx = this._references.indexOf(b) + if (idx < 0) { + return false + } + while (idx >= 0) { + this._references[idx] = this._references[this._references.length - 1] + this._references.pop() + b._refCount -= 1 + b._checkDelete() + idx = this._references.indexOf(b) + } + return true + } + + _linked (b) { + return this._references.indexOf(b) >= 0 + } + + _checkDelete () { + if (this._refCount <= 0 && + this._pendingDelete && + this._ !== 0) { + while (this._references.length > 0) { + this._unlink(this._references[0]) + } + this._performDelete() + this._ = 0 + } + } + + _performDelete () {} +} + +module.exports = { Linkable } + +},{}],151:[function(require,module,exports){ +(function (process){ +const NativeWebGL = require('bindings')('webgl') +const { WebGLRenderingContext: NativeWebGLRenderingContext } = NativeWebGL +process.on('exit', NativeWebGL.cleanup) + +const gl = NativeWebGLRenderingContext.prototype + +// from binding.gyp +delete gl['1.0.0'] + +// from binding.gyp +delete NativeWebGLRenderingContext['1.0.0'] + +module.exports = { gl, NativeWebGL, NativeWebGLRenderingContext } + +}).call(this,require('_process')) +},{"_process":437,"bindings":31}],152:[function(require,module,exports){ +const bits = require('bit-twiddle') +const { WebGLContextAttributes } = require('./webgl-context-attributes') +const { WebGLRenderingContext, wrapContext } = require('./webgl-rendering-context') +const { WebGLTextureUnit } = require('./webgl-texture-unit') +const { WebGLVertexArrayObjectState, WebGLVertexArrayGlobalState } = require('./webgl-vertex-attribute') + +let CONTEXT_COUNTER = 0 + +function flag (options, name, dflt) { + if (!options || !(typeof options === 'object') || !(name in options)) { + return dflt + } + return !!options[name] +} + +function createContext (width, height, options) { + width = width | 0 + height = height | 0 + if (!(width > 0 && height > 0)) { + return null + } + + const contextAttributes = new WebGLContextAttributes( + flag(options, 'alpha', true), + flag(options, 'depth', true), + flag(options, 'stencil', false), + false, // flag(options, 'antialias', true), + flag(options, 'premultipliedAlpha', true), + flag(options, 'preserveDrawingBuffer', false), + flag(options, 'preferLowPowerToHighPerformance', false), + flag(options, 'failIfMajorPerformanceCaveat', false)) + + // Can only use premultipliedAlpha if alpha is set + contextAttributes.premultipliedAlpha = + contextAttributes.premultipliedAlpha && contextAttributes.alpha + + let ctx + try { + ctx = new WebGLRenderingContext( + 1, + 1, + contextAttributes.alpha, + contextAttributes.depth, + contextAttributes.stencil, + contextAttributes.antialias, + contextAttributes.premultipliedAlpha, + contextAttributes.preserveDrawingBuffer, + contextAttributes.preferLowPowerToHighPerformance, + contextAttributes.failIfMajorPerformanceCaveat) + } catch (e) {} + if (!ctx) { + return null + } + + ctx.drawingBufferWidth = width + ctx.drawingBufferHeight = height + + ctx._ = CONTEXT_COUNTER++ + + ctx._contextAttributes = contextAttributes + + ctx._extensions = {} + ctx._programs = {} + ctx._shaders = {} + ctx._buffers = {} + ctx._textures = {} + ctx._framebuffers = {} + ctx._renderbuffers = {} + + ctx._activeProgram = null + ctx._activeFramebuffer = null + ctx._activeRenderbuffer = null + ctx._checkStencil = false + ctx._stencilState = true + + // Initialize texture units + const numTextures = ctx.getParameter(ctx.MAX_COMBINED_TEXTURE_IMAGE_UNITS) + ctx._textureUnits = new Array(numTextures) + for (let i = 0; i < numTextures; ++i) { + ctx._textureUnits[i] = new WebGLTextureUnit(i) + } + ctx._activeTextureUnit = 0 + ctx.activeTexture(ctx.TEXTURE0) + + ctx._errorStack = [] + + // Vertex array attributes that are in vertex array objects. + ctx._defaultVertexObjectState = new WebGLVertexArrayObjectState(ctx) + ctx._vertexObjectState = ctx._defaultVertexObjectState + + // Vertex array attibures that are not in vertex array objects. + ctx._vertexGlobalState = new WebGLVertexArrayGlobalState(ctx) + + // Store limits + ctx._maxTextureSize = ctx.getParameter(ctx.MAX_TEXTURE_SIZE) + ctx._maxTextureLevel = bits.log2(bits.nextPow2(ctx._maxTextureSize)) + ctx._maxCubeMapSize = ctx.getParameter(ctx.MAX_CUBE_MAP_TEXTURE_SIZE) + ctx._maxCubeMapLevel = bits.log2(bits.nextPow2(ctx._maxCubeMapSize)) + + // Unpack alignment + ctx._unpackAlignment = 4 + ctx._packAlignment = 4 + + // Allocate framebuffer + ctx._allocateDrawingBuffer(width, height) + + const attrib0Buffer = ctx.createBuffer() + ctx._attrib0Buffer = attrib0Buffer + + // Initialize defaults + ctx.bindBuffer(ctx.ARRAY_BUFFER, null) + ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null) + ctx.bindFramebuffer(ctx.FRAMEBUFFER, null) + ctx.bindRenderbuffer(ctx.RENDERBUFFER, null) + + // Set viewport and scissor + ctx.viewport(0, 0, width, height) + ctx.scissor(0, 0, width, height) + + // Clear buffers + ctx.clearDepth(1) + ctx.clearColor(0, 0, 0, 0) + ctx.clearStencil(0) + ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT | ctx.STENCIL_BUFFER_BIT) + + return wrapContext(ctx) +} + +module.exports = createContext + +},{"./webgl-context-attributes":156,"./webgl-rendering-context":161,"./webgl-texture-unit":164,"./webgl-vertex-attribute":167,"bit-twiddle":32}],153:[function(require,module,exports){ +(function (Buffer){ +const { gl } = require('./native-gl') + +const { WebGLUniformLocation } = require('./webgl-uniform-location') + +function bindPublics (props, wrapper, privateInstance, privateMethods) { + for (let i = 0; i < props.length; i++) { + const prop = props[i] + const value = privateInstance[prop] + if (typeof value === 'function') { + if (privateMethods.indexOf(prop) === -1) { + wrapper[prop] = value.bind(privateInstance) + } + } else { + if (prop[0] === '_' || + prop[0] === '0' || + prop[0] === '1') { + continue + } + wrapper[prop] = value + } + } +} + +function checkObject (object) { + return typeof object === 'object' || + (object === undefined) +} + +function checkUniform (program, location) { + return location instanceof WebGLUniformLocation && + location._program === program && + location._linkCount === program._linkCount +} + +function isTypedArray (data) { + return data instanceof Uint8Array || + data instanceof Uint8ClampedArray || + data instanceof Int8Array || + data instanceof Uint16Array || + data instanceof Int16Array || + data instanceof Uint32Array || + data instanceof Int32Array || + data instanceof Float32Array || + data instanceof Float64Array +} + +// Don't allow: ", $, `, @, \, ', \0 +function isValidString (str) { + // Remove comments first + const c = str.replace(/(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm, '') + return !(/["$`@\\'\0]/.test(c)) +} + +function vertexCount (primitive, count) { + switch (primitive) { + case gl.TRIANGLES: + return count - (count % 3) + case gl.LINES: + return count - (count % 2) + case gl.LINE_LOOP: + case gl.POINTS: + return count + case gl.TRIANGLE_FAN: + case gl.LINE_STRIP: + if (count < 2) { + return 0 + } + return count + case gl.TRIANGLE_STRIP: + if (count < 3) { + return 0 + } + return count + default: + return -1 + } +} + +function typeSize (type) { + switch (type) { + case gl.UNSIGNED_BYTE: + case gl.BYTE: + return 1 + case gl.UNSIGNED_SHORT: + case gl.SHORT: + return 2 + case gl.UNSIGNED_INT: + case gl.INT: + case gl.FLOAT: + return 4 + } + return 0 +} + +function uniformTypeSize (type) { + switch (type) { + case gl.BOOL_VEC4: + case gl.INT_VEC4: + case gl.FLOAT_VEC4: + return 4 + + case gl.BOOL_VEC3: + case gl.INT_VEC3: + case gl.FLOAT_VEC3: + return 3 + + case gl.BOOL_VEC2: + case gl.INT_VEC2: + case gl.FLOAT_VEC2: + return 2 + + case gl.BOOL: + case gl.INT: + case gl.FLOAT: + case gl.SAMPLER_2D: + case gl.SAMPLER_CUBE: + return 1 + + default: + return 0 + } +} + +function unpackTypedArray (array) { + return (new Uint8Array(array.buffer)).subarray( + array.byteOffset, + array.byteLength + array.byteOffset) +} + +function extractImageData (pixels) { + if (typeof pixels === 'object' && typeof pixels.width !== 'undefined' && typeof pixels.height !== 'undefined') { + if (typeof pixels.data !== 'undefined') { + return pixels + } + + let context = null + + if (typeof pixels.getContext === 'function') { + context = pixels.getContext('2d') + } else if (typeof pixels.src !== 'undefined' && typeof document === 'object' && typeof document.createElement === 'function') { + const canvas = document.createElement('canvas') + + if (typeof canvas === 'object' && typeof canvas.getContext === 'function') { + context = canvas.getContext('2d') + + if (context !== null) { + context.drawImage(pixels, 0, 0) + } + } + } + + if (context !== null) { + return context.getImageData(0, 0, pixels.width, pixels.height) + } + } + + return null +} + +function formatSize (internalFormat) { + switch (internalFormat) { + case gl.ALPHA: + case gl.LUMINANCE: + return 1 + case gl.LUMINANCE_ALPHA: + return 2 + case gl.RGB: + return 3 + case gl.RGBA: + return 4 + } + return 0 +} + +function convertPixels (pixels) { + if (typeof pixels === 'object' && pixels !== null) { + if (pixels instanceof ArrayBuffer) { + return new Uint8Array(pixels) + } else if (pixels instanceof Uint8Array || + pixels instanceof Uint16Array || + pixels instanceof Uint8ClampedArray || + pixels instanceof Float32Array) { + return unpackTypedArray(pixels) + } else if (pixels instanceof Buffer) { + return new Uint8Array(pixels) + } + } + return null +} + +function checkFormat (format) { + return ( + format === gl.ALPHA || + format === gl.LUMINANCE_ALPHA || + format === gl.LUMINANCE || + format === gl.RGB || + format === gl.RGBA) +} + +function validCubeTarget (target) { + return target === gl.TEXTURE_CUBE_MAP_POSITIVE_X || + target === gl.TEXTURE_CUBE_MAP_NEGATIVE_X || + target === gl.TEXTURE_CUBE_MAP_POSITIVE_Y || + target === gl.TEXTURE_CUBE_MAP_NEGATIVE_Y || + target === gl.TEXTURE_CUBE_MAP_POSITIVE_Z || + target === gl.TEXTURE_CUBE_MAP_NEGATIVE_Z +} + +module.exports = { + bindPublics, + checkObject, + isTypedArray, + isValidString, + vertexCount, + typeSize, + uniformTypeSize, + unpackTypedArray, + extractImageData, + formatSize, + checkFormat, + checkUniform, + convertPixels, + validCubeTarget +} + +}).call(this,require("buffer").Buffer) +},{"./native-gl":151,"./webgl-uniform-location":166,"buffer":299}],154:[function(require,module,exports){ +class WebGLActiveInfo { + constructor (_) { + this.size = _.size + this.type = _.type + this.name = _.name + } +} +module.exports = { WebGLActiveInfo } + +},{}],155:[function(require,module,exports){ +const { Linkable } = require('./linkable') +const { gl } = require('./native-gl') + +class WebGLBuffer extends Linkable { + constructor (_, ctx) { + super(_) + this._ctx = ctx + this._size = 0 + this._elements = new Uint8Array(0) + } + + _performDelete () { + const ctx = this._ctx + delete ctx._buffers[this._ | 0] + gl.deleteBuffer.call(ctx, this._ | 0) + } +} + +module.exports = { WebGLBuffer } + +},{"./linkable":150,"./native-gl":151}],156:[function(require,module,exports){ +class WebGLContextAttributes { + constructor ( + alpha, + depth, + stencil, + antialias, + premultipliedAlpha, + preserveDrawingBuffer, + preferLowPowerToHighPerformance, + failIfMajorPerformanceCaveat) { + this.alpha = alpha + this.depth = depth + this.stencil = stencil + this.antialias = antialias + this.premultipliedAlpha = premultipliedAlpha + this.preserveDrawingBuffer = preserveDrawingBuffer + this.preferLowPowerToHighPerformance = preferLowPowerToHighPerformance + this.failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat + } +} + +module.exports = { WebGLContextAttributes } + +},{}],157:[function(require,module,exports){ +class WebGLDrawingBufferWrapper { + constructor (framebuffer, color, depthStencil) { + this._framebuffer = framebuffer + this._color = color + this._depthStencil = depthStencil + } +} + +module.exports = { WebGLDrawingBufferWrapper } + +},{}],158:[function(require,module,exports){ +const { Linkable } = require('./linkable') +const { gl } = require('./native-gl') + +class WebGLFramebuffer extends Linkable { + constructor (_, ctx) { + super(_) + this._ctx = ctx + this._binding = 0 + + this._width = 0 + this._height = 0 + this._status = null + + this._attachments = {} + this._attachments[gl.COLOR_ATTACHMENT0] = null + this._attachments[gl.DEPTH_ATTACHMENT] = null + this._attachments[gl.STENCIL_ATTACHMENT] = null + this._attachments[gl.DEPTH_STENCIL_ATTACHMENT] = null + + this._attachmentLevel = {} + this._attachmentLevel[gl.COLOR_ATTACHMENT0] = 0 + this._attachmentLevel[gl.DEPTH_ATTACHMENT] = 0 + this._attachmentLevel[gl.STENCIL_ATTACHMENT] = 0 + this._attachmentLevel[gl.DEPTH_STENCIL_ATTACHMENT] = 0 + + this._attachmentFace = {} + this._attachmentFace[gl.COLOR_ATTACHMENT0] = 0 + this._attachmentFace[gl.DEPTH_ATTACHMENT] = 0 + this._attachmentFace[gl.STENCIL_ATTACHMENT] = 0 + this._attachmentFace[gl.DEPTH_STENCIL_ATTACHMENT] = 0 + + if (ctx._extensions.webgl_draw_buffers) { + const { webgl_draw_buffers } = ctx._extensions // eslint-disable-line + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT1_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT2_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT3_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT4_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT5_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT6_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT7_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT8_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT9_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT10_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT11_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT12_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT13_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT14_WEBGL] = null + this._attachments[webgl_draw_buffers.COLOR_ATTACHMENT15_WEBGL] = null + this._attachments[gl.NONE] = null + this._attachments[gl.BACK] = null + + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT1_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT2_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT3_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT4_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT5_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT6_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT7_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT8_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT9_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT10_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT11_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT12_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT13_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT14_WEBGL] = 0 + this._attachmentLevel[webgl_draw_buffers.COLOR_ATTACHMENT15_WEBGL] = 0 + this._attachmentLevel[gl.NONE] = null + this._attachmentLevel[gl.BACK] = null + + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT1_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT2_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT3_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT4_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT5_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT6_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT7_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT8_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT9_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT10_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT11_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT12_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT13_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT14_WEBGL] = 0 + this._attachmentFace[webgl_draw_buffers.COLOR_ATTACHMENT15_WEBGL] = 0 + this._attachmentFace[gl.NONE] = null + this._attachmentFace[gl.BACK] = null + } + } + + _clearAttachment (attachment) { + const object = this._attachments[attachment] + if (!object) { + return + } + this._attachments[attachment] = null + this._unlink(object) + } + + _setAttachment (object, attachment) { + const prevObject = this._attachments[attachment] + if (prevObject === object) { + return + } + + this._clearAttachment(attachment) + if (!object) { + return + } + + this._attachments[attachment] = object + + this._link(object) + } + + _performDelete () { + const ctx = this._ctx + delete ctx._framebuffers[this._ | 0] + gl.deleteFramebuffer.call(ctx, this._ | 0) + } +} + +module.exports = { WebGLFramebuffer } + +},{"./linkable":150,"./native-gl":151}],159:[function(require,module,exports){ +const { Linkable } = require('./linkable') +const { gl } = require('./native-gl') + +class WebGLProgram extends Linkable { + constructor (_, ctx) { + super(_) + this._ctx = ctx + this._linkCount = 0 + this._linkStatus = false + this._linkInfoLog = 'not linked' + this._attributes = [] + this._uniforms = [] + } + + _performDelete () { + const ctx = this._ctx + delete ctx._programs[this._ | 0] + gl.deleteProgram.call(ctx, this._ | 0) + } +} + +module.exports = { WebGLProgram } + +},{"./linkable":150,"./native-gl":151}],160:[function(require,module,exports){ +const { Linkable } = require('./linkable') +const { gl } = require('./native-gl') + +class WebGLRenderbuffer extends Linkable { + constructor (_, ctx) { + super(_) + this._ctx = ctx + this._binding = 0 + this._width = 0 + this._height = 0 + this._format = 0 + } + + _performDelete () { + const ctx = this._ctx + delete ctx._renderbuffers[this._ | 0] + gl.deleteRenderbuffer.call(ctx, this._ | 0) + } +} + +module.exports = { WebGLRenderbuffer } + +},{"./linkable":150,"./native-gl":151}],161:[function(require,module,exports){ +const bits = require('bit-twiddle') +const tokenize = require('glsl-tokenizer/string') +const HEADLESS_VERSION = require('../../package.json').version +const { gl, NativeWebGLRenderingContext, NativeWebGL } = require('./native-gl') +const { getANGLEInstancedArrays } = require('./extensions/angle-instanced-arrays') +const { getOESElementIndexUint } = require('./extensions/oes-element-index-unit') +const { getOESStandardDerivatives } = require('./extensions/oes-standard-derivatives') +const { getOESTextureFloat } = require('./extensions/oes-texture-float') +const { getOESTextureFloatLinear } = require('./extensions/oes-texture-float-linear') +const { getSTACKGLDestroyContext } = require('./extensions/stackgl-destroy-context') +const { getSTACKGLResizeDrawingBuffer } = require('./extensions/stackgl-resize-drawing-buffer') +const { getWebGLDrawBuffers } = require('./extensions/webgl-draw-buffers') +const { getEXTBlendMinMax } = require('./extensions/ext-blend-minmax') +const { getEXTTextureFilterAnisotropic } = require('./extensions/ext-texture-filter-anisotropic') +const { getOESVertexArrayObject } = require('./extensions/oes-vertex-array-object') +const { + bindPublics, + checkObject, + checkUniform, + formatSize, + isValidString, + typeSize, + uniformTypeSize, + extractImageData, + vertexCount, + isTypedArray, + unpackTypedArray, + convertPixels, + checkFormat, + validCubeTarget +} = require('./utils') + +const { WebGLActiveInfo } = require('./webgl-active-info') +const { WebGLFramebuffer } = require('./webgl-framebuffer') +const { WebGLBuffer } = require('./webgl-buffer') +const { WebGLDrawingBufferWrapper } = require('./webgl-drawing-buffer-wrapper') +const { WebGLProgram } = require('./webgl-program') +const { WebGLRenderbuffer } = require('./webgl-renderbuffer') +const { WebGLShader } = require('./webgl-shader') +const { WebGLShaderPrecisionFormat } = require('./webgl-shader-precision-format') +const { WebGLTexture } = require('./webgl-texture') +const { WebGLUniformLocation } = require('./webgl-uniform-location') + +// These are defined by the WebGL spec +const MAX_UNIFORM_LENGTH = 256 +const MAX_ATTRIBUTE_LENGTH = 256 + +const DEFAULT_ATTACHMENTS = [ + gl.COLOR_ATTACHMENT0, + gl.DEPTH_ATTACHMENT, + gl.STENCIL_ATTACHMENT, + gl.DEPTH_STENCIL_ATTACHMENT +] + +const DEFAULT_COLOR_ATTACHMENTS = [gl.COLOR_ATTACHMENT0] + +const availableExtensions = { + angle_instanced_arrays: getANGLEInstancedArrays, + oes_element_index_uint: getOESElementIndexUint, + oes_texture_float: getOESTextureFloat, + oes_texture_float_linear: getOESTextureFloatLinear, + oes_standard_derivatives: getOESStandardDerivatives, + oes_vertex_array_object: getOESVertexArrayObject, + stackgl_destroy_context: getSTACKGLDestroyContext, + stackgl_resize_drawingbuffer: getSTACKGLResizeDrawingBuffer, + webgl_draw_buffers: getWebGLDrawBuffers, + ext_blend_minmax: getEXTBlendMinMax, + ext_texture_filter_anisotropic: getEXTTextureFilterAnisotropic +} + +const privateMethods = [ + 'resize', + 'destroy' +] + +function wrapContext (ctx) { + const wrapper = new WebGLRenderingContext() + bindPublics(Object.keys(ctx), wrapper, ctx, privateMethods) + bindPublics(Object.keys(ctx.constructor.prototype), wrapper, ctx, privateMethods) + bindPublics(Object.getOwnPropertyNames(ctx), wrapper, ctx, privateMethods) + bindPublics(Object.getOwnPropertyNames(ctx.constructor.prototype), wrapper, ctx, privateMethods) + + Object.defineProperties(wrapper, { + drawingBufferWidth: { + get () { return ctx.drawingBufferWidth }, + set (value) { ctx.drawingBufferWidth = value } + }, + drawingBufferHeight: { + get () { return ctx.drawingBufferHeight }, + set (value) { ctx.drawingBufferHeight = value } + } + }) + + return wrapper +} + +// We need to wrap some of the native WebGL functions to handle certain error codes and check input values +class WebGLRenderingContext extends NativeWebGLRenderingContext { + _checkDimensions ( + target, + width, + height, + level) { + if (level < 0 || + width < 0 || + height < 0) { + this.setError(gl.INVALID_VALUE) + return false + } + if (target === gl.TEXTURE_2D) { + if (width > this._maxTextureSize || + height > this._maxTextureSize || + level > this._maxTextureLevel) { + this.setError(gl.INVALID_VALUE) + return false + } + } else if (this._validCubeTarget(target)) { + if (width > this._maxCubeMapSize || + height > this._maxCubeMapSize || + level > this._maxCubeMapLevel) { + this.setError(gl.INVALID_VALUE) + return false + } + } else { + this.setError(gl.INVALID_ENUM) + return false + } + return true + } + + _checkLocation (location) { + if (!(location instanceof WebGLUniformLocation)) { + this.setError(gl.INVALID_VALUE) + return false + } else if (location._program._ctx !== this || + location._linkCount !== location._program._linkCount) { + this.setError(gl.INVALID_OPERATION) + return false + } + return true + } + + _checkLocationActive (location) { + if (!location) { + return false + } else if (!this._checkLocation(location)) { + return false + } else if (location._program !== this._activeProgram) { + this.setError(gl.INVALID_OPERATION) + return false + } + return true + } + + _checkOwns (object) { + return typeof object === 'object' && + object._ctx === this + } + + _checkShaderSource (shader) { + const source = shader._source + const tokens = tokenize(source) + + let errorStatus = false + const errorLog = [] + + for (let i = 0; i < tokens.length; ++i) { + const tok = tokens[i] + switch (tok.type) { + case 'ident': + if (!this._validGLSLIdentifier(tok.data)) { + errorStatus = true + errorLog.push(tok.line + ':' + tok.column + + ' invalid identifier - ' + tok.data) + } + break + case 'preprocessor': { + const bodyToks = tokenize(tok.data.match(/^\s*#\s*(.*)$/)[1]) + for (let j = 0; j < bodyToks.length; ++j) { + const btok = bodyToks[j] + if (btok.type === 'ident' || btok.type === undefined) { + if (!this._validGLSLIdentifier(btok.data)) { + errorStatus = true + errorLog.push(tok.line + ':' + btok.column + + ' invalid identifier - ' + btok.data) + } + } + } + break + } + case 'keyword': + switch (tok.data) { + case 'do': + errorStatus = true + errorLog.push(tok.line + ':' + tok.column + ' do not supported') + break + } + break + case 'builtin': + switch (tok.data) { + case 'dFdx': + case 'dFdy': + case 'fwidth': + if (!this._extensions.oes_standard_derivatives) { + errorStatus = true + errorLog.push(tok.line + ':' + tok.column + ' ' + tok.data + ' not supported') + } + break + } + } + } + + if (errorStatus) { + shader._compileInfo = errorLog.join('\n') + } + return !errorStatus + } + + _checkStencilState () { + if (!this._checkStencil) { + return this._stencilState + } + this._checkStencil = false + this._stencilState = true + if (this.getParameter(gl.STENCIL_WRITEMASK) !== + this.getParameter(gl.STENCIL_BACK_WRITEMASK) || + this.getParameter(gl.STENCIL_VALUE_MASK) !== + this.getParameter(gl.STENCIL_BACK_VALUE_MASK) || + this.getParameter(gl.STENCIL_REF) !== + this.getParameter(gl.STENCIL_BACK_REF)) { + this.setError(gl.INVALID_OPERATION) + this._stencilState = false + } + return this._stencilState + } + + _checkTextureTarget (target) { + const unit = this._getActiveTextureUnit() + let tex = null + if (target === gl.TEXTURE_2D) { + tex = unit._bind2D + } else if (target === gl.TEXTURE_CUBE_MAP) { + tex = unit._bindCube + } else { + this.setError(gl.INVALID_ENUM) + return false + } + if (!tex) { + this.setError(gl.INVALID_OPERATION) + return false + } + return true + } + + _checkWrapper (object, Wrapper) { + if (!this._checkValid(object, Wrapper)) { + this.setError(gl.INVALID_VALUE) + return false + } else if (!this._checkOwns(object)) { + this.setError(gl.INVALID_OPERATION) + return false + } + return true + } + + _checkValid (object, Type) { + return object instanceof Type && object._ !== 0 + } + + _checkVertexAttribState (maxIndex) { + const program = this._activeProgram + if (!program) { + this.setError(gl.INVALID_OPERATION) + return false + } + const attribs = this._vertexObjectState._attribs + for (let i = 0; i < attribs.length; ++i) { + const attrib = attribs[i] + if (attrib._isPointer) { + const buffer = attrib._pointerBuffer + if (!buffer) { + this.setError(gl.INVALID_OPERATION) + return false + } + if (program._attributes.indexOf(i) >= 0) { + let maxByte = 0 + if (attrib._divisor) { + maxByte = attrib._pointerSize + + attrib._pointerOffset + } else { + maxByte = attrib._pointerStride * maxIndex + + attrib._pointerSize + + attrib._pointerOffset + } + if (maxByte > buffer._size) { + this.setError(gl.INVALID_OPERATION) + return false + } + } + } + } + return true + } + + _checkVertexIndex (index) { + if (index < 0 || index >= this._vertexObjectState._attribs.length) { + this.setError(gl.INVALID_VALUE) + return false + } + return true + } + + _computePixelSize (type, internalFormat) { + const pixelSize = formatSize(internalFormat) + if (pixelSize === 0) { + this.setError(gl.INVALID_ENUM) + return 0 + } + switch (type) { + case gl.UNSIGNED_BYTE: + return pixelSize + case gl.UNSIGNED_SHORT_5_6_5: + if (internalFormat !== gl.RGB) { + this.setError(gl.INVALID_OPERATION) + break + } + return 2 + case gl.UNSIGNED_SHORT_4_4_4_4: + case gl.UNSIGNED_SHORT_5_5_5_1: + if (internalFormat !== gl.RGBA) { + this.setError(gl.INVALID_OPERATION) + break + } + return 2 + case gl.FLOAT: + return 1 + } + this.setError(gl.INVALID_ENUM) + return 0 + } + + _computeRowStride (width, pixelSize) { + let rowStride = width * pixelSize + if (rowStride % this._unpackAlignment) { + rowStride += this._unpackAlignment - (rowStride % this._unpackAlignment) + } + return rowStride + } + + _fixupLink (program) { + if (!super.getProgramParameter(program._, gl.LINK_STATUS)) { + program._linkInfoLog = super.getProgramInfoLog(program) + return false + } + + // Record attribute attributeLocations + const numAttribs = this.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES) + const names = new Array(numAttribs) + program._attributes.length = numAttribs + for (let i = 0; i < numAttribs; ++i) { + names[i] = this.getActiveAttrib(program, i).name + program._attributes[i] = this.getAttribLocation(program, names[i]) | 0 + } + + // Check attribute names + for (let i = 0; i < names.length; ++i) { + if (names[i].length > MAX_ATTRIBUTE_LENGTH) { + program._linkInfoLog = 'attribute ' + names[i] + ' is too long' + return false + } + } + + for (let i = 0; i < numAttribs; ++i) { + super.bindAttribLocation( + program._ | 0, + program._attributes[i], + names[i]) + } + + super.linkProgram(program._ | 0) + + const numUniforms = this.getProgramParameter(program, gl.ACTIVE_UNIFORMS) + program._uniforms.length = numUniforms + for (let i = 0; i < numUniforms; ++i) { + program._uniforms[i] = this.getActiveUniform(program, i) + } + + // Check attribute and uniform name lengths + for (let i = 0; i < program._uniforms.length; ++i) { + if (program._uniforms[i].name.length > MAX_UNIFORM_LENGTH) { + program._linkInfoLog = 'uniform ' + program._uniforms[i].name + ' is too long' + return false + } + } + + program._linkInfoLog = '' + return true + } + + _framebufferOk () { + const framebuffer = this._activeFramebuffer + if (framebuffer && + this._preCheckFramebufferStatus(framebuffer) !== gl.FRAMEBUFFER_COMPLETE) { + this.setError(gl.INVALID_FRAMEBUFFER_OPERATION) + return false + } + return true + } + + _getActiveBuffer (target) { + if (target === gl.ARRAY_BUFFER) { + return this._vertexGlobalState._arrayBufferBinding + } else if (target === gl.ELEMENT_ARRAY_BUFFER) { + return this._vertexObjectState._elementArrayBufferBinding + } + return null + } + + _getActiveTextureUnit () { + return this._textureUnits[this._activeTextureUnit] + } + + _getActiveTexture (target) { + const activeUnit = this._getActiveTextureUnit() + if (target === gl.TEXTURE_2D) { + return activeUnit._bind2D + } else if (target === gl.TEXTURE_CUBE_MAP) { + return activeUnit._bindCube + } + return null + } + + _getAttachments () { + return this._extensions.webgl_draw_buffers ? this._extensions.webgl_draw_buffers._ALL_ATTACHMENTS : DEFAULT_ATTACHMENTS + } + + _getColorAttachments () { + return this._extensions.webgl_draw_buffers ? this._extensions.webgl_draw_buffers._ALL_COLOR_ATTACHMENTS : DEFAULT_COLOR_ATTACHMENTS + } + + _getParameterDirect (pname) { + return super.getParameter(pname) + } + + _getTexImage (target) { + const unit = this._getActiveTextureUnit() + if (target === gl.TEXTURE_2D) { + return unit._bind2D + } else if (validCubeTarget(target)) { + return unit._bindCube + } + this.setError(gl.INVALID_ENUM) + return null + } + + _preCheckFramebufferStatus (framebuffer) { + const attachments = framebuffer._attachments + const width = [] + const height = [] + const depthAttachment = attachments[gl.DEPTH_ATTACHMENT] + const depthStencilAttachment = attachments[gl.DEPTH_STENCIL_ATTACHMENT] + const stencilAttachment = attachments[gl.STENCIL_ATTACHMENT] + + if ((depthStencilAttachment && (stencilAttachment || depthAttachment)) || + (stencilAttachment && depthAttachment)) { + return gl.FRAMEBUFFER_UNSUPPORTED + } + + const colorAttachments = this._getColorAttachments() + let colorAttachmentCount = 0 + for (const attachmentEnum in attachments) { + if (attachments[attachmentEnum] && colorAttachments.indexOf(attachmentEnum * 1) !== -1) { + colorAttachmentCount++ + } + } + if (colorAttachmentCount === 0) { + return gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT + } + + if (depthStencilAttachment instanceof WebGLTexture) { + return gl.FRAMEBUFFER_UNSUPPORTED + } else if (depthStencilAttachment instanceof WebGLRenderbuffer) { + if (depthStencilAttachment._format !== gl.DEPTH_STENCIL) { + return gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT + } + width.push(depthStencilAttachment._width) + height.push(depthStencilAttachment._height) + } + + if (depthAttachment instanceof WebGLTexture) { + return gl.FRAMEBUFFER_UNSUPPORTED + } else if (depthAttachment instanceof WebGLRenderbuffer) { + if (depthAttachment._format !== gl.DEPTH_COMPONENT16) { + return gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT + } + width.push(depthAttachment._width) + height.push(depthAttachment._height) + } + + if (stencilAttachment instanceof WebGLTexture) { + return gl.FRAMEBUFFER_UNSUPPORTED + } else if (stencilAttachment instanceof WebGLRenderbuffer) { + if (stencilAttachment._format !== gl.STENCIL_INDEX8) { + return gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT + } + width.push(stencilAttachment._width) + height.push(stencilAttachment._height) + } + + let colorAttached = false + for (let i = 0; i < colorAttachments.length; ++i) { + const colorAttachment = attachments[colorAttachments[i]] + if (colorAttachment instanceof WebGLTexture) { + if (colorAttachment._format !== gl.RGBA || + !(colorAttachment._type === gl.UNSIGNED_BYTE || colorAttachment._type === gl.FLOAT)) { + return gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT + } + colorAttached = true + const level = framebuffer._attachmentLevel[gl.COLOR_ATTACHMENT0] + width.push(colorAttachment._levelWidth[level]) + height.push(colorAttachment._levelHeight[level]) + } else if (colorAttachment instanceof WebGLRenderbuffer) { + const format = colorAttachment._format + if (format !== gl.RGBA4 && + format !== gl.RGB565 && + format !== gl.RGB5_A1) { + return gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT + } + colorAttached = true + width.push(colorAttachment._width) + height.push(colorAttachment._height) + } + } + + if (!colorAttached && + !stencilAttachment && + !depthAttachment && + !depthStencilAttachment) { + return gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT + } + + if (width.length <= 0 || height.length <= 0) { + return gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT + } + + for (let i = 1; i < width.length; ++i) { + if (width[i - 1] !== width[i] || + height[i - 1] !== height[i]) { + return gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS + } + } + + if (width[0] === 0 || height[0] === 0) { + return gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT + } + + framebuffer._width = width[0] + framebuffer._height = height[0] + + return gl.FRAMEBUFFER_COMPLETE + } + + _isConstantBlendFunc (factor) { + return ( + factor === gl.CONSTANT_COLOR || + factor === gl.ONE_MINUS_CONSTANT_COLOR || + factor === gl.CONSTANT_ALPHA || + factor === gl.ONE_MINUS_CONSTANT_ALPHA) + } + + _isObject (object, method, Wrapper) { + if (!(object === null || object === undefined) && + !(object instanceof Wrapper)) { + throw new TypeError(method + '(' + Wrapper.name + ')') + } + if (this._checkValid(object, Wrapper) && this._checkOwns(object)) { + return true + } + return false + } + + _resizeDrawingBuffer (width, height) { + const prevFramebuffer = this._activeFramebuffer + const prevTexture = this._getActiveTexture(gl.TEXTURE_2D) + const prevRenderbuffer = this._activeRenderbuffer + + const contextAttributes = this._contextAttributes + + const drawingBuffer = this._drawingBuffer + super.bindFramebuffer(gl.FRAMEBUFFER, drawingBuffer._framebuffer) + const attachments = this._getAttachments() + // Clear all attachments + for (let i = 0; i < attachments.length; ++i) { + super.framebufferTexture2D( + gl.FRAMEBUFFER, + attachments[i], + gl.TEXTURE_2D, + 0, + 0) + } + + // Update color attachment + super.bindTexture(gl.TEXTURE_2D, drawingBuffer._color) + const colorFormat = contextAttributes.alpha ? gl.RGBA : gl.RGB + super.texImage2D( + gl.TEXTURE_2D, + 0, + colorFormat, + width, + height, + 0, + colorFormat, + gl.UNSIGNED_BYTE, + null) + super.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) + super.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + super.framebufferTexture2D( + gl.FRAMEBUFFER, + gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, + drawingBuffer._color, + 0) + + // Update depth-stencil attachments if needed + let storage = 0 + let attachment = 0 + if (contextAttributes.depth && contextAttributes.stencil) { + storage = gl.DEPTH_STENCIL + attachment = gl.DEPTH_STENCIL_ATTACHMENT + } else if (contextAttributes.depth) { + storage = 0x81A7 + attachment = gl.DEPTH_ATTACHMENT + } else if (contextAttributes.stencil) { + storage = gl.STENCIL_INDEX8 + attachment = gl.STENCIL_ATTACHMENT + } + + if (storage) { + super.bindRenderbuffer( + gl.RENDERBUFFER, + drawingBuffer._depthStencil) + super.renderbufferStorage( + gl.RENDERBUFFER, + storage, + width, + height) + super.framebufferRenderbuffer( + gl.FRAMEBUFFER, + attachment, + gl.RENDERBUFFER, + drawingBuffer._depthStencil) + } + + // Restore previous binding state + this.bindFramebuffer(gl.FRAMEBUFFER, prevFramebuffer) + this.bindTexture(gl.TEXTURE_2D, prevTexture) + this.bindRenderbuffer(gl.RENDERBUFFER, prevRenderbuffer) + } + + _restoreError (lastError) { + const topError = this._errorStack.pop() + if (topError === gl.NO_ERROR) { + this.setError(lastError) + } else { + this.setError(topError) + } + } + + _saveError () { + this._errorStack.push(this.getError()) + } + + _switchActiveProgram (active) { + if (active) { + active._refCount -= 1 + active._checkDelete() + } + } + + _tryDetachFramebuffer (framebuffer, renderbuffer) { + // FIXME: Does the texture get unbound from *all* framebuffers, or just the + // active FBO? + if (framebuffer && framebuffer._linked(renderbuffer)) { + const attachments = this._getAttachments() + const framebufferAttachments = Object.keys(framebuffer._attachments) + for (let i = 0; i < framebufferAttachments.length; ++i) { + if (framebuffer._attachments[attachments[i]] === renderbuffer) { + this.framebufferTexture2D( + gl.FRAMEBUFFER, + attachments[i] | 0, + gl.TEXTURE_2D, + null) + } + } + } + } + + _updateFramebufferAttachments (framebuffer) { + const prevStatus = framebuffer._status + const attachments = this._getAttachments() + framebuffer._status = this._preCheckFramebufferStatus(framebuffer) + if (framebuffer._status !== gl.FRAMEBUFFER_COMPLETE) { + if (prevStatus === gl.FRAMEBUFFER_COMPLETE) { + for (let i = 0; i < attachments.length; ++i) { + const attachmentEnum = attachments[i] + super.framebufferTexture2D( + gl.FRAMEBUFFER, + attachmentEnum, + framebuffer._attachmentFace[attachmentEnum], + 0, + framebuffer._attachmentLevel[attachmentEnum]) + } + } + return + } + + for (let i = 0; i < attachments.length; ++i) { + const attachmentEnum = attachments[i] + super.framebufferTexture2D( + gl.FRAMEBUFFER, + attachmentEnum, + framebuffer._attachmentFace[attachmentEnum], + 0, + framebuffer._attachmentLevel[attachmentEnum]) + } + + for (let i = 0; i < attachments.length; ++i) { + const attachmentEnum = attachments[i] + const attachment = framebuffer._attachments[attachmentEnum] + if (attachment instanceof WebGLTexture) { + super.framebufferTexture2D( + gl.FRAMEBUFFER, + attachmentEnum, + framebuffer._attachmentFace[attachmentEnum], + attachment._ | 0, + framebuffer._attachmentLevel[attachmentEnum]) + } else if (attachment instanceof WebGLRenderbuffer) { + super.framebufferRenderbuffer( + gl.FRAMEBUFFER, + attachmentEnum, + gl.RENDERBUFFER, + attachment._ | 0) + } + } + } + + _validBlendFunc (factor) { + return factor === gl.ZERO || + factor === gl.ONE || + factor === gl.SRC_COLOR || + factor === gl.ONE_MINUS_SRC_COLOR || + factor === gl.DST_COLOR || + factor === gl.ONE_MINUS_DST_COLOR || + factor === gl.SRC_ALPHA || + factor === gl.ONE_MINUS_SRC_ALPHA || + factor === gl.DST_ALPHA || + factor === gl.ONE_MINUS_DST_ALPHA || + factor === gl.SRC_ALPHA_SATURATE || + factor === gl.CONSTANT_COLOR || + factor === gl.ONE_MINUS_CONSTANT_COLOR || + factor === gl.CONSTANT_ALPHA || + factor === gl.ONE_MINUS_CONSTANT_ALPHA + } + + _validBlendMode (mode) { + return mode === gl.FUNC_ADD || + mode === gl.FUNC_SUBTRACT || + mode === gl.FUNC_REVERSE_SUBTRACT || + (this._extensions.ext_blend_minmax && ( + mode === this._extensions.ext_blend_minmax.MIN_EXT || + mode === this._extensions.ext_blend_minmax.MAX_EXT)) + } + + _validCubeTarget (target) { + return target === gl.TEXTURE_CUBE_MAP_POSITIVE_X || + target === gl.TEXTURE_CUBE_MAP_NEGATIVE_X || + target === gl.TEXTURE_CUBE_MAP_POSITIVE_Y || + target === gl.TEXTURE_CUBE_MAP_NEGATIVE_Y || + target === gl.TEXTURE_CUBE_MAP_POSITIVE_Z || + target === gl.TEXTURE_CUBE_MAP_NEGATIVE_Z + } + + _validFramebufferAttachment (attachment) { + switch (attachment) { + case gl.DEPTH_ATTACHMENT: + case gl.STENCIL_ATTACHMENT: + case gl.DEPTH_STENCIL_ATTACHMENT: + case gl.COLOR_ATTACHMENT0: + return true + } + + if (this._extensions.webgl_draw_buffers) { // eslint-disable-line + const { webgl_draw_buffers } = this._extensions; // eslint-disable-line + return attachment < (webgl_draw_buffers.COLOR_ATTACHMENT0_WEBGL + webgl_draw_buffers._maxDrawBuffers) // eslint-disable-line + } + + return false + } + + _validGLSLIdentifier (str) { + return !(str.indexOf('webgl_') === 0 || + str.indexOf('_webgl_') === 0 || + str.length > 256) + } + + _validTextureTarget (target) { + return target === gl.TEXTURE_2D || + target === gl.TEXTURE_CUBE_MAP + } + + _verifyTextureCompleteness (target, pname, param) { + const unit = this._getActiveTextureUnit() + let texture = null + if (target === gl.TEXTURE_2D) { + texture = unit._bind2D + } else if (this._validCubeTarget(target)) { + texture = unit._bindCube + } + + // oes_texture_float but not oes_texture_float_linear + if (this._extensions.oes_texture_float && !this._extensions.oes_texture_float_linear && texture && texture._type === gl.FLOAT && (pname === gl.TEXTURE_MAG_FILTER || pname === gl.TEXTURE_MIN_FILTER) && (param === gl.LINEAR || param === gl.LINEAR_MIPMAP_NEAREST || param === gl.NEAREST_MIPMAP_LINEAR || param === gl.LINEAR_MIPMAP_LINEAR)) { + texture._complete = false + this.bindTexture(target, texture) + return + } + + if (texture && texture._complete === false) { + texture._complete = true + this.bindTexture(target, texture) + } + } + + _wrapShader (type, source) { // eslint-disable-line + // the gl implementation seems to define `GL_OES_standard_derivatives` even when the extension is disabled + // this behaviour causes one conformance test ('GL_OES_standard_derivatives defined in shaders when extension is disabled') to fail + // by `undef`ing `GL_OES_standard_derivatives`, this appears to solve the issue + if (!this._extensions.oes_standard_derivatives && /#ifdef\s+GL_OES_standard_derivatives/.test(source)) { + source = '#undef GL_OES_standard_derivatives\n' + source + } + + return this._extensions.webgl_draw_buffers ? source : '#define gl_MaxDrawBuffers 1\n' + source // eslint-disable-line + } + + _beginAttrib0Hack () { + super.bindBuffer(gl.ARRAY_BUFFER, this._attrib0Buffer._) + super.bufferData( + gl.ARRAY_BUFFER, + this._vertexGlobalState._attribs[0]._data, + gl.STREAM_DRAW) + super.enableVertexAttribArray(0) + super.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0) + super._vertexAttribDivisor(0, 1) + } + + _endAttrib0Hack () { + const attrib = this._vertexObjectState._attribs[0] + if (attrib._pointerBuffer) { + super.bindBuffer(gl.ARRAY_BUFFER, attrib._pointerBuffer._) + } else { + super.bindBuffer(gl.ARRAY_BUFFER, 0) + } + super.vertexAttribPointer( + 0, + attrib._inputSize, + attrib._pointerType, + attrib._pointerNormal, + attrib._inputStride, + attrib._pointerOffset) + super._vertexAttribDivisor(0, attrib._divisor) + super.disableVertexAttribArray(0) + if (this._vertexGlobalState._arrayBufferBinding) { + super.bindBuffer(gl.ARRAY_BUFFER, this._vertexGlobalState._arrayBufferBinding._) + } else { + super.bindBuffer(gl.ARRAY_BUFFER, 0) + } + } + + activeTexture (texture) { + texture |= 0 + const texNum = texture - gl.TEXTURE0 + if (texNum >= 0 && texNum < this._textureUnits.length) { + this._activeTextureUnit = texNum + return super.activeTexture(texture) + } + + this.setError(gl.INVALID_ENUM) + } + + attachShader (program, shader) { + if (!checkObject(program) || + !checkObject(shader)) { + throw new TypeError('attachShader(WebGLProgram, WebGLShader)') + } + if (!program || !shader) { + this.setError(gl.INVALID_VALUE) + return + } else if (program instanceof WebGLProgram && + shader instanceof WebGLShader && + this._checkOwns(program) && + this._checkOwns(shader)) { + if (!program._linked(shader)) { + this._saveError() + super.attachShader( + program._ | 0, + shader._ | 0) + const error = this.getError() + this._restoreError(error) + if (error === gl.NO_ERROR) { + program._link(shader) + } + return + } + } + this.setError(gl.INVALID_OPERATION) + } + + bindAttribLocation (program, index, name) { + if (!checkObject(program) || + typeof name !== 'string') { + throw new TypeError('bindAttribLocation(WebGLProgram, GLint, String)') + } + name += '' + if (!isValidString(name) || name.length > MAX_ATTRIBUTE_LENGTH) { + this.setError(gl.INVALID_VALUE) + } else if (/^_?webgl_a/.test(name)) { + this.setError(gl.INVALID_OPERATION) + } else if (this._checkWrapper(program, WebGLProgram)) { + return super.bindAttribLocation( + program._ | 0, + index | 0, + name) + } + } + + bindFramebuffer (target, framebuffer) { + if (!checkObject(framebuffer)) { + throw new TypeError('bindFramebuffer(GLenum, WebGLFramebuffer)') + } + if (target !== gl.FRAMEBUFFER) { + this.setError(gl.INVALID_ENUM) + return + } + if (!framebuffer) { + super.bindFramebuffer( + gl.FRAMEBUFFER, + this._drawingBuffer._framebuffer) + } else if (framebuffer._pendingDelete) { + return + } else if (this._checkWrapper(framebuffer, WebGLFramebuffer)) { + super.bindFramebuffer( + gl.FRAMEBUFFER, + framebuffer._ | 0) + } else { + return + } + const activeFramebuffer = this._activeFramebuffer + if (activeFramebuffer !== framebuffer) { + if (activeFramebuffer) { + activeFramebuffer._refCount -= 1 + activeFramebuffer._checkDelete() + } + if (framebuffer) { + framebuffer._refCount += 1 + } + } + this._activeFramebuffer = framebuffer + if (framebuffer) { + this._updateFramebufferAttachments(framebuffer) + } + } + + bindBuffer (target, buffer) { + target |= 0 + if (!checkObject(buffer)) { + throw new TypeError('bindBuffer(GLenum, WebGLBuffer)') + } + if (target !== gl.ARRAY_BUFFER && + target !== gl.ELEMENT_ARRAY_BUFFER) { + this.setError(gl.INVALID_ENUM) + return + } + + if (!buffer) { + buffer = null + super.bindBuffer(target, 0) + } else if (buffer._pendingDelete) { + return + } else if (this._checkWrapper(buffer, WebGLBuffer)) { + if (buffer._binding && buffer._binding !== target) { + this.setError(gl.INVALID_OPERATION) + return + } + buffer._binding = target | 0 + + super.bindBuffer(target, buffer._ | 0) + } else { + return + } + + if (target === gl.ARRAY_BUFFER) { + // Buffers of type ARRAY_BUFFER are bound to the global vertex state. + this._vertexGlobalState.setArrayBuffer(buffer) + } else { + // Buffers of type ELEMENT_ARRAY_BUFFER are bound to vertex array object state. + this._vertexObjectState.setElementArrayBuffer(buffer) + } + } + + bindRenderbuffer (target, object) { + if (!checkObject(object)) { + throw new TypeError('bindRenderbuffer(GLenum, WebGLRenderbuffer)') + } + + if (target !== gl.RENDERBUFFER) { + this.setError(gl.INVALID_ENUM) + return + } + + if (!object) { + super.bindRenderbuffer( + target | 0, + 0) + } else if (object._pendingDelete) { + return + } else if (this._checkWrapper(object, WebGLRenderbuffer)) { + super.bindRenderbuffer( + target | 0, + object._ | 0) + } else { + return + } + const active = this._activeRenderbuffer + if (active !== object) { + if (active) { + active._refCount -= 1 + active._checkDelete() + } + if (object) { + object._refCount += 1 + } + } + this._activeRenderbuffer = object + } + + bindTexture (target, texture) { + target |= 0 + + if (!checkObject(texture)) { + throw new TypeError('bindTexture(GLenum, WebGLTexture)') + } + + if (!this._validTextureTarget(target)) { + this.setError(gl.INVALID_ENUM) + return + } + + // Get texture id + let textureId = 0 + if (!texture) { + texture = null + } else if (texture instanceof WebGLTexture && + texture._pendingDelete) { + // Special case: error codes for deleted textures don't get set for some dumb reason + return + } else if (this._checkWrapper(texture, WebGLTexture)) { + // Check binding mode of texture + if (texture._binding && texture._binding !== target) { + this.setError(gl.INVALID_OPERATION) + return + } + texture._binding = target + + if (texture._complete) { + textureId = texture._ | 0 + } + } else { + return + } + + this._saveError() + super.bindTexture( + target, + textureId) + const error = this.getError() + this._restoreError(error) + + if (error !== gl.NO_ERROR) { + return + } + + const activeUnit = this._getActiveTextureUnit() + const activeTex = this._getActiveTexture(target) + + // Update references + if (activeTex !== texture) { + if (activeTex) { + activeTex._refCount -= 1 + activeTex._checkDelete() + } + if (texture) { + texture._refCount += 1 + } + } + + if (target === gl.TEXTURE_2D) { + activeUnit._bind2D = texture + } else if (target === gl.TEXTURE_CUBE_MAP) { + activeUnit._bindCube = texture + } + } + + blendColor (red, green, blue, alpha) { + return super.blendColor(+red, +green, +blue, +alpha) + } + + blendEquation (mode) { + mode |= 0 + if (this._validBlendMode(mode)) { + return super.blendEquation(mode) + } + this.setError(gl.INVALID_ENUM) + } + + blendEquationSeparate (modeRGB, modeAlpha) { + modeRGB |= 0 + modeAlpha |= 0 + if (this._validBlendMode(modeRGB) && this._validBlendMode(modeAlpha)) { + return super.blendEquationSeparate(modeRGB, modeAlpha) + } + this.setError(gl.INVALID_ENUM) + } + + createBuffer () { + const id = super.createBuffer() + if (id <= 0) return null + const webGLBuffer = new WebGLBuffer(id, this) + this._buffers[id] = webGLBuffer + return webGLBuffer + } + + createFramebuffer () { + const id = super.createFramebuffer() + if (id <= 0) return null + const webGLFramebuffer = new WebGLFramebuffer(id, this) + this._framebuffers[id] = webGLFramebuffer + return webGLFramebuffer + } + + createProgram () { + const id = super.createProgram() + if (id <= 0) return null + const webGLProgram = new WebGLProgram(id, this) + this._programs[id] = webGLProgram + return webGLProgram + } + + createRenderbuffer () { + const id = super.createRenderbuffer() + if (id <= 0) return null + const webGLRenderbuffer = new WebGLRenderbuffer(id, this) + this._renderbuffers[id] = webGLRenderbuffer + return webGLRenderbuffer + } + + createTexture () { + const id = super.createTexture() + if (id <= 0) return null + const webGlTexture = new WebGLTexture(id, this) + this._textures[id] = webGlTexture + return webGlTexture + } + + getContextAttributes () { + return this._contextAttributes + } + + getExtension (name) { + const str = name.toLowerCase() + if (str in this._extensions) { + return this._extensions[str] + } + const ext = availableExtensions[str] ? availableExtensions[str](this) : null + if (ext) { + this._extensions[str] = ext + } + return ext + } + + getSupportedExtensions () { + const exts = [ + 'ANGLE_instanced_arrays', + 'STACKGL_resize_drawingbuffer', + 'STACKGL_destroy_context' + ] + + const supportedExts = super.getSupportedExtensions() + + if (supportedExts.indexOf('GL_OES_element_index_uint') >= 0) { + exts.push('OES_element_index_uint') + } + + if (supportedExts.indexOf('GL_OES_standard_derivatives') >= 0) { + exts.push('OES_standard_derivatives') + } + + if (supportedExts.indexOf('GL_OES_texture_float') >= 0) { + exts.push('OES_texture_float') + } + + if (supportedExts.indexOf('GL_OES_texture_float_linear') >= 0) { + exts.push('OES_texture_float_linear') + } + + if (supportedExts.indexOf('EXT_draw_buffers') >= 0) { + exts.push('WEBGL_draw_buffers') + } + + if (supportedExts.indexOf('EXT_blend_minmax') >= 0) { + exts.push('EXT_blend_minmax') + } + + if (supportedExts.indexOf('EXT_texture_filter_anisotropic') >= 0) { + exts.push('EXT_texture_filter_anisotropic') + } + + if (supportedExts.indexOf('GL_OES_vertex_array_object') >= 0) { + exts.push('OES_vertex_array_object') + } + + return exts + } + + setError (error) { + NativeWebGL.setError.call(this, error | 0) + } + + blendFunc (sfactor, dfactor) { + sfactor |= 0 + dfactor |= 0 + if (!this._validBlendFunc(sfactor) || + !this._validBlendFunc(dfactor)) { + this.setError(gl.INVALID_ENUM) + return + } + if (this._isConstantBlendFunc(sfactor) && this._isConstantBlendFunc(dfactor)) { + this.setError(gl.INVALID_OPERATION) + return + } + super.blendFunc(sfactor, dfactor) + } + + blendFuncSeparate ( + srcRGB, + dstRGB, + srcAlpha, + dstAlpha) { + srcRGB |= 0 + dstRGB |= 0 + srcAlpha |= 0 + dstAlpha |= 0 + + if (!(this._validBlendFunc(srcRGB) && + this._validBlendFunc(dstRGB) && + this._validBlendFunc(srcAlpha) && + this._validBlendFunc(dstAlpha))) { + this.setError(gl.INVALID_ENUM) + return + } + + if ((this._isConstantBlendFunc(srcRGB) && this._isConstantBlendFunc(dstRGB)) || + (this._isConstantBlendFunc(srcAlpha) && this._isConstantBlendFunc(dstAlpha))) { + this.setError(gl.INVALID_OPERATION) + return + } + + super.blendFuncSeparate( + srcRGB, + dstRGB, + srcAlpha, + dstAlpha) + } + + bufferData (target, data, usage) { + target |= 0 + usage |= 0 + if (usage !== gl.STREAM_DRAW && + usage !== gl.STATIC_DRAW && + usage !== gl.DYNAMIC_DRAW) { + this.setError(gl.INVALID_ENUM) + return + } + + if (target !== gl.ARRAY_BUFFER && + target !== gl.ELEMENT_ARRAY_BUFFER) { + this.setError(gl.INVALID_ENUM) + return + } + + const active = this._getActiveBuffer(target) + if (!active) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (typeof data === 'object') { + let u8Data = null + if (isTypedArray(data)) { + u8Data = unpackTypedArray(data) + } else if (data instanceof ArrayBuffer) { + u8Data = new Uint8Array(data) + } else { + this.setError(gl.INVALID_VALUE) + return + } + + this._saveError() + super.bufferData( + target, + u8Data, + usage) + const error = this.getError() + this._restoreError(error) + if (error !== gl.NO_ERROR) { + return + } + + active._size = u8Data.length + if (target === gl.ELEMENT_ARRAY_BUFFER) { + active._elements = new Uint8Array(u8Data) + } + } else if (typeof data === 'number') { + const size = data | 0 + if (size < 0) { + this.setError(gl.INVALID_VALUE) + return + } + + this._saveError() + super.bufferData( + target, + size, + usage) + const error = this.getError() + this._restoreError(error) + if (error !== gl.NO_ERROR) { + return + } + + active._size = size + if (target === gl.ELEMENT_ARRAY_BUFFER) { + active._elements = new Uint8Array(size) + } + } else { + this.setError(gl.INVALID_VALUE) + } + } + + bufferSubData (target, offset, data) { + target |= 0 + offset |= 0 + + if (target !== gl.ARRAY_BUFFER && + target !== gl.ELEMENT_ARRAY_BUFFER) { + this.setError(gl.INVALID_ENUM) + return + } + + if (data === null) { + return + } + + if (!data || typeof data !== 'object') { + this.setError(gl.INVALID_VALUE) + return + } + + const active = this._getActiveBuffer(target) + if (!active) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (offset < 0 || offset >= active._size) { + this.setError(gl.INVALID_VALUE) + return + } + + let u8Data = null + if (isTypedArray(data)) { + u8Data = unpackTypedArray(data) + } else if (data instanceof ArrayBuffer) { + u8Data = new Uint8Array(data) + } else { + this.setError(gl.INVALID_VALUE) + return + } + + if (offset + u8Data.length > active._size) { + this.setError(gl.INVALID_VALUE) + return + } + + if (target === gl.ELEMENT_ARRAY_BUFFER) { + active._elements.set(u8Data, offset) + } + + super.bufferSubData( + target, + offset, + u8Data) + } + + checkFramebufferStatus (target) { + if (target !== gl.FRAMEBUFFER) { + this.setError(gl.INVALID_ENUM) + return 0 + } + + const framebuffer = this._activeFramebuffer + if (!framebuffer) { + return gl.FRAMEBUFFER_COMPLETE + } + + return this._preCheckFramebufferStatus(framebuffer) + } + + clear (mask) { + if (!this._framebufferOk()) { + return + } + return super.clear(mask | 0) + } + + clearColor (red, green, blue, alpha) { + return super.clearColor(+red, +green, +blue, +alpha) + } + + clearDepth (depth) { + return super.clearDepth(+depth) + } + + clearStencil (s) { + this._checkStencil = false + return super.clearStencil(s | 0) + } + + colorMask (red, green, blue, alpha) { + return super.colorMask(!!red, !!green, !!blue, !!alpha) + } + + compileShader (shader) { + if (!checkObject(shader)) { + throw new TypeError('compileShader(WebGLShader)') + } + if (this._checkWrapper(shader, WebGLShader) && + this._checkShaderSource(shader)) { + const prevError = this.getError() + super.compileShader(shader._ | 0) + const error = this.getError() + shader._compileStatus = !!super.getShaderParameter( + shader._ | 0, + gl.COMPILE_STATUS) + shader._compileInfo = super.getShaderInfoLog(shader._ | 0) + this.getError() + this.setError(prevError || error) + } + } + + copyTexImage2D ( + target, + level, + internalFormat, + x, y, width, height, + border) { + target |= 0 + level |= 0 + internalFormat |= 0 + x |= 0 + y |= 0 + width |= 0 + height |= 0 + border |= 0 + + const texture = this._getTexImage(target) + if (!texture) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (internalFormat !== gl.RGBA && + internalFormat !== gl.RGB && + internalFormat !== gl.ALPHA && + internalFormat !== gl.LUMINANCE && + internalFormat !== gl.LUMINANCE_ALPHA) { + this.setError(gl.INVALID_ENUM) + return + } + + if (level < 0 || width < 0 || height < 0 || border !== 0) { + this.setError(gl.INVALID_VALUE) + return + } + + if (level > 0 && !(bits.isPow2(width) && bits.isPow2(height))) { + this.setError(gl.INVALID_VALUE) + return + } + + this._saveError() + super.copyTexImage2D( + target, + level, + internalFormat, + x, + y, + width, + height, + border) + const error = this.getError() + this._restoreError(error) + + if (error === gl.NO_ERROR) { + texture._levelWidth[level] = width + texture._levelHeight[level] = height + texture._format = gl.RGBA + texture._type = gl.UNSIGNED_BYTE + } + } + + copyTexSubImage2D ( + target, + level, + xoffset, yoffset, + x, y, width, height) { + target |= 0 + level |= 0 + xoffset |= 0 + yoffset |= 0 + x |= 0 + y |= 0 + width |= 0 + height |= 0 + + const texture = this._getTexImage(target) + if (!texture) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (width < 0 || height < 0 || xoffset < 0 || yoffset < 0 || level < 0) { + this.setError(gl.INVALID_VALUE) + return + } + + super.copyTexSubImage2D( + target, + level, + xoffset, + yoffset, + x, + y, + width, + height) + } + + cullFace (mode) { + return super.cullFace(mode | 0) + } + + createShader (type) { + type |= 0 + if (type !== gl.FRAGMENT_SHADER && + type !== gl.VERTEX_SHADER) { + this.setError(gl.INVALID_ENUM) + return null + } + const id = super.createShader(type) + if (id < 0) { + return null + } + const result = new WebGLShader(id, this, type) + this._shaders[id] = result + return result + } + + deleteProgram (object) { + return this._deleteLinkable('deleteProgram', object, WebGLProgram) + } + + deleteShader (object) { + return this._deleteLinkable('deleteShader', object, WebGLShader) + } + + _deleteLinkable (name, object, Type) { + if (!checkObject(object)) { + throw new TypeError(name + '(' + Type.name + ')') + } + if (object instanceof Type && + this._checkOwns(object)) { + object._pendingDelete = true + object._checkDelete() + return + } + this.setError(gl.INVALID_OPERATION) + } + + deleteBuffer (buffer) { + if (!checkObject(buffer) || + (buffer !== null && !(buffer instanceof WebGLBuffer))) { + throw new TypeError('deleteBuffer(WebGLBuffer)') + } + + if (!(buffer instanceof WebGLBuffer && + this._checkOwns(buffer))) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (this._vertexGlobalState._arrayBufferBinding === buffer) { + this.bindBuffer(gl.ARRAY_BUFFER, null) + } + if (this._vertexObjectState._elementArrayBufferBinding === buffer) { + this.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null) + } + + if (this._vertexObjectState === this._defaultVertexObjectState) { + // If no vertex array object is bound, release attrib bindings for the + // array buffer. + this._vertexObjectState.releaseArrayBuffer(buffer) + } + + buffer._pendingDelete = true + buffer._checkDelete() + } + + deleteFramebuffer (framebuffer) { + if (!checkObject(framebuffer)) { + throw new TypeError('deleteFramebuffer(WebGLFramebuffer)') + } + + if (!(framebuffer instanceof WebGLFramebuffer && + this._checkOwns(framebuffer))) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (this._activeFramebuffer === framebuffer) { + this.bindFramebuffer(gl.FRAMEBUFFER, null) + } + + framebuffer._pendingDelete = true + framebuffer._checkDelete() + } + + // Need to handle textures and render buffers as a special case: + // When a texture gets deleted, we need to do the following extra steps: + // 1. Is it bound to the current texture unit? + // If so, then unbind it + // 2. Is it attached to the active fbo? + // If so, then detach it + // + // For renderbuffers only need to do second step + // + // After this, proceed with the usual deletion algorithm + // + deleteRenderbuffer (renderbuffer) { + if (!checkObject(renderbuffer)) { + throw new TypeError('deleteRenderbuffer(WebGLRenderbuffer)') + } + + if (!(renderbuffer instanceof WebGLRenderbuffer && + this._checkOwns(renderbuffer))) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (this._activeRenderbuffer === renderbuffer) { + this.bindRenderbuffer(gl.RENDERBUFFER, null) + } + + const activeFramebuffer = this._activeFramebuffer + + this._tryDetachFramebuffer(activeFramebuffer, renderbuffer) + + renderbuffer._pendingDelete = true + renderbuffer._checkDelete() + } + + deleteTexture (texture) { + if (!checkObject(texture)) { + throw new TypeError('deleteTexture(WebGLTexture)') + } + + if (texture instanceof WebGLTexture) { + if (!this._checkOwns(texture)) { + this.setError(gl.INVALID_OPERATION) + return + } + } else { + return + } + + // Unbind from all texture units + const curActive = this._activeTextureUnit + + for (let i = 0; i < this._textureUnits.length; ++i) { + const unit = this._textureUnits[i] + if (unit._bind2D === texture) { + this.activeTexture(gl.TEXTURE0 + i) + this.bindTexture(gl.TEXTURE_2D, null) + } else if (unit._bindCube === texture) { + this.activeTexture(gl.TEXTURE0 + i) + this.bindTexture(gl.TEXTURE_CUBE_MAP, null) + } + } + this.activeTexture(gl.TEXTURE0 + curActive) + + // FIXME: Does the texture get unbound from *all* framebuffers, or just the + // active FBO? + const ctx = this + const activeFramebuffer = this._activeFramebuffer + function tryDetach (framebuffer) { + if (framebuffer && framebuffer._linked(texture)) { + const attachments = ctx._getAttachments() + for (let i = 0; i < attachments.length; ++i) { + const attachment = attachments[i] + if (framebuffer._attachments[attachment] === texture) { + ctx.framebufferTexture2D( + gl.FRAMEBUFFER, + attachment, + gl.TEXTURE_2D, + null) + } + } + } + } + + tryDetach(activeFramebuffer) + + // Mark texture for deletion + texture._pendingDelete = true + texture._checkDelete() + } + + depthFunc (func) { + func |= 0 + switch (func) { + case gl.NEVER: + case gl.LESS: + case gl.EQUAL: + case gl.LEQUAL: + case gl.GREATER: + case gl.NOTEQUAL: + case gl.GEQUAL: + case gl.ALWAYS: + return super.depthFunc(func) + default: + this.setError(gl.INVALID_ENUM) + } + } + + depthMask (flag) { + return super.depthMask(!!flag) + } + + depthRange (zNear, zFar) { + zNear = +zNear + zFar = +zFar + if (zNear <= zFar) { + return super.depthRange(zNear, zFar) + } + this.setError(gl.INVALID_OPERATION) + } + + destroy () { + super.destroy() + } + + detachShader (program, shader) { + if (!checkObject(program) || + !checkObject(shader)) { + throw new TypeError('detachShader(WebGLProgram, WebGLShader)') + } + if (this._checkWrapper(program, WebGLProgram) && + this._checkWrapper(shader, WebGLShader)) { + if (program._linked(shader)) { + super.detachShader(program._, shader._) + program._unlink(shader) + } else { + this.setError(gl.INVALID_OPERATION) + } + } + } + + disable (cap) { + cap |= 0 + super.disable(cap) + if (cap === gl.TEXTURE_2D || + cap === gl.TEXTURE_CUBE_MAP) { + const active = this._getActiveTextureUnit() + if (active._mode === cap) { + active._mode = 0 + } + } + } + + disableVertexAttribArray (index) { + index |= 0 + if (index < 0 || index >= this._vertexObjectState._attribs.length) { + this.setError(gl.INVALID_VALUE) + return + } + super.disableVertexAttribArray(index) + this._vertexObjectState._attribs[index]._isPointer = false + } + + drawArrays (mode, first, count) { + mode |= 0 + first |= 0 + count |= 0 + + if (first < 0 || count < 0) { + this.setError(gl.INVALID_VALUE) + return + } + + if (!this._checkStencilState()) { + return + } + + const reducedCount = vertexCount(mode, count) + if (reducedCount < 0) { + this.setError(gl.INVALID_ENUM) + return + } + + if (!this._framebufferOk()) { + return + } + + if (count === 0) { + return + } + + let maxIndex = first + if (count > 0) { + maxIndex = (count + first - 1) >>> 0 + } + if (this._checkVertexAttribState(maxIndex)) { + if ( + this._vertexObjectState._attribs[0]._isPointer || ( + this._extensions.webgl_draw_buffers && + this._extensions.webgl_draw_buffers._buffersState && + this._extensions.webgl_draw_buffers._buffersState.length > 0 + ) + ) { + return super.drawArrays(mode, first, reducedCount) + } else { + this._beginAttrib0Hack() + super._drawArraysInstanced(mode, first, reducedCount, 1) + this._endAttrib0Hack() + } + } + } + + drawElements (mode, count, type, ioffset) { + mode |= 0 + count |= 0 + type |= 0 + ioffset |= 0 + + if (count < 0 || ioffset < 0) { + this.setError(gl.INVALID_VALUE) + return + } + + if (!this._checkStencilState()) { + return + } + + const elementBuffer = this._vertexObjectState._elementArrayBufferBinding + if (!elementBuffer) { + this.setError(gl.INVALID_OPERATION) + return + } + + // Unpack element data + let elementData = null + let offset = ioffset + if (type === gl.UNSIGNED_SHORT) { + if (offset % 2) { + this.setError(gl.INVALID_OPERATION) + return + } + offset >>= 1 + elementData = new Uint16Array(elementBuffer._elements.buffer) + } else if (this._extensions.oes_element_index_uint && type === gl.UNSIGNED_INT) { + if (offset % 4) { + this.setError(gl.INVALID_OPERATION) + return + } + offset >>= 2 + elementData = new Uint32Array(elementBuffer._elements.buffer) + } else if (type === gl.UNSIGNED_BYTE) { + elementData = elementBuffer._elements + } else { + this.setError(gl.INVALID_ENUM) + return + } + + let reducedCount = count + switch (mode) { + case gl.TRIANGLES: + if (count % 3) { + reducedCount -= (count % 3) + } + break + case gl.LINES: + if (count % 2) { + reducedCount -= (count % 2) + } + break + case gl.POINTS: + break + case gl.LINE_LOOP: + case gl.LINE_STRIP: + if (count < 2) { + this.setError(gl.INVALID_OPERATION) + return + } + break + case gl.TRIANGLE_FAN: + case gl.TRIANGLE_STRIP: + if (count < 3) { + this.setError(gl.INVALID_OPERATION) + return + } + break + default: + this.setError(gl.INVALID_ENUM) + return + } + + if (!this._framebufferOk()) { + return + } + + if (count === 0) { + this._checkVertexAttribState(0) + return + } + + if ((count + offset) >>> 0 > elementData.length) { + this.setError(gl.INVALID_OPERATION) + return + } + + // Compute max index + let maxIndex = -1 + for (let i = offset; i < offset + count; ++i) { + maxIndex = Math.max(maxIndex, elementData[i]) + } + + if (maxIndex < 0) { + this._checkVertexAttribState(0) + return + } + + if (this._checkVertexAttribState(maxIndex)) { + if (reducedCount > 0) { + if (this._vertexObjectState._attribs[0]._isPointer) { + return super.drawElements(mode, reducedCount, type, ioffset) + } else { + this._beginAttrib0Hack() + super._drawElementsInstanced(mode, reducedCount, type, ioffset, 1) + this._endAttrib0Hack() + } + } + } + } + + enable (cap) { + cap |= 0 + super.enable(cap) + } + + enableVertexAttribArray (index) { + index |= 0 + if (index < 0 || index >= this._vertexObjectState._attribs.length) { + this.setError(gl.INVALID_VALUE) + return + } + + super.enableVertexAttribArray(index) + + this._vertexObjectState._attribs[index]._isPointer = true + } + + finish () { + return super.finish() + } + + flush () { + return super.flush() + } + + framebufferRenderbuffer ( + target, + attachment, + renderbufferTarget, + renderbuffer) { + target = target | 0 + attachment = attachment | 0 + renderbufferTarget = renderbufferTarget | 0 + + if (!checkObject(renderbuffer)) { + throw new TypeError('framebufferRenderbuffer(GLenum, GLenum, GLenum, WebGLRenderbuffer)') + } + + if (target !== gl.FRAMEBUFFER || + !this._validFramebufferAttachment(attachment) || + renderbufferTarget !== gl.RENDERBUFFER) { + this.setError(gl.INVALID_ENUM) + return + } + + const framebuffer = this._activeFramebuffer + if (!framebuffer) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (renderbuffer && !this._checkWrapper(renderbuffer, WebGLRenderbuffer)) { + return + } + + framebuffer._setAttachment(renderbuffer, attachment) + this._updateFramebufferAttachments(framebuffer) + } + + framebufferTexture2D ( + target, + attachment, + textarget, + texture, + level) { + target |= 0 + attachment |= 0 + textarget |= 0 + level |= 0 + if (!checkObject(texture)) { + throw new TypeError('framebufferTexture2D(GLenum, GLenum, GLenum, WebGLTexture, GLint)') + } + + // Check parameters are ok + if (target !== gl.FRAMEBUFFER || + !this._validFramebufferAttachment(attachment)) { + this.setError(gl.INVALID_ENUM) + return + } + + if (level !== 0) { + this.setError(gl.INVALID_VALUE) + return + } + + // Check object ownership + if (texture && !this._checkWrapper(texture, WebGLTexture)) { + return + } + + // Check texture target is ok + if (textarget === gl.TEXTURE_2D) { + if (texture && texture._binding !== gl.TEXTURE_2D) { + this.setError(gl.INVALID_OPERATION) + return + } + } else if (this._validCubeTarget(textarget)) { + if (texture && texture._binding !== gl.TEXTURE_CUBE_MAP) { + this.setError(gl.INVALID_OPERATION) + return + } + } else { + this.setError(gl.INVALID_ENUM) + return + } + + // Check a framebuffer is actually bound + const framebuffer = this._activeFramebuffer + if (!framebuffer) { + this.setError(gl.INVALID_OPERATION) + return + } + + framebuffer._attachmentLevel[attachment] = level + framebuffer._attachmentFace[attachment] = textarget + framebuffer._setAttachment(texture, attachment) + this._updateFramebufferAttachments(framebuffer) + } + + frontFace (mode) { + return super.frontFace(mode | 0) + } + + generateMipmap (target) { + return super.generateMipmap(target | 0) | 0 + } + + getActiveAttrib (program, index) { + if (!checkObject(program)) { + throw new TypeError('getActiveAttrib(WebGLProgram)') + } else if (!program) { + this.setError(gl.INVALID_VALUE) + } else if (this._checkWrapper(program, WebGLProgram)) { + const info = super.getActiveAttrib(program._ | 0, index | 0) + if (info) { + return new WebGLActiveInfo(info) + } + } + return null + } + + getActiveUniform (program, index) { + if (!checkObject(program)) { + throw new TypeError('getActiveUniform(WebGLProgram, GLint)') + } else if (!program) { + this.setError(gl.INVALID_VALUE) + } else if (this._checkWrapper(program, WebGLProgram)) { + const info = super.getActiveUniform(program._ | 0, index | 0) + if (info) { + return new WebGLActiveInfo(info) + } + } + return null + } + + getAttachedShaders (program) { + if (!checkObject(program) || + (typeof program === 'object' && + program !== null && + !(program instanceof WebGLProgram))) { + throw new TypeError('getAttachedShaders(WebGLProgram)') + } + if (!program) { + this.setError(gl.INVALID_VALUE) + } else if (this._checkWrapper(program, WebGLProgram)) { + const shaderArray = super.getAttachedShaders(program._ | 0) + if (!shaderArray) { + return null + } + const unboxedShaders = new Array(shaderArray.length) + for (let i = 0; i < shaderArray.length; ++i) { + unboxedShaders[i] = this._shaders[shaderArray[i]] + } + return unboxedShaders + } + return null + } + + getAttribLocation (program, name) { + if (!checkObject(program)) { + throw new TypeError('getAttribLocation(WebGLProgram, String)') + } + name += '' + if (!isValidString(name) || name.length > MAX_ATTRIBUTE_LENGTH) { + this.setError(gl.INVALID_VALUE) + } else if (this._checkWrapper(program, WebGLProgram)) { + return super.getAttribLocation(program._ | 0, name + '') + } + return -1 + } + + getParameter (pname) { + pname |= 0 + switch (pname) { + case gl.ARRAY_BUFFER_BINDING: + return this._vertexGlobalState._arrayBufferBinding + case gl.ELEMENT_ARRAY_BUFFER_BINDING: + return this._vertexObjectState._elementArrayBufferBinding + case gl.CURRENT_PROGRAM: + return this._activeProgram + case gl.FRAMEBUFFER_BINDING: + return this._activeFramebuffer + case gl.RENDERBUFFER_BINDING: + return this._activeRenderbuffer + case gl.TEXTURE_BINDING_2D: + return this._getActiveTextureUnit()._bind2D + case gl.TEXTURE_BINDING_CUBE_MAP: + return this._getActiveTextureUnit()._bindCube + case gl.VERSION: + return 'WebGL 1.0 stack-gl ' + HEADLESS_VERSION + case gl.VENDOR: + return 'stack-gl' + case gl.RENDERER: + return 'ANGLE' + case gl.SHADING_LANGUAGE_VERSION: + return 'WebGL GLSL ES 1.0 stack-gl' + + case gl.COMPRESSED_TEXTURE_FORMATS: + return new Uint32Array(0) + + // Int arrays + case gl.MAX_VIEWPORT_DIMS: + case gl.SCISSOR_BOX: + case gl.VIEWPORT: + return new Int32Array(super.getParameter(pname)) + + // Float arrays + case gl.ALIASED_LINE_WIDTH_RANGE: + case gl.ALIASED_POINT_SIZE_RANGE: + case gl.DEPTH_RANGE: + case gl.BLEND_COLOR: + case gl.COLOR_CLEAR_VALUE: + return new Float32Array(super.getParameter(pname)) + + case gl.COLOR_WRITEMASK: + return super.getParameter(pname) + + case gl.DEPTH_CLEAR_VALUE: + case gl.LINE_WIDTH: + case gl.POLYGON_OFFSET_FACTOR: + case gl.POLYGON_OFFSET_UNITS: + case gl.SAMPLE_COVERAGE_VALUE: + return +super.getParameter(pname) + + case gl.BLEND: + case gl.CULL_FACE: + case gl.DEPTH_TEST: + case gl.DEPTH_WRITEMASK: + case gl.DITHER: + case gl.POLYGON_OFFSET_FILL: + case gl.SAMPLE_COVERAGE_INVERT: + case gl.SCISSOR_TEST: + case gl.STENCIL_TEST: + case gl.UNPACK_FLIP_Y_WEBGL: + case gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL: + return !!super.getParameter(pname) + + case gl.ACTIVE_TEXTURE: + case gl.ALPHA_BITS: + case gl.BLEND_DST_ALPHA: + case gl.BLEND_DST_RGB: + case gl.BLEND_EQUATION_ALPHA: + case gl.BLEND_EQUATION_RGB: + case gl.BLEND_SRC_ALPHA: + case gl.BLEND_SRC_RGB: + case gl.BLUE_BITS: + case gl.CULL_FACE_MODE: + case gl.DEPTH_BITS: + case gl.DEPTH_FUNC: + case gl.FRONT_FACE: + case gl.GENERATE_MIPMAP_HINT: + case gl.GREEN_BITS: + case gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS: + case gl.MAX_CUBE_MAP_TEXTURE_SIZE: + case gl.MAX_FRAGMENT_UNIFORM_VECTORS: + case gl.MAX_RENDERBUFFER_SIZE: + case gl.MAX_TEXTURE_IMAGE_UNITS: + case gl.MAX_TEXTURE_SIZE: + case gl.MAX_VARYING_VECTORS: + case gl.MAX_VERTEX_ATTRIBS: + case gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS: + case gl.MAX_VERTEX_UNIFORM_VECTORS: + case gl.PACK_ALIGNMENT: + case gl.RED_BITS: + case gl.SAMPLE_BUFFERS: + case gl.SAMPLES: + case gl.STENCIL_BACK_FAIL: + case gl.STENCIL_BACK_FUNC: + case gl.STENCIL_BACK_PASS_DEPTH_FAIL: + case gl.STENCIL_BACK_PASS_DEPTH_PASS: + case gl.STENCIL_BACK_REF: + case gl.STENCIL_BACK_VALUE_MASK: + case gl.STENCIL_BACK_WRITEMASK: + case gl.STENCIL_BITS: + case gl.STENCIL_CLEAR_VALUE: + case gl.STENCIL_FAIL: + case gl.STENCIL_FUNC: + case gl.STENCIL_PASS_DEPTH_FAIL: + case gl.STENCIL_PASS_DEPTH_PASS: + case gl.STENCIL_REF: + case gl.STENCIL_VALUE_MASK: + case gl.STENCIL_WRITEMASK: + case gl.SUBPIXEL_BITS: + case gl.UNPACK_ALIGNMENT: + case gl.UNPACK_COLORSPACE_CONVERSION_WEBGL: + return super.getParameter(pname) | 0 + + case gl.IMPLEMENTATION_COLOR_READ_FORMAT: + case gl.IMPLEMENTATION_COLOR_READ_TYPE: + return super.getParameter(pname) + + default: + if (this._extensions.webgl_draw_buffers) { + const ext = this._extensions.webgl_draw_buffers + switch (pname) { + case ext.DRAW_BUFFER0_WEBGL: + case ext.DRAW_BUFFER1_WEBGL: + case ext.DRAW_BUFFER2_WEBGL: + case ext.DRAW_BUFFER3_WEBGL: + case ext.DRAW_BUFFER4_WEBGL: + case ext.DRAW_BUFFER5_WEBGL: + case ext.DRAW_BUFFER6_WEBGL: + case ext.DRAW_BUFFER7_WEBGL: + case ext.DRAW_BUFFER8_WEBGL: + case ext.DRAW_BUFFER9_WEBGL: + case ext.DRAW_BUFFER10_WEBGL: + case ext.DRAW_BUFFER11_WEBGL: + case ext.DRAW_BUFFER12_WEBGL: + case ext.DRAW_BUFFER13_WEBGL: + case ext.DRAW_BUFFER14_WEBGL: + case ext.DRAW_BUFFER15_WEBGL: + if (ext._buffersState.length === 1 && ext._buffersState[0] === gl.BACK) { + return gl.BACK + } + return super.getParameter(pname) + case ext.MAX_DRAW_BUFFERS_WEBGL: + case ext.MAX_COLOR_ATTACHMENTS_WEBGL: + return super.getParameter(pname) + } + } + + if (this._extensions.oes_standard_derivatives && pname === this._extensions.oes_standard_derivatives.FRAGMENT_SHADER_DERIVATIVE_HINT_OES) { + return super.getParameter(pname) + } + + if (this._extensions.ext_texture_filter_anisotropic && pname === this._extensions.ext_texture_filter_anisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT) { + return super.getParameter(pname) + } + + if (this._extensions.oes_vertex_array_object && pname === this._extensions.oes_vertex_array_object.VERTEX_ARRAY_BINDING_OES) { + return this._extensions.oes_vertex_array_object._activeVertexArrayObject + } + + this.setError(gl.INVALID_ENUM) + return null + } + } + + getShaderPrecisionFormat ( + shaderType, + precisionType) { + shaderType |= 0 + precisionType |= 0 + + if (!(shaderType === gl.FRAGMENT_SHADER || + shaderType === gl.VERTEX_SHADER) || + !(precisionType === gl.LOW_FLOAT || + precisionType === gl.MEDIUM_FLOAT || + precisionType === gl.HIGH_FLOAT || + precisionType === gl.LOW_INT || + precisionType === gl.MEDIUM_INT || + precisionType === gl.HIGH_INT)) { + this.setError(gl.INVALID_ENUM) + return + } + + const format = super.getShaderPrecisionFormat(shaderType, precisionType) + if (!format) { + return null + } + + return new WebGLShaderPrecisionFormat(format) + } + + getBufferParameter (target, pname) { + target |= 0 + pname |= 0 + if (target !== gl.ARRAY_BUFFER && + target !== gl.ELEMENT_ARRAY_BUFFER) { + this.setError(gl.INVALID_ENUM) + return null + } + + switch (pname) { + case gl.BUFFER_SIZE: + case gl.BUFFER_USAGE: + return super.getBufferParameter(target | 0, pname | 0) + default: + this.setError(gl.INVALID_ENUM) + return null + } + } + + getError () { + return super.getError() + } + + getFramebufferAttachmentParameter (target, attachment, pname) { + target |= 0 + attachment |= 0 + pname |= 0 + + if (target !== gl.FRAMEBUFFER || + !this._validFramebufferAttachment(attachment)) { + this.setError(gl.INVALID_ENUM) + return null + } + + const framebuffer = this._activeFramebuffer + if (!framebuffer) { + this.setError(gl.INVALID_OPERATION) + return null + } + + const object = framebuffer._attachments[attachment] + if (object === null) { + if (pname === gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) { + return gl.NONE + } + } else if (object instanceof WebGLTexture) { + switch (pname) { + case gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + return object + case gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + return gl.TEXTURE + case gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + return framebuffer._attachmentLevel[attachment] + case gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: { + const face = framebuffer._attachmentFace[attachment] + if (face === gl.TEXTURE_2D) { + return 0 + } + return face + } + } + } else if (object instanceof WebGLRenderbuffer) { + switch (pname) { + case gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + return object + case gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + return gl.RENDERBUFFER + } + } + + this.setError(gl.INVALID_ENUM) + return null + } + + getProgramParameter (program, pname) { + pname |= 0 + if (!checkObject(program)) { + throw new TypeError('getProgramParameter(WebGLProgram, GLenum)') + } else if (this._checkWrapper(program, WebGLProgram)) { + switch (pname) { + case gl.DELETE_STATUS: + return program._pendingDelete + + case gl.LINK_STATUS: + return program._linkStatus + + case gl.VALIDATE_STATUS: + return !!super.getProgramParameter(program._, pname) + + case gl.ATTACHED_SHADERS: + case gl.ACTIVE_ATTRIBUTES: + case gl.ACTIVE_UNIFORMS: + return super.getProgramParameter(program._, pname) + } + this.setError(gl.INVALID_ENUM) + } + return null + } + + getProgramInfoLog (program) { + if (!checkObject(program)) { + throw new TypeError('getProgramInfoLog(WebGLProgram)') + } else if (this._checkWrapper(program, WebGLProgram)) { + return program._linkInfoLog + } + return null + } + + getRenderbufferParameter (target, pname) { + target |= 0 + pname |= 0 + if (target !== gl.RENDERBUFFER) { + this.setError(gl.INVALID_ENUM) + return null + } + const renderbuffer = this._activeRenderbuffer + if (!renderbuffer) { + this.setError(gl.INVALID_OPERATION) + return null + } + switch (pname) { + case gl.RENDERBUFFER_INTERNAL_FORMAT: + return renderbuffer._format + case gl.RENDERBUFFER_WIDTH: + return renderbuffer._width + case gl.RENDERBUFFER_HEIGHT: + return renderbuffer._height + case gl.RENDERBUFFER_SIZE: + case gl.RENDERBUFFER_RED_SIZE: + case gl.RENDERBUFFER_GREEN_SIZE: + case gl.RENDERBUFFER_BLUE_SIZE: + case gl.RENDERBUFFER_ALPHA_SIZE: + case gl.RENDERBUFFER_DEPTH_SIZE: + case gl.RENDERBUFFER_STENCIL_SIZE: + return super.getRenderbufferParameter(target, pname) + } + this.setError(gl.INVALID_ENUM) + return null + } + + getShaderParameter (shader, pname) { + pname |= 0 + if (!checkObject(shader)) { + throw new TypeError('getShaderParameter(WebGLShader, GLenum)') + } else if (this._checkWrapper(shader, WebGLShader)) { + switch (pname) { + case gl.DELETE_STATUS: + return shader._pendingDelete + case gl.COMPILE_STATUS: + return shader._compileStatus + case gl.SHADER_TYPE: + return shader._type + } + this.setError(gl.INVALID_ENUM) + } + return null + } + + getShaderInfoLog (shader) { + if (!checkObject(shader)) { + throw new TypeError('getShaderInfoLog(WebGLShader)') + } else if (this._checkWrapper(shader, WebGLShader)) { + return shader._compileInfo + } + return null + } + + getShaderSource (shader) { + if (!checkObject(shader)) { + throw new TypeError('Input to getShaderSource must be an object') + } else if (this._checkWrapper(shader, WebGLShader)) { + return shader._source + } + return null + } + + getTexParameter (target, pname) { + target |= 0 + pname |= 0 + + if (!this._checkTextureTarget(target)) { + return null + } + + const unit = this._getActiveTextureUnit() + if ((target === gl.TEXTURE_2D && !unit._bind2D) || + (target === gl.TEXTURE_CUBE_MAP && !unit._bindCube)) { + this.setError(gl.INVALID_OPERATION) + return null + } + + switch (pname) { + case gl.TEXTURE_MAG_FILTER: + case gl.TEXTURE_MIN_FILTER: + case gl.TEXTURE_WRAP_S: + case gl.TEXTURE_WRAP_T: + return super.getTexParameter(target, pname) + } + + if (this._extensions.ext_texture_filter_anisotropic && pname === this._extensions.ext_texture_filter_anisotropic.TEXTURE_MAX_ANISOTROPY_EXT) { + return super.getTexParameter(target, pname) + } + + this.setError(gl.INVALID_ENUM) + return null + } + + getUniform (program, location) { + if (!checkObject(program) || + !checkObject(location)) { + throw new TypeError('getUniform(WebGLProgram, WebGLUniformLocation)') + } else if (!program) { + this.setError(gl.INVALID_VALUE) + return null + } else if (!location) { + return null + } else if (this._checkWrapper(program, WebGLProgram)) { + if (!checkUniform(program, location)) { + this.setError(gl.INVALID_OPERATION) + return null + } + const data = super.getUniform(program._ | 0, location._ | 0) + if (!data) { + return null + } + switch (location._activeInfo.type) { + case gl.FLOAT: + return data[0] + case gl.FLOAT_VEC2: + return new Float32Array(data.slice(0, 2)) + case gl.FLOAT_VEC3: + return new Float32Array(data.slice(0, 3)) + case gl.FLOAT_VEC4: + return new Float32Array(data.slice(0, 4)) + case gl.INT: + return data[0] | 0 + case gl.INT_VEC2: + return new Int32Array(data.slice(0, 2)) + case gl.INT_VEC3: + return new Int32Array(data.slice(0, 3)) + case gl.INT_VEC4: + return new Int32Array(data.slice(0, 4)) + case gl.BOOL: + return !!data[0] + case gl.BOOL_VEC2: + return [!!data[0], !!data[1]] + case gl.BOOL_VEC3: + return [!!data[0], !!data[1], !!data[2]] + case gl.BOOL_VEC4: + return [!!data[0], !!data[1], !!data[2], !!data[3]] + case gl.FLOAT_MAT2: + return new Float32Array(data.slice(0, 4)) + case gl.FLOAT_MAT3: + return new Float32Array(data.slice(0, 9)) + case gl.FLOAT_MAT4: + return new Float32Array(data.slice(0, 16)) + case gl.SAMPLER_2D: + case gl.SAMPLER_CUBE: + return data[0] | 0 + default: + return null + } + } + return null + } + + getUniformLocation (program, name) { + if (!checkObject(program)) { + throw new TypeError('getUniformLocation(WebGLProgram, String)') + } + + name += '' + if (!isValidString(name)) { + this.setError(gl.INVALID_VALUE) + return + } + + if (this._checkWrapper(program, WebGLProgram)) { + const loc = super.getUniformLocation(program._ | 0, name) + if (loc >= 0) { + let searchName = name + if (/\[\d+\]$/.test(name)) { + searchName = name.replace(/\[\d+\]$/, '[0]') + } + + let info = null + for (let i = 0; i < program._uniforms.length; ++i) { + const infoItem = program._uniforms[i] + if (infoItem.name === searchName) { + info = { + size: infoItem.size, + type: infoItem.type, + name: infoItem.name + } + } + } + if (!info) { + return null + } + + const result = new WebGLUniformLocation( + loc, + program, + info) + + // handle array case + if (/\[0\]$/.test(name)) { + const baseName = name.replace(/\[0\]$/, '') + const arrayLocs = [] + + // if (offset < 0 || offset >= info.size) { + // return null + // } + + this._saveError() + for (let i = 0; this.getError() === gl.NO_ERROR; ++i) { + const xloc = super.getUniformLocation( + program._ | 0, + baseName + '[' + i + ']') + if (this.getError() !== gl.NO_ERROR || xloc < 0) { + break + } + arrayLocs.push(xloc) + } + this._restoreError(gl.NO_ERROR) + + result._array = arrayLocs + } else if (/\[(\d+)\]$/.test(name)) { + const offset = +(/\[(\d+)\]$/.exec(name))[1] + if (offset < 0 || offset >= info.size) { + return null + } + } + return result + } + } + return null + } + + getVertexAttrib (index, pname) { + index |= 0 + pname |= 0 + if (index < 0 || index >= this._vertexObjectState._attribs.length) { + this.setError(gl.INVALID_VALUE) + return null + } + const attrib = this._vertexObjectState._attribs[index] + const vertexAttribValue = this._vertexGlobalState._attribs[index]._data + + const extInstancing = this._extensions.angle_instanced_arrays + if (extInstancing) { + if (pname === extInstancing.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE) { + return attrib._divisor + } + } + + switch (pname) { + case gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + return attrib._pointerBuffer + case gl.VERTEX_ATTRIB_ARRAY_ENABLED: + return attrib._isPointer + case gl.VERTEX_ATTRIB_ARRAY_SIZE: + return attrib._inputSize + case gl.VERTEX_ATTRIB_ARRAY_STRIDE: + return attrib._inputStride + case gl.VERTEX_ATTRIB_ARRAY_TYPE: + return attrib._pointerType + case gl.VERTEX_ATTRIB_ARRAY_NORMALIZED: + return attrib._pointerNormal + case gl.CURRENT_VERTEX_ATTRIB: + return new Float32Array(vertexAttribValue) + default: + this.setError(gl.INVALID_ENUM) + return null + } + } + + getVertexAttribOffset (index, pname) { + index |= 0 + pname |= 0 + if (index < 0 || index >= this._vertexObjectState._attribs.length) { + this.setError(gl.INVALID_VALUE) + return null + } + if (pname === gl.VERTEX_ATTRIB_ARRAY_POINTER) { + return this._vertexObjectState._attribs[index]._pointerOffset + } else { + this.setError(gl.INVALID_ENUM) + return null + } + } + + hint (target, mode) { + target |= 0 + mode |= 0 + + if (!( + target === gl.GENERATE_MIPMAP_HINT || + ( + this._extensions.oes_standard_derivatives && target === this._extensions.oes_standard_derivatives.FRAGMENT_SHADER_DERIVATIVE_HINT_OES + ) + )) { + this.setError(gl.INVALID_ENUM) + return + } + + if (mode !== gl.FASTEST && + mode !== gl.NICEST && + mode !== gl.DONT_CARE) { + this.setError(gl.INVALID_ENUM) + return + } + + return super.hint(target, mode) + } + + isBuffer (object) { + if (!this._isObject(object, 'isBuffer', WebGLBuffer)) return false + return super.isBuffer(object._ | 0) + } + + isFramebuffer (object) { + if (!this._isObject(object, 'isFramebuffer', WebGLFramebuffer)) return false + return super.isFramebuffer(object._ | 0) + } + + isProgram (object) { + if (!this._isObject(object, 'isProgram', WebGLProgram)) return false + return super.isProgram(object._ | 0) + } + + isRenderbuffer (object) { + if (!this._isObject(object, 'isRenderbuffer', WebGLRenderbuffer)) return false + return super.isRenderbuffer(object._ | 0) + } + + isShader (object) { + if (!this._isObject(object, 'isShader', WebGLShader)) return false + return super.isShader(object._ | 0) + } + + isTexture (object) { + if (!this._isObject(object, 'isTexture', WebGLTexture)) return false + return super.isTexture(object._ | 0) + } + + isEnabled (cap) { + return super.isEnabled(cap | 0) + } + + lineWidth (width) { + if (isNaN(width)) { + this.setError(gl.INVALID_VALUE) + return + } + return super.lineWidth(+width) + } + + linkProgram (program) { + if (!checkObject(program)) { + throw new TypeError('linkProgram(WebGLProgram)') + } + if (this._checkWrapper(program, WebGLProgram)) { + program._linkCount += 1 + program._attributes = [] + const prevError = this.getError() + super.linkProgram(program._ | 0) + const error = this.getError() + if (error === gl.NO_ERROR) { + program._linkStatus = this._fixupLink(program) + } + this.getError() + this.setError(prevError || error) + } + } + + pixelStorei (pname, param) { + pname |= 0 + param |= 0 + if (pname === gl.UNPACK_ALIGNMENT) { + if (param === 1 || + param === 2 || + param === 4 || + param === 8) { + this._unpackAlignment = param + } else { + this.setError(gl.INVALID_VALUE) + return + } + } else if (pname === gl.PACK_ALIGNMENT) { + if (param === 1 || + param === 2 || + param === 4 || + param === 8) { + this._packAlignment = param + } else { + this.setError(gl.INVALID_VALUE) + return + } + } else if (pname === gl.UNPACK_COLORSPACE_CONVERSION_WEBGL) { + if (!(param === gl.NONE || param === gl.BROWSER_DEFAULT_WEBGL)) { + this.setError(gl.INVALID_VALUE) + return + } + } + return super.pixelStorei(pname, param) + } + + polygonOffset (factor, units) { + return super.polygonOffset(+factor, +units) + } + + readPixels (x, y, width, height, format, type, pixels) { + x |= 0 + y |= 0 + width |= 0 + height |= 0 + + if (this._extensions.oes_texture_float && type === gl.FLOAT && format === gl.RGBA) { + } else if (format === gl.RGB || + format === gl.ALPHA || + type !== gl.UNSIGNED_BYTE) { + this.setError(gl.INVALID_OPERATION) + return + } else if (format !== gl.RGBA) { + this.setError(gl.INVALID_ENUM) + return + } else if ( + width < 0 || + height < 0 || + !(pixels instanceof Uint8Array)) { + this.setError(gl.INVALID_VALUE) + return + } + + if (!this._framebufferOk()) { + return + } + + let rowStride = width * 4 + if (rowStride % this._packAlignment !== 0) { + rowStride += this._packAlignment - (rowStride % this._packAlignment) + } + + const imageSize = rowStride * (height - 1) + width * 4 + if (imageSize <= 0) { + return + } + if (pixels.length < imageSize) { + this.setError(gl.INVALID_VALUE) + return + } + + // Handle reading outside the window + let viewWidth = this.drawingBufferWidth + let viewHeight = this.drawingBufferHeight + + if (this._activeFramebuffer) { + viewWidth = this._activeFramebuffer._width + viewHeight = this._activeFramebuffer._height + } + + const pixelData = unpackTypedArray(pixels) + + if (x >= viewWidth || x + width <= 0 || + y >= viewHeight || y + height <= 0) { + for (let i = 0; i < pixelData.length; ++i) { + pixelData[i] = 0 + } + } else if (x < 0 || x + width > viewWidth || + y < 0 || y + height > viewHeight) { + for (let i = 0; i < pixelData.length; ++i) { + pixelData[i] = 0 + } + + let nx = x + let nWidth = width + if (x < 0) { + nWidth += x + nx = 0 + } + if (nx + width > viewWidth) { + nWidth = viewWidth - nx + } + let ny = y + let nHeight = height + if (y < 0) { + nHeight += y + ny = 0 + } + if (ny + height > viewHeight) { + nHeight = viewHeight - ny + } + + let nRowStride = nWidth * 4 + if (nRowStride % this._packAlignment !== 0) { + nRowStride += this._packAlignment - (nRowStride % this._packAlignment) + } + + if (nWidth > 0 && nHeight > 0) { + const subPixels = new Uint8Array(nRowStride * nHeight) + super.readPixels( + nx, + ny, + nWidth, + nHeight, + format, + type, + subPixels) + + const offset = 4 * (nx - x) + (ny - y) * rowStride + for (let j = 0; j < nHeight; ++j) { + for (let i = 0; i < nWidth; ++i) { + for (let k = 0; k < 4; ++k) { + pixelData[offset + j * rowStride + 4 * i + k] = + subPixels[j * nRowStride + 4 * i + k] + } + } + } + } + } else { + super.readPixels( + x, + y, + width, + height, + format, + type, + pixelData) + } + } + + renderbufferStorage ( + target, + internalFormat, + width, + height) { + target |= 0 + internalFormat |= 0 + width |= 0 + height |= 0 + + if (target !== gl.RENDERBUFFER) { + this.setError(gl.INVALID_ENUM) + return + } + + const renderbuffer = this._activeRenderbuffer + if (!renderbuffer) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (internalFormat !== gl.RGBA4 && + internalFormat !== gl.RGB565 && + internalFormat !== gl.RGB5_A1 && + internalFormat !== gl.DEPTH_COMPONENT16 && + internalFormat !== gl.STENCIL_INDEX && + internalFormat !== gl.STENCIL_INDEX8 && + internalFormat !== gl.DEPTH_STENCIL) { + this.setError(gl.INVALID_ENUM) + return + } + + this._saveError() + super.renderbufferStorage( + target, + internalFormat, + width, + height) + const error = this.getError() + this._restoreError(error) + if (error !== gl.NO_ERROR) { + return + } + + renderbuffer._width = width + renderbuffer._height = height + renderbuffer._format = internalFormat + + const activeFramebuffer = this._activeFramebuffer + if (activeFramebuffer) { + let needsUpdate = false + const attachments = this._getAttachments() + for (let i = 0; i < attachments.length; ++i) { + if (activeFramebuffer._attachments[attachments[i]] === renderbuffer) { + needsUpdate = true + break + } + } + if (needsUpdate) { + this._updateFramebufferAttachments(this._activeFramebuffer) + } + } + } + + resize (width, height) { + width = width | 0 + height = height | 0 + if (!(width > 0 && height > 0)) { + throw new Error('Invalid surface dimensions') + } else if (width !== this.drawingBufferWidth || + height !== this.drawingBufferHeight) { + this._resizeDrawingBuffer(width, height) + this.drawingBufferWidth = width + this.drawingBufferHeight = height + } + } + + sampleCoverage (value, invert) { + return super.sampleCoverage(+value, !!invert) + } + + scissor (x, y, width, height) { + return super.scissor(x | 0, y | 0, width | 0, height | 0) + } + + shaderSource (shader, source) { + if (!checkObject(shader)) { + throw new TypeError('shaderSource(WebGLShader, String)') + } + if (!shader || (!source && typeof source !== 'string')) { + this.setError(gl.INVALID_VALUE) + return + } + source += '' + if (!isValidString(source)) { + this.setError(gl.INVALID_VALUE) + } else if (this._checkWrapper(shader, WebGLShader)) { + super.shaderSource(shader._ | 0, this._wrapShader(shader._type, source)) // eslint-disable-line + shader._source = source + } + } + + stencilFunc (func, ref, mask) { + this._checkStencil = true + return super.stencilFunc(func | 0, ref | 0, mask | 0) + } + + stencilFuncSeparate (face, func, ref, mask) { + this._checkStencil = true + return super.stencilFuncSeparate(face | 0, func | 0, ref | 0, mask | 0) + } + + stencilMask (mask) { + this._checkStencil = true + return super.stencilMask(mask | 0) + } + + stencilMaskSeparate (face, mask) { + this._checkStencil = true + return super.stencilMaskSeparate(face | 0, mask | 0) + } + + stencilOp (fail, zfail, zpass) { + this._checkStencil = true + return super.stencilOp(fail | 0, zfail | 0, zpass | 0) + } + + stencilOpSeparate (face, fail, zfail, zpass) { + this._checkStencil = true + return super.stencilOpSeparate(face | 0, fail | 0, zfail | 0, zpass | 0) + } + + texImage2D ( + target, + level, + internalFormat, + width, + height, + border, + format, + type, + pixels) { + if (arguments.length === 6) { + pixels = border + type = height + format = width + + pixels = extractImageData(pixels) + + if (pixels == null) { + throw new TypeError('texImage2D(GLenum, GLint, GLenum, GLint, GLenum, GLenum, ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement)') + } + + width = pixels.width + height = pixels.height + pixels = pixels.data + } + + target |= 0 + level |= 0 + internalFormat |= 0 + width |= 0 + height |= 0 + border |= 0 + format |= 0 + type |= 0 + + if (typeof pixels !== 'object' && pixels !== undefined) { + throw new TypeError('texImage2D(GLenum, GLint, GLenum, GLint, GLint, GLint, GLenum, GLenum, Uint8Array)') + } + + if (!checkFormat(format) || !checkFormat(internalFormat)) { + this.setError(gl.INVALID_ENUM) + return + } + + if (type === gl.FLOAT && !this._extensions.oes_texture_float) { + this.setError(gl.INVALID_ENUM) + return + } + + const texture = this._getTexImage(target) + if (!texture || format !== internalFormat) { + this.setError(gl.INVALID_OPERATION) + return + } + + const pixelSize = this._computePixelSize(type, format) + if (pixelSize === 0) { + return + } + + if (!this._checkDimensions( + target, + width, + height, + level)) { + return + } + + const data = convertPixels(pixels) + const rowStride = this._computeRowStride(width, pixelSize) + const imageSize = rowStride * height + + if (data && data.length < imageSize) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (border !== 0 || + (validCubeTarget(target) && width !== height)) { + this.setError(gl.INVALID_VALUE) + return + } + // Need to check for out of memory error + this._saveError() + super.texImage2D( + target, + level, + internalFormat, + width, + height, + border, + format, + type, + data) + const error = this.getError() + this._restoreError(error) + if (error !== gl.NO_ERROR) { + return + } + + // Save width and height at level + texture._levelWidth[level] = width + texture._levelHeight[level] = height + texture._format = format + texture._type = type + + const activeFramebuffer = this._activeFramebuffer + if (activeFramebuffer) { + let needsUpdate = false + const attachments = this._getAttachments() + for (let i = 0; i < attachments.length; ++i) { + if (activeFramebuffer._attachments[attachments[i]] === texture) { + needsUpdate = true + break + } + } + if (needsUpdate) { + this._updateFramebufferAttachments(this._activeFramebuffer) + } + } + } + + texSubImage2D ( + target, + level, + xoffset, + yoffset, + width, + height, + format, + type, + pixels) { + if (arguments.length === 7) { + pixels = format + type = height + format = width + + pixels = extractImageData(pixels) + + if (pixels == null) { + throw new TypeError('texSubImage2D(GLenum, GLint, GLint, GLint, GLenum, GLenum, ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement)') + } + + width = pixels.width + height = pixels.height + pixels = pixels.data + } + + if (typeof pixels !== 'object') { + throw new TypeError('texSubImage2D(GLenum, GLint, GLint, GLint, GLint, GLint, GLenum, GLenum, Uint8Array)') + } + + target |= 0 + level |= 0 + xoffset |= 0 + yoffset |= 0 + width |= 0 + height |= 0 + format |= 0 + type |= 0 + + const texture = this._getTexImage(target) + if (!texture) { + this.setError(gl.INVALID_OPERATION) + return + } + + if (type === gl.FLOAT && !this._extensions.oes_texture_float) { + this.setError(gl.INVALID_ENUM) + return + } + + const pixelSize = this._computePixelSize(type, format) + if (pixelSize === 0) { + return + } + + if (!this._checkDimensions( + target, + width, + height, + level)) { + return + } + + if (xoffset < 0 || yoffset < 0) { + this.setError(gl.INVALID_VALUE) + return + } + + const data = convertPixels(pixels) + const rowStride = this._computeRowStride(width, pixelSize) + const imageSize = rowStride * height + + if (!data || data.length < imageSize) { + this.setError(gl.INVALID_OPERATION) + return + } + + super.texSubImage2D( + target, + level, + xoffset, + yoffset, + width, + height, + format, + type, + data) + } + + texParameterf (target, pname, param) { + target |= 0 + pname |= 0 + param = +param + + if (this._checkTextureTarget(target)) { + this._verifyTextureCompleteness(target, pname, param) + switch (pname) { + case gl.TEXTURE_MIN_FILTER: + case gl.TEXTURE_MAG_FILTER: + case gl.TEXTURE_WRAP_S: + case gl.TEXTURE_WRAP_T: + return super.texParameterf(target, pname, param) + } + + if (this._extensions.ext_texture_filter_anisotropic && pname === this._extensions.ext_texture_filter_anisotropic.TEXTURE_MAX_ANISOTROPY_EXT) { + return super.texParameterf(target, pname, param) + } + + this.setError(gl.INVALID_ENUM) + } + } + + texParameteri (target, pname, param) { + target |= 0 + pname |= 0 + param |= 0 + + if (this._checkTextureTarget(target)) { + this._verifyTextureCompleteness(target, pname, param) + switch (pname) { + case gl.TEXTURE_MIN_FILTER: + case gl.TEXTURE_MAG_FILTER: + case gl.TEXTURE_WRAP_S: + case gl.TEXTURE_WRAP_T: + return super.texParameteri(target, pname, param) + } + + if (this._extensions.ext_texture_filter_anisotropic && pname === this._extensions.ext_texture_filter_anisotropic.TEXTURE_MAX_ANISOTROPY_EXT) { + return super.texParameteri(target, pname, param) + } + + this.setError(gl.INVALID_ENUM) + } + } + + useProgram (program) { + if (!checkObject(program)) { + throw new TypeError('useProgram(WebGLProgram)') + } else if (!program) { + this._switchActiveProgram(this._activeProgram) + this._activeProgram = null + return super.useProgram(0) + } else if (this._checkWrapper(program, WebGLProgram)) { + if (this._activeProgram !== program) { + this._switchActiveProgram(this._activeProgram) + this._activeProgram = program + program._refCount += 1 + } + return super.useProgram(program._ | 0) + } + } + + validateProgram (program) { + if (this._checkWrapper(program, WebGLProgram)) { + super.validateProgram(program._ | 0) + const error = this.getError() + if (error === gl.NO_ERROR) { + program._linkInfoLog = super.getProgramInfoLog(program._ | 0) + } + this.getError() + this.setError(error) + } + } + + vertexAttribPointer ( + index, + size, + type, + normalized, + stride, + offset) { + if (stride < 0 || offset < 0) { + this.setError(gl.INVALID_VALUE) + return + } + + index |= 0 + size |= 0 + type |= 0 + normalized = !!normalized + stride |= 0 + offset |= 0 + + if (stride < 0 || + offset < 0 || + index < 0 || index >= this._vertexObjectState._attribs.length || + !(size === 1 || size === 2 || size === 3 || size === 4)) { + this.setError(gl.INVALID_VALUE) + return + } + + if (this._vertexGlobalState._arrayBufferBinding === null) { + this.setError(gl.INVALID_OPERATION) + return + } + + // fixed, int and unsigned int aren't allowed in WebGL + const byteSize = typeSize(type) + if (byteSize === 0 || + type === gl.INT || + type === gl.UNSIGNED_INT) { + this.setError(gl.INVALID_ENUM) + return + } + + if (stride > 255 || stride < 0) { + this.setError(gl.INVALID_VALUE) + return + } + + // stride and offset must be multiples of size + if ((stride % byteSize) !== 0 || + (offset % byteSize) !== 0) { + this.setError(gl.INVALID_OPERATION) + return + } + + // Call vertex attrib pointer + super.vertexAttribPointer(index, size, type, normalized, stride, offset) + + // Update the vertex state object and references. + this._vertexObjectState.setVertexAttribPointer( + /* buffer */ this._vertexGlobalState._arrayBufferBinding, + /* index */ index, + /* pointerSize */ size * byteSize, + /* pointerOffset */ offset, + /* pointerStride */ stride || (size * byteSize), + /* pointerType */ type, + /* pointerNormal */ normalized, + /* inputStride */ stride, + /* inputSize */ size + ) + } + + viewport (x, y, width, height) { + return super.viewport(x | 0, y | 0, width | 0, height | 0) + } + + _allocateDrawingBuffer (width, height) { + this._drawingBuffer = new WebGLDrawingBufferWrapper( + super.createFramebuffer(), + super.createTexture(), + super.createRenderbuffer()) + + this._resizeDrawingBuffer(width, height) + } + + isContextLost () { + return false + } + + compressedTexImage2D () { + // TODO not yet implemented + } + + compressedTexSubImage2D () { + // TODO not yet implemented + } + + _checkUniformValid (location, v0, name, count, type) { + if (!checkObject(location)) { + throw new TypeError(`${name}(WebGLUniformLocation, ...)`) + } else if (!location) { + return false + } else if (this._checkLocationActive(location)) { + const utype = location._activeInfo.type + if (utype === gl.SAMPLER_2D || utype === gl.SAMPLER_CUBE) { + if (count !== 1) { + this.setError(gl.INVALID_VALUE) + return + } + if (type !== 'i') { + this.setError(gl.INVALID_OPERATION) + return + } + if (v0 < 0 || v0 >= this._textureUnits.length) { + this.setError(gl.INVALID_VALUE) + return false + } + } + if (uniformTypeSize(utype) > count) { + this.setError(gl.INVALID_OPERATION) + return false + } + return true + } + return false + } + + _checkUniformValueValid (location, value, name, count, type) { + if (!checkObject(location) || + !checkObject(value)) { + throw new TypeError(`${name}v(WebGLUniformLocation, Array)`) + } else if (!location) { + return false + } else if (!this._checkLocationActive(location)) { + return false + } else if (typeof value !== 'object' || !value || typeof value.length !== 'number') { + throw new TypeError(`Second argument to ${name} must be array`) + } else if (uniformTypeSize(location._activeInfo.type) > count) { + this.setError(gl.INVALID_OPERATION) + return false + } else if (value.length >= count && value.length % count === 0) { + if (location._array) { + return true + } else if (value.length === count) { + return true + } else { + this.setError(gl.INVALID_OPERATION) + return false + } + } + this.setError(gl.INVALID_VALUE) + return false + } + + uniform1f (location, v0) { + if (!this._checkUniformValid(location, v0, 'uniform1f', 1, 'f')) return + super.uniform1f(location._ | 0, v0) + } + + uniform1fv (location, value) { + if (!this._checkUniformValueValid(location, value, 'uniform1fv', 1, 'f')) return + if (location._array) { + const locs = location._array + for (let i = 0; i < locs.length && i < value.length; ++i) { + const loc = locs[i] + super.uniform1f(loc, value[i]) + } + return + } + super.uniform1f(location._ | 0, value[0]) + } + + uniform1i (location, v0) { + if (!this._checkUniformValid(location, v0, 'uniform1i', 1, 'i')) return + super.uniform1i(location._ | 0, v0) + } + + uniform1iv (location, value) { + if (!this._checkUniformValueValid(location, value, 'uniform1iv', 1, 'i')) return + if (location._array) { + const locs = location._array + for (let i = 0; i < locs.length && i < value.length; ++i) { + const loc = locs[i] + super.uniform1i(loc, value[i]) + } + return + } + this.uniform1i(location, value[0]) + } + + uniform2f (location, v0, v1) { + if (!this._checkUniformValid(location, v0, 'uniform2f', 2, 'f')) return + super.uniform2f(location._ | 0, v0, v1) + } + + uniform2fv (location, value) { + if (!this._checkUniformValueValid(location, value, 'uniform2fv', 2, 'f')) return + if (location._array) { + const locs = location._array + for (let i = 0; i < locs.length && 2 * i < value.length; ++i) { + const loc = locs[i] + super.uniform2f(loc, value[2 * i], value[(2 * i) + 1]) + } + return + } + super.uniform2f(location._ | 0, value[0], value[1]) + } + + uniform2i (location, v0, v1) { + if (!this._checkUniformValid(location, v0, 'uniform2i', 2, 'i')) return + super.uniform2i(location._ | 0, v0, v1) + } + + uniform2iv (location, value) { + if (!this._checkUniformValueValid(location, value, 'uniform2iv', 2, 'i')) return + if (location._array) { + const locs = location._array + for (let i = 0; i < locs.length && 2 * i < value.length; ++i) { + const loc = locs[i] + super.uniform2i(loc, value[2 * i], value[2 * i + 1]) + } + return + } + this.uniform2i(location, value[0], value[1]) + } + + uniform3f (location, v0, v1, v2) { + if (!this._checkUniformValid(location, v0, 'uniform3f', 3, 'f')) return + super.uniform3f(location._ | 0, v0, v1, v2) + } + + uniform3fv (location, value) { + if (!this._checkUniformValueValid(location, value, 'uniform3fv', 3, 'f')) return + if (location._array) { + const locs = location._array + for (let i = 0; i < locs.length && 3 * i < value.length; ++i) { + const loc = locs[i] + super.uniform3f(loc, value[3 * i], value[3 * i + 1], value[3 * i + 2]) + } + return + } + super.uniform3f(location._ | 0, value[0], value[1], value[2]) + } + + uniform3i (location, v0, v1, v2) { + if (!this._checkUniformValid(location, v0, 'uniform3i', 3, 'i')) return + super.uniform3i(location._ | 0, v0, v1, v2) + } + + uniform3iv (location, value) { + if (!this._checkUniformValueValid(location, value, 'uniform3iv', 3, 'i')) return + if (location._array) { + const locs = location._array + for (let i = 0; i < locs.length && 3 * i < value.length; ++i) { + const loc = locs[i] + super.uniform3i(loc, value[3 * i], value[3 * i + 1], value[3 * i + 2]) + } + return + } + this.uniform3i(location, value[0], value[1], value[2]) + } + + uniform4f (location, v0, v1, v2, v3) { + if (!this._checkUniformValid(location, v0, 'uniform4f', 4, 'f')) return + super.uniform4f(location._ | 0, v0, v1, v2, v3) + } + + uniform4fv (location, value) { + if (!this._checkUniformValueValid(location, value, 'uniform4fv', 4, 'f')) return + if (location._array) { + const locs = location._array + for (let i = 0; i < locs.length && 4 * i < value.length; ++i) { + const loc = locs[i] + super.uniform4f(loc, value[4 * i], value[4 * i + 1], value[4 * i + 2], value[4 * i + 3]) + } + return + } + super.uniform4f(location._ | 0, value[0], value[1], value[2], value[3]) + } + + uniform4i (location, v0, v1, v2, v3) { + if (!this._checkUniformValid(location, v0, 'uniform4i', 4, 'i')) return + super.uniform4i(location._ | 0, v0, v1, v2, v3) + } + + uniform4iv (location, value) { + if (!this._checkUniformValueValid(location, value, 'uniform4iv', 4, 'i')) return + if (location._array) { + const locs = location._array + for (let i = 0; i < locs.length && 4 * i < value.length; ++i) { + const loc = locs[i] + super.uniform4i(loc, value[4 * i], value[4 * i + 1], value[4 * i + 2], value[4 * i + 3]) + } + return + } + this.uniform4i(location, value[0], value[1], value[2], value[3]) + } + + _checkUniformMatrix (location, transpose, value, name, count) { + if (!checkObject(location) || + typeof value !== 'object') { + throw new TypeError(name + '(WebGLUniformLocation, Boolean, Array)') + } else if (!!transpose || + typeof value !== 'object' || + value === null || + !value.length || + value.length % count * count !== 0) { + this.setError(gl.INVALID_VALUE) + return false + } + if (!location) { + return false + } + if (!this._checkLocationActive(location)) { + return false + } + + if (value.length === count * count) { + return true + } else if (location._array) { + return true + } + this.setError(gl.INVALID_VALUE) + return false + } + + uniformMatrix2fv (location, transpose, value) { + if (!this._checkUniformMatrix(location, transpose, value, 'uniformMatrix2fv', 2)) return + const data = new Float32Array(value) + super.uniformMatrix2fv( + location._ | 0, + !!transpose, + data) + } + + uniformMatrix3fv (location, transpose, value) { + if (!this._checkUniformMatrix(location, transpose, value, 'uniformMatrix3fv', 3)) return + const data = new Float32Array(value) + super.uniformMatrix3fv( + location._ | 0, + !!transpose, + data) + } + + uniformMatrix4fv (location, transpose, value) { + if (!this._checkUniformMatrix(location, transpose, value, 'uniformMatrix4fv', 4)) return + const data = new Float32Array(value) + super.uniformMatrix4fv( + location._ | 0, + !!transpose, + data) + } + + vertexAttrib1f (index, v0) { + index |= 0 + if (!this._checkVertexIndex(index)) return + const data = this._vertexGlobalState._attribs[index]._data + data[3] = 1 + data[1] = data[2] = 0 + data[0] = v0 + return super.vertexAttrib1f(index | 0, +v0) + } + + vertexAttrib2f (index, v0, v1) { + index |= 0 + if (!this._checkVertexIndex(index)) return + const data = this._vertexGlobalState._attribs[index]._data + data[3] = 1 + data[2] = 0 + data[1] = v1 + data[0] = v0 + return super.vertexAttrib2f(index | 0, +v0, +v1) + } + + vertexAttrib3f (index, v0, v1, v2) { + index |= 0 + if (!this._checkVertexIndex(index)) return + const data = this._vertexGlobalState._attribs[index]._data + data[3] = 1 + data[2] = v2 + data[1] = v1 + data[0] = v0 + return super.vertexAttrib3f(index | 0, +v0, +v1, +v2) + } + + vertexAttrib4f (index, v0, v1, v2, v3) { + index |= 0 + if (!this._checkVertexIndex(index)) return + const data = this._vertexGlobalState._attribs[index]._data + data[3] = v3 + data[2] = v2 + data[1] = v1 + data[0] = v0 + return super.vertexAttrib4f(index | 0, +v0, +v1, +v2, +v3) + } + + vertexAttrib1fv (index, value) { + if (typeof value !== 'object' || value === null || value.length < 1) { + this.setError(gl.INVALID_OPERATION) + return + } + const data = this._vertexGlobalState._attribs[index]._data + data[3] = 1 + data[2] = 0 + data[1] = 0 + data[0] = value[0] + return super.vertexAttrib1f(index | 0, +value[0]) + } + + vertexAttrib2fv (index, value) { + if (typeof value !== 'object' || value === null || value.length < 2) { + this.setError(gl.INVALID_OPERATION) + return + } + const data = this._vertexGlobalState._attribs[index]._data + data[3] = 1 + data[2] = 0 + data[1] = value[1] + data[0] = value[0] + return super.vertexAttrib2f(index | 0, +value[0], +value[1]) + } + + vertexAttrib3fv (index, value) { + if (typeof value !== 'object' || value === null || value.length < 3) { + this.setError(gl.INVALID_OPERATION) + return + } + const data = this._vertexGlobalState._attribs[index]._data + data[3] = 1 + data[2] = value[2] + data[1] = value[1] + data[0] = value[0] + return super.vertexAttrib3f(index | 0, +value[0], +value[1], +value[2]) + } + + vertexAttrib4fv (index, value) { + if (typeof value !== 'object' || value === null || value.length < 4) { + this.setError(gl.INVALID_OPERATION) + return + } + const data = this._vertexGlobalState._attribs[index]._data + data[3] = value[3] + data[2] = value[2] + data[1] = value[1] + data[0] = value[0] + return super.vertexAttrib4f(index | 0, +value[0], +value[1], +value[2], +value[3]) + } +} + +module.exports = { WebGLRenderingContext, wrapContext } + +},{"../../package.json":137,"./extensions/angle-instanced-arrays":139,"./extensions/ext-blend-minmax":140,"./extensions/ext-texture-filter-anisotropic":141,"./extensions/oes-element-index-unit":142,"./extensions/oes-standard-derivatives":143,"./extensions/oes-texture-float":145,"./extensions/oes-texture-float-linear":144,"./extensions/oes-vertex-array-object":146,"./extensions/stackgl-destroy-context":147,"./extensions/stackgl-resize-drawing-buffer":148,"./extensions/webgl-draw-buffers":149,"./native-gl":151,"./utils":153,"./webgl-active-info":154,"./webgl-buffer":155,"./webgl-drawing-buffer-wrapper":157,"./webgl-framebuffer":158,"./webgl-program":159,"./webgl-renderbuffer":160,"./webgl-shader":163,"./webgl-shader-precision-format":162,"./webgl-texture":165,"./webgl-uniform-location":166,"bit-twiddle":32,"glsl-tokenizer/string":182}],162:[function(require,module,exports){ +class WebGLShaderPrecisionFormat { + constructor (_) { + this.rangeMin = _.rangeMin + this.rangeMax = _.rangeMax + this.precision = _.precision + } +} + +module.exports = { WebGLShaderPrecisionFormat } + +},{}],163:[function(require,module,exports){ +const { gl } = require('./native-gl') +const { Linkable } = require('./linkable') + +class WebGLShader extends Linkable { + constructor (_, ctx, type) { + super(_) + this._type = type + this._ctx = ctx + this._source = '' + this._compileStatus = false + this._compileInfo = '' + } + + _performDelete () { + const ctx = this._ctx + delete ctx._shaders[this._ | 0] + gl.deleteShader.call(ctx, this._ | 0) + } +} + +module.exports = { WebGLShader } + +},{"./linkable":150,"./native-gl":151}],164:[function(require,module,exports){ +class WebGLTextureUnit { + constructor (ctx, idx) { + this._ctx = ctx + this._idx = idx + this._mode = 0 + this._bind2D = null + this._bindCube = null + } +} + +module.exports = { WebGLTextureUnit } + +},{}],165:[function(require,module,exports){ +const { Linkable } = require('./linkable') +const { gl } = require('./native-gl') + +class WebGLTexture extends Linkable { + constructor (_, ctx) { + super(_) + this._ctx = ctx + this._binding = 0 + this._levelWidth = new Int32Array(32) + this._levelHeight = new Int32Array(32) + this._format = 0 + this._type = 0 + this._complete = true + } + + _performDelete () { + const ctx = this._ctx + delete ctx._textures[this._ | 0] + gl.deleteTexture.call(ctx, this._ | 0) + } +} + +module.exports = { WebGLTexture } + +},{"./linkable":150,"./native-gl":151}],166:[function(require,module,exports){ +class WebGLUniformLocation { + constructor (_, program, info) { + this._ = _ + this._program = program + this._linkCount = program._linkCount + this._activeInfo = info + this._array = null + } +} + +module.exports = { WebGLUniformLocation } + +},{}],167:[function(require,module,exports){ +const { gl } = require('./native-gl') +const { WebGLBuffer } = require('./webgl-buffer') + +class WebGLVertexArrayObjectAttribute { + constructor (ctx, idx) { + this._ctx = ctx + this._idx = idx + this._clear() + } + + _clear () { + this._isPointer = false + this._pointerBuffer = null + this._pointerOffset = 0 + this._pointerSize = 0 + this._pointerStride = 0 + this._pointerType = gl.FLOAT + this._pointerNormal = false + this._divisor = 0 + this._inputSize = 4 + this._inputStride = 0 + } +} + +class WebGLVertexArrayGlobalAttribute { + constructor (idx) { + this._idx = idx + this._data = new Float32Array([0, 0, 0, 1]) + } +} + +class WebGLVertexArrayObjectState { + constructor (ctx) { + const numAttribs = ctx.getParameter(ctx.MAX_VERTEX_ATTRIBS) + this._attribs = new Array(numAttribs) + for (let i = 0; i < numAttribs; ++i) { + this._attribs[i] = new WebGLVertexArrayObjectAttribute(ctx, i) + } + this._elementArrayBufferBinding = null + } + + setElementArrayBuffer (buffer) { + if (buffer !== null && !(buffer instanceof WebGLBuffer)) { + throw new TypeError('setElementArrayBuffer(WebGLBuffer?)') + } + const current = this._elementArrayBufferBinding + if (current !== buffer) { + if (current) { + current._refCount -= 1 + current._checkDelete() + } + if (buffer) { + buffer._refCount += 1 + } + this._elementArrayBufferBinding = buffer + } + } + + cleanUp () { + const elementArrayBuffer = this._elementArrayBufferBinding + if (elementArrayBuffer) { + elementArrayBuffer._refCount -= 1 + elementArrayBuffer._checkDelete() + this._elementArrayBufferBinding = null + } + + for (let i = 0; i < this._attribs.length; ++i) { + const attrib = this._attribs[i] + if (attrib._pointerBuffer) { + attrib._pointerBuffer._refCount -= 1 + attrib._pointerBuffer._checkDelete() + } + attrib._clear() + } + } + + releaseArrayBuffer (buffer) { + if (!buffer) { + return + } + for (let i = 0; i < this._attribs.length; ++i) { + const attrib = this._attribs[i] + if (attrib._pointerBuffer === buffer) { + attrib._pointerBuffer._refCount -= 1 + attrib._pointerBuffer._checkDelete() + attrib._clear() + } + } + } + + setVertexAttribPointer ( + buffer, + index, + pointerSize, + pointerOffset, + pointerStride, + pointerType, + pointerNormal, + inputStride, + inputSize) { + const attrib = this._attribs[index] + if (buffer !== attrib._pointerBuffer) { + if (attrib._pointerBuffer) { + attrib._pointerBuffer._refCount -= 1 + attrib._pointerBuffer._checkDelete() + } + if (buffer) { + buffer._refCount += 1 + } + attrib._pointerBuffer = buffer + } + attrib._pointerSize = pointerSize + attrib._pointerOffset = pointerOffset + attrib._pointerStride = pointerStride + attrib._pointerType = pointerType + attrib._pointerNormal = pointerNormal + attrib._inputStride = inputStride + attrib._inputSize = inputSize + } +} + +class WebGLVertexArrayGlobalState { + constructor (ctx) { + const numAttribs = ctx.getParameter(ctx.MAX_VERTEX_ATTRIBS) + this._attribs = new Array(numAttribs) + for (let i = 0; i < numAttribs; ++i) { + this._attribs[i] = new WebGLVertexArrayGlobalAttribute(i) + } + this._arrayBufferBinding = null + } + + setArrayBuffer (buffer) { + if (buffer !== null && !(buffer instanceof WebGLBuffer)) { + throw new TypeError('setArrayBuffer(WebGLBuffer?)') + } + const current = this._arrayBufferBinding + if (current !== buffer) { + if (current) { + current._refCount -= 1 + current._checkDelete() + } + if (buffer) { + buffer._refCount += 1 + } + this._arrayBufferBinding = buffer + } + } +} + +module.exports = { + WebGLVertexArrayObjectAttribute, + WebGLVertexArrayGlobalAttribute, + WebGLVertexArrayObjectState, + WebGLVertexArrayGlobalState +} + +},{"./native-gl":151,"./webgl-buffer":155}],168:[function(require,module,exports){ +/* + * glfx.js + * http://evanw.github.com/glfx.js/ + * + * Copyright 2011 Evan Wallace + * Released under the MIT license + */ +var fx=function(){function q(a,d,c){return Math.max(a,Math.min(d,c))}function w(b){return{_:b,loadContentsOf:function(b){a=this._.gl;this._.loadContentsOf(b)},destroy:function(){a=this._.gl;this._.destroy()}}}function A(a){return w(r.fromElement(a))}function B(b,d){var c=a.UNSIGNED_BYTE;if(a.getExtension("OES_texture_float")&&a.getExtension("OES_texture_float_linear")){var e=new r(100,100,a.RGBA,a.FLOAT);try{e.drawTo(function(){c=a.FLOAT})}catch(g){}e.destroy()}this._.texture&&this._.texture.destroy(); +this._.spareTexture&&this._.spareTexture.destroy();this.width=b;this.height=d;this._.texture=new r(b,d,a.RGBA,c);this._.spareTexture=new r(b,d,a.RGBA,c);this._.extraTexture=this._.extraTexture||new r(0,0,a.RGBA,c);this._.flippedShader=this._.flippedShader||new h(null,"uniform sampler2D texture;varying vec2 texCoord;void main(){gl_FragColor=texture2D(texture,vec2(texCoord.x,1.0-texCoord.y));}");this._.isInitialized=!0}function C(a,d,c){if(!this._.isInitialized|| +a._.width!=this.width||a._.height!=this.height)B.call(this,d?d:a._.width,c?c:a._.height);a._.use();this._.texture.drawTo(function(){h.getDefaultShader().drawRect()});return this}function D(){this._.texture.use();this._.flippedShader.drawRect();return this}function f(a,d,c,e){(c||this._.texture).use();this._.spareTexture.drawTo(function(){a.uniforms(d).drawRect()});this._.spareTexture.swapWith(e||this._.texture)}function E(a){a.parentNode.insertBefore(this,a);a.parentNode.removeChild(a);return this} +function F(){var b=new r(this._.texture.width,this._.texture.height,a.RGBA,a.UNSIGNED_BYTE);this._.texture.use();b.drawTo(function(){h.getDefaultShader().drawRect()});return w(b)}function G(){var b=this._.texture.width,d=this._.texture.height,c=new Uint8Array(4*b*d);this._.texture.drawTo(function(){a.readPixels(0,0,b,d,a.RGBA,a.UNSIGNED_BYTE,c)});return c}function k(b){return function(){a=this._.gl;return b.apply(this,arguments)}}function x(a,d,c,e,g,n,l,p){var m=c-g,h=e-n,f=l-g,k=p-n;g=a-c+g-l;n= +d-e+n-p;var q=m*k-f*h,f=(g*k-f*n)/q,m=(m*n-g*h)/q;return[c-a+f*c,e-d+f*e,f,l-a+m*l,p-d+m*p,m,a,d,1]}function y(a){var d=a[0],c=a[1],e=a[2],g=a[3],n=a[4],l=a[5],p=a[6],m=a[7];a=a[8];var f=d*n*a-d*l*m-c*g*a+c*l*p+e*g*m-e*n*p;return[(n*a-l*m)/f,(e*m-c*a)/f,(c*l-e*n)/f,(l*p-g*a)/f,(d*a-e*p)/f,(e*g-d*l)/f,(g*m-n*p)/f,(c*p-d*m)/f,(d*n-c*g)/f]}function z(a){var d=a.length;this.xa=[];this.ya=[];this.u=[];this.y2=[];a.sort(function(a,b){return a[0]-b[0]});for(var c=0;cd;d++)f.call(this,a.denoise,{exponent:Math.max(0,b),texSize:[this.width,this.height]});return this}function L(b,d){a.brightnessContrast=a.brightnessContrast||new h(null,"uniform sampler2D texture;uniform float brightness;uniform float contrast;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);color.rgb+=brightness;if(contrast>0.0){color.rgb=(color.rgb-0.5)/(1.0-contrast)+0.5;}else{color.rgb=(color.rgb-0.5)*(1.0+contrast)+0.5;}gl_FragColor=color;}"); +f.call(this,a.brightnessContrast,{brightness:q(-1,b,1),contrast:q(-1,d,1)});return this}function t(a){a=new z(a);for(var d=[],c=0;256>c;c++)d.push(q(0,Math.floor(256*a.interpolate(c/255)),255));return d}function M(b,d,c){b=t(b);1==arguments.length?d=c=b:(d=t(d),c=t(c));for(var e=[],g=0;256>g;g++)e.splice(e.length,0,b[g],d[g],c[g],255);this._.extraTexture.initFromBytes(256,1,e);this._.extraTexture.use(1);a.curves=a.curves||new h(null,"uniform sampler2D texture;uniform sampler2D map;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);color.r=texture2D(map,vec2(color.r)).r;color.g=texture2D(map,vec2(color.g)).g;color.b=texture2D(map,vec2(color.b)).b;gl_FragColor=color;}"); +a.curves.textures({map:1});f.call(this,a.curves,{});return this}function N(b,d){a.unsharpMask=a.unsharpMask||new h(null,"uniform sampler2D blurredTexture;uniform sampler2D originalTexture;uniform float strength;uniform float threshold;varying vec2 texCoord;void main(){vec4 blurred=texture2D(blurredTexture,texCoord);vec4 original=texture2D(originalTexture,texCoord);gl_FragColor=mix(blurred,original,1.0+strength);}"); +this._.extraTexture.ensureFormat(this._.texture);this._.texture.use();this._.extraTexture.drawTo(function(){h.getDefaultShader().drawRect()});this._.extraTexture.use(1);this.triangleBlur(b);a.unsharpMask.textures({originalTexture:1});f.call(this,a.unsharpMask,{strength:d});this._.extraTexture.unuse(1);return this}function O(b){a.sepia=a.sepia||new h(null,"uniform sampler2D texture;uniform float amount;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);float r=color.r;float g=color.g;float b=color.b;color.r=min(1.0,(r*(1.0-(0.607*amount)))+(g*(0.769*amount))+(b*(0.189*amount)));color.g=min(1.0,(r*0.349*amount)+(g*(1.0-(0.314*amount)))+(b*0.168*amount));color.b=min(1.0,(r*0.272*amount)+(g*0.534*amount)+(b*(1.0-(0.869*amount))));gl_FragColor=color;}"); +f.call(this,a.sepia,{amount:q(0,b,1)});return this}function P(b,d){a.hueSaturation=a.hueSaturation||new h(null,"uniform sampler2D texture;uniform float hue;uniform float saturation;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);float angle=hue*3.14159265;float s=sin(angle),c=cos(angle);vec3 weights=(vec3(2.0*c,-sqrt(3.0)*s-c,sqrt(3.0)*s-c)+1.0)/3.0;float len=length(color.rgb);color.rgb=vec3(dot(color.rgb,weights.xyz),dot(color.rgb,weights.zxy),dot(color.rgb,weights.yzx));float average=(color.r+color.g+color.b)/3.0;if(saturation>0.0){color.rgb+=(average-color.rgb)*(1.0-1.0/(1.001-saturation));}else{color.rgb+=(average-color.rgb)*(-saturation);}gl_FragColor=color;}"); +f.call(this,a.hueSaturation,{hue:q(-1,b,1),saturation:q(-1,d,1)});return this}function Q(b,d,c){a.zoomBlur=a.zoomBlur||new h(null,"uniform sampler2D texture;uniform vec2 center;uniform float strength;uniform vec2 texSize;varying vec2 texCoord;"+s+"void main(){vec4 color=vec4(0.0);float total=0.0;vec2 toCenter=center-texCoord*texSize;float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=0.0;t<=40.0;t++){float percent=(t+offset)/40.0;float weight=4.0*(percent-percent*percent);vec4 sample=texture2D(texture,texCoord+toCenter*percent*strength/texSize);sample.rgb*=sample.a;color+=sample*weight;total+=weight;}gl_FragColor=color/total;gl_FragColor.rgb/=gl_FragColor.a+0.00001;}"); +f.call(this,a.zoomBlur,{center:[b,d],strength:c,texSize:[this.width,this.height]});return this}function R(b,d,c,e,g,n){a.tiltShift=a.tiltShift||new h(null,"uniform sampler2D texture;uniform float blurRadius;uniform float gradientRadius;uniform vec2 start;uniform vec2 end;uniform vec2 delta;uniform vec2 texSize;varying vec2 texCoord;"+s+"void main(){vec4 color=vec4(0.0);float total=0.0;float offset=random(vec3(12.9898,78.233,151.7182),0.0);vec2 normal=normalize(vec2(start.y-end.y,end.x-start.x));float radius=smoothstep(0.0,1.0,abs(dot(texCoord*texSize-start,normal))/gradientRadius)*blurRadius;for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec4 sample=texture2D(texture,texCoord+delta/texSize*percent*radius);sample.rgb*=sample.a;color+=sample*weight;total+=weight;}gl_FragColor=color/total;gl_FragColor.rgb/=gl_FragColor.a+0.00001;}"); +var l=c-b,p=e-d,m=Math.sqrt(l*l+p*p);f.call(this,a.tiltShift,{blurRadius:g,gradientRadius:n,start:[b,d],end:[c,e],delta:[l/m,p/m],texSize:[this.width,this.height]});f.call(this,a.tiltShift,{blurRadius:g,gradientRadius:n,start:[b,d],end:[c,e],delta:[-p/m,l/m],texSize:[this.width,this.height]});return this}function S(b,d,c){a.lensBlurPrePass=a.lensBlurPrePass||new h(null,"uniform sampler2D texture;uniform float power;varying vec2 texCoord;void main(){vec4 color=texture2D(texture,texCoord);color=pow(color,vec4(power));gl_FragColor=vec4(color);}"); +var e="uniform sampler2D texture0;uniform sampler2D texture1;uniform vec2 delta0;uniform vec2 delta1;uniform float power;varying vec2 texCoord;"+s+"vec4 sample(vec2 delta){float offset=random(vec3(delta,151.7182),0.0);vec4 color=vec4(0.0);float total=0.0;for(float t=0.0;t<=30.0;t++){float percent=(t+offset)/30.0;color+=texture2D(texture0,texCoord+delta*percent);total+=1.0;}return color/total;}"; +a.lensBlur0=a.lensBlur0||new h(null,e+"void main(){gl_FragColor=sample(delta0);}");a.lensBlur1=a.lensBlur1||new h(null,e+"void main(){gl_FragColor=(sample(delta0)+sample(delta1))*0.5;}");a.lensBlur2=a.lensBlur2||(new h(null,e+"void main(){vec4 color=(sample(delta0)+2.0*texture2D(texture1,texCoord))/3.0;gl_FragColor=pow(color,vec4(power));}")).textures({texture1:1});for(var e= +[],g=0;3>g;g++){var n=c+2*g*Math.PI/3;e.push([b*Math.sin(n)/this.width,b*Math.cos(n)/this.height])}b=Math.pow(10,q(-1,d,1));f.call(this,a.lensBlurPrePass,{power:b});this._.extraTexture.ensureFormat(this._.texture);f.call(this,a.lensBlur0,{delta0:e[0]},this._.texture,this._.extraTexture);f.call(this,a.lensBlur1,{delta0:e[1],delta1:e[2]},this._.extraTexture,this._.extraTexture);f.call(this,a.lensBlur0,{delta0:e[1]});this._.extraTexture.use(1);f.call(this,a.lensBlur2,{power:1/b,delta0:e[2]});return this} +function T(b){a.triangleBlur=a.triangleBlur||new h(null,"uniform sampler2D texture;uniform vec2 delta;varying vec2 texCoord;"+s+"void main(){vec4 color=vec4(0.0);float total=0.0;float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec4 sample=texture2D(texture,texCoord+delta*percent);sample.rgb*=sample.a;color+=sample*weight;total+=weight;}gl_FragColor=color/total;gl_FragColor.rgb/=gl_FragColor.a+0.00001;}"); +f.call(this,a.triangleBlur,{delta:[b/this.width,0]});f.call(this,a.triangleBlur,{delta:[0,b/this.height]});return this}function U(b){a.edgeWork1=a.edgeWork1||new h(null,"uniform sampler2D texture;uniform vec2 delta;varying vec2 texCoord;"+s+"void main(){vec2 color=vec2(0.0);vec2 total=vec2(0.0);float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec3 sample=texture2D(texture,texCoord+delta*percent).rgb;float average=(sample.r+sample.g+sample.b)/3.0;color.x+=average*weight;total.x+=weight;if(abs(t)<15.0){weight=weight*2.0-1.0;color.y+=average*weight;total.y+=weight;}}gl_FragColor=vec4(color/total,0.0,1.0);}"); +a.edgeWork2=a.edgeWork2||new h(null,"uniform sampler2D texture;uniform vec2 delta;varying vec2 texCoord;"+s+"void main(){vec2 color=vec2(0.0);vec2 total=vec2(0.0);float offset=random(vec3(12.9898,78.233,151.7182),0.0);for(float t=-30.0;t<=30.0;t++){float percent=(t+offset-0.5)/30.0;float weight=1.0-abs(percent);vec2 sample=texture2D(texture,texCoord+delta*percent).xy;color.x+=sample.x*weight;total.x+=weight;if(abs(t)<15.0){weight=weight*2.0-1.0;color.y+=sample.y*weight;total.y+=weight;}}float c=clamp(10000.0*(color.y/total.y-color.x/total.x)+0.5,0.0,1.0);gl_FragColor=vec4(c,c,c,1.0);}"); +f.call(this,a.edgeWork1,{delta:[b/this.width,0]});f.call(this,a.edgeWork2,{delta:[0,b/this.height]});return this}function V(b,d,c){a.hexagonalPixelate=a.hexagonalPixelate||new h(null,"uniform sampler2D texture;uniform vec2 center;uniform float scale;uniform vec2 texSize;varying vec2 texCoord;void main(){vec2 tex=(texCoord*texSize-center)/scale;tex.y/=0.866025404;tex.x-=tex.y*0.5;vec2 a;if(tex.x+tex.y-floor(tex.x)-floor(tex.y)<1.0)a=vec2(floor(tex.x),floor(tex.y));else a=vec2(ceil(tex.x),ceil(tex.y));vec2 b=vec2(ceil(tex.x),floor(tex.y));vec2 c=vec2(floor(tex.x),ceil(tex.y));vec3 TEX=vec3(tex.x,tex.y,1.0-tex.x-tex.y);vec3 A=vec3(a.x,a.y,1.0-a.x-a.y);vec3 B=vec3(b.x,b.y,1.0-b.x-b.y);vec3 C=vec3(c.x,c.y,1.0-c.x-c.y);float alen=length(TEX-A);float blen=length(TEX-B);float clen=length(TEX-C);vec2 choice;if(alen0.0){coord*=mix(1.0,smoothstep(0.0,radius/distance,percent),strength*0.75);}else{coord*=mix(1.0,pow(percent,1.0+strength*0.75)*radius/distance,1.0-percent);}}coord+=center;"); +f.call(this,a.bulgePinch,{radius:c,strength:q(-1,e,1),center:[b,d],texSize:[this.width,this.height]});return this}function ba(a,d){var c=x.apply(null,d),e=x.apply(null,a),c=y(c);return this.matrixWarp([c[0]*e[0]+c[1]*e[3]+c[2]*e[6],c[0]*e[1]+c[1]*e[4]+c[2]*e[7],c[0]*e[2]+c[1]*e[5]+c[2]*e[8],c[3]*e[0]+c[4]*e[3]+c[5]*e[6],c[3]*e[1]+c[4]*e[4]+c[5]*e[7],c[3]*e[2]+c[4]*e[5]+c[5]*e[8],c[6]*e[0]+c[7]*e[3]+c[8]*e[6],c[6]*e[1]+c[7]*e[4]+c[8]*e[7],c[6]*e[2]+c[7]*e[5]+c[8]*e[8]])}var v={};(function(){function a(b){if(!b.getExtension("OES_texture_float"))return!1; +var c=b.createFramebuffer(),e=b.createTexture();b.bindTexture(b.TEXTURE_2D,e);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,1,1,0,b.RGBA,b.UNSIGNED_BYTE,null);b.bindFramebuffer(b.FRAMEBUFFER,c);b.framebufferTexture2D(b.FRAMEBUFFER,b.COLOR_ATTACHMENT0,b.TEXTURE_2D, +e,0);c=b.createTexture();b.bindTexture(b.TEXTURE_2D,c);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.LINEAR);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.LINEAR);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,2,2,0,b.RGBA,b.FLOAT,new Float32Array([2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]));var e=b.createProgram(),d=b.createShader(b.VERTEX_SHADER),g=b.createShader(b.FRAGMENT_SHADER); +b.shaderSource(d,"attribute vec2 vertex;void main(){gl_Position=vec4(vertex,0.0,1.0);}");b.shaderSource(g,"uniform sampler2D texture;void main(){gl_FragColor=texture2D(texture,vec2(0.5));}");b.compileShader(d);b.compileShader(g);b.attachShader(e,d);b.attachShader(e,g);b.linkProgram(e);d=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,d);b.bufferData(b.ARRAY_BUFFER,new Float32Array([0,0]),b.STREAM_DRAW);b.enableVertexAttribArray(0); +b.vertexAttribPointer(0,2,b.FLOAT,!1,0,0);d=new Uint8Array(4);b.useProgram(e);b.viewport(0,0,1,1);b.bindTexture(b.TEXTURE_2D,c);b.drawArrays(b.POINTS,0,1);b.readPixels(0,0,1,1,b.RGBA,b.UNSIGNED_BYTE,d);return 127===d[0]||128===d[0]}function d(){}function c(a){"OES_texture_float_linear"===a?(void 0===this.$OES_texture_float_linear$&&Object.defineProperty(this,"$OES_texture_float_linear$",{enumerable:!1,configurable:!1,writable:!1,value:new d}),a=this.$OES_texture_float_linear$):a=l.call(this,a);return a} +function e(){var a=f.call(this);-1===a.indexOf("OES_texture_float_linear")&&a.push("OES_texture_float_linear");return a}try{var g=document.createElement("canvas").getContext("experimental-webgl")}catch(n){}if(g&&-1===g.getSupportedExtensions().indexOf("OES_texture_float_linear")&&a(g)){var l=WebGLRenderingContext.prototype.getExtension,f=WebGLRenderingContext.prototype.getSupportedExtensions;WebGLRenderingContext.prototype.getExtension=c;WebGLRenderingContext.prototype.getSupportedExtensions=e}})(); +var a;v.canvas=function(){var b=document.createElement("canvas");try{a=b.getContext("experimental-webgl",{premultipliedAlpha:!1})}catch(d){a=null}if(!a)throw"This browser does not support WebGL";b._={gl:a,isInitialized:!1,texture:null,spareTexture:null,flippedShader:null};b.texture=k(A);b.draw=k(C);b.update=k(D);b.replace=k(E);b.contents=k(F);b.getPixelArray=k(G);b.brightnessContrast=k(L);b.hexagonalPixelate=k(V);b.hueSaturation=k(P);b.colorHalftone=k(W);b.triangleBlur=k(T);b.unsharpMask=k(N);b.perspective= +k(ba);b.matrixWarp=k(Z);b.bulgePinch=k(aa);b.tiltShift=k(R);b.dotScreen=k(Y);b.edgeWork=k(U);b.lensBlur=k(S);b.zoomBlur=k(Q);b.noise=k(H);b.denoise=k(K);b.curves=k(M);b.swirl=k($);b.ink=k(X);b.vignette=k(J);b.vibrance=k(I);b.sepia=k(O);return b};v.splineInterpolate=t;var r=function(){function b(b,c,d,l){this.gl=a;this.id=a.createTexture();this.width=b;this.height=c;this.format=d;this.type=l;a.bindTexture(a.TEXTURE_2D,this.id);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR);a.texParameteri(a.TEXTURE_2D, +a.TEXTURE_MIN_FILTER,a.LINEAR);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE);b&&c&&a.texImage2D(a.TEXTURE_2D,0,this.format,b,c,0,this.format,this.type,null)}function d(a){null==c&&(c=document.createElement("canvas"));c.width=a.width;c.height=a.height;a=c.getContext("2d");a.clearRect(0,0,c.width,c.height);return a}b.fromElement=function(c){var d=new b(0,0,a.RGBA,a.UNSIGNED_BYTE);d.loadContentsOf(c);return d};b.prototype.loadContentsOf= +function(b){this.width=b.width||b.videoWidth;this.height=b.height||b.videoHeight;a.bindTexture(a.TEXTURE_2D,this.id);a.texImage2D(a.TEXTURE_2D,0,this.format,this.format,this.type,b)};b.prototype.initFromBytes=function(b,c,d){this.width=b;this.height=c;this.format=a.RGBA;this.type=a.UNSIGNED_BYTE;a.bindTexture(a.TEXTURE_2D,this.id);a.texImage2D(a.TEXTURE_2D,0,a.RGBA,b,c,0,a.RGBA,this.type,new Uint8Array(d))};b.prototype.destroy=function(){a.deleteTexture(this.id);this.id=null};b.prototype.use=function(b){a.activeTexture(a.TEXTURE0+ +(b||0));a.bindTexture(a.TEXTURE_2D,this.id)};b.prototype.unuse=function(b){a.activeTexture(a.TEXTURE0+(b||0));a.bindTexture(a.TEXTURE_2D,null)};b.prototype.ensureFormat=function(b,c,d,l){if(1==arguments.length){var f=arguments[0];b=f.width;c=f.height;d=f.format;l=f.type}if(b!=this.width||c!=this.height||d!=this.format||l!=this.type)this.width=b,this.height=c,this.format=d,this.type=l,a.bindTexture(a.TEXTURE_2D,this.id),a.texImage2D(a.TEXTURE_2D,0,this.format,b,c,0,this.format,this.type,null)};b.prototype.drawTo= +function(b){a.framebuffer=a.framebuffer||a.createFramebuffer();a.bindFramebuffer(a.FRAMEBUFFER,a.framebuffer);a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.id,0);if(a.checkFramebufferStatus(a.FRAMEBUFFER)!==a.FRAMEBUFFER_COMPLETE)throw Error("incomplete framebuffer");a.viewport(0,0,this.width,this.height);b();a.bindFramebuffer(a.FRAMEBUFFER,null)};var c=null;b.prototype.fillUsingCanvas=function(b){b(d(this));this.format=a.RGBA;this.type=a.UNSIGNED_BYTE;a.bindTexture(a.TEXTURE_2D, +this.id);a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,c);return this};b.prototype.toImage=function(b){this.use();h.getDefaultShader().drawRect();var g=4*this.width*this.height,f=new Uint8Array(g),l=d(this),p=l.createImageData(this.width,this.height);a.readPixels(0,0,this.width,this.height,a.RGBA,a.UNSIGNED_BYTE,f);for(var m=0;m>1;this.xa[e]>a?c=e:d=e}var e=this.xa[c]-this.xa[d],g=(this.xa[c]-a)/e;a=(a-this.xa[d])/e;return g*this.ya[d]+a*this.ya[c]+((g*g*g-g)*this.y2[d]+(a*a*a-a)*this.y2[c])*e*e/6};var h=function(){function b(b,c){var d=a.createShader(b);a.shaderSource(d,c);a.compileShader(d);if(!a.getShaderParameter(d,a.COMPILE_STATUS))throw"compile error: "+ +a.getShaderInfoLog(d);return d}function d(d,f){this.texCoordAttribute=this.vertexAttribute=null;this.program=a.createProgram();d=d||c;f=f||e;f="precision highp float;"+f;a.attachShader(this.program,b(a.VERTEX_SHADER,d));a.attachShader(this.program,b(a.FRAGMENT_SHADER,f));a.linkProgram(this.program);if(!a.getProgramParameter(this.program,a.LINK_STATUS))throw"link error: "+a.getProgramInfoLog(this.program);}var c="attribute vec2 vertex;attribute vec2 _texCoord;varying vec2 texCoord;void main(){texCoord=_texCoord;gl_Position=vec4(vertex*2.0-1.0,0.0,1.0);}", +e="uniform sampler2D texture;varying vec2 texCoord;void main(){gl_FragColor=texture2D(texture,texCoord);}";d.prototype.destroy=function(){a.deleteProgram(this.program);this.program=null};d.prototype.uniforms=function(b){a.useProgram(this.program);for(var c in b)if(b.hasOwnProperty(c)){var d=a.getUniformLocation(this.program,c);if(null!==d){var e=b[c];if("[object Array]"==Object.prototype.toString.call(e))switch(e.length){case 1:a.uniform1fv(d,new Float32Array(e));break; +case 2:a.uniform2fv(d,new Float32Array(e));break;case 3:a.uniform3fv(d,new Float32Array(e));break;case 4:a.uniform4fv(d,new Float32Array(e));break;case 9:a.uniformMatrix3fv(d,!1,new Float32Array(e));break;case 16:a.uniformMatrix4fv(d,!1,new Float32Array(e));break;default:throw"dont't know how to load uniform \""+c+'" of length '+e.length;}else if("[object Number]"==Object.prototype.toString.call(e))a.uniform1f(d,e);else throw'attempted to set uniform "'+c+'" to invalid value '+(e||"undefined").toString(); +}}return this};d.prototype.textures=function(b){a.useProgram(this.program);for(var c in b)b.hasOwnProperty(c)&&a.uniform1i(a.getUniformLocation(this.program,c),b[c]);return this};d.prototype.drawRect=function(b,c,d,e){var f=a.getParameter(a.VIEWPORT);c=void 0!==c?(c-f[1])/f[3]:0;b=void 0!==b?(b-f[0])/f[2]:0;d=void 0!==d?(d-f[0])/f[2]:1;e=void 0!==e?(e-f[1])/f[3]:1;null==a.vertexBuffer&&(a.vertexBuffer=a.createBuffer());a.bindBuffer(a.ARRAY_BUFFER,a.vertexBuffer);a.bufferData(a.ARRAY_BUFFER,new Float32Array([b, +c,b,e,d,c,d,e]),a.STATIC_DRAW);null==a.texCoordBuffer&&(a.texCoordBuffer=a.createBuffer(),a.bindBuffer(a.ARRAY_BUFFER,a.texCoordBuffer),a.bufferData(a.ARRAY_BUFFER,new Float32Array([0,0,0,1,1,0,1,1]),a.STATIC_DRAW));null==this.vertexAttribute&&(this.vertexAttribute=a.getAttribLocation(this.program,"vertex"),a.enableVertexAttribArray(this.vertexAttribute));null==this.texCoordAttribute&&(this.texCoordAttribute=a.getAttribLocation(this.program,"_texCoord"),a.enableVertexAttribArray(this.texCoordAttribute)); +a.useProgram(this.program);a.bindBuffer(a.ARRAY_BUFFER,a.vertexBuffer);a.vertexAttribPointer(this.vertexAttribute,2,a.FLOAT,!1,0,0);a.bindBuffer(a.ARRAY_BUFFER,a.texCoordBuffer);a.vertexAttribPointer(this.texCoordAttribute,2,a.FLOAT,!1,0,0);a.drawArrays(a.TRIANGLE_STRIP,0,4)};d.getDefaultShader=function(){a.defaultShader=a.defaultShader||new d;return a.defaultShader};return d}(),s="float random(vec3 scale,float seed){return fract(sin(dot(gl_FragCoord.xyz+seed,scale))*43758.5453+seed);}"; +return v}();"object"===typeof module?module.exports=fx:window.fx=fx; + +},{}],169:[function(require,module,exports){ +(function (process){ +'use strict'; +const {promisify} = require('util'); +const fs = require('fs'); +const path = require('path'); +const fastGlob = require('fast-glob'); +const gitIgnore = require('ignore'); +const slash = require('slash'); + +const DEFAULT_IGNORE = [ + '**/node_modules/**', + '**/flow-typed/**', + '**/coverage/**', + '**/.git' +]; + +const readFileP = promisify(fs.readFile); + +const mapGitIgnorePatternTo = base => ignore => { + if (ignore.startsWith('!')) { + return '!' + path.posix.join(base, ignore.slice(1)); + } + + return path.posix.join(base, ignore); +}; + +const parseGitIgnore = (content, options) => { + const base = slash(path.relative(options.cwd, path.dirname(options.fileName))); + + return content + .split(/\r?\n/) + .filter(Boolean) + .filter(line => !line.startsWith('#')) + .map(mapGitIgnorePatternTo(base)); +}; + +const reduceIgnore = files => { + return files.reduce((ignores, file) => { + ignores.add(parseGitIgnore(file.content, { + cwd: file.cwd, + fileName: file.filePath + })); + return ignores; + }, gitIgnore()); +}; + +const ensureAbsolutePathForCwd = (cwd, p) => { + if (path.isAbsolute(p)) { + if (p.startsWith(cwd)) { + return p; + } + + throw new Error(`Path ${p} is not in cwd ${cwd}`); + } + + return path.join(cwd, p); +}; + +const getIsIgnoredPredecate = (ignores, cwd) => { + return p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, p)))); +}; + +const getFile = async (file, cwd) => { + const filePath = path.join(cwd, file); + const content = await readFileP(filePath, 'utf8'); + + return { + cwd, + filePath, + content + }; +}; + +const getFileSync = (file, cwd) => { + const filePath = path.join(cwd, file); + const content = fs.readFileSync(filePath, 'utf8'); + + return { + cwd, + filePath, + content + }; +}; + +const normalizeOptions = ({ + ignore = [], + cwd = process.cwd() +} = {}) => { + return {ignore, cwd}; +}; + +module.exports = async options => { + options = normalizeOptions(options); + + const paths = await fastGlob('**/.gitignore', { + ignore: DEFAULT_IGNORE.concat(options.ignore), + cwd: options.cwd + }); + + const files = await Promise.all(paths.map(file => getFile(file, options.cwd))); + const ignores = reduceIgnore(files); + + return getIsIgnoredPredecate(ignores, options.cwd); +}; + +module.exports.sync = options => { + options = normalizeOptions(options); + + const paths = fastGlob.sync('**/.gitignore', { + ignore: DEFAULT_IGNORE.concat(options.ignore), + cwd: options.cwd + }); + + const files = paths.map(file => getFileSync(file, options.cwd)); + const ignores = reduceIgnore(files); + + return getIsIgnoredPredecate(ignores, options.cwd); +}; + +}).call(this,require('_process')) +},{"_process":437,"fast-glob":85,"fs":298,"ignore":174,"path":404,"slash":501,"util":523}],170:[function(require,module,exports){ +'use strict'; +const fs = require('fs'); +const arrayUnion = require('array-union'); +const merge2 = require('merge2'); +const glob = require('glob'); +const fastGlob = require('fast-glob'); +const dirGlob = require('dir-glob'); +const gitignore = require('./gitignore'); +const {FilterStream, UniqueStream} = require('./stream-utils'); + +const DEFAULT_FILTER = () => false; + +const isNegative = pattern => pattern[0] === '!'; + +const assertPatternsInput = patterns => { + if (!patterns.every(pattern => typeof pattern === 'string')) { + throw new TypeError('Patterns must be a string or an array of strings'); + } +}; + +const checkCwdOption = (options = {}) => { + if (!options.cwd) { + return; + } + + let stat; + try { + stat = fs.statSync(options.cwd); + } catch (_) { + return; + } + + if (!stat.isDirectory()) { + throw new Error('The `cwd` option must be a path to a directory'); + } +}; + +const getPathString = p => p.stats instanceof fs.Stats ? p.path : p; + +const generateGlobTasks = (patterns, taskOptions) => { + patterns = arrayUnion([].concat(patterns)); + assertPatternsInput(patterns); + checkCwdOption(taskOptions); + + const globTasks = []; + + taskOptions = { + ignore: [], + expandDirectories: true, + ...taskOptions + }; + + for (const [index, pattern] of patterns.entries()) { + if (isNegative(pattern)) { + continue; + } + + const ignore = patterns + .slice(index) + .filter(isNegative) + .map(pattern => pattern.slice(1)); + + const options = { + ...taskOptions, + ignore: taskOptions.ignore.concat(ignore) + }; + + globTasks.push({pattern, options}); + } + + return globTasks; +}; + +const globDirs = (task, fn) => { + let options = {}; + if (task.options.cwd) { + options.cwd = task.options.cwd; + } + + if (Array.isArray(task.options.expandDirectories)) { + options = { + ...options, + files: task.options.expandDirectories + }; + } else if (typeof task.options.expandDirectories === 'object') { + options = { + ...options, + ...task.options.expandDirectories + }; + } + + return fn(task.pattern, options); +}; + +const getPattern = (task, fn) => task.options.expandDirectories ? globDirs(task, fn) : [task.pattern]; + +const getFilterSync = options => { + return options && options.gitignore ? + gitignore.sync({cwd: options.cwd, ignore: options.ignore}) : + DEFAULT_FILTER; +}; + +const globToTask = task => glob => { + const {options} = task; + if (options.ignore && Array.isArray(options.ignore) && options.expandDirectories) { + options.ignore = dirGlob.sync(options.ignore); + } + + return { + pattern: glob, + options + }; +}; + +module.exports = async (patterns, options) => { + const globTasks = generateGlobTasks(patterns, options); + + const getFilter = async () => { + return options && options.gitignore ? + gitignore({cwd: options.cwd, ignore: options.ignore}) : + DEFAULT_FILTER; + }; + + const getTasks = async () => { + const tasks = await Promise.all(globTasks.map(async task => { + const globs = await getPattern(task, dirGlob); + return Promise.all(globs.map(globToTask(task))); + })); + + return arrayUnion(...tasks); + }; + + const [filter, tasks] = await Promise.all([getFilter(), getTasks()]); + const paths = await Promise.all(tasks.map(task => fastGlob(task.pattern, task.options))); + + return arrayUnion(...paths).filter(path_ => !filter(getPathString(path_))); +}; + +module.exports.sync = (patterns, options) => { + const globTasks = generateGlobTasks(patterns, options); + + const tasks = globTasks.reduce((tasks, task) => { + const newTask = getPattern(task, dirGlob.sync).map(globToTask(task)); + return tasks.concat(newTask); + }, []); + + const filter = getFilterSync(options); + + return tasks.reduce( + (matches, task) => arrayUnion(matches, fastGlob.sync(task.pattern, task.options)), + [] + ).filter(path_ => !filter(path_)); +}; + +module.exports.stream = (patterns, options) => { + const globTasks = generateGlobTasks(patterns, options); + + const tasks = globTasks.reduce((tasks, task) => { + const newTask = getPattern(task, dirGlob.sync).map(globToTask(task)); + return tasks.concat(newTask); + }, []); + + const filter = getFilterSync(options); + const filterStream = new FilterStream(p => !filter(p)); + const uniqueStream = new UniqueStream(); + + return merge2(tasks.map(task => fastGlob.stream(task.pattern, task.options))) + .pipe(filterStream) + .pipe(uniqueStream); +}; + +module.exports.generateGlobTasks = generateGlobTasks; + +module.exports.hasMagic = (patterns, options) => [] + .concat(patterns) + .some(pattern => glob.hasMagic(pattern, options)); + +module.exports.gitignore = gitignore; + +},{"./gitignore":169,"./stream-utils":175,"array-union":25,"dir-glob":53,"fast-glob":85,"fs":298,"glob":172,"merge2":381}],171:[function(require,module,exports){ +(function (process){ +exports.alphasort = alphasort +exports.alphasorti = alphasorti +exports.setopts = setopts +exports.ownProp = ownProp +exports.makeAbs = makeAbs +exports.finish = finish +exports.mark = mark +exports.isIgnored = isIgnored +exports.childrenIgnored = childrenIgnored + +function ownProp (obj, field) { + return Object.prototype.hasOwnProperty.call(obj, field) +} + +var path = require("path") +var minimatch = require("minimatch") +var isAbsolute = require("path-is-absolute") +var Minimatch = minimatch.Minimatch + +function alphasorti (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()) +} + +function alphasort (a, b) { + return a.localeCompare(b) +} + +function setupIgnores (self, options) { + self.ignore = options.ignore || [] + + if (!Array.isArray(self.ignore)) + self.ignore = [self.ignore] + + if (self.ignore.length) { + self.ignore = self.ignore.map(ignoreMap) + } +} + +// ignore patterns are always in dot:true mode. +function ignoreMap (pattern) { + var gmatcher = null + if (pattern.slice(-3) === '/**') { + var gpattern = pattern.replace(/(\/\*\*)+$/, '') + gmatcher = new Minimatch(gpattern, { dot: true }) + } + + return { + matcher: new Minimatch(pattern, { dot: true }), + gmatcher: gmatcher + } +} + +function setopts (self, pattern, options) { + if (!options) + options = {} + + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") + } + pattern = "**/" + pattern + } + + self.silent = !!options.silent + self.pattern = pattern + self.strict = options.strict !== false + self.realpath = !!options.realpath + self.realpathCache = options.realpathCache || Object.create(null) + self.follow = !!options.follow + self.dot = !!options.dot + self.mark = !!options.mark + self.nodir = !!options.nodir + if (self.nodir) + self.mark = true + self.sync = !!options.sync + self.nounique = !!options.nounique + self.nonull = !!options.nonull + self.nosort = !!options.nosort + self.nocase = !!options.nocase + self.stat = !!options.stat + self.noprocess = !!options.noprocess + self.absolute = !!options.absolute + + self.maxLength = options.maxLength || Infinity + self.cache = options.cache || Object.create(null) + self.statCache = options.statCache || Object.create(null) + self.symlinks = options.symlinks || Object.create(null) + + setupIgnores(self, options) + + self.changedCwd = false + var cwd = process.cwd() + if (!ownProp(options, "cwd")) + self.cwd = cwd + else { + self.cwd = path.resolve(options.cwd) + self.changedCwd = self.cwd !== cwd + } + + self.root = options.root || path.resolve(self.cwd, "/") + self.root = path.resolve(self.root) + if (process.platform === "win32") + self.root = self.root.replace(/\\/g, "/") + + // TODO: is an absolute `cwd` supposed to be resolved against `root`? + // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test') + self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd) + if (process.platform === "win32") + self.cwdAbs = self.cwdAbs.replace(/\\/g, "/") + self.nomount = !!options.nomount + + // disable comments and negation in Minimatch. + // Note that they are not supported in Glob itself anyway. + options.nonegate = true + options.nocomment = true + + self.minimatch = new Minimatch(pattern, options) + self.options = self.minimatch.options +} + +function finish (self) { + var nou = self.nounique + var all = nou ? [] : Object.create(null) + + for (var i = 0, l = self.matches.length; i < l; i ++) { + var matches = self.matches[i] + if (!matches || Object.keys(matches).length === 0) { + if (self.nonull) { + // do like the shell, and spit out the literal glob + var literal = self.minimatch.globSet[i] + if (nou) + all.push(literal) + else + all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) + all.push.apply(all, m) + else + m.forEach(function (m) { + all[m] = true + }) + } + } + + if (!nou) + all = Object.keys(all) + + if (!self.nosort) + all = all.sort(self.nocase ? alphasorti : alphasort) + + // at *some* point we statted all of these + if (self.mark) { + for (var i = 0; i < all.length; i++) { + all[i] = self._mark(all[i]) + } + if (self.nodir) { + all = all.filter(function (e) { + var notDir = !(/\/$/.test(e)) + var c = self.cache[e] || self.cache[makeAbs(self, e)] + if (notDir && c) + notDir = c !== 'DIR' && !Array.isArray(c) + return notDir + }) + } + } + + if (self.ignore.length) + all = all.filter(function(m) { + return !isIgnored(self, m) + }) + + self.found = all +} + +function mark (self, p) { + var abs = makeAbs(self, p) + var c = self.cache[abs] + var m = p + if (c) { + var isDir = c === 'DIR' || Array.isArray(c) + var slash = p.slice(-1) === '/' + + if (isDir && !slash) + m += '/' + else if (!isDir && slash) + m = m.slice(0, -1) + + if (m !== p) { + var mabs = makeAbs(self, m) + self.statCache[mabs] = self.statCache[abs] + self.cache[mabs] = self.cache[abs] + } + } + + return m +} + +// lotta situps... +function makeAbs (self, f) { + var abs = f + if (f.charAt(0) === '/') { + abs = path.join(self.root, f) + } else if (isAbsolute(f) || f === '') { + abs = f + } else if (self.changedCwd) { + abs = path.resolve(self.cwd, f) + } else { + abs = path.resolve(f) + } + + if (process.platform === 'win32') + abs = abs.replace(/\\/g, '/') + + return abs +} + + +// Return true, if pattern ends with globstar '**', for the accompanying parent directory. +// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents +function isIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) + }) +} + +function childrenIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return !!(item.gmatcher && item.gmatcher.match(path)) + }) +} + +}).call(this,require('_process')) +},{"_process":437,"minimatch":385,"path":404,"path-is-absolute":405}],172:[function(require,module,exports){ +(function (process){ +// Approach: +// +// 1. Get the minimatch set +// 2. For each pattern in the set, PROCESS(pattern, false) +// 3. Store matches per-set, then uniq them +// +// PROCESS(pattern, inGlobStar) +// Get the first [n] items from pattern that are all strings +// Join these together. This is PREFIX. +// If there is no more remaining, then stat(PREFIX) and +// add to matches if it succeeds. END. +// +// If inGlobStar and PREFIX is symlink and points to dir +// set ENTRIES = [] +// else readdir(PREFIX) as ENTRIES +// If fail, END +// +// with ENTRIES +// If pattern[n] is GLOBSTAR +// // handle the case where the globstar match is empty +// // by pruning it out, and testing the resulting pattern +// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) +// // handle other cases. +// for ENTRY in ENTRIES (not dotfiles) +// // attach globstar + tail onto the entry +// // Mark that this entry is a globstar match +// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) +// +// else // not globstar +// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) +// Test ENTRY against pattern[n] +// If fails, continue +// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) +// +// Caveat: +// Cache all stats and readdirs results to minimize syscall. Since all +// we ever care about is existence and directory-ness, we can just keep +// `true` for files, and [children,...] for directories, or `false` for +// things that don't exist. + +module.exports = glob + +var fs = require('fs') +var rp = require('fs.realpath') +var minimatch = require('minimatch') +var Minimatch = minimatch.Minimatch +var inherits = require('inherits') +var EE = require('events').EventEmitter +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path-is-absolute') +var globSync = require('./sync.js') +var common = require('./common.js') +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var inflight = require('inflight') +var util = require('util') +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored + +var once = require('once') + +function glob (pattern, options, cb) { + if (typeof options === 'function') cb = options, options = {} + if (!options) options = {} + + if (options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return globSync(pattern, options) + } + + return new Glob(pattern, options, cb) +} + +glob.sync = globSync +var GlobSync = glob.GlobSync = globSync.GlobSync + +// old api surface +glob.glob = glob + +function extend (origin, add) { + if (add === null || typeof add !== 'object') { + return origin + } + + var keys = Object.keys(add) + var i = keys.length + while (i--) { + origin[keys[i]] = add[keys[i]] + } + return origin +} + +glob.hasMagic = function (pattern, options_) { + var options = extend({}, options_) + options.noprocess = true + + var g = new Glob(pattern, options) + var set = g.minimatch.set + + if (!pattern) + return false + + if (set.length > 1) + return true + + for (var j = 0; j < set[0].length; j++) { + if (typeof set[0][j] !== 'string') + return true + } + + return false +} + +glob.Glob = Glob +inherits(Glob, EE) +function Glob (pattern, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } + + if (options && options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return new GlobSync(pattern, options) + } + + if (!(this instanceof Glob)) + return new Glob(pattern, options, cb) + + setopts(this, pattern, options) + this._didRealPath = false + + // process each pattern in the minimatch set + var n = this.minimatch.set.length + + // The matches are stored as {: true,...} so that + // duplicates are automagically pruned. + // Later, we do an Object.keys() on these. + // Keep them as a list so we can fill in when nonull is set. + this.matches = new Array(n) + + if (typeof cb === 'function') { + cb = once(cb) + this.on('error', cb) + this.on('end', function (matches) { + cb(null, matches) + }) + } + + var self = this + this._processing = 0 + + this._emitQueue = [] + this._processQueue = [] + this.paused = false + + if (this.noprocess) + return this + + if (n === 0) + return done() + + var sync = true + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false, done) + } + sync = false + + function done () { + --self._processing + if (self._processing <= 0) { + if (sync) { + process.nextTick(function () { + self._finish() + }) + } else { + self._finish() + } + } + } +} + +Glob.prototype._finish = function () { + assert(this instanceof Glob) + if (this.aborted) + return + + if (this.realpath && !this._didRealpath) + return this._realpath() + + common.finish(this) + this.emit('end', this.found) +} + +Glob.prototype._realpath = function () { + if (this._didRealpath) + return + + this._didRealpath = true + + var n = this.matches.length + if (n === 0) + return this._finish() + + var self = this + for (var i = 0; i < this.matches.length; i++) + this._realpathSet(i, next) + + function next () { + if (--n === 0) + self._finish() + } +} + +Glob.prototype._realpathSet = function (index, cb) { + var matchset = this.matches[index] + if (!matchset) + return cb() + + var found = Object.keys(matchset) + var self = this + var n = found.length + + if (n === 0) + return cb() + + var set = this.matches[index] = Object.create(null) + found.forEach(function (p, i) { + // If there's a problem with the stat, then it means that + // one or more of the links in the realpath couldn't be + // resolved. just return the abs value in that case. + p = self._makeAbs(p) + rp.realpath(p, self.realpathCache, function (er, real) { + if (!er) + set[real] = true + else if (er.syscall === 'stat') + set[p] = true + else + self.emit('error', er) // srsly wtf right here + + if (--n === 0) { + self.matches[index] = set + cb() + } + }) + }) +} + +Glob.prototype._mark = function (p) { + return common.mark(this, p) +} + +Glob.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} + +Glob.prototype.abort = function () { + this.aborted = true + this.emit('abort') +} + +Glob.prototype.pause = function () { + if (!this.paused) { + this.paused = true + this.emit('pause') + } +} + +Glob.prototype.resume = function () { + if (this.paused) { + this.emit('resume') + this.paused = false + if (this._emitQueue.length) { + var eq = this._emitQueue.slice(0) + this._emitQueue.length = 0 + for (var i = 0; i < eq.length; i ++) { + var e = eq[i] + this._emitMatch(e[0], e[1]) + } + } + if (this._processQueue.length) { + var pq = this._processQueue.slice(0) + this._processQueue.length = 0 + for (var i = 0; i < pq.length; i ++) { + var p = pq[i] + this._processing-- + this._process(p[0], p[1], p[2], p[3]) + } + } + } +} + +Glob.prototype._process = function (pattern, index, inGlobStar, cb) { + assert(this instanceof Glob) + assert(typeof cb === 'function') + + if (this.aborted) + return + + this._processing++ + if (this.paused) { + this._processQueue.push([pattern, index, inGlobStar, cb]) + return + } + + //console.error('PROCESS %d', this._processing, pattern) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // see if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index, cb) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip _processing + if (childrenIgnored(this, read)) + return cb() + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb) +} + +Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + +Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return cb() + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return cb() + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) + } + // This was the last one, and no stats were needed + return cb() + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + this._process([e].concat(remain), index, inGlobStar, cb) + } + cb() +} + +Glob.prototype._emitMatch = function (index, e) { + if (this.aborted) + return + + if (isIgnored(this, e)) + return + + if (this.paused) { + this._emitQueue.push([index, e]) + return + } + + var abs = isAbsolute(e) ? e : this._makeAbs(e) + + if (this.mark) + e = this._mark(e) + + if (this.absolute) + e = abs + + if (this.matches[index][e]) + return + + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return + } + + this.matches[index][e] = true + + var st = this.statCache[abs] + if (st) + this.emit('stat', e, st) + + this.emit('match', e) +} + +Glob.prototype._readdirInGlobStar = function (abs, cb) { + if (this.aborted) + return + + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false, cb) + + var lstatkey = 'lstat\0' + abs + var self = this + var lstatcb = inflight(lstatkey, lstatcb_) + + if (lstatcb) + fs.lstat(abs, lstatcb) + + function lstatcb_ (er, lstat) { + if (er && er.code === 'ENOENT') + return cb() + + var isSym = lstat && lstat.isSymbolicLink() + self.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && lstat && !lstat.isDirectory()) { + self.cache[abs] = 'FILE' + cb() + } else + self._readdir(abs, false, cb) + } +} + +Glob.prototype._readdir = function (abs, inGlobStar, cb) { + if (this.aborted) + return + + cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb) + if (!cb) + return + + //console.error('RD %j %j', +inGlobStar, abs) + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs, cb) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return cb() + + if (Array.isArray(c)) + return cb(null, c) + } + + var self = this + fs.readdir(abs, readdirCb(this, abs, cb)) +} + +function readdirCb (self, abs, cb) { + return function (er, entries) { + if (er) + self._readdirError(abs, er, cb) + else + self._readdirEntries(abs, entries, cb) + } +} + +Glob.prototype._readdirEntries = function (abs, entries, cb) { + if (this.aborted) + return + + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + return cb(null, entries) +} + +Glob.prototype._readdirError = function (f, er, cb) { + if (this.aborted) + return + + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + var abs = this._makeAbs(f) + this.cache[abs] = 'FILE' + if (abs === this.cwdAbs) { + var error = new Error(er.code + ' invalid cwd ' + this.cwd) + error.path = this.cwd + error.code = er.code + this.emit('error', error) + this.abort() + } + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) { + this.emit('error', er) + // If the error is handled, then we abort + // if not, we threw out of here + this.abort() + } + if (!this.silent) + console.error('glob error', er) + break + } + + return cb() +} + +Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + + +Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + //console.error('pgs2', prefix, remain[0], entries) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return cb() + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false, cb) + + var isSym = this.symlinks[abs] + var len = entries.length + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return cb() + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true, cb) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true, cb) + } + + cb() +} + +Glob.prototype._processSimple = function (prefix, index, cb) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var self = this + this._stat(prefix, function (er, exists) { + self._processSimple2(prefix, index, er, exists, cb) + }) +} +Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { + + //console.error('ps2', prefix, exists) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return cb() + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this._emitMatch(index, prefix) + cb() +} + +// Returns either 'DIR', 'FILE', or false +Glob.prototype._stat = function (f, cb) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return cb() + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return cb(null, c) + + if (needDir && c === 'FILE') + return cb() + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (stat !== undefined) { + if (stat === false) + return cb(null, stat) + else { + var type = stat.isDirectory() ? 'DIR' : 'FILE' + if (needDir && type === 'FILE') + return cb() + else + return cb(null, type, stat) + } + } + + var self = this + var statcb = inflight('stat\0' + abs, lstatcb_) + if (statcb) + fs.lstat(abs, statcb) + + function lstatcb_ (er, lstat) { + if (lstat && lstat.isSymbolicLink()) { + // If it's a symlink, then treat it as the target, unless + // the target does not exist, then treat it as a file. + return fs.stat(abs, function (er, stat) { + if (er) + self._stat2(f, abs, null, lstat, cb) + else + self._stat2(f, abs, er, stat, cb) + }) + } else { + self._stat2(f, abs, er, lstat, cb) + } + } +} + +Glob.prototype._stat2 = function (f, abs, er, stat, cb) { + if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { + this.statCache[abs] = false + return cb() + } + + var needDir = f.slice(-1) === '/' + this.statCache[abs] = stat + + if (abs.slice(-1) === '/' && stat && !stat.isDirectory()) + return cb(null, false, stat) + + var c = true + if (stat) + c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c === 'FILE') + return cb() + + return cb(null, c, stat) +} + +}).call(this,require('_process')) +},{"./common.js":171,"./sync.js":173,"_process":437,"assert":292,"events":300,"fs":298,"fs.realpath":121,"inflight":358,"inherits":359,"minimatch":385,"once":399,"path":404,"path-is-absolute":405,"util":523}],173:[function(require,module,exports){ +(function (process){ +module.exports = globSync +globSync.GlobSync = GlobSync + +var fs = require('fs') +var rp = require('fs.realpath') +var minimatch = require('minimatch') +var Minimatch = minimatch.Minimatch +var Glob = require('./glob.js').Glob +var util = require('util') +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path-is-absolute') +var common = require('./common.js') +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored + +function globSync (pattern, options) { + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') + + return new GlobSync(pattern, options).found +} + +function GlobSync (pattern, options) { + if (!pattern) + throw new Error('must provide pattern') + + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') + + if (!(this instanceof GlobSync)) + return new GlobSync(pattern, options) + + setopts(this, pattern, options) + + if (this.noprocess) + return this + + var n = this.minimatch.set.length + this.matches = new Array(n) + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false) + } + this._finish() +} + +GlobSync.prototype._finish = function () { + assert(this instanceof GlobSync) + if (this.realpath) { + var self = this + this.matches.forEach(function (matchset, index) { + var set = self.matches[index] = Object.create(null) + for (var p in matchset) { + try { + p = self._makeAbs(p) + var real = rp.realpathSync(p, self.realpathCache) + set[real] = true + } catch (er) { + if (er.syscall === 'stat') + set[self._makeAbs(p)] = true + else + throw er + } + } + }) + } + common.finish(this) +} + + +GlobSync.prototype._process = function (pattern, index, inGlobStar) { + assert(this instanceof GlobSync) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // See if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip processing + if (childrenIgnored(this, read)) + return + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar) +} + + +GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { + var entries = this._readdir(abs, inGlobStar) + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix.slice(-1) !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) + } + // This was the last one, and no stats were needed + return + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) + newPattern = [prefix, e] + else + newPattern = [e] + this._process(newPattern.concat(remain), index, inGlobStar) + } +} + + +GlobSync.prototype._emitMatch = function (index, e) { + if (isIgnored(this, e)) + return + + var abs = this._makeAbs(e) + + if (this.mark) + e = this._mark(e) + + if (this.absolute) { + e = abs + } + + if (this.matches[index][e]) + return + + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return + } + + this.matches[index][e] = true + + if (this.stat) + this._stat(e) +} + + +GlobSync.prototype._readdirInGlobStar = function (abs) { + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false) + + var entries + var lstat + var stat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + if (er.code === 'ENOENT') { + // lstat failed, doesn't exist + return null + } + } + + var isSym = lstat && lstat.isSymbolicLink() + this.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && lstat && !lstat.isDirectory()) + this.cache[abs] = 'FILE' + else + entries = this._readdir(abs, false) + + return entries +} + +GlobSync.prototype._readdir = function (abs, inGlobStar) { + var entries + + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return null + + if (Array.isArray(c)) + return c + } + + try { + return this._readdirEntries(abs, fs.readdirSync(abs)) + } catch (er) { + this._readdirError(abs, er) + return null + } +} + +GlobSync.prototype._readdirEntries = function (abs, entries) { + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + + // mark and cache dir-ness + return entries +} + +GlobSync.prototype._readdirError = function (f, er) { + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + var abs = this._makeAbs(f) + this.cache[abs] = 'FILE' + if (abs === this.cwdAbs) { + var error = new Error(er.code + ' invalid cwd ' + this.cwd) + error.path = this.cwd + error.code = er.code + throw error + } + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) + throw er + if (!this.silent) + console.error('glob error', er) + break + } +} + +GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { + + var entries = this._readdir(abs, inGlobStar) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false) + + var len = entries.length + var isSym = this.symlinks[abs] + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true) + } +} + +GlobSync.prototype._processSimple = function (prefix, index) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var exists = this._stat(prefix) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this._emitMatch(index, prefix) +} + +// Returns either 'DIR', 'FILE', or false +GlobSync.prototype._stat = function (f) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return false + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return c + + if (needDir && c === 'FILE') + return false + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (!stat) { + var lstat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { + this.statCache[abs] = false + return false + } + } + + if (lstat && lstat.isSymbolicLink()) { + try { + stat = fs.statSync(abs) + } catch (er) { + stat = lstat + } + } else { + stat = lstat + } + } + + this.statCache[abs] = stat + + var c = true + if (stat) + c = stat.isDirectory() ? 'DIR' : 'FILE' + + this.cache[abs] = this.cache[abs] || c + + if (needDir && c === 'FILE') + return false + + return c +} + +GlobSync.prototype._mark = function (p) { + return common.mark(this, p) +} + +GlobSync.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} + +}).call(this,require('_process')) +},{"./common.js":171,"./glob.js":172,"_process":437,"assert":292,"fs":298,"fs.realpath":121,"minimatch":385,"path":404,"path-is-absolute":405,"util":523}],174:[function(require,module,exports){ +(function (process){ +// A simple implementation of make-array +function makeArray (subject) { + return Array.isArray(subject) + ? subject + : [subject] +} + +const REGEX_TEST_BLANK_LINE = /^\s+$/ +const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/ +const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/ +const REGEX_SPLITALL_CRLF = /\r?\n/g +// /foo, +// ./foo, +// ../foo, +// . +// .. +const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/ + +const SLASH = '/' +const KEY_IGNORE = typeof Symbol !== 'undefined' + ? Symbol.for('node-ignore') + /* istanbul ignore next */ + : 'node-ignore' + +const define = (object, key, value) => + Object.defineProperty(object, key, {value}) + +const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g + +// Sanitize the range of a regular expression +// The cases are complicated, see test cases for details +const sanitizeRange = range => range.replace( + REGEX_REGEXP_RANGE, + (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) + ? match + // Invalid range (out of order) which is ok for gitignore rules but + // fatal for JavaScript regular expression, so eliminate it. + : '' +) + +// > If the pattern ends with a slash, +// > it is removed for the purpose of the following description, +// > but it would only find a match with a directory. +// > In other words, foo/ will match a directory foo and paths underneath it, +// > but will not match a regular file or a symbolic link foo +// > (this is consistent with the way how pathspec works in general in Git). +// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`' +// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call +// you could use option `mark: true` with `glob` + +// '`foo/`' should not continue with the '`..`' +const REPLACERS = [ + + // > Trailing spaces are ignored unless they are quoted with backslash ("\") + [ + // (a\ ) -> (a ) + // (a ) -> (a) + // (a \ ) -> (a ) + /\\?\s+$/, + match => match.indexOf('\\') === 0 + ? ' ' + : '' + ], + + // replace (\ ) with ' ' + [ + /\\\s/g, + () => ' ' + ], + + // Escape metacharacters + // which is written down by users but means special for regular expressions. + + // > There are 12 characters with special meanings: + // > - the backslash \, + // > - the caret ^, + // > - the dollar sign $, + // > - the period or dot ., + // > - the vertical bar or pipe symbol |, + // > - the question mark ?, + // > - the asterisk or star *, + // > - the plus sign +, + // > - the opening parenthesis (, + // > - the closing parenthesis ), + // > - and the opening square bracket [, + // > - the opening curly brace {, + // > These special characters are often called "metacharacters". + [ + /[\\^$.|*+(){]/g, + match => `\\${match}` + ], + + [ + // > [abc] matches any character inside the brackets + // > (in this case a, b, or c); + /\[([^\]/]*)($|\])/g, + (match, p1, p2) => p2 === ']' + ? `[${sanitizeRange(p1)}]` + : `\\${match}` + ], + + [ + // > a question mark (?) matches a single character + /(?!\\)\?/g, + () => '[^/]' + ], + + // leading slash + [ + + // > A leading slash matches the beginning of the pathname. + // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". + // A leading slash matches the beginning of the pathname + /^\//, + () => '^' + ], + + // replace special metacharacter slash after the leading slash + [ + /\//g, + () => '\\/' + ], + + [ + // > A leading "**" followed by a slash means match in all directories. + // > For example, "**/foo" matches file or directory "foo" anywhere, + // > the same as pattern "foo". + // > "**/foo/bar" matches file or directory "bar" anywhere that is directly + // > under directory "foo". + // Notice that the '*'s have been replaced as '\\*' + /^\^*\\\*\\\*\\\//, + + // '**/foo' <-> 'foo' + () => '^(?:.*\\/)?' + ], + + // ending + [ + // 'js' will not match 'js.' + // 'ab' will not match 'abc' + /(?:[^*])$/, + + // WTF! + // https://git-scm.com/docs/gitignore + // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1) + // which re-fixes #24, #38 + + // > If there is a separator at the end of the pattern then the pattern + // > will only match directories, otherwise the pattern can match both + // > files and directories. + + // 'js*' will not match 'a.js' + // 'js/' will not match 'a.js' + // 'js' will match 'a.js' and 'a.js/' + match => /\/$/.test(match) + // foo/ will not match 'foo' + ? `${match}$` + // foo matches 'foo' and 'foo/' + : `${match}(?=$|\\/$)` + ], + + // starting + [ + // there will be no leading '/' + // (which has been replaced by section "leading slash") + // If starts with '**', adding a '^' to the regular expression also works + /^(?=[^^])/, + function startingReplacer () { + // If has a slash `/` at the beginning or middle + return !/\/(?!$)/.test(this) + // > Prior to 2.22.1 + // > If the pattern does not contain a slash /, + // > Git treats it as a shell glob pattern + // Actually, if there is only a trailing slash, + // git also treats it as a shell glob pattern + + // After 2.22.1 (compatible but clearer) + // > If there is a separator at the beginning or middle (or both) + // > of the pattern, then the pattern is relative to the directory + // > level of the particular .gitignore file itself. + // > Otherwise the pattern may also match at any level below + // > the .gitignore level. + ? '(?:^|\\/)' + + // > Otherwise, Git treats the pattern as a shell glob suitable for + // > consumption by fnmatch(3) + : '^' + } + ], + + // two globstars + [ + // Use lookahead assertions so that we could match more than one `'/**'` + /\\\/\\\*\\\*(?=\\\/|$)/g, + + // Zero, one or several directories + // should not use '*', or it will be replaced by the next replacer + + // Check if it is not the last `'/**'` + (_, index, str) => index + 6 < str.length + + // case: /**/ + // > A slash followed by two consecutive asterisks then a slash matches + // > zero or more directories. + // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on. + // '/**/' + ? '(?:\\/[^\\/]+)*' + + // case: /** + // > A trailing `"/**"` matches everything inside. + + // #21: everything inside but it should not include the current folder + : '\\/.+' + ], + + // intermediate wildcards + [ + // Never replace escaped '*' + // ignore rule '\*' will match the path '*' + + // 'abc.*/' -> go + // 'abc.*' -> skip this rule + /(^|[^\\]+)\\\*(?=.+)/g, + + // '*.js' matches '.js' + // '*.js' doesn't match 'abc' + (_, p1) => `${p1}[^\\/]*` + ], + + // trailing wildcard + [ + /(\^|\\\/)?\\\*$/, + (_, p1) => { + const prefix = p1 + // '\^': + // '/*' does not match '' + // '/*' does not match everything + + // '\\\/': + // 'abc/*' does not match 'abc/' + ? `${p1}[^/]+` + + // 'a*' matches 'a' + // 'a*' matches 'aa' + : '[^/]*' + + return `${prefix}(?=$|\\/$)` + } + ], + + [ + // unescape + /\\\\\\/g, + () => '\\' + ] +] + +// A simple cache, because an ignore rule only has only one certain meaning +const regexCache = Object.create(null) + +// @param {pattern} +const makeRegex = (pattern, negative, ignorecase) => { + const r = regexCache[pattern] + if (r) { + return r + } + + // const replacers = negative + // ? NEGATIVE_REPLACERS + // : POSITIVE_REPLACERS + + const source = REPLACERS.reduce( + (prev, current) => prev.replace(current[0], current[1].bind(pattern)), + pattern + ) + + return regexCache[pattern] = ignorecase + ? new RegExp(source, 'i') + : new RegExp(source) +} + +const isString = subject => typeof subject === 'string' + +// > A blank line matches no files, so it can serve as a separator for readability. +const checkPattern = pattern => pattern + && isString(pattern) + && !REGEX_TEST_BLANK_LINE.test(pattern) + + // > A line starting with # serves as a comment. + && pattern.indexOf('#') !== 0 + +const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF) + +class IgnoreRule { + constructor ( + origin, + pattern, + negative, + regex + ) { + this.origin = origin + this.pattern = pattern + this.negative = negative + this.regex = regex + } +} + +const createRule = (pattern, ignorecase) => { + const origin = pattern + let negative = false + + // > An optional prefix "!" which negates the pattern; + if (pattern.indexOf('!') === 0) { + negative = true + pattern = pattern.substr(1) + } + + pattern = pattern + // > Put a backslash ("\") in front of the first "!" for patterns that + // > begin with a literal "!", for example, `"\!important!.txt"`. + .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!') + // > Put a backslash ("\") in front of the first hash for patterns that + // > begin with a hash. + .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#') + + const regex = makeRegex(pattern, negative, ignorecase) + + return new IgnoreRule( + origin, + pattern, + negative, + regex + ) +} + +const throwError = (message, Ctor) => { + throw new Ctor(message) +} + +const checkPath = (path, originalPath, doThrow) => { + if (!isString(path)) { + return doThrow( + `path must be a string, but got \`${originalPath}\``, + TypeError + ) + } + + // We don't know if we should ignore '', so throw + if (!path) { + return doThrow(`path must not be empty`, TypeError) + } + + // Check if it is a relative path + if (checkPath.isNotRelative(path)) { + const r = '`path.relative()`d' + return doThrow( + `path should be a ${r} string, but got "${originalPath}"`, + RangeError + ) + } + + return true +} + +const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path) + +checkPath.isNotRelative = isNotRelative +checkPath.convert = p => p + +class Ignore { + constructor ({ + ignorecase = true + } = {}) { + this._rules = [] + this._ignorecase = ignorecase + define(this, KEY_IGNORE, true) + this._initCache() + } + + _initCache () { + this._ignoreCache = Object.create(null) + this._testCache = Object.create(null) + } + + _addPattern (pattern) { + // #32 + if (pattern && pattern[KEY_IGNORE]) { + this._rules = this._rules.concat(pattern._rules) + this._added = true + return + } + + if (checkPattern(pattern)) { + const rule = createRule(pattern, this._ignorecase) + this._added = true + this._rules.push(rule) + } + } + + // @param {Array | string | Ignore} pattern + add (pattern) { + this._added = false + + makeArray( + isString(pattern) + ? splitPattern(pattern) + : pattern + ).forEach(this._addPattern, this) + + // Some rules have just added to the ignore, + // making the behavior changed. + if (this._added) { + this._initCache() + } + + return this + } + + // legacy + addPattern (pattern) { + return this.add(pattern) + } + + // | ignored : unignored + // negative | 0:0 | 0:1 | 1:0 | 1:1 + // -------- | ------- | ------- | ------- | -------- + // 0 | TEST | TEST | SKIP | X + // 1 | TESTIF | SKIP | TEST | X + + // - SKIP: always skip + // - TEST: always test + // - TESTIF: only test if checkUnignored + // - X: that never happen + + // @param {boolean} whether should check if the path is unignored, + // setting `checkUnignored` to `false` could reduce additional + // path matching. + + // @returns {TestResult} true if a file is ignored + _testOne (path, checkUnignored) { + let ignored = false + let unignored = false + + this._rules.forEach(rule => { + const {negative} = rule + if ( + unignored === negative && ignored !== unignored + || negative && !ignored && !unignored && !checkUnignored + ) { + return + } + + const matched = rule.regex.test(path) + + if (matched) { + ignored = !negative + unignored = negative + } + }) + + return { + ignored, + unignored + } + } + + // @returns {TestResult} + _test (originalPath, cache, checkUnignored, slices) { + const path = originalPath + // Supports nullable path + && checkPath.convert(originalPath) + + checkPath(path, originalPath, throwError) + + return this._t(path, cache, checkUnignored, slices) + } + + _t (path, cache, checkUnignored, slices) { + if (path in cache) { + return cache[path] + } + + if (!slices) { + // path/to/a.js + // ['path', 'to', 'a.js'] + slices = path.split(SLASH) + } + + slices.pop() + + // If the path has no parent directory, just test it + if (!slices.length) { + return cache[path] = this._testOne(path, checkUnignored) + } + + const parent = this._t( + slices.join(SLASH) + SLASH, + cache, + checkUnignored, + slices + ) + + // If the path contains a parent directory, check the parent first + return cache[path] = parent.ignored + // > It is not possible to re-include a file if a parent directory of + // > that file is excluded. + ? parent + : this._testOne(path, checkUnignored) + } + + ignores (path) { + return this._test(path, this._ignoreCache, false).ignored + } + + createFilter () { + return path => !this.ignores(path) + } + + filter (paths) { + return makeArray(paths).filter(this.createFilter()) + } + + // @returns {TestResult} + test (path) { + return this._test(path, this._testCache, true) + } +} + +const factory = options => new Ignore(options) + +const returnFalse = () => false + +const isPathValid = path => + checkPath(path && checkPath.convert(path), path, returnFalse) + +factory.isPathValid = isPathValid + +// Fixes typescript +factory.default = factory + +module.exports = factory + +// Windows +// -------------------------------------------------------------- +/* istanbul ignore if */ +if ( + // Detect `process` so that it can run in browsers. + typeof process !== 'undefined' + && ( + process.env && process.env.IGNORE_TEST_WIN32 + || process.platform === 'win32' + ) +) { + /* eslint no-control-regex: "off" */ + const makePosix = str => /^\\\\\?\\/.test(str) + || /["<>|\u0000-\u001F]+/u.test(str) + ? str + : str.replace(/\\/g, '/') + + checkPath.convert = makePosix + + // 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/' + // 'd:\\foo' + const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i + checkPath.isNotRelative = path => + REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path) + || isNotRelative(path) +} + +}).call(this,require('_process')) +},{"_process":437}],175:[function(require,module,exports){ +'use strict'; +const {Transform} = require('stream'); + +class ObjectTransform extends Transform { + constructor() { + super({ + objectMode: true + }); + } +} + +class FilterStream extends ObjectTransform { + constructor(filter) { + super(); + this._filter = filter; + } + + _transform(data, encoding, callback) { + if (this._filter(data)) { + this.push(data); + } + + callback(); + } +} + +class UniqueStream extends ObjectTransform { + constructor() { + super(); + this._pushed = new Set(); + } + + _transform(data, encoding, callback) { + if (!this._pushed.has(data)) { + this.push(data); + this._pushed.add(data); + } + + callback(); + } +} + +module.exports = { + FilterStream, + UniqueStream +}; + +},{"stream":503}],176:[function(require,module,exports){ +module.exports = tokenize + +var literals100 = require('./lib/literals') + , operators = require('./lib/operators') + , builtins100 = require('./lib/builtins') + , literals300es = require('./lib/literals-300es') + , builtins300es = require('./lib/builtins-300es') + +var NORMAL = 999 // <-- never emitted + , TOKEN = 9999 // <-- never emitted + , BLOCK_COMMENT = 0 + , LINE_COMMENT = 1 + , PREPROCESSOR = 2 + , OPERATOR = 3 + , INTEGER = 4 + , FLOAT = 5 + , IDENT = 6 + , BUILTIN = 7 + , KEYWORD = 8 + , WHITESPACE = 9 + , EOF = 10 + , HEX = 11 + +var map = [ + 'block-comment' + , 'line-comment' + , 'preprocessor' + , 'operator' + , 'integer' + , 'float' + , 'ident' + , 'builtin' + , 'keyword' + , 'whitespace' + , 'eof' + , 'integer' +] + +function tokenize(opt) { + var i = 0 + , total = 0 + , mode = NORMAL + , c + , last + , content = [] + , tokens = [] + , token_idx = 0 + , token_offs = 0 + , line = 1 + , col = 0 + , start = 0 + , isnum = false + , isoperator = false + , input = '' + , len + + opt = opt || {} + var allBuiltins = builtins100 + var allLiterals = literals100 + if (opt.version === '300 es') { + allBuiltins = builtins300es + allLiterals = literals300es + } + + // cache by name + var builtinsDict = {}, literalsDict = {} + for (var i = 0; i < allBuiltins.length; i++) { + builtinsDict[allBuiltins[i]] = true + } + for (var i = 0; i < allLiterals.length; i++) { + literalsDict[allLiterals[i]] = true + } + + return function(data) { + tokens = [] + if (data !== null) return write(data) + return end() + } + + function token(data) { + if (data.length) { + tokens.push({ + type: map[mode] + , data: data + , position: start + , line: line + , column: col + }) + } + } + + function write(chunk) { + i = 0 + + if (chunk.toString) chunk = chunk.toString() + + input += chunk.replace(/\r\n/g, '\n') + len = input.length + + + var last + + while(c = input[i], i < len) { + last = i + + switch(mode) { + case BLOCK_COMMENT: i = block_comment(); break + case LINE_COMMENT: i = line_comment(); break + case PREPROCESSOR: i = preprocessor(); break + case OPERATOR: i = operator(); break + case INTEGER: i = integer(); break + case HEX: i = hex(); break + case FLOAT: i = decimal(); break + case TOKEN: i = readtoken(); break + case WHITESPACE: i = whitespace(); break + case NORMAL: i = normal(); break + } + + if(last !== i) { + switch(input[last]) { + case '\n': col = 0; ++line; break + default: ++col; break + } + } + } + + total += i + input = input.slice(i) + return tokens + } + + function end(chunk) { + if(content.length) { + token(content.join('')) + } + + mode = EOF + token('(eof)') + return tokens + } + + function normal() { + content = content.length ? [] : content + + if(last === '/' && c === '*') { + start = total + i - 1 + mode = BLOCK_COMMENT + last = c + return i + 1 + } + + if(last === '/' && c === '/') { + start = total + i - 1 + mode = LINE_COMMENT + last = c + return i + 1 + } + + if(c === '#') { + mode = PREPROCESSOR + start = total + i + return i + } + + if(/\s/.test(c)) { + mode = WHITESPACE + start = total + i + return i + } + + isnum = /\d/.test(c) + isoperator = /[^\w_]/.test(c) + + start = total + i + mode = isnum ? INTEGER : isoperator ? OPERATOR : TOKEN + return i + } + + function whitespace() { + if(/[^\s]/g.test(c)) { + token(content.join('')) + mode = NORMAL + return i + } + content.push(c) + last = c + return i + 1 + } + + function preprocessor() { + if((c === '\r' || c === '\n') && last !== '\\') { + token(content.join('')) + mode = NORMAL + return i + } + content.push(c) + last = c + return i + 1 + } + + function line_comment() { + return preprocessor() + } + + function block_comment() { + if(c === '/' && last === '*') { + content.push(c) + token(content.join('')) + mode = NORMAL + return i + 1 + } + + content.push(c) + last = c + return i + 1 + } + + function operator() { + if(last === '.' && /\d/.test(c)) { + mode = FLOAT + return i + } + + if(last === '/' && c === '*') { + mode = BLOCK_COMMENT + return i + } + + if(last === '/' && c === '/') { + mode = LINE_COMMENT + return i + } + + if(c === '.' && content.length) { + while(determine_operator(content)); + + mode = FLOAT + return i + } + + if(c === ';' || c === ')' || c === '(') { + if(content.length) while(determine_operator(content)); + token(c) + mode = NORMAL + return i + 1 + } + + var is_composite_operator = content.length === 2 && c !== '=' + if(/[\w_\d\s]/.test(c) || is_composite_operator) { + while(determine_operator(content)); + mode = NORMAL + return i + } + + content.push(c) + last = c + return i + 1 + } + + function determine_operator(buf) { + var j = 0 + , idx + , res + + do { + idx = operators.indexOf(buf.slice(0, buf.length + j).join('')) + res = operators[idx] + + if(idx === -1) { + if(j-- + buf.length > 0) continue + res = buf.slice(0, 1).join('') + } + + token(res) + + start += res.length + content = content.slice(res.length) + return content.length + } while(1) + } + + function hex() { + if(/[^a-fA-F0-9]/.test(c)) { + token(content.join('')) + mode = NORMAL + return i + } + + content.push(c) + last = c + return i + 1 + } + + function integer() { + if(c === '.') { + content.push(c) + mode = FLOAT + last = c + return i + 1 + } + + if(/[eE]/.test(c)) { + content.push(c) + mode = FLOAT + last = c + return i + 1 + } + + if(c === 'x' && content.length === 1 && content[0] === '0') { + mode = HEX + content.push(c) + last = c + return i + 1 + } + + if(/[^\d]/.test(c)) { + token(content.join('')) + mode = NORMAL + return i + } + + content.push(c) + last = c + return i + 1 + } + + function decimal() { + if(c === 'f') { + content.push(c) + last = c + i += 1 + } + + if(/[eE]/.test(c)) { + content.push(c) + last = c + return i + 1 + } + + if ((c === '-' || c === '+') && /[eE]/.test(last)) { + content.push(c) + last = c + return i + 1 + } + + if(/[^\d]/.test(c)) { + token(content.join('')) + mode = NORMAL + return i + } + + content.push(c) + last = c + return i + 1 + } + + function readtoken() { + if(/[^\d\w_]/.test(c)) { + var contentstr = content.join('') + if(literalsDict[contentstr]) { + mode = KEYWORD + } else if(builtinsDict[contentstr]) { + mode = BUILTIN + } else { + mode = IDENT + } + token(content.join('')) + mode = NORMAL + return i + } + content.push(c) + last = c + return i + 1 + } +} + +},{"./lib/builtins":178,"./lib/builtins-300es":177,"./lib/literals":180,"./lib/literals-300es":179,"./lib/operators":181}],177:[function(require,module,exports){ +// 300es builtins/reserved words that were previously valid in v100 +var v100 = require('./builtins') + +// The texture2D|Cube functions have been removed +// And the gl_ features are updated +v100 = v100.slice().filter(function (b) { + return !/^(gl\_|texture)/.test(b) +}) + +module.exports = v100.concat([ + // the updated gl_ constants + 'gl_VertexID' + , 'gl_InstanceID' + , 'gl_Position' + , 'gl_PointSize' + , 'gl_FragCoord' + , 'gl_FrontFacing' + , 'gl_FragDepth' + , 'gl_PointCoord' + , 'gl_MaxVertexAttribs' + , 'gl_MaxVertexUniformVectors' + , 'gl_MaxVertexOutputVectors' + , 'gl_MaxFragmentInputVectors' + , 'gl_MaxVertexTextureImageUnits' + , 'gl_MaxCombinedTextureImageUnits' + , 'gl_MaxTextureImageUnits' + , 'gl_MaxFragmentUniformVectors' + , 'gl_MaxDrawBuffers' + , 'gl_MinProgramTexelOffset' + , 'gl_MaxProgramTexelOffset' + , 'gl_DepthRangeParameters' + , 'gl_DepthRange' + + // other builtins + , 'trunc' + , 'round' + , 'roundEven' + , 'isnan' + , 'isinf' + , 'floatBitsToInt' + , 'floatBitsToUint' + , 'intBitsToFloat' + , 'uintBitsToFloat' + , 'packSnorm2x16' + , 'unpackSnorm2x16' + , 'packUnorm2x16' + , 'unpackUnorm2x16' + , 'packHalf2x16' + , 'unpackHalf2x16' + , 'outerProduct' + , 'transpose' + , 'determinant' + , 'inverse' + , 'texture' + , 'textureSize' + , 'textureProj' + , 'textureLod' + , 'textureOffset' + , 'texelFetch' + , 'texelFetchOffset' + , 'textureProjOffset' + , 'textureLodOffset' + , 'textureProjLod' + , 'textureProjLodOffset' + , 'textureGrad' + , 'textureGradOffset' + , 'textureProjGrad' + , 'textureProjGradOffset' +]) + +},{"./builtins":178}],178:[function(require,module,exports){ +module.exports = [ + // Keep this list sorted + 'abs' + , 'acos' + , 'all' + , 'any' + , 'asin' + , 'atan' + , 'ceil' + , 'clamp' + , 'cos' + , 'cross' + , 'dFdx' + , 'dFdy' + , 'degrees' + , 'distance' + , 'dot' + , 'equal' + , 'exp' + , 'exp2' + , 'faceforward' + , 'floor' + , 'fract' + , 'gl_BackColor' + , 'gl_BackLightModelProduct' + , 'gl_BackLightProduct' + , 'gl_BackMaterial' + , 'gl_BackSecondaryColor' + , 'gl_ClipPlane' + , 'gl_ClipVertex' + , 'gl_Color' + , 'gl_DepthRange' + , 'gl_DepthRangeParameters' + , 'gl_EyePlaneQ' + , 'gl_EyePlaneR' + , 'gl_EyePlaneS' + , 'gl_EyePlaneT' + , 'gl_Fog' + , 'gl_FogCoord' + , 'gl_FogFragCoord' + , 'gl_FogParameters' + , 'gl_FragColor' + , 'gl_FragCoord' + , 'gl_FragData' + , 'gl_FragDepth' + , 'gl_FragDepthEXT' + , 'gl_FrontColor' + , 'gl_FrontFacing' + , 'gl_FrontLightModelProduct' + , 'gl_FrontLightProduct' + , 'gl_FrontMaterial' + , 'gl_FrontSecondaryColor' + , 'gl_LightModel' + , 'gl_LightModelParameters' + , 'gl_LightModelProducts' + , 'gl_LightProducts' + , 'gl_LightSource' + , 'gl_LightSourceParameters' + , 'gl_MaterialParameters' + , 'gl_MaxClipPlanes' + , 'gl_MaxCombinedTextureImageUnits' + , 'gl_MaxDrawBuffers' + , 'gl_MaxFragmentUniformComponents' + , 'gl_MaxLights' + , 'gl_MaxTextureCoords' + , 'gl_MaxTextureImageUnits' + , 'gl_MaxTextureUnits' + , 'gl_MaxVaryingFloats' + , 'gl_MaxVertexAttribs' + , 'gl_MaxVertexTextureImageUnits' + , 'gl_MaxVertexUniformComponents' + , 'gl_ModelViewMatrix' + , 'gl_ModelViewMatrixInverse' + , 'gl_ModelViewMatrixInverseTranspose' + , 'gl_ModelViewMatrixTranspose' + , 'gl_ModelViewProjectionMatrix' + , 'gl_ModelViewProjectionMatrixInverse' + , 'gl_ModelViewProjectionMatrixInverseTranspose' + , 'gl_ModelViewProjectionMatrixTranspose' + , 'gl_MultiTexCoord0' + , 'gl_MultiTexCoord1' + , 'gl_MultiTexCoord2' + , 'gl_MultiTexCoord3' + , 'gl_MultiTexCoord4' + , 'gl_MultiTexCoord5' + , 'gl_MultiTexCoord6' + , 'gl_MultiTexCoord7' + , 'gl_Normal' + , 'gl_NormalMatrix' + , 'gl_NormalScale' + , 'gl_ObjectPlaneQ' + , 'gl_ObjectPlaneR' + , 'gl_ObjectPlaneS' + , 'gl_ObjectPlaneT' + , 'gl_Point' + , 'gl_PointCoord' + , 'gl_PointParameters' + , 'gl_PointSize' + , 'gl_Position' + , 'gl_ProjectionMatrix' + , 'gl_ProjectionMatrixInverse' + , 'gl_ProjectionMatrixInverseTranspose' + , 'gl_ProjectionMatrixTranspose' + , 'gl_SecondaryColor' + , 'gl_TexCoord' + , 'gl_TextureEnvColor' + , 'gl_TextureMatrix' + , 'gl_TextureMatrixInverse' + , 'gl_TextureMatrixInverseTranspose' + , 'gl_TextureMatrixTranspose' + , 'gl_Vertex' + , 'greaterThan' + , 'greaterThanEqual' + , 'inversesqrt' + , 'length' + , 'lessThan' + , 'lessThanEqual' + , 'log' + , 'log2' + , 'matrixCompMult' + , 'max' + , 'min' + , 'mix' + , 'mod' + , 'normalize' + , 'not' + , 'notEqual' + , 'pow' + , 'radians' + , 'reflect' + , 'refract' + , 'sign' + , 'sin' + , 'smoothstep' + , 'sqrt' + , 'step' + , 'tan' + , 'texture2D' + , 'texture2DLod' + , 'texture2DProj' + , 'texture2DProjLod' + , 'textureCube' + , 'textureCubeLod' + , 'texture2DLodEXT' + , 'texture2DProjLodEXT' + , 'textureCubeLodEXT' + , 'texture2DGradEXT' + , 'texture2DProjGradEXT' + , 'textureCubeGradEXT' +] + +},{}],179:[function(require,module,exports){ +var v100 = require('./literals') + +module.exports = v100.slice().concat([ + 'layout' + , 'centroid' + , 'smooth' + , 'case' + , 'mat2x2' + , 'mat2x3' + , 'mat2x4' + , 'mat3x2' + , 'mat3x3' + , 'mat3x4' + , 'mat4x2' + , 'mat4x3' + , 'mat4x4' + , 'uvec2' + , 'uvec3' + , 'uvec4' + , 'samplerCubeShadow' + , 'sampler2DArray' + , 'sampler2DArrayShadow' + , 'isampler2D' + , 'isampler3D' + , 'isamplerCube' + , 'isampler2DArray' + , 'usampler2D' + , 'usampler3D' + , 'usamplerCube' + , 'usampler2DArray' + , 'coherent' + , 'restrict' + , 'readonly' + , 'writeonly' + , 'resource' + , 'atomic_uint' + , 'noperspective' + , 'patch' + , 'sample' + , 'subroutine' + , 'common' + , 'partition' + , 'active' + , 'filter' + , 'image1D' + , 'image2D' + , 'image3D' + , 'imageCube' + , 'iimage1D' + , 'iimage2D' + , 'iimage3D' + , 'iimageCube' + , 'uimage1D' + , 'uimage2D' + , 'uimage3D' + , 'uimageCube' + , 'image1DArray' + , 'image2DArray' + , 'iimage1DArray' + , 'iimage2DArray' + , 'uimage1DArray' + , 'uimage2DArray' + , 'image1DShadow' + , 'image2DShadow' + , 'image1DArrayShadow' + , 'image2DArrayShadow' + , 'imageBuffer' + , 'iimageBuffer' + , 'uimageBuffer' + , 'sampler1DArray' + , 'sampler1DArrayShadow' + , 'isampler1D' + , 'isampler1DArray' + , 'usampler1D' + , 'usampler1DArray' + , 'isampler2DRect' + , 'usampler2DRect' + , 'samplerBuffer' + , 'isamplerBuffer' + , 'usamplerBuffer' + , 'sampler2DMS' + , 'isampler2DMS' + , 'usampler2DMS' + , 'sampler2DMSArray' + , 'isampler2DMSArray' + , 'usampler2DMSArray' +]) + +},{"./literals":180}],180:[function(require,module,exports){ +module.exports = [ + // current + 'precision' + , 'highp' + , 'mediump' + , 'lowp' + , 'attribute' + , 'const' + , 'uniform' + , 'varying' + , 'break' + , 'continue' + , 'do' + , 'for' + , 'while' + , 'if' + , 'else' + , 'in' + , 'out' + , 'inout' + , 'float' + , 'int' + , 'uint' + , 'void' + , 'bool' + , 'true' + , 'false' + , 'discard' + , 'return' + , 'mat2' + , 'mat3' + , 'mat4' + , 'vec2' + , 'vec3' + , 'vec4' + , 'ivec2' + , 'ivec3' + , 'ivec4' + , 'bvec2' + , 'bvec3' + , 'bvec4' + , 'sampler1D' + , 'sampler2D' + , 'sampler3D' + , 'samplerCube' + , 'sampler1DShadow' + , 'sampler2DShadow' + , 'struct' + + // future + , 'asm' + , 'class' + , 'union' + , 'enum' + , 'typedef' + , 'template' + , 'this' + , 'packed' + , 'goto' + , 'switch' + , 'default' + , 'inline' + , 'noinline' + , 'volatile' + , 'public' + , 'static' + , 'extern' + , 'external' + , 'interface' + , 'long' + , 'short' + , 'double' + , 'half' + , 'fixed' + , 'unsigned' + , 'input' + , 'output' + , 'hvec2' + , 'hvec3' + , 'hvec4' + , 'dvec2' + , 'dvec3' + , 'dvec4' + , 'fvec2' + , 'fvec3' + , 'fvec4' + , 'sampler2DRect' + , 'sampler3DRect' + , 'sampler2DRectShadow' + , 'sizeof' + , 'cast' + , 'namespace' + , 'using' +] + +},{}],181:[function(require,module,exports){ +module.exports = [ + '<<=' + , '>>=' + , '++' + , '--' + , '<<' + , '>>' + , '<=' + , '>=' + , '==' + , '!=' + , '&&' + , '||' + , '+=' + , '-=' + , '*=' + , '/=' + , '%=' + , '&=' + , '^^' + , '^=' + , '|=' + , '(' + , ')' + , '[' + , ']' + , '.' + , '!' + , '~' + , '*' + , '/' + , '%' + , '+' + , '-' + , '<' + , '>' + , '&' + , '^' + , '|' + , '?' + , ':' + , '=' + , ',' + , ';' + , '{' + , '}' +] + +},{}],182:[function(require,module,exports){ +var tokenize = require('./index') + +module.exports = tokenizeString + +function tokenizeString(str, opt) { + var generator = tokenize(opt) + var tokens = [] + + tokens = tokens.concat(generator(str)) + tokens = tokens.concat(generator(null)) + + return tokens +} + +},{"./index":176}],183:[function(require,module,exports){ +function setupArguments(args) { + const newArguments = new Array(args.length); + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (arg.toArray) { + newArguments[i] = arg.toArray(); + } else { + newArguments[i] = arg; + } + } + return newArguments; +} + +function mock1D() { + const args = setupArguments(arguments); + const row = new Float32Array(this.output.x); + for (let x = 0; x < this.output.x; x++) { + this.thread.x = x; + this.thread.y = 0; + this.thread.z = 0; + row[x] = this._fn.apply(this, args); + } + return row; +} + +function mock2D() { + const args = setupArguments(arguments); + const matrix = new Array(this.output.y); + for (let y = 0; y < this.output.y; y++) { + const row = new Float32Array(this.output.x); + for (let x = 0; x < this.output.x; x++) { + this.thread.x = x; + this.thread.y = y; + this.thread.z = 0; + row[x] = this._fn.apply(this, args); + } + matrix[y] = row; + } + return matrix; +} + +function mock2DGraphical() { + const args = setupArguments(arguments); + for (let y = 0; y < this.output.y; y++) { + for (let x = 0; x < this.output.x; x++) { + this.thread.x = x; + this.thread.y = y; + this.thread.z = 0; + this._fn.apply(this, args); + } + } +} + +function mock3D() { + const args = setupArguments(arguments); + const cube = new Array(this.output.z); + for (let z = 0; z < this.output.z; z++) { + const matrix = new Array(this.output.y); + for (let y = 0; y < this.output.y; y++) { + const row = new Float32Array(this.output.x); + for (let x = 0; x < this.output.x; x++) { + this.thread.x = x; + this.thread.y = y; + this.thread.z = z; + row[x] = this._fn.apply(this, args); + } + matrix[y] = row; + } + cube[z] = matrix; + } + return cube; +} + +function apiDecorate(kernel) { + kernel.setOutput = (output) => { + kernel.output = setupOutput(output); + if (kernel.graphical) { + setupGraphical(kernel); + } + }; + kernel.toJSON = () => { + throw new Error('Not usable with gpuMock'); + }; + kernel.setConstants = (flag) => { + kernel.constants = flag; + return kernel; + }; + kernel.setGraphical = (flag) => { + kernel.graphical = flag; + return kernel; + }; + kernel.setCanvas = (flag) => { + kernel.canvas = flag; + return kernel; + }; + kernel.setContext = (flag) => { + kernel.context = flag; + return kernel; + }; + kernel.destroy = () => {}; + kernel.validateSettings = () => {}; + if (kernel.graphical && kernel.output) { + setupGraphical(kernel); + } + kernel.exec = function() { + return new Promise((resolve, reject) => { + try { + resolve(kernel.apply(kernel, arguments)); + } catch(e) { + reject(e); + } + }); + }; + kernel.getPixels = (flip) => { + const {x, y} = kernel.output; + // cpu is not flipped by default + return flip ? flipPixels(kernel._imageData.data, x, y) : kernel._imageData.data.slice(0); + }; + kernel.color = function(r, g, b, a) { + if (typeof a === 'undefined') { + a = 1; + } + + r = Math.floor(r * 255); + g = Math.floor(g * 255); + b = Math.floor(b * 255); + a = Math.floor(a * 255); + + const width = kernel.output.x; + const height = kernel.output.y; + + const x = kernel.thread.x; + const y = height - kernel.thread.y - 1; + + const index = x + y * width; + + kernel._colorData[index * 4 + 0] = r; + kernel._colorData[index * 4 + 1] = g; + kernel._colorData[index * 4 + 2] = b; + kernel._colorData[index * 4 + 3] = a; + }; + + // these are added for api compatibility, but have no affect + const mockMethod = () => kernel; + const methods = [ + 'setWarnVarUsage', + 'setArgumentTypes', + 'setTactic', + 'setOptimizeFloatMemory', + 'setDebug', + 'setLoopMaxIterations', + 'setConstantTypes', + 'setFunctions', + 'setNativeFunctions', + 'setInjectedNative', + 'setPipeline', + 'setPrecision', + 'setOutputToTexture', + 'setImmutable', + 'setStrictIntegers', + 'setDynamicOutput', + 'setHardcodeConstants', + 'setDynamicArguments', + 'setUseLegacyEncoder', + 'setWarnVarUsage', + 'addSubKernel', + ]; + for (let i = 0; i < methods.length; i++) { + kernel[methods[i]] = mockMethod; + } + return kernel; +} + +function setupGraphical(kernel) { + const {x, y} = kernel.output; + if (kernel.context && kernel.context.createImageData) { + const data = new Uint8ClampedArray(x * y * 4); + kernel._imageData = kernel.context.createImageData(x, y); + kernel._colorData = data; + } else { + const data = new Uint8ClampedArray(x * y * 4); + kernel._imageData = { data }; + kernel._colorData = data; + } +} + +function setupOutput(output) { + let result = null; + if (output.length) { + if (output.length === 3) { + const [x,y,z] = output; + result = { x, y, z }; + } else if (output.length === 2) { + const [x,y] = output; + result = { x, y }; + } else { + const [x] = output; + result = { x }; + } + } else { + result = output; + } + return result; +} + +function gpuMock(fn, settings = {}) { + const output = settings.output ? setupOutput(settings.output) : null; + function kernel() { + if (kernel.output.z) { + return mock3D.apply(kernel, arguments); + } else if (kernel.output.y) { + if (kernel.graphical) { + return mock2DGraphical.apply(kernel, arguments); + } + return mock2D.apply(kernel, arguments); + } else { + return mock1D.apply(kernel, arguments); + } + } + kernel._fn = fn; + kernel.constants = settings.constants || null; + kernel.context = settings.context || null; + kernel.canvas = settings.canvas || null; + kernel.graphical = settings.graphical || false; + kernel._imageData = null; + kernel._colorData = null; + kernel.output = output; + kernel.thread = { + x: 0, + y: 0, + z: 0 + }; + return apiDecorate(kernel); +} + +function flipPixels(pixels, width, height) { + // https://stackoverflow.com/a/41973289/1324039 + const halfHeight = height / 2 | 0; // the | 0 keeps the result an int + const bytesPerRow = width * 4; + // make a temp buffer to hold one row + const temp = new Uint8ClampedArray(width * 4); + const result = pixels.slice(0); + for (let y = 0; y < halfHeight; ++y) { + const topOffset = y * bytesPerRow; + const bottomOffset = (height - y - 1) * bytesPerRow; + + // make copy of a row on the top half + temp.set(result.subarray(topOffset, topOffset + bytesPerRow)); + + // copy a row from the bottom half to the top + result.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow); + + // copy the copy of the top half row to the bottom half + result.set(temp, bottomOffset); + } + return result; +} + +module.exports = { + gpuMock +}; + +},{}],184:[function(require,module,exports){ +const { utils } = require('./utils'); + +/** + * + * @param name + * @param source + * @returns {Function} + */ +function alias(name, source) { + const fnString = source.toString(); + return new Function(`return function ${ name } (${ utils.getArgumentNamesFromString(fnString).join(', ') }) { + ${ utils.getFunctionBodyFromString(fnString) } +}`)(); +} + +module.exports = { + alias +}; +},{"./utils":291}],185:[function(require,module,exports){ +const { FunctionNode } = require('../function-node'); + +/** + * @desc [INTERNAL] Represents a single function, inside JS + * + *

This handles all the raw state, converted state, etc. Of a single function.

+ */ +class CPUFunctionNode extends FunctionNode { + /** + * @desc Parses the abstract syntax tree for to its *named function* + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astFunction(ast, retArr) { + + // Setup function return type and name + if (!this.isRootKernel) { + retArr.push('function'); + retArr.push(' '); + retArr.push(this.name); + retArr.push('('); + + // Arguments handling + for (let i = 0; i < this.argumentNames.length; ++i) { + const argumentName = this.argumentNames[i]; + + if (i > 0) { + retArr.push(', '); + } + retArr.push('user_'); + retArr.push(argumentName); + } + + // Function opening + retArr.push(') {\n'); + } + + // Body statement iteration + for (let i = 0; i < ast.body.body.length; ++i) { + this.astGeneric(ast.body.body[i], retArr); + retArr.push('\n'); + } + + if (!this.isRootKernel) { + // Function closing + retArr.push('}\n'); + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for to *return* statement + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astReturnStatement(ast, retArr) { + const type = this.returnType || this.getType(ast.argument); + + if (!this.returnType) { + this.returnType = type; + } + + if (this.isRootKernel) { + retArr.push(this.leadingReturnStatement); + this.astGeneric(ast.argument, retArr); + retArr.push(';\n'); + retArr.push(this.followingReturnStatement); + retArr.push('continue;\n'); + } else if (this.isSubKernel) { + retArr.push(`subKernelResult_${ this.name } = `); + this.astGeneric(ast.argument, retArr); + retArr.push(';'); + retArr.push(`return subKernelResult_${ this.name };`); + } else { + retArr.push('return '); + this.astGeneric(ast.argument, retArr); + retArr.push(';'); + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *literal value* + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astLiteral(ast, retArr) { + + // Reject non numeric literals + if (isNaN(ast.value)) { + throw this.astErrorOutput( + 'Non-numeric literal not supported : ' + ast.value, + ast + ); + } + + retArr.push(ast.value); + + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *binary* expression + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astBinaryExpression(ast, retArr) { + retArr.push('('); + this.astGeneric(ast.left, retArr); + retArr.push(ast.operator); + this.astGeneric(ast.right, retArr); + retArr.push(')'); + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *identifier* expression + * @param {Object} idtNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astIdentifierExpression(idtNode, retArr) { + if (idtNode.type !== 'Identifier') { + throw this.astErrorOutput( + 'IdentifierExpression - not an Identifier', + idtNode + ); + } + + switch (idtNode.name) { + case 'Infinity': + retArr.push('Infinity'); + break; + default: + if (this.constants && this.constants.hasOwnProperty(idtNode.name)) { + retArr.push('constants_' + idtNode.name); + } else { + retArr.push('user_' + idtNode.name); + } + } + + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *for-loop* expression + * @param {Object} forNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the parsed webgl string + */ + astForStatement(forNode, retArr) { + if (forNode.type !== 'ForStatement') { + throw this.astErrorOutput('Invalid for statement', forNode); + } + + const initArr = []; + const testArr = []; + const updateArr = []; + const bodyArr = []; + let isSafe = null; + + if (forNode.init) { + this.pushState('in-for-loop-init'); + this.astGeneric(forNode.init, initArr); + for (let i = 0; i < initArr.length; i++) { + if (initArr[i].includes && initArr[i].includes(',')) { + isSafe = false; + } + } + this.popState('in-for-loop-init'); + } else { + isSafe = false; + } + + if (forNode.test) { + this.astGeneric(forNode.test, testArr); + } else { + isSafe = false; + } + + if (forNode.update) { + this.astGeneric(forNode.update, updateArr); + } else { + isSafe = false; + } + + if (forNode.body) { + this.pushState('loop-body'); + this.astGeneric(forNode.body, bodyArr); + this.popState('loop-body'); + } + + // have all parts, now make them safe + if (isSafe === null) { + isSafe = this.isSafe(forNode.init) && this.isSafe(forNode.test); + } + + if (isSafe) { + retArr.push(`for (${initArr.join('')};${testArr.join('')};${updateArr.join('')}){\n`); + retArr.push(bodyArr.join('')); + retArr.push('}\n'); + } else { + const iVariableName = this.getInternalVariableName('safeI'); + if (initArr.length > 0) { + retArr.push(initArr.join(''), ';\n'); + } + retArr.push(`for (let ${iVariableName}=0;${iVariableName} 0) { + retArr.push(`if (!${testArr.join('')}) break;\n`); + } + retArr.push(bodyArr.join('')); + retArr.push(`\n${updateArr.join('')};`); + retArr.push('}\n'); + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *while* loop + * @param {Object} whileNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the parsed javascript string + */ + astWhileStatement(whileNode, retArr) { + if (whileNode.type !== 'WhileStatement') { + throw this.astErrorOutput( + 'Invalid while statement', + whileNode + ); + } + + retArr.push('for (let i = 0; i < LOOP_MAX; i++) {'); + retArr.push('if ('); + this.astGeneric(whileNode.test, retArr); + retArr.push(') {\n'); + this.astGeneric(whileNode.body, retArr); + retArr.push('} else {\n'); + retArr.push('break;\n'); + retArr.push('}\n'); + retArr.push('}\n'); + + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *do while* loop + * @param {Object} doWhileNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the parsed webgl string + */ + astDoWhileStatement(doWhileNode, retArr) { + if (doWhileNode.type !== 'DoWhileStatement') { + throw this.astErrorOutput( + 'Invalid while statement', + doWhileNode + ); + } + + retArr.push('for (let i = 0; i < LOOP_MAX; i++) {'); + this.astGeneric(doWhileNode.body, retArr); + retArr.push('if (!'); + this.astGeneric(doWhileNode.test, retArr); + retArr.push(') {\n'); + retArr.push('break;\n'); + retArr.push('}\n'); + retArr.push('}\n'); + + return retArr; + + } + + /** + * @desc Parses the abstract syntax tree for *Assignment* Expression + * @param {Object} assNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astAssignmentExpression(assNode, retArr) { + const declaration = this.getDeclaration(assNode.left); + if (declaration && !declaration.assignable) { + throw this.astErrorOutput(`Variable ${assNode.left.name} is not assignable here`, assNode); + } + this.astGeneric(assNode.left, retArr); + retArr.push(assNode.operator); + this.astGeneric(assNode.right, retArr); + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *Block* statement + * @param {Object} bNode - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astBlockStatement(bNode, retArr) { + if (this.isState('loop-body')) { + this.pushState('block-body'); // this prevents recursive removal of braces + for (let i = 0; i < bNode.body.length; i++) { + this.astGeneric(bNode.body[i], retArr); + } + this.popState('block-body'); + } else { + retArr.push('{\n'); + for (let i = 0; i < bNode.body.length; i++) { + this.astGeneric(bNode.body[i], retArr); + } + retArr.push('}\n'); + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *Variable Declaration* + * @param {Object} varDecNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astVariableDeclaration(varDecNode, retArr) { + retArr.push(`${varDecNode.kind} `); + const { declarations } = varDecNode; + for (let i = 0; i < declarations.length; i++) { + if (i > 0) { + retArr.push(','); + } + const declaration = declarations[i]; + const info = this.getDeclaration(declaration.id); + if (!info.valueType) { + info.valueType = this.getType(declaration.init); + } + this.astGeneric(declaration, retArr); + } + if (!this.isState('in-for-loop-init')) { + retArr.push(';'); + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *If* Statement + * @param {Object} ifNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astIfStatement(ifNode, retArr) { + retArr.push('if ('); + this.astGeneric(ifNode.test, retArr); + retArr.push(')'); + if (ifNode.consequent.type === 'BlockStatement') { + this.astGeneric(ifNode.consequent, retArr); + } else { + retArr.push(' {\n'); + this.astGeneric(ifNode.consequent, retArr); + retArr.push('\n}\n'); + } + + if (ifNode.alternate) { + retArr.push('else '); + if (ifNode.alternate.type === 'BlockStatement' || ifNode.alternate.type === 'IfStatement') { + this.astGeneric(ifNode.alternate, retArr); + } else { + retArr.push(' {\n'); + this.astGeneric(ifNode.alternate, retArr); + retArr.push('\n}\n'); + } + } + return retArr; + + } + + astSwitchStatement(ast, retArr) { + const { discriminant, cases } = ast; + retArr.push('switch ('); + this.astGeneric(discriminant, retArr); + retArr.push(') {\n'); + for (let i = 0; i < cases.length; i++) { + if (cases[i].test === null) { + retArr.push('default:\n'); + this.astGeneric(cases[i].consequent, retArr); + if (cases[i].consequent && cases[i].consequent.length > 0) { + retArr.push('break;\n'); + } + continue; + } + retArr.push('case '); + this.astGeneric(cases[i].test, retArr); + retArr.push(':\n'); + if (cases[i].consequent && cases[i].consequent.length > 0) { + this.astGeneric(cases[i].consequent, retArr); + retArr.push('break;\n'); + } + } + retArr.push('\n}'); + } + + /** + * @desc Parses the abstract syntax tree for *This* expression + * @param {Object} tNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astThisExpression(tNode, retArr) { + retArr.push('_this'); + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *Member* Expression + * @param {Object} mNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astMemberExpression(mNode, retArr) { + const { + signature, + type, + property, + xProperty, + yProperty, + zProperty, + name, + origin + } = this.getMemberExpressionDetails(mNode); + switch (signature) { + case 'this.thread.value': + retArr.push(`_this.thread.${ name }`); + return retArr; + case 'this.output.value': + switch (name) { + case 'x': + retArr.push('outputX'); + break; + case 'y': + retArr.push('outputY'); + break; + case 'z': + retArr.push('outputZ'); + break; + default: + throw this.astErrorOutput('Unexpected expression', mNode); + } + return retArr; + case 'value': + throw this.astErrorOutput('Unexpected expression', mNode); + case 'value[]': + case 'value[][]': + case 'value[][][]': + case 'value.value': + if (origin === 'Math') { + retArr.push(Math[name]); + return retArr; + } + switch (property) { + case 'r': + retArr.push(`user_${ name }[0]`); + return retArr; + case 'g': + retArr.push(`user_${ name }[1]`); + return retArr; + case 'b': + retArr.push(`user_${ name }[2]`); + return retArr; + case 'a': + retArr.push(`user_${ name }[3]`); + return retArr; + } + break; + case 'this.constants.value': + case 'this.constants.value[]': + case 'this.constants.value[][]': + case 'this.constants.value[][][]': + break; + case 'fn()[]': + this.astGeneric(mNode.object, retArr); + retArr.push('['); + this.astGeneric(mNode.property, retArr); + retArr.push(']'); + return retArr; + case 'fn()[][]': + this.astGeneric(mNode.object.object, retArr); + retArr.push('['); + this.astGeneric(mNode.object.property, retArr); + retArr.push(']'); + retArr.push('['); + this.astGeneric(mNode.property, retArr); + retArr.push(']'); + return retArr; + default: + throw this.astErrorOutput('Unexpected expression', mNode); + } + + if (!mNode.computed) { + // handle simple types + switch (type) { + case 'Number': + case 'Integer': + case 'Float': + case 'Boolean': + retArr.push(`${origin}_${name}`); + return retArr; + } + } + + // handle more complex types + // argument may have come from a parent + const markupName = `${origin}_${name}`; + + switch (type) { + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + case 'Matrix(2)': + case 'Matrix(3)': + case 'Matrix(4)': + case 'HTMLImageArray': + case 'ArrayTexture(1)': + case 'ArrayTexture(2)': + case 'ArrayTexture(3)': + case 'ArrayTexture(4)': + case 'HTMLImage': + default: + let size; + let isInput; + if (origin === 'constants') { + const constant = this.constants[name]; + isInput = this.constantTypes[name] === 'Input'; + size = isInput ? constant.size : null; + } else { + isInput = this.isInput(name); + size = isInput ? this.argumentSizes[this.argumentNames.indexOf(name)] : null; + } + retArr.push(`${ markupName }`); + if (zProperty && yProperty) { + if (isInput) { + retArr.push('[('); + this.astGeneric(zProperty, retArr); + retArr.push(`*${ this.dynamicArguments ? '(outputY * outputX)' : size[1] * size[0] })+(`); + this.astGeneric(yProperty, retArr); + retArr.push(`*${ this.dynamicArguments ? 'outputX' : size[0] })+`); + this.astGeneric(xProperty, retArr); + retArr.push(']'); + } else { + retArr.push('['); + this.astGeneric(zProperty, retArr); + retArr.push(']'); + retArr.push('['); + this.astGeneric(yProperty, retArr); + retArr.push(']'); + retArr.push('['); + this.astGeneric(xProperty, retArr); + retArr.push(']'); + } + } else if (yProperty) { + if (isInput) { + retArr.push('[('); + this.astGeneric(yProperty, retArr); + retArr.push(`*${ this.dynamicArguments ? 'outputX' : size[0] })+`); + this.astGeneric(xProperty, retArr); + retArr.push(']'); + } else { + retArr.push('['); + this.astGeneric(yProperty, retArr); + retArr.push(']'); + retArr.push('['); + this.astGeneric(xProperty, retArr); + retArr.push(']'); + } + } else if (typeof xProperty !== 'undefined') { + retArr.push('['); + this.astGeneric(xProperty, retArr); + retArr.push(']'); + } + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *call* expression + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astCallExpression(ast, retArr) { + if (ast.type !== 'CallExpression') { + // Failure, unknown expression + throw this.astErrorOutput('Unknown CallExpression', ast); + } + // Get the full function call, unrolled + let functionName = this.astMemberExpressionUnroll(ast.callee); + + // Register the function into the called registry + if (this.calledFunctions.indexOf(functionName) < 0) { + this.calledFunctions.push(functionName); + } + + const isMathFunction = this.isAstMathFunction(ast); + + // track the function was called + if (this.onFunctionCall) { + this.onFunctionCall(this.name, functionName, ast.arguments); + } + + // Call the function + retArr.push(functionName); + + // Open arguments space + retArr.push('('); + const targetTypes = this.lookupFunctionArgumentTypes(functionName) || []; + // Add the arguments + for (let i = 0; i < ast.arguments.length; ++i) { + const argument = ast.arguments[i]; + + // in order to track return type, even though this is CPU + let argumentType = this.getType(argument); + if (!targetTypes[i]) { + this.triggerImplyArgumentType(functionName, i, argumentType, this); + } + + if (i > 0) { + retArr.push(', '); + } + this.astGeneric(argument, retArr); + } + // Close arguments space + retArr.push(')'); + + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *Array* Expression + * @param {Object} arrNode - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astArrayExpression(arrNode, retArr) { + const returnType = this.getType(arrNode); + const arrLen = arrNode.elements.length; + const elements = []; + for (let i = 0; i < arrLen; ++i) { + const element = []; + this.astGeneric(arrNode.elements[i], element); + elements.push(element.join('')); + } + switch (returnType) { + case 'Matrix(2)': + case 'Matrix(3)': + case 'Matrix(4)': + retArr.push(`[${elements.join(', ')}]`); + break; + default: + retArr.push(`new Float32Array([${elements.join(', ')}])`); + } + return retArr; + } + + astDebuggerStatement(arrNode, retArr) { + retArr.push('debugger;'); + return retArr; + } +} + +module.exports = { + CPUFunctionNode +}; +},{"../function-node":189}],186:[function(require,module,exports){ +const { utils } = require('../../utils'); + +function constantsToString(constants, types) { + const results = []; + for (const name in types) { + if (!types.hasOwnProperty(name)) continue; + const type = types[name]; + const constant = constants[name]; + switch (type) { + case 'Number': + case 'Integer': + case 'Float': + case 'Boolean': + results.push(`${name}:${constant}`); + break; + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + case 'Matrix(2)': + case 'Matrix(3)': + case 'Matrix(4)': + results.push(`${name}:new ${constant.constructor.name}(${JSON.stringify(Array.from(constant))})`); + break; + } + } + return `{ ${ results.join() } }`; +} + +function cpuKernelString(cpuKernel, name) { + const header = []; + const thisProperties = []; + const beforeReturn = []; + + const useFunctionKeyword = !/^function/.test(cpuKernel.color.toString()); + + header.push( + ' const { context, canvas, constants: incomingConstants } = settings;', + ` const output = new Int32Array(${JSON.stringify(Array.from(cpuKernel.output))});`, + ` const _constantTypes = ${JSON.stringify(cpuKernel.constantTypes)};`, + ` const _constants = ${constantsToString(cpuKernel.constants, cpuKernel.constantTypes)};` + ); + + thisProperties.push( + ' constants: _constants,', + ' context,', + ' output,', + ' thread: {x: 0, y: 0, z: 0},' + ); + + if (cpuKernel.graphical) { + header.push(` const _imageData = context.createImageData(${cpuKernel.output[0]}, ${cpuKernel.output[1]});`); + header.push(` const _colorData = new Uint8ClampedArray(${cpuKernel.output[0]} * ${cpuKernel.output[1]} * 4);`); + + const colorFn = utils.flattenFunctionToString((useFunctionKeyword ? 'function ' : '') + cpuKernel.color.toString(), { + thisLookup: (propertyName) => { + switch (propertyName) { + case '_colorData': + return '_colorData'; + case '_imageData': + return '_imageData'; + case 'output': + return 'output'; + case 'thread': + return 'this.thread'; + } + return JSON.stringify(cpuKernel[propertyName]); + }, + findDependency: (object, name) => { + return null; + } + }); + + const getPixelsFn = utils.flattenFunctionToString((useFunctionKeyword ? 'function ' : '') + cpuKernel.getPixels.toString(), { + thisLookup: (propertyName) => { + switch (propertyName) { + case '_colorData': + return '_colorData'; + case '_imageData': + return '_imageData'; + case 'output': + return 'output'; + case 'thread': + return 'this.thread'; + } + return JSON.stringify(cpuKernel[propertyName]); + }, + findDependency: () => { + return null; + } + }); + + thisProperties.push( + ' _imageData,', + ' _colorData,', + ` color: ${colorFn},` + ); + + beforeReturn.push( + ` kernel.getPixels = ${getPixelsFn};` + ); + } + + const constantTypes = []; + const constantKeys = Object.keys(cpuKernel.constantTypes); + for (let i = 0; i < constantKeys.length; i++) { + constantTypes.push(cpuKernel.constantTypes[constantKeys]); + } + if (cpuKernel.argumentTypes.indexOf('HTMLImageArray') !== -1 || constantTypes.indexOf('HTMLImageArray') !== -1) { + const flattenedImageTo3DArray = utils.flattenFunctionToString((useFunctionKeyword ? 'function ' : '') + cpuKernel._imageTo3DArray.toString(), { + doNotDefine: ['canvas'], + findDependency: (object, name) => { + if (object === 'this') { + return (useFunctionKeyword ? 'function ' : '') + cpuKernel[name].toString(); + } + return null; + }, + thisLookup: (propertyName) => { + switch (propertyName) { + case 'canvas': + return; + case 'context': + return 'context'; + } + } + }); + beforeReturn.push(flattenedImageTo3DArray); + thisProperties.push(` _mediaTo2DArray,`); + thisProperties.push(` _imageTo3DArray,`); + } else if (cpuKernel.argumentTypes.indexOf('HTMLImage') !== -1 || constantTypes.indexOf('HTMLImage') !== -1) { + const flattenedImageTo2DArray = utils.flattenFunctionToString((useFunctionKeyword ? 'function ' : '') + cpuKernel._mediaTo2DArray.toString(), { + findDependency: (object, name) => { + return null; + }, + thisLookup: (propertyName) => { + switch (propertyName) { + case 'canvas': + return 'settings.canvas'; + case 'context': + return 'settings.context'; + } + throw new Error('unhandled thisLookup'); + } + }); + beforeReturn.push(flattenedImageTo2DArray); + thisProperties.push(` _mediaTo2DArray,`); + } + + return `function(settings) { +${ header.join('\n') } + for (const p in _constantTypes) { + if (!_constantTypes.hasOwnProperty(p)) continue; + const type = _constantTypes[p]; + switch (type) { + case 'Number': + case 'Integer': + case 'Float': + case 'Boolean': + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + case 'Matrix(2)': + case 'Matrix(3)': + case 'Matrix(4)': + if (incomingConstants.hasOwnProperty(p)) { + console.warn('constant ' + p + ' of type ' + type + ' cannot be resigned'); + } + continue; + } + if (!incomingConstants.hasOwnProperty(p)) { + throw new Error('constant ' + p + ' not found'); + } + _constants[p] = incomingConstants[p]; + } + const kernel = (function() { +${cpuKernel._kernelString} + }) + .apply({ ${thisProperties.join('\n')} }); + ${ beforeReturn.join('\n') } + return kernel; +}`; +} + +module.exports = { + cpuKernelString +}; +},{"../../utils":291}],187:[function(require,module,exports){ +const { Kernel } = require('../kernel'); +const { FunctionBuilder } = require('../function-builder'); +const { CPUFunctionNode } = require('./function-node'); +const { utils } = require('../../utils'); +const { cpuKernelString } = require('./kernel-string'); + +/** + * @desc Kernel Implementation for CPU. + *

Instantiates properties to the CPU Kernel.

+ */ +class CPUKernel extends Kernel { + static getFeatures() { + return this.features; + } + static get features() { + return Object.freeze({ + kernelMap: true, + isIntegerDivisionAccurate: true + }); + } + static get isSupported() { + return true; + } + static isContextMatch(context) { + return false; + } + /** + * @desc The current mode in which gpu.js is executing. + */ + static get mode() { + return 'cpu'; + } + + static nativeFunctionArguments() { + return null; + } + + static nativeFunctionReturnType() { + throw new Error(`Looking up native function return type not supported on ${this.name}`); + } + + static combineKernels(combinedKernel) { + return combinedKernel; + } + + static getSignature(kernel, argumentTypes) { + return 'cpu' + (argumentTypes.length > 0 ? ':' + argumentTypes.join(',') : ''); + } + + constructor(source, settings) { + super(source, settings); + this.mergeSettings(source.settings || settings); + + this._imageData = null; + this._colorData = null; + this._kernelString = null; + this._prependedString = []; + this.thread = { + x: 0, + y: 0, + z: 0 + }; + this.translatedSources = null; + } + + initCanvas() { + if (typeof document !== 'undefined') { + return document.createElement('canvas'); + } else if (typeof OffscreenCanvas !== 'undefined') { + return new OffscreenCanvas(0, 0); + } + } + + initContext() { + if (!this.canvas) return null; + return this.canvas.getContext('2d'); + } + + initPlugins(settings) { + return []; + } + + /** + * @desc Validate settings related to Kernel, such as dimensions size, and auto output support. + * @param {IArguments} args + */ + validateSettings(args) { + if (!this.output || this.output.length === 0) { + if (args.length !== 1) { + throw new Error('Auto output only supported for kernels with only one input'); + } + + const argType = utils.getVariableType(args[0], this.strictIntegers); + if (argType === 'Array') { + this.output = utils.getDimensions(argType); + } else if (argType === 'NumberTexture' || argType === 'ArrayTexture(4)') { + this.output = args[0].output; + } else { + throw new Error('Auto output not supported for input type: ' + argType); + } + } + + if (this.graphical) { + if (this.output.length !== 2) { + throw new Error('Output must have 2 dimensions on graphical mode'); + } + } + + this.checkOutput(); + } + + translateSource() { + this.leadingReturnStatement = this.output.length > 1 ? 'resultX[x] = ' : 'result[x] = '; + if (this.subKernels) { + const followingReturnStatement = []; + for (let i = 0; i < this.subKernels.length; i++) { + const { + name + } = this.subKernels[i]; + followingReturnStatement.push(this.output.length > 1 ? `resultX_${ name }[x] = subKernelResult_${ name };\n` : `result_${ name }[x] = subKernelResult_${ name };\n`); + } + this.followingReturnStatement = followingReturnStatement.join(''); + } + const functionBuilder = FunctionBuilder.fromKernel(this, CPUFunctionNode); + this.translatedSources = functionBuilder.getPrototypes('kernel'); + if (!this.graphical && !this.returnType) { + this.returnType = functionBuilder.getKernelResultType(); + } + } + + /** + * @desc Builds the Kernel, by generating the kernel + * string using thread dimensions, and arguments + * supplied to the kernel. + * + *

If the graphical flag is enabled, canvas is used.

+ */ + build() { + if (this.built) return; + this.setupConstants(); + this.setupArguments(arguments); + this.validateSettings(arguments); + this.translateSource(); + + if (this.graphical) { + const { + canvas, + output + } = this; + if (!canvas) { + throw new Error('no canvas available for using graphical output'); + } + const width = output[0]; + const height = output[1] || 1; + canvas.width = width; + canvas.height = height; + this._imageData = this.context.createImageData(width, height); + this._colorData = new Uint8ClampedArray(width * height * 4); + } + + const kernelString = this.getKernelString(); + this.kernelString = kernelString; + + if (this.debug) { + console.log('Function output:'); + console.log(kernelString); + } + + try { + this.run = new Function([], kernelString).bind(this)(); + } catch (e) { + console.error('An error occurred compiling the javascript: ', e); + } + this.buildSignature(arguments); + this.built = true; + } + + color(r, g, b, a) { + if (typeof a === 'undefined') { + a = 1; + } + + r = Math.floor(r * 255); + g = Math.floor(g * 255); + b = Math.floor(b * 255); + a = Math.floor(a * 255); + + const width = this.output[0]; + const height = this.output[1]; + + const x = this.thread.x; + const y = height - this.thread.y - 1; + + const index = x + y * width; + + this._colorData[index * 4 + 0] = r; + this._colorData[index * 4 + 1] = g; + this._colorData[index * 4 + 2] = b; + this._colorData[index * 4 + 3] = a; + } + + /** + * @desc Generates kernel string for this kernel program. + * + *

If sub-kernels are supplied, they are also factored in. + * This string can be saved by calling the `toString` method + * and then can be reused later.

+ * + * @returns {String} result + * + */ + getKernelString() { + if (this._kernelString !== null) return this._kernelString; + + let kernelThreadString = null; + let { + translatedSources + } = this; + if (translatedSources.length > 1) { + translatedSources = translatedSources.filter(fn => { + if (/^function/.test(fn)) return fn; + kernelThreadString = fn; + return false; + }); + } else { + kernelThreadString = translatedSources.shift(); + } + return this._kernelString = ` const LOOP_MAX = ${ this._getLoopMaxString() }; + ${ this.injectedNative || '' } + const _this = this; + ${ this._resultKernelHeader() } + ${ this._processConstants() } + return (${ this.argumentNames.map(argumentName => 'user_' + argumentName).join(', ') }) => { + ${ this._prependedString.join('') } + ${ this._earlyThrows() } + ${ this._processArguments() } + ${ this.graphical ? this._graphicalKernelBody(kernelThreadString) : this._resultKernelBody(kernelThreadString) } + ${ translatedSources.length > 0 ? translatedSources.join('\n') : '' } + };`; + } + + /** + * @desc Returns the *pre-compiled* Kernel as a JS Object String, that can be reused. + */ + toString() { + return cpuKernelString(this); + } + + /** + * @desc Get the maximum loop size String. + * @returns {String} result + */ + _getLoopMaxString() { + return ( + this.loopMaxIterations ? + ` ${ parseInt(this.loopMaxIterations) };` : + ' 1000;' + ); + } + + _processConstants() { + if (!this.constants) return ''; + + const result = []; + for (let p in this.constants) { + const type = this.constantTypes[p]; + switch (type) { + case 'HTMLCanvas': + case 'HTMLImage': + case 'HTMLVideo': + result.push(` const constants_${p} = this._mediaTo2DArray(this.constants.${p});\n`); + break; + case 'HTMLImageArray': + result.push(` const constants_${p} = this._imageTo3DArray(this.constants.${p});\n`); + break; + case 'Input': + result.push(` const constants_${p} = this.constants.${p}.value;\n`); + break; + default: + result.push(` const constants_${p} = this.constants.${p};\n`); + } + } + return result.join(''); + } + + _earlyThrows() { + if (this.graphical) return ''; + if (this.immutable) return ''; + if (!this.pipeline) return ''; + const arrayArguments = []; + for (let i = 0; i < this.argumentTypes.length; i++) { + if (this.argumentTypes[i] === 'Array') { + arrayArguments.push(this.argumentNames[i]); + } + } + if (arrayArguments.length === 0) return ''; + const checks = []; + for (let i = 0; i < arrayArguments.length; i++) { + const argumentName = arrayArguments[i]; + const checkSubKernels = this._mapSubKernels(subKernel => `user_${argumentName} === result_${subKernel.name}`).join(' || '); + checks.push(`user_${argumentName} === result${checkSubKernels ? ` || ${checkSubKernels}` : ''}`); + } + return `if (${checks.join(' || ')}) throw new Error('Source and destination arrays are the same. Use immutable = true');`; + } + + _processArguments() { + const result = []; + for (let i = 0; i < this.argumentTypes.length; i++) { + const variableName = `user_${this.argumentNames[i]}`; + switch (this.argumentTypes[i]) { + case 'HTMLCanvas': + case 'HTMLImage': + case 'HTMLVideo': + result.push(` ${variableName} = this._mediaTo2DArray(${variableName});\n`); + break; + case 'HTMLImageArray': + result.push(` ${variableName} = this._imageTo3DArray(${variableName});\n`); + break; + case 'Input': + result.push(` ${variableName} = ${variableName}.value;\n`); + break; + case 'ArrayTexture(1)': + case 'ArrayTexture(2)': + case 'ArrayTexture(3)': + case 'ArrayTexture(4)': + case 'NumberTexture': + case 'MemoryOptimizedNumberTexture': + result.push(` + if (${variableName}.toArray) { + if (!_this.textureCache) { + _this.textureCache = []; + _this.arrayCache = []; + } + const textureIndex = _this.textureCache.indexOf(${variableName}); + if (textureIndex !== -1) { + ${variableName} = _this.arrayCache[textureIndex]; + } else { + _this.textureCache.push(${variableName}); + ${variableName} = ${variableName}.toArray(); + _this.arrayCache.push(${variableName}); + } + }`); + break; + } + } + return result.join(''); + } + + _mediaTo2DArray(media) { + const canvas = this.canvas; + const width = media.width > 0 ? media.width : media.videoWidth; + const height = media.height > 0 ? media.height : media.videoHeight; + if (canvas.width < width) { + canvas.width = width; + } + if (canvas.height < height) { + canvas.height = height; + } + const ctx = this.context; + ctx.drawImage(media, 0, 0, width, height); + const pixelsData = ctx.getImageData(0, 0, width, height).data; + const imageArray = new Array(height); + let index = 0; + for (let y = height - 1; y >= 0; y--) { + const row = imageArray[y] = new Array(width); + for (let x = 0; x < width; x++) { + const pixel = new Float32Array(4); + pixel[0] = pixelsData[index++] / 255; // r + pixel[1] = pixelsData[index++] / 255; // g + pixel[2] = pixelsData[index++] / 255; // b + pixel[3] = pixelsData[index++] / 255; // a + row[x] = pixel; + } + } + return imageArray; + } + + /** + * + * @param flip + * @return {Uint8ClampedArray} + */ + getPixels(flip) { + const [width, height] = this.output; + // cpu is not flipped by default + return flip ? utils.flipPixels(this._imageData.data, width, height) : this._imageData.data.slice(0); + } + + _imageTo3DArray(images) { + const imagesArray = new Array(images.length); + for (let i = 0; i < images.length; i++) { + imagesArray[i] = this._mediaTo2DArray(images[i]); + } + return imagesArray; + } + + _resultKernelHeader() { + if (this.graphical) return ''; + if (this.immutable) return ''; + if (!this.pipeline) return ''; + switch (this.output.length) { + case 1: + return this._mutableKernel1DResults(); + case 2: + return this._mutableKernel2DResults(); + case 3: + return this._mutableKernel3DResults(); + } + } + + _resultKernelBody(kernelString) { + switch (this.output.length) { + case 1: + return (!this.immutable && this.pipeline ? this._resultMutableKernel1DLoop(kernelString) : this._resultImmutableKernel1DLoop(kernelString)) + this._kernelOutput(); + case 2: + return (!this.immutable && this.pipeline ? this._resultMutableKernel2DLoop(kernelString) : this._resultImmutableKernel2DLoop(kernelString)) + this._kernelOutput(); + case 3: + return (!this.immutable && this.pipeline ? this._resultMutableKernel3DLoop(kernelString) : this._resultImmutableKernel3DLoop(kernelString)) + this._kernelOutput(); + default: + throw new Error('unsupported size kernel'); + } + } + + _graphicalKernelBody(kernelThreadString) { + switch (this.output.length) { + case 2: + return this._graphicalKernel2DLoop(kernelThreadString) + this._graphicalOutput(); + default: + throw new Error('unsupported size kernel'); + } + } + + _graphicalOutput() { + return ` + this._imageData.data.set(this._colorData); + this.context.putImageData(this._imageData, 0, 0); + return;` + } + + _getKernelResultTypeConstructorString() { + switch (this.returnType) { + case 'LiteralInteger': + case 'Number': + case 'Integer': + case 'Float': + return 'Float32Array'; + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + return 'Array'; + default: + if (this.graphical) { + return 'Float32Array'; + } + throw new Error(`unhandled returnType ${ this.returnType }`); + } + } + + _resultImmutableKernel1DLoop(kernelString) { + const constructorString = this._getKernelResultTypeConstructorString(); + return ` const outputX = _this.output[0]; + const result = new ${constructorString}(outputX); + ${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new ${constructorString}(outputX);\n`).join(' ') } + ${ this._mapSubKernels(subKernel => `let subKernelResult_${ subKernel.name };\n`).join(' ') } + for (let x = 0; x < outputX; x++) { + this.thread.x = x; + this.thread.y = 0; + this.thread.z = 0; + ${ kernelString } + }`; + } + + _mutableKernel1DResults() { + const constructorString = this._getKernelResultTypeConstructorString(); + return ` const outputX = _this.output[0]; + const result = new ${constructorString}(outputX); + ${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new ${constructorString}(outputX);\n`).join(' ') } + ${ this._mapSubKernels(subKernel => `let subKernelResult_${ subKernel.name };\n`).join(' ') }`; + } + + _resultMutableKernel1DLoop(kernelString) { + return ` const outputX = _this.output[0]; + for (let x = 0; x < outputX; x++) { + this.thread.x = x; + this.thread.y = 0; + this.thread.z = 0; + ${ kernelString } + }`; + } + + _resultImmutableKernel2DLoop(kernelString) { + const constructorString = this._getKernelResultTypeConstructorString(); + return ` const outputX = _this.output[0]; + const outputY = _this.output[1]; + const result = new Array(outputY); + ${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new Array(outputY);\n`).join(' ') } + ${ this._mapSubKernels(subKernel => `let subKernelResult_${ subKernel.name };\n`).join(' ') } + for (let y = 0; y < outputY; y++) { + this.thread.z = 0; + this.thread.y = y; + const resultX = result[y] = new ${constructorString}(outputX); + ${ this._mapSubKernels(subKernel => `const resultX_${ subKernel.name } = result_${subKernel.name}[y] = new ${constructorString}(outputX);\n`).join('') } + for (let x = 0; x < outputX; x++) { + this.thread.x = x; + ${ kernelString } + } + }`; + } + + _mutableKernel2DResults() { + const constructorString = this._getKernelResultTypeConstructorString(); + return ` const outputX = _this.output[0]; + const outputY = _this.output[1]; + const result = new Array(outputY); + ${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new Array(outputY);\n`).join(' ') } + ${ this._mapSubKernels(subKernel => `let subKernelResult_${ subKernel.name };\n`).join(' ') } + for (let y = 0; y < outputY; y++) { + const resultX = result[y] = new ${constructorString}(outputX); + ${ this._mapSubKernels(subKernel => `const resultX_${ subKernel.name } = result_${subKernel.name}[y] = new ${constructorString}(outputX);\n`).join('') } + }`; + } + + _resultMutableKernel2DLoop(kernelString) { + const constructorString = this._getKernelResultTypeConstructorString(); + return ` const outputX = _this.output[0]; + const outputY = _this.output[1]; + for (let y = 0; y < outputY; y++) { + this.thread.z = 0; + this.thread.y = y; + const resultX = result[y]; + ${ this._mapSubKernels(subKernel => `const resultX_${ subKernel.name } = result_${subKernel.name}[y] = new ${constructorString}(outputX);\n`).join('') } + for (let x = 0; x < outputX; x++) { + this.thread.x = x; + ${ kernelString } + } + }`; + } + + _graphicalKernel2DLoop(kernelString) { + return ` const outputX = _this.output[0]; + const outputY = _this.output[1]; + for (let y = 0; y < outputY; y++) { + this.thread.z = 0; + this.thread.y = y; + for (let x = 0; x < outputX; x++) { + this.thread.x = x; + ${ kernelString } + } + }`; + } + + _resultImmutableKernel3DLoop(kernelString) { + const constructorString = this._getKernelResultTypeConstructorString(); + return ` const outputX = _this.output[0]; + const outputY = _this.output[1]; + const outputZ = _this.output[2]; + const result = new Array(outputZ); + ${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new Array(outputZ);\n`).join(' ') } + ${ this._mapSubKernels(subKernel => `let subKernelResult_${ subKernel.name };\n`).join(' ') } + for (let z = 0; z < outputZ; z++) { + this.thread.z = z; + const resultY = result[z] = new Array(outputY); + ${ this._mapSubKernels(subKernel => `const resultY_${ subKernel.name } = result_${subKernel.name}[z] = new Array(outputY);\n`).join(' ') } + for (let y = 0; y < outputY; y++) { + this.thread.y = y; + const resultX = resultY[y] = new ${constructorString}(outputX); + ${ this._mapSubKernels(subKernel => `const resultX_${ subKernel.name } = resultY_${subKernel.name}[y] = new ${constructorString}(outputX);\n`).join(' ') } + for (let x = 0; x < outputX; x++) { + this.thread.x = x; + ${ kernelString } + } + } + }`; + } + + _mutableKernel3DResults() { + const constructorString = this._getKernelResultTypeConstructorString(); + return ` const outputX = _this.output[0]; + const outputY = _this.output[1]; + const outputZ = _this.output[2]; + const result = new Array(outputZ); + ${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new Array(outputZ);\n`).join(' ') } + ${ this._mapSubKernels(subKernel => `let subKernelResult_${ subKernel.name };\n`).join(' ') } + for (let z = 0; z < outputZ; z++) { + const resultY = result[z] = new Array(outputY); + ${ this._mapSubKernels(subKernel => `const resultY_${ subKernel.name } = result_${subKernel.name}[z] = new Array(outputY);\n`).join(' ') } + for (let y = 0; y < outputY; y++) { + const resultX = resultY[y] = new ${constructorString}(outputX); + ${ this._mapSubKernels(subKernel => `const resultX_${ subKernel.name } = resultY_${subKernel.name}[y] = new ${constructorString}(outputX);\n`).join(' ') } + } + }`; + } + + _resultMutableKernel3DLoop(kernelString) { + return ` const outputX = _this.output[0]; + const outputY = _this.output[1]; + const outputZ = _this.output[2]; + for (let z = 0; z < outputZ; z++) { + this.thread.z = z; + const resultY = result[z]; + for (let y = 0; y < outputY; y++) { + this.thread.y = y; + const resultX = resultY[y]; + for (let x = 0; x < outputX; x++) { + this.thread.x = x; + ${ kernelString } + } + } + }`; + } + + _kernelOutput() { + if (!this.subKernels) { + return '\n return result;'; + } + return `\n return { + result: result, + ${ this.subKernels.map(subKernel => `${ subKernel.property }: result_${ subKernel.name }`).join(',\n ') } + };`; + } + + _mapSubKernels(fn) { + return this.subKernels === null ? [''] : + this.subKernels.map(fn); + } + + destroy(removeCanvasReference) { + if (removeCanvasReference) { + delete this.canvas; + } + } + + static destroyContext(context) {} + + toJSON() { + const json = super.toJSON(); + json.functionNodes = FunctionBuilder.fromKernel(this, CPUFunctionNode).toJSON(); + return json; + } + + setOutput(output) { + super.setOutput(output); + const [width, height] = this.output; + if (this.graphical) { + this._imageData = this.context.createImageData(width, height); + this._colorData = new Uint8ClampedArray(width * height * 4); + } + } + + prependString(value) { + if (this._kernelString) throw new Error('Kernel already built'); + this._prependedString.push(value); + } + + hasPrependString(value) { + return this._prependedString.indexOf(value) > -1; + } +} + +module.exports = { + CPUKernel +}; +},{"../../utils":291,"../function-builder":188,"../kernel":215,"./function-node":185,"./kernel-string":186}],188:[function(require,module,exports){ +/** + * @desc This handles all the raw state, converted state, etc. of a single function. + * [INTERNAL] A collection of functionNodes. + * @class + */ +class FunctionBuilder { + /** + * + * @param {Kernel} kernel + * @param {FunctionNode} FunctionNode + * @param {object} [extraNodeOptions] + * @returns {FunctionBuilder} + * @static + */ + static fromKernel(kernel, FunctionNode, extraNodeOptions) { + const { + kernelArguments, + kernelConstants, + argumentNames, + argumentSizes, + argumentBitRatios, + constants, + constantBitRatios, + debug, + loopMaxIterations, + nativeFunctions, + output, + optimizeFloatMemory, + precision, + plugins, + source, + subKernels, + functions, + leadingReturnStatement, + followingReturnStatement, + dynamicArguments, + dynamicOutput, + } = kernel; + + const argumentTypes = new Array(kernelArguments.length); + const constantTypes = {}; + + for (let i = 0; i < kernelArguments.length; i++) { + argumentTypes[i] = kernelArguments[i].type; + } + + for (let i = 0; i < kernelConstants.length; i++) { + const kernelConstant = kernelConstants[i]; + constantTypes[kernelConstant.name] = kernelConstant.type; + } + + const needsArgumentType = (functionName, index) => { + return functionBuilder.needsArgumentType(functionName, index); + }; + + const assignArgumentType = (functionName, index, type) => { + functionBuilder.assignArgumentType(functionName, index, type); + }; + + const lookupReturnType = (functionName, ast, requestingNode) => { + return functionBuilder.lookupReturnType(functionName, ast, requestingNode); + }; + + const lookupFunctionArgumentTypes = (functionName) => { + return functionBuilder.lookupFunctionArgumentTypes(functionName); + }; + + const lookupFunctionArgumentName = (functionName, argumentIndex) => { + return functionBuilder.lookupFunctionArgumentName(functionName, argumentIndex); + }; + + const lookupFunctionArgumentBitRatio = (functionName, argumentName) => { + return functionBuilder.lookupFunctionArgumentBitRatio(functionName, argumentName); + }; + + const triggerImplyArgumentType = (functionName, i, argumentType, requestingNode) => { + functionBuilder.assignArgumentType(functionName, i, argumentType, requestingNode); + }; + + const triggerImplyArgumentBitRatio = (functionName, argumentName, calleeFunctionName, argumentIndex) => { + functionBuilder.assignArgumentBitRatio(functionName, argumentName, calleeFunctionName, argumentIndex); + }; + + const onFunctionCall = (functionName, calleeFunctionName, args) => { + functionBuilder.trackFunctionCall(functionName, calleeFunctionName, args); + }; + + const onNestedFunction = (ast, source) => { + const argumentNames = []; + for (let i = 0; i < ast.params.length; i++) { + argumentNames.push(ast.params[i].name); + } + const nestedFunction = new FunctionNode(source, Object.assign({}, nodeOptions, { + returnType: null, + ast, + name: ast.id.name, + argumentNames, + lookupReturnType, + lookupFunctionArgumentTypes, + lookupFunctionArgumentName, + lookupFunctionArgumentBitRatio, + needsArgumentType, + assignArgumentType, + triggerImplyArgumentType, + triggerImplyArgumentBitRatio, + onFunctionCall, + })); + nestedFunction.traceFunctionAST(ast); + functionBuilder.addFunctionNode(nestedFunction); + }; + + const nodeOptions = Object.assign({ + isRootKernel: false, + onNestedFunction, + lookupReturnType, + lookupFunctionArgumentTypes, + lookupFunctionArgumentName, + lookupFunctionArgumentBitRatio, + needsArgumentType, + assignArgumentType, + triggerImplyArgumentType, + triggerImplyArgumentBitRatio, + onFunctionCall, + optimizeFloatMemory, + precision, + constants, + constantTypes, + constantBitRatios, + debug, + loopMaxIterations, + output, + plugins, + dynamicArguments, + dynamicOutput, + }, extraNodeOptions || {}); + + const rootNodeOptions = Object.assign({}, nodeOptions, { + isRootKernel: true, + name: 'kernel', + argumentNames, + argumentTypes, + argumentSizes, + argumentBitRatios, + leadingReturnStatement, + followingReturnStatement, + }); + + if (typeof source === 'object' && source.functionNodes) { + return new FunctionBuilder().fromJSON(source.functionNodes, FunctionNode); + } + + const rootNode = new FunctionNode(source, rootNodeOptions); + + let functionNodes = null; + if (functions) { + functionNodes = functions.map((fn) => new FunctionNode(fn.source, { + returnType: fn.returnType, + argumentTypes: fn.argumentTypes, + output, + plugins, + constants, + constantTypes, + constantBitRatios, + optimizeFloatMemory, + precision, + lookupReturnType, + lookupFunctionArgumentTypes, + lookupFunctionArgumentName, + lookupFunctionArgumentBitRatio, + needsArgumentType, + assignArgumentType, + triggerImplyArgumentType, + triggerImplyArgumentBitRatio, + onFunctionCall, + onNestedFunction, + })); + } + + let subKernelNodes = null; + if (subKernels) { + subKernelNodes = subKernels.map((subKernel) => { + const { name, source } = subKernel; + return new FunctionNode(source, Object.assign({}, nodeOptions, { + name, + isSubKernel: true, + isRootKernel: false, + })); + }); + } + + const functionBuilder = new FunctionBuilder({ + kernel, + rootNode, + functionNodes, + nativeFunctions, + subKernelNodes + }); + + return functionBuilder; + } + + /** + * + * @param {IFunctionBuilderSettings} [settings] + */ + constructor(settings) { + settings = settings || {}; + this.kernel = settings.kernel; + this.rootNode = settings.rootNode; + this.functionNodes = settings.functionNodes || []; + this.subKernelNodes = settings.subKernelNodes || []; + this.nativeFunctions = settings.nativeFunctions || []; + this.functionMap = {}; + this.nativeFunctionNames = []; + this.lookupChain = []; + this.functionNodeDependencies = {}; + this.functionCalls = {}; + + if (this.rootNode) { + this.functionMap['kernel'] = this.rootNode; + } + + if (this.functionNodes) { + for (let i = 0; i < this.functionNodes.length; i++) { + this.functionMap[this.functionNodes[i].name] = this.functionNodes[i]; + } + } + + if (this.subKernelNodes) { + for (let i = 0; i < this.subKernelNodes.length; i++) { + this.functionMap[this.subKernelNodes[i].name] = this.subKernelNodes[i]; + } + } + + if (this.nativeFunctions) { + for (let i = 0; i < this.nativeFunctions.length; i++) { + const nativeFunction = this.nativeFunctions[i]; + this.nativeFunctionNames.push(nativeFunction.name); + } + } + } + + /** + * @desc Add the function node directly + * + * @param {FunctionNode} functionNode - functionNode to add + * + */ + addFunctionNode(functionNode) { + if (!functionNode.name) throw new Error('functionNode.name needs set'); + this.functionMap[functionNode.name] = functionNode; + if (functionNode.isRootKernel) { + this.rootNode = functionNode; + } + } + + /** + * @desc Trace all the depending functions being called, from a single function + * + * This allow for 'unneeded' functions to be automatically optimized out. + * Note that the 0-index, is the starting function trace. + * + * @param {String} functionName - Function name to trace from, default to 'kernel' + * @param {String[]} [retList] - Returning list of function names that is traced. Including itself. + * + * @returns {String[]} Returning list of function names that is traced. Including itself. + */ + traceFunctionCalls(functionName, retList) { + functionName = functionName || 'kernel'; + retList = retList || []; + + if (this.nativeFunctionNames.indexOf(functionName) > -1) { + const nativeFunctionIndex = retList.indexOf(functionName); + if (nativeFunctionIndex === -1) { + retList.push(functionName); + } else { + /** + * https://github.com/gpujs/gpu.js/issues/207 + * if dependent function is already in the list, because a function depends on it, and because it has + * already been traced, we know that we must move the dependent function to the end of the the retList. + * */ + const dependantNativeFunctionName = retList.splice(nativeFunctionIndex, 1)[0]; + retList.push(dependantNativeFunctionName); + } + return retList; + } + + const functionNode = this.functionMap[functionName]; + if (functionNode) { + // Check if function already exists + const functionIndex = retList.indexOf(functionName); + if (functionIndex === -1) { + retList.push(functionName); + functionNode.toString(); //ensure JS trace is done + for (let i = 0; i < functionNode.calledFunctions.length; ++i) { + this.traceFunctionCalls(functionNode.calledFunctions[i], retList); + } + } else { + /** + * https://github.com/gpujs/gpu.js/issues/207 + * if dependent function is already in the list, because a function depends on it, and because it has + * already been traced, we know that we must move the dependent function to the end of the the retList. + * */ + const dependantFunctionName = retList.splice(functionIndex, 1)[0]; + retList.push(dependantFunctionName); + } + } + + return retList; + } + + /** + * @desc Return the string for a function + * @param {String} functionName - Function name to trace from. If null, it returns the WHOLE builder stack + * @returns {String} The full string, of all the various functions. Trace optimized if functionName given + */ + getPrototypeString(functionName) { + return this.getPrototypes(functionName).join('\n'); + } + + /** + * @desc Return the string for a function + * @param {String} [functionName] - Function name to trace from. If null, it returns the WHOLE builder stack + * @returns {Array} The full string, of all the various functions. Trace optimized if functionName given + */ + getPrototypes(functionName) { + if (this.rootNode) { + this.rootNode.toString(); + } + if (functionName) { + return this.getPrototypesFromFunctionNames(this.traceFunctionCalls(functionName, []).reverse()); + } + return this.getPrototypesFromFunctionNames(Object.keys(this.functionMap)); + } + + /** + * @desc Get string from function names + * @param {String[]} functionList - List of function to build string + * @returns {String} The string, of all the various functions. Trace optimized if functionName given + */ + getStringFromFunctionNames(functionList) { + const ret = []; + for (let i = 0; i < functionList.length; ++i) { + const node = this.functionMap[functionList[i]]; + if (node) { + ret.push(this.functionMap[functionList[i]].toString()); + } + } + return ret.join('\n'); + } + + /** + * @desc Return string of all functions converted + * @param {String[]} functionList - List of function names to build the string. + * @returns {Array} Prototypes of all functions converted + */ + getPrototypesFromFunctionNames(functionList) { + const ret = []; + for (let i = 0; i < functionList.length; ++i) { + const functionName = functionList[i]; + const functionIndex = this.nativeFunctionNames.indexOf(functionName); + if (functionIndex > -1) { + ret.push(this.nativeFunctions[functionIndex].source); + continue; + } + const node = this.functionMap[functionName]; + if (node) { + ret.push(node.toString()); + } + } + return ret; + } + + toJSON() { + return this.traceFunctionCalls(this.rootNode.name).reverse().map(name => { + const nativeIndex = this.nativeFunctions.indexOf(name); + if (nativeIndex > -1) { + return { + name, + source: this.nativeFunctions[nativeIndex].source + }; + } else if (this.functionMap[name]) { + return this.functionMap[name].toJSON(); + } else { + throw new Error(`function ${ name } not found`); + } + }); + } + + fromJSON(jsonFunctionNodes, FunctionNode) { + this.functionMap = {}; + for (let i = 0; i < jsonFunctionNodes.length; i++) { + const jsonFunctionNode = jsonFunctionNodes[i]; + this.functionMap[jsonFunctionNode.settings.name] = new FunctionNode(jsonFunctionNode.ast, jsonFunctionNode.settings); + } + return this; + } + + /** + * @desc Get string for a particular function name + * @param {String} functionName - Function name to trace from. If null, it returns the WHOLE builder stack + * @returns {String} settings - The string, of all the various functions. Trace optimized if functionName given + */ + getString(functionName) { + if (functionName) { + return this.getStringFromFunctionNames(this.traceFunctionCalls(functionName).reverse()); + } + return this.getStringFromFunctionNames(Object.keys(this.functionMap)); + } + + lookupReturnType(functionName, ast, requestingNode) { + if (ast.type !== 'CallExpression') { + throw new Error(`expected ast type of "CallExpression", but is ${ ast.type }`); + } + if (this._isNativeFunction(functionName)) { + return this._lookupNativeFunctionReturnType(functionName); + } else if (this._isFunction(functionName)) { + const node = this._getFunction(functionName); + if (node.returnType) { + return node.returnType; + } else { + for (let i = 0; i < this.lookupChain.length; i++) { + // detect circlical logic + if (this.lookupChain[i].ast === ast) { + // detect if arguments have not resolved, preventing a return type + // if so, go ahead and resolve them, so we can resolve the return type + if (node.argumentTypes.length === 0 && ast.arguments.length > 0) { + const args = ast.arguments; + for (let j = 0; j < args.length; j++) { + this.lookupChain.push({ + name: requestingNode.name, + ast: args[i], + requestingNode + }); + node.argumentTypes[j] = requestingNode.getType(args[j]); + this.lookupChain.pop(); + } + return node.returnType = node.getType(node.getJsAST()); + } + + throw new Error('circlical logic detected!'); + } + } + // get ready for a ride! + this.lookupChain.push({ + name: requestingNode.name, + ast, + requestingNode + }); + const type = node.getType(node.getJsAST()); + this.lookupChain.pop(); + return node.returnType = type; + } + } + + return null; + } + + /** + * + * @param {String} functionName + * @return {FunctionNode} + * @private + */ + _getFunction(functionName) { + if (!this._isFunction(functionName)) { + new Error(`Function ${functionName} not found`); + } + return this.functionMap[functionName]; + } + + _isFunction(functionName) { + return Boolean(this.functionMap[functionName]); + } + + _getNativeFunction(functionName) { + for (let i = 0; i < this.nativeFunctions.length; i++) { + if (this.nativeFunctions[i].name === functionName) return this.nativeFunctions[i]; + } + return null; + } + + _isNativeFunction(functionName) { + return Boolean(this._getNativeFunction(functionName)); + } + + _lookupNativeFunctionReturnType(functionName) { + let nativeFunction = this._getNativeFunction(functionName); + if (nativeFunction) { + return nativeFunction.returnType; + } + throw new Error(`Native function ${ functionName } not found`); + } + + lookupFunctionArgumentTypes(functionName) { + if (this._isNativeFunction(functionName)) { + return this._getNativeFunction(functionName).argumentTypes; + } else if (this._isFunction(functionName)) { + return this._getFunction(functionName).argumentTypes; + } + return null; + } + + lookupFunctionArgumentName(functionName, argumentIndex) { + return this._getFunction(functionName).argumentNames[argumentIndex]; + } + + /** + * + * @param {string} functionName + * @param {string} argumentName + * @return {number} + */ + lookupFunctionArgumentBitRatio(functionName, argumentName) { + if (!this._isFunction(functionName)) { + throw new Error('function not found'); + } + if (this.rootNode.name === functionName) { + const i = this.rootNode.argumentNames.indexOf(argumentName); + if (i !== -1) { + return this.rootNode.argumentBitRatios[i]; + } + } + const node = this._getFunction(functionName); + const i = node.argumentNames.indexOf(argumentName); + if (i === -1) { + throw new Error('argument not found'); + } + const bitRatio = node.argumentBitRatios[i]; + if (typeof bitRatio !== 'number') { + throw new Error('argument bit ratio not found'); + } + return bitRatio; + } + + needsArgumentType(functionName, i) { + if (!this._isFunction(functionName)) return false; + const fnNode = this._getFunction(functionName); + return !fnNode.argumentTypes[i]; + } + + assignArgumentType(functionName, i, argumentType, requestingNode) { + if (!this._isFunction(functionName)) return; + const fnNode = this._getFunction(functionName); + if (!fnNode.argumentTypes[i]) { + fnNode.argumentTypes[i] = argumentType; + } + } + + /** + * @param {string} functionName + * @param {string} argumentName + * @param {string} calleeFunctionName + * @param {number} argumentIndex + * @return {number|null} + */ + assignArgumentBitRatio(functionName, argumentName, calleeFunctionName, argumentIndex) { + const node = this._getFunction(functionName); + if (this._isNativeFunction(calleeFunctionName)) return null; + const calleeNode = this._getFunction(calleeFunctionName); + const i = node.argumentNames.indexOf(argumentName); + if (i === -1) { + throw new Error(`Argument ${argumentName} not found in arguments from function ${functionName}`); + } + const bitRatio = node.argumentBitRatios[i]; + if (typeof bitRatio !== 'number') { + throw new Error(`Bit ratio for argument ${argumentName} not found in function ${functionName}`); + } + if (!calleeNode.argumentBitRatios) { + calleeNode.argumentBitRatios = new Array(calleeNode.argumentNames.length); + } + const calleeBitRatio = calleeNode.argumentBitRatios[i]; + if (typeof calleeBitRatio === 'number') { + if (calleeBitRatio !== bitRatio) { + throw new Error(`Incompatible bit ratio found at function ${functionName} at argument ${argumentName}`); + } + return calleeBitRatio; + } + calleeNode.argumentBitRatios[i] = bitRatio; + return bitRatio; + } + + trackFunctionCall(functionName, calleeFunctionName, args) { + if (!this.functionNodeDependencies[functionName]) { + this.functionNodeDependencies[functionName] = new Set(); + this.functionCalls[functionName] = []; + } + this.functionNodeDependencies[functionName].add(calleeFunctionName); + this.functionCalls[functionName].push(args); + } + + getKernelResultType() { + return this.rootNode.returnType || this.rootNode.getType(this.rootNode.ast); + } + + getSubKernelResultType(index) { + const subKernelNode = this.subKernelNodes[index]; + let called = false; + for (let functionCallIndex = 0; functionCallIndex < this.rootNode.functionCalls.length; functionCallIndex++) { + const functionCall = this.rootNode.functionCalls[functionCallIndex]; + if (functionCall.ast.callee.name === subKernelNode.name) { + called = true; + } + } + if (!called) { + throw new Error(`SubKernel ${ subKernelNode.name } never called by kernel`); + } + return subKernelNode.returnType || subKernelNode.getType(subKernelNode.getJsAST()); + } + + getReturnTypes() { + const result = { + [this.rootNode.name]: this.rootNode.getType(this.rootNode.ast), + }; + const list = this.traceFunctionCalls(this.rootNode.name); + for (let i = 0; i < list.length; i++) { + const functionName = list[i]; + const functionNode = this.functionMap[functionName]; + result[functionName] = functionNode.getType(functionNode.ast); + } + return result; + } +} + +module.exports = { + FunctionBuilder +}; +},{}],189:[function(require,module,exports){ +const acorn = require('acorn'); +const { utils } = require('../utils'); +const { FunctionTracer } = require('./function-tracer'); + +/** + * + * @desc Represents a single function, inside JS, webGL, or openGL. + *

This handles all the raw state, converted state, etc. Of a single function.

+ */ +class FunctionNode { + /** + * + * @param {string|object} source + * @param {IFunctionSettings} [settings] + */ + constructor(source, settings) { + if (!source && !settings.ast) { + throw new Error('source parameter is missing'); + } + settings = settings || {}; + this.source = source; + this.ast = null; + this.name = typeof source === 'string' ? settings.isRootKernel ? + 'kernel' : + (settings.name || utils.getFunctionNameFromString(source)) : null; + this.calledFunctions = []; + this.constants = {}; + this.constantTypes = {}; + this.constantBitRatios = {}; + this.isRootKernel = false; + this.isSubKernel = false; + this.debug = null; + this.functions = null; + this.identifiers = null; + this.contexts = null; + this.functionCalls = null; + this.states = []; + this.needsArgumentType = null; + this.assignArgumentType = null; + this.lookupReturnType = null; + this.lookupFunctionArgumentTypes = null; + this.lookupFunctionArgumentBitRatio = null; + this.triggerImplyArgumentType = null; + this.triggerImplyArgumentBitRatio = null; + this.onNestedFunction = null; + this.onFunctionCall = null; + this.optimizeFloatMemory = null; + this.precision = null; + this.loopMaxIterations = null; + this.argumentNames = (typeof this.source === 'string' ? utils.getArgumentNamesFromString(this.source) : null); + this.argumentTypes = []; + this.argumentSizes = []; + this.argumentBitRatios = null; + this.returnType = null; + this.output = []; + this.plugins = null; + this.leadingReturnStatement = null; + this.followingReturnStatement = null; + this.dynamicOutput = null; + this.dynamicArguments = null; + this.strictTypingChecking = false; + this.fixIntegerDivisionAccuracy = null; + + if (settings) { + for (const p in settings) { + if (!settings.hasOwnProperty(p)) continue; + if (!this.hasOwnProperty(p)) continue; + this[p] = settings[p]; + } + } + + this.literalTypes = {}; + + this.validate(); + this._string = null; + this._internalVariableNames = {}; + } + + validate() { + if (typeof this.source !== 'string' && !this.ast) { + throw new Error('this.source not a string'); + } + + if (!this.ast && !utils.isFunctionString(this.source)) { + throw new Error('this.source not a function string'); + } + + if (!this.name) { + throw new Error('this.name could not be set'); + } + + if (this.argumentTypes.length > 0 && this.argumentTypes.length !== this.argumentNames.length) { + throw new Error(`argumentTypes count of ${ this.argumentTypes.length } exceeds ${ this.argumentNames.length }`); + } + + if (this.output.length < 1) { + throw new Error('this.output is not big enough'); + } + } + + /** + * @param {String} name + * @returns {boolean} + */ + isIdentifierConstant(name) { + if (!this.constants) return false; + return this.constants.hasOwnProperty(name); + } + + isInput(argumentName) { + return this.argumentTypes[this.argumentNames.indexOf(argumentName)] === 'Input'; + } + + pushState(state) { + this.states.push(state); + } + + popState(state) { + if (this.state !== state) { + throw new Error(`Cannot popState ${ state } when in ${ this.state }`); + } + this.states.pop(); + } + + isState(state) { + return this.state === state; + } + + get state() { + return this.states[this.states.length - 1]; + } + + /** + * @function + * @name astMemberExpressionUnroll + * @desc Parses the abstract syntax tree for binary expression. + * + *

Utility function for astCallExpression.

+ * + * @param {Object} ast - the AST object to parse + * + * @returns {String} the function namespace call, unrolled + */ + astMemberExpressionUnroll(ast) { + if (ast.type === 'Identifier') { + return ast.name; + } else if (ast.type === 'ThisExpression') { + return 'this'; + } + + if (ast.type === 'MemberExpression') { + if (ast.object && ast.property) { + //babel sniffing + if (ast.object.hasOwnProperty('name') && ast.object.name !== 'Math') { + return this.astMemberExpressionUnroll(ast.property); + } + + return ( + this.astMemberExpressionUnroll(ast.object) + + '.' + + this.astMemberExpressionUnroll(ast.property) + ); + } + } + + //babel sniffing + if (ast.hasOwnProperty('expressions')) { + const firstExpression = ast.expressions[0]; + if (firstExpression.type === 'Literal' && firstExpression.value === 0 && ast.expressions.length === 2) { + return this.astMemberExpressionUnroll(ast.expressions[1]); + } + } + + // Failure, unknown expression + throw this.astErrorOutput('Unknown astMemberExpressionUnroll', ast); + } + + /** + * @desc Parses the class function JS, and returns its Abstract Syntax Tree object. + * This is used internally to convert to shader code + * + * @param {Object} [inParser] - Parser to use, assumes in scope 'parser' if null or undefined + * + * @returns {Object} The function AST Object, note that result is cached under this.ast; + */ + getJsAST(inParser) { + if (this.ast) { + return this.ast; + } + if (typeof this.source === 'object') { + this.traceFunctionAST(this.source); + return this.ast = this.source; + } + + inParser = inParser || acorn; + if (inParser === null) { + throw new Error('Missing JS to AST parser'); + } + + const ast = Object.freeze(inParser.parse(`const parser_${ this.name } = ${ this.source };`, { + locations: true + })); + // take out the function object, outside the var declarations + const functionAST = ast.body[0].declarations[0].init; + this.traceFunctionAST(functionAST); + + if (!ast) { + throw new Error('Failed to parse JS code'); + } + + return this.ast = functionAST; + } + + traceFunctionAST(ast) { + const { contexts, declarations, functions, identifiers, functionCalls } = new FunctionTracer(ast); + this.contexts = contexts; + this.identifiers = identifiers; + this.functionCalls = functionCalls; + this.functions = functions; + for (let i = 0; i < declarations.length; i++) { + const declaration = declarations[i]; + const { ast, inForLoopInit, inForLoopTest } = declaration; + const { init } = ast; + const dependencies = this.getDependencies(init); + let valueType = null; + + if (inForLoopInit && inForLoopTest) { + valueType = 'Integer'; + } else { + if (init) { + const realType = this.getType(init); + switch (realType) { + case 'Integer': + case 'Float': + case 'Number': + if (init.type === 'MemberExpression') { + valueType = realType; + } else { + valueType = 'Number'; + } + break; + case 'LiteralInteger': + valueType = 'Number'; + break; + default: + valueType = realType; + } + } + } + declaration.valueType = valueType; + declaration.dependencies = dependencies; + declaration.isSafe = this.isSafeDependencies(dependencies); + } + + for (let i = 0; i < functions.length; i++) { + this.onNestedFunction(functions[i], this.source); + } + } + + getDeclaration(ast) { + for (let i = 0; i < this.identifiers.length; i++) { + const identifier = this.identifiers[i]; + if (ast === identifier.ast) { + return identifier.declaration; + } + } + return null; + } + + /** + * @desc Return the type of parameter sent to subKernel/Kernel. + * @param {Object} ast - Identifier + * @returns {String} Type of the parameter + */ + getVariableType(ast) { + if (ast.type !== 'Identifier') { + throw new Error(`ast of ${ast.type} not "Identifier"`); + } + let type = null; + const argumentIndex = this.argumentNames.indexOf(ast.name); + if (argumentIndex === -1) { + const declaration = this.getDeclaration(ast); + if (declaration) { + return declaration.valueType; + } + } else { + const argumentType = this.argumentTypes[argumentIndex]; + if (argumentType) { + type = argumentType; + } + } + if (!type && this.strictTypingChecking) { + throw new Error(`Declaration of ${name} not found`); + } + return type; + } + + /** + * Generally used to lookup the value type returned from a member expressions + * @param {String} type + * @return {String} + */ + getLookupType(type) { + if (!typeLookupMap.hasOwnProperty(type)) { + throw new Error(`unknown typeLookupMap ${ type }`); + } + return typeLookupMap[type]; + } + + getConstantType(constantName) { + if (this.constantTypes[constantName]) { + const type = this.constantTypes[constantName]; + if (type === 'Float') { + return 'Number'; + } else { + return type; + } + } + throw new Error(`Type for constant "${ constantName }" not declared`); + } + + toString() { + if (this._string) return this._string; + return this._string = this.astGeneric(this.getJsAST(), []).join('').trim(); + } + + toJSON() { + const settings = { + source: this.source, + name: this.name, + constants: this.constants, + constantTypes: this.constantTypes, + isRootKernel: this.isRootKernel, + isSubKernel: this.isSubKernel, + debug: this.debug, + output: this.output, + loopMaxIterations: this.loopMaxIterations, + argumentNames: this.argumentNames, + argumentTypes: this.argumentTypes, + argumentSizes: this.argumentSizes, + returnType: this.returnType, + leadingReturnStatement: this.leadingReturnStatement, + followingReturnStatement: this.followingReturnStatement, + }; + + return { + ast: this.ast, + settings + }; + } + + /** + * Recursively looks up type for ast expression until it's found + * @param ast + * @returns {String|null} + */ + getType(ast) { + if (Array.isArray(ast)) { + return this.getType(ast[ast.length - 1]); + } + switch (ast.type) { + case 'BlockStatement': + return this.getType(ast.body); + case 'ArrayExpression': + const childType = this.getType(ast.elements[0]); + switch (childType) { + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + return `Matrix(${ast.elements.length})`; + } + return `Array(${ ast.elements.length })`; + case 'Literal': + const literalKey = this.astKey(ast); + if (this.literalTypes[literalKey]) { + return this.literalTypes[literalKey]; + } + if (Number.isInteger(ast.value)) { + return 'LiteralInteger'; + } else if (ast.value === true || ast.value === false) { + return 'Boolean'; + } else { + return 'Number'; + } + case 'AssignmentExpression': + return this.getType(ast.left); + case 'CallExpression': + if (this.isAstMathFunction(ast)) { + return 'Number'; + } + if (!ast.callee || !ast.callee.name) { + if (ast.callee.type === 'SequenceExpression' && ast.callee.expressions[ast.callee.expressions.length - 1].property.name) { + const functionName = ast.callee.expressions[ast.callee.expressions.length - 1].property.name; + this.inferArgumentTypesIfNeeded(functionName, ast.arguments); + return this.lookupReturnType(functionName, ast, this); + } + if (this.getVariableSignature(ast.callee, true) === 'this.color') { + return null; + } + if (ast.callee.type === 'MemberExpression' && ast.callee.object && ast.callee.property && ast.callee.property.name && ast.arguments) { + const functionName = ast.callee.property.name; + this.inferArgumentTypesIfNeeded(functionName, ast.arguments); + return this.lookupReturnType(functionName, ast, this); + } + throw this.astErrorOutput('Unknown call expression', ast); + } + if (ast.callee && ast.callee.name) { + const functionName = ast.callee.name; + this.inferArgumentTypesIfNeeded(functionName, ast.arguments); + return this.lookupReturnType(functionName, ast, this); + } + throw this.astErrorOutput(`Unhandled getType Type "${ ast.type }"`, ast); + case 'LogicalExpression': + return 'Boolean'; + case 'BinaryExpression': + // modulos is Number + switch (ast.operator) { + case '%': + case '/': + if (this.fixIntegerDivisionAccuracy) { + return 'Number'; + } else { + break; + } + case '>': + case '<': + return 'Boolean'; + case '&': + case '|': + case '^': + case '<<': + case '>>': + case '>>>': + return 'Integer'; + } + const type = this.getType(ast.left); + if (this.isState('skip-literal-correction')) return type; + if (type === 'LiteralInteger') { + const rightType = this.getType(ast.right); + if (rightType === 'LiteralInteger') { + if (ast.left.value % 1 === 0) { + return 'Integer'; + } else { + return 'Float'; + } + } + return rightType; + } + return typeLookupMap[type] || type; + case 'UpdateExpression': + return this.getType(ast.argument); + case 'UnaryExpression': + if (ast.operator === '~') { + return 'Integer'; + } + return this.getType(ast.argument); + case 'VariableDeclaration': { + const declarations = ast.declarations; + let lastType; + for (let i = 0; i < declarations.length; i++) { + const declaration = declarations[i]; + lastType = this.getType(declaration); + } + if (!lastType) { + throw this.astErrorOutput(`Unable to find type for declaration`, ast); + } + return lastType; + } + case 'VariableDeclarator': + const declaration = this.getDeclaration(ast.id); + if (!declaration) { + throw this.astErrorOutput(`Unable to find declarator`, ast); + } + + if (!declaration.valueType) { + throw this.astErrorOutput(`Unable to find declarator valueType`, ast); + } + + return declaration.valueType; + case 'Identifier': + if (ast.name === 'Infinity') { + return 'Number'; + } + if (this.isAstVariable(ast)) { + const signature = this.getVariableSignature(ast); + if (signature === 'value') { + return this.getCheckVariableType(ast); + } + } + const origin = this.findIdentifierOrigin(ast); + if (origin && origin.init) { + return this.getType(origin.init); + } + return null; + case 'ReturnStatement': + return this.getType(ast.argument); + case 'MemberExpression': + if (this.isAstMathFunction(ast)) { + switch (ast.property.name) { + case 'ceil': + return 'Integer'; + case 'floor': + return 'Integer'; + case 'round': + return 'Integer'; + } + return 'Number'; + } + if (this.isAstVariable(ast)) { + const variableSignature = this.getVariableSignature(ast); + switch (variableSignature) { + case 'value[]': + return this.getLookupType(this.getCheckVariableType(ast.object)); + case 'value[][]': + return this.getLookupType(this.getCheckVariableType(ast.object.object)); + case 'value[][][]': + return this.getLookupType(this.getCheckVariableType(ast.object.object.object)); + case 'value[][][][]': + return this.getLookupType(this.getCheckVariableType(ast.object.object.object.object)); + case 'value.thread.value': + case 'this.thread.value': + return 'Integer'; + case 'this.output.value': + return this.dynamicOutput ? 'Integer' : 'LiteralInteger'; + case 'this.constants.value': + return this.getConstantType(ast.property.name); + case 'this.constants.value[]': + return this.getLookupType(this.getConstantType(ast.object.property.name)); + case 'this.constants.value[][]': + return this.getLookupType(this.getConstantType(ast.object.object.property.name)); + case 'this.constants.value[][][]': + return this.getLookupType(this.getConstantType(ast.object.object.object.property.name)); + case 'this.constants.value[][][][]': + return this.getLookupType(this.getConstantType(ast.object.object.object.object.property.name)); + case 'fn()[]': + case 'fn()[][]': + case 'fn()[][][]': + return this.getLookupType(this.getType(ast.object)); + case 'value.value': + if (this.isAstMathVariable(ast)) { + return 'Number'; + } + switch (ast.property.name) { + case 'r': + case 'g': + case 'b': + case 'a': + return this.getLookupType(this.getCheckVariableType(ast.object)); + } + case '[][]': + return 'Number'; + } + throw this.astErrorOutput('Unhandled getType MemberExpression', ast); + } + throw this.astErrorOutput('Unhandled getType MemberExpression', ast); + case 'ConditionalExpression': + return this.getType(ast.consequent); + case 'FunctionDeclaration': + case 'FunctionExpression': + const lastReturn = this.findLastReturn(ast.body); + if (lastReturn) { + return this.getType(lastReturn); + } + return null; + case 'IfStatement': + return this.getType(ast.consequent); + case 'SequenceExpression': + return this.getType(ast.expressions[ast.expressions.length - 1]); + default: + throw this.astErrorOutput(`Unhandled getType Type "${ ast.type }"`, ast); + } + } + + getCheckVariableType(ast) { + const type = this.getVariableType(ast); + if (!type) { + throw this.astErrorOutput(`${ast.type} is not defined`, ast); + } + return type; + } + + inferArgumentTypesIfNeeded(functionName, args) { + // ensure arguments are filled in, so when we lookup return type, we already can infer it + for (let i = 0; i < args.length; i++) { + if (!this.needsArgumentType(functionName, i)) continue; + const type = this.getType(args[i]); + if (!type) { + throw this.astErrorOutput(`Unable to infer argument ${i}`, args[i]); + } + this.assignArgumentType(functionName, i, type); + } + } + + isAstMathVariable(ast) { + const mathProperties = [ + 'E', + 'PI', + 'SQRT2', + 'SQRT1_2', + 'LN2', + 'LN10', + 'LOG2E', + 'LOG10E', + ]; + return ast.type === 'MemberExpression' && + ast.object && ast.object.type === 'Identifier' && + ast.object.name === 'Math' && + ast.property && + ast.property.type === 'Identifier' && + mathProperties.indexOf(ast.property.name) > -1; + } + + isAstMathFunction(ast) { + const mathFunctions = [ + 'abs', + 'acos', + 'acosh', + 'asin', + 'asinh', + 'atan', + 'atan2', + 'atanh', + 'cbrt', + 'ceil', + 'clz32', + 'cos', + 'cosh', + 'expm1', + 'exp', + 'floor', + 'fround', + 'imul', + 'log', + 'log2', + 'log10', + 'log1p', + 'max', + 'min', + 'pow', + 'random', + 'round', + 'sign', + 'sin', + 'sinh', + 'sqrt', + 'tan', + 'tanh', + 'trunc', + ]; + return ast.type === 'CallExpression' && + ast.callee && + ast.callee.type === 'MemberExpression' && + ast.callee.object && + ast.callee.object.type === 'Identifier' && + ast.callee.object.name === 'Math' && + ast.callee.property && + ast.callee.property.type === 'Identifier' && + mathFunctions.indexOf(ast.callee.property.name) > -1; + } + + isAstVariable(ast) { + return ast.type === 'Identifier' || ast.type === 'MemberExpression'; + } + + isSafe(ast) { + return this.isSafeDependencies(this.getDependencies(ast)); + } + + isSafeDependencies(dependencies) { + return dependencies && dependencies.every ? dependencies.every(dependency => dependency.isSafe) : true; + } + + /** + * + * @param ast + * @param dependencies + * @param isNotSafe + * @return {Array} + */ + getDependencies(ast, dependencies, isNotSafe) { + if (!dependencies) { + dependencies = []; + } + if (!ast) return null; + if (Array.isArray(ast)) { + for (let i = 0; i < ast.length; i++) { + this.getDependencies(ast[i], dependencies, isNotSafe); + } + return dependencies; + } + switch (ast.type) { + case 'AssignmentExpression': + this.getDependencies(ast.left, dependencies, isNotSafe); + this.getDependencies(ast.right, dependencies, isNotSafe); + return dependencies; + case 'ConditionalExpression': + this.getDependencies(ast.test, dependencies, isNotSafe); + this.getDependencies(ast.alternate, dependencies, isNotSafe); + this.getDependencies(ast.consequent, dependencies, isNotSafe); + return dependencies; + case 'Literal': + dependencies.push({ + origin: 'literal', + value: ast.value, + isSafe: isNotSafe === true ? false : ast.value > -Infinity && ast.value < Infinity && !isNaN(ast.value) + }); + break; + case 'VariableDeclarator': + return this.getDependencies(ast.init, dependencies, isNotSafe); + case 'Identifier': + const declaration = this.getDeclaration(ast); + if (declaration) { + dependencies.push({ + name: ast.name, + origin: 'declaration', + isSafe: isNotSafe ? false : this.isSafeDependencies(declaration.dependencies), + }); + } else if (this.argumentNames.indexOf(ast.name) > -1) { + dependencies.push({ + name: ast.name, + origin: 'argument', + isSafe: false, + }); + } else if (this.strictTypingChecking) { + throw new Error(`Cannot find identifier origin "${ast.name}"`); + } + break; + case 'FunctionDeclaration': + return this.getDependencies(ast.body.body[ast.body.body.length - 1], dependencies, isNotSafe); + case 'ReturnStatement': + return this.getDependencies(ast.argument, dependencies); + case 'BinaryExpression': + case 'LogicalExpression': + isNotSafe = (ast.operator === '/' || ast.operator === '*'); + this.getDependencies(ast.left, dependencies, isNotSafe); + this.getDependencies(ast.right, dependencies, isNotSafe); + return dependencies; + case 'UnaryExpression': + case 'UpdateExpression': + return this.getDependencies(ast.argument, dependencies, isNotSafe); + case 'VariableDeclaration': + return this.getDependencies(ast.declarations, dependencies, isNotSafe); + case 'ArrayExpression': + dependencies.push({ + origin: 'declaration', + isSafe: true, + }); + return dependencies; + case 'CallExpression': + dependencies.push({ + origin: 'function', + isSafe: true, + }); + return dependencies; + case 'MemberExpression': + const details = this.getMemberExpressionDetails(ast); + switch (details.signature) { + case 'value[]': + this.getDependencies(ast.object, dependencies, isNotSafe); + break; + case 'value[][]': + this.getDependencies(ast.object.object, dependencies, isNotSafe); + break; + case 'value[][][]': + this.getDependencies(ast.object.object.object, dependencies, isNotSafe); + break; + case 'this.output.value': + if (this.dynamicOutput) { + dependencies.push({ + name: details.name, + origin: 'output', + isSafe: false, + }); + } + break; + } + if (details) { + if (details.property) { + this.getDependencies(details.property, dependencies, isNotSafe); + } + if (details.xProperty) { + this.getDependencies(details.xProperty, dependencies, isNotSafe); + } + if (details.yProperty) { + this.getDependencies(details.yProperty, dependencies, isNotSafe); + } + if (details.zProperty) { + this.getDependencies(details.zProperty, dependencies, isNotSafe); + } + return dependencies; + } + case 'SequenceExpression': + return this.getDependencies(ast.expressions, dependencies, isNotSafe); + default: + throw this.astErrorOutput(`Unhandled type ${ ast.type } in getDependencies`, ast); + } + return dependencies; + } + + getVariableSignature(ast, returnRawValue) { + if (!this.isAstVariable(ast)) { + throw new Error(`ast of type "${ ast.type }" is not a variable signature`); + } + if (ast.type === 'Identifier') { + return 'value'; + } + const signature = []; + while (true) { + if (!ast) break; + if (ast.computed) { + signature.push('[]'); + } else if (ast.type === 'ThisExpression') { + signature.unshift('this'); + } else if (ast.property && ast.property.name) { + if ( + ast.property.name === 'x' || + ast.property.name === 'y' || + ast.property.name === 'z' + ) { + signature.unshift(returnRawValue ? '.' + ast.property.name : '.value'); + } else if ( + ast.property.name === 'constants' || + ast.property.name === 'thread' || + ast.property.name === 'output' + ) { + signature.unshift('.' + ast.property.name); + } else { + signature.unshift(returnRawValue ? '.' + ast.property.name : '.value'); + } + } else if (ast.name) { + signature.unshift(returnRawValue ? ast.name : 'value'); + } else if (ast.callee && ast.callee.name) { + signature.unshift(returnRawValue ? ast.callee.name + '()' : 'fn()'); + } else if (ast.elements) { + signature.unshift('[]'); + } else { + signature.unshift('unknown'); + } + ast = ast.object; + } + + const signatureString = signature.join(''); + if (returnRawValue) { + return signatureString; + } + + const allowedExpressions = [ + 'value', + 'value[]', + 'value[][]', + 'value[][][]', + 'value[][][][]', + 'value.value', + 'value.thread.value', + 'this.thread.value', + 'this.output.value', + 'this.constants.value', + 'this.constants.value[]', + 'this.constants.value[][]', + 'this.constants.value[][][]', + 'this.constants.value[][][][]', + 'fn()[]', + 'fn()[][]', + 'fn()[][][]', + '[][]', + ]; + if (allowedExpressions.indexOf(signatureString) > -1) { + return signatureString; + } + return null; + } + + build() { + return this.toString().length > 0; + } + + /** + * @desc Parses the abstract syntax tree for generically to its respective function + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the parsed string array + */ + astGeneric(ast, retArr) { + if (ast === null) { + throw this.astErrorOutput('NULL ast', ast); + } else { + if (Array.isArray(ast)) { + for (let i = 0; i < ast.length; i++) { + this.astGeneric(ast[i], retArr); + } + return retArr; + } + + switch (ast.type) { + case 'FunctionDeclaration': + return this.astFunctionDeclaration(ast, retArr); + case 'FunctionExpression': + return this.astFunctionExpression(ast, retArr); + case 'ReturnStatement': + return this.astReturnStatement(ast, retArr); + case 'Literal': + return this.astLiteral(ast, retArr); + case 'BinaryExpression': + return this.astBinaryExpression(ast, retArr); + case 'Identifier': + return this.astIdentifierExpression(ast, retArr); + case 'AssignmentExpression': + return this.astAssignmentExpression(ast, retArr); + case 'ExpressionStatement': + return this.astExpressionStatement(ast, retArr); + case 'EmptyStatement': + return this.astEmptyStatement(ast, retArr); + case 'BlockStatement': + return this.astBlockStatement(ast, retArr); + case 'IfStatement': + return this.astIfStatement(ast, retArr); + case 'SwitchStatement': + return this.astSwitchStatement(ast, retArr); + case 'BreakStatement': + return this.astBreakStatement(ast, retArr); + case 'ContinueStatement': + return this.astContinueStatement(ast, retArr); + case 'ForStatement': + return this.astForStatement(ast, retArr); + case 'WhileStatement': + return this.astWhileStatement(ast, retArr); + case 'DoWhileStatement': + return this.astDoWhileStatement(ast, retArr); + case 'VariableDeclaration': + return this.astVariableDeclaration(ast, retArr); + case 'VariableDeclarator': + return this.astVariableDeclarator(ast, retArr); + case 'ThisExpression': + return this.astThisExpression(ast, retArr); + case 'SequenceExpression': + return this.astSequenceExpression(ast, retArr); + case 'UnaryExpression': + return this.astUnaryExpression(ast, retArr); + case 'UpdateExpression': + return this.astUpdateExpression(ast, retArr); + case 'LogicalExpression': + return this.astLogicalExpression(ast, retArr); + case 'MemberExpression': + return this.astMemberExpression(ast, retArr); + case 'CallExpression': + return this.astCallExpression(ast, retArr); + case 'ArrayExpression': + return this.astArrayExpression(ast, retArr); + case 'DebuggerStatement': + return this.astDebuggerStatement(ast, retArr); + case 'ConditionalExpression': + return this.astConditionalExpression(ast, retArr); + } + + throw this.astErrorOutput('Unknown ast type : ' + ast.type, ast); + } + } + /** + * @desc To throw the AST error, with its location. + * @param {string} error - the error message output + * @param {Object} ast - the AST object where the error is + */ + astErrorOutput(error, ast) { + if (typeof this.source !== 'string') { + return new Error(error); + } + + const debugString = utils.getAstString(this.source, ast); + const leadingSource = this.source.substr(ast.start); + const splitLines = leadingSource.split(/\n/); + const lineBefore = splitLines.length > 0 ? splitLines[splitLines.length - 1] : 0; + return new Error(`${error} on line ${ splitLines.length }, position ${ lineBefore.length }:\n ${ debugString }`); + } + + astDebuggerStatement(arrNode, retArr) { + return retArr; + } + + astConditionalExpression(ast, retArr) { + if (ast.type !== 'ConditionalExpression') { + throw this.astErrorOutput('Not a conditional expression', ast); + } + retArr.push('('); + this.astGeneric(ast.test, retArr); + retArr.push('?'); + this.astGeneric(ast.consequent, retArr); + retArr.push(':'); + this.astGeneric(ast.alternate, retArr); + retArr.push(')'); + return retArr; + } + + /** + * @abstract + * @param {Object} ast + * @param {String[]} retArr + * @returns {String[]} + */ + astFunction(ast, retArr) { + throw new Error(`"astFunction" not defined on ${ this.constructor.name }`); + } + + /** + * @desc Parses the abstract syntax tree for to its *named function declaration* + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astFunctionDeclaration(ast, retArr) { + if (this.isChildFunction(ast)) { + return retArr; + } + return this.astFunction(ast, retArr); + } + astFunctionExpression(ast, retArr) { + if (this.isChildFunction(ast)) { + return retArr; + } + return this.astFunction(ast, retArr); + } + isChildFunction(ast) { + for (let i = 0; i < this.functions.length; i++) { + if (this.functions[i] === ast) { + return true; + } + } + return false; + } + astReturnStatement(ast, retArr) { + return retArr; + } + astLiteral(ast, retArr) { + this.literalTypes[this.astKey(ast)] = 'Number'; + return retArr; + } + astBinaryExpression(ast, retArr) { + return retArr; + } + astIdentifierExpression(ast, retArr) { + return retArr; + } + astAssignmentExpression(ast, retArr) { + return retArr; + } + /** + * @desc Parses the abstract syntax tree for *generic expression* statement + * @param {Object} esNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astExpressionStatement(esNode, retArr) { + this.astGeneric(esNode.expression, retArr); + retArr.push(';'); + return retArr; + } + /** + * @desc Parses the abstract syntax tree for an *Empty* Statement + * @param {Object} eNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astEmptyStatement(eNode, retArr) { + return retArr; + } + astBlockStatement(ast, retArr) { + return retArr; + } + astIfStatement(ast, retArr) { + return retArr; + } + astSwitchStatement(ast, retArr) { + return retArr; + } + /** + * @desc Parses the abstract syntax tree for *Break* Statement + * @param {Object} brNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astBreakStatement(brNode, retArr) { + retArr.push('break;'); + return retArr; + } + /** + * @desc Parses the abstract syntax tree for *Continue* Statement + * @param {Object} crNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astContinueStatement(crNode, retArr) { + retArr.push('continue;\n'); + return retArr; + } + astForStatement(ast, retArr) { + return retArr; + } + astWhileStatement(ast, retArr) { + return retArr; + } + astDoWhileStatement(ast, retArr) { + return retArr; + } + /** + * @desc Parses the abstract syntax tree for *Variable Declarator* + * @param {Object} iVarDecNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astVariableDeclarator(iVarDecNode, retArr) { + this.astGeneric(iVarDecNode.id, retArr); + if (iVarDecNode.init !== null) { + retArr.push('='); + this.astGeneric(iVarDecNode.init, retArr); + } + return retArr; + } + astThisExpression(ast, retArr) { + return retArr; + } + astSequenceExpression(sNode, retArr) { + const { expressions } = sNode; + const sequenceResult = []; + for (let i = 0; i < expressions.length; i++) { + const expression = expressions[i]; + const expressionResult = []; + this.astGeneric(expression, expressionResult); + sequenceResult.push(expressionResult.join('')); + } + if (sequenceResult.length > 1) { + retArr.push('(', sequenceResult.join(','), ')'); + } else { + retArr.push(sequenceResult[0]); + } + return retArr; + } + /** + * @desc Parses the abstract syntax tree for *Unary* Expression + * @param {Object} uNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astUnaryExpression(uNode, retArr) { + const unaryResult = this.checkAndUpconvertBitwiseUnary(uNode, retArr); + if (unaryResult) { + return retArr; + } + + if (uNode.prefix) { + retArr.push(uNode.operator); + this.astGeneric(uNode.argument, retArr); + } else { + this.astGeneric(uNode.argument, retArr); + retArr.push(uNode.operator); + } + + return retArr; + } + + checkAndUpconvertBitwiseUnary(uNode, retArr) {} + + /** + * @desc Parses the abstract syntax tree for *Update* Expression + * @param {Object} uNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astUpdateExpression(uNode, retArr) { + if (uNode.prefix) { + retArr.push(uNode.operator); + this.astGeneric(uNode.argument, retArr); + } else { + this.astGeneric(uNode.argument, retArr); + retArr.push(uNode.operator); + } + + return retArr; + } + /** + * @desc Parses the abstract syntax tree for *Logical* Expression + * @param {Object} logNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astLogicalExpression(logNode, retArr) { + retArr.push('('); + this.astGeneric(logNode.left, retArr); + retArr.push(logNode.operator); + this.astGeneric(logNode.right, retArr); + retArr.push(')'); + return retArr; + } + astMemberExpression(ast, retArr) { + return retArr; + } + astCallExpression(ast, retArr) { + return retArr; + } + astArrayExpression(ast, retArr) { + return retArr; + } + + /** + * + * @param ast + * @return {IFunctionNodeMemberExpressionDetails} + */ + getMemberExpressionDetails(ast) { + if (ast.type !== 'MemberExpression') { + throw this.astErrorOutput(`Expression ${ ast.type } not a MemberExpression`, ast); + } + let name = null; + let type = null; + const variableSignature = this.getVariableSignature(ast); + switch (variableSignature) { + case 'value': + return null; + case 'value.thread.value': + case 'this.thread.value': + case 'this.output.value': + return { + signature: variableSignature, + type: 'Integer', + name: ast.property.name + }; + case 'value[]': + if (typeof ast.object.name !== 'string') { + throw this.astErrorOutput('Unexpected expression', ast); + } + name = ast.object.name; + return { + name, + origin: 'user', + signature: variableSignature, + type: this.getVariableType(ast.object), + xProperty: ast.property + }; + case 'value[][]': + if (typeof ast.object.object.name !== 'string') { + throw this.astErrorOutput('Unexpected expression', ast); + } + name = ast.object.object.name; + return { + name, + origin: 'user', + signature: variableSignature, + type: this.getVariableType(ast.object.object), + yProperty: ast.object.property, + xProperty: ast.property, + }; + case 'value[][][]': + if (typeof ast.object.object.object.name !== 'string') { + throw this.astErrorOutput('Unexpected expression', ast); + } + name = ast.object.object.object.name; + return { + name, + origin: 'user', + signature: variableSignature, + type: this.getVariableType(ast.object.object.object), + zProperty: ast.object.object.property, + yProperty: ast.object.property, + xProperty: ast.property, + }; + case 'value[][][][]': + if (typeof ast.object.object.object.object.name !== 'string') { + throw this.astErrorOutput('Unexpected expression', ast); + } + name = ast.object.object.object.object.name; + return { + name, + origin: 'user', + signature: variableSignature, + type: this.getVariableType(ast.object.object.object.object), + zProperty: ast.object.object.property, + yProperty: ast.object.property, + xProperty: ast.property, + }; + case 'value.value': + if (typeof ast.property.name !== 'string') { + throw this.astErrorOutput('Unexpected expression', ast); + } + if (this.isAstMathVariable(ast)) { + name = ast.property.name; + return { + name, + origin: 'Math', + type: 'Number', + signature: variableSignature, + }; + } + switch (ast.property.name) { + case 'r': + case 'g': + case 'b': + case 'a': + name = ast.object.name; + return { + name, + property: ast.property.name, + origin: 'user', + signature: variableSignature, + type: 'Number' + }; + default: + throw this.astErrorOutput('Unexpected expression', ast); + } + case 'this.constants.value': + if (typeof ast.property.name !== 'string') { + throw this.astErrorOutput('Unexpected expression', ast); + } + name = ast.property.name; + type = this.getConstantType(name); + if (!type) { + throw this.astErrorOutput('Constant has no type', ast); + } + return { + name, + type, + origin: 'constants', + signature: variableSignature, + }; + case 'this.constants.value[]': + if (typeof ast.object.property.name !== 'string') { + throw this.astErrorOutput('Unexpected expression', ast); + } + name = ast.object.property.name; + type = this.getConstantType(name); + if (!type) { + throw this.astErrorOutput('Constant has no type', ast); + } + return { + name, + type, + origin: 'constants', + signature: variableSignature, + xProperty: ast.property, + }; + case 'this.constants.value[][]': { + if (typeof ast.object.object.property.name !== 'string') { + throw this.astErrorOutput('Unexpected expression', ast); + } + name = ast.object.object.property.name; + type = this.getConstantType(name); + if (!type) { + throw this.astErrorOutput('Constant has no type', ast); + } + return { + name, + type, + origin: 'constants', + signature: variableSignature, + yProperty: ast.object.property, + xProperty: ast.property, + }; + } + case 'this.constants.value[][][]': { + if (typeof ast.object.object.object.property.name !== 'string') { + throw this.astErrorOutput('Unexpected expression', ast); + } + name = ast.object.object.object.property.name; + type = this.getConstantType(name); + if (!type) { + throw this.astErrorOutput('Constant has no type', ast); + } + return { + name, + type, + origin: 'constants', + signature: variableSignature, + zProperty: ast.object.object.property, + yProperty: ast.object.property, + xProperty: ast.property, + }; + } + case 'fn()[]': + case 'fn()[][]': + case '[][]': + return { + signature: variableSignature, + property: ast.property, + }; + default: + throw this.astErrorOutput('Unexpected expression', ast); + } + } + + findIdentifierOrigin(astToFind) { + const stack = [this.ast]; + + while (stack.length > 0) { + const atNode = stack[0]; + if (atNode.type === 'VariableDeclarator' && atNode.id && atNode.id.name && atNode.id.name === astToFind.name) { + return atNode; + } + stack.shift(); + if (atNode.argument) { + stack.push(atNode.argument); + } else if (atNode.body) { + stack.push(atNode.body); + } else if (atNode.declarations) { + stack.push(atNode.declarations); + } else if (Array.isArray(atNode)) { + for (let i = 0; i < atNode.length; i++) { + stack.push(atNode[i]); + } + } + } + return null; + } + + findLastReturn(ast) { + const stack = [ast || this.ast]; + + while (stack.length > 0) { + const atNode = stack.pop(); + if (atNode.type === 'ReturnStatement') { + return atNode; + } + if (atNode.type === 'FunctionDeclaration') { + continue; + } + if (atNode.argument) { + stack.push(atNode.argument); + } else if (atNode.body) { + stack.push(atNode.body); + } else if (atNode.declarations) { + stack.push(atNode.declarations); + } else if (Array.isArray(atNode)) { + for (let i = 0; i < atNode.length; i++) { + stack.push(atNode[i]); + } + } else if (atNode.consequent) { + stack.push(atNode.consequent); + } else if (atNode.cases) { + stack.push(atNode.cases); + } + } + return null; + } + + getInternalVariableName(name) { + if (!this._internalVariableNames.hasOwnProperty(name)) { + this._internalVariableNames[name] = 0; + } + this._internalVariableNames[name]++; + if (this._internalVariableNames[name] === 1) { + return name; + } + return name + this._internalVariableNames[name]; + } + + astKey(ast, separator = ',') { + if (!ast.start || !ast.end) throw new Error('AST start and end needed'); + return `${ast.start}${separator}${ast.end}`; + } +} + +const typeLookupMap = { + 'Number': 'Number', + 'Float': 'Float', + 'Integer': 'Integer', + 'Array': 'Number', + 'Array(2)': 'Number', + 'Array(3)': 'Number', + 'Array(4)': 'Number', + 'Matrix(2)': 'Number', + 'Matrix(3)': 'Number', + 'Matrix(4)': 'Number', + 'Array2D': 'Number', + 'Array3D': 'Number', + 'Input': 'Number', + 'HTMLCanvas': 'Array(4)', + 'HTMLImage': 'Array(4)', + 'HTMLVideo': 'Array(4)', + 'HTMLImageArray': 'Array(4)', + 'NumberTexture': 'Number', + 'MemoryOptimizedNumberTexture': 'Number', + 'Array1D(2)': 'Array(2)', + 'Array1D(3)': 'Array(3)', + 'Array1D(4)': 'Array(4)', + 'Array2D(2)': 'Array(2)', + 'Array2D(3)': 'Array(3)', + 'Array2D(4)': 'Array(4)', + 'Array3D(2)': 'Array(2)', + 'Array3D(3)': 'Array(3)', + 'Array3D(4)': 'Array(4)', + 'ArrayTexture(1)': 'Number', + 'ArrayTexture(2)': 'Array(2)', + 'ArrayTexture(3)': 'Array(3)', + 'ArrayTexture(4)': 'Array(4)', +}; + +module.exports = { + FunctionNode +}; +},{"../utils":291,"./function-tracer":190,"acorn":23}],190:[function(require,module,exports){ +const { utils } = require('../utils'); + +function last(array) { + return array.length > 0 ? array[array.length - 1] : null; +} + +const states = { + trackIdentifiers: 'trackIdentifiers', + memberExpression: 'memberExpression', + inForLoopInit: 'inForLoopInit' +}; + +class FunctionTracer { + constructor(ast) { + this.runningContexts = []; + this.functionContexts = []; + this.contexts = []; + this.functionCalls = []; + /** + * + * @type {IDeclaration[]} + */ + this.declarations = []; + this.identifiers = []; + this.functions = []; + this.returnStatements = []; + this.trackedIdentifiers = null; + this.states = []; + this.newFunctionContext(); + this.scan(ast); + } + + isState(state) { + return this.states[this.states.length - 1] === state; + } + + hasState(state) { + return this.states.indexOf(state) > -1; + } + + pushState(state) { + this.states.push(state); + } + + popState(state) { + if (this.isState(state)) { + this.states.pop(); + } else { + throw new Error(`Cannot pop the non-active state "${state}"`); + } + } + + get currentFunctionContext() { + return last(this.functionContexts); + } + + get currentContext() { + return last(this.runningContexts); + } + + newFunctionContext() { + const newContext = { '@contextType': 'function' }; + this.contexts.push(newContext); + this.functionContexts.push(newContext); + } + + newContext(run) { + const newContext = Object.assign({ '@contextType': 'const/let' }, this.currentContext); + this.contexts.push(newContext); + this.runningContexts.push(newContext); + run(); + const { currentFunctionContext } = this; + for (const p in currentFunctionContext) { + if (!currentFunctionContext.hasOwnProperty(p) || newContext.hasOwnProperty(p)) continue; + newContext[p] = currentFunctionContext[p]; + } + this.runningContexts.pop(); + return newContext; + } + + useFunctionContext(run) { + const functionContext = last(this.functionContexts); + this.runningContexts.push(functionContext); + run(); + this.runningContexts.pop(); + } + + getIdentifiers(run) { + const trackedIdentifiers = this.trackedIdentifiers = []; + this.pushState(states.trackIdentifiers); + run(); + this.trackedIdentifiers = null; + this.popState(states.trackIdentifiers); + return trackedIdentifiers; + } + + /** + * @param {string} name + * @returns {IDeclaration} + */ + getDeclaration(name) { + const { currentContext, currentFunctionContext, runningContexts } = this; + const declaration = currentContext[name] || currentFunctionContext[name] || null; + + if ( + !declaration && + currentContext === currentFunctionContext && + runningContexts.length > 0 + ) { + const previousRunningContext = runningContexts[runningContexts.length - 2]; + if (previousRunningContext[name]) { + return previousRunningContext[name]; + } + } + + return declaration; + } + + /** + * Recursively scans AST for declarations and functions, and add them to their respective context + * @param ast + */ + scan(ast) { + if (!ast) return; + if (Array.isArray(ast)) { + for (let i = 0; i < ast.length; i++) { + this.scan(ast[i]); + } + return; + } + switch (ast.type) { + case 'Program': + this.useFunctionContext(() => { + this.scan(ast.body); + }); + break; + case 'BlockStatement': + this.newContext(() => { + this.scan(ast.body); + }); + break; + case 'AssignmentExpression': + case 'LogicalExpression': + this.scan(ast.left); + this.scan(ast.right); + break; + case 'BinaryExpression': + this.scan(ast.left); + this.scan(ast.right); + break; + case 'UpdateExpression': + if (ast.operator === '++') { + const declaration = this.getDeclaration(ast.argument.name); + if (declaration) { + declaration.suggestedType = 'Integer'; + } + } + this.scan(ast.argument); + break; + case 'UnaryExpression': + this.scan(ast.argument); + break; + case 'VariableDeclaration': + if (ast.kind === 'var') { + this.useFunctionContext(() => { + ast.declarations = utils.normalizeDeclarations(ast); + this.scan(ast.declarations); + }); + } else { + ast.declarations = utils.normalizeDeclarations(ast); + this.scan(ast.declarations); + } + break; + case 'VariableDeclarator': { + const { currentContext } = this; + const inForLoopInit = this.hasState(states.inForLoopInit); + const declaration = { + ast: ast, + context: currentContext, + name: ast.id.name, + origin: 'declaration', + inForLoopInit, + inForLoopTest: null, + assignable: currentContext === this.currentFunctionContext || (!inForLoopInit && !currentContext.hasOwnProperty(ast.id.name)), + suggestedType: null, + valueType: null, + dependencies: null, + isSafe: null, + }; + if (!currentContext[ast.id.name]) { + currentContext[ast.id.name] = declaration; + } + this.declarations.push(declaration); + this.scan(ast.id); + this.scan(ast.init); + break; + } + case 'FunctionExpression': + case 'FunctionDeclaration': + if (this.runningContexts.length === 0) { + this.scan(ast.body); + } else { + this.functions.push(ast); + } + break; + case 'IfStatement': + this.scan(ast.test); + this.scan(ast.consequent); + if (ast.alternate) this.scan(ast.alternate); + break; + case 'ForStatement': { + let testIdentifiers; + const context = this.newContext(() => { + this.pushState(states.inForLoopInit); + this.scan(ast.init); + this.popState(states.inForLoopInit); + + testIdentifiers = this.getIdentifiers(() => { + this.scan(ast.test); + }); + + this.scan(ast.update); + this.newContext(() => { + this.scan(ast.body); + }); + }); + + if (testIdentifiers) { + for (const p in context) { + if (p === '@contextType') continue; + if (testIdentifiers.indexOf(p) > -1) { + context[p].inForLoopTest = true; + } + } + } + break; + } + case 'DoWhileStatement': + case 'WhileStatement': + this.newContext(() => { + this.scan(ast.body); + this.scan(ast.test); + }); + break; + case 'Identifier': { + if (this.isState(states.trackIdentifiers)) { + this.trackedIdentifiers.push(ast.name); + } + this.identifiers.push({ + context: this.currentContext, + declaration: this.getDeclaration(ast.name), + ast, + }); + break; + } + case 'ReturnStatement': + this.returnStatements.push(ast); + this.scan(ast.argument); + break; + case 'MemberExpression': + this.pushState(states.memberExpression); + this.scan(ast.object); + this.scan(ast.property); + this.popState(states.memberExpression); + break; + case 'ExpressionStatement': + this.scan(ast.expression); + break; + case 'SequenceExpression': + this.scan(ast.expressions); + break; + case 'CallExpression': + this.functionCalls.push({ + context: this.currentContext, + ast, + }); + this.scan(ast.arguments); + break; + case 'ArrayExpression': + this.scan(ast.elements); + break; + case 'ConditionalExpression': + this.scan(ast.test); + this.scan(ast.alternate); + this.scan(ast.consequent); + break; + case 'SwitchStatement': + this.scan(ast.discriminant); + this.scan(ast.cases); + break; + case 'SwitchCase': + this.scan(ast.test); + this.scan(ast.consequent); + break; + + case 'ThisExpression': + case 'Literal': + case 'DebuggerStatement': + case 'EmptyStatement': + case 'BreakStatement': + case 'ContinueStatement': + break; + default: + throw new Error(`unhandled type "${ast.type}"`); + } + } +} + +module.exports = { + FunctionTracer, +}; +},{"../utils":291}],191:[function(require,module,exports){ +const { glWiretap } = require('gl-wiretap'); +const { utils } = require('../../utils'); + +function toStringWithoutUtils(fn) { + return fn.toString() + .replace('=>', '') + .replace(/^function /, '') + .replace(/utils[.]/g, '/*utils.*/'); +} + +/** + * + * @param {GLKernel} Kernel + * @param {KernelVariable[]} args + * @param {Kernel} originKernel + * @param {string} [setupContextString] + * @param {string} [destroyContextString] + * @returns {string} + */ +function glKernelString(Kernel, args, originKernel, setupContextString, destroyContextString) { + if (!originKernel.built) { + originKernel.build.apply(originKernel, args); + } + args = args ? Array.from(args).map(arg => { + switch (typeof arg) { + case 'boolean': + return new Boolean(arg); + case 'number': + return new Number(arg); + default: + return arg; + } + }) : null; + const uploadedValues = []; + const postResult = []; + const context = glWiretap(originKernel.context, { + useTrackablePrimitives: true, + onReadPixels: (targetName) => { + if (kernel.subKernels) { + if (!subKernelsResultVariableSetup) { + postResult.push(` const result = { result: ${getRenderString(targetName, kernel)} };`); + subKernelsResultVariableSetup = true; + } else { + const property = kernel.subKernels[subKernelsResultIndex++].property; + postResult.push(` result${isNaN(property) ? '.' + property : `[${property}]`} = ${getRenderString(targetName, kernel)};`); + } + if (subKernelsResultIndex === kernel.subKernels.length) { + postResult.push(' return result;'); + } + return; + } + if (targetName) { + postResult.push(` return ${getRenderString(targetName, kernel)};`); + } else { + postResult.push(` return null;`); + } + }, + onUnrecognizedArgumentLookup: (argument) => { + const argumentName = findKernelValue(argument, kernel.kernelArguments, [], context, uploadedValues); + if (argumentName) { + return argumentName; + } + const constantName = findKernelValue(argument, kernel.kernelConstants, constants ? Object.keys(constants).map(key => constants[key]) : [], context, uploadedValues); + if (constantName) { + return constantName; + } + return null; + } + }); + let subKernelsResultVariableSetup = false; + let subKernelsResultIndex = 0; + const { + source, + canvas, + output, + pipeline, + graphical, + loopMaxIterations, + constants, + optimizeFloatMemory, + precision, + fixIntegerDivisionAccuracy, + functions, + nativeFunctions, + subKernels, + immutable, + argumentTypes, + constantTypes, + kernelArguments, + kernelConstants, + tactic, + } = originKernel; + const kernel = new Kernel(source, { + canvas, + context, + checkContext: false, + output, + pipeline, + graphical, + loopMaxIterations, + constants, + optimizeFloatMemory, + precision, + fixIntegerDivisionAccuracy, + functions, + nativeFunctions, + subKernels, + immutable, + argumentTypes, + constantTypes, + tactic, + }); + let result = []; + context.setIndent(2); + kernel.build.apply(kernel, args); + result.push(context.toString()); + context.reset(); + + kernel.kernelArguments.forEach((kernelArgument, i) => { + switch (kernelArgument.type) { + // primitives + case 'Integer': + case 'Boolean': + case 'Number': + case 'Float': + // non-primitives + case 'Array': + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + case 'HTMLCanvas': + case 'HTMLImage': + case 'HTMLVideo': + context.insertVariable(`uploadValue_${kernelArgument.name}`, kernelArgument.uploadValue); + break; + case 'HTMLImageArray': + for (let imageIndex = 0; imageIndex < args[i].length; imageIndex++) { + const arg = args[i]; + context.insertVariable(`uploadValue_${kernelArgument.name}[${imageIndex}]`, arg[imageIndex]); + } + break; + case 'Input': + context.insertVariable(`uploadValue_${kernelArgument.name}`, kernelArgument.uploadValue); + break; + case 'MemoryOptimizedNumberTexture': + case 'NumberTexture': + case 'Array1D(2)': + case 'Array1D(3)': + case 'Array1D(4)': + case 'Array2D(2)': + case 'Array2D(3)': + case 'Array2D(4)': + case 'Array3D(2)': + case 'Array3D(3)': + case 'Array3D(4)': + case 'ArrayTexture(1)': + case 'ArrayTexture(2)': + case 'ArrayTexture(3)': + case 'ArrayTexture(4)': + context.insertVariable(`uploadValue_${kernelArgument.name}`, args[i].texture); + break; + default: + throw new Error(`unhandled kernelArgumentType insertion for glWiretap of type ${kernelArgument.type}`); + } + }); + result.push('/** start of injected functions **/'); + result.push(`function ${toStringWithoutUtils(utils.flattenTo)}`); + result.push(`function ${toStringWithoutUtils(utils.flatten2dArrayTo)}`); + result.push(`function ${toStringWithoutUtils(utils.flatten3dArrayTo)}`); + result.push(`function ${toStringWithoutUtils(utils.flatten4dArrayTo)}`); + result.push(`function ${toStringWithoutUtils(utils.isArray)}`); + if (kernel.renderOutput !== kernel.renderTexture && kernel.formatValues) { + result.push( + ` const renderOutput = function ${toStringWithoutUtils(kernel.formatValues)};` + ); + } + result.push('/** end of injected functions **/'); + result.push(` const innerKernel = function (${kernel.kernelArguments.map(kernelArgument => kernelArgument.varName).join(', ')}) {`); + context.setIndent(4); + kernel.run.apply(kernel, args); + if (kernel.renderKernels) { + kernel.renderKernels(); + } else if (kernel.renderOutput) { + kernel.renderOutput(); + } + result.push(' /** start setup uploads for kernel values **/'); + kernel.kernelArguments.forEach(kernelArgument => { + result.push(' ' + kernelArgument.getStringValueHandler().split('\n').join('\n ')); + }); + result.push(' /** end setup uploads for kernel values **/'); + result.push(context.toString()); + if (kernel.renderOutput === kernel.renderTexture) { + context.reset(); + const framebufferName = context.getContextVariableName(kernel.framebuffer); + if (kernel.renderKernels) { + const results = kernel.renderKernels(); + const textureName = context.getContextVariableName(kernel.texture.texture); + result.push(` return { + result: { + texture: ${ textureName }, + type: '${ results.result.type }', + toArray: ${ getToArrayString(results.result, textureName, framebufferName) } + },`); + const { subKernels, mappedTextures } = kernel; + for (let i = 0; i < subKernels.length; i++) { + const texture = mappedTextures[i]; + const subKernel = subKernels[i]; + const subKernelResult = results[subKernel.property]; + const subKernelTextureName = context.getContextVariableName(texture.texture); + result.push(` + ${subKernel.property}: { + texture: ${ subKernelTextureName }, + type: '${ subKernelResult.type }', + toArray: ${ getToArrayString(subKernelResult, subKernelTextureName, framebufferName) } + },`); + } + result.push(` };`); + } else { + const rendered = kernel.renderOutput(); + const textureName = context.getContextVariableName(kernel.texture.texture); + result.push(` return { + texture: ${ textureName }, + type: '${ rendered.type }', + toArray: ${ getToArrayString(rendered, textureName, framebufferName) } + };`); + } + } + result.push(` ${destroyContextString ? '\n' + destroyContextString + ' ': ''}`); + result.push(postResult.join('\n')); + result.push(' };'); + if (kernel.graphical) { + result.push(getGetPixelsString(kernel)); + result.push(` innerKernel.getPixels = getPixels;`); + } + result.push(' return innerKernel;'); + + let constantsUpload = []; + kernelConstants.forEach((kernelConstant) => { + constantsUpload.push(`${kernelConstant.getStringValueHandler()}`); + }); + return `function kernel(settings) { + const { context, constants } = settings; + ${constantsUpload.join('')} + ${setupContextString ? setupContextString : ''} +${result.join('\n')} +}`; +} + +function getRenderString(targetName, kernel) { + const readBackValue = kernel.precision === 'single' ? targetName : `new Float32Array(${targetName}.buffer)`; + if (kernel.output[2]) { + return `renderOutput(${readBackValue}, ${kernel.output[0]}, ${kernel.output[1]}, ${kernel.output[2]})`; + } + if (kernel.output[1]) { + return `renderOutput(${readBackValue}, ${kernel.output[0]}, ${kernel.output[1]})`; + } + + return `renderOutput(${readBackValue}, ${kernel.output[0]})`; +} + +function getGetPixelsString(kernel) { + const getPixels = kernel.getPixels.toString(); + const useFunctionKeyword = !/^function/.test(getPixels); + return utils.flattenFunctionToString(`${useFunctionKeyword ? 'function ' : ''}${ getPixels }`, { + findDependency: (object, name) => { + if (object === 'utils') { + return `const ${name} = ${utils[name].toString()};`; + } + return null; + }, + thisLookup: (property) => { + if (property === 'context') { + return null; + } + if (kernel.hasOwnProperty(property)) { + return JSON.stringify(kernel[property]); + } + throw new Error(`unhandled thisLookup ${ property }`); + } + }); +} + +function getToArrayString(kernelResult, textureName, framebufferName) { + const toArray = kernelResult.toArray.toString(); + const useFunctionKeyword = !/^function/.test(toArray); + const flattenedFunctions = utils.flattenFunctionToString(`${useFunctionKeyword ? 'function ' : ''}${ toArray }`, { + findDependency: (object, name) => { + if (object === 'utils') { + return `const ${name} = ${utils[name].toString()};`; + } else if (object === 'this') { + if (name === 'framebuffer') { + return ''; + } + return `${useFunctionKeyword ? 'function ' : ''}${kernelResult[name].toString()}`; + } else { + throw new Error('unhandled fromObject'); + } + }, + thisLookup: (property, isDeclaration) => { + if (property === 'texture') { + return textureName; + } + if (property === 'context') { + if (isDeclaration) return null; + return 'gl'; + } + if (kernelResult.hasOwnProperty(property)) { + return JSON.stringify(kernelResult[property]); + } + throw new Error(`unhandled thisLookup ${ property }`); + } + }); + return `() => { + function framebuffer() { return ${framebufferName}; }; + ${flattenedFunctions} + return toArray(); + }`; +} + +/** + * + * @param {KernelVariable} argument + * @param {KernelValue[]} kernelValues + * @param {KernelVariable[]} values + * @param context + * @param {KernelVariable[]} uploadedValues + * @return {string|null} + */ +function findKernelValue(argument, kernelValues, values, context, uploadedValues) { + if (argument === null) return null; + if (kernelValues === null) return null; + switch (typeof argument) { + case 'boolean': + case 'number': + return null; + } + if ( + typeof HTMLImageElement !== 'undefined' && + argument instanceof HTMLImageElement + ) { + for (let i = 0; i < kernelValues.length; i++) { + const kernelValue = kernelValues[i]; + if (kernelValue.type !== 'HTMLImageArray' && kernelValue) continue; + if (kernelValue.uploadValue !== argument) continue; + // TODO: if we send two of the same image, the parser could get confused, and short circuit to the first, handle that here + const variableIndex = values[i].indexOf(argument); + if (variableIndex === -1) continue; + const variableName = `uploadValue_${kernelValue.name}[${variableIndex}]`; + context.insertVariable(variableName, argument); + return variableName; + } + } + + for (let i = 0; i < kernelValues.length; i++) { + const kernelValue = kernelValues[i]; + if (argument !== kernelValue.uploadValue) continue; + const variable = `uploadValue_${kernelValue.name}`; + context.insertVariable(variable, kernelValue); + return variable; + } + return null; +} + +module.exports = { + glKernelString +}; +},{"../../utils":291,"gl-wiretap":135}],192:[function(require,module,exports){ +const { Kernel } = require('../kernel'); +const { utils } = require('../../utils'); +const { GLTextureArray2Float } = require('./texture/array-2-float'); +const { GLTextureArray2Float2D } = require('./texture/array-2-float-2d'); +const { GLTextureArray2Float3D } = require('./texture/array-2-float-3d'); +const { GLTextureArray3Float } = require('./texture/array-3-float'); +const { GLTextureArray3Float2D } = require('./texture/array-3-float-2d'); +const { GLTextureArray3Float3D } = require('./texture/array-3-float-3d'); +const { GLTextureArray4Float } = require('./texture/array-4-float'); +const { GLTextureArray4Float2D } = require('./texture/array-4-float-2d'); +const { GLTextureArray4Float3D } = require('./texture/array-4-float-3d'); +const { GLTextureFloat } = require('./texture/float'); +const { GLTextureFloat2D } = require('./texture/float-2d'); +const { GLTextureFloat3D } = require('./texture/float-3d'); +const { GLTextureMemoryOptimized } = require('./texture/memory-optimized'); +const { GLTextureMemoryOptimized2D } = require('./texture/memory-optimized-2d'); +const { GLTextureMemoryOptimized3D } = require('./texture/memory-optimized-3d'); +const { GLTextureUnsigned } = require('./texture/unsigned'); +const { GLTextureUnsigned2D } = require('./texture/unsigned-2d'); +const { GLTextureUnsigned3D } = require('./texture/unsigned-3d'); +const { GLTextureGraphical } = require('./texture/graphical'); + +/** + * @abstract + * @extends Kernel + */ +class GLKernel extends Kernel { + static get mode() { + return 'gpu'; + } + + static getIsFloatRead() { + const kernelString = `function kernelFunction() { + return 1; + }`; + const kernel = new this(kernelString, { + context: this.testContext, + canvas: this.testCanvas, + validate: false, + output: [1], + precision: 'single', + returnType: 'Number', + tactic: 'speed', + }); + kernel.build(); + kernel.run(); + const result = kernel.renderOutput(); + kernel.destroy(true); + return result[0] === 1; + } + + static getIsIntegerDivisionAccurate() { + function kernelFunction(v1, v2) { + return v1[this.thread.x] / v2[this.thread.x]; + } + const kernel = new this(kernelFunction.toString(), { + context: this.testContext, + canvas: this.testCanvas, + validate: false, + output: [2], + returnType: 'Number', + precision: 'unsigned', + tactic: 'speed', + }); + const args = [ + [6, 6030401], + [3, 3991] + ]; + kernel.build.apply(kernel, args); + kernel.run.apply(kernel, args); + const result = kernel.renderOutput(); + kernel.destroy(true); + // have we not got whole numbers for 6/3 or 6030401/3991 + // add more here if others see this problem + return result[0] === 2 && result[1] === 1511; + } + + static getIsSpeedTacticSupported() { + function kernelFunction(value) { + return value[this.thread.x]; + } + const kernel = new this(kernelFunction.toString(), { + context: this.testContext, + canvas: this.testCanvas, + validate: false, + output: [4], + returnType: 'Number', + precision: 'unsigned', + tactic: 'speed', + }); + const args = [ + [0, 1, 2, 3] + ]; + kernel.build.apply(kernel, args); + kernel.run.apply(kernel, args); + const result = kernel.renderOutput(); + kernel.destroy(true); + return Math.round(result[0]) === 0 && Math.round(result[1]) === 1 && Math.round(result[2]) === 2 && Math.round(result[3]) === 3; + } + + /** + * @abstract + */ + static get testCanvas() { + throw new Error(`"testCanvas" not defined on ${ this.name }`); + } + + /** + * @abstract + */ + static get testContext() { + throw new Error(`"testContext" not defined on ${ this.name }`); + } + + static getFeatures() { + const gl = this.testContext; + const isDrawBuffers = this.getIsDrawBuffers(); + return Object.freeze({ + isFloatRead: this.getIsFloatRead(), + isIntegerDivisionAccurate: this.getIsIntegerDivisionAccurate(), + isSpeedTacticSupported: this.getIsSpeedTacticSupported(), + isTextureFloat: this.getIsTextureFloat(), + isDrawBuffers, + kernelMap: isDrawBuffers, + channelCount: this.getChannelCount(), + maxTextureSize: this.getMaxTextureSize(), + lowIntPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_INT), + lowFloatPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_FLOAT), + mediumIntPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_INT), + mediumFloatPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT), + highIntPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT), + highFloatPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT), + }); + } + + /** + * @abstract + */ + static setupFeatureChecks() { + throw new Error(`"setupFeatureChecks" not defined on ${ this.name }`); + } + + static getSignature(kernel, argumentTypes) { + return kernel.getVariablePrecisionString() + (argumentTypes.length > 0 ? ':' + argumentTypes.join(',') : ''); + } + + /** + * @desc Fix division by factor of 3 FP accuracy bug + * @param {Boolean} fix - should fix + */ + setFixIntegerDivisionAccuracy(fix) { + this.fixIntegerDivisionAccuracy = fix; + return this; + } + + /** + * @desc Toggle output mode + * @param {String} flag - 'single' or 'unsigned' + */ + setPrecision(flag) { + this.precision = flag; + return this; + } + + /** + * @desc Toggle texture output mode + * @param {Boolean} flag - true to enable floatTextures + * @deprecated + */ + setFloatTextures(flag) { + utils.warnDeprecated('method', 'setFloatTextures', 'setOptimizeFloatMemory'); + this.floatTextures = flag; + return this; + } + + /** + * A highly readable very forgiving micro-parser for a glsl function that gets argument types + * @param {String} source + * @returns {{argumentTypes: String[], argumentNames: String[]}} + */ + static nativeFunctionArguments(source) { + const argumentTypes = []; + const argumentNames = []; + const states = []; + const isStartingVariableName = /^[a-zA-Z_]/; + const isVariableChar = /[a-zA-Z_0-9]/; + let i = 0; + let argumentName = null; + let argumentType = null; + while (i < source.length) { + const char = source[i]; + const nextChar = source[i + 1]; + const state = states.length > 0 ? states[states.length - 1] : null; + + // begin MULTI_LINE_COMMENT handling + if (state === 'FUNCTION_ARGUMENTS' && char === '/' && nextChar === '*') { + states.push('MULTI_LINE_COMMENT'); + i += 2; + continue; + } else if (state === 'MULTI_LINE_COMMENT' && char === '*' && nextChar === '/') { + states.pop(); + i += 2; + continue; + } + // end MULTI_LINE_COMMENT handling + + // begin COMMENT handling + else if (state === 'FUNCTION_ARGUMENTS' && char === '/' && nextChar === '/') { + states.push('COMMENT'); + i += 2; + continue; + } else if (state === 'COMMENT' && char === '\n') { + states.pop(); + i++; + continue; + } + // end COMMENT handling + + // being FUNCTION_ARGUMENTS handling + else if (state === null && char === '(') { + states.push('FUNCTION_ARGUMENTS'); + i++; + continue; + } else if (state === 'FUNCTION_ARGUMENTS') { + if (char === ')') { + states.pop(); + break; + } + if (char === 'f' && nextChar === 'l' && source[i + 2] === 'o' && source[i + 3] === 'a' && source[i + 4] === 't' && source[i + 5] === ' ') { + states.push('DECLARE_VARIABLE'); + argumentType = 'float'; + argumentName = ''; + i += 6; + continue; + } else if (char === 'i' && nextChar === 'n' && source[i + 2] === 't' && source[i + 3] === ' ') { + states.push('DECLARE_VARIABLE'); + argumentType = 'int'; + argumentName = ''; + i += 4; + continue; + } else if (char === 'v' && nextChar === 'e' && source[i + 2] === 'c' && source[i + 3] === '2' && source[i + 4] === ' ') { + states.push('DECLARE_VARIABLE'); + argumentType = 'vec2'; + argumentName = ''; + i += 5; + continue; + } else if (char === 'v' && nextChar === 'e' && source[i + 2] === 'c' && source[i + 3] === '3' && source[i + 4] === ' ') { + states.push('DECLARE_VARIABLE'); + argumentType = 'vec3'; + argumentName = ''; + i += 5; + continue; + } else if (char === 'v' && nextChar === 'e' && source[i + 2] === 'c' && source[i + 3] === '4' && source[i + 4] === ' ') { + states.push('DECLARE_VARIABLE'); + argumentType = 'vec4'; + argumentName = ''; + i += 5; + continue; + } + } + // end FUNCTION_ARGUMENTS handling + + // begin DECLARE_VARIABLE handling + else if (state === 'DECLARE_VARIABLE') { + if (argumentName === '') { + if (char === ' ') { + i++; + continue; + } + if (!isStartingVariableName.test(char)) { + throw new Error('variable name is not expected string'); + } + } + argumentName += char; + if (!isVariableChar.test(nextChar)) { + states.pop(); + argumentNames.push(argumentName); + argumentTypes.push(typeMap[argumentType]); + } + } + // end DECLARE_VARIABLE handling + + // Progress to next character + i++; + } + if (states.length > 0) { + throw new Error('GLSL function was not parsable'); + } + return { + argumentNames, + argumentTypes, + }; + } + + static nativeFunctionReturnType(source) { + return typeMap[source.match(/int|float|vec[2-4]/)[0]]; + } + + static combineKernels(combinedKernel, lastKernel) { + combinedKernel.apply(null, arguments); + const { + texSize, + context, + threadDim + } = lastKernel.texSize; + let result; + if (lastKernel.precision === 'single') { + const w = texSize[0]; + const h = Math.ceil(texSize[1] / 4); + result = new Float32Array(w * h * 4 * 4); + context.readPixels(0, 0, w, h * 4, context.RGBA, context.FLOAT, result); + } else { + const bytes = new Uint8Array(texSize[0] * texSize[1] * 4); + context.readPixels(0, 0, texSize[0], texSize[1], context.RGBA, context.UNSIGNED_BYTE, bytes); + result = new Float32Array(bytes.buffer); + } + + result = result.subarray(0, threadDim[0] * threadDim[1] * threadDim[2]); + + if (lastKernel.output.length === 1) { + return result; + } else if (lastKernel.output.length === 2) { + return utils.splitArray(result, lastKernel.output[0]); + } else if (lastKernel.output.length === 3) { + const cube = utils.splitArray(result, lastKernel.output[0] * lastKernel.output[1]); + return cube.map(function(x) { + return utils.splitArray(x, lastKernel.output[0]); + }); + } + } + + constructor(source, settings) { + super(source, settings); + this.transferValues = null; + this.formatValues = null; + /** + * + * @type {Texture} + */ + this.TextureConstructor = null; + this.renderOutput = null; + this.renderRawOutput = null; + this.texSize = null; + this.translatedSource = null; + this.compiledFragmentShader = null; + this.compiledVertexShader = null; + this.switchingKernels = null; + this._textureSwitched = null; + this._mappedTextureSwitched = null; + } + + checkTextureSize() { + const { features } = this.constructor; + if (this.texSize[0] > features.maxTextureSize || this.texSize[1] > features.maxTextureSize) { + throw new Error(`Texture size [${this.texSize[0]},${this.texSize[1]}] generated by kernel is larger than supported size [${features.maxTextureSize},${features.maxTextureSize}]`); + } + } + + translateSource() { + throw new Error(`"translateSource" not defined on ${this.constructor.name}`); + } + + /** + * Picks a render strategy for the now finally parsed kernel + * @param args + * @return {null|KernelOutput} + */ + pickRenderStrategy(args) { + if (this.graphical) { + this.renderRawOutput = this.readPackedPixelsToUint8Array; + this.transferValues = (pixels) => pixels; + this.TextureConstructor = GLTextureGraphical; + return null; + } + if (this.precision === 'unsigned') { + this.renderRawOutput = this.readPackedPixelsToUint8Array; + this.transferValues = this.readPackedPixelsToFloat32Array; + if (this.pipeline) { + this.renderOutput = this.renderTexture; + if (this.subKernels !== null) { + this.renderKernels = this.renderKernelsToTextures; + } + switch (this.returnType) { + case 'LiteralInteger': + case 'Float': + case 'Number': + case 'Integer': + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureUnsigned3D; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureUnsigned2D; + return null; + } else { + this.TextureConstructor = GLTextureUnsigned; + return null; + } + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + return this.requestFallback(args); + } + } else { + if (this.subKernels !== null) { + this.renderKernels = this.renderKernelsToArrays; + } + switch (this.returnType) { + case 'LiteralInteger': + case 'Float': + case 'Number': + case 'Integer': + this.renderOutput = this.renderValues; + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureUnsigned3D; + this.formatValues = utils.erect3DPackedFloat; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureUnsigned2D; + this.formatValues = utils.erect2DPackedFloat; + return null; + } else { + this.TextureConstructor = GLTextureUnsigned; + this.formatValues = utils.erectPackedFloat; + return null; + } + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + return this.requestFallback(args); + } + } + } else if (this.precision === 'single') { + this.renderRawOutput = this.readFloatPixelsToFloat32Array; + this.transferValues = this.readFloatPixelsToFloat32Array; + if (this.pipeline) { + this.renderOutput = this.renderTexture; + if (this.subKernels !== null) { + this.renderKernels = this.renderKernelsToTextures; + } + switch (this.returnType) { + case 'LiteralInteger': + case 'Float': + case 'Number': + case 'Integer': { + if (this.optimizeFloatMemory) { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureMemoryOptimized3D; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureMemoryOptimized2D; + return null; + } else { + this.TextureConstructor = GLTextureMemoryOptimized; + return null; + } + } else { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureFloat3D; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureFloat2D; + return null; + } else { + this.TextureConstructor = GLTextureFloat; + return null; + } + } + } + case 'Array(2)': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureArray2Float3D; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureArray2Float2D; + return null; + } else { + this.TextureConstructor = GLTextureArray2Float; + return null; + } + } + case 'Array(3)': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureArray3Float3D; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureArray3Float2D; + return null; + } else { + this.TextureConstructor = GLTextureArray3Float; + return null; + } + } + case 'Array(4)': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureArray4Float3D; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureArray4Float2D; + return null; + } else { + this.TextureConstructor = GLTextureArray4Float; + return null; + } + } + } + } + this.renderOutput = this.renderValues; + if (this.subKernels !== null) { + this.renderKernels = this.renderKernelsToArrays; + } + if (this.optimizeFloatMemory) { + switch (this.returnType) { + case 'LiteralInteger': + case 'Float': + case 'Number': + case 'Integer': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureMemoryOptimized3D; + this.formatValues = utils.erectMemoryOptimized3DFloat; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureMemoryOptimized2D; + this.formatValues = utils.erectMemoryOptimized2DFloat; + return null; + } else { + this.TextureConstructor = GLTextureMemoryOptimized; + this.formatValues = utils.erectMemoryOptimizedFloat; + return null; + } + } + case 'Array(2)': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureArray2Float3D; + this.formatValues = utils.erect3DArray2; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureArray2Float2D; + this.formatValues = utils.erect2DArray2; + return null; + } else { + this.TextureConstructor = GLTextureArray2Float; + this.formatValues = utils.erectArray2; + return null; + } + } + case 'Array(3)': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureArray3Float3D; + this.formatValues = utils.erect3DArray3; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureArray3Float2D; + this.formatValues = utils.erect2DArray3; + return null; + } else { + this.TextureConstructor = GLTextureArray3Float; + this.formatValues = utils.erectArray3; + return null; + } + } + case 'Array(4)': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureArray4Float3D; + this.formatValues = utils.erect3DArray4; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureArray4Float2D; + this.formatValues = utils.erect2DArray4; + return null; + } else { + this.TextureConstructor = GLTextureArray4Float; + this.formatValues = utils.erectArray4; + return null; + } + } + } + } else { + switch (this.returnType) { + case 'LiteralInteger': + case 'Float': + case 'Number': + case 'Integer': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureFloat3D; + this.formatValues = utils.erect3DFloat; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureFloat2D; + this.formatValues = utils.erect2DFloat; + return null; + } else { + this.TextureConstructor = GLTextureFloat; + this.formatValues = utils.erectFloat; + return null; + } + } + case 'Array(2)': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureArray2Float3D; + this.formatValues = utils.erect3DArray2; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureArray2Float2D; + this.formatValues = utils.erect2DArray2; + return null; + } else { + this.TextureConstructor = GLTextureArray2Float; + this.formatValues = utils.erectArray2; + return null; + } + } + case 'Array(3)': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureArray3Float3D; + this.formatValues = utils.erect3DArray3; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureArray3Float2D; + this.formatValues = utils.erect2DArray3; + return null; + } else { + this.TextureConstructor = GLTextureArray3Float; + this.formatValues = utils.erectArray3; + return null; + } + } + case 'Array(4)': { + if (this.output[2] > 0) { + this.TextureConstructor = GLTextureArray4Float3D; + this.formatValues = utils.erect3DArray4; + return null; + } else if (this.output[1] > 0) { + this.TextureConstructor = GLTextureArray4Float2D; + this.formatValues = utils.erect2DArray4; + return null; + } else { + this.TextureConstructor = GLTextureArray4Float; + this.formatValues = utils.erectArray4; + return null; + } + } + } + } + } else { + throw new Error(`unhandled precision of "${this.precision}"`); + } + + throw new Error(`unhandled return type "${this.returnType}"`); + } + + /** + * @abstract + * @returns String + */ + getKernelString() { + throw new Error(`abstract method call`); + } + + getMainResultTexture() { + switch (this.returnType) { + case 'LiteralInteger': + case 'Float': + case 'Integer': + case 'Number': + return this.getMainResultNumberTexture(); + case 'Array(2)': + return this.getMainResultArray2Texture(); + case 'Array(3)': + return this.getMainResultArray3Texture(); + case 'Array(4)': + return this.getMainResultArray4Texture(); + default: + throw new Error(`unhandled returnType type ${ this.returnType }`); + } + } + + /** + * @abstract + * @returns String[] + */ + getMainResultKernelNumberTexture() { + throw new Error(`abstract method call`); + } + /** + * @abstract + * @returns String[] + */ + getMainResultSubKernelNumberTexture() { + throw new Error(`abstract method call`); + } + /** + * @abstract + * @returns String[] + */ + getMainResultKernelArray2Texture() { + throw new Error(`abstract method call`); + } + /** + * @abstract + * @returns String[] + */ + getMainResultSubKernelArray2Texture() { + throw new Error(`abstract method call`); + } + /** + * @abstract + * @returns String[] + */ + getMainResultKernelArray3Texture() { + throw new Error(`abstract method call`); + } + /** + * @abstract + * @returns String[] + */ + getMainResultSubKernelArray3Texture() { + throw new Error(`abstract method call`); + } + /** + * @abstract + * @returns String[] + */ + getMainResultKernelArray4Texture() { + throw new Error(`abstract method call`); + } + /** + * @abstract + * @returns String[] + */ + getMainResultSubKernelArray4Texture() { + throw new Error(`abstract method call`); + } + /** + * @abstract + * @returns String[] + */ + getMainResultGraphical() { + throw new Error(`abstract method call`); + } + /** + * @abstract + * @returns String[] + */ + getMainResultMemoryOptimizedFloats() { + throw new Error(`abstract method call`); + } + /** + * @abstract + * @returns String[] + */ + getMainResultPackedPixels() { + throw new Error(`abstract method call`); + } + + getMainResultString() { + if (this.graphical) { + return this.getMainResultGraphical(); + } else if (this.precision === 'single') { + if (this.optimizeFloatMemory) { + return this.getMainResultMemoryOptimizedFloats(); + } + return this.getMainResultTexture(); + } else { + return this.getMainResultPackedPixels(); + } + } + + getMainResultNumberTexture() { + return utils.linesToString(this.getMainResultKernelNumberTexture()) + + utils.linesToString(this.getMainResultSubKernelNumberTexture()); + } + + getMainResultArray2Texture() { + return utils.linesToString(this.getMainResultKernelArray2Texture()) + + utils.linesToString(this.getMainResultSubKernelArray2Texture()); + } + + getMainResultArray3Texture() { + return utils.linesToString(this.getMainResultKernelArray3Texture()) + + utils.linesToString(this.getMainResultSubKernelArray3Texture()); + } + + getMainResultArray4Texture() { + return utils.linesToString(this.getMainResultKernelArray4Texture()) + + utils.linesToString(this.getMainResultSubKernelArray4Texture()); + } + + /** + * + * @return {string} + */ + getFloatTacticDeclaration() { + const variablePrecision = this.getVariablePrecisionString(this.texSize, this.tactic); + return `precision ${variablePrecision} float;\n`; + } + + /** + * + * @return {string} + */ + getIntTacticDeclaration() { + return `precision ${this.getVariablePrecisionString(this.texSize, this.tactic, true)} int;\n`; + } + + /** + * + * @return {string} + */ + getSampler2DTacticDeclaration() { + return `precision ${this.getVariablePrecisionString(this.texSize, this.tactic)} sampler2D;\n`; + } + + getSampler2DArrayTacticDeclaration() { + return `precision ${this.getVariablePrecisionString(this.texSize, this.tactic)} sampler2DArray;\n`; + } + + renderTexture() { + return this.immutable ? this.texture.clone() : this.texture; + } + readPackedPixelsToUint8Array() { + if (this.precision !== 'unsigned') throw new Error('Requires this.precision to be "unsigned"'); + const { + texSize, + context: gl + } = this; + const result = new Uint8Array(texSize[0] * texSize[1] * 4); + gl.readPixels(0, 0, texSize[0], texSize[1], gl.RGBA, gl.UNSIGNED_BYTE, result); + return result; + } + + readPackedPixelsToFloat32Array() { + return new Float32Array(this.readPackedPixelsToUint8Array().buffer); + } + + readFloatPixelsToFloat32Array() { + if (this.precision !== 'single') throw new Error('Requires this.precision to be "single"'); + const { + texSize, + context: gl + } = this; + const w = texSize[0]; + const h = texSize[1]; + const result = new Float32Array(w * h * 4); + gl.readPixels(0, 0, w, h, gl.RGBA, gl.FLOAT, result); + return result; + } + + /** + * + * @param {Boolean} [flip] + * @return {Uint8ClampedArray} + */ + getPixels(flip) { + const { + context: gl, + output + } = this; + const [width, height] = output; + const pixels = new Uint8Array(width * height * 4); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + // flipped by default, so invert + return new Uint8ClampedArray((flip ? pixels : utils.flipPixels(pixels, width, height)).buffer); + } + + renderKernelsToArrays() { + const result = { + result: this.renderOutput(), + }; + for (let i = 0; i < this.subKernels.length; i++) { + result[this.subKernels[i].property] = this.mappedTextures[i].toArray(); + } + return result; + } + + renderKernelsToTextures() { + const result = { + result: this.renderOutput(), + }; + if (this.immutable) { + for (let i = 0; i < this.subKernels.length; i++) { + result[this.subKernels[i].property] = this.mappedTextures[i].clone(); + } + } else { + for (let i = 0; i < this.subKernels.length; i++) { + result[this.subKernels[i].property] = this.mappedTextures[i]; + } + } + return result; + } + + resetSwitchingKernels() { + const existingValue = this.switchingKernels; + this.switchingKernels = null; + return existingValue; + } + + setOutput(output) { + const newOutput = this.toKernelOutput(output); + if (this.program) { + if (!this.dynamicOutput) { + throw new Error('Resizing a kernel with dynamicOutput: false is not possible'); + } + const newThreadDim = [newOutput[0], newOutput[1] || 1, newOutput[2] || 1]; + const newTexSize = utils.getKernelTextureSize({ + optimizeFloatMemory: this.optimizeFloatMemory, + precision: this.precision, + }, newThreadDim); + const oldTexSize = this.texSize; + if (oldTexSize) { + const oldPrecision = this.getVariablePrecisionString(oldTexSize, this.tactic); + const newPrecision = this.getVariablePrecisionString(newTexSize, this.tactic); + if (oldPrecision !== newPrecision) { + if (this.debug) { + console.warn('Precision requirement changed, asking GPU instance to recompile'); + } + this.switchKernels({ + type: 'outputPrecisionMismatch', + precision: newPrecision, + needed: output + }); + return; + } + } + this.output = newOutput; + this.threadDim = newThreadDim; + this.texSize = newTexSize; + const { context: gl } = this; + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + this.updateMaxTexSize(); + this.framebuffer.width = this.texSize[0]; + this.framebuffer.height = this.texSize[1]; + gl.viewport(0, 0, this.maxTexSize[0], this.maxTexSize[1]); + this.canvas.width = this.maxTexSize[0]; + this.canvas.height = this.maxTexSize[1]; + if (this.texture) { + this.texture.delete(); + } + this.texture = null; + this._setupOutputTexture(); + if (this.mappedTextures && this.mappedTextures.length > 0) { + for (let i = 0; i < this.mappedTextures.length; i++) { + this.mappedTextures[i].delete(); + } + this.mappedTextures = null; + this._setupSubOutputTextures(); + } + } else { + this.output = newOutput; + } + return this; + } + renderValues() { + return this.formatValues( + this.transferValues(), + this.output[0], + this.output[1], + this.output[2] + ); + } + switchKernels(reason) { + if (this.switchingKernels) { + this.switchingKernels.push(reason); + } else { + this.switchingKernels = [reason]; + } + } + getVariablePrecisionString(textureSize = this.texSize, tactic = this.tactic, isInt = false) { + if (!tactic) { + if (!this.constructor.features.isSpeedTacticSupported) return 'highp'; + const low = this.constructor.features[isInt ? 'lowIntPrecision' : 'lowFloatPrecision']; + const medium = this.constructor.features[isInt ? 'mediumIntPrecision' : 'mediumFloatPrecision']; + const high = this.constructor.features[isInt ? 'highIntPrecision' : 'highFloatPrecision']; + const requiredSize = Math.log2(textureSize[0] * textureSize[1]); + if (requiredSize <= low.rangeMax) { + return 'lowp'; + } else if (requiredSize <= medium.rangeMax) { + return 'mediump'; + } else if (requiredSize <= high.rangeMax) { + return 'highp'; + } else { + throw new Error(`The required size exceeds that of the ability of your system`); + } + } + switch (tactic) { + case 'speed': + return 'lowp'; + case 'balanced': + return 'mediump'; + case 'precision': + return 'highp'; + default: + throw new Error(`Unknown tactic "${tactic}" use "speed", "balanced", "precision", or empty for auto`); + } + } + + /** + * + * @param {WebGLKernelValue} kernelValue + * @param {GLTexture} arg + */ + updateTextureArgumentRefs(kernelValue, arg) { + if (!this.immutable) return; + if (this.texture.texture === arg.texture) { + const { prevArg } = kernelValue; + if (prevArg) { + if (prevArg.texture._refs === 1) { + this.texture.delete(); + this.texture = prevArg.clone(); + this._textureSwitched = true; + } + prevArg.delete(); + } + kernelValue.prevArg = arg.clone(); + } else if (this.mappedTextures && this.mappedTextures.length > 0) { + const { mappedTextures } = this; + for (let i = 0; i < mappedTextures.length; i++) { + const mappedTexture = mappedTextures[i]; + if (mappedTexture.texture === arg.texture) { + const { prevArg } = kernelValue; + if (prevArg) { + if (prevArg.texture._refs === 1) { + mappedTexture.delete(); + mappedTextures[i] = prevArg.clone(); + this._mappedTextureSwitched[i] = true; + } + prevArg.delete(); + } + kernelValue.prevArg = arg.clone(); + return; + } + } + } + } + + onActivate(previousKernel) { + this._textureSwitched = true; + this.texture = previousKernel.texture; + if (this.mappedTextures) { + for (let i = 0; i < this.mappedTextures.length; i++) { + this._mappedTextureSwitched[i] = true; + } + this.mappedTextures = previousKernel.mappedTextures; + } + } + + initCanvas() {} +} + +const typeMap = { + int: 'Integer', + float: 'Number', + vec2: 'Array(2)', + vec3: 'Array(3)', + vec4: 'Array(4)', +}; + +module.exports = { + GLKernel +}; +},{"../../utils":291,"../kernel":215,"./texture/array-2-float":195,"./texture/array-2-float-2d":193,"./texture/array-2-float-3d":194,"./texture/array-3-float":198,"./texture/array-3-float-2d":196,"./texture/array-3-float-3d":197,"./texture/array-4-float":201,"./texture/array-4-float-2d":199,"./texture/array-4-float-3d":200,"./texture/float":204,"./texture/float-2d":202,"./texture/float-3d":203,"./texture/graphical":205,"./texture/memory-optimized":209,"./texture/memory-optimized-2d":207,"./texture/memory-optimized-3d":208,"./texture/unsigned":212,"./texture/unsigned-2d":210,"./texture/unsigned-3d":211}],193:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureArray2Float2D extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(2)'; + } + toArray() { + return utils.erect2DArray2(this.renderValues(), this.output[0], this.output[1]); + } +} + +module.exports = { + GLTextureArray2Float2D +}; +},{"../../../utils":291,"./float":204}],194:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureArray2Float3D extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(2)'; + } + toArray() { + return utils.erect3DArray2(this.renderValues(), this.output[0], this.output[1], this.output[2]); + } +} + +module.exports = { + GLTextureArray2Float3D +}; +},{"../../../utils":291,"./float":204}],195:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureArray2Float extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(2)'; + } + toArray() { + return utils.erectArray2(this.renderValues(), this.output[0], this.output[1]); + } +} + +module.exports = { + GLTextureArray2Float +}; +},{"../../../utils":291,"./float":204}],196:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureArray3Float2D extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(3)'; + } + toArray() { + return utils.erect2DArray3(this.renderValues(), this.output[0], this.output[1]); + } +} + +module.exports = { + GLTextureArray3Float2D +}; +},{"../../../utils":291,"./float":204}],197:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureArray3Float3D extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(3)'; + } + toArray() { + return utils.erect3DArray3(this.renderValues(), this.output[0], this.output[1], this.output[2]); + } +} + +module.exports = { + GLTextureArray3Float3D +}; +},{"../../../utils":291,"./float":204}],198:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureArray3Float extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(3)'; + } + toArray() { + return utils.erectArray3(this.renderValues(), this.output[0]); + } +} + +module.exports = { + GLTextureArray3Float +}; +},{"../../../utils":291,"./float":204}],199:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureArray4Float2D extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(4)'; + } + toArray() { + return utils.erect2DArray4(this.renderValues(), this.output[0], this.output[1]); + } +} + +module.exports = { + GLTextureArray4Float2D +}; +},{"../../../utils":291,"./float":204}],200:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureArray4Float3D extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(4)'; + } + toArray() { + return utils.erect3DArray4(this.renderValues(), this.output[0], this.output[1], this.output[2]); + } +} + +module.exports = { + GLTextureArray4Float3D +}; +},{"../../../utils":291,"./float":204}],201:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureArray4Float extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(4)'; + } + toArray() { + return utils.erectArray4(this.renderValues(), this.output[0]); + } +} + +module.exports = { + GLTextureArray4Float +}; +},{"../../../utils":291,"./float":204}],202:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureFloat2D extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(1)'; + } + toArray() { + return utils.erect2DFloat(this.renderValues(), this.output[0], this.output[1]); + } +} + +module.exports = { + GLTextureFloat2D +}; +},{"../../../utils":291,"./float":204}],203:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureFloat3D extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(1)'; + } + toArray() { + return utils.erect3DFloat(this.renderValues(), this.output[0], this.output[1], this.output[2]); + } +} + +module.exports = { + GLTextureFloat3D +}; +},{"../../../utils":291,"./float":204}],204:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTexture } = require('./index'); + +class GLTextureFloat extends GLTexture { + get textureType() { + return this.context.FLOAT; + } + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(1)'; + } + renderRawOutput() { + const gl = this.context; + const size = this.size; + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer()); + gl.framebufferTexture2D( + gl.FRAMEBUFFER, + gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, + this.texture, + 0 + ); + const result = new Float32Array(size[0] * size[1] * 4); + gl.readPixels(0, 0, size[0], size[1], gl.RGBA, gl.FLOAT, result); + return result; + } + renderValues() { + if (this._deleted) return null; + return this.renderRawOutput(); + } + toArray() { + return utils.erectFloat(this.renderValues(), this.output[0]); + } +} + +module.exports = { + GLTextureFloat +}; +},{"../../../utils":291,"./index":206}],205:[function(require,module,exports){ +const { GLTextureUnsigned } = require('./unsigned'); + +class GLTextureGraphical extends GLTextureUnsigned { + constructor(settings) { + super(settings); + this.type = 'ArrayTexture(4)'; + } + toArray() { + return this.renderValues(); + } +} + +module.exports = { + GLTextureGraphical +}; +},{"./unsigned":212}],206:[function(require,module,exports){ +const { Texture } = require('../../../texture'); + +/** + * @class + * @property framebuffer + * @extends Texture + */ +class GLTexture extends Texture { + /** + * @returns {Number} + * @abstract + */ + get textureType() { + throw new Error(`"textureType" not implemented on ${ this.name }`); + } + + clone() { + return new this.constructor(this); + } + + /** + * @returns {Boolean} + */ + beforeMutate() { + if (this.texture._refs > 1) { + this.newTexture(); + return true; + } + return false; + } + + /** + * @private + */ + cloneTexture() { + this.texture._refs--; + const { context: gl, size, texture, kernel } = this; + if (kernel.debug) { + console.warn('cloning internal texture'); + } + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer()); + selectTexture(gl, texture); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + const target = gl.createTexture(); + selectTexture(gl, target); + gl.texImage2D(gl.TEXTURE_2D, 0, this.internalFormat, size[0], size[1], 0, this.textureFormat, this.textureType, null); + gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, size[0], size[1]); + target._refs = 1; + this.texture = target; + } + + /** + * @private + */ + newTexture() { + this.texture._refs--; + const gl = this.context; + const size = this.size; + const kernel = this.kernel; + if (kernel.debug) { + console.warn('new internal texture'); + } + const target = gl.createTexture(); + selectTexture(gl, target); + gl.texImage2D(gl.TEXTURE_2D, 0, this.internalFormat, size[0], size[1], 0, this.textureFormat, this.textureType, null); + target._refs = 1; + this.texture = target; + } + + clear() { + if (this.texture._refs) { + this.texture._refs--; + const gl = this.context; + const target = this.texture = gl.createTexture(); + selectTexture(gl, target); + const size = this.size; + target._refs = 1; + gl.texImage2D(gl.TEXTURE_2D, 0, this.internalFormat, size[0], size[1], 0, this.textureFormat, this.textureType, null); + } + const { context: gl, texture } = this; + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer()); + gl.bindTexture(gl.TEXTURE_2D, texture); + selectTexture(gl, texture); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + gl.clearColor(0, 0, 0, 0); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + delete() { + if (this._deleted) return; + this._deleted = true; + if (this.texture._refs) { + this.texture._refs--; + if (this.texture._refs) return; + } + this.context.deleteTexture(this.texture); + // TODO: Remove me + // if (this.texture._refs === 0 && this._framebuffer) { + // this.context.deleteFramebuffer(this._framebuffer); + // this._framebuffer = null; + // } + } + + framebuffer() { + if (!this._framebuffer) { + this._framebuffer = this.kernel.getRawValueFramebuffer(this.size[0], this.size[1]); + } + return this._framebuffer; + } +} + +function selectTexture(gl, texture) { + /* Maximum a texture can be, so that collision is highly unlikely + * basically gl.TEXTURE15 + gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + * Was gl.TEXTURE31, but safari didn't like it + * */ + gl.activeTexture(gl.TEXTURE15); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); +} + +module.exports = { GLTexture }; +},{"../../../texture":290}],207:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureMemoryOptimized2D extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'MemoryOptimizedNumberTexture'; + } + toArray() { + return utils.erectMemoryOptimized2DFloat(this.renderValues(), this.output[0], this.output[1]); + } +} + +module.exports = { + GLTextureMemoryOptimized2D +}; +},{"../../../utils":291,"./float":204}],208:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureMemoryOptimized3D extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'MemoryOptimizedNumberTexture'; + } + toArray() { + return utils.erectMemoryOptimized3DFloat(this.renderValues(), this.output[0], this.output[1], this.output[2]); + } +} + +module.exports = { + GLTextureMemoryOptimized3D +}; +},{"../../../utils":291,"./float":204}],209:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureFloat } = require('./float'); + +class GLTextureMemoryOptimized extends GLTextureFloat { + constructor(settings) { + super(settings); + this.type = 'MemoryOptimizedNumberTexture'; + } + toArray() { + return utils.erectMemoryOptimizedFloat(this.renderValues(), this.output[0]); + } +} + +module.exports = { + GLTextureMemoryOptimized +}; +},{"../../../utils":291,"./float":204}],210:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureUnsigned } = require('./unsigned'); + +class GLTextureUnsigned2D extends GLTextureUnsigned { + constructor(settings) { + super(settings); + this.type = 'NumberTexture'; + } + toArray() { + return utils.erect2DPackedFloat(this.renderValues(), this.output[0], this.output[1]); + } +} + +module.exports = { + GLTextureUnsigned2D +}; +},{"../../../utils":291,"./unsigned":212}],211:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTextureUnsigned } = require('./unsigned'); + +class GLTextureUnsigned3D extends GLTextureUnsigned { + constructor(settings) { + super(settings); + this.type = 'NumberTexture'; + } + toArray() { + return utils.erect3DPackedFloat(this.renderValues(), this.output[0], this.output[1], this.output[2]); + } +} + +module.exports = { + GLTextureUnsigned3D +}; +},{"../../../utils":291,"./unsigned":212}],212:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { GLTexture } = require('./index'); + +class GLTextureUnsigned extends GLTexture { + get textureType() { + return this.context.UNSIGNED_BYTE; + } + constructor(settings) { + super(settings); + this.type = 'NumberTexture'; + } + renderRawOutput() { + const { context: gl } = this; + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer()); + gl.framebufferTexture2D( + gl.FRAMEBUFFER, + gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, + this.texture, + 0 + ); + const result = new Uint8Array(this.size[0] * this.size[1] * 4); + gl.readPixels(0, 0, this.size[0], this.size[1], gl.RGBA, gl.UNSIGNED_BYTE, result); + return result; + } + renderValues() { + if (this._deleted) return null; + return new Float32Array(this.renderRawOutput().buffer); + } + toArray() { + return utils.erectPackedFloat(this.renderValues(), this.output[0]); + } +} + +module.exports = { + GLTextureUnsigned +}; +},{"../../../utils":291,"./index":206}],213:[function(require,module,exports){ +const getContext = require('gl'); +const { WebGLKernel } = require('../web-gl/kernel'); +const { glKernelString } = require('../gl/kernel-string'); + +let isSupported = null; +let testCanvas = null; +let testContext = null; +let testExtensions = null; +let features = null; + +class HeadlessGLKernel extends WebGLKernel { + static get isSupported() { + if (isSupported !== null) return isSupported; + this.setupFeatureChecks(); + isSupported = testContext !== null; + return isSupported; + } + + static setupFeatureChecks() { + testCanvas = null; + testExtensions = null; + if (typeof getContext !== 'function') return; + try { // just in case, edge cases + testContext = getContext(2, 2, { + preserveDrawingBuffer: true + }); + if (!testContext || !testContext.getExtension) return; + testExtensions = { + STACKGL_resize_drawingbuffer: testContext.getExtension('STACKGL_resize_drawingbuffer'), + STACKGL_destroy_context: testContext.getExtension('STACKGL_destroy_context'), + OES_texture_float: testContext.getExtension('OES_texture_float'), + OES_texture_float_linear: testContext.getExtension('OES_texture_float_linear'), + OES_element_index_uint: testContext.getExtension('OES_element_index_uint'), + WEBGL_draw_buffers: testContext.getExtension('WEBGL_draw_buffers'), + WEBGL_color_buffer_float: testContext.getExtension('WEBGL_color_buffer_float'), + }; + features = this.getFeatures(); + } catch (e) { + console.warn(e); + } + } + + static isContextMatch(context) { + try { + return context.getParameter(context.RENDERER) === 'ANGLE'; + } catch (e) { + return false; + } + } + + static getIsTextureFloat() { + return Boolean(testExtensions.OES_texture_float); + } + + static getIsDrawBuffers() { + return Boolean(testExtensions.WEBGL_draw_buffers); + } + + static getChannelCount() { + return testExtensions.WEBGL_draw_buffers ? + testContext.getParameter(testExtensions.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL) : + 1; + } + + static getMaxTextureSize() { + return testContext.getParameter(testContext.MAX_TEXTURE_SIZE); + } + + static get testCanvas() { + return testCanvas; + } + + static get testContext() { + return testContext; + } + + static get features() { + return features; + } + + initCanvas() { + return {}; + } + + initContext() { + return getContext(2, 2, { + preserveDrawingBuffer: true + }); + } + + initExtensions() { + this.extensions = { + STACKGL_resize_drawingbuffer: this.context.getExtension('STACKGL_resize_drawingbuffer'), + STACKGL_destroy_context: this.context.getExtension('STACKGL_destroy_context'), + OES_texture_float: this.context.getExtension('OES_texture_float'), + OES_texture_float_linear: this.context.getExtension('OES_texture_float_linear'), + OES_element_index_uint: this.context.getExtension('OES_element_index_uint'), + WEBGL_draw_buffers: this.context.getExtension('WEBGL_draw_buffers'), + }; + } + + build() { + super.build.apply(this, arguments); + if (!this.fallbackRequested) { + this.extensions.STACKGL_resize_drawingbuffer.resize(this.maxTexSize[0], this.maxTexSize[1]); + } + } + + destroyExtensions() { + this.extensions.STACKGL_resize_drawingbuffer = null; + this.extensions.STACKGL_destroy_context = null; + this.extensions.OES_texture_float = null; + this.extensions.OES_texture_float_linear = null; + this.extensions.OES_element_index_uint = null; + this.extensions.WEBGL_draw_buffers = null; + } + + static destroyContext(context) { + const extension = context.getExtension('STACKGL_destroy_context'); + if (extension && extension.destroy) { + extension.destroy(); + } + } + + /** + * @desc Returns the *pre-compiled* Kernel as a JS Object String, that can be reused. + */ + toString() { + const setupContextString = `const gl = context || require('gl')(1, 1);\n`; + const destroyContextString = ` if (!context) { gl.getExtension('STACKGL_destroy_context').destroy(); }\n`; + return glKernelString(this.constructor, arguments, this, setupContextString, destroyContextString); + } + + setOutput(output) { + super.setOutput(output); + if (this.graphical && this.extensions.STACKGL_resize_drawingbuffer) { + this.extensions.STACKGL_resize_drawingbuffer.resize(this.maxTexSize[0], this.maxTexSize[1]); + } + return this; + } +} + +module.exports = { + HeadlessGLKernel +}; +},{"../gl/kernel-string":191,"../web-gl/kernel":249,"gl":136}],214:[function(require,module,exports){ +/** + * @class KernelValue + */ +class KernelValue { + /** + * @param {KernelVariable} value + * @param {IKernelValueSettings} settings + */ + constructor(value, settings) { + const { + name, + kernel, + context, + checkContext, + onRequestContextHandle, + onUpdateValueMismatch, + origin, + strictIntegers, + type, + tactic, + } = settings; + if (!name) { + throw new Error('name not set'); + } + if (!type) { + throw new Error('type not set'); + } + if (!origin) { + throw new Error('origin not set'); + } + if (origin !== 'user' && origin !== 'constants') { + throw new Error(`origin must be "user" or "constants" value is "${ origin }"`); + } + if (!onRequestContextHandle) { + throw new Error('onRequestContextHandle is not set'); + } + this.name = name; + this.origin = origin; + this.tactic = tactic; + this.varName = origin === 'constants' ? `constants.${name}` : name; + this.kernel = kernel; + this.strictIntegers = strictIntegers; + // handle textures + this.type = value.type || type; + this.size = value.size || null; + this.index = null; + this.context = context; + this.checkContext = checkContext !== null && checkContext !== undefined ? checkContext : true; + this.contextHandle = null; + this.onRequestContextHandle = onRequestContextHandle; + this.onUpdateValueMismatch = onUpdateValueMismatch; + this.forceUploadEachRun = null; + } + + get id() { + return `${this.origin}_${name}`; + } + + getSource() { + throw new Error(`"getSource" not defined on ${ this.constructor.name }`); + } + + updateValue(value) { + throw new Error(`"updateValue" not defined on ${ this.constructor.name }`); + } +} + +module.exports = { + KernelValue +}; +},{}],215:[function(require,module,exports){ +const { utils } = require('../utils'); +const { Input } = require('../input'); + +class Kernel { + /** + * @type {Boolean} + */ + static get isSupported() { + throw new Error(`"isSupported" not implemented on ${ this.name }`); + } + + /** + * @abstract + * @returns {Boolean} + */ + static isContextMatch(context) { + throw new Error(`"isContextMatch" not implemented on ${ this.name }`); + } + + /** + * @type {IKernelFeatures} + * Used internally to populate the kernel.feature, which is a getter for the output of this value + */ + static getFeatures() { + throw new Error(`"getFeatures" not implemented on ${ this.name }`); + } + + static destroyContext(context) { + throw new Error(`"destroyContext" called on ${ this.name }`); + } + + static nativeFunctionArguments() { + throw new Error(`"nativeFunctionArguments" called on ${ this.name }`); + } + + static nativeFunctionReturnType() { + throw new Error(`"nativeFunctionReturnType" called on ${ this.name }`); + } + + static combineKernels() { + throw new Error(`"combineKernels" called on ${ this.name }`); + } + + /** + * + * @param {string|IKernelJSON} source + * @param [settings] + */ + constructor(source, settings) { + if (typeof source !== 'object') { + if (typeof source !== 'string') { + throw new Error('source not a string'); + } + if (!utils.isFunctionString(source)) { + throw new Error('source not a function string'); + } + } + this.useLegacyEncoder = false; + this.fallbackRequested = false; + this.onRequestFallback = null; + + /** + * Name of the arguments found from parsing source argument + * @type {String[]} + */ + this.argumentNames = typeof source === 'string' ? utils.getArgumentNamesFromString(source) : null; + this.argumentTypes = null; + this.argumentSizes = null; + this.argumentBitRatios = null; + this.kernelArguments = null; + this.kernelConstants = null; + this.forceUploadKernelConstants = null; + + + /** + * The function source + * @type {String|IKernelJSON} + */ + this.source = source; + + /** + * The size of the kernel's output + * @type {Number[]} + */ + this.output = null; + + /** + * Debug mode + * @type {Boolean} + */ + this.debug = false; + + /** + * Graphical mode + * @type {Boolean} + */ + this.graphical = false; + + /** + * Maximum loops when using argument values to prevent infinity + * @type {Number} + */ + this.loopMaxIterations = 0; + + /** + * Constants used in kernel via `this.constants` + * @type {Object} + */ + this.constants = null; + + /** + * + * @type {Object.} + */ + this.constantTypes = null; + + /** + * + * @type {Object.} + */ + this.constantBitRatios = null; + + /** + * + * @type {boolean} + */ + this.dynamicArguments = false; + + /** + * + * @type {boolean} + */ + this.dynamicOutput = false; + + /** + * + * @type {Object} + */ + this.canvas = null; + + /** + * + * @type {Object} + */ + this.context = null; + + /** + * + * @type {Boolean} + */ + this.checkContext = null; + + /** + * + * @type {GPU} + */ + this.gpu = null; + + /** + * + * @type {IGPUFunction[]} + */ + this.functions = null; + + /** + * + * @type {IGPUNativeFunction[]} + */ + this.nativeFunctions = null; + + /** + * + * @type {String} + */ + this.injectedNative = null; + + /** + * + * @type {ISubKernel[]} + */ + this.subKernels = null; + + /** + * + * @type {Boolean} + */ + this.validate = true; + + /** + * Enforces kernel to write to a new array or texture on run + * @type {Boolean} + */ + this.immutable = false; + + /** + * Enforces kernel to write to a texture on run + * @type {Boolean} + */ + this.pipeline = false; + + /** + * Make GPU use single precision or unsigned. Acceptable values: 'single' or 'unsigned' + * @type {String|null} + * @enum 'single' | 'unsigned' + */ + this.precision = null; + + /** + * + * @type {String|null} + * @enum 'speed' | 'balanced' | 'precision' + */ + this.tactic = null; + + this.plugins = null; + + this.returnType = null; + this.leadingReturnStatement = null; + this.followingReturnStatement = null; + this.optimizeFloatMemory = null; + this.strictIntegers = false; + this.fixIntegerDivisionAccuracy = null; + this.built = false; + this.signature = null; + } + + /** + * + * @param {IDirectKernelSettings|IJSONSettings} settings + */ + mergeSettings(settings) { + for (let p in settings) { + if (!settings.hasOwnProperty(p) || !this.hasOwnProperty(p)) continue; + switch (p) { + case 'output': + if (!Array.isArray(settings.output)) { + this.setOutput(settings.output); // Flatten output object + continue; + } + break; + case 'functions': + this.functions = []; + for (let i = 0; i < settings.functions.length; i++) { + this.addFunction(settings.functions[i]); + } + continue; + case 'graphical': + if (settings[p] && !settings.hasOwnProperty('precision')) { + this.precision = 'unsigned'; + } + this[p] = settings[p]; + continue; + case 'nativeFunctions': + if (!settings.nativeFunctions) continue; + this.nativeFunctions = []; + for (let i = 0; i < settings.nativeFunctions.length; i++) { + const s = settings.nativeFunctions[i]; + const { name, source } = s; + this.addNativeFunction(name, source, s); + } + continue; + } + this[p] = settings[p]; + } + + if (!this.canvas) this.canvas = this.initCanvas(); + if (!this.context) this.context = this.initContext(); + if (!this.plugins) this.plugins = this.initPlugins(settings); + } + /** + * @desc Builds the Kernel, by compiling Fragment and Vertical Shaders, + * and instantiates the program. + * @abstract + */ + build() { + throw new Error(`"build" not defined on ${ this.constructor.name }`); + } + + /** + * @desc Run the kernel program, and send the output to renderOutput + *

This method calls a helper method *renderOutput* to return the result.

+ * @returns {Float32Array|Float32Array[]|Float32Array[][]|void} Result The final output of the program, as float, and as Textures for reuse. + * @abstract + */ + run() { + throw new Error(`"run" not defined on ${ this.constructor.name }`) + } + + /** + * @abstract + * @return {Object} + */ + initCanvas() { + throw new Error(`"initCanvas" not defined on ${ this.constructor.name }`); + } + + /** + * @abstract + * @return {Object} + */ + initContext() { + throw new Error(`"initContext" not defined on ${ this.constructor.name }`); + } + + /** + * @param {IDirectKernelSettings} settings + * @return {string[]}; + * @abstract + */ + initPlugins(settings) { + throw new Error(`"initPlugins" not defined on ${ this.constructor.name }`); + } + + /** + * + * @param {KernelFunction|string|IGPUFunction} source + * @param {IFunctionSettings} [settings] + * @return {Kernel} + */ + addFunction(source, settings = {}) { + if (source.name && source.source && source.argumentTypes && 'returnType' in source) { + this.functions.push(source); + } else if ('settings' in source && 'source' in source) { + this.functions.push(this.functionToIGPUFunction(source.source, source.settings)); + } else if (typeof source === 'string' || typeof source === 'function') { + this.functions.push(this.functionToIGPUFunction(source, settings)); + } else { + throw new Error(`function not properly defined`); + } + return this; + } + + /** + * + * @param {string} name + * @param {string} source + * @param {IGPUFunctionSettings} [settings] + */ + addNativeFunction(name, source, settings = {}) { + const { argumentTypes, argumentNames } = settings.argumentTypes ? + splitArgumentTypes(settings.argumentTypes) : + this.constructor.nativeFunctionArguments(source) || {}; + this.nativeFunctions.push({ + name, + source, + settings, + argumentTypes, + argumentNames, + returnType: settings.returnType || this.constructor.nativeFunctionReturnType(source) + }); + return this; + } + + /** + * @desc Setup the parameter types for the parameters + * supplied to the Kernel function + * + * @param {IArguments} args - The actual parameters sent to the Kernel + */ + setupArguments(args) { + this.kernelArguments = []; + if (!this.argumentTypes) { + if (!this.argumentTypes) { + this.argumentTypes = []; + for (let i = 0; i < args.length; i++) { + const argType = utils.getVariableType(args[i], this.strictIntegers); + const type = argType === 'Integer' ? 'Number' : argType; + this.argumentTypes.push(type); + this.kernelArguments.push({ + type + }); + } + } + } else { + for (let i = 0; i < this.argumentTypes.length; i++) { + this.kernelArguments.push({ + type: this.argumentTypes[i] + }); + } + } + + // setup sizes + this.argumentSizes = new Array(args.length); + this.argumentBitRatios = new Int32Array(args.length); + + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + this.argumentSizes[i] = arg.constructor === Input ? arg.size : null; + this.argumentBitRatios[i] = this.getBitRatio(arg); + } + + if (this.argumentNames.length !== args.length) { + throw new Error(`arguments are miss-aligned`); + } + } + + /** + * Setup constants + */ + setupConstants() { + this.kernelConstants = []; + let needsConstantTypes = this.constantTypes === null; + if (needsConstantTypes) { + this.constantTypes = {}; + } + this.constantBitRatios = {}; + if (this.constants) { + for (let name in this.constants) { + if (needsConstantTypes) { + const type = utils.getVariableType(this.constants[name], this.strictIntegers); + this.constantTypes[name] = type; + this.kernelConstants.push({ + name, + type + }); + } else { + this.kernelConstants.push({ + name, + type: this.constantTypes[name] + }); + } + this.constantBitRatios[name] = this.getBitRatio(this.constants[name]); + } + } + } + + /** + * + * @param flag + * @return {this} + */ + setOptimizeFloatMemory(flag) { + this.optimizeFloatMemory = flag; + return this; + } + + /** + * + * @param {Array|Object} output + * @return {number[]} + */ + toKernelOutput(output) { + if (output.hasOwnProperty('x')) { + if (output.hasOwnProperty('y')) { + if (output.hasOwnProperty('z')) { + return [output.x, output.y, output.z]; + } else { + return [output.x, output.y]; + } + } else { + return [output.x]; + } + } else { + return output; + } + } + + /** + * @desc Set output dimensions of the kernel function + * @param {Array|Object} output - The output array to set the kernel output size to + * @return {this} + */ + setOutput(output) { + this.output = this.toKernelOutput(output); + return this; + } + + /** + * @desc Toggle debug mode + * @param {Boolean} flag - true to enable debug + * @return {this} + */ + setDebug(flag) { + this.debug = flag; + return this; + } + + /** + * @desc Toggle graphical output mode + * @param {Boolean} flag - true to enable graphical output + * @return {this} + */ + setGraphical(flag) { + this.graphical = flag; + this.precision = 'unsigned'; + return this; + } + + /** + * @desc Set the maximum number of loop iterations + * @param {number} max - iterations count + * @return {this} + */ + setLoopMaxIterations(max) { + this.loopMaxIterations = max; + return this; + } + + /** + * @desc Set Constants + * @return {this} + */ + setConstants(constants) { + this.constants = constants; + return this; + } + + /** + * + * @param {IKernelValueTypes} constantTypes + * @return {this} + */ + setConstantTypes(constantTypes) { + this.constantTypes = constantTypes; + return this; + } + + /** + * + * @param {IFunction[]|KernelFunction[]} functions + * @return {this} + */ + setFunctions(functions) { + for (let i = 0; i < functions.length; i++) { + this.addFunction(functions[i]); + } + return this; + } + + /** + * + * @param {IGPUNativeFunction[]} nativeFunctions + * @return {this} + */ + setNativeFunctions(nativeFunctions) { + for (let i = 0; i < nativeFunctions.length; i++) { + const settings = nativeFunctions[i]; + const { name, source } = settings; + this.addNativeFunction(name, source, settings); + } + return this; + } + + /** + * + * @param {String} injectedNative + * @return {this} + */ + setInjectedNative(injectedNative) { + this.injectedNative = injectedNative; + return this; + } + + /** + * Set writing to texture on/off + * @param flag + * @return {this} + */ + setPipeline(flag) { + this.pipeline = flag; + return this; + } + + /** + * Set precision to 'unsigned' or 'single' + * @param {String} flag 'unsigned' or 'single' + * @return {this} + */ + setPrecision(flag) { + this.precision = flag; + return this; + } + + /** + * @param flag + * @return {Kernel} + * @deprecated + */ + setDimensions(flag) { + utils.warnDeprecated('method', 'setDimensions', 'setOutput'); + this.output = flag; + return this; + } + + /** + * @param flag + * @return {this} + * @deprecated + */ + setOutputToTexture(flag) { + utils.warnDeprecated('method', 'setOutputToTexture', 'setPipeline'); + this.pipeline = flag; + return this; + } + + /** + * Set to immutable + * @param flag + * @return {this} + */ + setImmutable(flag) { + this.immutable = flag; + return this; + } + + /** + * @desc Bind the canvas to kernel + * @param {Object} canvas + * @return {this} + */ + setCanvas(canvas) { + this.canvas = canvas; + return this; + } + + /** + * @param {Boolean} flag + * @return {this} + */ + setStrictIntegers(flag) { + this.strictIntegers = flag; + return this; + } + + /** + * + * @param flag + * @return {this} + */ + setDynamicOutput(flag) { + this.dynamicOutput = flag; + return this; + } + + /** + * @deprecated + * @param flag + * @return {this} + */ + setHardcodeConstants(flag) { + utils.warnDeprecated('method', 'setHardcodeConstants'); + this.setDynamicOutput(flag); + this.setDynamicArguments(flag); + return this; + } + + /** + * + * @param flag + * @return {this} + */ + setDynamicArguments(flag) { + this.dynamicArguments = flag; + return this; + } + + /** + * @param {Boolean} flag + * @return {this} + */ + setUseLegacyEncoder(flag) { + this.useLegacyEncoder = flag; + return this; + } + + /** + * + * @param {Boolean} flag + * @return {this} + */ + setWarnVarUsage(flag) { + utils.warnDeprecated('method', 'setWarnVarUsage'); + return this; + } + + /** + * @deprecated + * @returns {Object} + */ + getCanvas() { + utils.warnDeprecated('method', 'getCanvas'); + return this.canvas; + } + + /** + * @deprecated + * @returns {Object} + */ + getWebGl() { + utils.warnDeprecated('method', 'getWebGl'); + return this.context; + } + + /** + * @desc Bind the webGL instance to kernel + * @param {WebGLRenderingContext} context - webGl instance to bind + */ + setContext(context) { + this.context = context; + return this; + } + + /** + * + * @param {IKernelValueTypes|GPUVariableType[]} argumentTypes + * @return {this} + */ + setArgumentTypes(argumentTypes) { + if (Array.isArray(argumentTypes)) { + this.argumentTypes = argumentTypes; + } else { + this.argumentTypes = []; + for (const p in argumentTypes) { + if (!argumentTypes.hasOwnProperty(p)) continue; + const argumentIndex = this.argumentNames.indexOf(p); + if (argumentIndex === -1) throw new Error(`unable to find argument ${ p }`); + this.argumentTypes[argumentIndex] = argumentTypes[p]; + } + } + return this; + } + + /** + * + * @param {Tactic} tactic + * @return {this} + */ + setTactic(tactic) { + this.tactic = tactic; + return this; + } + + requestFallback(args) { + if (!this.onRequestFallback) { + throw new Error(`"onRequestFallback" not defined on ${ this.constructor.name }`); + } + this.fallbackRequested = true; + return this.onRequestFallback(args); + } + + /** + * @desc Validate settings + * @abstract + */ + validateSettings() { + throw new Error(`"validateSettings" not defined on ${ this.constructor.name }`); + } + + /** + * @desc Add a sub kernel to the root kernel instance. + * This is what `createKernelMap` uses. + * + * @param {ISubKernel} subKernel - function (as a String) of the subKernel to add + */ + addSubKernel(subKernel) { + if (this.subKernels === null) { + this.subKernels = []; + } + if (!subKernel.source) throw new Error('subKernel missing "source" property'); + if (!subKernel.property && isNaN(subKernel.property)) throw new Error('subKernel missing "property" property'); + if (!subKernel.name) throw new Error('subKernel missing "name" property'); + this.subKernels.push(subKernel); + return this; + } + + /** + * @desc Destroys all memory associated with this kernel + * @param {Boolean} [removeCanvasReferences] remove any associated canvas references + */ + destroy(removeCanvasReferences) { + throw new Error(`"destroy" called on ${ this.constructor.name }`); + } + + /** + * bit storage ratio of source to target 'buffer', i.e. if 8bit array -> 32bit tex = 4 + * @param value + * @returns {number} + */ + getBitRatio(value) { + if (this.precision === 'single') { + // 8 and 16 are up-converted to float32 + return 4; + } else if (Array.isArray(value[0])) { + return this.getBitRatio(value[0]); + } else if (value.constructor === Input) { + return this.getBitRatio(value.value); + } + switch (value.constructor) { + case Uint8ClampedArray: + case Uint8Array: + case Int8Array: + return 1; + case Uint16Array: + case Int16Array: + return 2; + case Float32Array: + case Int32Array: + default: + return 4; + } + } + + /** + * @param {Boolean} [flip] + * @returns {Uint8ClampedArray} + */ + getPixels(flip) { + throw new Error(`"getPixels" called on ${ this.constructor.name }`); + } + + checkOutput() { + if (!this.output || !utils.isArray(this.output)) throw new Error('kernel.output not an array'); + if (this.output.length < 1) throw new Error('kernel.output is empty, needs at least 1 value'); + for (let i = 0; i < this.output.length; i++) { + if (isNaN(this.output[i]) || this.output[i] < 1) { + throw new Error(`${ this.constructor.name }.output[${ i }] incorrectly defined as \`${ this.output[i] }\`, needs to be numeric, and greater than 0`); + } + } + } + + /** + * + * @param {String} value + */ + prependString(value) { + throw new Error(`"prependString" called on ${ this.constructor.name }`); + } + + /** + * + * @param {String} value + * @return Boolean + */ + hasPrependString(value) { + throw new Error(`"hasPrependString" called on ${ this.constructor.name }`); + } + + /** + * @return {IKernelJSON} + */ + toJSON() { + return { + settings: { + output: this.output, + pipeline: this.pipeline, + argumentNames: this.argumentNames, + argumentsTypes: this.argumentTypes, + constants: this.constants, + pluginNames: this.plugins ? this.plugins.map(plugin => plugin.name) : null, + returnType: this.returnType, + } + }; + } + + /** + * @param {IArguments} args + */ + buildSignature(args) { + const Constructor = this.constructor; + this.signature = Constructor.getSignature(this, Constructor.getArgumentTypes(this, args)); + } + + /** + * @param {Kernel} kernel + * @param {IArguments} args + * @returns GPUVariableType[] + */ + static getArgumentTypes(kernel, args) { + const argumentTypes = new Array(args.length); + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + const type = kernel.argumentTypes[i]; + if (arg.type) { + argumentTypes[i] = arg.type; + } else { + switch (type) { + case 'Number': + case 'Integer': + case 'Float': + case 'ArrayTexture(1)': + argumentTypes[i] = utils.getVariableType(arg); + break; + default: + argumentTypes[i] = type; + } + } + } + return argumentTypes; + } + + /** + * + * @param {Kernel} kernel + * @param {GPUVariableType[]} argumentTypes + * @abstract + */ + static getSignature(kernel, argumentTypes) { + throw new Error(`"getSignature" not implemented on ${ this.name }`); + } + + /** + * + * @param {String|Function} source + * @param {IFunctionSettings} [settings] + * @returns {IGPUFunction} + */ + functionToIGPUFunction(source, settings = {}) { + if (typeof source !== 'string' && typeof source !== 'function') throw new Error('source not a string or function'); + const sourceString = typeof source === 'string' ? source : source.toString(); + let argumentTypes = []; + + if (Array.isArray(settings.argumentTypes)) { + argumentTypes = settings.argumentTypes; + } else if (typeof settings.argumentTypes === 'object') { + argumentTypes = utils.getArgumentNamesFromString(sourceString) + .map(name => settings.argumentTypes[name]) || []; + } else { + argumentTypes = settings.argumentTypes || []; + } + + return { + name: utils.getFunctionNameFromString(sourceString) || null, + source: sourceString, + argumentTypes, + returnType: settings.returnType || null, + }; + } + + /** + * + * @param {Kernel} previousKernel + * @abstract + */ + onActivate(previousKernel) {} +} + +function splitArgumentTypes(argumentTypesObject) { + const argumentNames = Object.keys(argumentTypesObject); + const argumentTypes = []; + for (let i = 0; i < argumentNames.length; i++) { + const argumentName = argumentNames[i]; + argumentTypes.push(argumentTypesObject[argumentName]); + } + return { argumentTypes, argumentNames }; +} + +module.exports = { + Kernel +}; +},{"../input":287,"../utils":291}],216:[function(require,module,exports){ +// language=GLSL +const fragmentShader = `__HEADER__; +__FLOAT_TACTIC_DECLARATION__; +__INT_TACTIC_DECLARATION__; +__SAMPLER_2D_TACTIC_DECLARATION__; + +const int LOOP_MAX = __LOOP_MAX__; + +__PLUGINS__; +__CONSTANTS__; + +varying vec2 vTexCoord; + +float acosh(float x) { + return log(x + sqrt(x * x - 1.0)); +} + +float sinh(float x) { + return (pow(${Math.E}, x) - pow(${Math.E}, -x)) / 2.0; +} + +float asinh(float x) { + return log(x + sqrt(x * x + 1.0)); +} + +float atan2(float v1, float v2) { + if (v1 == 0.0 || v2 == 0.0) return 0.0; + return atan(v1 / v2); +} + +float atanh(float x) { + x = (x + 1.0) / (x - 1.0); + if (x < 0.0) { + return 0.5 * log(-x); + } + return 0.5 * log(x); +} + +float cbrt(float x) { + if (x >= 0.0) { + return pow(x, 1.0 / 3.0); + } else { + return -pow(x, 1.0 / 3.0); + } +} + +float cosh(float x) { + return (pow(${Math.E}, x) + pow(${Math.E}, -x)) / 2.0; +} + +float expm1(float x) { + return pow(${Math.E}, x) - 1.0; +} + +float fround(highp float x) { + return x; +} + +float imul(float v1, float v2) { + return float(int(v1) * int(v2)); +} + +float log10(float x) { + return log2(x) * (1.0 / log2(10.0)); +} + +float log1p(float x) { + return log(1.0 + x); +} + +float _pow(float v1, float v2) { + if (v2 == 0.0) return 1.0; + return pow(v1, v2); +} + +float tanh(float x) { + float e = exp(2.0 * x); + return (e - 1.0) / (e + 1.0); +} + +float trunc(float x) { + if (x >= 0.0) { + return floor(x); + } else { + return ceil(x); + } +} + +vec4 _round(vec4 x) { + return floor(x + 0.5); +} + +float _round(float x) { + return floor(x + 0.5); +} + +const int BIT_COUNT = 32; +int modi(int x, int y) { + return x - y * (x / y); +} + +int bitwiseOr(int a, int b) { + int result = 0; + int n = 1; + + for (int i = 0; i < BIT_COUNT; i++) { + if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) { + result += n; + } + a = a / 2; + b = b / 2; + n = n * 2; + if(!(a > 0 || b > 0)) { + break; + } + } + return result; +} +int bitwiseXOR(int a, int b) { + int result = 0; + int n = 1; + + for (int i = 0; i < BIT_COUNT; i++) { + if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) { + result += n; + } + a = a / 2; + b = b / 2; + n = n * 2; + if(!(a > 0 || b > 0)) { + break; + } + } + return result; +} +int bitwiseAnd(int a, int b) { + int result = 0; + int n = 1; + for (int i = 0; i < BIT_COUNT; i++) { + if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) { + result += n; + } + a = a / 2; + b = b / 2; + n = n * 2; + if(!(a > 0 && b > 0)) { + break; + } + } + return result; +} +int bitwiseNot(int a) { + int result = 0; + int n = 1; + + for (int i = 0; i < BIT_COUNT; i++) { + if (modi(a, 2) == 0) { + result += n; + } + a = a / 2; + n = n * 2; + } + return result; +} +int bitwiseZeroFillLeftShift(int n, int shift) { + int maxBytes = BIT_COUNT; + for (int i = 0; i < BIT_COUNT; i++) { + if (maxBytes >= n) { + break; + } + maxBytes *= 2; + } + for (int i = 0; i < BIT_COUNT; i++) { + if (i >= shift) { + break; + } + n *= 2; + } + + int result = 0; + int byteVal = 1; + for (int i = 0; i < BIT_COUNT; i++) { + if (i >= maxBytes) break; + if (modi(n, 2) > 0) { result += byteVal; } + n = int(n / 2); + byteVal *= 2; + } + return result; +} + +int bitwiseSignedRightShift(int num, int shifts) { + return int(floor(float(num) / pow(2.0, float(shifts)))); +} + +int bitwiseZeroFillRightShift(int n, int shift) { + int maxBytes = BIT_COUNT; + for (int i = 0; i < BIT_COUNT; i++) { + if (maxBytes >= n) { + break; + } + maxBytes *= 2; + } + for (int i = 0; i < BIT_COUNT; i++) { + if (i >= shift) { + break; + } + n /= 2; + } + int result = 0; + int byteVal = 1; + for (int i = 0; i < BIT_COUNT; i++) { + if (i >= maxBytes) break; + if (modi(n, 2) > 0) { result += byteVal; } + n = int(n / 2); + byteVal *= 2; + } + return result; +} + +vec2 integerMod(vec2 x, float y) { + vec2 res = floor(mod(x, y)); + return res * step(1.0 - floor(y), -res); +} + +vec3 integerMod(vec3 x, float y) { + vec3 res = floor(mod(x, y)); + return res * step(1.0 - floor(y), -res); +} + +vec4 integerMod(vec4 x, vec4 y) { + vec4 res = floor(mod(x, y)); + return res * step(1.0 - floor(y), -res); +} + +float integerMod(float x, float y) { + float res = floor(mod(x, y)); + return res * (res > floor(y) - 1.0 ? 0.0 : 1.0); +} + +int integerMod(int x, int y) { + return x - (y * int(x / y)); +} + +__DIVIDE_WITH_INTEGER_CHECK__; + +// Here be dragons! +// DO NOT OPTIMIZE THIS CODE +// YOU WILL BREAK SOMETHING ON SOMEBODY\'S MACHINE +// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME +const vec2 MAGIC_VEC = vec2(1.0, -256.0); +const vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0); +const vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536 +float decode32(vec4 texel) { + __DECODE32_ENDIANNESS__; + texel *= 255.0; + vec2 gte128; + gte128.x = texel.b >= 128.0 ? 1.0 : 0.0; + gte128.y = texel.a >= 128.0 ? 1.0 : 0.0; + float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC); + float res = exp2(_round(exponent)); + texel.b = texel.b - 128.0 * gte128.x; + res = dot(texel, SCALE_FACTOR) * exp2(_round(exponent-23.0)) + res; + res *= gte128.y * -2.0 + 1.0; + return res; +} + +float decode16(vec4 texel, int index) { + int channel = integerMod(index, 2); + if (channel == 0) return texel.r * 255.0 + texel.g * 65280.0; + if (channel == 1) return texel.b * 255.0 + texel.a * 65280.0; + return 0.0; +} + +float decode8(vec4 texel, int index) { + int channel = integerMod(index, 4); + if (channel == 0) return texel.r * 255.0; + if (channel == 1) return texel.g * 255.0; + if (channel == 2) return texel.b * 255.0; + if (channel == 3) return texel.a * 255.0; + return 0.0; +} + +vec4 legacyEncode32(float f) { + float F = abs(f); + float sign = f < 0.0 ? 1.0 : 0.0; + float exponent = floor(log2(F)); + float mantissa = (exp2(-exponent) * F); + // exponent += floor(log2(mantissa)); + vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV; + texel.rg = integerMod(texel.rg, 256.0); + texel.b = integerMod(texel.b, 128.0); + texel.a = exponent*0.5 + 63.5; + texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0; + texel = floor(texel); + texel *= 0.003921569; // 1/255 + __ENCODE32_ENDIANNESS__; + return texel; +} + +// https://github.com/gpujs/gpu.js/wiki/Encoder-details +vec4 encode32(float value) { + if (value == 0.0) return vec4(0, 0, 0, 0); + + float exponent; + float mantissa; + vec4 result; + float sgn; + + sgn = step(0.0, -value); + value = abs(value); + + exponent = floor(log2(value)); + + mantissa = value*pow(2.0, -exponent)-1.0; + exponent = exponent+127.0; + result = vec4(0,0,0,0); + + result.a = floor(exponent/2.0); + exponent = exponent - result.a*2.0; + result.a = result.a + 128.0*sgn; + + result.b = floor(mantissa * 128.0); + mantissa = mantissa - result.b / 128.0; + result.b = result.b + exponent*128.0; + + result.g = floor(mantissa*32768.0); + mantissa = mantissa - result.g/32768.0; + + result.r = floor(mantissa*8388608.0); + return result/255.0; +} +// Dragons end here + +int index; +ivec3 threadId; + +ivec3 indexTo3D(int idx, ivec3 texDim) { + int z = int(idx / (texDim.x * texDim.y)); + idx -= z * int(texDim.x * texDim.y); + int y = int(idx / texDim.x); + int x = int(integerMod(idx, texDim.x)); + return ivec3(x, y, z); +} + +float get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture2D(tex, st / vec2(texSize)); + return decode32(texel); +} + +float get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int w = texSize.x * 2; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture2D(tex, st / vec2(texSize.x * 2, texSize.y)); + return decode16(texel, index); +} + +float get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int w = texSize.x * 4; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture2D(tex, st / vec2(texSize.x * 4, texSize.y)); + return decode8(texel, index); +} + +float getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int channel = integerMod(index, 4); + index = index / 4; + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture2D(tex, st / vec2(texSize)); + if (channel == 0) return texel.r; + if (channel == 1) return texel.g; + if (channel == 2) return texel.b; + if (channel == 3) return texel.a; + return 0.0; +} + +vec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + return texture2D(tex, st / vec2(texSize)); +} + +float getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + vec4 result = getImage2D(tex, texSize, texDim, z, y, x); + return result[0]; +} + +vec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + vec4 result = getImage2D(tex, texSize, texDim, z, y, x); + return vec2(result[0], result[1]); +} + +vec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + (texDim.x * (y + (texDim.y * z))); + int channel = integerMod(index, 2); + index = index / 2; + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture2D(tex, st / vec2(texSize)); + if (channel == 0) return vec2(texel.r, texel.g); + if (channel == 1) return vec2(texel.b, texel.a); + return vec2(0.0, 0.0); +} + +vec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + vec4 result = getImage2D(tex, texSize, texDim, z, y, x); + return vec3(result[0], result[1], result[2]); +} + +vec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z)); + int vectorIndex = fieldIndex / 4; + int vectorOffset = fieldIndex - vectorIndex * 4; + int readY = vectorIndex / texSize.x; + int readX = vectorIndex - readY * texSize.x; + vec4 tex1 = texture2D(tex, (vec2(readX, readY) + 0.5) / vec2(texSize)); + + if (vectorOffset == 0) { + return tex1.xyz; + } else if (vectorOffset == 1) { + return tex1.yzw; + } else { + readX++; + if (readX >= texSize.x) { + readX = 0; + readY++; + } + vec4 tex2 = texture2D(tex, vec2(readX, readY) / vec2(texSize)); + if (vectorOffset == 2) { + return vec3(tex1.z, tex1.w, tex2.x); + } else { + return vec3(tex1.w, tex2.x, tex2.y); + } + } +} + +vec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + return getImage2D(tex, texSize, texDim, z, y, x); +} + +vec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int channel = integerMod(index, 2); + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture2D(tex, st / vec2(texSize)); + return vec4(texel.r, texel.g, texel.b, texel.a); +} + +vec4 actualColor; +void color(float r, float g, float b, float a) { + actualColor = vec4(r,g,b,a); +} + +void color(float r, float g, float b) { + color(r,g,b,1.0); +} + +void color(sampler2D image) { + actualColor = texture2D(image, vTexCoord); +} + +float modulo(float number, float divisor) { + if (number < 0.0) { + number = abs(number); + if (divisor < 0.0) { + divisor = abs(divisor); + } + return -mod(number, divisor); + } + if (divisor < 0.0) { + divisor = abs(divisor); + } + return mod(number, divisor); +} + +__INJECTED_NATIVE__; +__MAIN_CONSTANTS__; +__MAIN_ARGUMENTS__; +__KERNEL__; + +void main(void) { + index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x; + __MAIN_RESULT__; +}`; + +module.exports = { + fragmentShader +}; +},{}],217:[function(require,module,exports){ +const { utils } = require('../../utils'); +const { FunctionNode } = require('../function-node'); + +/** + * @desc [INTERNAL] Takes in a function node, and does all the AST voodoo required to toString its respective WebGL code + */ +class WebGLFunctionNode extends FunctionNode { + constructor(source, settings) { + super(source, settings); + if (settings && settings.hasOwnProperty('fixIntegerDivisionAccuracy')) { + this.fixIntegerDivisionAccuracy = settings.fixIntegerDivisionAccuracy; + } + } + + astConditionalExpression(ast, retArr) { + if (ast.type !== 'ConditionalExpression') { + throw this.astErrorOutput('Not a conditional expression', ast); + } + const consequentType = this.getType(ast.consequent); + const alternateType = this.getType(ast.alternate); + // minification handling if void + if (consequentType === null && alternateType === null) { + retArr.push('if ('); + this.astGeneric(ast.test, retArr); + retArr.push(') {'); + this.astGeneric(ast.consequent, retArr); + retArr.push(';'); + retArr.push('} else {'); + this.astGeneric(ast.alternate, retArr); + retArr.push(';'); + retArr.push('}'); + return retArr; + } + retArr.push('('); + this.astGeneric(ast.test, retArr); + retArr.push('?'); + this.astGeneric(ast.consequent, retArr); + retArr.push(':'); + this.astGeneric(ast.alternate, retArr); + retArr.push(')'); + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for to its *named function* + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astFunction(ast, retArr) { + // Setup function return type and name + if (this.isRootKernel) { + retArr.push('void'); + } else { + // looking up return type, this is a little expensive, and can be avoided if returnType is set + if (!this.returnType) { + const lastReturn = this.findLastReturn(); + if (lastReturn) { + this.returnType = this.getType(ast.body); + if (this.returnType === 'LiteralInteger') { + this.returnType = 'Number'; + } + } + } + + const { returnType } = this; + if (!returnType) { + retArr.push('void'); + } else { + const type = typeMap[returnType]; + if (!type) { + throw new Error(`unknown type ${returnType}`); + } + retArr.push(type); + } + } + retArr.push(' '); + retArr.push(this.name); + retArr.push('('); + + if (!this.isRootKernel) { + // Arguments handling + for (let i = 0; i < this.argumentNames.length; ++i) { + const argumentName = this.argumentNames[i]; + + if (i > 0) { + retArr.push(', '); + } + let argumentType = this.argumentTypes[this.argumentNames.indexOf(argumentName)]; + // The type is too loose ended, here we decide to solidify a type, lets go with float + if (!argumentType) { + throw this.astErrorOutput(`Unknown argument ${argumentName} type`, ast); + } + if (argumentType === 'LiteralInteger') { + this.argumentTypes[i] = argumentType = 'Number'; + } + const type = typeMap[argumentType]; + if (!type) { + throw this.astErrorOutput('Unexpected expression', ast); + } + const name = utils.sanitizeName(argumentName); + if (type === 'sampler2D' || type === 'sampler2DArray') { + // mash needed arguments together, since now we have end to end inference + retArr.push(`${type} user_${name},ivec2 user_${name}Size,ivec3 user_${name}Dim`); + } else { + retArr.push(`${type} user_${name}`); + } + } + } + + // Function opening + retArr.push(') {\n'); + + // Body statement iteration + for (let i = 0; i < ast.body.body.length; ++i) { + this.astGeneric(ast.body.body[i], retArr); + retArr.push('\n'); + } + + // Function closing + retArr.push('}\n'); + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for to *return* statement + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astReturnStatement(ast, retArr) { + if (!ast.argument) throw this.astErrorOutput('Unexpected return statement', ast); + this.pushState('skip-literal-correction'); + const type = this.getType(ast.argument); + this.popState('skip-literal-correction'); + + const result = []; + + if (!this.returnType) { + if (type === 'LiteralInteger' || type === 'Integer') { + this.returnType = 'Number'; + } else { + this.returnType = type; + } + } + + switch (this.returnType) { + case 'LiteralInteger': + case 'Number': + case 'Float': + switch (type) { + case 'Integer': + result.push('float('); + this.astGeneric(ast.argument, result); + result.push(')'); + break; + case 'LiteralInteger': + this.castLiteralToFloat(ast.argument, result); + + // Running astGeneric forces the LiteralInteger to pick a type, and here, if we are returning a float, yet + // the LiteralInteger has picked to be an integer because of constraints on it we cast it to float. + if (this.getType(ast) === 'Integer') { + result.unshift('float('); + result.push(')'); + } + break; + default: + this.astGeneric(ast.argument, result); + } + break; + case 'Integer': + switch (type) { + case 'Float': + case 'Number': + this.castValueToInteger(ast.argument, result); + break; + case 'LiteralInteger': + this.castLiteralToInteger(ast.argument, result); + break; + default: + this.astGeneric(ast.argument, result); + } + break; + case 'Array(4)': + case 'Array(3)': + case 'Array(2)': + case 'Matrix(2)': + case 'Matrix(3)': + case 'Matrix(4)': + case 'Input': + this.astGeneric(ast.argument, result); + break; + default: + throw this.astErrorOutput(`unhandled return type ${this.returnType}`, ast); + } + + if (this.isRootKernel) { + retArr.push(`kernelResult = ${ result.join('') };`); + retArr.push('return;'); + } else if (this.isSubKernel) { + retArr.push(`subKernelResult_${ this.name } = ${ result.join('') };`); + retArr.push(`return subKernelResult_${ this.name };`); + } else { + retArr.push(`return ${ result.join('') };`); + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *literal value* + * + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * + * @returns {Array} the append retArr + */ + astLiteral(ast, retArr) { + // Reject non numeric literals + if (isNaN(ast.value)) { + throw this.astErrorOutput( + 'Non-numeric literal not supported : ' + ast.value, + ast + ); + } + + const key = this.astKey(ast); + if (Number.isInteger(ast.value)) { + if (this.isState('casting-to-integer') || this.isState('building-integer')) { + this.literalTypes[key] = 'Integer'; + retArr.push(`${ast.value}`); + } else if (this.isState('casting-to-float') || this.isState('building-float')) { + this.literalTypes[key] = 'Number'; + retArr.push(`${ast.value}.0`); + } else { + this.literalTypes[key] = 'Number'; + retArr.push(`${ast.value}.0`); + } + } else if (this.isState('casting-to-integer') || this.isState('building-integer')) { + this.literalTypes[key] = 'Integer'; + retArr.push(Math.round(ast.value)); + } else { + this.literalTypes[key] = 'Number'; + retArr.push(`${ast.value}`); + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *binary* expression + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astBinaryExpression(ast, retArr) { + if (this.checkAndUpconvertOperator(ast, retArr)) { + return retArr; + } + + if (this.fixIntegerDivisionAccuracy && ast.operator === '/') { + retArr.push('divWithIntCheck('); + this.pushState('building-float'); + switch (this.getType(ast.left)) { + case 'Integer': + this.castValueToFloat(ast.left, retArr); + break; + case 'LiteralInteger': + this.castLiteralToFloat(ast.left, retArr); + break; + default: + this.astGeneric(ast.left, retArr); + } + retArr.push(', '); + switch (this.getType(ast.right)) { + case 'Integer': + this.castValueToFloat(ast.right, retArr); + break; + case 'LiteralInteger': + this.castLiteralToFloat(ast.right, retArr); + break; + default: + this.astGeneric(ast.right, retArr); + } + this.popState('building-float'); + retArr.push(')'); + return retArr; + } + + retArr.push('('); + const leftType = this.getType(ast.left) || 'Number'; + const rightType = this.getType(ast.right) || 'Number'; + if (!leftType || !rightType) { + throw this.astErrorOutput(`Unhandled binary expression`, ast); + } + const key = leftType + ' & ' + rightType; + switch (key) { + case 'Integer & Integer': + this.pushState('building-integer'); + this.astGeneric(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.astGeneric(ast.right, retArr); + this.popState('building-integer'); + break; + case 'Number & Float': + case 'Float & Number': + case 'Float & Float': + case 'Number & Number': + this.pushState('building-float'); + this.astGeneric(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.astGeneric(ast.right, retArr); + this.popState('building-float'); + break; + case 'LiteralInteger & LiteralInteger': + if (this.isState('casting-to-integer') || this.isState('building-integer')) { + this.pushState('building-integer'); + this.astGeneric(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.astGeneric(ast.right, retArr); + this.popState('building-integer'); + } else { + this.pushState('building-float'); + this.castLiteralToFloat(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.castLiteralToFloat(ast.right, retArr); + this.popState('building-float'); + } + break; + + case 'Integer & Float': + case 'Integer & Number': + if (ast.operator === '>' || ast.operator === '<' && ast.right.type === 'Literal') { + // if right value is actually a float, don't loose that information, cast left to right rather than the usual right to left + if (!Number.isInteger(ast.right.value)) { + this.pushState('building-float'); + this.castValueToFloat(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.astGeneric(ast.right, retArr); + this.popState('building-float'); + break; + } + } + this.pushState('building-integer'); + this.astGeneric(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.pushState('casting-to-integer'); + if (ast.right.type === 'Literal') { + const literalResult = []; + this.astGeneric(ast.right, literalResult); + const literalType = this.getType(ast.right); + if (literalType === 'Integer') { + retArr.push(literalResult.join('')); + } else { + throw this.astErrorOutput(`Unhandled binary expression with literal`, ast); + } + } else { + retArr.push('int('); + this.astGeneric(ast.right, retArr); + retArr.push(')'); + } + this.popState('casting-to-integer'); + this.popState('building-integer'); + break; + case 'Integer & LiteralInteger': + this.pushState('building-integer'); + this.astGeneric(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.castLiteralToInteger(ast.right, retArr); + this.popState('building-integer'); + break; + + case 'Number & Integer': + this.pushState('building-float'); + this.astGeneric(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.castValueToFloat(ast.right, retArr); + this.popState('building-float'); + break; + case 'Float & LiteralInteger': + case 'Number & LiteralInteger': + this.pushState('building-float'); + this.astGeneric(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.castLiteralToFloat(ast.right, retArr); + this.popState('building-float'); + break; + case 'LiteralInteger & Float': + case 'LiteralInteger & Number': + if (this.isState('casting-to-integer')) { + this.pushState('building-integer'); + this.castLiteralToInteger(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.castValueToInteger(ast.right, retArr); + this.popState('building-integer'); + } else { + this.pushState('building-float'); + this.astGeneric(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.pushState('casting-to-float'); + this.astGeneric(ast.right, retArr); + this.popState('casting-to-float'); + this.popState('building-float'); + } + break; + case 'LiteralInteger & Integer': + this.pushState('building-integer'); + this.castLiteralToInteger(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.astGeneric(ast.right, retArr); + this.popState('building-integer'); + break; + + case 'Boolean & Boolean': + this.pushState('building-boolean'); + this.astGeneric(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.astGeneric(ast.right, retArr); + this.popState('building-boolean'); + break; + + case 'Float & Integer': + this.pushState('building-float'); + this.astGeneric(ast.left, retArr); + retArr.push(operatorMap[ast.operator] || ast.operator); + this.castValueToFloat(ast.right, retArr); + this.popState('building-float'); + break; + + default: + throw this.astErrorOutput(`Unhandled binary expression between ${key}`, ast); + } + retArr.push(')'); + + return retArr; + } + + checkAndUpconvertOperator(ast, retArr) { + const bitwiseResult = this.checkAndUpconvertBitwiseOperators(ast, retArr); + if (bitwiseResult) { + return bitwiseResult; + } + const upconvertableOperators = { + '%': this.fixIntegerDivisionAccuracy ? 'integerCorrectionModulo' : 'modulo', + '**': 'pow', + }; + const foundOperator = upconvertableOperators[ast.operator]; + if (!foundOperator) return null; + retArr.push(foundOperator); + retArr.push('('); + switch (this.getType(ast.left)) { + case 'Integer': + this.castValueToFloat(ast.left, retArr); + break; + case 'LiteralInteger': + this.castLiteralToFloat(ast.left, retArr); + break; + default: + this.astGeneric(ast.left, retArr); + } + retArr.push(','); + switch (this.getType(ast.right)) { + case 'Integer': + this.castValueToFloat(ast.right, retArr); + break; + case 'LiteralInteger': + this.castLiteralToFloat(ast.right, retArr); + break; + default: + this.astGeneric(ast.right, retArr); + } + retArr.push(')'); + return retArr; + } + + checkAndUpconvertBitwiseOperators(ast, retArr) { + const upconvertableOperators = { + '&': 'bitwiseAnd', + '|': 'bitwiseOr', + '^': 'bitwiseXOR', + '<<': 'bitwiseZeroFillLeftShift', + '>>': 'bitwiseSignedRightShift', + '>>>': 'bitwiseZeroFillRightShift', + }; + const foundOperator = upconvertableOperators[ast.operator]; + if (!foundOperator) return null; + retArr.push(foundOperator); + retArr.push('('); + const leftType = this.getType(ast.left); + switch (leftType) { + case 'Number': + case 'Float': + this.castValueToInteger(ast.left, retArr); + break; + case 'LiteralInteger': + this.castLiteralToInteger(ast.left, retArr); + break; + default: + this.astGeneric(ast.left, retArr); + } + retArr.push(','); + const rightType = this.getType(ast.right); + switch (rightType) { + case 'Number': + case 'Float': + this.castValueToInteger(ast.right, retArr); + break; + case 'LiteralInteger': + this.castLiteralToInteger(ast.right, retArr); + break; + default: + this.astGeneric(ast.right, retArr); + } + retArr.push(')'); + return retArr; + } + + checkAndUpconvertBitwiseUnary(ast, retArr) { + const upconvertableOperators = { + '~': 'bitwiseNot', + }; + const foundOperator = upconvertableOperators[ast.operator]; + if (!foundOperator) return null; + retArr.push(foundOperator); + retArr.push('('); + switch (this.getType(ast.argument)) { + case 'Number': + case 'Float': + this.castValueToInteger(ast.argument, retArr); + break; + case 'LiteralInteger': + this.castLiteralToInteger(ast.argument, retArr); + break; + default: + this.astGeneric(ast.argument, retArr); + } + retArr.push(')'); + return retArr; + } + + /** + * + * @param {Object} ast + * @param {Array} retArr + * @return {String[]} + */ + castLiteralToInteger(ast, retArr) { + this.pushState('casting-to-integer'); + this.astGeneric(ast, retArr); + this.popState('casting-to-integer'); + return retArr; + } + + /** + * + * @param {Object} ast + * @param {Array} retArr + * @return {String[]} + */ + castLiteralToFloat(ast, retArr) { + this.pushState('casting-to-float'); + this.astGeneric(ast, retArr); + this.popState('casting-to-float'); + return retArr; + } + + /** + * + * @param {Object} ast + * @param {Array} retArr + * @return {String[]} + */ + castValueToInteger(ast, retArr) { + this.pushState('casting-to-integer'); + retArr.push('int('); + this.astGeneric(ast, retArr); + retArr.push(')'); + this.popState('casting-to-integer'); + return retArr; + } + + /** + * + * @param {Object} ast + * @param {Array} retArr + * @return {String[]} + */ + castValueToFloat(ast, retArr) { + this.pushState('casting-to-float'); + retArr.push('float('); + this.astGeneric(ast, retArr); + retArr.push(')'); + this.popState('casting-to-float'); + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *identifier* expression + * @param {Object} idtNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astIdentifierExpression(idtNode, retArr) { + if (idtNode.type !== 'Identifier') { + throw this.astErrorOutput('IdentifierExpression - not an Identifier', idtNode); + } + + const type = this.getType(idtNode); + + const name = utils.sanitizeName(idtNode.name); + if (idtNode.name === 'Infinity') { + // https://stackoverflow.com/a/47543127/1324039 + retArr.push('3.402823466e+38'); + } else if (type === 'Boolean') { + if (this.argumentNames.indexOf(name) > -1) { + retArr.push(`bool(user_${name})`); + } else { + retArr.push(`user_${name}`); + } + } else { + retArr.push(`user_${name}`); + } + + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *for-loop* expression + * @param {Object} forNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the parsed webgl string + */ + astForStatement(forNode, retArr) { + if (forNode.type !== 'ForStatement') { + throw this.astErrorOutput('Invalid for statement', forNode); + } + + const initArr = []; + const testArr = []; + const updateArr = []; + const bodyArr = []; + let isSafe = null; + + if (forNode.init) { + const { declarations } = forNode.init; + if (declarations.length > 1) { + isSafe = false; + } + this.astGeneric(forNode.init, initArr); + for (let i = 0; i < declarations.length; i++) { + if (declarations[i].init && declarations[i].init.type !== 'Literal') { + isSafe = false; + } + } + } else { + isSafe = false; + } + + if (forNode.test) { + this.astGeneric(forNode.test, testArr); + } else { + isSafe = false; + } + + if (forNode.update) { + this.astGeneric(forNode.update, updateArr); + } else { + isSafe = false; + } + + if (forNode.body) { + this.pushState('loop-body'); + this.astGeneric(forNode.body, bodyArr); + this.popState('loop-body'); + } + + // have all parts, now make them safe + if (isSafe === null) { + isSafe = this.isSafe(forNode.init) && this.isSafe(forNode.test); + } + + if (isSafe) { + const initString = initArr.join(''); + const initNeedsSemiColon = initString[initString.length - 1] !== ';'; + retArr.push(`for (${initString}${initNeedsSemiColon ? ';' : ''}${testArr.join('')};${updateArr.join('')}){\n`); + retArr.push(bodyArr.join('')); + retArr.push('}\n'); + } else { + const iVariableName = this.getInternalVariableName('safeI'); + if (initArr.length > 0) { + retArr.push(initArr.join(''), '\n'); + } + retArr.push(`for (int ${iVariableName}=0;${iVariableName} 0) { + retArr.push(`if (!${testArr.join('')}) break;\n`); + } + retArr.push(bodyArr.join('')); + retArr.push(`\n${updateArr.join('')};`); + retArr.push('}\n'); + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *while* loop + * @param {Object} whileNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the parsed webgl string + */ + astWhileStatement(whileNode, retArr) { + if (whileNode.type !== 'WhileStatement') { + throw this.astErrorOutput('Invalid while statement', whileNode); + } + + const iVariableName = this.getInternalVariableName('safeI'); + retArr.push(`for (int ${iVariableName}=0;${iVariableName} 0) { + declarationSets.push(declarationSet.join(',')); + } + + result.push(declarationSets.join(';')); + + retArr.push(result.join('')); + retArr.push(';'); + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *If* Statement + * @param {Object} ifNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astIfStatement(ifNode, retArr) { + retArr.push('if ('); + this.astGeneric(ifNode.test, retArr); + retArr.push(')'); + if (ifNode.consequent.type === 'BlockStatement') { + this.astGeneric(ifNode.consequent, retArr); + } else { + retArr.push(' {\n'); + this.astGeneric(ifNode.consequent, retArr); + retArr.push('\n}\n'); + } + + if (ifNode.alternate) { + retArr.push('else '); + if (ifNode.alternate.type === 'BlockStatement' || ifNode.alternate.type === 'IfStatement') { + this.astGeneric(ifNode.alternate, retArr); + } else { + retArr.push(' {\n'); + this.astGeneric(ifNode.alternate, retArr); + retArr.push('\n}\n'); + } + } + return retArr; + } + + astSwitchStatement(ast, retArr) { + if (ast.type !== 'SwitchStatement') { + throw this.astErrorOutput('Invalid switch statement', ast); + } + const { discriminant, cases } = ast; + const type = this.getType(discriminant); + const varName = `switchDiscriminant${this.astKey(ast, '_')}`; + switch (type) { + case 'Float': + case 'Number': + retArr.push(`float ${varName} = `); + this.astGeneric(discriminant, retArr); + retArr.push(';\n'); + break; + case 'Integer': + retArr.push(`int ${varName} = `); + this.astGeneric(discriminant, retArr); + retArr.push(';\n'); + break; + } + // switch with just a default: + if (cases.length === 1 && !cases[0].test) { + this.astGeneric(cases[0].consequent, retArr); + return retArr; + } + + // regular switches: + let fallingThrough = false; + let defaultResult = []; + let movingDefaultToEnd = false; + let pastFirstIf = false; + for (let i = 0; i < cases.length; i++) { + // default + if (!cases[i].test) { + if (cases.length > i + 1) { + movingDefaultToEnd = true; + this.astGeneric(cases[i].consequent, defaultResult); + continue; + } else { + retArr.push(' else {\n'); + } + } else { + // all others + if (i === 0 || !pastFirstIf) { + pastFirstIf = true; + retArr.push(`if (${varName} == `); + } else { + if (fallingThrough) { + retArr.push(`${varName} == `); + fallingThrough = false; + } else { + retArr.push(` else if (${varName} == `); + } + } + if (type === 'Integer') { + const testType = this.getType(cases[i].test); + switch (testType) { + case 'Number': + case 'Float': + this.castValueToInteger(cases[i].test, retArr); + break; + case 'LiteralInteger': + this.castLiteralToInteger(cases[i].test, retArr); + break; + } + } else if (type === 'Float') { + const testType = this.getType(cases[i].test); + switch (testType) { + case 'LiteralInteger': + this.castLiteralToFloat(cases[i].test, retArr); + break; + case 'Integer': + this.castValueToFloat(cases[i].test, retArr); + break; + } + } else { + throw new Error('unhanlded'); + } + if (!cases[i].consequent || cases[i].consequent.length === 0) { + fallingThrough = true; + retArr.push(' || '); + continue; + } + retArr.push(`) {\n`); + } + this.astGeneric(cases[i].consequent, retArr); + retArr.push('\n}'); + } + if (movingDefaultToEnd) { + retArr.push(' else {'); + retArr.push(defaultResult.join('')); + retArr.push('}'); + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *This* expression + * @param {Object} tNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astThisExpression(tNode, retArr) { + retArr.push('this'); + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *Member* Expression + * @param {Object} mNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astMemberExpression(mNode, retArr) { + const { + property, + name, + signature, + origin, + type, + xProperty, + yProperty, + zProperty + } = this.getMemberExpressionDetails(mNode); + switch (signature) { + case 'value.thread.value': + case 'this.thread.value': + if (name !== 'x' && name !== 'y' && name !== 'z') { + throw this.astErrorOutput('Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`', mNode); + } + retArr.push(`threadId.${name}`); + return retArr; + case 'this.output.value': + if (this.dynamicOutput) { + switch (name) { + case 'x': + if (this.isState('casting-to-float')) { + retArr.push('float(uOutputDim.x)'); + } else { + retArr.push('uOutputDim.x'); + } + break; + case 'y': + if (this.isState('casting-to-float')) { + retArr.push('float(uOutputDim.y)'); + } else { + retArr.push('uOutputDim.y'); + } + break; + case 'z': + if (this.isState('casting-to-float')) { + retArr.push('float(uOutputDim.z)'); + } else { + retArr.push('uOutputDim.z'); + } + break; + default: + throw this.astErrorOutput('Unexpected expression', mNode); + } + } else { + switch (name) { + case 'x': + if (this.isState('casting-to-integer')) { + retArr.push(this.output[0]); + } else { + retArr.push(this.output[0], '.0'); + } + break; + case 'y': + if (this.isState('casting-to-integer')) { + retArr.push(this.output[1]); + } else { + retArr.push(this.output[1], '.0'); + } + break; + case 'z': + if (this.isState('casting-to-integer')) { + retArr.push(this.output[2]); + } else { + retArr.push(this.output[2], '.0'); + } + break; + default: + throw this.astErrorOutput('Unexpected expression', mNode); + } + } + return retArr; + case 'value': + throw this.astErrorOutput('Unexpected expression', mNode); + case 'value[]': + case 'value[][]': + case 'value[][][]': + case 'value[][][][]': + case 'value.value': + if (origin === 'Math') { + retArr.push(Math[name]); + return retArr; + } + const cleanName = utils.sanitizeName(name); + switch (property) { + case 'r': + retArr.push(`user_${ cleanName }.r`); + return retArr; + case 'g': + retArr.push(`user_${ cleanName }.g`); + return retArr; + case 'b': + retArr.push(`user_${ cleanName }.b`); + return retArr; + case 'a': + retArr.push(`user_${ cleanName }.a`); + return retArr; + } + break; + case 'this.constants.value': + if (typeof xProperty === 'undefined') { + switch (type) { + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + retArr.push(`constants_${ utils.sanitizeName(name) }`); + return retArr; + } + } + case 'this.constants.value[]': + case 'this.constants.value[][]': + case 'this.constants.value[][][]': + case 'this.constants.value[][][][]': + break; + case 'fn()[]': + this.astCallExpression(mNode.object, retArr); + retArr.push('['); + retArr.push(this.memberExpressionPropertyMarkup(property)); + retArr.push(']'); + return retArr; + case 'fn()[][]': + this.astCallExpression(mNode.object.object, retArr); + retArr.push('['); + retArr.push(this.memberExpressionPropertyMarkup(mNode.object.property)); + retArr.push(']'); + retArr.push('['); + retArr.push(this.memberExpressionPropertyMarkup(mNode.property)); + retArr.push(']'); + return retArr; + case '[][]': + this.astArrayExpression(mNode.object, retArr); + retArr.push('['); + retArr.push(this.memberExpressionPropertyMarkup(property)); + retArr.push(']'); + return retArr; + default: + throw this.astErrorOutput('Unexpected expression', mNode); + } + + if (mNode.computed === false) { + // handle simple types + switch (type) { + case 'Number': + case 'Integer': + case 'Float': + case 'Boolean': + retArr.push(`${origin}_${utils.sanitizeName(name)}`); + return retArr; + } + } + + // handle more complex types + // argument may have come from a parent + const markupName = `${origin}_${utils.sanitizeName(name)}`; + + switch (type) { + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + // Get from local vec4 + this.astGeneric(mNode.object, retArr); + retArr.push('['); + retArr.push(this.memberExpressionPropertyMarkup(xProperty)); + retArr.push(']'); + break; + case 'HTMLImageArray': + retArr.push(`getImage3D(${ markupName }, ${ markupName }Size, ${ markupName }Dim, `); + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + break; + case 'ArrayTexture(1)': + retArr.push(`getFloatFromSampler2D(${ markupName }, ${ markupName }Size, ${ markupName }Dim, `); + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + break; + case 'Array1D(2)': + case 'Array2D(2)': + case 'Array3D(2)': + retArr.push(`getMemoryOptimizedVec2(${ markupName }, ${ markupName }Size, ${ markupName }Dim, `); + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + break; + case 'ArrayTexture(2)': + retArr.push(`getVec2FromSampler2D(${ markupName }, ${ markupName }Size, ${ markupName }Dim, `); + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + break; + case 'Array1D(3)': + case 'Array2D(3)': + case 'Array3D(3)': + retArr.push(`getMemoryOptimizedVec3(${ markupName }, ${ markupName }Size, ${ markupName }Dim, `); + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + break; + case 'ArrayTexture(3)': + retArr.push(`getVec3FromSampler2D(${ markupName }, ${ markupName }Size, ${ markupName }Dim, `); + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + break; + case 'Array1D(4)': + case 'Array2D(4)': + case 'Array3D(4)': + retArr.push(`getMemoryOptimizedVec4(${ markupName }, ${ markupName }Size, ${ markupName }Dim, `); + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + break; + case 'ArrayTexture(4)': + case 'HTMLCanvas': + case 'HTMLImage': + case 'HTMLVideo': + retArr.push(`getVec4FromSampler2D(${ markupName }, ${ markupName }Size, ${ markupName }Dim, `); + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + break; + case 'NumberTexture': + case 'Array': + case 'Array2D': + case 'Array3D': + case 'Array4D': + case 'Input': + case 'Number': + case 'Float': + case 'Integer': + if (this.precision === 'single') { + // bitRatio is always 4 here, javascript doesn't yet have 8 or 16 bit support + // TODO: make 8 or 16 bit work anyway! + retArr.push(`getMemoryOptimized32(${markupName}, ${markupName}Size, ${markupName}Dim, `); + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + } else { + const bitRatio = (origin === 'user' ? + this.lookupFunctionArgumentBitRatio(this.name, name) : + this.constantBitRatios[name] + ); + switch (bitRatio) { + case 1: + retArr.push(`get8(${markupName}, ${markupName}Size, ${markupName}Dim, `); + break; + case 2: + retArr.push(`get16(${markupName}, ${markupName}Size, ${markupName}Dim, `); + break; + case 4: + case 0: + retArr.push(`get32(${markupName}, ${markupName}Size, ${markupName}Dim, `); + break; + default: + throw new Error(`unhandled bit ratio of ${bitRatio}`); + } + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + } + break; + case 'MemoryOptimizedNumberTexture': + retArr.push(`getMemoryOptimized32(${ markupName }, ${ markupName }Size, ${ markupName }Dim, `); + this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); + retArr.push(')'); + break; + case 'Matrix(2)': + case 'Matrix(3)': + case 'Matrix(4)': + retArr.push(`${markupName}[${this.memberExpressionPropertyMarkup(yProperty)}]`); + if (yProperty) { + retArr.push(`[${this.memberExpressionPropertyMarkup(xProperty)}]`); + } + break; + default: + throw new Error(`unhandled member expression "${ type }"`); + } + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *call* expression + * @param {Object} ast - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astCallExpression(ast, retArr) { + if (!ast.callee) { + throw this.astErrorOutput('Unknown CallExpression', ast); + } + + let functionName = null; + const isMathFunction = this.isAstMathFunction(ast); + + // Its a math operator or this.something(), remove the prefix + if (isMathFunction || (ast.callee.object && ast.callee.object.type === 'ThisExpression')) { + functionName = ast.callee.property.name; + } + // Issue #212, BABEL! + else if (ast.callee.type === 'SequenceExpression' && ast.callee.expressions[0].type === 'Literal' && !isNaN(ast.callee.expressions[0].raw)) { + functionName = ast.callee.expressions[1].property.name; + } else { + functionName = ast.callee.name; + } + + if (!functionName) { + throw this.astErrorOutput(`Unhandled function, couldn't find name`, ast); + } + + // if this if grows to more than one, lets use a switch + switch (functionName) { + case 'pow': + functionName = '_pow'; + break; + case 'round': + functionName = '_round'; + break; + } + + // Register the function into the called registry + if (this.calledFunctions.indexOf(functionName) < 0) { + this.calledFunctions.push(functionName); + } + + if (functionName === 'random' && this.plugins && this.plugins.length > 0) { + for (let i = 0; i < this.plugins.length; i++) { + const plugin = this.plugins[i]; + if (plugin.functionMatch === 'Math.random()' && plugin.functionReplace) { + retArr.push(plugin.functionReplace); + return retArr; + } + } + } + + // track the function was called + if (this.onFunctionCall) { + this.onFunctionCall(this.name, functionName, ast.arguments); + } + + // Call the function + retArr.push(functionName); + + // Open arguments space + retArr.push('('); + + // Add the arguments + if (isMathFunction) { + for (let i = 0; i < ast.arguments.length; ++i) { + const argument = ast.arguments[i]; + const argumentType = this.getType(argument); + if (i > 0) { + retArr.push(', '); + } + + switch (argumentType) { + case 'Integer': + this.castValueToFloat(argument, retArr); + break; + default: + this.astGeneric(argument, retArr); + break; + } + } + } else { + const targetTypes = this.lookupFunctionArgumentTypes(functionName) || []; + for (let i = 0; i < ast.arguments.length; ++i) { + const argument = ast.arguments[i]; + let targetType = targetTypes[i]; + if (i > 0) { + retArr.push(', '); + } + const argumentType = this.getType(argument); + if (!targetType) { + this.triggerImplyArgumentType(functionName, i, argumentType, this); + targetType = argumentType; + } + switch (argumentType) { + case 'Boolean': + this.astGeneric(argument, retArr); + continue; + case 'Number': + case 'Float': + if (targetType === 'Integer') { + retArr.push('int('); + this.astGeneric(argument, retArr); + retArr.push(')'); + continue; + } else if (targetType === 'Number' || targetType === 'Float') { + this.astGeneric(argument, retArr); + continue; + } else if (targetType === 'LiteralInteger') { + this.castLiteralToFloat(argument, retArr); + continue; + } + break; + case 'Integer': + if (targetType === 'Number' || targetType === 'Float') { + retArr.push('float('); + this.astGeneric(argument, retArr); + retArr.push(')'); + continue; + } else if (targetType === 'Integer') { + this.astGeneric(argument, retArr); + continue; + } + break; + case 'LiteralInteger': + if (targetType === 'Integer') { + this.castLiteralToInteger(argument, retArr); + continue; + } else if (targetType === 'Number' || targetType === 'Float') { + this.castLiteralToFloat(argument, retArr); + continue; + } else if (targetType === 'LiteralInteger') { + this.astGeneric(argument, retArr); + continue; + } + break; + case 'Array(2)': + case 'Array(3)': + case 'Array(4)': + if (targetType === argumentType) { + if (argument.type === 'Identifier') { + retArr.push(`user_${utils.sanitizeName(argument.name)}`); + } else if (argument.type === 'ArrayExpression' || argument.type === 'MemberExpression' || argument.type === 'CallExpression') { + this.astGeneric(argument, retArr); + } else { + throw this.astErrorOutput(`Unhandled argument type ${ argument.type }`, ast); + } + continue; + } + break; + case 'HTMLCanvas': + case 'HTMLImage': + case 'HTMLImageArray': + case 'HTMLVideo': + case 'ArrayTexture(1)': + case 'ArrayTexture(2)': + case 'ArrayTexture(3)': + case 'ArrayTexture(4)': + case 'Array': + case 'Input': + if (targetType === argumentType) { + if (argument.type !== 'Identifier') throw this.astErrorOutput(`Unhandled argument type ${ argument.type }`, ast); + this.triggerImplyArgumentBitRatio(this.name, argument.name, functionName, i); + const name = utils.sanitizeName(argument.name); + retArr.push(`user_${name},user_${name}Size,user_${name}Dim`); + continue; + } + break; + } + throw this.astErrorOutput(`Unhandled argument combination of ${ argumentType } and ${ targetType } for argument named "${ argument.name }"`, ast); + } + } + // Close arguments space + retArr.push(')'); + + return retArr; + } + + /** + * @desc Parses the abstract syntax tree for *Array* Expression + * @param {Object} arrNode - the AST object to parse + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astArrayExpression(arrNode, retArr) { + const returnType = this.getType(arrNode); + + const arrLen = arrNode.elements.length; + + switch (returnType) { + case 'Matrix(2)': + case 'Matrix(3)': + case 'Matrix(4)': + retArr.push(`mat${arrLen}(`); + break; + default: + retArr.push(`vec${arrLen}(`); + } + for (let i = 0; i < arrLen; ++i) { + if (i > 0) { + retArr.push(', '); + } + const subNode = arrNode.elements[i]; + this.astGeneric(subNode, retArr) + } + retArr.push(')'); + + return retArr; + } + + memberExpressionXYZ(x, y, z, retArr) { + if (z) { + retArr.push(this.memberExpressionPropertyMarkup(z), ', '); + } else { + retArr.push('0, '); + } + if (y) { + retArr.push(this.memberExpressionPropertyMarkup(y), ', '); + } else { + retArr.push('0, '); + } + retArr.push(this.memberExpressionPropertyMarkup(x)); + return retArr; + } + + memberExpressionPropertyMarkup(property) { + if (!property) { + throw new Error('Property not set'); + } + const type = this.getType(property); + const result = []; + switch (type) { + case 'Number': + case 'Float': + this.castValueToInteger(property, result); + break; + case 'LiteralInteger': + this.castLiteralToInteger(property, result); + break; + default: + this.astGeneric(property, result); + } + return result.join(''); + } +} + +const typeMap = { + 'Array': 'sampler2D', + 'Array(2)': 'vec2', + 'Array(3)': 'vec3', + 'Array(4)': 'vec4', + 'Matrix(2)': 'mat2', + 'Matrix(3)': 'mat3', + 'Matrix(4)': 'mat4', + 'Array2D': 'sampler2D', + 'Array3D': 'sampler2D', + 'Boolean': 'bool', + 'Float': 'float', + 'Input': 'sampler2D', + 'Integer': 'int', + 'Number': 'float', + 'LiteralInteger': 'float', + 'NumberTexture': 'sampler2D', + 'MemoryOptimizedNumberTexture': 'sampler2D', + 'ArrayTexture(1)': 'sampler2D', + 'ArrayTexture(2)': 'sampler2D', + 'ArrayTexture(3)': 'sampler2D', + 'ArrayTexture(4)': 'sampler2D', + 'HTMLVideo': 'sampler2D', + 'HTMLCanvas': 'sampler2D', + 'HTMLImage': 'sampler2D', + 'HTMLImageArray': 'sampler2DArray', +}; + +const operatorMap = { + '===': '==', + '!==': '!=' +}; + +module.exports = { + WebGLFunctionNode +}; +},{"../../utils":291,"../function-node":189}],218:[function(require,module,exports){ +const { WebGLKernelValueBoolean } = require('./kernel-value/boolean'); +const { WebGLKernelValueFloat } = require('./kernel-value/float'); +const { WebGLKernelValueInteger } = require('./kernel-value/integer'); + +const { WebGLKernelValueHTMLImage } = require('./kernel-value/html-image'); +const { WebGLKernelValueDynamicHTMLImage } = require('./kernel-value/dynamic-html-image'); + +const { WebGLKernelValueHTMLVideo } = require('./kernel-value/html-video'); +const { WebGLKernelValueDynamicHTMLVideo } = require('./kernel-value/dynamic-html-video'); + +const { WebGLKernelValueSingleInput } = require('./kernel-value/single-input'); +const { WebGLKernelValueDynamicSingleInput } = require('./kernel-value/dynamic-single-input'); + +const { WebGLKernelValueUnsignedInput } = require('./kernel-value/unsigned-input'); +const { WebGLKernelValueDynamicUnsignedInput } = require('./kernel-value/dynamic-unsigned-input'); + +const { WebGLKernelValueMemoryOptimizedNumberTexture } = require('./kernel-value/memory-optimized-number-texture'); +const { WebGLKernelValueDynamicMemoryOptimizedNumberTexture } = require('./kernel-value/dynamic-memory-optimized-number-texture'); + +const { WebGLKernelValueNumberTexture } = require('./kernel-value/number-texture'); +const { WebGLKernelValueDynamicNumberTexture } = require('./kernel-value/dynamic-number-texture'); + +const { WebGLKernelValueSingleArray } = require('./kernel-value/single-array'); +const { WebGLKernelValueDynamicSingleArray } = require('./kernel-value/dynamic-single-array'); + +const { WebGLKernelValueSingleArray1DI } = require('./kernel-value/single-array1d-i'); +const { WebGLKernelValueDynamicSingleArray1DI } = require('./kernel-value/dynamic-single-array1d-i'); + +const { WebGLKernelValueSingleArray2DI } = require('./kernel-value/single-array2d-i'); +const { WebGLKernelValueDynamicSingleArray2DI } = require('./kernel-value/dynamic-single-array2d-i'); + +const { WebGLKernelValueSingleArray3DI } = require('./kernel-value/single-array3d-i'); +const { WebGLKernelValueDynamicSingleArray3DI } = require('./kernel-value/dynamic-single-array3d-i'); + +const { WebGLKernelValueArray2 } = require('./kernel-value/array2'); +const { WebGLKernelValueArray3 } = require('./kernel-value/array3'); +const { WebGLKernelValueArray4 } = require('./kernel-value/array4'); + +const { WebGLKernelValueUnsignedArray } = require('./kernel-value/unsigned-array'); +const { WebGLKernelValueDynamicUnsignedArray } = require('./kernel-value/dynamic-unsigned-array'); + +const kernelValueMaps = { + unsigned: { + dynamic: { + 'Boolean': WebGLKernelValueBoolean, + 'Integer': WebGLKernelValueInteger, + 'Float': WebGLKernelValueFloat, + 'Array': WebGLKernelValueDynamicUnsignedArray, + 'Array(2)': WebGLKernelValueArray2, + 'Array(3)': WebGLKernelValueArray3, + 'Array(4)': WebGLKernelValueArray4, + 'Array1D(2)': false, + 'Array1D(3)': false, + 'Array1D(4)': false, + 'Array2D(2)': false, + 'Array2D(3)': false, + 'Array2D(4)': false, + 'Array3D(2)': false, + 'Array3D(3)': false, + 'Array3D(4)': false, + 'Input': WebGLKernelValueDynamicUnsignedInput, + 'NumberTexture': WebGLKernelValueDynamicNumberTexture, + 'ArrayTexture(1)': WebGLKernelValueDynamicNumberTexture, + 'ArrayTexture(2)': WebGLKernelValueDynamicNumberTexture, + 'ArrayTexture(3)': WebGLKernelValueDynamicNumberTexture, + 'ArrayTexture(4)': WebGLKernelValueDynamicNumberTexture, + 'MemoryOptimizedNumberTexture': WebGLKernelValueDynamicMemoryOptimizedNumberTexture, + 'HTMLCanvas': WebGLKernelValueDynamicHTMLImage, + 'HTMLImage': WebGLKernelValueDynamicHTMLImage, + 'HTMLImageArray': false, + 'HTMLVideo': WebGLKernelValueDynamicHTMLVideo, + }, + static: { + 'Boolean': WebGLKernelValueBoolean, + 'Float': WebGLKernelValueFloat, + 'Integer': WebGLKernelValueInteger, + 'Array': WebGLKernelValueUnsignedArray, + 'Array(2)': WebGLKernelValueArray2, + 'Array(3)': WebGLKernelValueArray3, + 'Array(4)': WebGLKernelValueArray4, + 'Array1D(2)': false, + 'Array1D(3)': false, + 'Array1D(4)': false, + 'Array2D(2)': false, + 'Array2D(3)': false, + 'Array2D(4)': false, + 'Array3D(2)': false, + 'Array3D(3)': false, + 'Array3D(4)': false, + 'Input': WebGLKernelValueUnsignedInput, + 'NumberTexture': WebGLKernelValueNumberTexture, + 'ArrayTexture(1)': WebGLKernelValueNumberTexture, + 'ArrayTexture(2)': WebGLKernelValueNumberTexture, + 'ArrayTexture(3)': WebGLKernelValueNumberTexture, + 'ArrayTexture(4)': WebGLKernelValueNumberTexture, + 'MemoryOptimizedNumberTexture': WebGLKernelValueMemoryOptimizedNumberTexture, + 'HTMLCanvas': WebGLKernelValueHTMLImage, + 'HTMLImage': WebGLKernelValueHTMLImage, + 'HTMLImageArray': false, + 'HTMLVideo': WebGLKernelValueHTMLVideo, + } + }, + single: { + dynamic: { + 'Boolean': WebGLKernelValueBoolean, + 'Integer': WebGLKernelValueInteger, + 'Float': WebGLKernelValueFloat, + 'Array': WebGLKernelValueDynamicSingleArray, + 'Array(2)': WebGLKernelValueArray2, + 'Array(3)': WebGLKernelValueArray3, + 'Array(4)': WebGLKernelValueArray4, + 'Array1D(2)': WebGLKernelValueDynamicSingleArray1DI, + 'Array1D(3)': WebGLKernelValueDynamicSingleArray1DI, + 'Array1D(4)': WebGLKernelValueDynamicSingleArray1DI, + 'Array2D(2)': WebGLKernelValueDynamicSingleArray2DI, + 'Array2D(3)': WebGLKernelValueDynamicSingleArray2DI, + 'Array2D(4)': WebGLKernelValueDynamicSingleArray2DI, + 'Array3D(2)': WebGLKernelValueDynamicSingleArray3DI, + 'Array3D(3)': WebGLKernelValueDynamicSingleArray3DI, + 'Array3D(4)': WebGLKernelValueDynamicSingleArray3DI, + 'Input': WebGLKernelValueDynamicSingleInput, + 'NumberTexture': WebGLKernelValueDynamicNumberTexture, + 'ArrayTexture(1)': WebGLKernelValueDynamicNumberTexture, + 'ArrayTexture(2)': WebGLKernelValueDynamicNumberTexture, + 'ArrayTexture(3)': WebGLKernelValueDynamicNumberTexture, + 'ArrayTexture(4)': WebGLKernelValueDynamicNumberTexture, + 'MemoryOptimizedNumberTexture': WebGLKernelValueDynamicMemoryOptimizedNumberTexture, + 'HTMLCanvas': WebGLKernelValueDynamicHTMLImage, + 'HTMLImage': WebGLKernelValueDynamicHTMLImage, + 'HTMLImageArray': false, + 'HTMLVideo': WebGLKernelValueDynamicHTMLVideo, + }, + static: { + 'Boolean': WebGLKernelValueBoolean, + 'Float': WebGLKernelValueFloat, + 'Integer': WebGLKernelValueInteger, + 'Array': WebGLKernelValueSingleArray, + 'Array(2)': WebGLKernelValueArray2, + 'Array(3)': WebGLKernelValueArray3, + 'Array(4)': WebGLKernelValueArray4, + 'Array1D(2)': WebGLKernelValueSingleArray1DI, + 'Array1D(3)': WebGLKernelValueSingleArray1DI, + 'Array1D(4)': WebGLKernelValueSingleArray1DI, + 'Array2D(2)': WebGLKernelValueSingleArray2DI, + 'Array2D(3)': WebGLKernelValueSingleArray2DI, + 'Array2D(4)': WebGLKernelValueSingleArray2DI, + 'Array3D(2)': WebGLKernelValueSingleArray3DI, + 'Array3D(3)': WebGLKernelValueSingleArray3DI, + 'Array3D(4)': WebGLKernelValueSingleArray3DI, + 'Input': WebGLKernelValueSingleInput, + 'NumberTexture': WebGLKernelValueNumberTexture, + 'ArrayTexture(1)': WebGLKernelValueNumberTexture, + 'ArrayTexture(2)': WebGLKernelValueNumberTexture, + 'ArrayTexture(3)': WebGLKernelValueNumberTexture, + 'ArrayTexture(4)': WebGLKernelValueNumberTexture, + 'MemoryOptimizedNumberTexture': WebGLKernelValueMemoryOptimizedNumberTexture, + 'HTMLCanvas': WebGLKernelValueHTMLImage, + 'HTMLImage': WebGLKernelValueHTMLImage, + 'HTMLImageArray': false, + 'HTMLVideo': WebGLKernelValueHTMLVideo, + } + }, +}; + +function lookupKernelValueType(type, dynamic, precision, value) { + if (!type) { + throw new Error('type missing'); + } + if (!dynamic) { + throw new Error('dynamic missing'); + } + if (!precision) { + throw new Error('precision missing'); + } + if (value.type) { + type = value.type; + } + const types = kernelValueMaps[precision][dynamic]; + if (types[type] === false) { + return null; + } else if (types[type] === undefined) { + throw new Error(`Could not find a KernelValue for ${ type }`); + } + return types[type]; +} + +module.exports = { + lookupKernelValueType, + kernelValueMaps, +}; +},{"./kernel-value/array2":220,"./kernel-value/array3":221,"./kernel-value/array4":222,"./kernel-value/boolean":223,"./kernel-value/dynamic-html-image":224,"./kernel-value/dynamic-html-video":225,"./kernel-value/dynamic-memory-optimized-number-texture":226,"./kernel-value/dynamic-number-texture":227,"./kernel-value/dynamic-single-array":228,"./kernel-value/dynamic-single-array1d-i":229,"./kernel-value/dynamic-single-array2d-i":230,"./kernel-value/dynamic-single-array3d-i":231,"./kernel-value/dynamic-single-input":232,"./kernel-value/dynamic-unsigned-array":233,"./kernel-value/dynamic-unsigned-input":234,"./kernel-value/float":235,"./kernel-value/html-image":236,"./kernel-value/html-video":237,"./kernel-value/integer":239,"./kernel-value/memory-optimized-number-texture":240,"./kernel-value/number-texture":241,"./kernel-value/single-array":242,"./kernel-value/single-array1d-i":243,"./kernel-value/single-array2d-i":244,"./kernel-value/single-array3d-i":245,"./kernel-value/single-input":246,"./kernel-value/unsigned-array":247,"./kernel-value/unsigned-input":248}],219:[function(require,module,exports){ +const { WebGLKernelValue } = require('./index'); +const { Input } = require('../../../input'); + +/** + * @abstract + */ +class WebGLKernelArray extends WebGLKernelValue { + /** + * + * @param {number} width + * @param {number} height + */ + checkSize(width, height) { + if (!this.kernel.validate) return; + const { maxTextureSize } = this.kernel.constructor.features; + if (width > maxTextureSize || height > maxTextureSize) { + if (width > height) { + throw new Error(`Argument texture width of ${width} larger than maximum size of ${maxTextureSize} for your GPU`); + } else if (width < height) { + throw new Error(`Argument texture height of ${height} larger than maximum size of ${maxTextureSize} for your GPU`); + } else { + throw new Error(`Argument texture height and width of ${height} larger than maximum size of ${maxTextureSize} for your GPU`); + } + } + } + + setup() { + this.requestTexture(); + this.setupTexture(); + this.defineTexture(); + } + + requestTexture() { + this.texture = this.onRequestTexture(); + } + + defineTexture() { + const { context: gl } = this; + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + } + + setupTexture() { + this.contextHandle = this.onRequestContextHandle(); + this.index = this.onRequestIndex(); + this.dimensionsId = this.id + 'Dim'; + this.sizeId = this.id + 'Size'; + } + + /** + * bit storage ratio of source to target 'buffer', i.e. if 8bit array -> 32bit tex = 4 + * @param value + * @returns {number} + */ + getBitRatio(value) { + if (Array.isArray(value[0])) { + return this.getBitRatio(value[0]); + } else if (value.constructor === Input) { + return this.getBitRatio(value.value); + } + switch (value.constructor) { + case Uint8ClampedArray: + case Uint8Array: + case Int8Array: + return 1; + case Uint16Array: + case Int16Array: + return 2; + case Float32Array: + case Int32Array: + default: + return 4; + } + } + + destroy() { + if (this.prevArg) { + this.prevArg.delete(); + } + this.context.deleteTexture(this.texture); + } +} + +module.exports = { + WebGLKernelArray +}; +},{"../../../input":287,"./index":238}],220:[function(require,module,exports){ +const { WebGLKernelValue } = require('./index'); + +class WebGLKernelValueArray2 extends WebGLKernelValue { + constructor(value, settings) { + super(value, settings); + this.uploadValue = value; + } + getSource(value) { + if (this.origin === 'constants') { + return `const vec2 ${this.id} = vec2(${value[0]},${value[1]});\n`; + } + return `uniform vec2 ${this.id};\n`; + } + + getStringValueHandler() { + // resetting isn't supported for Array(2) + if (this.origin === 'constants') return ''; + return `const uploadValue_${this.name} = ${this.varName};\n`; + } + + updateValue(value) { + if (this.origin === 'constants') return; + this.kernel.setUniform2fv(this.id, this.uploadValue = value); + } +} + +module.exports = { + WebGLKernelValueArray2 +}; +},{"./index":238}],221:[function(require,module,exports){ +const { WebGLKernelValue } = require('./index'); + +class WebGLKernelValueArray3 extends WebGLKernelValue { + constructor(value, settings) { + super(value, settings); + this.uploadValue = value; + } + getSource(value) { + if (this.origin === 'constants') { + return `const vec3 ${this.id} = vec3(${value[0]},${value[1]},${value[2]});\n`; + } + return `uniform vec3 ${this.id};\n`; + } + + getStringValueHandler() { + // resetting isn't supported for Array(3) + if (this.origin === 'constants') return ''; + return `const uploadValue_${this.name} = ${this.varName};\n`; + } + + updateValue(value) { + if (this.origin === 'constants') return; + this.kernel.setUniform3fv(this.id, this.uploadValue = value); + } +} + +module.exports = { + WebGLKernelValueArray3 +}; +},{"./index":238}],222:[function(require,module,exports){ +const { WebGLKernelValue } = require('./index'); + +class WebGLKernelValueArray4 extends WebGLKernelValue { + constructor(value, settings) { + super(value, settings); + this.uploadValue = value; + } + getSource(value) { + if (this.origin === 'constants') { + return `const vec4 ${this.id} = vec4(${value[0]},${value[1]},${value[2]},${value[3]});\n`; + } + return `uniform vec4 ${this.id};\n`; + } + + getStringValueHandler() { + // resetting isn't supported for Array(4) + if (this.origin === 'constants') return ''; + return `const uploadValue_${this.name} = ${this.varName};\n`; + } + + updateValue(value) { + if (this.origin === 'constants') return; + this.kernel.setUniform4fv(this.id, this.uploadValue = value); + } +} + +module.exports = { + WebGLKernelValueArray4 +}; +},{"./index":238}],223:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValue } = require('./index'); + +class WebGLKernelValueBoolean extends WebGLKernelValue { + constructor(value, settings) { + super(value, settings); + this.uploadValue = value; + } + getSource(value) { + if (this.origin === 'constants') { + return `const bool ${this.id} = ${value};\n`; + } + return `uniform bool ${this.id};\n`; + } + + getStringValueHandler() { + return `const uploadValue_${this.name} = ${this.varName};\n`; + } + + updateValue(value) { + if (this.origin === 'constants') return; + this.kernel.setUniform1i(this.id, this.uploadValue = value); + } +} + +module.exports = { + WebGLKernelValueBoolean +}; +},{"../../../utils":291,"./index":238}],224:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueHTMLImage } = require('./html-image'); + +class WebGLKernelValueDynamicHTMLImage extends WebGLKernelValueHTMLImage { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + const { width, height } = value; + this.checkSize(width, height); + this.dimensions = [width, height, 1]; + this.textureSize = [width, height]; + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGLKernelValueDynamicHTMLImage +}; +},{"../../../utils":291,"./html-image":236}],225:[function(require,module,exports){ +const { WebGLKernelValueDynamicHTMLImage } = require('./dynamic-html-image'); + +class WebGLKernelValueDynamicHTMLVideo extends WebGLKernelValueDynamicHTMLImage {} + +module.exports = { + WebGLKernelValueDynamicHTMLVideo +}; +},{"./dynamic-html-image":224}],226:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueMemoryOptimizedNumberTexture } = require('./memory-optimized-number-texture'); + +class WebGLKernelValueDynamicMemoryOptimizedNumberTexture extends WebGLKernelValueMemoryOptimizedNumberTexture { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(inputTexture) { + this.dimensions = inputTexture.dimensions; + this.checkSize(inputTexture.size[0], inputTexture.size[1]); + this.textureSize = inputTexture.size; + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(inputTexture); + } +} + +module.exports = { + WebGLKernelValueDynamicMemoryOptimizedNumberTexture +}; +},{"../../../utils":291,"./memory-optimized-number-texture":240}],227:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueNumberTexture } = require('./number-texture'); + +class WebGLKernelValueDynamicNumberTexture extends WebGLKernelValueNumberTexture { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + this.dimensions = value.dimensions; + this.checkSize(value.size[0], value.size[1]); + this.textureSize = value.size; + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGLKernelValueDynamicNumberTexture +}; +},{"../../../utils":291,"./number-texture":241}],228:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueSingleArray } = require('./single-array'); + +class WebGLKernelValueDynamicSingleArray extends WebGLKernelValueSingleArray { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + this.dimensions = utils.getDimensions(value, true); + this.textureSize = utils.getMemoryOptimizedFloatTextureSize(this.dimensions, this.bitRatio); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.uploadValue = new Float32Array(this.uploadArrayLength); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGLKernelValueDynamicSingleArray +}; +},{"../../../utils":291,"./single-array":242}],229:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueSingleArray1DI } = require('./single-array1d-i'); + +class WebGLKernelValueDynamicSingleArray1DI extends WebGLKernelValueSingleArray1DI { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + this.setShape(value); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGLKernelValueDynamicSingleArray1DI +}; +},{"../../../utils":291,"./single-array1d-i":243}],230:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueSingleArray2DI } = require('./single-array2d-i'); + +class WebGLKernelValueDynamicSingleArray2DI extends WebGLKernelValueSingleArray2DI { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + this.setShape(value); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGLKernelValueDynamicSingleArray2DI +}; +},{"../../../utils":291,"./single-array2d-i":244}],231:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueSingleArray3DI } = require('./single-array3d-i'); + +class WebGLKernelValueDynamicSingleArray3DI extends WebGLKernelValueSingleArray3DI { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + this.setShape(value); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGLKernelValueDynamicSingleArray3DI +}; +},{"../../../utils":291,"./single-array3d-i":245}],232:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueSingleInput } = require('./single-input'); + +class WebGLKernelValueDynamicSingleInput extends WebGLKernelValueSingleInput { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + let [w, h, d] = value.size; + this.dimensions = new Int32Array([w || 1, h || 1, d || 1]); + this.textureSize = utils.getMemoryOptimizedFloatTextureSize(this.dimensions, this.bitRatio); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.uploadValue = new Float32Array(this.uploadArrayLength); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGLKernelValueDynamicSingleInput +}; +},{"../../../utils":291,"./single-input":246}],233:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueUnsignedArray } = require('./unsigned-array'); + +class WebGLKernelValueDynamicUnsignedArray extends WebGLKernelValueUnsignedArray { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + this.dimensions = utils.getDimensions(value, true); + this.textureSize = utils.getMemoryOptimizedPackedTextureSize(this.dimensions, this.bitRatio); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * (4 / this.bitRatio); + this.checkSize(this.textureSize[0], this.textureSize[1]); + const Type = this.getTransferArrayType(value); + this.preUploadValue = new Type(this.uploadArrayLength); + this.uploadValue = new Uint8Array(this.preUploadValue.buffer); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGLKernelValueDynamicUnsignedArray +}; +},{"../../../utils":291,"./unsigned-array":247}],234:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueUnsignedInput } = require('./unsigned-input'); + +class WebGLKernelValueDynamicUnsignedInput extends WebGLKernelValueUnsignedInput { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + let [w, h, d] = value.size; + this.dimensions = new Int32Array([w || 1, h || 1, d || 1]); + this.textureSize = utils.getMemoryOptimizedPackedTextureSize(this.dimensions, this.bitRatio); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * (4 / this.bitRatio); + this.checkSize(this.textureSize[0], this.textureSize[1]); + const Type = this.getTransferArrayType(value.value); + this.preUploadValue = new Type(this.uploadArrayLength); + this.uploadValue = new Uint8Array(this.preUploadValue.buffer); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGLKernelValueDynamicUnsignedInput +}; +},{"../../../utils":291,"./unsigned-input":248}],235:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValue } = require('./index'); + +class WebGLKernelValueFloat extends WebGLKernelValue { + constructor(value, settings) { + super(value, settings); + this.uploadValue = value; + } + getStringValueHandler() { + return `const uploadValue_${this.name} = ${this.varName};\n`; + } + getSource(value) { + if (this.origin === 'constants') { + if (Number.isInteger(value)) { + return `const float ${this.id} = ${value}.0;\n`; + } + return `const float ${this.id} = ${value};\n`; + } + return `uniform float ${this.id};\n`; + } + + updateValue(value) { + if (this.origin === 'constants') return; + this.kernel.setUniform1f(this.id, this.uploadValue = value); + } +} + +module.exports = { + WebGLKernelValueFloat +}; +},{"../../../utils":291,"./index":238}],236:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('./array'); + +class WebGLKernelValueHTMLImage extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + const { width, height } = value; + this.checkSize(width, height); + this.dimensions = [width, height, 1]; + this.textureSize = [width, height]; + this.uploadValue = value; + } + + getStringValueHandler() { + return `const uploadValue_${this.name} = ${this.varName};\n`; + } + + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(inputImage) { + if (inputImage.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(inputImage.constructor); + return; + } + const { context: gl } = this; + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.uploadValue = inputImage); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGLKernelValueHTMLImage +}; +},{"../../../utils":291,"./array":219}],237:[function(require,module,exports){ +const { WebGLKernelValueHTMLImage } = require('./html-image'); + +class WebGLKernelValueHTMLVideo extends WebGLKernelValueHTMLImage {} + +module.exports = { + WebGLKernelValueHTMLVideo +}; +},{"./html-image":236}],238:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { KernelValue } = require('../../kernel-value'); + +class WebGLKernelValue extends KernelValue { + /** + * @param {KernelVariable} value + * @param {IWebGLKernelValueSettings} settings + */ + constructor(value, settings) { + super(value, settings); + this.dimensionsId = null; + this.sizeId = null; + this.initialValueConstructor = value.constructor; + this.onRequestTexture = settings.onRequestTexture; + this.onRequestIndex = settings.onRequestIndex; + this.uploadValue = null; + this.textureSize = null; + this.bitRatio = null; + this.prevArg = null; + } + + get id() { + return `${this.origin}_${utils.sanitizeName(this.name)}`; + } + + setup() {} + + getTransferArrayType(value) { + if (Array.isArray(value[0])) { + return this.getTransferArrayType(value[0]); + } + switch (value.constructor) { + case Array: + case Int32Array: + case Int16Array: + case Int8Array: + return Float32Array; + case Uint8ClampedArray: + case Uint8Array: + case Uint16Array: + case Uint32Array: + case Float32Array: + case Float64Array: + return value.constructor; + } + console.warn('Unfamiliar constructor type. Will go ahead and use, but likley this may result in a transfer of zeros'); + return value.constructor; + } + + /** + * Used for when we want a string output of our kernel, so we can still input values to the kernel + */ + getStringValueHandler() { + throw new Error(`"getStringValueHandler" not implemented on ${this.constructor.name}`); + } + + getVariablePrecisionString() { + return this.kernel.getVariablePrecisionString(this.textureSize || undefined, this.tactic || undefined); + } + + destroy() {} +} + +module.exports = { + WebGLKernelValue +}; +},{"../../../utils":291,"../../kernel-value":214}],239:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValue } = require('./index'); + +class WebGLKernelValueInteger extends WebGLKernelValue { + constructor(value, settings) { + super(value, settings); + this.uploadValue = value; + } + getStringValueHandler() { + return `const uploadValue_${this.name} = ${this.varName};\n`; + } + getSource(value) { + if (this.origin === 'constants') { + return `const int ${this.id} = ${ parseInt(value) };\n`; + } + return `uniform int ${this.id};\n`; + } + + updateValue(value) { + if (this.origin === 'constants') return; + this.kernel.setUniform1i(this.id, this.uploadValue = value); + } +} + +module.exports = { + WebGLKernelValueInteger +}; +},{"../../../utils":291,"./index":238}],240:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('./array'); + +const sameError = `Source and destination textures are the same. Use immutable = true and manually cleanup kernel output texture memory with texture.delete()`; + +class WebGLKernelValueMemoryOptimizedNumberTexture extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + const [width, height] = value.size; + this.checkSize(width, height); + this.dimensions = value.dimensions; + this.textureSize = value.size; + this.uploadValue = value.texture; + this.forceUploadEachRun = true; + } + + setup() { + this.setupTexture(); + } + + getStringValueHandler() { + return `const uploadValue_${this.name} = ${this.varName}.texture;\n`; + } + + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + /** + * @param {GLTextureMemoryOptimized} inputTexture + */ + updateValue(inputTexture) { + if (inputTexture.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(inputTexture.constructor); + return; + } + if (this.checkContext && inputTexture.context !== this.context) { + throw new Error(`Value ${this.name} (${this.type}) must be from same context`); + } + + const { kernel, context: gl } = this; + if (kernel.pipeline) { + if (kernel.immutable) { + kernel.updateTextureArgumentRefs(this, inputTexture); + } else { + if (kernel.texture && kernel.texture.texture === inputTexture.texture) { + throw new Error(sameError); + } else if (kernel.mappedTextures) { + const { mappedTextures } = kernel; + for (let i = 0; i < mappedTextures.length; i++) { + if (mappedTextures[i].texture === inputTexture.texture) { + throw new Error(sameError); + } + } + } + } + } + + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.uploadValue = inputTexture.texture); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGLKernelValueMemoryOptimizedNumberTexture, + sameError +}; +},{"../../../utils":291,"./array":219}],241:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('./array'); +const { sameError } = require('./memory-optimized-number-texture'); + +class WebGLKernelValueNumberTexture extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + const [width, height] = value.size; + this.checkSize(width, height); + const { size: textureSize, dimensions } = value; + this.bitRatio = this.getBitRatio(value); + this.dimensions = dimensions; + this.textureSize = textureSize; + this.uploadValue = value.texture; + this.forceUploadEachRun = true; + } + + setup() { + this.setupTexture(); + } + + getStringValueHandler() { + return `const uploadValue_${this.name} = ${this.varName}.texture;\n`; + } + + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + /** + * + * @param {GLTexture} inputTexture + */ + updateValue(inputTexture) { + if (inputTexture.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(inputTexture.constructor); + return; + } + if (this.checkContext && inputTexture.context !== this.context) { + throw new Error(`Value ${this.name} (${this.type}) must be from same context`); + } + + const { kernel, context: gl } = this; + if (kernel.pipeline) { + if (kernel.immutable) { + kernel.updateTextureArgumentRefs(this, inputTexture); + } else { + if (kernel.texture && kernel.texture.texture === inputTexture.texture) { + throw new Error(sameError); + } else if (kernel.mappedTextures) { + const { mappedTextures } = kernel; + for (let i = 0; i < mappedTextures.length; i++) { + if (mappedTextures[i].texture === inputTexture.texture) { + throw new Error(sameError); + } + } + } + } + } + + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.uploadValue = inputTexture.texture); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGLKernelValueNumberTexture +}; +},{"../../../utils":291,"./array":219,"./memory-optimized-number-texture":240}],242:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('./array'); + +class WebGLKernelValueSingleArray extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + this.bitRatio = 4; + this.dimensions = utils.getDimensions(value, true); + this.textureSize = utils.getMemoryOptimizedFloatTextureSize(this.dimensions, this.bitRatio); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.uploadValue = new Float32Array(this.uploadArrayLength); + } + + getStringValueHandler() { + return utils.linesToString([ + `const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`, + `flattenTo(${this.varName}, uploadValue_${this.name})`, + ]); + } + + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(value) { + if (value.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(value.constructor); + return; + } + const { context: gl } = this; + utils.flattenTo(value, this.uploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGLKernelValueSingleArray +}; +},{"../../../utils":291,"./array":219}],243:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('./array'); + +class WebGLKernelValueSingleArray1DI extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + this.bitRatio = 4; + this.setShape(value); + } + + setShape(value) { + const valueDimensions = utils.getDimensions(value, true); + this.textureSize = utils.getMemoryOptimizedFloatTextureSize(valueDimensions, this.bitRatio); + this.dimensions = new Int32Array([valueDimensions[1], 1, 1]); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.uploadValue = new Float32Array(this.uploadArrayLength); + } + + getStringValueHandler() { + return utils.linesToString([ + `const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`, + `flattenTo(${this.varName}, uploadValue_${this.name})`, + ]); + } + + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(value) { + if (value.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(value.constructor); + return; + } + const { context: gl } = this; + utils.flatten2dArrayTo(value, this.uploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGLKernelValueSingleArray1DI +}; +},{"../../../utils":291,"./array":219}],244:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('./array'); + +class WebGLKernelValueSingleArray2DI extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + this.bitRatio = 4; + this.setShape(value); + } + + setShape(value) { + const valueDimensions = utils.getDimensions(value, true); + this.textureSize = utils.getMemoryOptimizedFloatTextureSize(valueDimensions, this.bitRatio); + this.dimensions = new Int32Array([valueDimensions[1], valueDimensions[2], 1]); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.uploadValue = new Float32Array(this.uploadArrayLength); + } + + getStringValueHandler() { + return utils.linesToString([ + `const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`, + `flattenTo(${this.varName}, uploadValue_${this.name})`, + ]); + } + + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(value) { + if (value.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(value.constructor); + return; + } + const { context: gl } = this; + utils.flatten3dArrayTo(value, this.uploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGLKernelValueSingleArray2DI +}; +},{"../../../utils":291,"./array":219}],245:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('./array'); + +class WebGLKernelValueSingleArray3DI extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + this.bitRatio = 4; + this.setShape(value); + } + + setShape(value) { + const valueDimensions = utils.getDimensions(value, true); + this.textureSize = utils.getMemoryOptimizedFloatTextureSize(valueDimensions, this.bitRatio); + this.dimensions = new Int32Array([valueDimensions[1], valueDimensions[2], valueDimensions[3]]); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.uploadValue = new Float32Array(this.uploadArrayLength); + } + + getStringValueHandler() { + return utils.linesToString([ + `const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`, + `flattenTo(${this.varName}, uploadValue_${this.name})`, + ]); + } + + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(value) { + if (value.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(value.constructor); + return; + } + const { context: gl } = this; + utils.flatten4dArrayTo(value, this.uploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGLKernelValueSingleArray3DI +}; +},{"../../../utils":291,"./array":219}],246:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('./array'); + +class WebGLKernelValueSingleInput extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + this.bitRatio = 4; + let [w, h, d] = value.size; + this.dimensions = new Int32Array([w || 1, h || 1, d || 1]); + this.textureSize = utils.getMemoryOptimizedFloatTextureSize(this.dimensions, this.bitRatio); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.uploadValue = new Float32Array(this.uploadArrayLength); + } + + getStringValueHandler() { + return utils.linesToString([ + `const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`, + `flattenTo(${this.varName}.value, uploadValue_${this.name})`, + ]); + } + + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(input) { + if (input.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(input.constructor); + return; + } + const { context: gl } = this; + utils.flattenTo(input.value, this.uploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGLKernelValueSingleInput +}; +},{"../../../utils":291,"./array":219}],247:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('./array'); + +class WebGLKernelValueUnsignedArray extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + this.bitRatio = this.getBitRatio(value); + this.dimensions = utils.getDimensions(value, true); + this.textureSize = utils.getMemoryOptimizedPackedTextureSize(this.dimensions, this.bitRatio); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * (4 / this.bitRatio); + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.TranserArrayType = this.getTransferArrayType(value); + this.preUploadValue = new this.TranserArrayType(this.uploadArrayLength); + this.uploadValue = new Uint8Array(this.preUploadValue.buffer); + } + + getStringValueHandler() { + return utils.linesToString([ + `const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`, + `const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`, + `flattenTo(${this.varName}, preUploadValue_${this.name})`, + ]); + } + + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(value) { + if (value.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(value.constructor); + return; + } + const { context: gl } = this; + utils.flattenTo(value, this.preUploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGLKernelValueUnsignedArray +}; +},{"../../../utils":291,"./array":219}],248:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('./array'); + +class WebGLKernelValueUnsignedInput extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + this.bitRatio = this.getBitRatio(value); + const [w, h, d] = value.size; + this.dimensions = new Int32Array([w || 1, h || 1, d || 1]); + this.textureSize = utils.getMemoryOptimizedPackedTextureSize(this.dimensions, this.bitRatio); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * (4 / this.bitRatio); + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.TranserArrayType = this.getTransferArrayType(value.value); + this.preUploadValue = new this.TranserArrayType(this.uploadArrayLength); + this.uploadValue = new Uint8Array(this.preUploadValue.buffer); + } + + getStringValueHandler() { + return utils.linesToString([ + `const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`, + `const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`, + `flattenTo(${this.varName}.value, preUploadValue_${this.name})`, + ]); + } + + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(input) { + if (input.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(value.constructor); + return; + } + const { context: gl } = this; + utils.flattenTo(input.value, this.preUploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGLKernelValueUnsignedInput +}; +},{"../../../utils":291,"./array":219}],249:[function(require,module,exports){ +const { GLKernel } = require('../gl/kernel'); +const { FunctionBuilder } = require('../function-builder'); +const { WebGLFunctionNode } = require('./function-node'); +const { utils } = require('../../utils'); +const mrud = require('../../plugins/math-random-uniformly-distributed'); +const { fragmentShader } = require('./fragment-shader'); +const { vertexShader } = require('./vertex-shader'); +const { glKernelString } = require('../gl/kernel-string'); +const { lookupKernelValueType } = require('./kernel-value-maps'); + +let isSupported = null; +/** + * + * @type {HTMLCanvasElement|OffscreenCanvas|null} + */ +let testCanvas = null; +/** + * + * @type {WebGLRenderingContext|null} + */ +let testContext = null; +let testExtensions = null; +let features = null; + +const plugins = [mrud]; +const canvases = []; +const maxTexSizes = {}; + + +/** + * @desc Kernel Implementation for WebGL. + *

This builds the shaders and runs them on the GPU, + * the outputs the result back as float(enabled by default) and Texture.

+ * + * @property {WebGLTexture[]} textureCache - webGl Texture cache + * @property {Object.} programUniformLocationCache - Location of program variables in memory + * @property {WebGLFramebuffer} framebuffer - Webgl frameBuffer + * @property {WebGLBuffer} buffer - WebGL buffer + * @property {WebGLProgram} program - The webGl Program + * @property {FunctionBuilder} functionBuilder - Function Builder instance bound to this Kernel + * @property {Boolean} pipeline - Set output type to FAST mode (GPU to GPU via Textures), instead of float + * @property {string} endianness - Endian information like Little-endian, Big-endian. + * @property {string[]} argumentTypes - Types of parameters sent to the Kernel + * @property {string|null} compiledFragmentShader - Compiled fragment shader string + * @property {string|null} compiledVertexShader - Compiled Vertical shader string + * @extends GLKernel + */ +class WebGLKernel extends GLKernel { + static get isSupported() { + if (isSupported !== null) { + return isSupported; + } + this.setupFeatureChecks(); + isSupported = this.isContextMatch(testContext); + return isSupported; + } + + static setupFeatureChecks() { + if (typeof document !== 'undefined') { + testCanvas = document.createElement('canvas'); + } else if (typeof OffscreenCanvas !== 'undefined') { + testCanvas = new OffscreenCanvas(0, 0); + } + if (!testCanvas) return; + testContext = testCanvas.getContext('webgl') || testCanvas.getContext('experimental-webgl'); + if (!testContext || !testContext.getExtension) return; + testExtensions = { + OES_texture_float: testContext.getExtension('OES_texture_float'), + OES_texture_float_linear: testContext.getExtension('OES_texture_float_linear'), + OES_element_index_uint: testContext.getExtension('OES_element_index_uint'), + WEBGL_draw_buffers: testContext.getExtension('WEBGL_draw_buffers'), + }; + features = this.getFeatures(); + } + + static isContextMatch(context) { + if (typeof WebGLRenderingContext !== 'undefined') { + return context instanceof WebGLRenderingContext; + } + return false; + } + + static getIsTextureFloat() { + return Boolean(testExtensions.OES_texture_float); + } + + static getIsDrawBuffers() { + return Boolean(testExtensions.WEBGL_draw_buffers); + } + + static getChannelCount() { + return testExtensions.WEBGL_draw_buffers ? + testContext.getParameter(testExtensions.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL) : + 1; + } + + static getMaxTextureSize() { + return testContext.getParameter(testContext.MAX_TEXTURE_SIZE); + } + + /** + * + * @param type + * @param dynamic + * @param precision + * @param value + * @returns {KernelValue} + */ + static lookupKernelValueType(type, dynamic, precision, value) { + return lookupKernelValueType(type, dynamic, precision, value); + } + + static get testCanvas() { + return testCanvas; + } + + static get testContext() { + return testContext; + } + + static get features() { + return features; + } + + static get fragmentShader() { + return fragmentShader; + } + + static get vertexShader() { + return vertexShader; + } + + /** + * + * @param {String|IKernelJSON} source + * @param {IDirectKernelSettings} settings + */ + constructor(source, settings) { + super(source, settings); + this.program = null; + this.pipeline = settings.pipeline; + this.endianness = utils.systemEndianness(); + this.extensions = {}; + this.argumentTextureCount = 0; + this.constantTextureCount = 0; + this.fragShader = null; + this.vertShader = null; + this.drawBuffersMap = null; + + /** + * + * @type {Int32Array|null} + */ + this.maxTexSize = null; + this.onRequestSwitchKernel = null; + + this.texture = null; + this.mappedTextures = null; + this.mergeSettings(source.settings || settings); + + /** + * The thread dimensions, x, y and z + * @type {Array|null} + */ + this.threadDim = null; + this.framebuffer = null; + this.buffer = null; + + this.textureCache = []; + this.programUniformLocationCache = {}; + this.uniform1fCache = {}; + this.uniform1iCache = {}; + this.uniform2fCache = {}; + this.uniform2fvCache = {}; + this.uniform2ivCache = {}; + this.uniform3fvCache = {}; + this.uniform3ivCache = {}; + this.uniform4fvCache = {}; + this.uniform4ivCache = {}; + } + + initCanvas() { + if (typeof document !== 'undefined') { + const canvas = document.createElement('canvas'); + // Default width and height, to fix webgl issue in safari + canvas.width = 2; + canvas.height = 2; + return canvas; + } else if (typeof OffscreenCanvas !== 'undefined') { + return new OffscreenCanvas(0, 0); + } + } + + /** + * + * @return {WebGLRenderingContext} + */ + initContext() { + const settings = { + alpha: false, + depth: false, + antialias: false + }; + return this.canvas.getContext('webgl', settings) || this.canvas.getContext('experimental-webgl', settings); + } + + /** + * + * @param {IDirectKernelSettings} settings + * @return {string[]} + */ + initPlugins(settings) { + // default plugins + const pluginsToUse = []; + const { source } = this; + if (typeof source === 'string') { + for (let i = 0; i < plugins.length; i++) { + const plugin = plugins[i]; + if (source.match(plugin.functionMatch)) { + pluginsToUse.push(plugin); + } + } + } else if (typeof source === 'object') { + // `source` is from object, json + if (settings.pluginNames) { //TODO: in context of JSON support, pluginNames may not exist here + for (let i = 0; i < plugins.length; i++) { + const plugin = plugins[i]; + const usePlugin = settings.pluginNames.some(pluginName => pluginName === plugin.name); + if (usePlugin) { + pluginsToUse.push(plugin); + } + } + } + } + return pluginsToUse; + } + + initExtensions() { + this.extensions = { + OES_texture_float: this.context.getExtension('OES_texture_float'), + OES_texture_float_linear: this.context.getExtension('OES_texture_float_linear'), + OES_element_index_uint: this.context.getExtension('OES_element_index_uint'), + WEBGL_draw_buffers: this.context.getExtension('WEBGL_draw_buffers'), + WEBGL_color_buffer_float: this.context.getExtension('WEBGL_color_buffer_float'), + }; + } + + /** + * @desc Validate settings related to Kernel, such as dimensions size, and auto output support. + * @param {IArguments} args + */ + validateSettings(args) { + if (!this.validate) { + this.texSize = utils.getKernelTextureSize({ + optimizeFloatMemory: this.optimizeFloatMemory, + precision: this.precision, + }, this.output); + return; + } + + const { features } = this.constructor; + + if (this.optimizeFloatMemory === true && !features.isTextureFloat) { + throw new Error('Float textures are not supported'); + } else if (this.precision === 'single' && !features.isFloatRead) { + throw new Error('Single precision not supported'); + } else if (!this.graphical && this.precision === null && features.isTextureFloat) { + this.precision = features.isFloatRead ? 'single' : 'unsigned'; + } + + if (this.subKernels && this.subKernels.length > 0 && !this.extensions.WEBGL_draw_buffers) { + throw new Error('could not instantiate draw buffers extension'); + } + + if (this.fixIntegerDivisionAccuracy === null) { + this.fixIntegerDivisionAccuracy = !features.isIntegerDivisionAccurate; + } else if (this.fixIntegerDivisionAccuracy && features.isIntegerDivisionAccurate) { + this.fixIntegerDivisionAccuracy = false; + } + + this.checkOutput(); + + if (!this.output || this.output.length === 0) { + if (args.length !== 1) { + throw new Error('Auto output only supported for kernels with only one input'); + } + + const argType = utils.getVariableType(args[0], this.strictIntegers); + switch (argType) { + case 'Array': + this.output = utils.getDimensions(argType); + break; + case 'NumberTexture': + case 'MemoryOptimizedNumberTexture': + case 'ArrayTexture(1)': + case 'ArrayTexture(2)': + case 'ArrayTexture(3)': + case 'ArrayTexture(4)': + this.output = args[0].output; + break; + default: + throw new Error('Auto output not supported for input type: ' + argType); + } + } + + if (this.graphical) { + if (this.output.length !== 2) { + throw new Error('Output must have 2 dimensions on graphical mode'); + } + + if (this.precision === 'precision') { + this.precision = 'unsigned'; + console.warn('Cannot use graphical mode and single precision at the same time'); + } + + this.texSize = utils.clone(this.output); + return; + } else if (this.precision === null && features.isTextureFloat) { + this.precision = 'single'; + } + + this.texSize = utils.getKernelTextureSize({ + optimizeFloatMemory: this.optimizeFloatMemory, + precision: this.precision, + }, this.output); + + this.checkTextureSize(); + } + + updateMaxTexSize() { + const { texSize, canvas } = this; + if (this.maxTexSize === null) { + let canvasIndex = canvases.indexOf(canvas); + if (canvasIndex === -1) { + canvasIndex = canvases.length; + canvases.push(canvas); + maxTexSizes[canvasIndex] = [texSize[0], texSize[1]]; + } + this.maxTexSize = maxTexSizes[canvasIndex]; + } + if (this.maxTexSize[0] < texSize[0]) { + this.maxTexSize[0] = texSize[0]; + } + if (this.maxTexSize[1] < texSize[1]) { + this.maxTexSize[1] = texSize[1]; + } + } + + setupArguments(args) { + this.kernelArguments = []; + this.argumentTextureCount = 0; + const needsArgumentTypes = this.argumentTypes === null; + // TODO: remove + if (needsArgumentTypes) { + this.argumentTypes = []; + } + this.argumentSizes = []; + this.argumentBitRatios = []; + // TODO: end remove + + if (args.length < this.argumentNames.length) { + throw new Error('not enough arguments for kernel'); + } else if (args.length > this.argumentNames.length) { + throw new Error('too many arguments for kernel'); + } + + const { context: gl } = this; + let textureIndexes = 0; + + const onRequestTexture = () => { + return this.createTexture(); + }; + const onRequestIndex = () => { + return this.constantTextureCount + textureIndexes++; + }; + const onUpdateValueMismatch = (constructor) => { + this.switchKernels({ + type: 'argumentMismatch', + needed: constructor + }); + }; + const onRequestContextHandle = () => { + return gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount++; + }; + + for (let index = 0; index < args.length; index++) { + const value = args[index]; + const name = this.argumentNames[index]; + let type; + if (needsArgumentTypes) { + type = utils.getVariableType(value, this.strictIntegers); + this.argumentTypes.push(type); + } else { + type = this.argumentTypes[index]; + } + const KernelValue = this.constructor.lookupKernelValueType(type, this.dynamicArguments ? 'dynamic' : 'static', this.precision, args[index]); + if (KernelValue === null) { + return this.requestFallback(args); + } + const kernelArgument = new KernelValue(value, { + name, + type, + tactic: this.tactic, + origin: 'user', + context: gl, + checkContext: this.checkContext, + kernel: this, + strictIntegers: this.strictIntegers, + onRequestTexture, + onRequestIndex, + onUpdateValueMismatch, + onRequestContextHandle, + }); + this.kernelArguments.push(kernelArgument); + kernelArgument.setup(); + this.argumentSizes.push(kernelArgument.textureSize); + this.argumentBitRatios[index] = kernelArgument.bitRatio; + } + } + + createTexture() { + const texture = this.context.createTexture(); + this.textureCache.push(texture); + return texture; + } + + setupConstants(args) { + const { context: gl } = this; + this.kernelConstants = []; + this.forceUploadKernelConstants = []; + let needsConstantTypes = this.constantTypes === null; + if (needsConstantTypes) { + this.constantTypes = {}; + } + this.constantBitRatios = {}; + let textureIndexes = 0; + for (const name in this.constants) { + const value = this.constants[name]; + let type; + if (needsConstantTypes) { + type = utils.getVariableType(value, this.strictIntegers); + this.constantTypes[name] = type; + } else { + type = this.constantTypes[name]; + } + const KernelValue = this.constructor.lookupKernelValueType(type, 'static', this.precision, value); + if (KernelValue === null) { + return this.requestFallback(args); + } + const kernelValue = new KernelValue(value, { + name, + type, + tactic: this.tactic, + origin: 'constants', + context: this.context, + checkContext: this.checkContext, + kernel: this, + strictIntegers: this.strictIntegers, + onRequestTexture: () => { + return this.createTexture(); + }, + onRequestIndex: () => { + return textureIndexes++; + }, + onRequestContextHandle: () => { + return gl.TEXTURE0 + this.constantTextureCount++; + } + }); + this.constantBitRatios[name] = kernelValue.bitRatio; + this.kernelConstants.push(kernelValue); + kernelValue.setup(); + if (kernelValue.forceUploadEachRun) { + this.forceUploadKernelConstants.push(kernelValue); + } + } + } + + build() { + if (this.built) return; + this.initExtensions(); + this.validateSettings(arguments); + this.setupConstants(arguments); + if (this.fallbackRequested) return; + this.setupArguments(arguments); + if (this.fallbackRequested) return; + this.updateMaxTexSize(); + this.translateSource(); + const failureResult = this.pickRenderStrategy(arguments); + if (failureResult) { + return failureResult; + } + const { texSize, context: gl, canvas } = this; + gl.enable(gl.SCISSOR_TEST); + if (this.pipeline && this.precision === 'single') { + gl.viewport(0, 0, this.maxTexSize[0], this.maxTexSize[1]); + canvas.width = this.maxTexSize[0]; + canvas.height = this.maxTexSize[1]; + } else { + gl.viewport(0, 0, this.maxTexSize[0], this.maxTexSize[1]); + canvas.width = this.maxTexSize[0]; + canvas.height = this.maxTexSize[1]; + } + const threadDim = this.threadDim = Array.from(this.output); + while (threadDim.length < 3) { + threadDim.push(1); + } + + const compiledVertexShader = this.getVertexShader(arguments); + const vertShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertShader, compiledVertexShader); + gl.compileShader(vertShader); + this.vertShader = vertShader; + + const compiledFragmentShader = this.getFragmentShader(arguments); + const fragShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragShader, compiledFragmentShader); + gl.compileShader(fragShader); + this.fragShader = fragShader; + + if (this.debug) { + console.log('GLSL Shader Output:'); + console.log(compiledFragmentShader); + } + + if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) { + throw new Error('Error compiling vertex shader: ' + gl.getShaderInfoLog(vertShader)); + } + if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)) { + throw new Error('Error compiling fragment shader: ' + gl.getShaderInfoLog(fragShader)); + } + + const program = this.program = gl.createProgram(); + gl.attachShader(program, vertShader); + gl.attachShader(program, fragShader); + gl.linkProgram(program); + this.framebuffer = gl.createFramebuffer(); + this.framebuffer.width = texSize[0]; + this.framebuffer.height = texSize[1]; + this.rawValueFramebuffers = {}; + + const vertices = new Float32Array([-1, -1, + 1, -1, -1, 1, + 1, 1 + ]); + const texCoords = new Float32Array([ + 0, 0, + 1, 0, + 0, 1, + 1, 1 + ]); + + const texCoordOffset = vertices.byteLength; + + let buffer = this.buffer; + if (!buffer) { + buffer = this.buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, vertices.byteLength + texCoords.byteLength, gl.STATIC_DRAW); + } else { + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + } + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices); + gl.bufferSubData(gl.ARRAY_BUFFER, texCoordOffset, texCoords); + + const aPosLoc = gl.getAttribLocation(this.program, 'aPos'); + gl.enableVertexAttribArray(aPosLoc); + gl.vertexAttribPointer(aPosLoc, 2, gl.FLOAT, false, 0, 0); + const aTexCoordLoc = gl.getAttribLocation(this.program, 'aTexCoord'); + gl.enableVertexAttribArray(aTexCoordLoc); + gl.vertexAttribPointer(aTexCoordLoc, 2, gl.FLOAT, false, 0, texCoordOffset); + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + + let i = 0; + gl.useProgram(this.program); + for (let p in this.constants) { + this.kernelConstants[i++].updateValue(this.constants[p]); + } + + this._setupOutputTexture(); + if ( + this.subKernels !== null && + this.subKernels.length > 0 + ) { + this._mappedTextureSwitched = {}; + this._setupSubOutputTextures(); + } + this.buildSignature(arguments); + this.built = true; + } + + translateSource() { + const functionBuilder = FunctionBuilder.fromKernel(this, WebGLFunctionNode, { + fixIntegerDivisionAccuracy: this.fixIntegerDivisionAccuracy + }); + this.translatedSource = functionBuilder.getPrototypeString('kernel'); + this.setupReturnTypes(functionBuilder); + } + + setupReturnTypes(functionBuilder) { + if (!this.graphical && !this.returnType) { + this.returnType = functionBuilder.getKernelResultType(); + } + + if (this.subKernels && this.subKernels.length > 0) { + for (let i = 0; i < this.subKernels.length; i++) { + const subKernel = this.subKernels[i]; + if (!subKernel.returnType) { + subKernel.returnType = functionBuilder.getSubKernelResultType(i); + } + } + } + } + + run() { + const { kernelArguments, texSize, forceUploadKernelConstants, context: gl } = this; + + gl.useProgram(this.program); + gl.scissor(0, 0, texSize[0], texSize[1]); + if (this.dynamicOutput) { + this.setUniform3iv('uOutputDim', new Int32Array(this.threadDim)); + this.setUniform2iv('uTexSize', texSize); + } + + this.setUniform2f('ratio', texSize[0] / this.maxTexSize[0], texSize[1] / this.maxTexSize[1]); + + for (let i = 0; i < forceUploadKernelConstants.length; i++) { + const constant = forceUploadKernelConstants[i]; + constant.updateValue(this.constants[constant.name]); + if (this.switchingKernels) return; + } + for (let i = 0; i < kernelArguments.length; i++) { + kernelArguments[i].updateValue(arguments[i]); + if (this.switchingKernels) return; + } + + if (this.plugins) { + for (let i = 0; i < this.plugins.length; i++) { + const plugin = this.plugins[i]; + if (plugin.onBeforeRun) { + plugin.onBeforeRun(this); + } + } + } + + if (this.graphical) { + if (this.pipeline) { + gl.bindRenderbuffer(gl.RENDERBUFFER, null); + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + if (this.immutable) { + this._replaceOutputTexture(); + } + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); + return this.immutable ? this.texture.clone() : this.texture; + } + gl.bindRenderbuffer(gl.RENDERBUFFER, null); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); + return; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + if (this.immutable) { + this._replaceOutputTexture(); + } + + if (this.subKernels !== null) { + if (this.immutable) { + this._replaceSubOutputTextures(); + } + this.drawBuffers(); + } + + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); + } + + drawBuffers() { + this.extensions.WEBGL_draw_buffers.drawBuffersWEBGL(this.drawBuffersMap); + } + + getInternalFormat() { + return this.context.RGBA; + } + getTextureFormat() { + const { context: gl } = this; + switch (this.getInternalFormat()) { + case gl.RGBA: + return gl.RGBA; + default: + throw new Error('Unknown internal format'); + } + } + + /** + * + * @desc replace output textures where arguments my be the same values + */ + _replaceOutputTexture() { + if (this.texture.beforeMutate() || this._textureSwitched) { + const gl = this.context; + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); + this._textureSwitched = false; + } + } + + /** + * @desc Setup output texture + */ + _setupOutputTexture() { + const gl = this.context; + const texSize = this.texSize; + if (this.texture) { + // here we inherit from an already existing kernel, so go ahead and just bind textures to the framebuffer + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); + return; + } + const texture = this.createTexture(); + gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + const format = this.getInternalFormat(); + if (this.precision === 'single') { + gl.texImage2D(gl.TEXTURE_2D, 0, format, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); + } else { + gl.texImage2D(gl.TEXTURE_2D, 0, format, texSize[0], texSize[1], 0, format, gl.UNSIGNED_BYTE, null); + } + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + this.texture = new this.TextureConstructor({ + texture, + size: texSize, + dimensions: this.threadDim, + output: this.output, + context: this.context, + internalFormat: this.getInternalFormat(), + textureFormat: this.getTextureFormat(), + kernel: this, + }); + } + + /** + * + * @desc replace sub-output textures where arguments my be the same values + */ + _replaceSubOutputTextures() { + const gl = this.context; + for (let i = 0; i < this.mappedTextures.length; i++) { + const mappedTexture = this.mappedTextures[i]; + if (mappedTexture.beforeMutate() || this._mappedTextureSwitched[i]) { + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i + 1, gl.TEXTURE_2D, mappedTexture.texture, 0); + this._mappedTextureSwitched[i] = false; + } + } + } + + /** + * @desc Setup on inherit sub-output textures + */ + _setupSubOutputTextures() { + const gl = this.context; + if (this.mappedTextures) { + // here we inherit from an already existing kernel, so go ahead and just bind textures to the framebuffer + for (let i = 0; i < this.subKernels.length; i++) { + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i + 1, gl.TEXTURE_2D, this.mappedTextures[i].texture, 0); + } + return; + } + const texSize = this.texSize; + this.drawBuffersMap = [gl.COLOR_ATTACHMENT0]; + this.mappedTextures = []; + for (let i = 0; i < this.subKernels.length; i++) { + const texture = this.createTexture(); + this.drawBuffersMap.push(gl.COLOR_ATTACHMENT0 + i + 1); + gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount + i); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + if (this.precision === 'single') { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); + } else { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i + 1, gl.TEXTURE_2D, texture, 0); + + this.mappedTextures.push(new this.TextureConstructor({ + texture, + size: texSize, + dimensions: this.threadDim, + output: this.output, + context: this.context, + internalFormat: this.getInternalFormat(), + textureFormat: this.getTextureFormat(), + kernel: this, + })); + } + } + + setUniform1f(name, value) { + if (this.uniform1fCache.hasOwnProperty(name)) { + const cache = this.uniform1fCache[name]; + if (value === cache) { + return; + } + } + this.uniform1fCache[name] = value; + const loc = this.getUniformLocation(name); + this.context.uniform1f(loc, value); + } + + setUniform1i(name, value) { + if (this.uniform1iCache.hasOwnProperty(name)) { + const cache = this.uniform1iCache[name]; + if (value === cache) { + return; + } + } + this.uniform1iCache[name] = value; + const loc = this.getUniformLocation(name); + this.context.uniform1i(loc, value); + } + + setUniform2f(name, value1, value2) { + if (this.uniform2fCache.hasOwnProperty(name)) { + const cache = this.uniform2fCache[name]; + if ( + value1 === cache[0] && + value2 === cache[1] + ) { + return; + } + } + this.uniform2fCache[name] = [value1, value2]; + const loc = this.getUniformLocation(name); + this.context.uniform2f(loc, value1, value2); + } + + setUniform2fv(name, value) { + if (this.uniform2fvCache.hasOwnProperty(name)) { + const cache = this.uniform2fvCache[name]; + if ( + value[0] === cache[0] && + value[1] === cache[1] + ) { + return; + } + } + this.uniform2fvCache[name] = value; + const loc = this.getUniformLocation(name); + this.context.uniform2fv(loc, value); + } + + setUniform2iv(name, value) { + if (this.uniform2ivCache.hasOwnProperty(name)) { + const cache = this.uniform2ivCache[name]; + if ( + value[0] === cache[0] && + value[1] === cache[1] + ) { + return; + } + } + this.uniform2ivCache[name] = value; + const loc = this.getUniformLocation(name); + this.context.uniform2iv(loc, value); + } + + setUniform3fv(name, value) { + if (this.uniform3fvCache.hasOwnProperty(name)) { + const cache = this.uniform3fvCache[name]; + if ( + value[0] === cache[0] && + value[1] === cache[1] && + value[2] === cache[2] + ) { + return; + } + } + this.uniform3fvCache[name] = value; + const loc = this.getUniformLocation(name); + this.context.uniform3fv(loc, value); + } + + setUniform3iv(name, value) { + if (this.uniform3ivCache.hasOwnProperty(name)) { + const cache = this.uniform3ivCache[name]; + if ( + value[0] === cache[0] && + value[1] === cache[1] && + value[2] === cache[2] + ) { + return; + } + } + this.uniform3ivCache[name] = value; + const loc = this.getUniformLocation(name); + this.context.uniform3iv(loc, value); + } + + setUniform4fv(name, value) { + if (this.uniform4fvCache.hasOwnProperty(name)) { + const cache = this.uniform4fvCache[name]; + if ( + value[0] === cache[0] && + value[1] === cache[1] && + value[2] === cache[2] && + value[3] === cache[3] + ) { + return; + } + } + this.uniform4fvCache[name] = value; + const loc = this.getUniformLocation(name); + this.context.uniform4fv(loc, value); + } + + setUniform4iv(name, value) { + if (this.uniform4ivCache.hasOwnProperty(name)) { + const cache = this.uniform4ivCache[name]; + if ( + value[0] === cache[0] && + value[1] === cache[1] && + value[2] === cache[2] && + value[3] === cache[3] + ) { + return; + } + } + this.uniform4ivCache[name] = value; + const loc = this.getUniformLocation(name); + this.context.uniform4iv(loc, value); + } + + /** + * @desc Return WebGlUniformLocation for various variables + * related to webGl program, such as user-defined variables, + * as well as, dimension sizes, etc. + */ + getUniformLocation(name) { + if (this.programUniformLocationCache.hasOwnProperty(name)) { + return this.programUniformLocationCache[name]; + } + return this.programUniformLocationCache[name] = this.context.getUniformLocation(this.program, name); + } + + /** + * @desc Generate Shader artifacts for the kernel program. + * The final object contains HEADER, KERNEL, MAIN_RESULT, and others. + * + * @param {Array} args - The actual parameters sent to the Kernel + * @returns {Object} An object containing the Shader Artifacts(CONSTANTS, HEADER, KERNEL, etc.) + */ + _getFragShaderArtifactMap(args) { + return { + HEADER: this._getHeaderString(), + LOOP_MAX: this._getLoopMaxString(), + PLUGINS: this._getPluginsString(), + CONSTANTS: this._getConstantsString(), + DECODE32_ENDIANNESS: this._getDecode32EndiannessString(), + ENCODE32_ENDIANNESS: this._getEncode32EndiannessString(), + DIVIDE_WITH_INTEGER_CHECK: this._getDivideWithIntegerCheckString(), + INJECTED_NATIVE: this._getInjectedNative(), + MAIN_CONSTANTS: this._getMainConstantsString(), + MAIN_ARGUMENTS: this._getMainArgumentsString(args), + KERNEL: this.getKernelString(), + MAIN_RESULT: this.getMainResultString(), + FLOAT_TACTIC_DECLARATION: this.getFloatTacticDeclaration(), + INT_TACTIC_DECLARATION: this.getIntTacticDeclaration(), + SAMPLER_2D_TACTIC_DECLARATION: this.getSampler2DTacticDeclaration(), + SAMPLER_2D_ARRAY_TACTIC_DECLARATION: this.getSampler2DArrayTacticDeclaration(), + }; + } + + /** + * @desc Generate Shader artifacts for the kernel program. + * The final object contains HEADER, KERNEL, MAIN_RESULT, and others. + * + * @param {Array} args - The actual parameters sent to the Kernel + * @returns {Object} An object containing the Shader Artifacts(CONSTANTS, HEADER, KERNEL, etc.) + */ + _getVertShaderArtifactMap(args) { + return { + FLOAT_TACTIC_DECLARATION: this.getFloatTacticDeclaration(), + INT_TACTIC_DECLARATION: this.getIntTacticDeclaration(), + SAMPLER_2D_TACTIC_DECLARATION: this.getSampler2DTacticDeclaration(), + SAMPLER_2D_ARRAY_TACTIC_DECLARATION: this.getSampler2DArrayTacticDeclaration(), + }; + } + + /** + * @desc Get the header string for the program. + * This returns an empty string if no sub-kernels are defined. + * + * @returns {String} result + */ + _getHeaderString() { + return ( + this.subKernels !== null ? + '#extension GL_EXT_draw_buffers : require\n' : + '' + ); + } + + /** + * @desc Get the maximum loop size String. + * @returns {String} result + */ + _getLoopMaxString() { + return ( + this.loopMaxIterations ? + ` ${parseInt(this.loopMaxIterations)};\n` : + ' 1000;\n' + ); + } + + _getPluginsString() { + if (!this.plugins) return '\n'; + return this.plugins.map(plugin => plugin.source && this.source.match(plugin.functionMatch) ? plugin.source : '').join('\n'); + } + + /** + * @desc Generate transpiled glsl Strings for constant parameters sent to a kernel + * @returns {String} result + */ + _getConstantsString() { + const result = []; + const { threadDim, texSize } = this; + if (this.dynamicOutput) { + result.push( + 'uniform ivec3 uOutputDim', + 'uniform ivec2 uTexSize' + ); + } else { + result.push( + `ivec3 uOutputDim = ivec3(${threadDim[0]}, ${threadDim[1]}, ${threadDim[2]})`, + `ivec2 uTexSize = ivec2(${texSize[0]}, ${texSize[1]})` + ); + } + return utils.linesToString(result); + } + + /** + * @desc Get texture coordinate string for the program + * @returns {String} result + */ + _getTextureCoordinate() { + const subKernels = this.subKernels; + if (subKernels === null || subKernels.length < 1) { + return 'varying vec2 vTexCoord;\n'; + } else { + return 'out vec2 vTexCoord;\n'; + } + } + + /** + * @desc Get Decode32 endianness string for little-endian and big-endian + * @returns {String} result + */ + _getDecode32EndiannessString() { + return ( + this.endianness === 'LE' ? + '' : + ' texel.rgba = texel.abgr;\n' + ); + } + + /** + * @desc Get Encode32 endianness string for little-endian and big-endian + * @returns {String} result + */ + _getEncode32EndiannessString() { + return ( + this.endianness === 'LE' ? + '' : + ' texel.rgba = texel.abgr;\n' + ); + } + + /** + * @desc if fixIntegerDivisionAccuracy provide method to replace / + * @returns {String} result + */ + _getDivideWithIntegerCheckString() { + return this.fixIntegerDivisionAccuracy ? + `float divWithIntCheck(float x, float y) { + if (floor(x) == x && floor(y) == y && integerMod(x, y) == 0.0) { + return float(int(x) / int(y)); + } + return x / y; +} + +float integerCorrectionModulo(float number, float divisor) { + if (number < 0.0) { + number = abs(number); + if (divisor < 0.0) { + divisor = abs(divisor); + } + return -(number - (divisor * floor(divWithIntCheck(number, divisor)))); + } + if (divisor < 0.0) { + divisor = abs(divisor); + } + return number - (divisor * floor(divWithIntCheck(number, divisor))); +}` : + ''; + } + + /** + * @desc Generate transpiled glsl Strings for user-defined parameters sent to a kernel + * @param {Array} args - The actual parameters sent to the Kernel + * @returns {String} result + */ + _getMainArgumentsString(args) { + const results = []; + const { argumentNames } = this; + for (let i = 0; i < argumentNames.length; i++) { + results.push(this.kernelArguments[i].getSource(args[i])); + } + return results.join(''); + } + + _getInjectedNative() { + return this.injectedNative || ''; + } + + _getMainConstantsString() { + const result = []; + const { constants } = this; + if (constants) { + let i = 0; + for (const name in constants) { + if (!this.constants.hasOwnProperty(name)) continue; + result.push(this.kernelConstants[i++].getSource(this.constants[name])); + } + } + return result.join(''); + } + + getRawValueFramebuffer(width, height) { + if (!this.rawValueFramebuffers[width]) { + this.rawValueFramebuffers[width] = {}; + } + if (!this.rawValueFramebuffers[width][height]) { + const framebuffer = this.context.createFramebuffer(); + framebuffer.width = width; + framebuffer.height = height; + this.rawValueFramebuffers[width][height] = framebuffer; + } + return this.rawValueFramebuffers[width][height]; + } + + getKernelResultDeclaration() { + switch (this.returnType) { + case 'Array(2)': + return 'vec2 kernelResult'; + case 'Array(3)': + return 'vec3 kernelResult'; + case 'Array(4)': + return 'vec4 kernelResult'; + case 'LiteralInteger': + case 'Float': + case 'Number': + case 'Integer': + return 'float kernelResult'; + default: + if (this.graphical) { + return 'float kernelResult'; + } else { + throw new Error(`unrecognized output type "${ this.returnType }"`); + } + } + } + /** + * @desc Get Kernel program string (in *glsl*) for a kernel. + * @returns {String} result + */ + getKernelString() { + const result = [this.getKernelResultDeclaration()]; + const { subKernels } = this; + if (subKernels !== null) { + switch (this.returnType) { + case 'Number': + case 'Float': + case 'Integer': + for (let i = 0; i < subKernels.length; i++) { + const subKernel = subKernels[i]; + result.push( + subKernel.returnType === 'Integer' ? + `int subKernelResult_${ subKernel.name } = 0` : + `float subKernelResult_${ subKernel.name } = 0.0` + ); + } + break; + case 'Array(2)': + for (let i = 0; i < subKernels.length; i++) { + result.push( + `vec2 subKernelResult_${ subKernels[i].name }` + ); + } + break; + case 'Array(3)': + for (let i = 0; i < subKernels.length; i++) { + result.push( + `vec3 subKernelResult_${ subKernels[i].name }` + ); + } + break; + case 'Array(4)': + for (let i = 0; i < subKernels.length; i++) { + result.push( + `vec4 subKernelResult_${ subKernels[i].name }` + ); + } + break; + } + } + + return utils.linesToString(result) + this.translatedSource; + } + + getMainResultGraphical() { + return utils.linesToString([ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ' gl_FragColor = actualColor', + ]); + } + + getMainResultPackedPixels() { + switch (this.returnType) { + case 'LiteralInteger': + case 'Number': + case 'Integer': + case 'Float': + return this.getMainResultKernelPackedPixels() + + this.getMainResultSubKernelPackedPixels(); + default: + throw new Error(`packed output only usable with Numbers, "${this.returnType}" specified`); + } + } + + /** + * @return {String} + */ + getMainResultKernelPackedPixels() { + return utils.linesToString([ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ` gl_FragData[0] = ${this.useLegacyEncoder ? 'legacyEncode32' : 'encode32'}(kernelResult)` + ]); + } + + /** + * @return {String} + */ + getMainResultSubKernelPackedPixels() { + const result = []; + if (!this.subKernels) return ''; + for (let i = 0; i < this.subKernels.length; i++) { + const subKernel = this.subKernels[i]; + if (subKernel.returnType === 'Integer') { + result.push( + ` gl_FragData[${i + 1}] = ${this.useLegacyEncoder ? 'legacyEncode32' : 'encode32'}(float(subKernelResult_${this.subKernels[i].name}))` + ); + } else { + result.push( + ` gl_FragData[${i + 1}] = ${this.useLegacyEncoder ? 'legacyEncode32' : 'encode32'}(subKernelResult_${this.subKernels[i].name})` + ); + } + } + return utils.linesToString(result); + } + + getMainResultMemoryOptimizedFloats() { + const result = [ + ' index *= 4', + ]; + + switch (this.returnType) { + case 'Number': + case 'Integer': + case 'Float': + const channels = ['r', 'g', 'b', 'a']; + for (let i = 0; i < channels.length; i++) { + const channel = channels[i]; + this.getMainResultKernelMemoryOptimizedFloats(result, channel); + this.getMainResultSubKernelMemoryOptimizedFloats(result, channel); + if (i + 1 < channels.length) { + result.push(' index += 1'); + } + } + break; + default: + throw new Error(`optimized output only usable with Numbers, ${this.returnType} specified`); + } + + return utils.linesToString(result); + } + + getMainResultKernelMemoryOptimizedFloats(result, channel) { + result.push( + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ` gl_FragData[0].${channel} = kernelResult` + ); + } + + getMainResultSubKernelMemoryOptimizedFloats(result, channel) { + if (!this.subKernels) return result; + for (let i = 0; i < this.subKernels.length; i++) { + const subKernel = this.subKernels[i]; + if (subKernel.returnType === 'Integer') { + result.push( + ` gl_FragData[${i + 1}].${channel} = float(subKernelResult_${this.subKernels[i].name})` + ); + } else { + result.push( + ` gl_FragData[${i + 1}].${channel} = subKernelResult_${this.subKernels[i].name}` + ); + } + } + } + + getMainResultKernelNumberTexture() { + return [ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ' gl_FragData[0][0] = kernelResult', + ]; + } + + getMainResultSubKernelNumberTexture() { + const result = []; + if (!this.subKernels) return result; + for (let i = 0; i < this.subKernels.length; ++i) { + const subKernel = this.subKernels[i]; + if (subKernel.returnType === 'Integer') { + result.push( + ` gl_FragData[${i + 1}][0] = float(subKernelResult_${subKernel.name})` + ); + } else { + result.push( + ` gl_FragData[${i + 1}][0] = subKernelResult_${subKernel.name}` + ); + } + } + return result; + } + + getMainResultKernelArray2Texture() { + return [ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ' gl_FragData[0][0] = kernelResult[0]', + ' gl_FragData[0][1] = kernelResult[1]', + ]; + } + + getMainResultSubKernelArray2Texture() { + const result = []; + if (!this.subKernels) return result; + for (let i = 0; i < this.subKernels.length; ++i) { + result.push( + ` gl_FragData[${i + 1}][0] = subKernelResult_${this.subKernels[i].name}[0]`, + ` gl_FragData[${i + 1}][1] = subKernelResult_${this.subKernels[i].name}[1]` + ); + } + return result; + } + + getMainResultKernelArray3Texture() { + return [ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ' gl_FragData[0][0] = kernelResult[0]', + ' gl_FragData[0][1] = kernelResult[1]', + ' gl_FragData[0][2] = kernelResult[2]', + ]; + } + + getMainResultSubKernelArray3Texture() { + const result = []; + if (!this.subKernels) return result; + for (let i = 0; i < this.subKernels.length; ++i) { + result.push( + ` gl_FragData[${i + 1}][0] = subKernelResult_${this.subKernels[i].name}[0]`, + ` gl_FragData[${i + 1}][1] = subKernelResult_${this.subKernels[i].name}[1]`, + ` gl_FragData[${i + 1}][2] = subKernelResult_${this.subKernels[i].name}[2]` + ); + } + return result; + } + + getMainResultKernelArray4Texture() { + return [ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ' gl_FragData[0] = kernelResult', + ]; + } + + getMainResultSubKernelArray4Texture() { + const result = []; + if (!this.subKernels) return result; + switch (this.returnType) { + case 'Number': + case 'Float': + case 'Integer': + for (let i = 0; i < this.subKernels.length; ++i) { + const subKernel = this.subKernels[i]; + if (subKernel.returnType === 'Integer') { + result.push( + ` gl_FragData[${i + 1}] = float(subKernelResult_${this.subKernels[i].name})` + ); + } else { + result.push( + ` gl_FragData[${i + 1}] = subKernelResult_${this.subKernels[i].name}` + ); + } + } + break; + case 'Array(2)': + for (let i = 0; i < this.subKernels.length; ++i) { + result.push( + ` gl_FragData[${i + 1}][0] = subKernelResult_${this.subKernels[i].name}[0]`, + ` gl_FragData[${i + 1}][1] = subKernelResult_${this.subKernels[i].name}[1]` + ); + } + break; + case 'Array(3)': + for (let i = 0; i < this.subKernels.length; ++i) { + result.push( + ` gl_FragData[${i + 1}][0] = subKernelResult_${this.subKernels[i].name}[0]`, + ` gl_FragData[${i + 1}][1] = subKernelResult_${this.subKernels[i].name}[1]`, + ` gl_FragData[${i + 1}][2] = subKernelResult_${this.subKernels[i].name}[2]` + ); + } + break; + case 'Array(4)': + for (let i = 0; i < this.subKernels.length; ++i) { + result.push( + ` gl_FragData[${i + 1}][0] = subKernelResult_${this.subKernels[i].name}[0]`, + ` gl_FragData[${i + 1}][1] = subKernelResult_${this.subKernels[i].name}[1]`, + ` gl_FragData[${i + 1}][2] = subKernelResult_${this.subKernels[i].name}[2]`, + ` gl_FragData[${i + 1}][3] = subKernelResult_${this.subKernels[i].name}[3]` + ); + } + break; + } + + return result; + } + + /** + * @param {String} src - Shader string + * @param {Object} map - Variables/Constants associated with shader + */ + replaceArtifacts(src, map) { + return src.replace(/[ ]*__([A-Z]+[0-9]*([_]?[A-Z]*[0-9]?)*)__;\n/g, (match, artifact) => { + if (map.hasOwnProperty(artifact)) { + return map[artifact]; + } + throw `unhandled artifact ${artifact}`; + }); + } + + /** + * @desc Get the fragment shader String. + * If the String hasn't been compiled yet, + * then this method compiles it as well + * + * @param {Array} args - The actual parameters sent to the Kernel + * @returns {string} Fragment Shader string + */ + getFragmentShader(args) { + if (this.compiledFragmentShader !== null) { + return this.compiledFragmentShader; + } + return this.compiledFragmentShader = this.replaceArtifacts(this.constructor.fragmentShader, this._getFragShaderArtifactMap(args)); + } + + /** + * @desc Get the vertical shader String + * @param {Array|IArguments} args - The actual parameters sent to the Kernel + * @returns {string} Vertical Shader string + */ + getVertexShader(args) { + if (this.compiledVertexShader !== null) { + return this.compiledVertexShader; + } + return this.compiledVertexShader = this.replaceArtifacts(this.constructor.vertexShader, this._getVertShaderArtifactMap(args)); + } + + /** + * @desc Returns the *pre-compiled* Kernel as a JS Object String, that can be reused. + */ + toString() { + const setupContextString = utils.linesToString([ + `const gl = context`, + ]); + return glKernelString(this.constructor, arguments, this, setupContextString); + } + + destroy(removeCanvasReferences) { + if (!this.context) return; + if (this.buffer) { + this.context.deleteBuffer(this.buffer); + } + if (this.framebuffer) { + this.context.deleteFramebuffer(this.framebuffer); + } + for (const width in this.rawValueFramebuffers) { + for (const height in this.rawValueFramebuffers[width]) { + this.context.deleteFramebuffer(this.rawValueFramebuffers[width][height]); + delete this.rawValueFramebuffers[width][height]; + } + delete this.rawValueFramebuffers[width]; + } + if (this.vertShader) { + this.context.deleteShader(this.vertShader); + } + if (this.fragShader) { + this.context.deleteShader(this.fragShader); + } + if (this.program) { + this.context.deleteProgram(this.program); + } + if (this.texture) { + this.texture.delete(); + const textureCacheIndex = this.textureCache.indexOf(this.texture.texture); + if (textureCacheIndex > -1) { + this.textureCache.splice(textureCacheIndex, 1); + } + this.texture = null; + } + if (this.mappedTextures && this.mappedTextures.length) { + for (let i = 0; i < this.mappedTextures.length; i++) { + const mappedTexture = this.mappedTextures[i]; + mappedTexture.delete(); + const textureCacheIndex = this.textureCache.indexOf(mappedTexture.texture); + if (textureCacheIndex > -1) { + this.textureCache.splice(textureCacheIndex, 1); + } + } + this.mappedTextures = null; + } + if (this.kernelArguments) { + for (let i = 0; i < this.kernelArguments.length; i++) { + this.kernelArguments[i].destroy(); + } + } + if (this.kernelConstants) { + for (let i = 0; i < this.kernelConstants.length; i++) { + this.kernelConstants[i].destroy(); + } + } + while (this.textureCache.length > 0) { + const texture = this.textureCache.pop(); + this.context.deleteTexture(texture); + } + if (removeCanvasReferences) { + const idx = canvases.indexOf(this.canvas); + if (idx >= 0) { + canvases[idx] = null; + maxTexSizes[idx] = null; + } + } + this.destroyExtensions(); + delete this.context; + delete this.canvas; + if (!this.gpu) return; + const i = this.gpu.kernels.indexOf(this); + if (i === -1) return; + this.gpu.kernels.splice(i, 1); + } + + destroyExtensions() { + this.extensions.OES_texture_float = null; + this.extensions.OES_texture_float_linear = null; + this.extensions.OES_element_index_uint = null; + this.extensions.WEBGL_draw_buffers = null; + } + + static destroyContext(context) { + const extension = context.getExtension('WEBGL_lose_context'); + if (extension) { + extension.loseContext(); + } + } + + /** + * @return {IKernelJSON} + */ + toJSON() { + const json = super.toJSON(); + json.functionNodes = FunctionBuilder.fromKernel(this, WebGLFunctionNode).toJSON(); + json.settings.threadDim = this.threadDim; + return json; + } +} + +module.exports = { + WebGLKernel +}; +},{"../../plugins/math-random-uniformly-distributed":289,"../../utils":291,"../function-builder":188,"../gl/kernel":192,"../gl/kernel-string":191,"./fragment-shader":216,"./function-node":217,"./kernel-value-maps":218,"./vertex-shader":250}],250:[function(require,module,exports){ +// language=GLSL +const vertexShader = `__FLOAT_TACTIC_DECLARATION__; +__INT_TACTIC_DECLARATION__; +__SAMPLER_2D_TACTIC_DECLARATION__; + +attribute vec2 aPos; +attribute vec2 aTexCoord; + +varying vec2 vTexCoord; +uniform vec2 ratio; + +void main(void) { + gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1); + vTexCoord = aTexCoord; +}`; + +module.exports = { + vertexShader +}; +},{}],251:[function(require,module,exports){ +// language=GLSL +const fragmentShader = `#version 300 es +__HEADER__; +__FLOAT_TACTIC_DECLARATION__; +__INT_TACTIC_DECLARATION__; +__SAMPLER_2D_TACTIC_DECLARATION__; +__SAMPLER_2D_ARRAY_TACTIC_DECLARATION__; + +const int LOOP_MAX = __LOOP_MAX__; + +__PLUGINS__; +__CONSTANTS__; + +in vec2 vTexCoord; + +float atan2(float v1, float v2) { + if (v1 == 0.0 || v2 == 0.0) return 0.0; + return atan(v1 / v2); +} + +float cbrt(float x) { + if (x >= 0.0) { + return pow(x, 1.0 / 3.0); + } else { + return -pow(x, 1.0 / 3.0); + } +} + +float expm1(float x) { + return pow(${Math.E}, x) - 1.0; +} + +float fround(highp float x) { + return x; +} + +float imul(float v1, float v2) { + return float(int(v1) * int(v2)); +} + +float log10(float x) { + return log2(x) * (1.0 / log2(10.0)); +} + +float log1p(float x) { + return log(1.0 + x); +} + +float _pow(float v1, float v2) { + if (v2 == 0.0) return 1.0; + return pow(v1, v2); +} + +float _round(float x) { + return floor(x + 0.5); +} + + +const int BIT_COUNT = 32; +int modi(int x, int y) { + return x - y * (x / y); +} + +int bitwiseOr(int a, int b) { + int result = 0; + int n = 1; + + for (int i = 0; i < BIT_COUNT; i++) { + if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) { + result += n; + } + a = a / 2; + b = b / 2; + n = n * 2; + if(!(a > 0 || b > 0)) { + break; + } + } + return result; +} +int bitwiseXOR(int a, int b) { + int result = 0; + int n = 1; + + for (int i = 0; i < BIT_COUNT; i++) { + if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) { + result += n; + } + a = a / 2; + b = b / 2; + n = n * 2; + if(!(a > 0 || b > 0)) { + break; + } + } + return result; +} +int bitwiseAnd(int a, int b) { + int result = 0; + int n = 1; + for (int i = 0; i < BIT_COUNT; i++) { + if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) { + result += n; + } + a = a / 2; + b = b / 2; + n = n * 2; + if(!(a > 0 && b > 0)) { + break; + } + } + return result; +} +int bitwiseNot(int a) { + int result = 0; + int n = 1; + + for (int i = 0; i < BIT_COUNT; i++) { + if (modi(a, 2) == 0) { + result += n; + } + a = a / 2; + n = n * 2; + } + return result; +} +int bitwiseZeroFillLeftShift(int n, int shift) { + int maxBytes = BIT_COUNT; + for (int i = 0; i < BIT_COUNT; i++) { + if (maxBytes >= n) { + break; + } + maxBytes *= 2; + } + for (int i = 0; i < BIT_COUNT; i++) { + if (i >= shift) { + break; + } + n *= 2; + } + + int result = 0; + int byteVal = 1; + for (int i = 0; i < BIT_COUNT; i++) { + if (i >= maxBytes) break; + if (modi(n, 2) > 0) { result += byteVal; } + n = int(n / 2); + byteVal *= 2; + } + return result; +} + +int bitwiseSignedRightShift(int num, int shifts) { + return int(floor(float(num) / pow(2.0, float(shifts)))); +} + +int bitwiseZeroFillRightShift(int n, int shift) { + int maxBytes = BIT_COUNT; + for (int i = 0; i < BIT_COUNT; i++) { + if (maxBytes >= n) { + break; + } + maxBytes *= 2; + } + for (int i = 0; i < BIT_COUNT; i++) { + if (i >= shift) { + break; + } + n /= 2; + } + int result = 0; + int byteVal = 1; + for (int i = 0; i < BIT_COUNT; i++) { + if (i >= maxBytes) break; + if (modi(n, 2) > 0) { result += byteVal; } + n = int(n / 2); + byteVal *= 2; + } + return result; +} + +vec2 integerMod(vec2 x, float y) { + vec2 res = floor(mod(x, y)); + return res * step(1.0 - floor(y), -res); +} + +vec3 integerMod(vec3 x, float y) { + vec3 res = floor(mod(x, y)); + return res * step(1.0 - floor(y), -res); +} + +vec4 integerMod(vec4 x, vec4 y) { + vec4 res = floor(mod(x, y)); + return res * step(1.0 - floor(y), -res); +} + +float integerMod(float x, float y) { + float res = floor(mod(x, y)); + return res * (res > floor(y) - 1.0 ? 0.0 : 1.0); +} + +int integerMod(int x, int y) { + return x - (y * int(x/y)); +} + +__DIVIDE_WITH_INTEGER_CHECK__; + +// Here be dragons! +// DO NOT OPTIMIZE THIS CODE +// YOU WILL BREAK SOMETHING ON SOMEBODY\'S MACHINE +// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME +const vec2 MAGIC_VEC = vec2(1.0, -256.0); +const vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0); +const vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536 +float decode32(vec4 texel) { + __DECODE32_ENDIANNESS__; + texel *= 255.0; + vec2 gte128; + gte128.x = texel.b >= 128.0 ? 1.0 : 0.0; + gte128.y = texel.a >= 128.0 ? 1.0 : 0.0; + float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC); + float res = exp2(round(exponent)); + texel.b = texel.b - 128.0 * gte128.x; + res = dot(texel, SCALE_FACTOR) * exp2(round(exponent-23.0)) + res; + res *= gte128.y * -2.0 + 1.0; + return res; +} + +float decode16(vec4 texel, int index) { + int channel = integerMod(index, 2); + return texel[channel*2] * 255.0 + texel[channel*2 + 1] * 65280.0; +} + +float decode8(vec4 texel, int index) { + int channel = integerMod(index, 4); + return texel[channel] * 255.0; +} + +vec4 legacyEncode32(float f) { + float F = abs(f); + float sign = f < 0.0 ? 1.0 : 0.0; + float exponent = floor(log2(F)); + float mantissa = (exp2(-exponent) * F); + // exponent += floor(log2(mantissa)); + vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV; + texel.rg = integerMod(texel.rg, 256.0); + texel.b = integerMod(texel.b, 128.0); + texel.a = exponent*0.5 + 63.5; + texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0; + texel = floor(texel); + texel *= 0.003921569; // 1/255 + __ENCODE32_ENDIANNESS__; + return texel; +} + +// https://github.com/gpujs/gpu.js/wiki/Encoder-details +vec4 encode32(float value) { + if (value == 0.0) return vec4(0, 0, 0, 0); + + float exponent; + float mantissa; + vec4 result; + float sgn; + + sgn = step(0.0, -value); + value = abs(value); + + exponent = floor(log2(value)); + + mantissa = value*pow(2.0, -exponent)-1.0; + exponent = exponent+127.0; + result = vec4(0,0,0,0); + + result.a = floor(exponent/2.0); + exponent = exponent - result.a*2.0; + result.a = result.a + 128.0*sgn; + + result.b = floor(mantissa * 128.0); + mantissa = mantissa - result.b / 128.0; + result.b = result.b + exponent*128.0; + + result.g = floor(mantissa*32768.0); + mantissa = mantissa - result.g/32768.0; + + result.r = floor(mantissa*8388608.0); + return result/255.0; +} +// Dragons end here + +int index; +ivec3 threadId; + +ivec3 indexTo3D(int idx, ivec3 texDim) { + int z = int(idx / (texDim.x * texDim.y)); + idx -= z * int(texDim.x * texDim.y); + int y = int(idx / texDim.x); + int x = int(integerMod(idx, texDim.x)); + return ivec3(x, y, z); +} + +float get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture(tex, st / vec2(texSize)); + return decode32(texel); +} + +float get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + (texDim.x * (y + (texDim.y * z))); + int w = texSize.x * 2; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture(tex, st / vec2(texSize.x * 2, texSize.y)); + return decode16(texel, index); +} + +float get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + (texDim.x * (y + (texDim.y * z))); + int w = texSize.x * 4; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture(tex, st / vec2(texSize.x * 4, texSize.y)); + return decode8(texel, index); +} + +float getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + (texDim.x * (y + (texDim.y * z))); + int channel = integerMod(index, 4); + index = index / 4; + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + index = index / 4; + vec4 texel = texture(tex, st / vec2(texSize)); + return texel[channel]; +} + +vec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + return texture(tex, st / vec2(texSize)); +} + +vec4 getImage3D(sampler2DArray tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + return texture(tex, vec3(st / vec2(texSize), z)); +} + +float getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + vec4 result = getImage2D(tex, texSize, texDim, z, y, x); + return result[0]; +} + +vec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + vec4 result = getImage2D(tex, texSize, texDim, z, y, x); + return vec2(result[0], result[1]); +} + +vec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int channel = integerMod(index, 2); + index = index / 2; + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture(tex, st / vec2(texSize)); + if (channel == 0) return vec2(texel.r, texel.g); + if (channel == 1) return vec2(texel.b, texel.a); + return vec2(0.0, 0.0); +} + +vec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + vec4 result = getImage2D(tex, texSize, texDim, z, y, x); + return vec3(result[0], result[1], result[2]); +} + +vec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z)); + int vectorIndex = fieldIndex / 4; + int vectorOffset = fieldIndex - vectorIndex * 4; + int readY = vectorIndex / texSize.x; + int readX = vectorIndex - readY * texSize.x; + vec4 tex1 = texture(tex, (vec2(readX, readY) + 0.5) / vec2(texSize)); + + if (vectorOffset == 0) { + return tex1.xyz; + } else if (vectorOffset == 1) { + return tex1.yzw; + } else { + readX++; + if (readX >= texSize.x) { + readX = 0; + readY++; + } + vec4 tex2 = texture(tex, vec2(readX, readY) / vec2(texSize)); + if (vectorOffset == 2) { + return vec3(tex1.z, tex1.w, tex2.x); + } else { + return vec3(tex1.w, tex2.x, tex2.y); + } + } +} + +vec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + return getImage2D(tex, texSize, texDim, z, y, x); +} + +vec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { + int index = x + texDim.x * (y + texDim.y * z); + int channel = integerMod(index, 2); + int w = texSize.x; + vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; + vec4 texel = texture(tex, st / vec2(texSize)); + return vec4(texel.r, texel.g, texel.b, texel.a); +} + +vec4 actualColor; +void color(float r, float g, float b, float a) { + actualColor = vec4(r,g,b,a); +} + +void color(float r, float g, float b) { + color(r,g,b,1.0); +} + +float modulo(float number, float divisor) { + if (number < 0.0) { + number = abs(number); + if (divisor < 0.0) { + divisor = abs(divisor); + } + return -mod(number, divisor); + } + if (divisor < 0.0) { + divisor = abs(divisor); + } + return mod(number, divisor); +} + +__INJECTED_NATIVE__; +__MAIN_CONSTANTS__; +__MAIN_ARGUMENTS__; +__KERNEL__; + +void main(void) { + index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x; + __MAIN_RESULT__; +}`; + +module.exports = { + fragmentShader +}; +},{}],252:[function(require,module,exports){ +const { utils } = require('../../utils'); +const { WebGLFunctionNode } = require('../web-gl/function-node'); + +/** + * @class WebGL2FunctionNode + * @desc [INTERNAL] Takes in a function node, and does all the AST voodoo required to toString its respective webGL code. + * @extends WebGLFunctionNode + * @returns the converted webGL function string + */ +class WebGL2FunctionNode extends WebGLFunctionNode { + + /** + * @desc Parses the abstract syntax tree for *identifier* expression + * @param {Object} idtNode - An ast Node + * @param {Array} retArr - return array string + * @returns {Array} the append retArr + */ + astIdentifierExpression(idtNode, retArr) { + if (idtNode.type !== 'Identifier') { + throw this.astErrorOutput( + 'IdentifierExpression - not an Identifier', + idtNode + ); + } + + const type = this.getType(idtNode); + + const name = utils.sanitizeName(idtNode.name); + if (idtNode.name === 'Infinity') { + retArr.push('intBitsToFloat(2139095039)'); + } else if (type === 'Boolean') { + if (this.argumentNames.indexOf(name) > -1) { + retArr.push(`bool(user_${name})`); + } else { + retArr.push(`user_${name}`); + } + } else { + retArr.push(`user_${name}`); + } + + return retArr; + } +} + +module.exports = { + WebGL2FunctionNode +}; +},{"../../utils":291,"../web-gl/function-node":217}],253:[function(require,module,exports){ +const { WebGL2KernelValueBoolean } = require('./kernel-value/boolean'); +const { WebGL2KernelValueFloat } = require('./kernel-value/float'); +const { WebGL2KernelValueInteger } = require('./kernel-value/integer'); + +const { WebGL2KernelValueHTMLImage } = require('./kernel-value/html-image'); +const { WebGL2KernelValueDynamicHTMLImage } = require('./kernel-value/dynamic-html-image'); + +const { WebGL2KernelValueHTMLImageArray } = require('./kernel-value/html-image-array'); +const { WebGL2KernelValueDynamicHTMLImageArray } = require('./kernel-value/dynamic-html-image-array'); + +const { WebGL2KernelValueHTMLVideo } = require('./kernel-value/html-video'); +const { WebGL2KernelValueDynamicHTMLVideo } = require('./kernel-value/dynamic-html-video'); + +const { WebGL2KernelValueSingleInput } = require('./kernel-value/single-input'); +const { WebGL2KernelValueDynamicSingleInput } = require('./kernel-value/dynamic-single-input'); + +const { WebGL2KernelValueUnsignedInput } = require('./kernel-value/unsigned-input'); +const { WebGL2KernelValueDynamicUnsignedInput } = require('./kernel-value/dynamic-unsigned-input'); + +const { WebGL2KernelValueMemoryOptimizedNumberTexture } = require('./kernel-value/memory-optimized-number-texture'); +const { WebGL2KernelValueDynamicMemoryOptimizedNumberTexture } = require('./kernel-value/dynamic-memory-optimized-number-texture'); + +const { WebGL2KernelValueNumberTexture } = require('./kernel-value/number-texture'); +const { WebGL2KernelValueDynamicNumberTexture } = require('./kernel-value/dynamic-number-texture'); + +const { WebGL2KernelValueSingleArray } = require('./kernel-value/single-array'); +const { WebGL2KernelValueDynamicSingleArray } = require('./kernel-value/dynamic-single-array'); + +const { WebGL2KernelValueSingleArray1DI } = require('./kernel-value/single-array1d-i'); +const { WebGL2KernelValueDynamicSingleArray1DI } = require('./kernel-value/dynamic-single-array1d-i'); + +const { WebGL2KernelValueSingleArray2DI } = require('./kernel-value/single-array2d-i'); +const { WebGL2KernelValueDynamicSingleArray2DI } = require('./kernel-value/dynamic-single-array2d-i'); + +const { WebGL2KernelValueSingleArray3DI } = require('./kernel-value/single-array3d-i'); +const { WebGL2KernelValueDynamicSingleArray3DI } = require('./kernel-value/dynamic-single-array3d-i'); + +const { WebGL2KernelValueArray2 } = require('./kernel-value/array2'); +const { WebGL2KernelValueArray3 } = require('./kernel-value/array3'); +const { WebGL2KernelValueArray4 } = require('./kernel-value/array4'); + +const { WebGL2KernelValueUnsignedArray } = require('./kernel-value/unsigned-array'); +const { WebGL2KernelValueDynamicUnsignedArray } = require('./kernel-value/dynamic-unsigned-array'); + +const kernelValueMaps = { + unsigned: { + dynamic: { + 'Boolean': WebGL2KernelValueBoolean, + 'Integer': WebGL2KernelValueInteger, + 'Float': WebGL2KernelValueFloat, + 'Array': WebGL2KernelValueDynamicUnsignedArray, + 'Array(2)': WebGL2KernelValueArray2, + 'Array(3)': WebGL2KernelValueArray3, + 'Array(4)': WebGL2KernelValueArray4, + 'Array1D(2)': false, + 'Array1D(3)': false, + 'Array1D(4)': false, + 'Array2D(2)': false, + 'Array2D(3)': false, + 'Array2D(4)': false, + 'Array3D(2)': false, + 'Array3D(3)': false, + 'Array3D(4)': false, + 'Input': WebGL2KernelValueDynamicUnsignedInput, + 'NumberTexture': WebGL2KernelValueDynamicNumberTexture, + 'ArrayTexture(1)': WebGL2KernelValueDynamicNumberTexture, + 'ArrayTexture(2)': WebGL2KernelValueDynamicNumberTexture, + 'ArrayTexture(3)': WebGL2KernelValueDynamicNumberTexture, + 'ArrayTexture(4)': WebGL2KernelValueDynamicNumberTexture, + 'MemoryOptimizedNumberTexture': WebGL2KernelValueDynamicMemoryOptimizedNumberTexture, + 'HTMLCanvas': WebGL2KernelValueDynamicHTMLImage, + 'HTMLImage': WebGL2KernelValueDynamicHTMLImage, + 'HTMLImageArray': WebGL2KernelValueDynamicHTMLImageArray, + 'HTMLVideo': WebGL2KernelValueDynamicHTMLVideo, + }, + static: { + 'Boolean': WebGL2KernelValueBoolean, + 'Float': WebGL2KernelValueFloat, + 'Integer': WebGL2KernelValueInteger, + 'Array': WebGL2KernelValueUnsignedArray, + 'Array(2)': WebGL2KernelValueArray2, + 'Array(3)': WebGL2KernelValueArray3, + 'Array(4)': WebGL2KernelValueArray4, + 'Array1D(2)': false, + 'Array1D(3)': false, + 'Array1D(4)': false, + 'Array2D(2)': false, + 'Array2D(3)': false, + 'Array2D(4)': false, + 'Array3D(2)': false, + 'Array3D(3)': false, + 'Array3D(4)': false, + 'Input': WebGL2KernelValueUnsignedInput, + 'NumberTexture': WebGL2KernelValueNumberTexture, + 'ArrayTexture(1)': WebGL2KernelValueNumberTexture, + 'ArrayTexture(2)': WebGL2KernelValueNumberTexture, + 'ArrayTexture(3)': WebGL2KernelValueNumberTexture, + 'ArrayTexture(4)': WebGL2KernelValueNumberTexture, + 'MemoryOptimizedNumberTexture': WebGL2KernelValueDynamicMemoryOptimizedNumberTexture, + 'HTMLCanvas': WebGL2KernelValueHTMLImage, + 'HTMLImage': WebGL2KernelValueHTMLImage, + 'HTMLImageArray': WebGL2KernelValueHTMLImageArray, + 'HTMLVideo': WebGL2KernelValueHTMLVideo, + } + }, + single: { + dynamic: { + 'Boolean': WebGL2KernelValueBoolean, + 'Integer': WebGL2KernelValueInteger, + 'Float': WebGL2KernelValueFloat, + 'Array': WebGL2KernelValueDynamicSingleArray, + 'Array(2)': WebGL2KernelValueArray2, + 'Array(3)': WebGL2KernelValueArray3, + 'Array(4)': WebGL2KernelValueArray4, + 'Array1D(2)': WebGL2KernelValueDynamicSingleArray1DI, + 'Array1D(3)': WebGL2KernelValueDynamicSingleArray1DI, + 'Array1D(4)': WebGL2KernelValueDynamicSingleArray1DI, + 'Array2D(2)': WebGL2KernelValueDynamicSingleArray2DI, + 'Array2D(3)': WebGL2KernelValueDynamicSingleArray2DI, + 'Array2D(4)': WebGL2KernelValueDynamicSingleArray2DI, + 'Array3D(2)': WebGL2KernelValueDynamicSingleArray3DI, + 'Array3D(3)': WebGL2KernelValueDynamicSingleArray3DI, + 'Array3D(4)': WebGL2KernelValueDynamicSingleArray3DI, + 'Input': WebGL2KernelValueDynamicSingleInput, + 'NumberTexture': WebGL2KernelValueDynamicNumberTexture, + 'ArrayTexture(1)': WebGL2KernelValueDynamicNumberTexture, + 'ArrayTexture(2)': WebGL2KernelValueDynamicNumberTexture, + 'ArrayTexture(3)': WebGL2KernelValueDynamicNumberTexture, + 'ArrayTexture(4)': WebGL2KernelValueDynamicNumberTexture, + 'MemoryOptimizedNumberTexture': WebGL2KernelValueDynamicMemoryOptimizedNumberTexture, + 'HTMLCanvas': WebGL2KernelValueDynamicHTMLImage, + 'HTMLImage': WebGL2KernelValueDynamicHTMLImage, + 'HTMLImageArray': WebGL2KernelValueDynamicHTMLImageArray, + 'HTMLVideo': WebGL2KernelValueDynamicHTMLVideo, + }, + static: { + 'Boolean': WebGL2KernelValueBoolean, + 'Float': WebGL2KernelValueFloat, + 'Integer': WebGL2KernelValueInteger, + 'Array': WebGL2KernelValueSingleArray, + 'Array(2)': WebGL2KernelValueArray2, + 'Array(3)': WebGL2KernelValueArray3, + 'Array(4)': WebGL2KernelValueArray4, + 'Array1D(2)': WebGL2KernelValueSingleArray1DI, + 'Array1D(3)': WebGL2KernelValueSingleArray1DI, + 'Array1D(4)': WebGL2KernelValueSingleArray1DI, + 'Array2D(2)': WebGL2KernelValueSingleArray2DI, + 'Array2D(3)': WebGL2KernelValueSingleArray2DI, + 'Array2D(4)': WebGL2KernelValueSingleArray2DI, + 'Array3D(2)': WebGL2KernelValueSingleArray3DI, + 'Array3D(3)': WebGL2KernelValueSingleArray3DI, + 'Array3D(4)': WebGL2KernelValueSingleArray3DI, + 'Input': WebGL2KernelValueSingleInput, + 'NumberTexture': WebGL2KernelValueNumberTexture, + 'ArrayTexture(1)': WebGL2KernelValueNumberTexture, + 'ArrayTexture(2)': WebGL2KernelValueNumberTexture, + 'ArrayTexture(3)': WebGL2KernelValueNumberTexture, + 'ArrayTexture(4)': WebGL2KernelValueNumberTexture, + 'MemoryOptimizedNumberTexture': WebGL2KernelValueMemoryOptimizedNumberTexture, + 'HTMLCanvas': WebGL2KernelValueHTMLImage, + 'HTMLImage': WebGL2KernelValueHTMLImage, + 'HTMLImageArray': WebGL2KernelValueHTMLImageArray, + 'HTMLVideo': WebGL2KernelValueHTMLVideo, + } + }, +}; + +function lookupKernelValueType(type, dynamic, precision, value) { + if (!type) { + throw new Error('type missing'); + } + if (!dynamic) { + throw new Error('dynamic missing'); + } + if (!precision) { + throw new Error('precision missing'); + } + if (value.type) { + type = value.type; + } + const types = kernelValueMaps[precision][dynamic]; + if (types[type] === false) { + return null; + } else if (types[type] === undefined) { + throw new Error(`Could not find a KernelValue for ${ type }`); + } + return types[type]; +} + +module.exports = { + kernelValueMaps, + lookupKernelValueType +}; +},{"./kernel-value/array2":254,"./kernel-value/array3":255,"./kernel-value/array4":256,"./kernel-value/boolean":257,"./kernel-value/dynamic-html-image":259,"./kernel-value/dynamic-html-image-array":258,"./kernel-value/dynamic-html-video":260,"./kernel-value/dynamic-memory-optimized-number-texture":261,"./kernel-value/dynamic-number-texture":262,"./kernel-value/dynamic-single-array":263,"./kernel-value/dynamic-single-array1d-i":264,"./kernel-value/dynamic-single-array2d-i":265,"./kernel-value/dynamic-single-array3d-i":266,"./kernel-value/dynamic-single-input":267,"./kernel-value/dynamic-unsigned-array":268,"./kernel-value/dynamic-unsigned-input":269,"./kernel-value/float":270,"./kernel-value/html-image":272,"./kernel-value/html-image-array":271,"./kernel-value/html-video":273,"./kernel-value/integer":274,"./kernel-value/memory-optimized-number-texture":275,"./kernel-value/number-texture":276,"./kernel-value/single-array":277,"./kernel-value/single-array1d-i":278,"./kernel-value/single-array2d-i":279,"./kernel-value/single-array3d-i":280,"./kernel-value/single-input":281,"./kernel-value/unsigned-array":282,"./kernel-value/unsigned-input":283}],254:[function(require,module,exports){ +const { WebGLKernelValueArray2 } = require('../../web-gl/kernel-value/array2'); + +class WebGL2KernelValueArray2 extends WebGLKernelValueArray2 {} + +module.exports = { + WebGL2KernelValueArray2 +}; +},{"../../web-gl/kernel-value/array2":220}],255:[function(require,module,exports){ +const { WebGLKernelValueArray3 } = require('../../web-gl/kernel-value/array3'); + +class WebGL2KernelValueArray3 extends WebGLKernelValueArray3 {} + +module.exports = { + WebGL2KernelValueArray3 +}; +},{"../../web-gl/kernel-value/array3":221}],256:[function(require,module,exports){ +const { WebGLKernelValueArray4 } = require('../../web-gl/kernel-value/array4'); + +class WebGL2KernelValueArray4 extends WebGLKernelValueArray4 {} + +module.exports = { + WebGL2KernelValueArray4 +}; +},{"../../web-gl/kernel-value/array4":222}],257:[function(require,module,exports){ +const { WebGLKernelValueBoolean } = require('../../web-gl/kernel-value/boolean'); + +class WebGL2KernelValueBoolean extends WebGLKernelValueBoolean {} + +module.exports = { + WebGL2KernelValueBoolean +}; +},{"../../web-gl/kernel-value/boolean":223}],258:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGL2KernelValueHTMLImageArray } = require('./html-image-array'); + +class WebGL2KernelValueDynamicHTMLImageArray extends WebGL2KernelValueHTMLImageArray { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2DArray ${this.id}`, + `uniform ${ variablePrecision } ivec2 ${this.sizeId}`, + `uniform ${ variablePrecision } ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(images) { + const { width, height } = images[0]; + this.checkSize(width, height); + this.dimensions = [width, height, images.length]; + this.textureSize = [width, height]; + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(images); + } +} + +module.exports = { + WebGL2KernelValueDynamicHTMLImageArray +}; +},{"../../../utils":291,"./html-image-array":271}],259:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueDynamicHTMLImage } = require('../../web-gl/kernel-value/dynamic-html-image'); + +class WebGL2KernelValueDynamicHTMLImage extends WebGLKernelValueDynamicHTMLImage { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `uniform ${ variablePrecision } ivec2 ${this.sizeId}`, + `uniform ${ variablePrecision } ivec3 ${this.dimensionsId}`, + ]); + } +} + +module.exports = { + WebGL2KernelValueDynamicHTMLImage +}; +},{"../../../utils":291,"../../web-gl/kernel-value/dynamic-html-image":224}],260:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGL2KernelValueDynamicHTMLImage } = require('./dynamic-html-image'); + +class WebGL2KernelValueDynamicHTMLVideo extends WebGL2KernelValueDynamicHTMLImage {} + +module.exports = { + WebGL2KernelValueDynamicHTMLVideo +}; +},{"../../../utils":291,"./dynamic-html-image":259}],261:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueDynamicMemoryOptimizedNumberTexture } = require('../../web-gl/kernel-value/dynamic-memory-optimized-number-texture'); + +class WebGL2KernelValueDynamicMemoryOptimizedNumberTexture extends WebGLKernelValueDynamicMemoryOptimizedNumberTexture { + getSource() { + return utils.linesToString([ + `uniform sampler2D ${this.id}`, + `uniform ivec2 ${this.sizeId}`, + `uniform ivec3 ${this.dimensionsId}`, + ]); + } +} + +module.exports = { + WebGL2KernelValueDynamicMemoryOptimizedNumberTexture +}; +},{"../../../utils":291,"../../web-gl/kernel-value/dynamic-memory-optimized-number-texture":226}],262:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueDynamicNumberTexture } = require('../../web-gl/kernel-value/dynamic-number-texture'); + +class WebGL2KernelValueDynamicNumberTexture extends WebGLKernelValueDynamicNumberTexture { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `uniform ${ variablePrecision } ivec2 ${this.sizeId}`, + `uniform ${ variablePrecision } ivec3 ${this.dimensionsId}`, + ]); + } +} + +module.exports = { + WebGL2KernelValueDynamicNumberTexture +}; +},{"../../../utils":291,"../../web-gl/kernel-value/dynamic-number-texture":227}],263:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGL2KernelValueSingleArray } = require('../../web-gl2/kernel-value/single-array'); + +class WebGL2KernelValueDynamicSingleArray extends WebGL2KernelValueSingleArray { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `uniform ${ variablePrecision } ivec2 ${this.sizeId}`, + `uniform ${ variablePrecision } ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + this.dimensions = utils.getDimensions(value, true); + this.textureSize = utils.getMemoryOptimizedFloatTextureSize(this.dimensions, this.bitRatio); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.uploadValue = new Float32Array(this.uploadArrayLength); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGL2KernelValueDynamicSingleArray +}; +},{"../../../utils":291,"../../web-gl2/kernel-value/single-array":277}],264:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGL2KernelValueSingleArray1DI } = require('../../web-gl2/kernel-value/single-array1d-i'); + +class WebGL2KernelValueDynamicSingleArray1DI extends WebGL2KernelValueSingleArray1DI { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `uniform ${ variablePrecision } ivec2 ${this.sizeId}`, + `uniform ${ variablePrecision } ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + this.setShape(value); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGL2KernelValueDynamicSingleArray1DI +}; +},{"../../../utils":291,"../../web-gl2/kernel-value/single-array1d-i":278}],265:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGL2KernelValueSingleArray2DI } = require('../../web-gl2/kernel-value/single-array2d-i'); + +class WebGL2KernelValueDynamicSingleArray2DI extends WebGL2KernelValueSingleArray2DI { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `uniform ${ variablePrecision } ivec2 ${this.sizeId}`, + `uniform ${ variablePrecision } ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + this.setShape(value); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGL2KernelValueDynamicSingleArray2DI +}; +},{"../../../utils":291,"../../web-gl2/kernel-value/single-array2d-i":279}],266:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGL2KernelValueSingleArray3DI } = require('../../web-gl2/kernel-value/single-array3d-i'); + +class WebGL2KernelValueDynamicSingleArray3DI extends WebGL2KernelValueSingleArray3DI { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `uniform ${ variablePrecision } ivec2 ${this.sizeId}`, + `uniform ${ variablePrecision } ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + this.setShape(value); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGL2KernelValueDynamicSingleArray3DI +}; +},{"../../../utils":291,"../../web-gl2/kernel-value/single-array3d-i":280}],267:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGL2KernelValueSingleInput } = require('../../web-gl2/kernel-value/single-input'); + +class WebGL2KernelValueDynamicSingleInput extends WebGL2KernelValueSingleInput { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `uniform ${ variablePrecision } ivec2 ${this.sizeId}`, + `uniform ${ variablePrecision } ivec3 ${this.dimensionsId}`, + ]); + } + + updateValue(value) { + let [w, h, d] = value.size; + this.dimensions = new Int32Array([w || 1, h || 1, d || 1]); + this.textureSize = utils.getMemoryOptimizedFloatTextureSize(this.dimensions, this.bitRatio); + this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; + this.checkSize(this.textureSize[0], this.textureSize[1]); + this.uploadValue = new Float32Array(this.uploadArrayLength); + this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); + this.kernel.setUniform2iv(this.sizeId, this.textureSize); + super.updateValue(value); + } +} + +module.exports = { + WebGL2KernelValueDynamicSingleInput +}; +},{"../../../utils":291,"../../web-gl2/kernel-value/single-input":281}],268:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueDynamicUnsignedArray } = require('../../web-gl/kernel-value/dynamic-unsigned-array'); + +class WebGL2KernelValueDynamicUnsignedArray extends WebGLKernelValueDynamicUnsignedArray { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `uniform ${ variablePrecision } ivec2 ${this.sizeId}`, + `uniform ${ variablePrecision } ivec3 ${this.dimensionsId}`, + ]); + } +} + +module.exports = { + WebGL2KernelValueDynamicUnsignedArray +}; +},{"../../../utils":291,"../../web-gl/kernel-value/dynamic-unsigned-array":233}],269:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueDynamicUnsignedInput } = require('../../web-gl/kernel-value/dynamic-unsigned-input'); + +class WebGL2KernelValueDynamicUnsignedInput extends WebGLKernelValueDynamicUnsignedInput { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `uniform ${ variablePrecision } ivec2 ${this.sizeId}`, + `uniform ${ variablePrecision } ivec3 ${this.dimensionsId}`, + ]); + } +} + +module.exports = { + WebGL2KernelValueDynamicUnsignedInput +}; +},{"../../../utils":291,"../../web-gl/kernel-value/dynamic-unsigned-input":234}],270:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueFloat } = require('../../web-gl/kernel-value/float'); + +class WebGL2KernelValueFloat extends WebGLKernelValueFloat {} + +module.exports = { + WebGL2KernelValueFloat +}; +},{"../../../utils":291,"../../web-gl/kernel-value/float":235}],271:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelArray } = require('../../web-gl/kernel-value/array'); + +class WebGL2KernelValueHTMLImageArray extends WebGLKernelArray { + constructor(value, settings) { + super(value, settings); + this.checkSize(value[0].width, value[0].height); + this.dimensions = [value[0].width, value[0].height, value.length]; + this.textureSize = [value[0].width, value[0].height]; + } + defineTexture() { + const { context: gl } = this; + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.texture); + gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + } + + getStringValueHandler() { + return `const uploadValue_${this.name} = ${this.varName};\n`; + } + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2DArray ${this.id}`, + `${ variablePrecision } ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `${ variablePrecision } ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(images) { + const { context: gl } = this; + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + // Upload the images into the texture. + gl.texImage3D( + gl.TEXTURE_2D_ARRAY, + 0, + gl.RGBA, + images[0].width, + images[0].height, + images.length, + 0, + gl.RGBA, + gl.UNSIGNED_BYTE, + null + ); + for (let i = 0; i < images.length; i++) { + const xOffset = 0; + const yOffset = 0; + const imageDepth = 1; + gl.texSubImage3D( + gl.TEXTURE_2D_ARRAY, + 0, + xOffset, + yOffset, + i, + images[i].width, + images[i].height, + imageDepth, + gl.RGBA, + gl.UNSIGNED_BYTE, + this.uploadValue = images[i] + ); + } + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGL2KernelValueHTMLImageArray +}; +},{"../../../utils":291,"../../web-gl/kernel-value/array":219}],272:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueHTMLImage } = require('../../web-gl/kernel-value/html-image'); + +class WebGL2KernelValueHTMLImage extends WebGLKernelValueHTMLImage { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `${ variablePrecision } ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `${ variablePrecision } ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } +} + +module.exports = { + WebGL2KernelValueHTMLImage +}; +},{"../../../utils":291,"../../web-gl/kernel-value/html-image":236}],273:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGL2KernelValueHTMLImage } = require('./html-image'); + +class WebGL2KernelValueHTMLVideo extends WebGL2KernelValueHTMLImage {} + +module.exports = { + WebGL2KernelValueHTMLVideo +}; +},{"../../../utils":291,"./html-image":272}],274:[function(require,module,exports){ +const { WebGLKernelValueInteger } = require('../../web-gl/kernel-value/integer'); + +class WebGL2KernelValueInteger extends WebGLKernelValueInteger { + getSource(value) { + const variablePrecision = this.getVariablePrecisionString(); + if (this.origin === 'constants') { + return `const ${ variablePrecision } int ${this.id} = ${ parseInt(value) };\n`; + } + return `uniform ${ variablePrecision } int ${this.id};\n`; + } + + updateValue(value) { + if (this.origin === 'constants') return; + this.kernel.setUniform1i(this.id, this.uploadValue = value); + } +} + +module.exports = { + WebGL2KernelValueInteger +}; +},{"../../web-gl/kernel-value/integer":239}],275:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueMemoryOptimizedNumberTexture } = require('../../web-gl/kernel-value/memory-optimized-number-texture'); + +class WebGL2KernelValueMemoryOptimizedNumberTexture extends WebGLKernelValueMemoryOptimizedNumberTexture { + getSource() { + const { id, sizeId, textureSize, dimensionsId, dimensions } = this; + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform sampler2D ${id}`, + `${ variablePrecision } ivec2 ${sizeId} = ivec2(${textureSize[0]}, ${textureSize[1]})`, + `${ variablePrecision } ivec3 ${dimensionsId} = ivec3(${dimensions[0]}, ${dimensions[1]}, ${dimensions[2]})`, + ]); + } +} + +module.exports = { + WebGL2KernelValueMemoryOptimizedNumberTexture +}; +},{"../../../utils":291,"../../web-gl/kernel-value/memory-optimized-number-texture":240}],276:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueNumberTexture } = require('../../web-gl/kernel-value/number-texture'); + +class WebGL2KernelValueNumberTexture extends WebGLKernelValueNumberTexture { + getSource() { + const { id, sizeId, textureSize, dimensionsId, dimensions } = this; + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${id}`, + `${ variablePrecision } ivec2 ${sizeId} = ivec2(${textureSize[0]}, ${textureSize[1]})`, + `${ variablePrecision } ivec3 ${dimensionsId} = ivec3(${dimensions[0]}, ${dimensions[1]}, ${dimensions[2]})`, + ]); + } +} + +module.exports = { + WebGL2KernelValueNumberTexture +}; +},{"../../../utils":291,"../../web-gl/kernel-value/number-texture":241}],277:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueSingleArray } = require('../../web-gl/kernel-value/single-array'); + +class WebGL2KernelValueSingleArray extends WebGLKernelValueSingleArray { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `${ variablePrecision } ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `${ variablePrecision } ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(value) { + if (value.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(value.constructor); + return; + } + const { context: gl } = this; + utils.flattenTo(value, this.uploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGL2KernelValueSingleArray +}; +},{"../../../utils":291,"../../web-gl/kernel-value/single-array":242}],278:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueSingleArray1DI } = require('../../web-gl/kernel-value/single-array1d-i'); + +class WebGL2KernelValueSingleArray1DI extends WebGLKernelValueSingleArray1DI { + updateValue(value) { + if (value.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(value.constructor); + return; + } + const { context: gl } = this; + utils.flattenTo(value, this.uploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGL2KernelValueSingleArray1DI +}; +},{"../../../utils":291,"../../web-gl/kernel-value/single-array1d-i":243}],279:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueSingleArray2DI } = require('../../web-gl/kernel-value/single-array2d-i'); + +class WebGL2KernelValueSingleArray2DI extends WebGLKernelValueSingleArray2DI { + updateValue(value) { + if (value.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(value.constructor); + return; + } + const { context: gl } = this; + utils.flattenTo(value, this.uploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGL2KernelValueSingleArray2DI +}; +},{"../../../utils":291,"../../web-gl/kernel-value/single-array2d-i":244}],280:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueSingleArray3DI } = require('../../web-gl/kernel-value/single-array3d-i'); + +class WebGL2KernelValueSingleArray3DI extends WebGLKernelValueSingleArray3DI { + updateValue(value) { + if (value.constructor !== this.initialValueConstructor) { + this.onUpdateValueMismatch(value.constructor); + return; + } + const { context: gl } = this; + utils.flattenTo(value, this.uploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGL2KernelValueSingleArray3DI +}; +},{"../../../utils":291,"../../web-gl/kernel-value/single-array3d-i":245}],281:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueSingleInput } = require('../../web-gl/kernel-value/single-input'); + +class WebGL2KernelValueSingleInput extends WebGLKernelValueSingleInput { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `${ variablePrecision } ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `${ variablePrecision } ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } + + updateValue(input) { + const { context: gl } = this; + utils.flattenTo(input.value, this.uploadValue); + gl.activeTexture(this.contextHandle); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); + this.kernel.setUniform1i(this.id, this.index); + } +} + +module.exports = { + WebGL2KernelValueSingleInput +}; +},{"../../../utils":291,"../../web-gl/kernel-value/single-input":246}],282:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueUnsignedArray } = require('../../web-gl/kernel-value/unsigned-array'); + +class WebGL2KernelValueUnsignedArray extends WebGLKernelValueUnsignedArray { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `${ variablePrecision } ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `${ variablePrecision } ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } +} + +module.exports = { + WebGL2KernelValueUnsignedArray +}; +},{"../../../utils":291,"../../web-gl/kernel-value/unsigned-array":247}],283:[function(require,module,exports){ +const { utils } = require('../../../utils'); +const { WebGLKernelValueUnsignedInput } = require('../../web-gl/kernel-value/unsigned-input'); + +class WebGL2KernelValueUnsignedInput extends WebGLKernelValueUnsignedInput { + getSource() { + const variablePrecision = this.getVariablePrecisionString(); + return utils.linesToString([ + `uniform ${ variablePrecision } sampler2D ${this.id}`, + `${ variablePrecision } ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, + `${ variablePrecision } ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, + ]); + } +} + +module.exports = { + WebGL2KernelValueUnsignedInput +}; +},{"../../../utils":291,"../../web-gl/kernel-value/unsigned-input":248}],284:[function(require,module,exports){ +const { WebGLKernel } = require('../web-gl/kernel'); +const { WebGL2FunctionNode } = require('./function-node'); +const { FunctionBuilder } = require('../function-builder'); +const { utils } = require('../../utils'); +const { fragmentShader } = require('./fragment-shader'); +const { vertexShader } = require('./vertex-shader'); +const { lookupKernelValueType } = require('./kernel-value-maps'); + +let isSupported = null; +/** + * + * @type {HTMLCanvasElement|OffscreenCanvas} + */ +let testCanvas = null; +/** + * + * @type {WebGLRenderingContext} + */ +let testContext = null; +let testExtensions = null; + +/** + * + * @type {IKernelFeatures} + */ +let features = null; + +/** + * @extends WebGLKernel + */ +class WebGL2Kernel extends WebGLKernel { + static get isSupported() { + if (isSupported !== null) { + return isSupported; + } + this.setupFeatureChecks(); + isSupported = this.isContextMatch(testContext); + return isSupported; + } + + static setupFeatureChecks() { + if (typeof document !== 'undefined') { + testCanvas = document.createElement('canvas'); + } else if (typeof OffscreenCanvas !== 'undefined') { + testCanvas = new OffscreenCanvas(0, 0); + } + if (!testCanvas) return; + testContext = testCanvas.getContext('webgl2'); + if (!testContext || !testContext.getExtension) return; + testExtensions = { + EXT_color_buffer_float: testContext.getExtension('EXT_color_buffer_float'), + OES_texture_float_linear: testContext.getExtension('OES_texture_float_linear'), + }; + features = this.getFeatures(); + } + + static isContextMatch(context) { + // from global + if (typeof WebGL2RenderingContext !== 'undefined') { + return context instanceof WebGL2RenderingContext; + } + return false; + } + + /** + * + * @return {IKernelFeatures} + */ + static getFeatures() { + const gl = this.testContext; + return Object.freeze({ + isFloatRead: this.getIsFloatRead(), + isIntegerDivisionAccurate: this.getIsIntegerDivisionAccurate(), + isSpeedTacticSupported: this.getIsSpeedTacticSupported(), + kernelMap: true, + isTextureFloat: true, + isDrawBuffers: true, + channelCount: this.getChannelCount(), + maxTextureSize: this.getMaxTextureSize(), + lowIntPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_INT), + lowFloatPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_FLOAT), + mediumIntPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_INT), + mediumFloatPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT), + highIntPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT), + highFloatPrecision: gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT), + }); + } + + static getIsTextureFloat() { + return true; + } + + static getChannelCount() { + return testContext.getParameter(testContext.MAX_DRAW_BUFFERS); + } + + static getMaxTextureSize() { + return testContext.getParameter(testContext.MAX_TEXTURE_SIZE); + } + + static lookupKernelValueType(type, dynamic, precision, value) { + return lookupKernelValueType(type, dynamic, precision, value); + } + + static get testCanvas() { + return testCanvas; + } + + static get testContext() { + return testContext; + } + + /** + * + * @returns {{isFloatRead: Boolean, isIntegerDivisionAccurate: Boolean, kernelMap: Boolean, isTextureFloat: Boolean}} + */ + static get features() { + return features; + } + + static get fragmentShader() { + return fragmentShader; + } + static get vertexShader() { + return vertexShader; + } + + /** + * + * @return {WebGLRenderingContext|WebGL2RenderingContext} + */ + initContext() { + const settings = { + alpha: false, + depth: false, + antialias: false + }; + return this.canvas.getContext('webgl2', settings); + } + + initExtensions() { + this.extensions = { + EXT_color_buffer_float: this.context.getExtension('EXT_color_buffer_float'), + OES_texture_float_linear: this.context.getExtension('OES_texture_float_linear'), + }; + } + + /** + * @desc Validate settings related to Kernel, such as dimensions size, and auto output support. + * @param {IArguments} args + */ + validateSettings(args) { + if (!this.validate) { + this.texSize = utils.getKernelTextureSize({ + optimizeFloatMemory: this.optimizeFloatMemory, + precision: this.precision, + }, this.output); + return; + } + + const { features } = this.constructor; + if (this.precision === 'single' && !features.isFloatRead) { + throw new Error('Float texture outputs are not supported'); + } else if (!this.graphical && this.precision === null) { + this.precision = features.isFloatRead ? 'single' : 'unsigned'; + } + + if (this.fixIntegerDivisionAccuracy === null) { + this.fixIntegerDivisionAccuracy = !features.isIntegerDivisionAccurate; + } else if (this.fixIntegerDivisionAccuracy && features.isIntegerDivisionAccurate) { + this.fixIntegerDivisionAccuracy = false; + } + + this.checkOutput(); + + if (!this.output || this.output.length === 0) { + if (args.length !== 1) { + throw new Error('Auto output only supported for kernels with only one input'); + } + + const argType = utils.getVariableType(args[0], this.strictIntegers); + switch (argType) { + case 'Array': + this.output = utils.getDimensions(argType); + break; + case 'NumberTexture': + case 'MemoryOptimizedNumberTexture': + case 'ArrayTexture(1)': + case 'ArrayTexture(2)': + case 'ArrayTexture(3)': + case 'ArrayTexture(4)': + this.output = args[0].output; + break; + default: + throw new Error('Auto output not supported for input type: ' + argType); + } + } + + if (this.graphical) { + if (this.output.length !== 2) { + throw new Error('Output must have 2 dimensions on graphical mode'); + } + + if (this.precision === 'single') { + console.warn('Cannot use graphical mode and single precision at the same time'); + this.precision = 'unsigned'; + } + + this.texSize = utils.clone(this.output); + return; + } else if (!this.graphical && this.precision === null && features.isTextureFloat) { + this.precision = 'single'; + } + + this.texSize = utils.getKernelTextureSize({ + optimizeFloatMemory: this.optimizeFloatMemory, + precision: this.precision, + }, this.output); + + this.checkTextureSize(); + } + + translateSource() { + const functionBuilder = FunctionBuilder.fromKernel(this, WebGL2FunctionNode, { + fixIntegerDivisionAccuracy: this.fixIntegerDivisionAccuracy + }); + this.translatedSource = functionBuilder.getPrototypeString('kernel'); + this.setupReturnTypes(functionBuilder); + } + + drawBuffers() { + this.context.drawBuffers(this.drawBuffersMap); + } + + getTextureFormat() { + const { context: gl } = this; + switch (this.getInternalFormat()) { + case gl.R32F: + return gl.RED; + case gl.RG32F: + return gl.RG; + case gl.RGBA32F: + return gl.RGBA; + case gl.RGBA: + return gl.RGBA; + default: + throw new Error('Unknown internal format'); + } + } + getInternalFormat() { + const { context: gl } = this; + + if (this.precision === 'single') { + if (this.pipeline) { + switch (this.returnType) { + case 'Number': + case 'Float': + case 'Integer': + if (this.optimizeFloatMemory) { + return gl.RGBA32F; + } else { + return gl.R32F; + } + case 'Array(2)': + return gl.RG32F; + case 'Array(3)': // there is _no_ 3 channel format which is guaranteed to be color-renderable + case 'Array(4)': + return gl.RGBA32F; + default: + throw new Error('Unhandled return type'); + } + } + return gl.RGBA32F; + } + return gl.RGBA; + } + + _setupOutputTexture() { + const gl = this.context; + if (this.texture) { + // here we inherit from an already existing kernel, so go ahead and just bind textures to the framebuffer + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); + return; + } + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + const texture = gl.createTexture(); + const texSize = this.texSize; + gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + const format = this.getInternalFormat(); + if (this.precision === 'single') { + gl.texStorage2D(gl.TEXTURE_2D, 1, format, texSize[0], texSize[1]); + } else { + gl.texImage2D(gl.TEXTURE_2D, 0, format, texSize[0], texSize[1], 0, format, gl.UNSIGNED_BYTE, null); + } + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + this.texture = new this.TextureConstructor({ + texture, + size: texSize, + dimensions: this.threadDim, + output: this.output, + context: this.context, + internalFormat: this.getInternalFormat(), + textureFormat: this.getTextureFormat(), + kernel: this, + }); + } + + _setupSubOutputTextures() { + const gl = this.context; + if (this.mappedTextures) { + // here we inherit from an already existing kernel, so go ahead and just bind textures to the framebuffer + for (let i = 0; i < this.subKernels.length; i++) { + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i + 1, gl.TEXTURE_2D, this.mappedTextures[i].texture, 0); + } + return; + } + const texSize = this.texSize; + this.drawBuffersMap = [gl.COLOR_ATTACHMENT0]; + this.mappedTextures = []; + for (let i = 0; i < this.subKernels.length; i++) { + const texture = this.createTexture(); + this.drawBuffersMap.push(gl.COLOR_ATTACHMENT0 + i + 1); + gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount + i); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + // TODO: upgrade this + const format = this.getInternalFormat(); + if (this.precision === 'single') { + gl.texStorage2D(gl.TEXTURE_2D, 1, format, texSize[0], texSize[1]); + // gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); + } else { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i + 1, gl.TEXTURE_2D, texture, 0); + + this.mappedTextures.push(new this.TextureConstructor({ + texture, + size: texSize, + dimensions: this.threadDim, + output: this.output, + context: this.context, + internalFormat: this.getInternalFormat(), + textureFormat: this.getTextureFormat(), + kernel: this, + })); + } + } + + /** + * + * @desc Get the header string for the program. + * This returns an empty string if no sub-kernels are defined. + * + * @returns {String} result + */ + _getHeaderString() { + return ''; + } + + /** + * @desc Get texture coordinate string for the program + * @returns {String} result + */ + _getTextureCoordinate() { + const subKernels = this.subKernels; + const variablePrecision = this.getVariablePrecisionString(this.texSize, this.tactic); + if (subKernels === null || subKernels.length < 1) { + return `in ${ variablePrecision } vec2 vTexCoord;\n`; + } else { + return `out ${ variablePrecision } vec2 vTexCoord;\n`; + } + } + + /** + * @desc Generate transpiled glsl Strings for user-defined parameters sent to a kernel + * @param {Array} args - The actual parameters sent to the Kernel + * @returns {String} result + */ + _getMainArgumentsString(args) { + const result = []; + const argumentNames = this.argumentNames; + for (let i = 0; i < argumentNames.length; i++) { + result.push(this.kernelArguments[i].getSource(args[i])); + } + return result.join(''); + } + + /** + * @desc Get Kernel program string (in *glsl*) for a kernel. + * @returns {String} result + */ + getKernelString() { + const result = [this.getKernelResultDeclaration()]; + const subKernels = this.subKernels; + if (subKernels !== null) { + result.push( + 'layout(location = 0) out vec4 data0' + ); + switch (this.returnType) { + case 'Number': + case 'Float': + case 'Integer': + for (let i = 0; i < subKernels.length; i++) { + const subKernel = subKernels[i]; + result.push( + subKernel.returnType === 'Integer' ? + `int subKernelResult_${ subKernel.name } = 0` : + `float subKernelResult_${ subKernel.name } = 0.0`, + `layout(location = ${ i + 1 }) out vec4 data${ i + 1 }` + ); + } + break; + case 'Array(2)': + for (let i = 0; i < subKernels.length; i++) { + result.push( + `vec2 subKernelResult_${ subKernels[i].name }`, + `layout(location = ${ i + 1 }) out vec4 data${ i + 1 }` + ); + } + break; + case 'Array(3)': + for (let i = 0; i < subKernels.length; i++) { + result.push( + `vec3 subKernelResult_${ subKernels[i].name }`, + `layout(location = ${ i + 1 }) out vec4 data${ i + 1 }` + ); + } + break; + case 'Array(4)': + for (let i = 0; i < subKernels.length; i++) { + result.push( + `vec4 subKernelResult_${ subKernels[i].name }`, + `layout(location = ${ i + 1 }) out vec4 data${ i + 1 }` + ); + } + break; + } + } else { + result.push( + 'out vec4 data0' + ); + } + + return utils.linesToString(result) + this.translatedSource; + } + + getMainResultGraphical() { + return utils.linesToString([ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ' data0 = actualColor', + ]); + } + + getMainResultPackedPixels() { + switch (this.returnType) { + case 'LiteralInteger': + case 'Number': + case 'Integer': + case 'Float': + return this.getMainResultKernelPackedPixels() + + this.getMainResultSubKernelPackedPixels(); + default: + throw new Error(`packed output only usable with Numbers, "${this.returnType}" specified`); + } + } + + /** + * @return {String} + */ + getMainResultKernelPackedPixels() { + return utils.linesToString([ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ` data0 = ${this.useLegacyEncoder ? 'legacyEncode32' : 'encode32'}(kernelResult)` + ]); + } + + /** + * @return {String} + */ + getMainResultSubKernelPackedPixels() { + const result = []; + if (!this.subKernels) return ''; + for (let i = 0; i < this.subKernels.length; i++) { + const subKernel = this.subKernels[i]; + if (subKernel.returnType === 'Integer') { + result.push( + ` data${i + 1} = ${this.useLegacyEncoder ? 'legacyEncode32' : 'encode32'}(float(subKernelResult_${this.subKernels[i].name}))` + ); + } else { + result.push( + ` data${i + 1} = ${this.useLegacyEncoder ? 'legacyEncode32' : 'encode32'}(subKernelResult_${this.subKernels[i].name})` + ); + } + } + return utils.linesToString(result); + } + + getMainResultKernelMemoryOptimizedFloats(result, channel) { + result.push( + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ` data0.${channel} = kernelResult` + ); + } + + getMainResultSubKernelMemoryOptimizedFloats(result, channel) { + if (!this.subKernels) return result; + for (let i = 0; i < this.subKernels.length; i++) { + const subKernel = this.subKernels[i]; + if (subKernel.returnType === 'Integer') { + result.push( + ` data${i + 1}.${channel} = float(subKernelResult_${subKernel.name})` + ); + } else { + result.push( + ` data${i + 1}.${channel} = subKernelResult_${subKernel.name}` + ); + } + } + } + + getMainResultKernelNumberTexture() { + return [ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ' data0[0] = kernelResult', + ]; + } + + getMainResultSubKernelNumberTexture() { + const result = []; + if (!this.subKernels) return result; + for (let i = 0; i < this.subKernels.length; ++i) { + const subKernel = this.subKernels[i]; + if (subKernel.returnType === 'Integer') { + result.push( + ` data${i + 1}[0] = float(subKernelResult_${subKernel.name})` + ); + } else { + result.push( + ` data${i + 1}[0] = subKernelResult_${subKernel.name}` + ); + } + } + return result; + } + + getMainResultKernelArray2Texture() { + return [ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ' data0[0] = kernelResult[0]', + ' data0[1] = kernelResult[1]', + ]; + } + + getMainResultSubKernelArray2Texture() { + const result = []; + if (!this.subKernels) return result; + for (let i = 0; i < this.subKernels.length; ++i) { + const subKernel = this.subKernels[i]; + result.push( + ` data${i + 1}[0] = subKernelResult_${subKernel.name}[0]`, + ` data${i + 1}[1] = subKernelResult_${subKernel.name}[1]` + ); + } + return result; + } + + getMainResultKernelArray3Texture() { + return [ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ' data0[0] = kernelResult[0]', + ' data0[1] = kernelResult[1]', + ' data0[2] = kernelResult[2]', + ]; + } + + getMainResultSubKernelArray3Texture() { + const result = []; + if (!this.subKernels) return result; + for (let i = 0; i < this.subKernels.length; ++i) { + const subKernel = this.subKernels[i]; + result.push( + ` data${i + 1}[0] = subKernelResult_${subKernel.name}[0]`, + ` data${i + 1}[1] = subKernelResult_${subKernel.name}[1]`, + ` data${i + 1}[2] = subKernelResult_${subKernel.name}[2]` + ); + } + return result; + } + + getMainResultKernelArray4Texture() { + return [ + ' threadId = indexTo3D(index, uOutputDim)', + ' kernel()', + ' data0 = kernelResult', + ]; + } + + getMainResultSubKernelArray4Texture() { + const result = []; + if (!this.subKernels) return result; + for (let i = 0; i < this.subKernels.length; ++i) { + result.push( + ` data${i + 1} = subKernelResult_${this.subKernels[i].name}` + ); + } + return result; + } + + destroyExtensions() { + this.extensions.EXT_color_buffer_float = null; + this.extensions.OES_texture_float_linear = null; + } + + /** + * @return {IKernelJSON} + */ + toJSON() { + const json = super.toJSON(); + json.functionNodes = FunctionBuilder.fromKernel(this, WebGL2FunctionNode).toJSON(); + json.settings.threadDim = this.threadDim; + return json; + } +} + +module.exports = { + WebGL2Kernel +}; +},{"../../utils":291,"../function-builder":188,"../web-gl/kernel":249,"./fragment-shader":251,"./function-node":252,"./kernel-value-maps":253,"./vertex-shader":285}],285:[function(require,module,exports){ +// language=GLSL +const vertexShader = `#version 300 es +__FLOAT_TACTIC_DECLARATION__; +__INT_TACTIC_DECLARATION__; +__SAMPLER_2D_TACTIC_DECLARATION__; + +in vec2 aPos; +in vec2 aTexCoord; + +out vec2 vTexCoord; +uniform vec2 ratio; + +void main(void) { + gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1); + vTexCoord = aTexCoord; +}`; + +module.exports = { + vertexShader +}; +},{}],286:[function(require,module,exports){ +const { gpuMock } = require('gpu-mock.js'); +const { utils } = require('./utils'); +const { Kernel } = require('./backend/kernel'); +const { CPUKernel } = require('./backend/cpu/kernel'); +const { HeadlessGLKernel } = require('./backend/headless-gl/kernel'); +const { WebGL2Kernel } = require('./backend/web-gl2/kernel'); +const { WebGLKernel } = require('./backend/web-gl/kernel'); +const { kernelRunShortcut } = require('./kernel-run-shortcut'); + + +/** + * + * @type {Array.} + */ +const kernelOrder = [HeadlessGLKernel, WebGL2Kernel, WebGLKernel]; + +/** + * + * @type {string[]} + */ +const kernelTypes = ['gpu', 'cpu']; + +const internalKernels = { + 'headlessgl': HeadlessGLKernel, + 'webgl2': WebGL2Kernel, + 'webgl': WebGLKernel, +}; + +let validate = true; + +/** + * The GPU.js library class which manages the GPU context for the creating kernels + * @class + * @return {GPU} + */ +class GPU { + static disableValidation() { + validate = false; + } + + static enableValidation() { + validate = true; + } + + static get isGPUSupported() { + return kernelOrder.some(Kernel => Kernel.isSupported); + } + + /** + * + * @returns {boolean} + */ + static get isKernelMapSupported() { + return kernelOrder.some(Kernel => Kernel.isSupported && Kernel.features.kernelMap); + } + + /** + * @desc TRUE is platform supports OffscreenCanvas + */ + static get isOffscreenCanvasSupported() { + return (typeof Worker !== 'undefined' && typeof OffscreenCanvas !== 'undefined') || typeof importScripts !== 'undefined'; + } + + /** + * @desc TRUE if platform supports WebGL + */ + static get isWebGLSupported() { + return WebGLKernel.isSupported; + } + + /** + * @desc TRUE if platform supports WebGL2 + */ + static get isWebGL2Supported() { + return WebGL2Kernel.isSupported; + } + + /** + * @desc TRUE if platform supports HeadlessGL + */ + static get isHeadlessGLSupported() { + return HeadlessGLKernel.isSupported; + } + + /** + * + * @desc TRUE if platform supports Canvas + */ + static get isCanvasSupported() { + return typeof HTMLCanvasElement !== 'undefined'; + } + + /** + * @desc TRUE if platform supports HTMLImageArray} + */ + static get isGPUHTMLImageArraySupported() { + return WebGL2Kernel.isSupported; + } + + /** + * @desc TRUE if platform supports single precision} + * @returns {boolean} + */ + static get isSinglePrecisionSupported() { + return kernelOrder.some(Kernel => Kernel.isSupported && Kernel.features.isFloatRead && Kernel.features.isTextureFloat); + } + + /** + * Creates an instance of GPU. + * @param {IGPUSettings} [settings] - Settings to set mode, and other properties + * @constructor + */ + constructor(settings) { + settings = settings || {}; + this.canvas = settings.canvas || null; + this.context = settings.context || null; + this.mode = settings.mode; + this.Kernel = null; + this.kernels = []; + this.functions = []; + this.nativeFunctions = []; + this.injectedNative = null; + if (this.mode === 'dev') return; + this.chooseKernel(); + // add functions from settings + if (settings.functions) { + for (let i = 0; i < settings.functions.length; i++) { + this.addFunction(settings.functions[i]); + } + } + + // add native functions from settings + if (settings.nativeFunctions) { + for (const p in settings.nativeFunctions) { + if (!settings.nativeFunctions.hasOwnProperty(p)) continue; + const s = settings.nativeFunctions[p]; + const { name, source } = s; + this.addNativeFunction(name, source, s); + } + } + } + + /** + * Choose kernel type and save on .Kernel property of GPU + */ + chooseKernel() { + if (this.Kernel) return; + + /** + * + * @type {WebGLKernel|WebGL2Kernel|HeadlessGLKernel|CPUKernel} + */ + let Kernel = null; + + if (this.context) { + for (let i = 0; i < kernelOrder.length; i++) { + const ExternalKernel = kernelOrder[i]; + if (ExternalKernel.isContextMatch(this.context)) { + if (!ExternalKernel.isSupported) { + throw new Error(`Kernel type ${ExternalKernel.name} not supported`); + } + Kernel = ExternalKernel; + break; + } + } + if (Kernel === null) { + throw new Error('unknown Context'); + } + } else if (this.mode) { + if (this.mode in internalKernels) { + if (!validate || internalKernels[this.mode].isSupported) { + Kernel = internalKernels[this.mode]; + } + } else if (this.mode === 'gpu') { + for (let i = 0; i < kernelOrder.length; i++) { + if (kernelOrder[i].isSupported) { + Kernel = kernelOrder[i]; + break; + } + } + } else if (this.mode === 'cpu') { + Kernel = CPUKernel; + } + if (!Kernel) { + throw new Error(`A requested mode of "${this.mode}" and is not supported`); + } + } else { + for (let i = 0; i < kernelOrder.length; i++) { + if (kernelOrder[i].isSupported) { + Kernel = kernelOrder[i]; + break; + } + } + if (!Kernel) { + Kernel = CPUKernel; + } + } + + if (!this.mode) { + this.mode = Kernel.mode; + } + this.Kernel = Kernel; + } + + /** + * @desc This creates a callable function object to call the kernel function with the argument parameter set + * @param {Function|String|object} source - The calling to perform the conversion + * @param {IGPUKernelSettings} [settings] - The parameter configuration object + * @return {IKernelRunShortcut} callable function to run + */ + createKernel(source, settings) { + if (typeof source === 'undefined') { + throw new Error('Missing source parameter'); + } + if (typeof source !== 'object' && !utils.isFunction(source) && typeof source !== 'string') { + throw new Error('source parameter not a function'); + } + + const kernels = this.kernels; + if (this.mode === 'dev') { + const devKernel = gpuMock(source, upgradeDeprecatedCreateKernelSettings(settings)); + kernels.push(devKernel); + return devKernel; + } + + source = typeof source === 'function' ? source.toString() : source; + const switchableKernels = {}; + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings) || {}; + // handle conversion of argumentTypes + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } + + function onRequestFallback(args) { + console.warn('Falling back to CPU'); + const fallbackKernel = new CPUKernel(source, { + argumentTypes: kernelRun.argumentTypes, + constantTypes: kernelRun.constantTypes, + graphical: kernelRun.graphical, + loopMaxIterations: kernelRun.loopMaxIterations, + constants: kernelRun.constants, + dynamicOutput: kernelRun.dynamicOutput, + dynamicArgument: kernelRun.dynamicArguments, + output: kernelRun.output, + precision: kernelRun.precision, + pipeline: kernelRun.pipeline, + immutable: kernelRun.immutable, + optimizeFloatMemory: kernelRun.optimizeFloatMemory, + fixIntegerDivisionAccuracy: kernelRun.fixIntegerDivisionAccuracy, + functions: kernelRun.functions, + nativeFunctions: kernelRun.nativeFunctions, + injectedNative: kernelRun.injectedNative, + subKernels: kernelRun.subKernels, + strictIntegers: kernelRun.strictIntegers, + debug: kernelRun.debug, + }); + fallbackKernel.build.apply(fallbackKernel, args); + const result = fallbackKernel.run.apply(fallbackKernel, args); + kernelRun.replaceKernel(fallbackKernel); + return result; + } + + /** + * + * @param {IReason[]} reasons + * @param {IArguments} args + * @param {Kernel} _kernel + * @returns {*} + */ + function onRequestSwitchKernel(reasons, args, _kernel) { + if (_kernel.debug) { + console.warn('Switching kernels'); + } + let newOutput = null; + if (_kernel.signature && !switchableKernels[_kernel.signature]) { + switchableKernels[_kernel.signature] = _kernel; + } + if (_kernel.dynamicOutput) { + for (let i = reasons.length - 1; i >= 0; i--) { + const reason = reasons[i]; + if (reason.type === 'outputPrecisionMismatch') { + newOutput = reason.needed; + } + } + } + + const Constructor = _kernel.constructor; + const argumentTypes = Constructor.getArgumentTypes(_kernel, args); + const signature = Constructor.getSignature(_kernel, argumentTypes); + const existingKernel = switchableKernels[signature]; + if (existingKernel) { + existingKernel.onActivate(_kernel); + return existingKernel; + } + + const newKernel = switchableKernels[signature] = new Constructor(source, { + argumentTypes, + constantTypes: _kernel.constantTypes, + graphical: _kernel.graphical, + loopMaxIterations: _kernel.loopMaxIterations, + constants: _kernel.constants, + dynamicOutput: _kernel.dynamicOutput, + dynamicArgument: _kernel.dynamicArguments, + context: _kernel.context, + canvas: _kernel.canvas, + output: newOutput || _kernel.output, + precision: _kernel.precision, + pipeline: _kernel.pipeline, + immutable: _kernel.immutable, + optimizeFloatMemory: _kernel.optimizeFloatMemory, + fixIntegerDivisionAccuracy: _kernel.fixIntegerDivisionAccuracy, + functions: _kernel.functions, + nativeFunctions: _kernel.nativeFunctions, + injectedNative: _kernel.injectedNative, + subKernels: _kernel.subKernels, + strictIntegers: _kernel.strictIntegers, + debug: _kernel.debug, + gpu: _kernel.gpu, + validate, + returnType: _kernel.returnType, + tactic: _kernel.tactic, + onRequestFallback, + onRequestSwitchKernel, + texture: _kernel.texture, + mappedTextures: _kernel.mappedTextures, + drawBuffersMap: _kernel.drawBuffersMap, + }); + newKernel.build.apply(newKernel, args); + kernelRun.replaceKernel(newKernel); + kernels.push(newKernel); + return newKernel; + } + const mergedSettings = Object.assign({ + context: this.context, + canvas: this.canvas, + functions: this.functions, + nativeFunctions: this.nativeFunctions, + injectedNative: this.injectedNative, + gpu: this, + validate, + onRequestFallback, + onRequestSwitchKernel + }, settingsCopy); + + const kernel = new this.Kernel(source, mergedSettings); + const kernelRun = kernelRunShortcut(kernel); + + //if canvas didn't come from this, propagate from kernel + if (!this.canvas) { + this.canvas = kernel.canvas; + } + + //if context didn't come from this, propagate from kernel + if (!this.context) { + this.context = kernel.context; + } + + kernels.push(kernel); + + return kernelRun; + } + + /** + * + * Create a super kernel which executes sub kernels + * and saves their output to be used with the next sub kernel. + * This can be useful if we want to save the output on one kernel, + * and then use it as an input to another kernel. *Machine Learning* + * + * @param {Object|Array} subKernels - Sub kernels for this kernel + * @param {Function} rootKernel - Root kernel + * + * @returns {Function} callable kernel function + * + * @example + * const megaKernel = gpu.createKernelMap({ + * addResult: function add(a, b) { + * return a[this.thread.x] + b[this.thread.x]; + * }, + * multiplyResult: function multiply(a, b) { + * return a[this.thread.x] * b[this.thread.x]; + * }, + * }, function(a, b, c) { + * return multiply(add(a, b), c); + * }); + * + * megaKernel(a, b, c); + * + * Note: You can also define subKernels as an array of functions. + * > [add, multiply] + * + */ + createKernelMap() { + let fn; + let settings; + const argument2Type = typeof arguments[arguments.length - 2]; + if (argument2Type === 'function' || argument2Type === 'string') { + fn = arguments[arguments.length - 2]; + settings = arguments[arguments.length - 1]; + } else { + fn = arguments[arguments.length - 1]; + } + + if (this.mode !== 'dev') { + if (!this.Kernel.isSupported || !this.Kernel.features.kernelMap) { + if (this.mode && kernelTypes.indexOf(this.mode) < 0) { + throw new Error(`kernelMap not supported on ${this.Kernel.name}`); + } + } + } + + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings); + // handle conversion of argumentTypes + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } + + if (Array.isArray(arguments[0])) { + settingsCopy.subKernels = []; + const functions = arguments[0]; + for (let i = 0; i < functions.length; i++) { + const source = functions[i].toString(); + const name = utils.getFunctionNameFromString(source); + settingsCopy.subKernels.push({ + name, + source, + property: i, + }); + } + } else { + settingsCopy.subKernels = []; + const functions = arguments[0]; + for (let p in functions) { + if (!functions.hasOwnProperty(p)) continue; + const source = functions[p].toString(); + const name = utils.getFunctionNameFromString(source); + settingsCopy.subKernels.push({ + name: name || p, + source, + property: p, + }); + } + } + return this.createKernel(fn, settingsCopy); + } + + /** + * + * Combine different kernels into one super Kernel, + * useful to perform multiple operations inside one + * kernel without the penalty of data transfer between + * cpu and gpu. + * + * The number of kernel functions sent to this method can be variable. + * You can send in one, two, etc. + * + * @param {Function} subKernels - Kernel function(s) to combine. + * @param {Function} rootKernel - Root kernel to combine kernels into + * + * @example + * combineKernels(add, multiply, function(a,b,c){ + * return add(multiply(a,b), c) + * }) + * + * @returns {Function} Callable kernel function + * + */ + combineKernels() { + const firstKernel = arguments[0]; + const combinedKernel = arguments[arguments.length - 1]; + if (firstKernel.kernel.constructor.mode === 'cpu') return combinedKernel; + const canvas = arguments[0].canvas; + const context = arguments[0].context; + const max = arguments.length - 1; + for (let i = 0; i < max; i++) { + arguments[i] + .setCanvas(canvas) + .setContext(context) + .setPipeline(true); + } + + return function() { + const texture = combinedKernel.apply(this, arguments); + if (texture.toArray) { + return texture.toArray(); + } + return texture; + }; + } + + setFunctions(functions) { + this.functions = functions; + return this; + } + + setNativeFunctions(nativeFunctions) { + this.nativeFunctions = nativeFunctions; + return this; + } + + /** + * @desc Adds additional functions, that the kernel may call. + * @param {Function|String} source - Javascript function to convert + * @param {IFunctionSettings} [settings] + * @returns {GPU} returns itself + */ + addFunction(source, settings) { + this.functions.push({ source, settings }); + return this; + } + + /** + * @desc Adds additional native functions, that the kernel may call. + * @param {String} name - native function name, used for reverse lookup + * @param {String} source - the native function implementation, as it would be defined in it's entirety + * @param {object} [settings] + * @returns {GPU} returns itself + */ + addNativeFunction(name, source, settings) { + if (this.kernels.length > 0) { + throw new Error('Cannot call "addNativeFunction" after "createKernels" has been called.'); + } + this.nativeFunctions.push(Object.assign({ name, source }, settings)); + return this; + } + + /** + * Inject a string just before translated kernel functions + * @param {String} source + * @return {GPU} + */ + injectNative(source) { + this.injectedNative = source; + return this; + } + + /** + * @desc Destroys all memory associated with gpu.js & the webGl if we created it + * @return {Promise} + * @resolve {void} + * @reject {Error} + */ + destroy() { + return new Promise((resolve, reject) => { + if (!this.kernels) { + resolve(); + } + // perform on next run loop - for some reason we dont get lose context events + // if webGl is created and destroyed in the same run loop. + setTimeout(() => { + try { + for (let i = 0; i < this.kernels.length; i++) { + this.kernels[i].destroy(true); // remove canvas if exists + } + // all kernels are associated with one context, go ahead and take care of it here + let firstKernel = this.kernels[0]; + if (firstKernel) { + // if it is shortcut + if (firstKernel.kernel) { + firstKernel = firstKernel.kernel; + } + if (firstKernel.constructor.destroyContext) { + firstKernel.constructor.destroyContext(this.context); + } + } + } catch (e) { + reject(e); + } + resolve(); + }, 0); + }); + } +} + + +function upgradeDeprecatedCreateKernelSettings(settings) { + if (!settings) { + return {}; + } + const upgradedSettings = Object.assign({}, settings); + + if (settings.hasOwnProperty('floatOutput')) { + utils.warnDeprecated('setting', 'floatOutput', 'precision'); + upgradedSettings.precision = settings.floatOutput ? 'single' : 'unsigned'; + } + if (settings.hasOwnProperty('outputToTexture')) { + utils.warnDeprecated('setting', 'outputToTexture', 'pipeline'); + upgradedSettings.pipeline = Boolean(settings.outputToTexture); + } + if (settings.hasOwnProperty('outputImmutable')) { + utils.warnDeprecated('setting', 'outputImmutable', 'immutable'); + upgradedSettings.immutable = Boolean(settings.outputImmutable); + } + if (settings.hasOwnProperty('floatTextures')) { + utils.warnDeprecated('setting', 'floatTextures', 'optimizeFloatMemory'); + upgradedSettings.optimizeFloatMemory = Boolean(settings.floatTextures); + } + return upgradedSettings; +} + +module.exports = { + GPU, + kernelOrder, + kernelTypes +}; +},{"./backend/cpu/kernel":187,"./backend/headless-gl/kernel":213,"./backend/kernel":215,"./backend/web-gl/kernel":249,"./backend/web-gl2/kernel":284,"./kernel-run-shortcut":288,"./utils":291,"gpu-mock.js":183}],287:[function(require,module,exports){ +class Input { + constructor(value, size) { + this.value = value; + if (Array.isArray(size)) { + this.size = size; + } else { + this.size = new Int32Array(3); + if (size.z) { + this.size = new Int32Array([size.x, size.y, size.z]); + } else if (size.y) { + this.size = new Int32Array([size.x, size.y]); + } else { + this.size = new Int32Array([size.x]); + } + } + + const [w, h, d] = this.size; + if (d) { + if (this.value.length !== (w * h * d)) { + throw new Error(`Input size ${this.value.length} does not match ${w} * ${h} * ${d} = ${(h * w * d)}`); + } + } else if (h) { + if (this.value.length !== (w * h)) { + throw new Error(`Input size ${this.value.length} does not match ${w} * ${h} = ${(h * w)}`); + } + } else { + if (this.value.length !== w) { + throw new Error(`Input size ${this.value.length} does not match ${w}`); + } + } + + } + + toArray() { + const { utils } = require('./utils'); + const [w, h, d] = this.size; + if (d) { + return utils.erectMemoryOptimized3DFloat(this.value.subarray ? this.value : new Float32Array(this.value), w, h, d); + } else if (h) { + return utils.erectMemoryOptimized2DFloat(this.value.subarray ? this.value : new Float32Array(this.value), w, h); + } else { + return this.value; + } + } +} + +function input(value, size) { + return new Input(value, size); +} + +module.exports = { + Input, + input +}; +},{"./utils":291}],288:[function(require,module,exports){ +const { utils } = require('./utils'); + +/** + * Makes kernels easier for mortals (including me) + * @param kernel + * @returns {function()} + */ +function kernelRunShortcut(kernel) { + let run = function() { + kernel.build.apply(kernel, arguments); + run = function() { + let result = kernel.run.apply(kernel, arguments); + if (kernel.switchingKernels) { + const reasons = kernel.resetSwitchingKernels(); + const newKernel = kernel.onRequestSwitchKernel(reasons, arguments, kernel); + shortcut.kernel = kernel = newKernel; + result = newKernel.run.apply(newKernel, arguments); + } + if (kernel.renderKernels) { + return kernel.renderKernels(); + } else if (kernel.renderOutput) { + return kernel.renderOutput(); + } else { + return result; + } + }; + return run.apply(kernel, arguments); + }; + const shortcut = function() { + return run.apply(kernel, arguments); + }; + /** + * Run kernel in async mode + * @returns {Promise} + */ + shortcut.exec = function() { + return new Promise((accept, reject) => { + try { + accept(run.apply(this, arguments)); + } catch (e) { + reject(e); + } + }); + }; + shortcut.replaceKernel = function(replacementKernel) { + kernel = replacementKernel; + bindKernelToShortcut(kernel, shortcut); + }; + + bindKernelToShortcut(kernel, shortcut); + return shortcut; +} + +function bindKernelToShortcut(kernel, shortcut) { + if (shortcut.kernel) { + shortcut.kernel = kernel; + return; + } + const properties = utils.allPropertiesOf(kernel); + for (let i = 0; i < properties.length; i++) { + const property = properties[i]; + if (property[0] === '_' && property[1] === '_') continue; + if (typeof kernel[property] === 'function') { + if (property.substring(0, 3) === 'add' || property.substring(0, 3) === 'set') { + shortcut[property] = function() { + shortcut.kernel[property].apply(shortcut.kernel, arguments); + return shortcut; + }; + } else { + shortcut[property] = function() { + return shortcut.kernel[property].apply(shortcut.kernel, arguments); + }; + } + } else { + shortcut.__defineGetter__(property, () => shortcut.kernel[property]); + shortcut.__defineSetter__(property, (value) => { + shortcut.kernel[property] = value; + }); + } + } + shortcut.kernel = kernel; +} +module.exports = { + kernelRunShortcut +}; +},{"./utils":291}],289:[function(require,module,exports){ +// language=GLSL +const source = `// https://www.shadertoy.com/view/4t2SDh +//note: uniformly distributed, normalized rand, [0,1] +highp float randomSeedShift = 1.0; +highp float slide = 1.0; +uniform highp float randomSeed1; +uniform highp float randomSeed2; + +highp float nrand(highp vec2 n) { + highp float result = fract(sin(dot((n.xy + 1.0) * vec2(randomSeed1 * slide, randomSeed2 * randomSeedShift), vec2(12.9898, 78.233))) * 43758.5453); + randomSeedShift = result; + if (randomSeedShift > 0.5) { + slide += 0.00009; + } else { + slide += 0.0009; + } + return result; +}`; + +const name = 'math-random-uniformly-distributed'; + +// language=JavaScript +const functionMatch = `Math.random()`; + +const functionReplace = `nrand(vTexCoord)`; + +const functionReturnType = 'Number'; +/** + * + * @param {Kernel} kernel + */ +const onBeforeRun = (kernel) => { + kernel.setUniform1f('randomSeed1', Math.random()); + kernel.setUniform1f('randomSeed2', Math.random()); +}; + +/** + * + * @type IPlugin + */ +const plugin = { + name, + onBeforeRun, + functionMatch, + functionReplace, + functionReturnType, + source +}; + +module.exports = plugin; +},{}],290:[function(require,module,exports){ +/** + * @desc WebGl Texture implementation in JS + * @param {IGPUTextureSettings} settings + */ +class Texture { + constructor(settings) { + const { + texture, + size, + dimensions, + output, + context, + type = 'NumberTexture', + kernel, + internalFormat, + textureFormat + } = settings; + if (!output) throw new Error('settings property "output" required.'); + if (!context) throw new Error('settings property "context" required.'); + if (!texture) throw new Error('settings property "texture" required.'); + if (!kernel) throw new Error('settings property "kernel" required.'); + this.texture = texture; + if (texture._refs) { + texture._refs++; + } else { + texture._refs = 1; + } + this.size = size; + this.dimensions = dimensions; + this.output = output; + this.context = context; + /** + * @type {Kernel} + */ + this.kernel = kernel; + this.type = type; + this._deleted = false; + this.internalFormat = internalFormat; + this.textureFormat = textureFormat; + } + + /** + * @desc Converts the Texture into a JavaScript Array + * @returns {TextureArrayOutput} + */ + toArray() { + throw new Error(`Not implemented on ${this.constructor.name}`); + } + + /** + * @desc Clones the Texture + * @returns {Texture} + */ + clone() { + throw new Error(`Not implemented on ${this.constructor.name}`); + } + + /** + * @desc Deletes the Texture + */ + delete() { + throw new Error(`Not implemented on ${this.constructor.name}`); + } + + clear() { + throw new Error(`Not implemented on ${this.constructor.name}`); + } +} + +module.exports = { + Texture +}; +},{}],291:[function(require,module,exports){ +const acorn = require('acorn'); +const { Input } = require('./input'); +const { Texture } = require('./texture'); + +const FUNCTION_NAME = /function ([^(]*)/; +const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; +const ARGUMENT_NAMES = /([^\s,]+)/g; + +/** + * + * @desc Various utility functions / snippets of code that GPU.JS uses internally. + * @type {utils} + * This covers various snippets of code that is not entirely gpu.js specific (ie. may find uses elsewhere) + */ +const utils = { + /** + * + * @desc Gets the system endianness, and cache it + * @returns {String} 'LE' or 'BE' depending on system architecture + * Credit: https://gist.github.com/TooTallNate/4750953 + */ + systemEndianness() { + return _systemEndianness; + }, + getSystemEndianness() { + const b = new ArrayBuffer(4); + const a = new Uint32Array(b); + const c = new Uint8Array(b); + a[0] = 0xdeadbeef; + if (c[0] === 0xef) return 'LE'; + if (c[0] === 0xde) return 'BE'; + throw new Error('unknown endianness'); + }, + + /** + * @descReturn TRUE, on a JS function + * @param {Function} funcObj - Object to validate if its a function + * @returns {Boolean} TRUE if the object is a JS function + */ + isFunction(funcObj) { + return typeof(funcObj) === 'function'; + }, + + /** + * @desc Return TRUE, on a valid JS function string + * Note: This does just a VERY simply sanity check. And may give false positives. + * + * @param {String} fn - String of JS function to validate + * @returns {Boolean} TRUE if the string passes basic validation + */ + isFunctionString(fn) { + if (typeof fn === 'string') { + return (fn + .slice(0, 'function'.length) + .toLowerCase() === 'function'); + } + return false; + }, + + /** + * @desc Return the function name from a JS function string + * @param {String} funcStr - String of JS function to validate + * @returns {String} Function name string (if found) + */ + getFunctionNameFromString(funcStr) { + const result = FUNCTION_NAME.exec(funcStr); + if (!result || result.length === 0) return null; + return result[1].trim(); + }, + + getFunctionBodyFromString(funcStr) { + return funcStr.substring(funcStr.indexOf('{') + 1, funcStr.lastIndexOf('}')); + }, + + /** + * @desc Return list of argument names extracted from a javascript function + * @param {String} fn - String of JS function to validate + * @returns {String[]} Array representing all the parameter names + */ + getArgumentNamesFromString(fn) { + const fnStr = fn.replace(STRIP_COMMENTS, ''); + let result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); + if (result === null) { + result = []; + } + return result; + }, + + /** + * @desc Returns a clone + * @param {Object} obj - Object to clone + * @returns {Object|Array} Cloned object + */ + clone(obj) { + if (obj === null || typeof obj !== 'object' || obj.hasOwnProperty('isActiveClone')) return obj; + + const temp = obj.constructor(); // changed + + for (let key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + obj.isActiveClone = null; + temp[key] = utils.clone(obj[key]); + delete obj.isActiveClone; + } + } + + return temp; + }, + + /** + * @desc Checks if is an array or Array-like object + * @param {Object} array - The argument object to check if is array + * @returns {Boolean} true if is array or Array-like object + */ + isArray(array) { + return !isNaN(array.length); + }, + + /** + * @desc Evaluate the argument type, to apply respective logic for it + * @param {*} value - The argument object to evaluate type + * @param {boolean} [strictIntegers] + * @returns {String} Argument type Array/Number/Float/Texture/Unknown + */ + getVariableType(value, strictIntegers) { + if (utils.isArray(value)) { + if (value.length > 0 && value[0].nodeName === 'IMG') { + return 'HTMLImageArray'; + } + return 'Array'; + } + + switch (value.constructor) { + case Boolean: + return 'Boolean'; + case Number: + if (strictIntegers && Number.isInteger(value)) { + return 'Integer'; + } + return 'Float'; + case Texture: + return value.type; + case Input: + return 'Input'; + } + switch (value.nodeName) { + case 'IMG': + return 'HTMLImage'; + case 'CANVAS': + return 'HTMLImage'; + case 'VIDEO': + return 'HTMLVideo'; + } + if (value.hasOwnProperty('type')) { + return value.type; + } + return 'Unknown'; + }, + + getKernelTextureSize(settings, dimensions) { + let [w, h, d] = dimensions; + let texelCount = (w || 1) * (h || 1) * (d || 1); + + if (settings.optimizeFloatMemory && settings.precision === 'single') { + w = texelCount = Math.ceil(texelCount / 4); + } + // if given dimensions == a 2d image + if (h > 1 && w * h === texelCount) { + return new Int32Array([w, h]); + } + return utils.closestSquareDimensions(texelCount); + }, + + /** + * + * @param {Number} length + * @returns {TextureDimensions} + */ + closestSquareDimensions(length) { + const sqrt = Math.sqrt(length); + let high = Math.ceil(sqrt); + let low = Math.floor(sqrt); + while (high * low < length) { + high--; + low = Math.ceil(length / high); + } + return new Int32Array([low, Math.ceil(length / low)]); + }, + + /** + * A texture takes up four + * @param {OutputDimensions} dimensions + * @param {Number} bitRatio + * @returns {TextureDimensions} + */ + getMemoryOptimizedFloatTextureSize(dimensions, bitRatio) { + const totalArea = utils.roundTo((dimensions[0] || 1) * (dimensions[1] || 1) * (dimensions[2] || 1) * (dimensions[3] || 1), 4); + const texelCount = totalArea / bitRatio; + return utils.closestSquareDimensions(texelCount); + }, + + /** + * + * @param dimensions + * @param bitRatio + * @returns {*|TextureDimensions} + */ + getMemoryOptimizedPackedTextureSize(dimensions, bitRatio) { + const [w, h, d] = dimensions; + const totalArea = utils.roundTo((w || 1) * (h || 1) * (d || 1), 4); + const texelCount = totalArea / (4 / bitRatio); + return utils.closestSquareDimensions(texelCount); + }, + + roundTo(n, d) { + return Math.floor((n + d - 1) / d) * d; + }, + /** + * @desc Return the dimension of an array. + * @param {Array|String|Texture|Input} x - The array + * @param {Boolean} [pad] - To include padding in the dimension calculation + * @returns {OutputDimensions} + */ + getDimensions(x, pad) { + let ret; + if (utils.isArray(x)) { + const dim = []; + let temp = x; + while (utils.isArray(temp)) { + dim.push(temp.length); + temp = temp[0]; + } + ret = dim.reverse(); + } else if (x instanceof Texture) { + ret = x.output; + } else if (x instanceof Input) { + ret = x.size; + } else { + throw new Error(`Unknown dimensions of ${x}`); + } + + if (pad) { + ret = Array.from(ret); + while (ret.length < 3) { + ret.push(1); + } + } + + return new Int32Array(ret); + }, + + /** + * Puts a nested 2d array into a one-dimensional target array + * @param {Array|*} array + * @param {Float32Array|Float64Array} target + */ + flatten2dArrayTo(array, target) { + let offset = 0; + for (let y = 0; y < array.length; y++) { + target.set(array[y], offset); + offset += array[y].length; + } + }, + + /** + * Puts a nested 3d array into a one-dimensional target array + * @param {Array|*} array + * @param {Float32Array|Float64Array} target + */ + flatten3dArrayTo(array, target) { + let offset = 0; + for (let z = 0; z < array.length; z++) { + for (let y = 0; y < array[z].length; y++) { + target.set(array[z][y], offset); + offset += array[z][y].length; + } + } + }, + + /** + * Puts a nested 4d array into a one-dimensional target array + * @param {Array|*} array + * @param {Float32Array|Float64Array} target + */ + flatten4dArrayTo(array, target) { + let offset = 0; + for (let l = 0; l < array.length; l++) { + for (let z = 0; z < array[l].length; z++) { + for (let y = 0; y < array[l][z].length; y++) { + target.set(array[l][z][y], offset); + offset += array[l][z][y].length; + } + } + } + }, + + /** + * Puts a nested 1d, 2d, or 3d array into a one-dimensional target array + * @param {Float32Array|Uint16Array|Uint8Array} array + * @param {Float32Array} target + */ + flattenTo(array, target) { + if (utils.isArray(array[0])) { + if (utils.isArray(array[0][0])) { + if (utils.isArray(array[0][0][0])) { + utils.flatten4dArrayTo(array, target); + } else { + utils.flatten3dArrayTo(array, target); + } + } else { + utils.flatten2dArrayTo(array, target); + } + } else { + target.set(array); + } + }, + + /** + * + * @desc Splits an array into smaller arrays. + * Number of elements in one small chunk is given by `part` + * + * @param {Number[]} array - The array to split into chunks + * @param {Number} part - elements in one chunk + * + * @returns {Number[]} An array of smaller chunks + */ + splitArray(array, part) { + const result = []; + for (let i = 0; i < array.length; i += part) { + result.push(new array.constructor(array.buffer, i * 4 + array.byteOffset, part)); + } + return result; + }, + + getAstString(source, ast) { + const lines = Array.isArray(source) ? source : source.split(/\r?\n/g); + const start = ast.loc.start; + const end = ast.loc.end; + const result = []; + if (start.line === end.line) { + result.push(lines[start.line - 1].substring(start.column, end.column)); + } else { + result.push(lines[start.line - 1].slice(start.column)); + for (let i = start.line; i < end.line; i++) { + result.push(lines[i]); + } + result.push(lines[end.line - 1].slice(0, end.column)); + } + return result.join('\n'); + }, + + allPropertiesOf(obj) { + const props = []; + + do { + props.push.apply(props, Object.getOwnPropertyNames(obj)); + } while (obj = Object.getPrototypeOf(obj)); + + return props; + }, + + /** + * @param {Array} lines - An Array of strings + * @returns {String} Single combined String, separated by *\n* + */ + linesToString(lines) { + if (lines.length > 0) { + return lines.join(';\n') + ';\n'; + } else { + return '\n'; + } + }, + warnDeprecated(type, oldName, newName) { + if (newName) { + console.warn(`You are using a deprecated ${ type } "${ oldName }". It has been replaced with "${ newName }". Fixing, but please upgrade as it will soon be removed.`); + } else { + console.warn(`You are using a deprecated ${ type } "${ oldName }". It has been removed. Fixing, but please upgrade as it will soon be removed.`); + } + }, + flipPixels: (pixels, width, height) => { + // https://stackoverflow.com/a/41973289/1324039 + const halfHeight = height / 2 | 0; // the | 0 keeps the result an int + const bytesPerRow = width * 4; + // make a temp buffer to hold one row + const temp = new Uint8ClampedArray(width * 4); + const result = pixels.slice(0); + for (let y = 0; y < halfHeight; ++y) { + const topOffset = y * bytesPerRow; + const bottomOffset = (height - y - 1) * bytesPerRow; + + // make copy of a row on the top half + temp.set(result.subarray(topOffset, topOffset + bytesPerRow)); + + // copy a row from the bottom half to the top + result.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow); + + // copy the copy of the top half row to the bottom half + result.set(temp, bottomOffset); + } + return result; + }, + erectPackedFloat: (array, width) => { + return array.subarray(0, width); + }, + erect2DPackedFloat: (array, width, height) => { + const yResults = new Array(height); + for (let y = 0; y < height; y++) { + const xStart = y * width; + const xEnd = xStart + width; + yResults[y] = array.subarray(xStart, xEnd); + } + return yResults; + }, + erect3DPackedFloat: (array, width, height, depth) => { + const zResults = new Array(depth); + for (let z = 0; z < depth; z++) { + const yResults = new Array(height); + for (let y = 0; y < height; y++) { + const xStart = (z * height * width) + y * width; + const xEnd = xStart + width; + yResults[y] = array.subarray(xStart, xEnd); + } + zResults[z] = yResults; + } + return zResults; + }, + erectMemoryOptimizedFloat: (array, width) => { + return array.subarray(0, width); + }, + erectMemoryOptimized2DFloat: (array, width, height) => { + const yResults = new Array(height); + for (let y = 0; y < height; y++) { + const offset = y * width; + yResults[y] = array.subarray(offset, offset + width); + } + return yResults; + }, + erectMemoryOptimized3DFloat: (array, width, height, depth) => { + const zResults = new Array(depth); + for (let z = 0; z < depth; z++) { + const yResults = new Array(height); + for (let y = 0; y < height; y++) { + const offset = (z * height * width) + (y * width); + yResults[y] = array.subarray(offset, offset + width); + } + zResults[z] = yResults; + } + return zResults; + }, + erectFloat: (array, width) => { + const xResults = new Float32Array(width); + let i = 0; + for (let x = 0; x < width; x++) { + xResults[x] = array[i]; + i += 4; + } + return xResults; + }, + erect2DFloat: (array, width, height) => { + const yResults = new Array(height); + let i = 0; + for (let y = 0; y < height; y++) { + const xResults = new Float32Array(width); + for (let x = 0; x < width; x++) { + xResults[x] = array[i]; + i += 4; + } + yResults[y] = xResults; + } + return yResults; + }, + erect3DFloat: (array, width, height, depth) => { + const zResults = new Array(depth); + let i = 0; + for (let z = 0; z < depth; z++) { + const yResults = new Array(height); + for (let y = 0; y < height; y++) { + const xResults = new Float32Array(width); + for (let x = 0; x < width; x++) { + xResults[x] = array[i]; + i += 4; + } + yResults[y] = xResults; + } + zResults[z] = yResults; + } + return zResults; + }, + erectArray2: (array, width) => { + const xResults = new Array(width); + const xResultsMax = width * 4; + let i = 0; + for (let x = 0; x < xResultsMax; x += 4) { + xResults[i++] = array.subarray(x, x + 2); + } + return xResults; + }, + erect2DArray2: (array, width, height) => { + const yResults = new Array(height); + const XResultsMax = width * 4; + for (let y = 0; y < height; y++) { + const xResults = new Array(width); + const offset = y * XResultsMax; + let i = 0; + for (let x = 0; x < XResultsMax; x += 4) { + xResults[i++] = array.subarray(x + offset, x + offset + 2); + } + yResults[y] = xResults; + } + return yResults; + }, + erect3DArray2: (array, width, height, depth) => { + const xResultsMax = width * 4; + const zResults = new Array(depth); + for (let z = 0; z < depth; z++) { + const yResults = new Array(height); + for (let y = 0; y < height; y++) { + const xResults = new Array(width); + const offset = (z * xResultsMax * height) + (y * xResultsMax); + let i = 0; + for (let x = 0; x < xResultsMax; x += 4) { + xResults[i++] = array.subarray(x + offset, x + offset + 2); + } + yResults[y] = xResults; + } + zResults[z] = yResults; + } + return zResults; + }, + erectArray3: (array, width) => { + const xResults = new Array(width); + const xResultsMax = width * 4; + let i = 0; + for (let x = 0; x < xResultsMax; x += 4) { + xResults[i++] = array.subarray(x, x + 3); + } + return xResults; + }, + erect2DArray3: (array, width, height) => { + const xResultsMax = width * 4; + const yResults = new Array(height); + for (let y = 0; y < height; y++) { + const xResults = new Array(width); + const offset = y * xResultsMax; + let i = 0; + for (let x = 0; x < xResultsMax; x += 4) { + xResults[i++] = array.subarray(x + offset, x + offset + 3); + } + yResults[y] = xResults; + } + return yResults; + }, + erect3DArray3: (array, width, height, depth) => { + const xResultsMax = width * 4; + const zResults = new Array(depth); + for (let z = 0; z < depth; z++) { + const yResults = new Array(height); + for (let y = 0; y < height; y++) { + const xResults = new Array(width); + const offset = (z * xResultsMax * height) + (y * xResultsMax); + let i = 0; + for (let x = 0; x < xResultsMax; x += 4) { + xResults[i++] = array.subarray(x + offset, x + offset + 3); + } + yResults[y] = xResults; + } + zResults[z] = yResults; + } + return zResults; + }, + erectArray4: (array, width) => { + const xResults = new Array(array); + const xResultsMax = width * 4; + let i = 0; + for (let x = 0; x < xResultsMax; x += 4) { + xResults[i++] = array.subarray(x, x + 4); + } + return xResults; + }, + erect2DArray4: (array, width, height) => { + const xResultsMax = width * 4; + const yResults = new Array(height); + for (let y = 0; y < height; y++) { + const xResults = new Array(width); + const offset = y * xResultsMax; + let i = 0; + for (let x = 0; x < xResultsMax; x += 4) { + xResults[i++] = array.subarray(x + offset, x + offset + 4); + } + yResults[y] = xResults; + } + return yResults; + }, + erect3DArray4: (array, width, height, depth) => { + const xResultsMax = width * 4; + const zResults = new Array(depth); + for (let z = 0; z < depth; z++) { + const yResults = new Array(height); + for (let y = 0; y < height; y++) { + const xResults = new Array(width); + const offset = (z * xResultsMax * height) + (y * xResultsMax); + let i = 0; + for (let x = 0; x < xResultsMax; x += 4) { + xResults[i++] = array.subarray(x + offset, x + offset + 4); + } + yResults[y] = xResults; + } + zResults[z] = yResults; + } + return zResults; + }, + + /** + * + * @param {String} source + * @param {Object} settings + * @return {String} + */ + flattenFunctionToString: (source, settings) => { + const { findDependency, thisLookup, doNotDefine } = settings; + let flattened = settings.flattened; + if (!flattened) { + flattened = settings.flattened = {}; + } + const ast = acorn.parse(source); + const functionDependencies = []; + let indent = 0; + + function flatten(ast) { + if (Array.isArray(ast)) { + const results = []; + for (let i = 0; i < ast.length; i++) { + results.push(flatten(ast[i])); + } + return results.join(''); + } + switch (ast.type) { + case 'Program': + return flatten(ast.body) + (ast.body[0].type === 'VariableDeclaration' ? ';' : ''); + case 'FunctionDeclaration': + return `function ${ast.id.name}(${ast.params.map(flatten).join(', ')}) ${ flatten(ast.body) }`; + case 'BlockStatement': { + const result = []; + indent += 2; + for (let i = 0; i < ast.body.length; i++) { + const flat = flatten(ast.body[i]); + if (flat) { + result.push(' '.repeat(indent) + flat, ';\n'); + } + } + indent -= 2; + return `{\n${result.join('')}}`; + } + case 'VariableDeclaration': + const declarations = utils.normalizeDeclarations(ast) + .map(flatten) + .filter(r => r !== null); + if (declarations.length < 1) { + return ''; + } else { + return `${ast.kind} ${declarations.join(',')}`; + } + case 'VariableDeclarator': + if (ast.init.object && ast.init.object.type === 'ThisExpression') { + const lookup = thisLookup(ast.init.property.name, true); + if (lookup) { + return `${ast.id.name} = ${flatten(ast.init)}`; + } else { + return null; + } + } else { + return `${ast.id.name} = ${flatten(ast.init)}`; + } + case 'CallExpression': { + if (ast.callee.property.name === 'subarray') { + return `${flatten(ast.callee.object)}.${flatten(ast.callee.property)}(${ast.arguments.map(value => flatten(value)).join(', ')})`; + } + if (ast.callee.object.name === 'gl' || ast.callee.object.name === 'context') { + return `${flatten(ast.callee.object)}.${flatten(ast.callee.property)}(${ast.arguments.map(value => flatten(value)).join(', ')})`; + } + if (ast.callee.object.type === 'ThisExpression') { + functionDependencies.push(findDependency('this', ast.callee.property.name)); + return `${ast.callee.property.name}(${ast.arguments.map(value => flatten(value)).join(', ')})`; + } else if (ast.callee.object.name) { + const foundSource = findDependency(ast.callee.object.name, ast.callee.property.name); + if (foundSource === null) { + // we're not flattening it + return `${ast.callee.object.name}.${ast.callee.property.name}(${ast.arguments.map(value => flatten(value)).join(', ')})`; + } else { + functionDependencies.push(foundSource); + // we're flattening it + return `${ast.callee.property.name}(${ast.arguments.map(value => flatten(value)).join(', ')})`; + } + } else if (ast.callee.object.type === 'MemberExpression') { + return `${flatten(ast.callee.object)}.${ast.callee.property.name}(${ast.arguments.map(value => flatten(value)).join(', ')})`; + } else { + throw new Error('unknown ast.callee'); + } + } + case 'ReturnStatement': + return `return ${flatten(ast.argument)}`; + case 'BinaryExpression': + return `(${flatten(ast.left)}${ast.operator}${flatten(ast.right)})`; + case 'UnaryExpression': + if (ast.prefix) { + return `${ast.operator} ${flatten(ast.argument)}`; + } else { + return `${flatten(ast.argument)} ${ast.operator}`; + } + case 'ExpressionStatement': + return `${flatten(ast.expression)}`; + case 'SequenceExpression': + return `(${flatten(ast.expressions)})`; + case 'ArrowFunctionExpression': + return `(${ast.params.map(flatten).join(', ')}) => ${flatten(ast.body)}`; + case 'Literal': + return ast.raw; + case 'Identifier': + return ast.name; + case 'MemberExpression': + if (ast.object.type === 'ThisExpression') { + return thisLookup(ast.property.name); + } + if (ast.computed) { + return `${flatten(ast.object)}[${flatten(ast.property)}]`; + } + return flatten(ast.object) + '.' + flatten(ast.property); + case 'ThisExpression': + return 'this'; + case 'NewExpression': + return `new ${flatten(ast.callee)}(${ast.arguments.map(value => flatten(value)).join(', ')})`; + case 'ForStatement': + return `for (${flatten(ast.init)};${flatten(ast.test)};${flatten(ast.update)}) ${flatten(ast.body)}`; + case 'AssignmentExpression': + return `${flatten(ast.left)}${ast.operator}${flatten(ast.right)}`; + case 'UpdateExpression': + return `${flatten(ast.argument)}${ast.operator}`; + case 'IfStatement': + return `if (${flatten(ast.test)}) ${flatten(ast.consequent)}`; + case 'ThrowStatement': + return `throw ${flatten(ast.argument)}`; + case 'ObjectPattern': + return ast.properties.map(flatten).join(', '); + case 'ArrayPattern': + return ast.elements.map(flatten).join(', '); + case 'DebuggerStatement': + return 'debugger;'; + case 'ConditionalExpression': + return `${flatten(ast.test)}?${flatten(ast.consequent)}:${flatten(ast.alternate)}`; + case 'Property': + if (ast.kind === 'init') { + return flatten(ast.key); + } + } + throw new Error(`unhandled ast.type of ${ ast.type }`); + } + const result = flatten(ast); + if (functionDependencies.length > 0) { + const flattenedFunctionDependencies = []; + for (let i = 0; i < functionDependencies.length; i++) { + const functionDependency = functionDependencies[i]; + if (!flattened[functionDependency]) { + flattened[functionDependency] = true; + } + functionDependency ? flattenedFunctionDependencies.push(utils.flattenFunctionToString(functionDependency, settings) + '\n') : ''; + } + return flattenedFunctionDependencies.join('') + result; + } + return result; + }, + + normalizeDeclarations: (ast) => { + if (ast.type !== 'VariableDeclaration') throw new Error('Ast is not of type "VariableDeclaration"'); + const normalizedDeclarations = []; + for (let declarationIndex = 0; declarationIndex < ast.declarations.length; declarationIndex++) { + const declaration = ast.declarations[declarationIndex]; + if (declaration.id && declaration.id.type === 'ObjectPattern' && declaration.id.properties) { + const { properties } = declaration.id; + for (let propertyIndex = 0; propertyIndex < properties.length; propertyIndex++) { + const property = properties[propertyIndex]; + if (property.value.type === 'ObjectPattern' && property.value.properties) { + for (let subPropertyIndex = 0; subPropertyIndex < property.value.properties.length; subPropertyIndex++) { + const subProperty = property.value.properties[subPropertyIndex]; + if (subProperty.type === 'Property') { + normalizedDeclarations.push({ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: subProperty.key.name + }, + init: { + type: 'MemberExpression', + object: { + type: 'MemberExpression', + object: declaration.init, + property: { + type: 'Identifier', + name: property.key.name + }, + computed: false + }, + property: { + type: 'Identifier', + name: subProperty.key.name + }, + computed: false + } + }); + } else { + throw new Error('unexpected state'); + } + } + } else if (property.value.type === 'Identifier') { + normalizedDeclarations.push({ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: property.value && property.value.name ? property.value.name : property.key.name + }, + init: { + type: 'MemberExpression', + object: declaration.init, + property: { + type: 'Identifier', + name: property.key.name + }, + computed: false + } + }); + } else { + throw new Error('unexpected state'); + } + } + } else if (declaration.id && declaration.id.type === 'ArrayPattern' && declaration.id.elements) { + const { elements } = declaration.id; + for (let elementIndex = 0; elementIndex < elements.length; elementIndex++) { + const element = elements[elementIndex]; + if (element.type === 'Identifier') { + normalizedDeclarations.push({ + type: 'VariableDeclarator', + id: { + type: 'Identifier', + name: element.name + }, + init: { + type: 'MemberExpression', + object: declaration.init, + property: { + type: 'Literal', + value: elementIndex, + raw: elementIndex.toString(), + start: element.start, + end: element.end + }, + computed: true + } + }); + } else { + throw new Error('unexpected state'); + } + } + } else { + normalizedDeclarations.push(declaration); + } + } + return normalizedDeclarations; + }, + + /** + * + * @param {GPU} gpu + * @param image + * @return {Array} + */ + splitHTMLImageToRGB: (gpu, image) => { + const rKernel = gpu.createKernel(function(a) { + const pixel = a[this.thread.y][this.thread.x]; + return pixel.r * 255; + }, { + output: [image.width, image.height], + precision: 'unsigned', + argumentTypes: { a: 'HTMLImage' }, + }); + const gKernel = gpu.createKernel(function(a) { + const pixel = a[this.thread.y][this.thread.x]; + return pixel.g * 255; + }, { + output: [image.width, image.height], + precision: 'unsigned', + argumentTypes: { a: 'HTMLImage' }, + }); + const bKernel = gpu.createKernel(function(a) { + const pixel = a[this.thread.y][this.thread.x]; + return pixel.b * 255; + }, { + output: [image.width, image.height], + precision: 'unsigned', + argumentTypes: { a: 'HTMLImage' }, + }); + const aKernel = gpu.createKernel(function(a) { + const pixel = a[this.thread.y][this.thread.x]; + return pixel.a * 255; + }, { + output: [image.width, image.height], + precision: 'unsigned', + argumentTypes: { a: 'HTMLImage' }, + }); + const result = [ + rKernel(image), + gKernel(image), + bKernel(image), + aKernel(image), + ]; + result.rKernel = rKernel; + result.gKernel = gKernel; + result.bKernel = bKernel; + result.aKernel = aKernel; + result.gpu = gpu; + return result; + }, + + /** + * A visual debug utility + * @param {GPU} gpu + * @param rgba + * @param width + * @param height + * @return {Object[]} + */ + splitRGBAToCanvases: (gpu, rgba, width, height) => { + const visualKernelR = gpu.createKernel(function(v) { + const pixel = v[this.thread.y][this.thread.x]; + this.color(pixel.r / 255, 0, 0, 255); + }, { + output: [width, height], + graphical: true, + argumentTypes: { v: 'Array2D(4)' } + }); + visualKernelR(rgba); + + const visualKernelG = gpu.createKernel(function(v) { + const pixel = v[this.thread.y][this.thread.x]; + this.color(0, pixel.g / 255, 0, 255); + }, { + output: [width, height], + graphical: true, + argumentTypes: { v: 'Array2D(4)' } + }); + visualKernelG(rgba); + + const visualKernelB = gpu.createKernel(function(v) { + const pixel = v[this.thread.y][this.thread.x]; + this.color(0, 0, pixel.b / 255, 255); + }, { + output: [width, height], + graphical: true, + argumentTypes: { v: 'Array2D(4)' } + }); + visualKernelB(rgba); + + const visualKernelA = gpu.createKernel(function(v) { + const pixel = v[this.thread.y][this.thread.x]; + this.color(255, 255, 255, pixel.a / 255); + }, { + output: [width, height], + graphical: true, + argumentTypes: { v: 'Array2D(4)' } + }); + visualKernelA(rgba); + return [ + visualKernelR.canvas, + visualKernelG.canvas, + visualKernelB.canvas, + visualKernelA.canvas, + ]; + }, + + getMinifySafeName: (fn) => { + try { + const ast = acorn.parse(`const value = ${fn.toString()}`); + const { init } = ast.body[0].declarations[0]; + return init.body.name || init.body.body[0].argument.name; + } catch (e) { + throw new Error('Unrecognized function type. Please use `() => yourFunctionVariableHere` or function() { return yourFunctionVariableHere; }'); + } + }, + sanitizeName: function(name) { + if (dollarSign.test(name)) { + name = name.replace(dollarSign, 'S_S'); + } + if (doubleUnderscore.test(name)) { + name = name.replace(doubleUnderscore, 'U_U'); + } else if (singleUnderscore.test(name)) { + name = name.replace(singleUnderscore, 'u_u'); + } + return name; + } +}; + +const dollarSign = /\$/; +const doubleUnderscore = /__/; +const singleUnderscore = /_/; + +const _systemEndianness = utils.getSystemEndianness(); + +module.exports = { + utils +}; +},{"./input":287,"./texture":290,"acorn":23}],292:[function(require,module,exports){ +(function (global){ +'use strict'; + +// compare and isBuffer 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 + * @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; +} +function isBuffer(b) { + if (global.Buffer && typeof global.Buffer.isBuffer === 'function') { + return global.Buffer.isBuffer(b); + } + return !!(b != null && b._isBuffer); +} + +// based on node assert, original notice: + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// 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. + +var util = require('util/'); +var hasOwn = Object.prototype.hasOwnProperty; +var pSlice = Array.prototype.slice; +var functionsHaveNames = (function () { + return function foo() {}.name === 'foo'; +}()); +function pToString (obj) { + return Object.prototype.toString.call(obj); +} +function isView(arrbuf) { + if (isBuffer(arrbuf)) { + return false; + } + if (typeof global.ArrayBuffer !== 'function') { + return false; + } + if (typeof ArrayBuffer.isView === 'function') { + return ArrayBuffer.isView(arrbuf); + } + if (!arrbuf) { + return false; + } + if (arrbuf instanceof DataView) { + return true; + } + if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { + return true; + } + return false; +} +// 1. 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; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({ message: message, +// actual: actual, +// expected: expected }) + +var regex = /\s*function\s+([^\(\s]*)\s*/; +// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js +function getName(func) { + if (!util.isFunction(func)) { + return; + } + if (functionsHaveNames) { + return func.name; + } + var str = func.toString(); + var match = str.match(regex); + return match && match[1]; +} +assert.AssertionError = function AssertionError(options) { + this.name = 'AssertionError'; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + if (options.message) { + this.message = options.message; + this.generatedMessage = false; + } else { + this.message = getMessage(this); + this.generatedMessage = true; + } + var stackStartFunction = options.stackStartFunction || fail; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } else { + // non v8 browsers so we can have a stacktrace + var err = new Error(); + if (err.stack) { + var out = err.stack; + + // try to strip useless frames + var fn_name = getName(stackStartFunction); + var idx = out.indexOf('\n' + fn_name); + if (idx >= 0) { + // once we have located the function frame + // we need to strip out everything before it (and its line) + var next_line = out.indexOf('\n', idx + 1); + out = out.substring(next_line + 1); + } + + this.stack = out; + } + } +}; + +// assert.AssertionError instanceof Error +util.inherits(assert.AssertionError, Error); + +function truncate(s, n) { + if (typeof s === 'string') { + return s.length < n ? s : s.slice(0, n); + } else { + return s; + } +} +function inspect(something) { + if (functionsHaveNames || !util.isFunction(something)) { + return util.inspect(something); + } + var rawname = getName(something); + var name = rawname ? ': ' + rawname : ''; + return '[Function' + name + ']'; +} +function getMessage(self) { + return truncate(inspect(self.actual), 128) + ' ' + + self.operator + ' ' + + truncate(inspect(self.expected), 128); +} + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. 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 fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, !!guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +function ok(value, message) { + if (!value) fail(value, true, message, '==', assert.ok); +} +assert.ok = ok; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, '==', assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, '!=', assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected, false)) { + fail(actual, expected, message, 'deepEqual', assert.deepEqual); + } +}; + +assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { + if (!_deepEqual(actual, expected, true)) { + fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual); + } +}; + +function _deepEqual(actual, expected, strict, memos) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + } else if (isBuffer(actual) && isBuffer(expected)) { + return compare(actual, expected) === 0; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (util.isDate(actual) && util.isDate(expected)) { + return actual.getTime() === expected.getTime(); + + // 7.3 If the expected value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object with the same source and + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). + } else if (util.isRegExp(actual) && util.isRegExp(expected)) { + return actual.source === expected.source && + actual.global === expected.global && + actual.multiline === expected.multiline && + actual.lastIndex === expected.lastIndex && + actual.ignoreCase === expected.ignoreCase; + + // 7.4. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if ((actual === null || typeof actual !== 'object') && + (expected === null || typeof expected !== 'object')) { + return strict ? actual === expected : actual == expected; + + // If both values are instances of typed arrays, wrap their underlying + // ArrayBuffers in a Buffer each to increase performance + // This optimization requires the arrays to have the same type as checked by + // Object.prototype.toString (aka pToString). Never perform binary + // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their + // bit patterns are not identical. + } else if (isView(actual) && isView(expected) && + pToString(actual) === pToString(expected) && + !(actual instanceof Float32Array || + actual instanceof Float64Array)) { + return compare(new Uint8Array(actual.buffer), + new Uint8Array(expected.buffer)) === 0; + + // 7.5 For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else if (isBuffer(actual) !== isBuffer(expected)) { + return false; + } else { + memos = memos || {actual: [], expected: []}; + + var actualIndex = memos.actual.indexOf(actual); + if (actualIndex !== -1) { + if (actualIndex === memos.expected.indexOf(expected)) { + return true; + } + } + + memos.actual.push(actual); + memos.expected.push(expected); + + return objEquiv(actual, expected, strict, memos); + } +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b, strict, actualVisitedObjects) { + if (a === null || a === undefined || b === null || b === undefined) + return false; + // if one is a primitive, the other must be same + if (util.isPrimitive(a) || util.isPrimitive(b)) + return a === b; + if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) + return false; + var aIsArgs = isArguments(a); + var bIsArgs = isArguments(b); + if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) + return false; + if (aIsArgs) { + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b, strict); + } + var ka = objectKeys(a); + var kb = objectKeys(b); + var key, i; + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length !== kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] !== kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) + return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected, false)) { + fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); + } +}; + +assert.notDeepStrictEqual = notDeepStrictEqual; +function notDeepStrictEqual(actual, expected, message) { + if (_deepEqual(actual, expected, true)) { + fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual); + } +} + + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, '===', assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as +// determined by !==. assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, '!==', assert.notStrictEqual); + } +}; + +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } + + if (Object.prototype.toString.call(expected) == '[object RegExp]') { + return expected.test(actual); + } + + try { + if (actual instanceof expected) { + return true; + } + } catch (e) { + // Ignore. The instanceof check doesn't work for arrow functions. + } + + if (Error.isPrototypeOf(expected)) { + return false; + } + + return expected.call({}, actual) === true; +} + +function _tryBlock(block) { + var error; + try { + block(); + } catch (e) { + error = e; + } + return error; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (typeof block !== 'function') { + throw new TypeError('"block" argument must be a function'); + } + + if (typeof expected === 'string') { + message = expected; + expected = null; + } + + actual = _tryBlock(block); + + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail(actual, expected, 'Missing expected exception' + message); + } + + var userProvidedMessage = typeof message === 'string'; + var isUnwantedException = !shouldThrow && util.isError(actual); + var isUnexpectedException = !shouldThrow && actual && !expected; + + if ((isUnwantedException && + userProvidedMessage && + expectedException(actual, expected)) || + isUnexpectedException) { + fail(actual, expected, 'Got unwanted exception' + message); + } + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; + } +} + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws(true, block, error, message); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { + _throws(false, block, error, message); +}; + +assert.ifError = function(err) { if (err) throw err; }; + +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + if (hasOwn.call(obj, key)) keys.push(key); + } + return keys; +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"util/":295}],293:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, 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) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],294:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],295:[function(require,module,exports){ +(function (process,global){ +// 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 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) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + 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 debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + 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()`. +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; + +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; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = 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 = require('./support/isBuffer'); + +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 = require('inherits'); + +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); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":294,"_process":437,"inherits":293}],296:[function(require,module,exports){ +(function (process,Buffer){ +'use strict'; +/* eslint camelcase: "off" */ + +var assert = require('assert'); + +var Zstream = require('pako/lib/zlib/zstream'); +var zlib_deflate = require('pako/lib/zlib/deflate.js'); +var zlib_inflate = require('pako/lib/zlib/inflate.js'); +var constants = require('pako/lib/zlib/constants'); + +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; +}).call(this,require('_process'),require("buffer").Buffer) +},{"_process":437,"assert":292,"buffer":299,"pako/lib/zlib/constants":304,"pako/lib/zlib/deflate.js":306,"pako/lib/zlib/inflate.js":308,"pako/lib/zlib/zstream":312}],297:[function(require,module,exports){ +(function (process){ +'use strict'; + +var Buffer = require('buffer').Buffer; +var Transform = require('stream').Transform; +var binding = require('./binding'); +var util = require('util'); +var assert = require('assert').ok; +var kMaxLength = require('buffer').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); +}).call(this,require('_process')) +},{"./binding":296,"_process":437,"assert":292,"buffer":299,"stream":503,"util":523}],298:[function(require,module,exports){ +arguments[4][35][0].apply(exports,arguments) +},{"dup":35}],299:[function(require,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = require('base64-js') +var ieee754 = require('ieee754') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +var 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 { + var arr = new Uint8Array(1) + arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} + return arr.foo() === 42 + } catch (e) { + return false + } +} + +function createBuffer (length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('Invalid typed array length') + } + // Return an augmented `Uint8Array` instance + var buf = new Uint8Array(length) + buf.__proto__ = 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 Error( + 'If encoding is specified then the first argument must be a string' + ) + } + return allocUnsafe(arg) + } + return from(arg, encodingOrOffset, length) +} + +// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 +if (typeof Symbol !== 'undefined' && Symbol.species && + Buffer[Symbol.species] === Buffer) { + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true, + enumerable: false, + writable: false + }) +} + +Buffer.poolSize = 8192 // not used by this implementation + +function from (value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('"value" argument must not be a number') + } + + if (isArrayBuffer(value)) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + + return fromObject(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 +Buffer.prototype.__proto__ = Uint8Array.prototype +Buffer.__proto__ = Uint8Array + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be a number') + } else if (size < 0) { + throw new RangeError('"size" argument must not be negative') + } +} + +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 interpretted 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('"encoding" must be a valid string encoding') + } + + var length = byteLength(string, encoding) | 0 + var buf = createBuffer(length) + + var 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) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + var buf = createBuffer(length) + for (var i = 0; i < length; i += 1) { + buf[i] = array[i] & 255 + } + return buf +} + +function fromArrayBuffer (array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('\'offset\' is out of bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('\'length\' is out of bounds') + } + + var 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 + buf.__proto__ = Buffer.prototype + return buf +} + +function fromObject (obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + var buf = createBuffer(len) + + if (buf.length === 0) { + return buf + } + + obj.copy(buf, 0, 0, len) + return buf + } + + if (obj) { + if (isArrayBufferView(obj) || 'length' in obj) { + 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) + } + } + + throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') +} + +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 +} + +Buffer.compare = function compare (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError('Arguments must be Buffers') + } + + 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 +} + +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) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (isArrayBufferView(string) || isArrayBuffer(string)) { + return string.byteLength + } + if (typeof string !== 'string') { + string = '' + string + } + + var len = string.length + if (len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + case undefined: + 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 utf8ToBytes(string).length // assume utf8 + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var 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 coersion 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) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var 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 () { + var length = this.length + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +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 () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) str += ' ... ' + } + return '' +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (!Buffer.isBuffer(target)) { + throw new TypeError('Argument must be a Buffer') + } + + 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 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var 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) { + var indexSize = 1 + var arrLength = arr.length + var 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) + } + } + + var i + if (dir) { + var 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--) { + var found = true + for (var 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 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var 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 latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, 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' + ) + } + + var 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' + + var 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': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(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) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var 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 +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var 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". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var 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 + + var newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + newBuf.__proto__ = 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 = function readUIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +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 = function readUInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +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 = 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.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var 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) + + var i = byteLength + var mul = 1 + var 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) + var 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) + var 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.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 = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +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 = 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 = 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 = 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 = 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 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var 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) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var 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 +} + +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 (!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('sourceStart out of bounds') + 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 + } + + var len = end - start + var i + + if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else if (len < 1000) { + // ascending copy from start + for (i = 0; i < len; ++i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, start + len), + 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 (val.length === 1) { + var code = val.charCodeAt(0) + if (code < 256) { + val = code + } + } + 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) + } + } else if (typeof val === 'number') { + val = val & 255 + } + + // 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 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : new Buffer(val, encoding) + var len = bytes.length + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g + +function base64clean (str) { + // 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 toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var 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) { + var byteArray = [] + for (var 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) { + var c, hi, lo + var byteArray = [] + for (var 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) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +// ArrayBuffers from another context (i.e. an iframe) do not pass the `instanceof` check +// but they should be treated as valid. See: https://github.com/feross/buffer/issues/166 +function isArrayBuffer (obj) { + return obj instanceof ArrayBuffer || + (obj != null && obj.constructor != null && obj.constructor.name === 'ArrayBuffer' && + typeof obj.byteLength === 'number') +} + +// Node 0.10 supports `ArrayBuffer` but lacks `ArrayBuffer.isView` +function isArrayBufferView (obj) { + return (typeof ArrayBuffer.isView === 'function') && ArrayBuffer.isView(obj) +} + +function numberIsNaN (obj) { + return obj !== obj // eslint-disable-line no-self-compare +} + +},{"base64-js":28,"ieee754":317}],300:[function(require,module,exports){ +// 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 objectCreate = Object.create || objectCreatePolyfill +var objectKeys = Object.keys || objectKeysPolyfill +var bind = Function.prototype.bind || functionBindPolyfill + +function EventEmitter() { + if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) { + this._events = objectCreate(null); + this._eventsCount = 0; + } + + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +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; + +var hasDefineProperty; +try { + var o = {}; + if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 }); + hasDefineProperty = o.x === 0; +} catch (err) { hasDefineProperty = false } +if (hasDefineProperty) { + Object.defineProperty(EventEmitter, 'defaultMaxListeners', { + enumerable: true, + get: function() { + return defaultMaxListeners; + }, + set: function(arg) { + // check whether the input is a positive number (whose value is zero or + // greater and not a NaN). + if (typeof arg !== 'number' || arg < 0 || arg !== arg) + throw new TypeError('"defaultMaxListeners" must be a positive number'); + defaultMaxListeners = arg; + } + }); +} else { + EventEmitter.defaultMaxListeners = defaultMaxListeners; +} + +// 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 || isNaN(n)) + throw new TypeError('"n" argument must be a positive number'); + 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); +}; + +// These standalone emit* functions are used to optimize calling of event +// handlers for fast cases because emit() itself often has a variable number of +// arguments and can be deoptimized because of that. These functions always have +// the same number of arguments and thus do not get deoptimized, so the code +// inside them can execute faster. +function emitNone(handler, isFn, self) { + if (isFn) + handler.call(self); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self); + } +} +function emitOne(handler, isFn, self, arg1) { + if (isFn) + handler.call(self, arg1); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1); + } +} +function emitTwo(handler, isFn, self, arg1, arg2) { + if (isFn) + handler.call(self, arg1, arg2); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1, arg2); + } +} +function emitThree(handler, isFn, self, arg1, arg2, arg3) { + if (isFn) + handler.call(self, arg1, arg2, arg3); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1, arg2, arg3); + } +} + +function emitMany(handler, isFn, self, args) { + if (isFn) + handler.apply(self, args); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].apply(self, args); + } +} + +EventEmitter.prototype.emit = function emit(type) { + var er, handler, len, args, i, events; + var doError = (type === 'error'); + + events = this._events; + if (events) + doError = (doError && events.error == null); + else if (!doError) + return false; + + // If there is no 'error' event listener then throw. + if (doError) { + if (arguments.length > 1) + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Unhandled "error" event. (' + er + ')'); + err.context = er; + throw err; + } + return false; + } + + handler = events[type]; + + if (!handler) + return false; + + var isFn = typeof handler === 'function'; + len = arguments.length; + switch (len) { + // fast cases + case 1: + emitNone(handler, isFn, this); + break; + case 2: + emitOne(handler, isFn, this, arguments[1]); + break; + case 3: + emitTwo(handler, isFn, this, arguments[1], arguments[2]); + break; + case 4: + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); + break; + // slower + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + emitMany(handler, isFn, this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = target._events; + if (!events) { + events = target._events = objectCreate(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) { + 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) { + // 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]; + } else { + // If we've already got an array, just append. + if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + } + + // Check for listener leak + if (!existing.warned) { + m = $getMaxListeners(target); + if (m && m > 0 && existing.length > m) { + existing.warned = true; + 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; + if (typeof console === 'object' && console.warn) { + console.warn('%s: %s', w.name, w.message); + } + } + } + } + + 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; + switch (arguments.length) { + case 0: + return this.listener.call(this.target); + case 1: + return this.listener.call(this.target, arguments[0]); + case 2: + return this.listener.call(this.target, arguments[0], arguments[1]); + case 3: + return this.listener.call(this.target, arguments[0], arguments[1], + arguments[2]); + default: + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) + args[i] = arguments[i]; + this.listener.apply(this.target, args); + } + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = bind.call(onceWrapper, state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + 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; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = this._events; + if (!events) + return this; + + list = events[type]; + if (!list) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = objectCreate(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) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (!events) + return this; + + // not listening for removeListener, no need to emit + if (!events.removeListener) { + if (arguments.length === 0) { + this._events = objectCreate(null); + this._eventsCount = 0; + } else if (events[type]) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = objectKeys(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 = objectCreate(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners) { + // 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) + return []; + + var evlistener = events[type]; + if (!evlistener) + 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) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; +}; + +// About 1.5x faster than the two-arg version of Array#splice(). +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) + list[i] = list[k]; + list.pop(); +} + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +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 objectCreatePolyfill(proto) { + var F = function() {}; + F.prototype = proto; + return new F; +} +function objectKeysPolyfill(obj) { + var keys = []; + for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { + keys.push(k); + } + return k; +} +function functionBindPolyfill(context) { + var fn = this; + return function () { + return fn.apply(context, arguments); + }; +} + +},{}],301:[function(require,module,exports){ +exports.endianness = function () { return 'LE' }; + +exports.hostname = function () { + if (typeof location !== 'undefined') { + return location.hostname + } + else return ''; +}; + +exports.loadavg = function () { return [] }; + +exports.uptime = function () { return 0 }; + +exports.freemem = function () { + return Number.MAX_VALUE; +}; + +exports.totalmem = function () { + return Number.MAX_VALUE; +}; + +exports.cpus = function () { return [] }; + +exports.type = function () { return 'Browser' }; + +exports.release = function () { + if (typeof navigator !== 'undefined') { + return navigator.appVersion; + } + return ''; +}; + +exports.networkInterfaces += exports.getNetworkInterfaces += function () { return {} }; + +exports.arch = function () { return 'javascript' }; + +exports.platform = function () { return 'browser' }; + +exports.tmpdir = exports.tmpDir = function () { + return '/tmp'; +}; + +exports.EOL = '\n'; + +exports.homedir = function () { + return '/' +}; + +},{}],302:[function(require,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); + +},{}],303:[function(require,module,exports){ +'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; + +},{}],304:[function(require,module,exports){ +'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 +}; + +},{}],305:[function(require,module,exports){ +'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; + +},{}],306:[function(require,module,exports){ +'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 = require('../utils/common'); +var trees = require('./trees'); +var adler32 = require('./adler32'); +var crc32 = require('./crc32'); +var msg = require('./messages'); + +/* 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; +*/ + +},{"../utils/common":302,"./adler32":303,"./crc32":305,"./messages":310,"./trees":311}],307:[function(require,module,exports){ +'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; +}; + +},{}],308:[function(require,module,exports){ +'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 = require('../utils/common'); +var adler32 = require('./adler32'); +var crc32 = require('./crc32'); +var inflate_fast = require('./inffast'); +var inflate_table = require('./inftrees'); + +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; +*/ + +},{"../utils/common":302,"./adler32":303,"./crc32":305,"./inffast":307,"./inftrees":309}],309:[function(require,module,exports){ +'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 = require('../utils/common'); + +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; +}; + +},{"../utils/common":302}],310:[function(require,module,exports){ +'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) */ +}; + +},{}],311:[function(require,module,exports){ +'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 = require('../utils/common'); + +/* 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< 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; + +},{"../utils/common":302}],312:[function(require,module,exports){ +'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; + +},{}],313:[function(require,module,exports){ +"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SIGNALS=void 0; + +const SIGNALS=[ +{ +name:"SIGHUP", +number:1, +action:"terminate", +description:"Terminal closed", +standard:"posix"}, + +{ +name:"SIGINT", +number:2, +action:"terminate", +description:"User interruption with CTRL-C", +standard:"ansi"}, + +{ +name:"SIGQUIT", +number:3, +action:"core", +description:"User interruption with CTRL-\\", +standard:"posix"}, + +{ +name:"SIGILL", +number:4, +action:"core", +description:"Invalid machine instruction", +standard:"ansi"}, + +{ +name:"SIGTRAP", +number:5, +action:"core", +description:"Debugger breakpoint", +standard:"posix"}, + +{ +name:"SIGABRT", +number:6, +action:"core", +description:"Aborted", +standard:"ansi"}, + +{ +name:"SIGIOT", +number:6, +action:"core", +description:"Aborted", +standard:"bsd"}, + +{ +name:"SIGBUS", +number:7, +action:"core", +description: +"Bus error due to misaligned, non-existing address or paging error", +standard:"bsd"}, + +{ +name:"SIGEMT", +number:7, +action:"terminate", +description:"Command should be emulated but is not implemented", +standard:"other"}, + +{ +name:"SIGFPE", +number:8, +action:"core", +description:"Floating point arithmetic error", +standard:"ansi"}, + +{ +name:"SIGKILL", +number:9, +action:"terminate", +description:"Forced termination", +standard:"posix", +forced:true}, + +{ +name:"SIGUSR1", +number:10, +action:"terminate", +description:"Application-specific signal", +standard:"posix"}, + +{ +name:"SIGSEGV", +number:11, +action:"core", +description:"Segmentation fault", +standard:"ansi"}, + +{ +name:"SIGUSR2", +number:12, +action:"terminate", +description:"Application-specific signal", +standard:"posix"}, + +{ +name:"SIGPIPE", +number:13, +action:"terminate", +description:"Broken pipe or socket", +standard:"posix"}, + +{ +name:"SIGALRM", +number:14, +action:"terminate", +description:"Timeout or timer", +standard:"posix"}, + +{ +name:"SIGTERM", +number:15, +action:"terminate", +description:"Termination", +standard:"ansi"}, + +{ +name:"SIGSTKFLT", +number:16, +action:"terminate", +description:"Stack is empty or overflowed", +standard:"other"}, + +{ +name:"SIGCHLD", +number:17, +action:"ignore", +description:"Child process terminated, paused or unpaused", +standard:"posix"}, + +{ +name:"SIGCLD", +number:17, +action:"ignore", +description:"Child process terminated, paused or unpaused", +standard:"other"}, + +{ +name:"SIGCONT", +number:18, +action:"unpause", +description:"Unpaused", +standard:"posix", +forced:true}, + +{ +name:"SIGSTOP", +number:19, +action:"pause", +description:"Paused", +standard:"posix", +forced:true}, + +{ +name:"SIGTSTP", +number:20, +action:"pause", +description:"Paused using CTRL-Z or \"suspend\"", +standard:"posix"}, + +{ +name:"SIGTTIN", +number:21, +action:"pause", +description:"Background process cannot read terminal input", +standard:"posix"}, + +{ +name:"SIGBREAK", +number:21, +action:"terminate", +description:"User interruption with CTRL-BREAK", +standard:"other"}, + +{ +name:"SIGTTOU", +number:22, +action:"pause", +description:"Background process cannot write to terminal output", +standard:"posix"}, + +{ +name:"SIGURG", +number:23, +action:"ignore", +description:"Socket received out-of-band data", +standard:"bsd"}, + +{ +name:"SIGXCPU", +number:24, +action:"core", +description:"Process timed out", +standard:"bsd"}, + +{ +name:"SIGXFSZ", +number:25, +action:"core", +description:"File too big", +standard:"bsd"}, + +{ +name:"SIGVTALRM", +number:26, +action:"terminate", +description:"Timeout or timer", +standard:"bsd"}, + +{ +name:"SIGPROF", +number:27, +action:"terminate", +description:"Timeout or timer", +standard:"bsd"}, + +{ +name:"SIGWINCH", +number:28, +action:"ignore", +description:"Terminal window size changed", +standard:"bsd"}, + +{ +name:"SIGIO", +number:29, +action:"terminate", +description:"I/O is available", +standard:"other"}, + +{ +name:"SIGPOLL", +number:29, +action:"terminate", +description:"Watched event", +standard:"other"}, + +{ +name:"SIGINFO", +number:29, +action:"ignore", +description:"Request for process information", +standard:"other"}, + +{ +name:"SIGPWR", +number:30, +action:"terminate", +description:"Device running out of power", +standard:"systemv"}, + +{ +name:"SIGSYS", +number:31, +action:"core", +description:"Invalid system call", +standard:"other"}, + +{ +name:"SIGUNUSED", +number:31, +action:"terminate", +description:"Invalid system call", +standard:"other"}];exports.SIGNALS=SIGNALS; + +},{}],314:[function(require,module,exports){ +"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.signalsByNumber=exports.signalsByName=void 0;var _os=require("os"); + +var _signals=require("./signals.js"); +var _realtime=require("./realtime.js"); + + + +const getSignalsByName=function(){ +const signals=(0,_signals.getSignals)(); +return signals.reduce(getSignalByName,{}); +}; + +const getSignalByName=function( +signalByNameMemo, +{name,number,description,supported,action,forced,standard}) +{ +return{ +...signalByNameMemo, +[name]:{name,number,description,supported,action,forced,standard}}; + +}; + +const signalsByName=getSignalsByName();exports.signalsByName=signalsByName; + + + + +const getSignalsByNumber=function(){ +const signals=(0,_signals.getSignals)(); +const length=_realtime.SIGRTMAX+1; +const signalsA=Array.from({length},(value,number)=> +getSignalByNumber(number,signals)); + +return Object.assign({},...signalsA); +}; + +const getSignalByNumber=function(number,signals){ +const signal=findSignalByNumber(number,signals); + +if(signal===undefined){ +return{}; +} + +const{name,description,supported,action,forced,standard}=signal; +return{ +[number]:{ +name, +number, +description, +supported, +action, +forced, +standard}}; + + +}; + + + +const findSignalByNumber=function(number,signals){ +const signal=signals.find(({name})=>_os.constants.signals[name]===number); + +if(signal!==undefined){ +return signal; +} + +return signals.find(signalA=>signalA.number===number); +}; + +const signalsByNumber=getSignalsByNumber();exports.signalsByNumber=signalsByNumber; + +},{"./realtime.js":315,"./signals.js":316,"os":301}],315:[function(require,module,exports){ +"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SIGRTMAX=exports.getRealtimeSignals=void 0; +const getRealtimeSignals=function(){ +const length=SIGRTMAX-SIGRTMIN+1; +return Array.from({length},getRealtimeSignal); +};exports.getRealtimeSignals=getRealtimeSignals; + +const getRealtimeSignal=function(value,index){ +return{ +name:`SIGRT${index+1}`, +number:SIGRTMIN+index, +action:"terminate", +description:"Application-specific signal (realtime)", +standard:"posix"}; + +}; + +const SIGRTMIN=34; +const SIGRTMAX=64;exports.SIGRTMAX=SIGRTMAX; + +},{}],316:[function(require,module,exports){ +"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getSignals=void 0;var _os=require("os"); + +var _core=require("./core.js"); +var _realtime=require("./realtime.js"); + + + +const getSignals=function(){ +const realtimeSignals=(0,_realtime.getRealtimeSignals)(); +const signals=[..._core.SIGNALS,...realtimeSignals].map(normalizeSignal); +return signals; +};exports.getSignals=getSignals; + + + + + + + +const normalizeSignal=function({ +name, +number:defaultNumber, +description, +action, +forced=false, +standard}) +{ +const{ +signals:{[name]:constantSignal}}= +_os.constants; +const supported=constantSignal!==undefined; +const number=supported?constantSignal:defaultNumber; +return{name,number,description,supported,action,forced,standard}; +}; + +},{"./core.js":313,"./realtime.js":315,"os":301}],317:[function(require,module,exports){ +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 +} + +},{}],318:[function(require,module,exports){ +/** + * Copyright (c) 2015 Guyon Roche + * + * 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. + * + */ +"use strict"; + +var _ = require("underscore"); + +var main = module.exports = { + Bitmap: require("./lib/bitmap") +}; + +_.extend(main, require("./lib/enums")); + +},{"./lib/bitmap":319,"./lib/enums":320,"underscore":516}],319:[function(require,module,exports){ +(function (Buffer){ +/** + * Copyright (c) 2015 Guyon Roche + * + * 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. + * + */ +"use strict"; + +var fs = require("fs"); +var _ = require("underscore"); +var Promise = require("bluebird"); +var jpeg = require("jpeg-js"); +//var png = require("png-js"); +var PNG = require("node-png").PNG; + +var Enums = require("./enums"); +var Utils = require("./utils"); +var Resize = require("./resize"); +//var Graphics = require("./graphics"); + +// default pad colour +var transparentBlack = { + r: 0, g: 0, b: 0, a: 0 +}; + +var Bitmap = module.exports = function(options) { + if (options) { + if (options instanceof Bitmap) { + this._data = { + data: new Buffer(options.data.data), + width: options.width, + height: options.height + }; + } else if (options.data) { + // attach to supplied data + this._data = options; + } else if (options.width && options.height) { + // construct new bitmap + this._data = { + data: new Buffer(4 * options.width * options.height), + width: options.width, + height: options.height + }; + + // optional colour + if (options.color) { + this._fill(options.color); + } + } + } +}; + +Bitmap.prototype = { + get width() { + return this._data.width; + }, + get height() { + return this._data.height; + }, + //get graphics() { + // if (!this._graphics) { + // this._graphics = new Graphics(this); + // } + // return this._graphics; + //}, + + attach: function(data) { + var prev = this._data; + this._data = data; + return prev; + }, + detach: function() { + var data = this._data; + delete this._data; + return data; + }, + + _deduceFileType: function(filename) { + if (!filename) { + throw new Error("Can't determine image type"); + } + switch (filename.substr(-4).toLowerCase()) { + case ".jpg": + return Enums.ImageType.JPG; + case ".png": + return Enums.ImageType.PNG; + } + if (filename.substr(-5).toLowerCase() == ".jpeg") { + return Enums.ImageType.JPG; + } + throw new Error("Can't recognise image type: " + filename); + }, + + _readStream: function(stream) { + var self = this; + var deferred = Promise.defer(); + + var chunks = []; + stream.on('data', function(chunk) { + chunks.push(chunk); + }); + stream.on('end', function() { + var data = Buffer.concat(chunks); + deferred.resolve(data); + }); + stream.on('error', function(error) { + deferred.reject(error); + }); + + return deferred.promise; + }, + _readPNG: function(stream) { + var deferred = Promise.defer(); + + var png = new PNG({filterType: 4}); + png.on('parsed', function() { + deferred.resolve(png); + }); + png.on('error', function(error) { + deferred.rejecyt(error); + }); + stream.pipe(png); + + return deferred.promise; + }, + _parseOptions: function(options, filename) { + options = options || {}; + if (typeof options === "number") { + options = { type: options }; + } + options.type = options.type || this._deduceFileType(filename); + return options; + }, + read: function(stream, options) { + var self = this; + options = this._parseOptions(options); + + switch(options.type) { + case Enums.ImageType.JPG: + return this._readStream(stream) + .then(function(data) { + self._data = jpeg.decode(data); + }); + case Enums.ImageType.PNG: + return this._readPNG(stream) + .then(function(png) { + self._data = { + data: png.data, + width: png.width, + height: png.height + }; + }); + default: + return Promise.reject(new Error("Not supported: ImageType " + options.type)); + } + }, + readFile: function(filename, options) { + var self = this; + return Utils.fs.exists(filename) + .then(function(exists) { + if (exists) { + options = self._parseOptions(options, filename); + var stream = fs.createReadStream(filename); + return self.read(stream, options); + } else { + throw new Error("File Not Found: " + filename); + } + }); + }, + + write: function(stream, options) { + options = this._parseOptions(options); + var deferred = Promise.defer(); + try { + stream.on('finish', function() { + deferred.resolve(); + }); + stream.on('error', function(error) { + deferred.reject(error); + }); + + switch(options.type) { + case Enums.ImageType.JPG: + var buffer = jpeg.encode(this._data, options.quality || 90).data; + stream.write(buffer); + stream.end(); + break; + case Enums.ImageType.PNG: + var png = new PNG(); + png.width = this.width; + png.height = this.height; + png.data = this._data.data; + png.on('end', function() { + deferred.resolve(); + }); + png.on('error', function(error) { + deferred.reject(error); + }); + png.pack().pipe(stream); + break; + default: + throw new Error("Not supported: ImageType " + options.type); + } + } + catch(ex) { + deferred.reject(ex); + } + return deferred.promise; + }, + writeFile: function(filename, options) { + options = this._parseOptions(options, filename); + var stream = fs.createWriteStream(filename); + return this.write(stream, options); + }, + + clone: function() { + return new Bitmap({ + width: this.width, + height: this.height, + data: new Buffer(this._data.data) + }); + }, + + setPixel: function(x,y, r,g,b,a) { + if (g === undefined) { + var color = r; + r = color.r; + g = color.g; + b = color.b; + a = color.a; + } + if (a === undefined) a = 255; + var pos = (y * this.width + x) * 4; + var buffer = this._data.data; + buffer[pos++] = r; + buffer[pos++] = g; + buffer[pos++] = b; + buffer[pos++] = a; + }, + getPixel: function(x,y, color) { + var pos = (y * this.width + x) * 4; + color = color || {}; + var buffer = this._data.data; + color.r = buffer[pos++]; + color.g = buffer[pos++]; + color.b = buffer[pos++]; + color.a = buffer[pos++]; + return color; + }, + + negative: function() { + var that = new Bitmap({width: this.width, height: this.height}); + var n = this.width * this.height; + + var src = this._data.data; + var dst = that._data.data; + var srcPos = 0; + var dstPos = 0; + for (var i = 0; i < n; i++) { + dst[dstPos++] = 255 - src[srcPos++]; + dst[dstPos++] = 255 - src[srcPos++]; + dst[dstPos++] = 255 - src[srcPos++]; + dst[dstPos++] = src[srcPos++]; + } + return that; + }, + + resize: function(options) { + var that = new Bitmap(options); + var temp; + switch (options.fit) { + case "pad": // fit all of src in dst with aspect ratio preserved. + var padColor = options.padColor || transparentBlack; + var srcAr = this.width / this.height; + var w2 = Math.round(srcAr * that.height); + var h2 = Math.round(that.width / srcAr); + var wMargin = 0; + var hMargin = 0; + if (w2 < that.width) { + // pad sides + temp = new Bitmap({width: w2, height: that.height}); + wMargin = (that.width - w2) / 2; + that._fill(padColor, 0, 0, Math.floor(wMargin), that.height); + that._fill(padColor, that.width - Math.ceil(wMargin), 0, Math.ceil(wMargin), that.height); + + Resize[options.algorithm](this, temp, options); + that._blt(temp, {left: Math.floor(wMargin), top: Math.floor(hMargin)}); + } else if (h2 < that.height) { + // pad top & bottom + temp = new Bitmap({width: that.width, height: h2}); + hMargin = (that.height - h2) / 2; + that._fill(padColor, 0, 0, that.width, Math.floor(hMargin)); + that._fill(padColor, 0, that.height - Math.ceil(hMargin), that.width, Math.ceil(hMargin)); + + Resize[options.algorithm](this, temp, options); + that._blt(temp, {left: Math.floor(wMargin), top: Math.floor(hMargin)}); + } else { + // stretch straight into that + Resize[options.algorithm](this, that, options); + } + break; + case "crop": // crop original to fit in dst with aspect ratio preserved + var gravity = options.gravity || {x: 0.5, y: 0.5}; + var dstAr = that.width / that.height; + var w2 = Math.round(dstAr * this.height); + var h2 = Math.round(this.width / dstAr); + if (w2 < this.width) { + // crop src width + var dw = this.width - w2; + temp = this.crop({left: Math.round(gravity.x * dw), top: 0, width: w2, height: this.height}); + } else if (h2 < this.height) { + // crop src height + var dh = this.height - h2; + temp = this.crop({left: 0, top: Math.round(gravity.y * dh), width: this.width, height: h2}); + } else { + temp = this; + } + Resize[options.algorithm](temp, that, options); + break; + case "stretch": + default: + Resize[options.algorithm](this, that, options); + break; + } + + return that; + }, + + rotate: function(options) { + // TODO: crop, user supplied dst width, height + + // options.degrees || options.radians; + // options.fit = ['pad','crop','same'] + // options.padColor + var radians = options.radians !== undefined ? options.radians : 3.141592653589793 * options.degrees / 180; + if (radians < 0.000000001) { + return new Bitmap(this); + } + //console.log("radians=" + radians); + + var rotators = { + forward: { + cos: Math.cos(radians), + sin: Math.sin(radians) + }, + backward: { + cos: Math.cos(-radians), + sin: Math.sin(-radians) + } + } + //console.log("cos=" + cos + ", sin=" + sin) + + var srcWidth = this.width; + var srcHeight = this.height; + var srcWidthHalf = srcWidth / 2; + var srcHeightHalf = srcHeight / 2; + + var padColor = options.padColor || transparentBlack; + var padArray = [padColor.r, padColor.g, padColor.b, padColor.a]; + var rotate = function(point, rotator) { + // in-place rotation of point + var x = rotator.cos * point.x - rotator.sin * point.y; + var y = rotator.sin * point.x + rotator.cos * point.y; + point.x = x; + point.y = y; + return point; + }; + var cropToSource = function(point) { + var m = Math.abs(point.x/srcWidthHalf); + var n = Math.abs(point.y/srcHeightHalf); + return Math.max(m,n); + }; + + var dstWidth, dstHeight; + switch (options.fit) { + case 'custom': + dstWidth = options.width; + dstHeight = options.height; + break; + case 'pad': + // entire src fits in dst + var tl = rotate({x:-srcWidthHalf,y:srcHeightHalf}, rotators.forward); + var tr = rotate({x:srcWidthHalf,y:srcHeightHalf}, rotators.forward); + var bl = rotate({x:-srcWidthHalf,y:-srcHeightHalf}, rotators.forward); + var br = rotate({x:srcWidthHalf,y:-srcHeightHalf}, rotators.forward); + dstWidth = Math.round(Math.max(tl.x,tr.x,bl.x,br.x) - Math.min(tl.x,tr.x,bl.x,br.x)); + dstHeight = Math.round(Math.max(tl.y,tr.y,bl.y,br.y) - Math.min(tl.y,tr.y,bl.y,br.y)); + break; + case 'crop': + var tl = rotate({x:-srcWidthHalf,y:srcHeightHalf}, rotators.forward); + var tr = rotate({x:srcWidthHalf,y:srcHeightHalf}, rotators.forward); + var bl = rotate({x:-srcWidthHalf,y:-srcHeightHalf}, rotators.forward); + var br = rotate({x:srcWidthHalf,y:-srcHeightHalf}, rotators.forward); + var d = Math.max(cropToSource(tl), cropToSource(tr), cropToSource(bl), cropToSource(br)); + dstWidth = Math.floor(srcWidth / d); + dstHeight = Math.floor(srcHeight / d); + break; + case 'same': + default: + // dst is same size as src + dstWidth = srcWidth; + dstHeight = srcHeight; + break; + } + + var that = new Bitmap({width: dstWidth, height: dstHeight}); + + var srcBuf = this._data.data; + var dstBuf = that._data.data; + + // we will rotate the destination pixels back to the source and interpolate the colour + var srcCoord = {}; + var dstWidthHalf = dstWidth / 2; + var dstHeightHalf = dstHeight / 2; + var dstWidth4 = dstWidth * 4; + var srcWidth4 = srcWidth * 4; + + //console.log("src=[" + srcWidth + "," + srcHeight + "]") + //console.log("dst=[" + dstWidth + "," + dstHeight + "]") + for (var i = 0; i < dstHeight; i++) { + for (var j = 0; j < dstWidth; j++) { + // calculate src coords + srcCoord.x = j - dstWidthHalf; + srcCoord.y = dstHeightHalf - i; + //console.log("x=" + srcCoord.x + ", y=" + srcCoord.y); + rotate(srcCoord, rotators.backward); + //console.log(" ==> x=" + srcCoord.x + ", y=" + srcCoord.y); + + // srcX and SrcY are in src coords + var srcX = srcCoord.x + srcWidthHalf; + var srcY = srcHeightHalf - srcCoord.y; + //console.log("srcX=" + srcX + ", srcY=" + srcY); + + // now interpolate (bilinear! + var dstPos = (i * dstWidth + j) * 4; + //console.log("dstPos=" + dstPos) + if ((srcX > -1) && (srcX < srcWidth) && (srcY > -1) && (srcY < srcHeight)) { + var srcPosX = Math.floor(srcX); + var srcPosY = Math.floor(srcY); + var srcPos = (srcPosY * srcWidth + srcPosX) * 4; + for (var k = 0; k < 4; k++) { + var kSrcPos = srcPos + k; + var kPad = padArray[k]; + + var tl = ((srcX >= 0) && (srcY >= 0)) ? srcBuf[kSrcPos] : kPad; + var tr = ((srcX < srcWidth-1) && (srcY >= 0)) ? srcBuf[kSrcPos+4] : kPad; + var bl = ((srcX >= 0) && (srcY < srcHeight-1)) ? srcBuf[kSrcPos + srcWidth4] : kPad; + var br = ((srcX < srcWidth-1) && (srcY < srcHeight-1)) ? srcBuf[kSrcPos + srcWidth4 + 4] : kPad; + + var tx = srcX - srcPosX; + var ty = srcY - srcPosY; + + var t = (1-tx) * tl + tx * tr; + var b = (1-tx) * bl + tx * br; + dstBuf[dstPos++] = (1-ty) * t + ty * b; + } + } else { + dstBuf[dstPos++] = padColor.r; + dstBuf[dstPos++] = padColor.g; + dstBuf[dstPos++] = padColor.b; + dstBuf[dstPos++] = padColor.a; + } + } + } + return that; + }, + + crop: function(options) { + var t = options.top; + var l = options.left; + var w = options.width; + var h = options.height; + //console.log("Crop: l="+l + ", t="+t + ", w="+w + ", h="+h); + + var that = new Bitmap({width: w, height: h}); + + var srcBuf = this._data.data; + var dstBuf = that._data.data; + + var w4 = w * 4; + for (var i = 0; i < h; i++) { + var srcPos = ((i+t)*this.width + l) * 4; + var dstPos = i * w * 4; + srcBuf.copy(dstBuf, dstPos, srcPos, srcPos + w4); + } + return that; + }, + + blur: function(options) { + // todo: expand to own file with different blur algorithms + var that = new Bitmap({width: this.width, height: this.height}); + var w = this.width; + var h = this.height; + + var W = w-1; + var H = h-1; + + var V = w*4; // used for i offsets + + var src = this._data.data; + var dst = that._data.data; + for (var i = 0; i < h; i++) { + for (var j = 0; j < w; j++) { + for (var k = 0; k < 4; k++) { + var pos = (i*w + j) * 4 + k; + var t = src[pos -(i>0?V:0) - (j>0?4:0)] * 1 + // 1/16 + src[pos -(i>0?V:0) ] * 2 + // 2/16 + src[pos -(i>0?V:0) + (j0?4:0)] * 2 + // 2/16 + src[pos ] * 4 + // 4/16 + src[pos + (j0?4:0)] * 1 + // 1/16 + src[pos +(i + * + * 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. + * + */ +"use strict"; + +module.exports = { + ImageType: { + JPG: 1, + PNG: 2 + } +}; +},{}],321:[function(require,module,exports){ +(function (Buffer){ +/** + * Copyright (c) 2015 Guyon Roche + * + * 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. + * + */ +"use strict"; + +var _ = require("underscore"); +var Promise = require("bluebird"); + +module.exports = { + _writeFile: function(width, height, data, filename) { + // for debugging + + var Bitmap = require("./bitmap"); + var bmp = new Bitmap({ + width: width, height: height, + data: data + }); + bmp.writeFile(filename); + }, + + nearestNeighbor: function(src, dst, options) { + + var wSrc = src.width; + var hSrc = src.height; + //console.log("wSrc="+wSrc + ", hSrc="+hSrc); + + var wDst = dst.width; + var hDst = dst.height; + //console.log("wDst="+wDst + ", hDst="+hDst); + + var bufSrc = src._data.data; + var bufDst = dst._data.data; + + for (var i = 0; i < hDst; i++) { + for (var j = 0; j < wDst; j++) { + var posDst = (i * wDst + j) * 4; + + var iSrc = Math.round(i * hSrc / hDst); + var jSrc = Math.round(j * wSrc / wDst); + var posSrc = (iSrc * wSrc + jSrc) * 4; + + bufDst[posDst++] = bufSrc[posSrc++]; + bufDst[posDst++] = bufSrc[posSrc++]; + bufDst[posDst++] = bufSrc[posSrc++]; + bufDst[posDst++] = bufSrc[posSrc++]; + } + } + }, + bilinearInterpolation: function(src, dst, options) { + + var wSrc = src.width; + var hSrc = src.height; + //console.log("wSrc="+wSrc + ", hSrc="+hSrc); + + var wDst = dst.width; + var hDst = dst.height; + //console.log("wDst="+wDst + ", hDst="+hDst); + + var bufSrc = src._data.data; + var bufDst = dst._data.data; + + var interpolate = function(k, kMin, vMin, kMax, vMax) { + // special case - k is integer + if (kMin === kMax) { + return vMin; + } + + return Math.round((k - kMin) * vMax + (kMax - k) * vMin); + }; + var assign = function(pos, offset, x, xMin, xMax, y, yMin, yMax) { + var posMin = (yMin * wSrc + xMin) * 4 + offset; + var posMax = (yMin * wSrc + xMax) * 4 + offset; + var vMin = interpolate(x, xMin, bufSrc[posMin], xMax, bufSrc[posMax]); + + // special case, y is integer + if (yMax === yMin) { + bufDst[pos+offset] = vMin; + } else { + posMin = (yMax * wSrc + xMin) * 4 + offset; + posMax = (yMax * wSrc + xMax) * 4 + offset; + var vMax = interpolate(x, xMin, bufSrc[posMin], xMax, bufSrc[posMax]); + + bufDst[pos+offset] = interpolate(y, yMin, vMin, yMax, vMax); + } + } + + for (var i = 0; i < hDst; i++) { + for (var j = 0; j < wDst; j++) { + var posDst = (i * wDst + j) * 4; + + // x & y in src coordinates + var x = j * wSrc / wDst; + var xMin = Math.floor(x); + var xMax = Math.min(Math.ceil(x), wSrc-1); + + var y = i * hSrc / hDst; + var yMin = Math.floor(y); + var yMax = Math.min(Math.ceil(y), hSrc-1); + + assign(posDst, 0, x, xMin, xMax, y, yMin, yMax); + assign(posDst, 1, x, xMin, xMax, y, yMin, yMax); + assign(posDst, 2, x, xMin, xMax, y, yMin, yMax); + assign(posDst, 3, x, xMin, xMax, y, yMin, yMax); + } + } + }, + + _interpolate2D: function(src, dst, options, interpolate) { + + var bufSrc = src._data.data; + var bufDst = dst._data.data; + + var wSrc = src.width; + var hSrc = src.height; + //console.log("wSrc="+wSrc + ", hSrc="+hSrc + ", srcLen="+bufSrc.length); + + var wDst = dst.width; + var hDst = dst.height; + //console.log("wDst="+wDst + ", hDst="+hDst + ", dstLen="+bufDst.length); + + // when dst smaller than src/2, interpolate first to a multiple between 0.5 and 1.0 src, then sum squares + var wM = Math.max(1, Math.floor(wSrc / wDst)); + var wDst2 = wDst * wM; + var hM = Math.max(1, Math.floor(hSrc / hDst)); + var hDst2 = hDst * hM; + //console.log("wM="+wM + ", wDst2="+wDst2 + ", hM="+hM + ", hDst2="+hDst2); + + // =========================================================== + // Pass 1 - interpolate rows + // buf1 has width of dst2 and height of src + var buf1 = new Buffer(wDst2 * hSrc * 4); + for (var i = 0; i < hSrc; i++) { + for (var j = 0; j < wDst2; j++) { + // i in src coords, j in dst coords + + // calculate x in src coords + // this interpolation requires 4 sample points and the two inner ones must be real + // the outer points can be fudged for the edges. + // therefore (wSrc-1)/wDst2 + var x = j * (wSrc-1) / wDst2; + var xPos = Math.floor(x); + var t = x - xPos; + var srcPos = (i * wSrc + xPos) * 4; + + var buf1Pos = (i * wDst2 + j) * 4; + for (var k = 0; k < 4; k++) { + var kPos = srcPos + k; + var x0 = (xPos > 0) ? bufSrc[kPos - 4] : 2*bufSrc[kPos]-bufSrc[kPos+4]; + var x1 = bufSrc[kPos]; + var x2 = bufSrc[kPos + 4]; + var x3 = (xPos < wSrc - 2) ? bufSrc[kPos + 8] : 2*bufSrc[kPos + 4]-bufSrc[kPos]; + buf1[buf1Pos+k] = interpolate(x0,x1,x2,x3,t); + } + } + } + //this._writeFile(wDst2, hSrc, buf1, "out/buf1.jpg"); + + // =========================================================== + // Pass 2 - interpolate columns + // buf2 has width and height of dst2 + var buf2 = new Buffer(wDst2 * hDst2 * 4); + for (var i = 0; i < hDst2; i++) { + for (var j = 0; j < wDst2; j++) { + // i&j in dst2 coords + + // calculate y in buf1 coords + // this interpolation requires 4 sample points and the two inner ones must be real + // the outer points can be fudged for the edges. + // therefore (hSrc-1)/hDst2 + var y = i * (hSrc-1) / hDst2; + var yPos = Math.floor(y); + var t = y - yPos; + var buf1Pos = (yPos * wDst2 + j) * 4; + var buf2Pos = (i * wDst2 + j) * 4; + for (var k = 0; k < 4; k++) { + var kPos = buf1Pos + k; + var y0 = (yPos > 0) ? buf1[kPos - wDst2*4] : 2*buf1[kPos]-buf1[kPos + wDst2*4]; + var y1 = buf1[kPos]; + var y2 = buf1[kPos + wDst2*4]; + var y3 = (yPos < hSrc-2) ? buf1[kPos + wDst2*8] : 2*buf1[kPos + wDst2*4]-buf1[kPos]; + + buf2[buf2Pos + k] = interpolate(y0,y1,y2,y3,t); + } + } + } + //this._writeFile(wDst2, hDst2, buf2, "out/buf2.jpg"); + + // =========================================================== + // Pass 3 - scale to dst + var m = wM * hM; + if (m > 1) { + for (var i = 0; i < hDst; i++) { + for (var j = 0; j < wDst; j++) { + // i&j in dst bounded coords + var r = 0; + var g = 0; + var b = 0; + var a = 0; + for (var y = 0; y < hM; y++) { + var yPos = i * hM + y; + for (var x = 0; x < wM; x++) { + var xPos = j * wM + x; + var xyPos = (yPos * wDst2 + xPos) * 4; + r += buf2[xyPos]; + g += buf2[xyPos+1]; + b += buf2[xyPos+2]; + a += buf2[xyPos+3]; + } + } + + var pos = (i*wDst + j) * 4; + bufDst[pos] = Math.round(r / m); + bufDst[pos+1] = Math.round(g / m); + bufDst[pos+2] = Math.round(b / m); + bufDst[pos+3] = Math.round(a / m); + } + } + } else { + // replace dst buffer with buf2 + dst._data.data = buf2; + } + }, + + bicubicInterpolation: function(src, dst, options) { + var interpolateCubic = function(x0, x1, x2, x3, t) { + var a0 = x3 - x2 - x0 + x1; + var a1 = x0 - x1 - a0; + var a2 = x2 - x0; + var a3 = x1; + return Math.max(0,Math.min(255,(a0 * (t * t * t)) + (a1 * (t * t)) + (a2 * t) + (a3))); + } + return this._interpolate2D(src, dst, options, interpolateCubic); + }, + + hermiteInterpolation: function(src, dst, options) { + var interpolateHermite = function(x0, x1, x2, x3, t) + { + var c0 = x1; + var c1 = 0.5 * (x2 - x0); + var c2 = x0 - (2.5 * x1) + (2 * x2) - (0.5 * x3); + var c3 = (0.5 * (x3 - x0)) + (1.5 * (x1 - x2)); + return Math.max(0,Math.min(255,Math.round((((((c3 * t) + c2) * t) + c1) * t) + c0))); + } + return this._interpolate2D(src, dst, options, interpolateHermite); + }, + + bezierInterpolation: function(src, dst, options) { + // between 2 points y(n), y(n+1), use next points out, y(n-1), y(n+2) + // to predict control points (a & b) to be placed at n+0.5 + // ya(n) = y(n) + (y(n+1)-y(n-1))/4 + // yb(n) = y(n+1) - (y(n+2)-y(n))/4 + // then use std bezier to interpolate [n,n+1) + // y(n+t) = y(n)*(1-t)^3 + 3 * ya(n)*(1-t)^2*t + 3 * yb(n)*(1-t)*t^2 + y(n+1)*t^3 + // note the 3* factor for the two control points + // for edge cases, can choose: + // y(-1) = y(0) - 2*(y(1)-y(0)) + // y(w) = y(w-1) + 2*(y(w-1)-y(w-2)) + // but can go with y(-1) = y(0) and y(w) = y(w-1) + var interpolateBezier = function(x0, x1, x2, x3, t) { + // x1, x2 are the knots, use x0 and x3 to calculate control points + var cp1 = x1 + (x2-x0)/4; + var cp2 = x2 - (x3-x1)/4; + var nt = 1-t; + var c0 = x1 * nt * nt * nt; + var c1 = 3 * cp1 * nt * nt * t; + var c2 = 3 * cp2 * nt * t * t; + var c3 = x2 * t * t * t; + return Math.max(0,Math.min(255,Math.round(c0 + c1 + c2 + c3))); + } + return this._interpolate2D(src, dst, options, interpolateBezier); + } +} +}).call(this,require("buffer").Buffer) +},{"./bitmap":319,"bluebird":33,"buffer":299,"underscore":516}],322:[function(require,module,exports){ +/** + * Copyright (c) 2015 Guyon Roche + * + * 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. + * + */ +"use strict"; + +var fs = require("fs"); +var _ = require("underscore"); +var Promise = require("bluebird"); + + +var utils = module.exports = { + + // Promisification of fs + fs: { + exists: function(filename) { + var deferred = Promise.defer(); + fs.exists(filename, function(exists) { + deferred.resolve(exists); + }); + return deferred.promise; + } + } +} +},{"bluebird":33,"fs":298,"underscore":516}],323:[function(require,module,exports){ +var encode = require('./lib/encoder'), + decode = require('./lib/decoder'); + +module.exports = { + encode: encode, + decode: decode +}; + +},{"./lib/decoder":324,"./lib/encoder":325}],324:[function(require,module,exports){ +(function (Buffer){ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* + Copyright 2011 notmasteryet + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// - The JPEG specification can be found in the ITU CCITT Recommendation T.81 +// (www.w3.org/Graphics/JPEG/itu-t81.pdf) +// - The JFIF specification can be found in the JPEG File Interchange Format +// (www.w3.org/Graphics/JPEG/jfif3.pdf) +// - The Adobe Application-Specific JPEG markers in the Supporting the DCT Filters +// in PostScript Level 2, Technical Note #5116 +// (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf) + +var JpegImage = (function jpegImage() { + "use strict"; + var dctZigZag = new Int32Array([ + 0, + 1, 8, + 16, 9, 2, + 3, 10, 17, 24, + 32, 25, 18, 11, 4, + 5, 12, 19, 26, 33, 40, + 48, 41, 34, 27, 20, 13, 6, + 7, 14, 21, 28, 35, 42, 49, 56, + 57, 50, 43, 36, 29, 22, 15, + 23, 30, 37, 44, 51, 58, + 59, 52, 45, 38, 31, + 39, 46, 53, 60, + 61, 54, 47, + 55, 62, + 63 + ]); + + var dctCos1 = 4017 // cos(pi/16) + var dctSin1 = 799 // sin(pi/16) + var dctCos3 = 3406 // cos(3*pi/16) + var dctSin3 = 2276 // sin(3*pi/16) + var dctCos6 = 1567 // cos(6*pi/16) + var dctSin6 = 3784 // sin(6*pi/16) + var dctSqrt2 = 5793 // sqrt(2) + var dctSqrt1d2 = 2896 // sqrt(2) / 2 + + function constructor() { + } + + function buildHuffmanTable(codeLengths, values) { + var k = 0, code = [], i, j, length = 16; + while (length > 0 && !codeLengths[length - 1]) + length--; + code.push({children: [], index: 0}); + var p = code[0], q; + for (i = 0; i < length; i++) { + for (j = 0; j < codeLengths[i]; j++) { + p = code.pop(); + p.children[p.index] = values[k]; + while (p.index > 0) { + p = code.pop(); + } + p.index++; + code.push(p); + while (code.length <= i) { + code.push(q = {children: [], index: 0}); + p.children[p.index] = q.children; + p = q; + } + k++; + } + if (i + 1 < length) { + // p here points to last code + code.push(q = {children: [], index: 0}); + p.children[p.index] = q.children; + p = q; + } + } + return code[0].children; + } + + function decodeScan(data, offset, + frame, components, resetInterval, + spectralStart, spectralEnd, + successivePrev, successive) { + var precision = frame.precision; + var samplesPerLine = frame.samplesPerLine; + var scanLines = frame.scanLines; + var mcusPerLine = frame.mcusPerLine; + var progressive = frame.progressive; + var maxH = frame.maxH, maxV = frame.maxV; + + var startOffset = offset, bitsData = 0, bitsCount = 0; + function readBit() { + if (bitsCount > 0) { + bitsCount--; + return (bitsData >> bitsCount) & 1; + } + bitsData = data[offset++]; + if (bitsData == 0xFF) { + var nextByte = data[offset++]; + if (nextByte) { + throw "unexpected marker: " + ((bitsData << 8) | nextByte).toString(16); + } + // unstuff 0 + } + bitsCount = 7; + return bitsData >>> 7; + } + function decodeHuffman(tree) { + var node = tree, bit; + while ((bit = readBit()) !== null) { + node = node[bit]; + if (typeof node === 'number') + return node; + if (typeof node !== 'object') + throw "invalid huffman sequence"; + } + return null; + } + function receive(length) { + var n = 0; + while (length > 0) { + var bit = readBit(); + if (bit === null) return; + n = (n << 1) | bit; + length--; + } + return n; + } + function receiveAndExtend(length) { + var n = receive(length); + if (n >= 1 << (length - 1)) + return n; + return n + (-1 << length) + 1; + } + function decodeBaseline(component, zz) { + var t = decodeHuffman(component.huffmanTableDC); + var diff = t === 0 ? 0 : receiveAndExtend(t); + zz[0]= (component.pred += diff); + var k = 1; + while (k < 64) { + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) + break; + k += 16; + continue; + } + k += r; + var z = dctZigZag[k]; + zz[z] = receiveAndExtend(s); + k++; + } + } + function decodeDCFirst(component, zz) { + var t = decodeHuffman(component.huffmanTableDC); + var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive); + zz[0] = (component.pred += diff); + } + function decodeDCSuccessive(component, zz) { + zz[0] |= readBit() << successive; + } + var eobrun = 0; + function decodeACFirst(component, zz) { + if (eobrun > 0) { + eobrun--; + return; + } + var k = spectralStart, e = spectralEnd; + while (k <= e) { + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r) - 1; + break; + } + k += 16; + continue; + } + k += r; + var z = dctZigZag[k]; + zz[z] = receiveAndExtend(s) * (1 << successive); + k++; + } + } + var successiveACState = 0, successiveACNextValue; + function decodeACSuccessive(component, zz) { + var k = spectralStart, e = spectralEnd, r = 0; + while (k <= e) { + var z = dctZigZag[k]; + switch (successiveACState) { + case 0: // initial state + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r); + successiveACState = 4; + } else { + r = 16; + successiveACState = 1; + } + } else { + if (s !== 1) + throw "invalid ACn encoding"; + successiveACNextValue = receiveAndExtend(s); + successiveACState = r ? 2 : 3; + } + continue; + case 1: // skipping r zero items + case 2: + if (zz[z]) + zz[z] += (readBit() << successive); + else { + r--; + if (r === 0) + successiveACState = successiveACState == 2 ? 3 : 0; + } + break; + case 3: // set value for a zero item + if (zz[z]) + zz[z] += (readBit() << successive); + else { + zz[z] = successiveACNextValue << successive; + successiveACState = 0; + } + break; + case 4: // eob + if (zz[z]) + zz[z] += (readBit() << successive); + break; + } + k++; + } + if (successiveACState === 4) { + eobrun--; + if (eobrun === 0) + successiveACState = 0; + } + } + function decodeMcu(component, decode, mcu, row, col) { + var mcuRow = (mcu / mcusPerLine) | 0; + var mcuCol = mcu % mcusPerLine; + var blockRow = mcuRow * component.v + row; + var blockCol = mcuCol * component.h + col; + decode(component, component.blocks[blockRow][blockCol]); + } + function decodeBlock(component, decode, mcu) { + var blockRow = (mcu / component.blocksPerLine) | 0; + var blockCol = mcu % component.blocksPerLine; + decode(component, component.blocks[blockRow][blockCol]); + } + + var componentsLength = components.length; + var component, i, j, k, n; + var decodeFn; + if (progressive) { + if (spectralStart === 0) + decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive; + else + decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive; + } else { + decodeFn = decodeBaseline; + } + + var mcu = 0, marker; + var mcuExpected; + if (componentsLength == 1) { + mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn; + } else { + mcuExpected = mcusPerLine * frame.mcusPerColumn; + } + if (!resetInterval) resetInterval = mcuExpected; + + var h, v; + while (mcu < mcuExpected) { + // reset interval stuff + for (i = 0; i < componentsLength; i++) + components[i].pred = 0; + eobrun = 0; + + if (componentsLength == 1) { + component = components[0]; + for (n = 0; n < resetInterval; n++) { + decodeBlock(component, decodeFn, mcu); + mcu++; + } + } else { + for (n = 0; n < resetInterval; n++) { + for (i = 0; i < componentsLength; i++) { + component = components[i]; + h = component.h; + v = component.v; + for (j = 0; j < v; j++) { + for (k = 0; k < h; k++) { + decodeMcu(component, decodeFn, mcu, j, k); + } + } + } + mcu++; + + // If we've reached our expected MCU's, stop decoding + if (mcu === mcuExpected) break; + } + } + + // find marker + bitsCount = 0; + marker = (data[offset] << 8) | data[offset + 1]; + if (marker < 0xFF00) { + throw "marker was not found"; + } + + if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx + offset += 2; + } + else + break; + } + + return offset - startOffset; + } + + function buildComponentData(frame, component) { + var lines = []; + var blocksPerLine = component.blocksPerLine; + var blocksPerColumn = component.blocksPerColumn; + var samplesPerLine = blocksPerLine << 3; + var R = new Int32Array(64), r = new Uint8Array(64); + + // A port of poppler's IDCT method which in turn is taken from: + // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, + // "Practical Fast 1-D DCT Algorithms with 11 Multiplications", + // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, + // 988-991. + function quantizeAndInverse(zz, dataOut, dataIn) { + var qt = component.quantizationTable; + var v0, v1, v2, v3, v4, v5, v6, v7, t; + var p = dataIn; + var i; + + // dequant + for (i = 0; i < 64; i++) + p[i] = zz[i] * qt[i]; + + // inverse DCT on rows + for (i = 0; i < 8; ++i) { + var row = 8 * i; + + // check for all-zero AC coefficients + if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 && + p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 && + p[7 + row] == 0) { + t = (dctSqrt2 * p[0 + row] + 512) >> 10; + p[0 + row] = t; + p[1 + row] = t; + p[2 + row] = t; + p[3 + row] = t; + p[4 + row] = t; + p[5 + row] = t; + p[6 + row] = t; + p[7 + row] = t; + continue; + } + + // stage 4 + v0 = (dctSqrt2 * p[0 + row] + 128) >> 8; + v1 = (dctSqrt2 * p[4 + row] + 128) >> 8; + v2 = p[2 + row]; + v3 = p[6 + row]; + v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8; + v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8; + v5 = p[3 + row] << 4; + v6 = p[5 + row] << 4; + + // stage 3 + t = (v0 - v1+ 1) >> 1; + v0 = (v0 + v1 + 1) >> 1; + v1 = t; + t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; + v3 = t; + t = (v4 - v6 + 1) >> 1; + v4 = (v4 + v6 + 1) >> 1; + v6 = t; + t = (v7 + v5 + 1) >> 1; + v5 = (v7 - v5 + 1) >> 1; + v7 = t; + + // stage 2 + t = (v0 - v3 + 1) >> 1; + v0 = (v0 + v3 + 1) >> 1; + v3 = t; + t = (v1 - v2 + 1) >> 1; + v1 = (v1 + v2 + 1) >> 1; + v2 = t; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + p[0 + row] = v0 + v7; + p[7 + row] = v0 - v7; + p[1 + row] = v1 + v6; + p[6 + row] = v1 - v6; + p[2 + row] = v2 + v5; + p[5 + row] = v2 - v5; + p[3 + row] = v3 + v4; + p[4 + row] = v3 - v4; + } + + // inverse DCT on columns + for (i = 0; i < 8; ++i) { + var col = i; + + // check for all-zero AC coefficients + if (p[1*8 + col] == 0 && p[2*8 + col] == 0 && p[3*8 + col] == 0 && + p[4*8 + col] == 0 && p[5*8 + col] == 0 && p[6*8 + col] == 0 && + p[7*8 + col] == 0) { + t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14; + p[0*8 + col] = t; + p[1*8 + col] = t; + p[2*8 + col] = t; + p[3*8 + col] = t; + p[4*8 + col] = t; + p[5*8 + col] = t; + p[6*8 + col] = t; + p[7*8 + col] = t; + continue; + } + + // stage 4 + v0 = (dctSqrt2 * p[0*8 + col] + 2048) >> 12; + v1 = (dctSqrt2 * p[4*8 + col] + 2048) >> 12; + v2 = p[2*8 + col]; + v3 = p[6*8 + col]; + v4 = (dctSqrt1d2 * (p[1*8 + col] - p[7*8 + col]) + 2048) >> 12; + v7 = (dctSqrt1d2 * (p[1*8 + col] + p[7*8 + col]) + 2048) >> 12; + v5 = p[3*8 + col]; + v6 = p[5*8 + col]; + + // stage 3 + t = (v0 - v1 + 1) >> 1; + v0 = (v0 + v1 + 1) >> 1; + v1 = t; + t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; + v3 = t; + t = (v4 - v6 + 1) >> 1; + v4 = (v4 + v6 + 1) >> 1; + v6 = t; + t = (v7 + v5 + 1) >> 1; + v5 = (v7 - v5 + 1) >> 1; + v7 = t; + + // stage 2 + t = (v0 - v3 + 1) >> 1; + v0 = (v0 + v3 + 1) >> 1; + v3 = t; + t = (v1 - v2 + 1) >> 1; + v1 = (v1 + v2 + 1) >> 1; + v2 = t; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + p[0*8 + col] = v0 + v7; + p[7*8 + col] = v0 - v7; + p[1*8 + col] = v1 + v6; + p[6*8 + col] = v1 - v6; + p[2*8 + col] = v2 + v5; + p[5*8 + col] = v2 - v5; + p[3*8 + col] = v3 + v4; + p[4*8 + col] = v3 - v4; + } + + // convert to 8-bit integers + for (i = 0; i < 64; ++i) { + var sample = 128 + ((p[i] + 8) >> 4); + dataOut[i] = sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample; + } + } + + var i, j; + for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) { + var scanLine = blockRow << 3; + for (i = 0; i < 8; i++) + lines.push(new Uint8Array(samplesPerLine)); + for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) { + quantizeAndInverse(component.blocks[blockRow][blockCol], r, R); + + var offset = 0, sample = blockCol << 3; + for (j = 0; j < 8; j++) { + var line = lines[scanLine + j]; + for (i = 0; i < 8; i++) + line[sample + i] = r[offset++]; + } + } + } + return lines; + } + + function clampTo8bit(a) { + return a < 0 ? 0 : a > 255 ? 255 : a; + } + + constructor.prototype = { + load: function load(path) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", path, true); + xhr.responseType = "arraybuffer"; + xhr.onload = (function() { + // TODO catch parse error + var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer); + this.parse(data); + if (this.onload) + this.onload(); + }).bind(this); + xhr.send(null); + }, + parse: function parse(data) { + var offset = 0, length = data.length; + function readUint16() { + var value = (data[offset] << 8) | data[offset + 1]; + offset += 2; + return value; + } + function readDataBlock() { + var length = readUint16(); + var array = data.subarray(offset, offset + length - 2); + offset += array.length; + return array; + } + function prepareComponents(frame) { + var maxH = 0, maxV = 0; + var component, componentId; + for (componentId in frame.components) { + if (frame.components.hasOwnProperty(componentId)) { + component = frame.components[componentId]; + if (maxH < component.h) maxH = component.h; + if (maxV < component.v) maxV = component.v; + } + } + var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / maxH); + var mcusPerColumn = Math.ceil(frame.scanLines / 8 / maxV); + for (componentId in frame.components) { + if (frame.components.hasOwnProperty(componentId)) { + component = frame.components[componentId]; + var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / maxH); + var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / maxV); + var blocksPerLineForMcu = mcusPerLine * component.h; + var blocksPerColumnForMcu = mcusPerColumn * component.v; + var blocks = []; + for (var i = 0; i < blocksPerColumnForMcu; i++) { + var row = []; + for (var j = 0; j < blocksPerLineForMcu; j++) + row.push(new Int32Array(64)); + blocks.push(row); + } + component.blocksPerLine = blocksPerLine; + component.blocksPerColumn = blocksPerColumn; + component.blocks = blocks; + } + } + frame.maxH = maxH; + frame.maxV = maxV; + frame.mcusPerLine = mcusPerLine; + frame.mcusPerColumn = mcusPerColumn; + } + var jfif = null; + var adobe = null; + var pixels = null; + var frame, resetInterval; + var quantizationTables = [], frames = []; + var huffmanTablesAC = [], huffmanTablesDC = []; + var fileMarker = readUint16(); + if (fileMarker != 0xFFD8) { // SOI (Start of Image) + throw "SOI not found"; + } + + fileMarker = readUint16(); + while (fileMarker != 0xFFD9) { // EOI (End of image) + var i, j, l; + switch(fileMarker) { + case 0xFF00: break; + case 0xFFE0: // APP0 (Application Specific) + case 0xFFE1: // APP1 + case 0xFFE2: // APP2 + case 0xFFE3: // APP3 + case 0xFFE4: // APP4 + case 0xFFE5: // APP5 + case 0xFFE6: // APP6 + case 0xFFE7: // APP7 + case 0xFFE8: // APP8 + case 0xFFE9: // APP9 + case 0xFFEA: // APP10 + case 0xFFEB: // APP11 + case 0xFFEC: // APP12 + case 0xFFED: // APP13 + case 0xFFEE: // APP14 + case 0xFFEF: // APP15 + case 0xFFFE: // COM (Comment) + var appData = readDataBlock(); + + if (fileMarker === 0xFFE0) { + if (appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 && + appData[3] === 0x46 && appData[4] === 0) { // 'JFIF\x00' + jfif = { + version: { major: appData[5], minor: appData[6] }, + densityUnits: appData[7], + xDensity: (appData[8] << 8) | appData[9], + yDensity: (appData[10] << 8) | appData[11], + thumbWidth: appData[12], + thumbHeight: appData[13], + thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13]) + }; + } + } + // TODO APP1 - Exif + if (fileMarker === 0xFFEE) { + if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F && + appData[3] === 0x62 && appData[4] === 0x65 && appData[5] === 0) { // 'Adobe\x00' + adobe = { + version: appData[6], + flags0: (appData[7] << 8) | appData[8], + flags1: (appData[9] << 8) | appData[10], + transformCode: appData[11] + }; + } + } + break; + + case 0xFFDB: // DQT (Define Quantization Tables) + var quantizationTablesLength = readUint16(); + var quantizationTablesEnd = quantizationTablesLength + offset - 2; + while (offset < quantizationTablesEnd) { + var quantizationTableSpec = data[offset++]; + var tableData = new Int32Array(64); + if ((quantizationTableSpec >> 4) === 0) { // 8 bit values + for (j = 0; j < 64; j++) { + var z = dctZigZag[j]; + tableData[z] = data[offset++]; + } + } else if ((quantizationTableSpec >> 4) === 1) { //16 bit + for (j = 0; j < 64; j++) { + var z = dctZigZag[j]; + tableData[z] = readUint16(); + } + } else + throw "DQT: invalid table spec"; + quantizationTables[quantizationTableSpec & 15] = tableData; + } + break; + + case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT) + case 0xFFC1: // SOF1 (Start of Frame, Extended DCT) + case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT) + readUint16(); // skip data length + frame = {}; + frame.extended = (fileMarker === 0xFFC1); + frame.progressive = (fileMarker === 0xFFC2); + frame.precision = data[offset++]; + frame.scanLines = readUint16(); + frame.samplesPerLine = readUint16(); + frame.components = {}; + frame.componentsOrder = []; + var componentsCount = data[offset++], componentId; + var maxH = 0, maxV = 0; + for (i = 0; i < componentsCount; i++) { + componentId = data[offset]; + var h = data[offset + 1] >> 4; + var v = data[offset + 1] & 15; + var qId = data[offset + 2]; + frame.componentsOrder.push(componentId); + frame.components[componentId] = { + h: h, + v: v, + quantizationIdx: qId + }; + offset += 3; + } + prepareComponents(frame); + frames.push(frame); + break; + + case 0xFFC4: // DHT (Define Huffman Tables) + var huffmanLength = readUint16(); + for (i = 2; i < huffmanLength;) { + var huffmanTableSpec = data[offset++]; + var codeLengths = new Uint8Array(16); + var codeLengthSum = 0; + for (j = 0; j < 16; j++, offset++) + codeLengthSum += (codeLengths[j] = data[offset]); + var huffmanValues = new Uint8Array(codeLengthSum); + for (j = 0; j < codeLengthSum; j++, offset++) + huffmanValues[j] = data[offset]; + i += 17 + codeLengthSum; + + ((huffmanTableSpec >> 4) === 0 ? + huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = + buildHuffmanTable(codeLengths, huffmanValues); + } + break; + + case 0xFFDD: // DRI (Define Restart Interval) + readUint16(); // skip data length + resetInterval = readUint16(); + break; + + case 0xFFDA: // SOS (Start of Scan) + var scanLength = readUint16(); + var selectorsCount = data[offset++]; + var components = [], component; + for (i = 0; i < selectorsCount; i++) { + component = frame.components[data[offset++]]; + var tableSpec = data[offset++]; + component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; + component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; + components.push(component); + } + var spectralStart = data[offset++]; + var spectralEnd = data[offset++]; + var successiveApproximation = data[offset++]; + var processed = decodeScan(data, offset, + frame, components, resetInterval, + spectralStart, spectralEnd, + successiveApproximation >> 4, successiveApproximation & 15); + offset += processed; + break; + default: + if (data[offset - 3] == 0xFF && + data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) { + // could be incorrect encoding -- last 0xFF byte of the previous + // block was eaten by the encoder + offset -= 3; + break; + } + throw "unknown JPEG marker " + fileMarker.toString(16); + } + fileMarker = readUint16(); + } + if (frames.length != 1) + throw "only single frame JPEGs supported"; + + // set each frame's components quantization table + for (var i = 0; i < frames.length; i++) { + var cp = frames[i].components; + for (var j in cp) { + cp[j].quantizationTable = quantizationTables[cp[j].quantizationIdx]; + delete cp[j].quantizationIdx; + } + } + + this.width = frame.samplesPerLine; + this.height = frame.scanLines; + this.jfif = jfif; + this.adobe = adobe; + this.components = []; + for (var i = 0; i < frame.componentsOrder.length; i++) { + var component = frame.components[frame.componentsOrder[i]]; + this.components.push({ + lines: buildComponentData(frame, component), + scaleX: component.h / frame.maxH, + scaleY: component.v / frame.maxV + }); + } + }, + getData: function getData(width, height) { + var scaleX = this.width / width, scaleY = this.height / height; + + var component1, component2, component3, component4; + var component1Line, component2Line, component3Line, component4Line; + var x, y; + var offset = 0; + var Y, Cb, Cr, K, C, M, Ye, R, G, B; + var colorTransform; + var dataLength = width * height * this.components.length; + var data = new Uint8Array(dataLength); + switch (this.components.length) { + case 1: + component1 = this.components[0]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)]; + for (x = 0; x < width; x++) { + Y = component1Line[0 | (x * component1.scaleX * scaleX)]; + + data[offset++] = Y; + } + } + break; + case 2: + // PDF might compress two component data in custom colorspace + component1 = this.components[0]; + component2 = this.components[1]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)]; + component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)]; + for (x = 0; x < width; x++) { + Y = component1Line[0 | (x * component1.scaleX * scaleX)]; + data[offset++] = Y; + Y = component2Line[0 | (x * component2.scaleX * scaleX)]; + data[offset++] = Y; + } + } + break; + case 3: + // The default transform for three components is true + colorTransform = true; + // The adobe transform marker overrides any previous setting + if (this.adobe && this.adobe.transformCode) + colorTransform = true; + else if (typeof this.colorTransform !== 'undefined') + colorTransform = !!this.colorTransform; + + component1 = this.components[0]; + component2 = this.components[1]; + component3 = this.components[2]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)]; + component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)]; + component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)]; + for (x = 0; x < width; x++) { + if (!colorTransform) { + R = component1Line[0 | (x * component1.scaleX * scaleX)]; + G = component2Line[0 | (x * component2.scaleX * scaleX)]; + B = component3Line[0 | (x * component3.scaleX * scaleX)]; + } else { + Y = component1Line[0 | (x * component1.scaleX * scaleX)]; + Cb = component2Line[0 | (x * component2.scaleX * scaleX)]; + Cr = component3Line[0 | (x * component3.scaleX * scaleX)]; + + R = clampTo8bit(Y + 1.402 * (Cr - 128)); + G = clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128)); + B = clampTo8bit(Y + 1.772 * (Cb - 128)); + } + + data[offset++] = R; + data[offset++] = G; + data[offset++] = B; + } + } + break; + case 4: + if (!this.adobe) + throw 'Unsupported color mode (4 components)'; + // The default transform for four components is false + colorTransform = false; + // The adobe transform marker overrides any previous setting + if (this.adobe && this.adobe.transformCode) + colorTransform = true; + else if (typeof this.colorTransform !== 'undefined') + colorTransform = !!this.colorTransform; + + component1 = this.components[0]; + component2 = this.components[1]; + component3 = this.components[2]; + component4 = this.components[3]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)]; + component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)]; + component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)]; + component4Line = component4.lines[0 | (y * component4.scaleY * scaleY)]; + for (x = 0; x < width; x++) { + if (!colorTransform) { + C = component1Line[0 | (x * component1.scaleX * scaleX)]; + M = component2Line[0 | (x * component2.scaleX * scaleX)]; + Ye = component3Line[0 | (x * component3.scaleX * scaleX)]; + K = component4Line[0 | (x * component4.scaleX * scaleX)]; + } else { + Y = component1Line[0 | (x * component1.scaleX * scaleX)]; + Cb = component2Line[0 | (x * component2.scaleX * scaleX)]; + Cr = component3Line[0 | (x * component3.scaleX * scaleX)]; + K = component4Line[0 | (x * component4.scaleX * scaleX)]; + + C = 255 - clampTo8bit(Y + 1.402 * (Cr - 128)); + M = 255 - clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128)); + Ye = 255 - clampTo8bit(Y + 1.772 * (Cb - 128)); + } + data[offset++] = C; + data[offset++] = M; + data[offset++] = Ye; + data[offset++] = K; + } + } + break; + default: + throw 'Unsupported color mode'; + } + return data; + }, + copyToImageData: function copyToImageData(imageData) { + var width = imageData.width, height = imageData.height; + var imageDataArray = imageData.data; + var data = this.getData(width, height); + var i = 0, j = 0, x, y; + var Y, K, C, M, R, G, B; + switch (this.components.length) { + case 1: + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + Y = data[i++]; + + imageDataArray[j++] = Y; + imageDataArray[j++] = Y; + imageDataArray[j++] = Y; + imageDataArray[j++] = 255; + } + } + break; + case 3: + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + R = data[i++]; + G = data[i++]; + B = data[i++]; + + imageDataArray[j++] = R; + imageDataArray[j++] = G; + imageDataArray[j++] = B; + imageDataArray[j++] = 255; + } + } + break; + case 4: + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + C = data[i++]; + M = data[i++]; + Y = data[i++]; + K = data[i++]; + + R = 255 - clampTo8bit(C * (1 - K / 255) + K); + G = 255 - clampTo8bit(M * (1 - K / 255) + K); + B = 255 - clampTo8bit(Y * (1 - K / 255) + K); + + imageDataArray[j++] = R; + imageDataArray[j++] = G; + imageDataArray[j++] = B; + imageDataArray[j++] = 255; + } + } + break; + default: + throw 'Unsupported color mode'; + } + } + }; + + return constructor; +})(); +module.exports = decode; + +function decode(jpegData) { + var arr = new Uint8Array(jpegData); + var decoder = new JpegImage(); + decoder.parse(arr); + + var image = { + width: decoder.width, + height: decoder.height, + data: new Buffer(decoder.width * decoder.height * 4) + }; + + decoder.copyToImageData(image); + + return image; +} + +}).call(this,require("buffer").Buffer) +},{"buffer":299}],325:[function(require,module,exports){ +(function (Buffer){ +/* + Copyright (c) 2008, Adobe Systems Incorporated + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Adobe Systems Incorporated nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009 + +Basic GUI blocking jpeg encoder +*/ + +var btoa = btoa || function(buf) { + return new Buffer(buf).toString('base64'); +}; + +function JPEGEncoder(quality) { + var self = this; + var fround = Math.round; + var ffloor = Math.floor; + var YTable = new Array(64); + var UVTable = new Array(64); + var fdtbl_Y = new Array(64); + var fdtbl_UV = new Array(64); + var YDC_HT; + var UVDC_HT; + var YAC_HT; + var UVAC_HT; + + var bitcode = new Array(65535); + var category = new Array(65535); + var outputfDCTQuant = new Array(64); + var DU = new Array(64); + var byteout = []; + var bytenew = 0; + var bytepos = 7; + + var YDU = new Array(64); + var UDU = new Array(64); + var VDU = new Array(64); + var clt = new Array(256); + var RGB_YUV_TABLE = new Array(2048); + var currentQuality; + + var ZigZag = [ + 0, 1, 5, 6,14,15,27,28, + 2, 4, 7,13,16,26,29,42, + 3, 8,12,17,25,30,41,43, + 9,11,18,24,31,40,44,53, + 10,19,23,32,39,45,52,54, + 20,22,33,38,46,51,55,60, + 21,34,37,47,50,56,59,61, + 35,36,48,49,57,58,62,63 + ]; + + var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0]; + var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11]; + var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d]; + var std_ac_luminance_values = [ + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12, + 0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07, + 0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0, + 0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16, + 0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39, + 0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49, + 0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69, + 0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79, + 0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98, + 0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7, + 0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5, + 0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4, + 0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea, + 0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa + ]; + + var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0]; + var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11]; + var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77]; + var std_ac_chrominance_values = [ + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21, + 0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71, + 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0, + 0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34, + 0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38, + 0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48, + 0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68, + 0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78, + 0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96, + 0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5, + 0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3, + 0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2, + 0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9, + 0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa + ]; + + function initQuantTables(sf){ + var YQT = [ + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68,109,103, 77, + 24, 35, 55, 64, 81,104,113, 92, + 49, 64, 78, 87,103,121,120,101, + 72, 92, 95, 98,112,100,103, 99 + ]; + + for (var i = 0; i < 64; i++) { + var t = ffloor((YQT[i]*sf+50)/100); + if (t < 1) { + t = 1; + } else if (t > 255) { + t = 255; + } + YTable[ZigZag[i]] = t; + } + var UVQT = [ + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + ]; + for (var j = 0; j < 64; j++) { + var u = ffloor((UVQT[j]*sf+50)/100); + if (u < 1) { + u = 1; + } else if (u > 255) { + u = 255; + } + UVTable[ZigZag[j]] = u; + } + var aasf = [ + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + ]; + var k = 0; + for (var row = 0; row < 8; row++) + { + for (var col = 0; col < 8; col++) + { + fdtbl_Y[k] = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0)); + fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0)); + k++; + } + } + } + + function computeHuffmanTbl(nrcodes, std_table){ + var codevalue = 0; + var pos_in_table = 0; + var HT = new Array(); + for (var k = 1; k <= 16; k++) { + for (var j = 1; j <= nrcodes[k]; j++) { + HT[std_table[pos_in_table]] = []; + HT[std_table[pos_in_table]][0] = codevalue; + HT[std_table[pos_in_table]][1] = k; + pos_in_table++; + codevalue++; + } + codevalue*=2; + } + return HT; + } + + function initHuffmanTbl() + { + YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values); + UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values); + YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values); + UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values); + } + + function initCategoryNumber() + { + var nrlower = 1; + var nrupper = 2; + for (var cat = 1; cat <= 15; cat++) { + //Positive numbers + for (var nr = nrlower; nr>0] = 38470 * i; + RGB_YUV_TABLE[(i+ 512)>>0] = 7471 * i + 0x8000; + RGB_YUV_TABLE[(i+ 768)>>0] = -11059 * i; + RGB_YUV_TABLE[(i+1024)>>0] = -21709 * i; + RGB_YUV_TABLE[(i+1280)>>0] = 32768 * i + 0x807FFF; + RGB_YUV_TABLE[(i+1536)>>0] = -27439 * i; + RGB_YUV_TABLE[(i+1792)>>0] = - 5329 * i; + } + } + + // IO functions + function writeBits(bs) + { + var value = bs[0]; + var posval = bs[1]-1; + while ( posval >= 0 ) { + if (value & (1 << posval) ) { + bytenew |= (1 << bytepos); + } + posval--; + bytepos--; + if (bytepos < 0) { + if (bytenew == 0xFF) { + writeByte(0xFF); + writeByte(0); + } + else { + writeByte(bytenew); + } + bytepos=7; + bytenew=0; + } + } + } + + function writeByte(value) + { + //byteout.push(clt[value]); // write char directly instead of converting later + byteout.push(value); + } + + function writeWord(value) + { + writeByte((value>>8)&0xFF); + writeByte((value )&0xFF); + } + + // DCT & quantization core + function fDCTQuant(data, fdtbl) + { + var d0, d1, d2, d3, d4, d5, d6, d7; + /* Pass 1: process rows. */ + var dataOff=0; + var i; + const I8 = 8; + const I64 = 64; + for (i=0; i 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0); + //outputfDCTQuant[i] = fround(fDCTQuant); + + } + return outputfDCTQuant; + } + + function writeAPP0() + { + writeWord(0xFFE0); // marker + writeWord(16); // length + writeByte(0x4A); // J + writeByte(0x46); // F + writeByte(0x49); // I + writeByte(0x46); // F + writeByte(0); // = "JFIF",'\0' + writeByte(1); // versionhi + writeByte(1); // versionlo + writeByte(0); // xyunits + writeWord(1); // xdensity + writeWord(1); // ydensity + writeByte(0); // thumbnwidth + writeByte(0); // thumbnheight + } + + function writeSOF0(width, height) + { + writeWord(0xFFC0); // marker + writeWord(17); // length, truecolor YUV JPG + writeByte(8); // precision + writeWord(height); + writeWord(width); + writeByte(3); // nrofcomponents + writeByte(1); // IdY + writeByte(0x11); // HVY + writeByte(0); // QTY + writeByte(2); // IdU + writeByte(0x11); // HVU + writeByte(1); // QTU + writeByte(3); // IdV + writeByte(0x11); // HVV + writeByte(1); // QTV + } + + function writeDQT() + { + writeWord(0xFFDB); // marker + writeWord(132); // length + writeByte(0); + for (var i=0; i<64; i++) { + writeByte(YTable[i]); + } + writeByte(1); + for (var j=0; j<64; j++) { + writeByte(UVTable[j]); + } + } + + function writeDHT() + { + writeWord(0xFFC4); // marker + writeWord(0x01A2); // length + + writeByte(0); // HTYDCinfo + for (var i=0; i<16; i++) { + writeByte(std_dc_luminance_nrcodes[i+1]); + } + for (var j=0; j<=11; j++) { + writeByte(std_dc_luminance_values[j]); + } + + writeByte(0x10); // HTYACinfo + for (var k=0; k<16; k++) { + writeByte(std_ac_luminance_nrcodes[k+1]); + } + for (var l=0; l<=161; l++) { + writeByte(std_ac_luminance_values[l]); + } + + writeByte(1); // HTUDCinfo + for (var m=0; m<16; m++) { + writeByte(std_dc_chrominance_nrcodes[m+1]); + } + for (var n=0; n<=11; n++) { + writeByte(std_dc_chrominance_values[n]); + } + + writeByte(0x11); // HTUACinfo + for (var o=0; o<16; o++) { + writeByte(std_ac_chrominance_nrcodes[o+1]); + } + for (var p=0; p<=161; p++) { + writeByte(std_ac_chrominance_values[p]); + } + } + + function writeSOS() + { + writeWord(0xFFDA); // marker + writeWord(12); // length + writeByte(3); // nrofcomponents + writeByte(1); // IdY + writeByte(0); // HTY + writeByte(2); // IdU + writeByte(0x11); // HTU + writeByte(3); // IdV + writeByte(0x11); // HTV + writeByte(0); // Ss + writeByte(0x3f); // Se + writeByte(0); // Bf + } + + function processDU(CDU, fdtbl, DC, HTDC, HTAC){ + var EOB = HTAC[0x00]; + var M16zeroes = HTAC[0xF0]; + var pos; + const I16 = 16; + const I63 = 63; + const I64 = 64; + var DU_DCT = fDCTQuant(CDU, fdtbl); + //ZigZag reorder + for (var j=0;j0)&&(DU[end0pos]==0); end0pos--) {}; + //end0pos = first element in reverse order !=0 + if ( end0pos == 0) { + writeBits(EOB); + return DC; + } + var i = 1; + var lng; + while ( i <= end0pos ) { + var startpos = i; + for (; (DU[i]==0) && (i<=end0pos); ++i) {} + var nrzeroes = i-startpos; + if ( nrzeroes >= I16 ) { + lng = nrzeroes>>4; + for (var nrmarker=1; nrmarker <= lng; ++nrmarker) + writeBits(M16zeroes); + nrzeroes = nrzeroes&0xF; + } + pos = 32767+DU[i]; + writeBits(HTAC[(nrzeroes<<4)+category[pos]]); + writeBits(bitcode[pos]); + i++; + } + if ( end0pos != I63 ) { + writeBits(EOB); + } + return DC; + } + + function initCharLookupTable(){ + var sfcc = String.fromCharCode; + for(var i=0; i < 256; i++){ ///// ACHTUNG // 255 + clt[i] = sfcc(i); + } + } + + this.encode = function(image,quality) // image data object + { + var time_start = new Date().getTime(); + + if(quality) setQuality(quality); + + // Initialize bit writer + byteout = new Array(); + bytenew=0; + bytepos=7; + + // Add JPEG headers + writeWord(0xFFD8); // SOI + writeAPP0(); + writeDQT(); + writeSOF0(image.width,image.height); + writeDHT(); + writeSOS(); + + + // Encode 8x8 macroblocks + var DCY=0; + var DCU=0; + var DCV=0; + + bytenew=0; + bytepos=7; + + + this.encode.displayName = "_encode_"; + + var imageData = image.data; + var width = image.width; + var height = image.height; + + var quadWidth = width*4; + var tripleWidth = width*3; + + var x, y = 0; + var r, g, b; + var start,p, col,row,pos; + while(y < height){ + x = 0; + while(x < quadWidth){ + start = quadWidth * y + x; + p = start; + col = -1; + row = 0; + + for(pos=0; pos < 64; pos++){ + row = pos >> 3;// /8 + col = ( pos & 7 ) * 4; // %8 + p = start + ( row * quadWidth ) + col; + + if(y+row >= height){ // padding bottom + p-= (quadWidth*(y+1+row-height)); + } + + if(x+col >= quadWidth){ // padding right + p-= ((x+col) - quadWidth +4) + } + + r = imageData[ p++ ]; + g = imageData[ p++ ]; + b = imageData[ p++ ]; + + + /* // calculate YUV values dynamically + YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80 + UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b)); + VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b)); + */ + + // use lookup table (slightly faster) + YDU[pos] = ((RGB_YUV_TABLE[r] + RGB_YUV_TABLE[(g + 256)>>0] + RGB_YUV_TABLE[(b + 512)>>0]) >> 16)-128; + UDU[pos] = ((RGB_YUV_TABLE[(r + 768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128; + VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128; + + } + + DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + x+=32; + } + y+=8; + } + + + //////////////////////////////////////////////////////////////// + + // Do the bit alignment of the EOI marker + if ( bytepos >= 0 ) { + var fillbits = []; + fillbits[1] = bytepos+1; + fillbits[0] = (1<<(bytepos+1))-1; + writeBits(fillbits); + } + + writeWord(0xFFD9); //EOI + + //return new Uint8Array(byteout); + return new Buffer(byteout); + + var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join('')); + + byteout = []; + + // benchmarking + var duration = new Date().getTime() - time_start; + //console.log('Encoding time: '+ duration + 'ms'); + // + + return jpegDataUri + } + + function setQuality(quality){ + if (quality <= 0) { + quality = 1; + } + if (quality > 100) { + quality = 100; + } + + if(currentQuality == quality) return // don't recalc if unchanged + + var sf = 0; + if (quality < 50) { + sf = Math.floor(5000 / quality); + } else { + sf = Math.floor(200 - quality*2); + } + + initQuantTables(sf); + currentQuality = quality; + //console.log('Quality set to: '+quality +'%'); + } + + function init(){ + var time_start = new Date().getTime(); + if(!quality) quality = 50; + // Create tables + initCharLookupTable() + initHuffmanTbl(); + initCategoryNumber(); + initRGBYUVTable(); + + setQuality(quality); + var duration = new Date().getTime() - time_start; + //console.log('Initialization '+ duration + 'ms'); + } + + init(); + +}; +module.exports = encode; + +function encode(imgData, qu) { + if (typeof qu === 'undefined') qu = 50; + var encoder = new JPEGEncoder(qu); + var data = encoder.encode(imgData, qu); + return { + data: data, + width: imgData.width, + height: imgData.height + }; +} + +// helper function to get the imageData of an existing image on the current page. +function getImageDataFromImage(idOrElement){ + var theImg = (typeof(idOrElement)=='string')? document.getElementById(idOrElement):idOrElement; + var cvs = document.createElement('canvas'); + cvs.width = theImg.width; + cvs.height = theImg.height; + var ctx = cvs.getContext("2d"); + ctx.drawImage(theImg,0,0); + + return (ctx.getImageData(0, 0, cvs.width, cvs.height)); +} + +}).call(this,require("buffer").Buffer) +},{"buffer":299}],326:[function(require,module,exports){ +(function (Buffer){ +'use strict'; +const execBuffer = require('exec-buffer'); +const isJpg = require('is-jpg'); +const jpegtran = require('jpegtran-bin'); + +module.exports = options => buf => { + options = {...options}; + + if (!Buffer.isBuffer(buf)) { + return Promise.reject(new TypeError('Expected a buffer')); + } + + if (!isJpg(buf)) { + return Promise.resolve(buf); + } + + const args = ['-copy', 'none']; + + if (options.progressive) { + args.push('-progressive'); + } + + if (options.arithmetic) { + args.push('-arithmetic'); + } else { + args.push('-optimize'); + } + + args.push('-outfile', execBuffer.output, execBuffer.input); + + return execBuffer({ + input: buf, + bin: jpegtran, + args + }).catch(error => { + error.message = error.stderr || error.message; + throw error; + }); +}; + +}).call(this,{"isBuffer":require("../is-buffer/index.js")}) +},{"../is-buffer/index.js":361,"exec-buffer":57,"is-jpg":364,"jpegtran-bin":327}],327:[function(require,module,exports){ +'use strict'; +module.exports = require('./lib').path(); + +},{"./lib":328}],328:[function(require,module,exports){ +(function (process,__dirname){ +'use strict'; +const path = require('path'); +const BinWrapper = require('bin-wrapper'); +const pkg = require('../package.json'); + +const url = `https://raw.githubusercontent.com/imagemin/jpegtran-bin/v${pkg.version}/vendor/`; + +module.exports = new BinWrapper() + .src(`${url}macos/jpegtran`, 'darwin') + .src(`${url}linux/x86/jpegtran`, 'linux', 'x86') + .src(`${url}linux/x64/jpegtran`, 'linux', 'x64') + .src(`${url}freebsd/x86/jpegtran`, 'freebsd', 'x86') + .src(`${url}freebsd/x64/jpegtran`, 'freebsd', 'x64') + .src(`${url}sunos/x86/jpegtran`, 'sunos', 'x86') + .src(`${url}sunos/x64/jpegtran`, 'sunos', 'x64') + .src(`${url}win/x86/jpegtran.exe`, 'win32', 'x86') + .src(`${url}win/x64/jpegtran.exe`, 'win32', 'x64') + .src(`${url}win/x86/libjpeg-62.dll`, 'win32', 'x86') + .src(`${url}win/x64/libjpeg-62.dll`, 'win32', 'x64') + .dest(path.join(__dirname, '../vendor')) + .use(process.platform === 'win32' ? 'jpegtran.exe' : 'jpegtran'); + +}).call(this,require('_process'),"/node_modules/imagemin-jpegtran/node_modules/jpegtran-bin/lib") +},{"../package.json":329,"_process":437,"bin-wrapper":29,"path":404}],329:[function(require,module,exports){ +module.exports={ + "name": "jpegtran-bin", + "version": "5.0.2", + "description": "jpegtran (part of libjpeg-turbo) bin-wrapper that makes it seamlessly available as a local dependency", + "license": "MIT", + "repository": "imagemin/jpegtran-bin", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "maintainers": [ + { + "name": "Kevin Mårtensson", + "email": "kevinmartensson@gmail.com", + "url": "github.com/kevva" + }, + { + "name": "Shinnosuke Watanabe", + "url": "github.com/shinnn" + } + ], + "bin": { + "jpegtran": "cli.js" + }, + "engines": { + "node": ">=10" + }, + "scripts": { + "postinstall": "node lib/install.js", + "test": "xo && ava --timeout=120s" + }, + "files": [ + "index.js", + "cli.js", + "lib", + "test", + "vendor/source" + ], + "keywords": [ + "imagemin", + "compress", + "image", + "img", + "jpeg", + "jpg", + "minify", + "optimize", + "jpegtran" + ], + "dependencies": { + "bin-build": "^3.0.0", + "bin-wrapper": "^4.0.0", + "logalot": "^2.0.0" + }, + "devDependencies": { + "ava": "^3.8.0", + "bin-check": "^4.0.1", + "compare-size": "^3.0.0", + "execa": "^4.0.0", + "tempy": "^0.5.0", + "xo": "^0.30.0" + } +} + +},{}],330:[function(require,module,exports){ +(function (Buffer){ +'use strict'; +const execa = require('execa'); +const isPng = require('is-png'); +const isStream = require('is-stream'); +const pngquant = require('pngquant-bin'); +const ow = require('ow'); + +const imageminPngquant = (options = {}) => input => { + const isBuffer = Buffer.isBuffer(input); + + if (!isBuffer && !isStream(input)) { + return Promise.reject(new TypeError(`Expected a Buffer or Stream, got ${typeof input}`)); + } + + if (isBuffer && !isPng(input)) { + return Promise.resolve(input); + } + + const args = ['-']; + + if (typeof options.speed !== 'undefined') { + ow(options.speed, ow.number.integer.inRange(1, 11)); + args.push('--speed', options.speed); + } + + if (typeof options.strip !== 'undefined') { + ow(options.strip, ow.boolean); + + if (options.strip) { + args.push('--strip'); + } + } + + if (typeof options.quality !== 'undefined') { + ow(options.quality, ow.array.length(2).ofType(ow.number.inRange(0, 1))); + const [min, max] = options.quality; + args.push('--quality', `${Math.round(min * 100)}-${Math.round(max * 100)}`); + } + + if (typeof options.dithering !== 'undefined') { + ow(options.dithering, ow.any(ow.number.inRange(0, 1), ow.boolean.false)); + + if (typeof options.dithering === 'number') { + args.push(`--floyd=${options.dithering}`); + } else if (options.dithering === false) { + args.push('--ordered'); + } + } + + if (typeof options.posterize !== 'undefined') { + ow(options.posterize, ow.number); + args.push('--posterize', options.posterize); + } + + if (typeof options.verbose !== 'undefined') { + ow(options.verbose, ow.boolean); + args.push('--verbose'); + } + + const subprocess = execa(pngquant, args, { + encoding: null, + maxBuffer: Infinity, + input + }); + + const promise = subprocess + .then(result => result.stdout) // eslint-disable-line promise/prefer-await-to-then + .catch(error => { + // We use `error.exitCode` to check for a special condition when running the pngquant binary. + // See details on handling of "99" code at https://pngquant.org (search for "status code 99"). + if (error.exitCode === 99) { + return input; + } + + error.message = error.stderr || error.message; + throw error; + }); + + subprocess.stdout.then = promise.then.bind(promise); // eslint-disable-line promise/prefer-await-to-then + subprocess.stdout.catch = promise.catch.bind(promise); + + return subprocess.stdout; +}; + +module.exports = imageminPngquant; +module.exports.default = imageminPngquant; + +}).call(this,{"isBuffer":require("../is-buffer/index.js")}) +},{"../is-buffer/index.js":361,"execa":337,"is-png":365,"is-stream":346,"ow":401,"pngquant-bin":434}],331:[function(require,module,exports){ +'use strict'; + +const cp = require('child_process'); +const parse = require('./lib/parse'); +const enoent = require('./lib/enoent'); + +function spawn(command, args, options) { + // Parse the arguments + const parsed = parse(command, args, options); + + // Spawn the child process + const spawned = cp.spawn(parsed.command, parsed.args, parsed.options); + + // Hook into child process "exit" event to emit an error if the command + // does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + enoent.hookChildProcess(spawned, parsed); + + return spawned; +} + +function spawnSync(command, args, options) { + // Parse the arguments + const parsed = parse(command, args, options); + + // Spawn the child process + const result = cp.spawnSync(parsed.command, parsed.args, parsed.options); + + // Analyze if the command does not exist, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); + + return result; +} + +module.exports = spawn; +module.exports.spawn = spawn; +module.exports.sync = spawnSync; + +module.exports._parse = parse; +module.exports._enoent = enoent; + +},{"./lib/enoent":332,"./lib/parse":333,"child_process":298}],332:[function(require,module,exports){ +(function (process){ +'use strict'; + +const isWin = process.platform === 'win32'; + +function notFoundError(original, syscall) { + return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), { + code: 'ENOENT', + errno: 'ENOENT', + syscall: `${syscall} ${original.command}`, + path: original.command, + spawnargs: original.args, + }); +} + +function hookChildProcess(cp, parsed) { + if (!isWin) { + return; + } + + const originalEmit = cp.emit; + + cp.emit = function (name, arg1) { + // If emitting "exit" event and exit code is 1, we need to check if + // the command exists and emit an "error" instead + // See https://github.com/IndigoUnited/node-cross-spawn/issues/16 + if (name === 'exit') { + const err = verifyENOENT(arg1, parsed, 'spawn'); + + if (err) { + return originalEmit.call(cp, 'error', err); + } + } + + return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params + }; +} + +function verifyENOENT(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawn'); + } + + return null; +} + +function verifyENOENTSync(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawnSync'); + } + + return null; +} + +module.exports = { + hookChildProcess, + verifyENOENT, + verifyENOENTSync, + notFoundError, +}; + +}).call(this,require('_process')) +},{"_process":437}],333:[function(require,module,exports){ +(function (process){ +'use strict'; + +const path = require('path'); +const resolveCommand = require('./util/resolveCommand'); +const escape = require('./util/escape'); +const readShebang = require('./util/readShebang'); + +const isWin = process.platform === 'win32'; +const isExecutableRegExp = /\.(?:com|exe)$/i; +const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; + +function detectShebang(parsed) { + parsed.file = resolveCommand(parsed); + + const shebang = parsed.file && readShebang(parsed.file); + + if (shebang) { + parsed.args.unshift(parsed.file); + parsed.command = shebang; + + return resolveCommand(parsed); + } + + return parsed.file; +} + +function parseNonShell(parsed) { + if (!isWin) { + return parsed; + } + + // Detect & add support for shebangs + const commandFile = detectShebang(parsed); + + // We don't need a shell if the command filename is an executable + const needsShell = !isExecutableRegExp.test(commandFile); + + // If a shell is required, use cmd.exe and take care of escaping everything correctly + // Note that `forceShell` is an hidden option used only in tests + if (parsed.options.forceShell || needsShell) { + // Need to double escape meta chars if the command is a cmd-shim located in `node_modules/.bin/` + // The cmd-shim simply calls execute the package bin file with NodeJS, proxying any argument + // Because the escape of metachars with ^ gets interpreted when the cmd.exe is first called, + // we need to double escape them + const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile); + + // Normalize posix paths into OS compatible paths (e.g.: foo/bar -> foo\bar) + // This is necessary otherwise it will always fail with ENOENT in those cases + parsed.command = path.normalize(parsed.command); + + // Escape command & arguments + parsed.command = escape.command(parsed.command); + parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars)); + + const shellCommand = [parsed.command].concat(parsed.args).join(' '); + + parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`]; + parsed.command = process.env.comspec || 'cmd.exe'; + parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped + } + + return parsed; +} + +function parse(command, args, options) { + // Normalize arguments, similar to nodejs + if (args && !Array.isArray(args)) { + options = args; + args = null; + } + + args = args ? args.slice(0) : []; // Clone array to avoid changing the original + options = Object.assign({}, options); // Clone object to avoid changing the original + + // Build our parsed object + const parsed = { + command, + args, + options, + file: undefined, + original: { + command, + args, + }, + }; + + // Delegate further parsing to shell or non-shell + return options.shell ? parsed : parseNonShell(parsed); +} + +module.exports = parse; + +}).call(this,require('_process')) +},{"./util/escape":334,"./util/readShebang":335,"./util/resolveCommand":336,"_process":437,"path":404}],334:[function(require,module,exports){ +'use strict'; + +// See http://www.robvanderwoude.com/escapechars.php +const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; + +function escapeCommand(arg) { + // Escape meta chars + arg = arg.replace(metaCharsRegExp, '^$1'); + + return arg; +} + +function escapeArgument(arg, doubleEscapeMetaChars) { + // Convert to string + arg = `${arg}`; + + // Algorithm below is based on https://qntm.org/cmd + + // Sequence of backslashes followed by a double quote: + // double up all the backslashes and escape the double quote + arg = arg.replace(/(\\*)"/g, '$1$1\\"'); + + // Sequence of backslashes followed by the end of the string + // (which will become a double quote later): + // double up all the backslashes + arg = arg.replace(/(\\*)$/, '$1$1'); + + // All other backslashes occur literally + + // Quote the whole thing: + arg = `"${arg}"`; + + // Escape meta chars + arg = arg.replace(metaCharsRegExp, '^$1'); + + // Double escape meta chars if necessary + if (doubleEscapeMetaChars) { + arg = arg.replace(metaCharsRegExp, '^$1'); + } + + return arg; +} + +module.exports.command = escapeCommand; +module.exports.argument = escapeArgument; + +},{}],335:[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +const fs = require('fs'); +const shebangCommand = require('shebang-command'); + +function readShebang(command) { + // Read the first 150 bytes from the file + const size = 150; + const buffer = Buffer.alloc(size); + + let fd; + + try { + fd = fs.openSync(command, 'r'); + fs.readSync(fd, buffer, 0, size, 0); + fs.closeSync(fd); + } catch (e) { /* Empty */ } + + // Attempt to extract shebang (null is returned if not a shebang) + return shebangCommand(buffer.toString()); +} + +module.exports = readShebang; + +}).call(this,require("buffer").Buffer) +},{"buffer":299,"fs":298,"shebang-command":349}],336:[function(require,module,exports){ +(function (process){ +'use strict'; + +const path = require('path'); +const which = require('which'); +const getPathKey = require('path-key'); + +function resolveCommandAttempt(parsed, withoutPathExt) { + const env = parsed.options.env || process.env; + const cwd = process.cwd(); + const hasCustomCwd = parsed.options.cwd != null; + // Worker threads do not have process.chdir() + const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled; + + // If a custom `cwd` was specified, we need to change the process cwd + // because `which` will do stat calls but does not support a custom cwd + if (shouldSwitchCwd) { + try { + process.chdir(parsed.options.cwd); + } catch (err) { + /* Empty */ + } + } + + let resolved; + + try { + resolved = which.sync(parsed.command, { + path: env[getPathKey({ env })], + pathExt: withoutPathExt ? path.delimiter : undefined, + }); + } catch (e) { + /* Empty */ + } finally { + if (shouldSwitchCwd) { + process.chdir(cwd); + } + } + + // If we successfully resolved, ensure that an absolute path is returned + // Note that when a custom `cwd` was used, we need to resolve to an absolute path based on it + if (resolved) { + resolved = path.resolve(hasCustomCwd ? parsed.options.cwd : '', resolved); + } + + return resolved; +} + +function resolveCommand(parsed) { + return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true); +} + +module.exports = resolveCommand; + +}).call(this,require('_process')) +},{"_process":437,"path":404,"path-key":348,"which":351}],337:[function(require,module,exports){ +(function (Buffer,process){ +'use strict'; +const path = require('path'); +const childProcess = require('child_process'); +const crossSpawn = require('cross-spawn'); +const stripFinalNewline = require('strip-final-newline'); +const npmRunPath = require('npm-run-path'); +const onetime = require('onetime'); +const makeError = require('./lib/error'); +const normalizeStdio = require('./lib/stdio'); +const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = require('./lib/kill'); +const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = require('./lib/stream.js'); +const {mergePromise, getSpawnedPromise} = require('./lib/promise.js'); +const {joinCommand, parseCommand} = require('./lib/command.js'); + +const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100; + +const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => { + const env = extendEnv ? {...process.env, ...envOption} : envOption; + + if (preferLocal) { + return npmRunPath.env({env, cwd: localDir, execPath}); + } + + return env; +}; + +const handleArguments = (file, args, options = {}) => { + const parsed = crossSpawn._parse(file, args, options); + file = parsed.command; + args = parsed.args; + options = parsed.options; + + options = { + maxBuffer: DEFAULT_MAX_BUFFER, + buffer: true, + stripFinalNewline: true, + extendEnv: true, + preferLocal: false, + localDir: options.cwd || process.cwd(), + execPath: process.execPath, + encoding: 'utf8', + reject: true, + cleanup: true, + all: false, + windowsHide: true, + ...options + }; + + options.env = getEnv(options); + + options.stdio = normalizeStdio(options); + + if (process.platform === 'win32' && path.basename(file, '.exe') === 'cmd') { + // #116 + args.unshift('/q'); + } + + return {file, args, options, parsed}; +}; + +const handleOutput = (options, value, error) => { + if (typeof value !== 'string' && !Buffer.isBuffer(value)) { + // When `execa.sync()` errors, we normalize it to '' to mimic `execa()` + return error === undefined ? undefined : ''; + } + + if (options.stripFinalNewline) { + return stripFinalNewline(value); + } + + return value; +}; + +const execa = (file, args, options) => { + const parsed = handleArguments(file, args, options); + const command = joinCommand(file, args); + + let spawned; + try { + spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options); + } catch (error) { + // Ensure the returned error is always both a promise and a child process + const dummySpawned = new childProcess.ChildProcess(); + const errorPromise = Promise.reject(makeError({ + error, + stdout: '', + stderr: '', + all: '', + command, + parsed, + timedOut: false, + isCanceled: false, + killed: false + })); + return mergePromise(dummySpawned, errorPromise); + } + + const spawnedPromise = getSpawnedPromise(spawned); + const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise); + const processDone = setExitHandler(spawned, parsed.options, timedPromise); + + const context = {isCanceled: false}; + + spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned)); + spawned.cancel = spawnedCancel.bind(null, spawned, context); + + const handlePromise = async () => { + const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone); + const stdout = handleOutput(parsed.options, stdoutResult); + const stderr = handleOutput(parsed.options, stderrResult); + const all = handleOutput(parsed.options, allResult); + + if (error || exitCode !== 0 || signal !== null) { + const returnedError = makeError({ + error, + exitCode, + signal, + stdout, + stderr, + all, + command, + parsed, + timedOut, + isCanceled: context.isCanceled, + killed: spawned.killed + }); + + if (!parsed.options.reject) { + return returnedError; + } + + throw returnedError; + } + + return { + command, + exitCode: 0, + stdout, + stderr, + all, + failed: false, + timedOut: false, + isCanceled: false, + killed: false + }; + }; + + const handlePromiseOnce = onetime(handlePromise); + + crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed); + + handleInput(spawned, parsed.options.input); + + spawned.all = makeAllStream(spawned, parsed.options); + + return mergePromise(spawned, handlePromiseOnce); +}; + +module.exports = execa; + +module.exports.sync = (file, args, options) => { + const parsed = handleArguments(file, args, options); + const command = joinCommand(file, args); + + validateInputSync(parsed.options); + + let result; + try { + result = childProcess.spawnSync(parsed.file, parsed.args, parsed.options); + } catch (error) { + throw makeError({ + error, + stdout: '', + stderr: '', + all: '', + command, + parsed, + timedOut: false, + isCanceled: false, + killed: false + }); + } + + const stdout = handleOutput(parsed.options, result.stdout, result.error); + const stderr = handleOutput(parsed.options, result.stderr, result.error); + + if (result.error || result.status !== 0 || result.signal !== null) { + const error = makeError({ + stdout, + stderr, + error: result.error, + signal: result.signal, + exitCode: result.status, + command, + parsed, + timedOut: result.error && result.error.code === 'ETIMEDOUT', + isCanceled: false, + killed: result.signal !== null + }); + + if (!parsed.options.reject) { + return error; + } + + throw error; + } + + return { + command, + exitCode: 0, + stdout, + stderr, + failed: false, + timedOut: false, + isCanceled: false, + killed: false + }; +}; + +module.exports.command = (command, options) => { + const [file, ...args] = parseCommand(command); + return execa(file, args, options); +}; + +module.exports.commandSync = (command, options) => { + const [file, ...args] = parseCommand(command); + return execa.sync(file, args, options); +}; + +module.exports.node = (scriptPath, args, options = {}) => { + if (args && !Array.isArray(args) && typeof args === 'object') { + options = args; + args = []; + } + + const stdio = normalizeStdio.node(options); + const defaultExecArgv = process.execArgv.filter(arg => !arg.startsWith('--inspect')); + + const { + nodePath = process.execPath, + nodeOptions = defaultExecArgv + } = options; + + return execa( + nodePath, + [ + ...nodeOptions, + scriptPath, + ...(Array.isArray(args) ? args : []) + ], + { + ...options, + stdin: undefined, + stdout: undefined, + stderr: undefined, + stdio, + shell: false + } + ); +}; + +}).call(this,{"isBuffer":require("../../../is-buffer/index.js")},require('_process')) +},{"../../../is-buffer/index.js":361,"./lib/command.js":338,"./lib/error":339,"./lib/kill":340,"./lib/promise.js":341,"./lib/stdio":342,"./lib/stream.js":343,"_process":437,"child_process":298,"cross-spawn":331,"npm-run-path":347,"onetime":400,"path":404,"strip-final-newline":510}],338:[function(require,module,exports){ +'use strict'; +const SPACES_REGEXP = / +/g; + +const joinCommand = (file, args = []) => { + if (!Array.isArray(args)) { + return file; + } + + return [file, ...args].join(' '); +}; + +// Handle `execa.command()` +const parseCommand = command => { + const tokens = []; + for (const token of command.trim().split(SPACES_REGEXP)) { + // Allow spaces to be escaped by a backslash if not meant as a delimiter + const previousToken = tokens[tokens.length - 1]; + if (previousToken && previousToken.endsWith('\\')) { + // Merge previous token with current one + tokens[tokens.length - 1] = `${previousToken.slice(0, -1)} ${token}`; + } else { + tokens.push(token); + } + } + + return tokens; +}; + +module.exports = { + joinCommand, + parseCommand +}; + +},{}],339:[function(require,module,exports){ +'use strict'; +const {signalsByName} = require('human-signals'); + +const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => { + if (timedOut) { + return `timed out after ${timeout} milliseconds`; + } + + if (isCanceled) { + return 'was canceled'; + } + + if (errorCode !== undefined) { + return `failed with ${errorCode}`; + } + + if (signal !== undefined) { + return `was killed with ${signal} (${signalDescription})`; + } + + if (exitCode !== undefined) { + return `failed with exit code ${exitCode}`; + } + + return 'failed'; +}; + +const makeError = ({ + stdout, + stderr, + all, + error, + signal, + exitCode, + command, + timedOut, + isCanceled, + killed, + parsed: {options: {timeout}} +}) => { + // `signal` and `exitCode` emitted on `spawned.on('exit')` event can be `null`. + // We normalize them to `undefined` + exitCode = exitCode === null ? undefined : exitCode; + signal = signal === null ? undefined : signal; + const signalDescription = signal === undefined ? undefined : signalsByName[signal].description; + + const errorCode = error && error.code; + + const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}); + const execaMessage = `Command ${prefix}: ${command}`; + const isError = Object.prototype.toString.call(error) === '[object Error]'; + const shortMessage = isError ? `${execaMessage}\n${error.message}` : execaMessage; + const message = [shortMessage, stderr, stdout].filter(Boolean).join('\n'); + + if (isError) { + error.originalMessage = error.message; + error.message = message; + } else { + error = new Error(message); + } + + error.shortMessage = shortMessage; + error.command = command; + error.exitCode = exitCode; + error.signal = signal; + error.signalDescription = signalDescription; + error.stdout = stdout; + error.stderr = stderr; + + if (all !== undefined) { + error.all = all; + } + + if ('bufferedData' in error) { + delete error.bufferedData; + } + + error.failed = true; + error.timedOut = Boolean(timedOut); + error.isCanceled = isCanceled; + error.killed = killed && !timedOut; + + return error; +}; + +module.exports = makeError; + +},{"human-signals":314}],340:[function(require,module,exports){ +'use strict'; +const os = require('os'); +const onExit = require('signal-exit'); + +const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5; + +// Monkey-patches `childProcess.kill()` to add `forceKillAfterTimeout` behavior +const spawnedKill = (kill, signal = 'SIGTERM', options = {}) => { + const killResult = kill(signal); + setKillTimeout(kill, signal, options, killResult); + return killResult; +}; + +const setKillTimeout = (kill, signal, options, killResult) => { + if (!shouldForceKill(signal, options, killResult)) { + return; + } + + const timeout = getForceKillAfterTimeout(options); + const t = setTimeout(() => { + kill('SIGKILL'); + }, timeout); + + // Guarded because there's no `.unref()` when `execa` is used in the renderer + // process in Electron. This cannot be tested since we don't run tests in + // Electron. + // istanbul ignore else + if (t.unref) { + t.unref(); + } +}; + +const shouldForceKill = (signal, {forceKillAfterTimeout}, killResult) => { + return isSigterm(signal) && forceKillAfterTimeout !== false && killResult; +}; + +const isSigterm = signal => { + return signal === os.constants.signals.SIGTERM || + (typeof signal === 'string' && signal.toUpperCase() === 'SIGTERM'); +}; + +const getForceKillAfterTimeout = ({forceKillAfterTimeout = true}) => { + if (forceKillAfterTimeout === true) { + return DEFAULT_FORCE_KILL_TIMEOUT; + } + + if (!Number.isFinite(forceKillAfterTimeout) || forceKillAfterTimeout < 0) { + throw new TypeError(`Expected the \`forceKillAfterTimeout\` option to be a non-negative integer, got \`${forceKillAfterTimeout}\` (${typeof forceKillAfterTimeout})`); + } + + return forceKillAfterTimeout; +}; + +// `childProcess.cancel()` +const spawnedCancel = (spawned, context) => { + const killResult = spawned.kill(); + + if (killResult) { + context.isCanceled = true; + } +}; + +const timeoutKill = (spawned, signal, reject) => { + spawned.kill(signal); + reject(Object.assign(new Error('Timed out'), {timedOut: true, signal})); +}; + +// `timeout` option handling +const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise) => { + if (timeout === 0 || timeout === undefined) { + return spawnedPromise; + } + + if (!Number.isFinite(timeout) || timeout < 0) { + throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`); + } + + let timeoutId; + const timeoutPromise = new Promise((resolve, reject) => { + timeoutId = setTimeout(() => { + timeoutKill(spawned, killSignal, reject); + }, timeout); + }); + + const safeSpawnedPromise = spawnedPromise.finally(() => { + clearTimeout(timeoutId); + }); + + return Promise.race([timeoutPromise, safeSpawnedPromise]); +}; + +// `cleanup` option handling +const setExitHandler = async (spawned, {cleanup, detached}, timedPromise) => { + if (!cleanup || detached) { + return timedPromise; + } + + const removeExitHandler = onExit(() => { + spawned.kill(); + }); + + return timedPromise.finally(() => { + removeExitHandler(); + }); +}; + +module.exports = { + spawnedKill, + spawnedCancel, + setupTimeout, + setExitHandler +}; + +},{"os":301,"signal-exit":499}],341:[function(require,module,exports){ +'use strict'; + +const nativePromisePrototype = (async () => {})().constructor.prototype; +const descriptors = ['then', 'catch', 'finally'].map(property => [ + property, + Reflect.getOwnPropertyDescriptor(nativePromisePrototype, property) +]); + +// The return value is a mixin of `childProcess` and `Promise` +const mergePromise = (spawned, promise) => { + for (const [property, descriptor] of descriptors) { + // Starting the main `promise` is deferred to avoid consuming streams + const value = typeof promise === 'function' ? + (...args) => Reflect.apply(descriptor.value, promise(), args) : + descriptor.value.bind(promise); + + Reflect.defineProperty(spawned, property, {...descriptor, value}); + } + + return spawned; +}; + +// Use promises instead of `child_process` events +const getSpawnedPromise = spawned => { + return new Promise((resolve, reject) => { + spawned.on('exit', (exitCode, signal) => { + resolve({exitCode, signal}); + }); + + spawned.on('error', error => { + reject(error); + }); + + if (spawned.stdin) { + spawned.stdin.on('error', error => { + reject(error); + }); + } + }); +}; + +module.exports = { + mergePromise, + getSpawnedPromise +}; + + +},{}],342:[function(require,module,exports){ +'use strict'; +const aliases = ['stdin', 'stdout', 'stderr']; + +const hasAlias = opts => aliases.some(alias => opts[alias] !== undefined); + +const normalizeStdio = opts => { + if (!opts) { + return; + } + + const {stdio} = opts; + + if (stdio === undefined) { + return aliases.map(alias => opts[alias]); + } + + if (hasAlias(opts)) { + throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${aliases.map(alias => `\`${alias}\``).join(', ')}`); + } + + if (typeof stdio === 'string') { + return stdio; + } + + if (!Array.isArray(stdio)) { + throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); + } + + const length = Math.max(stdio.length, aliases.length); + return Array.from({length}, (value, index) => stdio[index]); +}; + +module.exports = normalizeStdio; + +// `ipc` is pushed unless it is already present +module.exports.node = opts => { + const stdio = normalizeStdio(opts); + + if (stdio === 'ipc') { + return 'ipc'; + } + + if (stdio === undefined || typeof stdio === 'string') { + return [stdio, stdio, stdio, 'ipc']; + } + + if (stdio.includes('ipc')) { + return stdio; + } + + return [...stdio, 'ipc']; +}; + +},{}],343:[function(require,module,exports){ +'use strict'; +const isStream = require('is-stream'); +const getStream = require('get-stream'); +const mergeStream = require('merge-stream'); + +// `input` option +const handleInput = (spawned, input) => { + // Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852 + // TODO: Remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0 + if (input === undefined || spawned.stdin === undefined) { + return; + } + + if (isStream(input)) { + input.pipe(spawned.stdin); + } else { + spawned.stdin.end(input); + } +}; + +// `all` interleaves `stdout` and `stderr` +const makeAllStream = (spawned, {all}) => { + if (!all || (!spawned.stdout && !spawned.stderr)) { + return; + } + + const mixed = mergeStream(); + + if (spawned.stdout) { + mixed.add(spawned.stdout); + } + + if (spawned.stderr) { + mixed.add(spawned.stderr); + } + + return mixed; +}; + +// On failure, `result.stdout|stderr|all` should contain the currently buffered stream +const getBufferedData = async (stream, streamPromise) => { + if (!stream) { + return; + } + + stream.destroy(); + + try { + return await streamPromise; + } catch (error) { + return error.bufferedData; + } +}; + +const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => { + if (!stream || !buffer) { + return; + } + + if (encoding) { + return getStream(stream, {encoding, maxBuffer}); + } + + return getStream.buffer(stream, {maxBuffer}); +}; + +// Retrieve result of child process: exit code, signal, error, streams (stdout/stderr/all) +const getSpawnedResult = async ({stdout, stderr, all}, {encoding, buffer, maxBuffer}, processDone) => { + const stdoutPromise = getStreamPromise(stdout, {encoding, buffer, maxBuffer}); + const stderrPromise = getStreamPromise(stderr, {encoding, buffer, maxBuffer}); + const allPromise = getStreamPromise(all, {encoding, buffer, maxBuffer: maxBuffer * 2}); + + try { + return await Promise.all([processDone, stdoutPromise, stderrPromise, allPromise]); + } catch (error) { + return Promise.all([ + {error, signal: error.signal, timedOut: error.timedOut}, + getBufferedData(stdout, stdoutPromise), + getBufferedData(stderr, stderrPromise), + getBufferedData(all, allPromise) + ]); + } +}; + +const validateInputSync = ({input}) => { + if (isStream(input)) { + throw new TypeError('The `input` option cannot be a stream in sync mode'); + } +}; + +module.exports = { + handleInput, + makeAllStream, + getSpawnedResult, + validateInputSync +}; + + +},{"get-stream":345,"is-stream":346,"merge-stream":380}],344:[function(require,module,exports){ +(function (Buffer){ +'use strict'; +const {PassThrough: PassThroughStream} = require('stream'); + +module.exports = options => { + options = {...options}; + + const {array} = options; + let {encoding} = options; + const isBuffer = encoding === 'buffer'; + let objectMode = false; + + if (array) { + objectMode = !(encoding || isBuffer); + } else { + encoding = encoding || 'utf8'; + } + + if (isBuffer) { + encoding = null; + } + + const stream = new PassThroughStream({objectMode}); + + if (encoding) { + stream.setEncoding(encoding); + } + + let length = 0; + const chunks = []; + + stream.on('data', chunk => { + chunks.push(chunk); + + if (objectMode) { + length = chunks.length; + } else { + length += chunk.length; + } + }); + + stream.getBufferedValue = () => { + if (array) { + return chunks; + } + + return isBuffer ? Buffer.concat(chunks, length) : chunks.join(''); + }; + + stream.getBufferedLength = () => length; + + return stream; +}; + +}).call(this,require("buffer").Buffer) +},{"buffer":299,"stream":503}],345:[function(require,module,exports){ +'use strict'; +const {constants: BufferConstants} = require('buffer'); +const pump = require('pump'); +const bufferStream = require('./buffer-stream'); + +class MaxBufferError extends Error { + constructor() { + super('maxBuffer exceeded'); + this.name = 'MaxBufferError'; + } +} + +async function getStream(inputStream, options) { + if (!inputStream) { + return Promise.reject(new Error('Expected a stream')); + } + + options = { + maxBuffer: Infinity, + ...options + }; + + const {maxBuffer} = options; + + let stream; + await new Promise((resolve, reject) => { + const rejectPromise = error => { + // Don't retrieve an oversized buffer. + if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) { + error.bufferedData = stream.getBufferedValue(); + } + + reject(error); + }; + + stream = pump(inputStream, bufferStream(options), error => { + if (error) { + rejectPromise(error); + return; + } + + resolve(); + }); + + stream.on('data', () => { + if (stream.getBufferedLength() > maxBuffer) { + rejectPromise(new MaxBufferError()); + } + }); + }); + + return stream.getBufferedValue(); +} + +module.exports = getStream; +// TODO: Remove this for the next major release +module.exports.default = getStream; +module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'}); +module.exports.array = (stream, options) => getStream(stream, {...options, array: true}); +module.exports.MaxBufferError = MaxBufferError; + +},{"./buffer-stream":344,"buffer":299,"pump":440}],346:[function(require,module,exports){ +'use strict'; + +const isStream = stream => + stream !== null && + typeof stream === 'object' && + typeof stream.pipe === 'function'; + +isStream.writable = stream => + isStream(stream) && + stream.writable !== false && + typeof stream._write === 'function' && + typeof stream._writableState === 'object'; + +isStream.readable = stream => + isStream(stream) && + stream.readable !== false && + typeof stream._read === 'function' && + typeof stream._readableState === 'object'; + +isStream.duplex = stream => + isStream.writable(stream) && + isStream.readable(stream); + +isStream.transform = stream => + isStream.duplex(stream) && + typeof stream._transform === 'function' && + typeof stream._transformState === 'object'; + +module.exports = isStream; + +},{}],347:[function(require,module,exports){ +(function (process){ +'use strict'; +const path = require('path'); +const pathKey = require('path-key'); + +const npmRunPath = options => { + options = { + cwd: process.cwd(), + path: process.env[pathKey()], + execPath: process.execPath, + ...options + }; + + let previous; + let cwdPath = path.resolve(options.cwd); + const result = []; + + while (previous !== cwdPath) { + result.push(path.join(cwdPath, 'node_modules/.bin')); + previous = cwdPath; + cwdPath = path.resolve(cwdPath, '..'); + } + + // Ensure the running `node` binary is used + const execPathDir = path.resolve(options.cwd, options.execPath, '..'); + result.push(execPathDir); + + return result.concat(options.path).join(path.delimiter); +}; + +module.exports = npmRunPath; +// TODO: Remove this for the next major release +module.exports.default = npmRunPath; + +module.exports.env = options => { + options = { + env: process.env, + ...options + }; + + const env = {...options.env}; + const path = pathKey({env}); + + options.path = env[path]; + env[path] = module.exports(options); + + return env; +}; + +}).call(this,require('_process')) +},{"_process":437,"path":404,"path-key":348}],348:[function(require,module,exports){ +(function (process){ +'use strict'; + +const pathKey = (options = {}) => { + const environment = options.env || process.env; + const platform = options.platform || process.platform; + + if (platform !== 'win32') { + return 'PATH'; + } + + return Object.keys(environment).reverse().find(key => key.toUpperCase() === 'PATH') || 'Path'; +}; + +module.exports = pathKey; +// TODO: Remove this for the next major release +module.exports.default = pathKey; + +}).call(this,require('_process')) +},{"_process":437}],349:[function(require,module,exports){ +'use strict'; +const shebangRegex = require('shebang-regex'); + +module.exports = (string = '') => { + const match = string.match(shebangRegex); + + if (!match) { + return null; + } + + const [path, argument] = match[0].replace(/#! ?/, '').split(' '); + const binary = path.split('/').pop(); + + if (binary === 'env') { + return argument; + } + + return argument ? `${binary} ${argument}` : binary; +}; + +},{"shebang-regex":350}],350:[function(require,module,exports){ +'use strict'; +module.exports = /^#!(.*)/; + +},{}],351:[function(require,module,exports){ +(function (process){ +const isWindows = process.platform === 'win32' || + process.env.OSTYPE === 'cygwin' || + process.env.OSTYPE === 'msys' + +const path = require('path') +const COLON = isWindows ? ';' : ':' +const isexe = require('isexe') + +const getNotFoundError = (cmd) => + Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) + +const getPathInfo = (cmd, opt) => { + const colon = opt.colon || COLON + + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [''] + : ( + [ + // windows always checks the cwd first + ...(isWindows ? [process.cwd()] : []), + ...(opt.path || process.env.PATH || + /* istanbul ignore next: very unusual */ '').split(colon), + ] + ) + const pathExtExe = isWindows + ? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM' + : '' + const pathExt = isWindows ? pathExtExe.split(colon) : [''] + + if (isWindows) { + if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') + pathExt.unshift('') + } + + return { + pathEnv, + pathExt, + pathExtExe, + } +} + +const which = (cmd, opt, cb) => { + if (typeof opt === 'function') { + cb = opt + opt = {} + } + if (!opt) + opt = {} + + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + const step = i => new Promise((resolve, reject) => { + if (i === pathEnv.length) + return opt.all && found.length ? resolve(found) + : reject(getNotFoundError(cmd)) + + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw + + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd + + resolve(subStep(p, i, 0)) + }) + + const subStep = (p, i, ii) => new Promise((resolve, reject) => { + if (ii === pathExt.length) + return resolve(step(i + 1)) + const ext = pathExt[ii] + isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { + if (!er && is) { + if (opt.all) + found.push(p + ext) + else + return resolve(p + ext) + } + return resolve(subStep(p, i, ii + 1)) + }) + }) + + return cb ? step(0).then(res => cb(null, res), cb) : step(0) +} + +const whichSync = (cmd, opt) => { + opt = opt || {} + + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + for (let i = 0; i < pathEnv.length; i ++) { + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw + + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd + + for (let j = 0; j < pathExt.length; j ++) { + const cur = p + pathExt[j] + try { + const is = isexe.sync(cur, { pathExt: pathExtExe }) + if (is) { + if (opt.all) + found.push(cur) + else + return cur + } + } catch (ex) {} + } + } + + if (opt.all && found.length) + return found + + if (opt.nothrow) + return null + + throw getNotFoundError(cmd) +} + +module.exports = which +which.sync = whichSync + +}).call(this,require('_process')) +},{"_process":437,"isexe":368,"path":404}],352:[function(require,module,exports){ +(function (Buffer){ +'use strict'; +const {promisify} = require('util'); +const path = require('path'); +const fs = require('graceful-fs'); +const fileType = require('file-type'); +const globby = require('globby'); +const makeDir = require('make-dir'); +const pPipe = require('p-pipe'); +const replaceExt = require('replace-ext'); +const junk = require('junk'); + +const readFile = promisify(fs.readFile); +const writeFile = promisify(fs.writeFile); + +const handleFile = async (sourcePath, {destination, plugins = []}) => { + if (plugins && !Array.isArray(plugins)) { + throw new TypeError('The `plugins` option should be an `Array`'); + } + + let data = await readFile(sourcePath); + data = await (plugins.length > 0 ? pPipe(...plugins)(data) : data); + + let destinationPath = destination ? path.join(destination, path.basename(sourcePath)) : undefined; + destinationPath = (fileType(data) && fileType(data).ext === 'webp') ? replaceExt(destinationPath, '.webp') : destinationPath; + + const returnValue = { + data, + sourcePath, + destinationPath + }; + + if (!destinationPath) { + return returnValue; + } + + await makeDir(path.dirname(returnValue.destinationPath)); + await writeFile(returnValue.destinationPath, returnValue.data); + + return returnValue; +}; + +module.exports = async (input, {glob = true, ...options} = {}) => { + if (!Array.isArray(input)) { + throw new TypeError(`Expected an \`Array\`, got \`${typeof input}\``); + } + + const filePaths = glob ? await globby(input, {onlyFiles: true}) : input; + + return Promise.all( + filePaths + .filter(filePath => junk.not(path.basename(filePath))) + .map(async filePath => { + try { + return await handleFile(filePath, options); + } catch (error) { + error.message = `Error occurred when handling file: ${input}\n\n${error.stack}`; + throw error; + } + }) + ); +}; + +module.exports.buffer = async (input, {plugins = []} = {}) => { + if (!Buffer.isBuffer(input)) { + throw new TypeError(`Expected a \`Buffer\`, got \`${typeof input}\``); + } + + if (plugins.length === 0) { + return input; + } + + return pPipe(...plugins)(input); +}; + +}).call(this,{"isBuffer":require("../is-buffer/index.js")}) +},{"../is-buffer/index.js":361,"file-type":109,"globby":170,"graceful-fs":354,"junk":375,"make-dir":378,"p-pipe":403,"path":404,"replace-ext":488,"util":523}],353:[function(require,module,exports){ +'use strict' + +module.exports = clone + +function clone (obj) { + if (obj === null || typeof obj !== 'object') + return obj + + if (obj instanceof Object) + var copy = { __proto__: obj.__proto__ } + else + var copy = Object.create(null) + + Object.getOwnPropertyNames(obj).forEach(function (key) { + Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key)) + }) + + return copy +} + +},{}],354:[function(require,module,exports){ +(function (process,global){ +var fs = require('fs') +var polyfills = require('./polyfills.js') +var legacy = require('./legacy-streams.js') +var clone = require('./clone.js') + +var util = require('util') + +/* istanbul ignore next - node 0.x polyfill */ +var gracefulQueue +var previousSymbol + +/* istanbul ignore else - node 0.x polyfill */ +if (typeof Symbol === 'function' && typeof Symbol.for === 'function') { + gracefulQueue = Symbol.for('graceful-fs.queue') + // This is used in testing by future versions + previousSymbol = Symbol.for('graceful-fs.previous') +} else { + gracefulQueue = '___graceful-fs.queue' + previousSymbol = '___graceful-fs.previous' +} + +function noop () {} + +var debug = noop +if (util.debuglog) + debug = util.debuglog('gfs4') +else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) + debug = function() { + var m = util.format.apply(util, arguments) + m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ') + console.error(m) + } + +// Once time initialization +if (!global[gracefulQueue]) { + // This queue can be shared by multiple loaded instances + var queue = [] + Object.defineProperty(global, gracefulQueue, { + get: function() { + return queue + } + }) + + // Patch fs.close/closeSync to shared queue version, because we need + // to retry() whenever a close happens *anywhere* in the program. + // This is essential when multiple graceful-fs instances are + // in play at the same time. + fs.close = (function (fs$close) { + function close (fd, cb) { + return fs$close.call(fs, fd, function (err) { + // This function uses the graceful-fs shared queue + if (!err) { + retry() + } + + if (typeof cb === 'function') + cb.apply(this, arguments) + }) + } + + Object.defineProperty(close, previousSymbol, { + value: fs$close + }) + return close + })(fs.close) + + fs.closeSync = (function (fs$closeSync) { + function closeSync (fd) { + // This function uses the graceful-fs shared queue + fs$closeSync.apply(fs, arguments) + retry() + } + + Object.defineProperty(closeSync, previousSymbol, { + value: fs$closeSync + }) + return closeSync + })(fs.closeSync) + + if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) { + process.on('exit', function() { + debug(global[gracefulQueue]) + require('assert').equal(global[gracefulQueue].length, 0) + }) + } +} + +module.exports = patch(clone(fs)) +if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) { + module.exports = patch(fs) + fs.__patched = true; +} + +function patch (fs) { + // Everything that references the open() function needs to be in here + polyfills(fs) + fs.gracefulify = patch + + fs.createReadStream = createReadStream + fs.createWriteStream = createWriteStream + var fs$readFile = fs.readFile + fs.readFile = readFile + function readFile (path, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$readFile(path, options, cb) + + function go$readFile (path, options, cb) { + return fs$readFile(path, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$readFile, [path, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$writeFile = fs.writeFile + fs.writeFile = writeFile + function writeFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$writeFile(path, data, options, cb) + + function go$writeFile (path, data, options, cb) { + return fs$writeFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$writeFile, [path, data, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$appendFile = fs.appendFile + if (fs$appendFile) + fs.appendFile = appendFile + function appendFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$appendFile(path, data, options, cb) + + function go$appendFile (path, data, options, cb) { + return fs$appendFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$appendFile, [path, data, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$readdir = fs.readdir + fs.readdir = readdir + function readdir (path, options, cb) { + var args = [path] + if (typeof options !== 'function') { + args.push(options) + } else { + cb = options + } + args.push(go$readdir$cb) + + return go$readdir(args) + + function go$readdir$cb (err, files) { + if (files && files.sort) + files.sort() + + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$readdir, [args]]) + + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + } + } + + function go$readdir (args) { + return fs$readdir.apply(fs, args) + } + + if (process.version.substr(0, 4) === 'v0.8') { + var legStreams = legacy(fs) + ReadStream = legStreams.ReadStream + WriteStream = legStreams.WriteStream + } + + var fs$ReadStream = fs.ReadStream + if (fs$ReadStream) { + ReadStream.prototype = Object.create(fs$ReadStream.prototype) + ReadStream.prototype.open = ReadStream$open + } + + var fs$WriteStream = fs.WriteStream + if (fs$WriteStream) { + WriteStream.prototype = Object.create(fs$WriteStream.prototype) + WriteStream.prototype.open = WriteStream$open + } + + Object.defineProperty(fs, 'ReadStream', { + get: function () { + return ReadStream + }, + set: function (val) { + ReadStream = val + }, + enumerable: true, + configurable: true + }) + Object.defineProperty(fs, 'WriteStream', { + get: function () { + return WriteStream + }, + set: function (val) { + WriteStream = val + }, + enumerable: true, + configurable: true + }) + + // legacy names + var FileReadStream = ReadStream + Object.defineProperty(fs, 'FileReadStream', { + get: function () { + return FileReadStream + }, + set: function (val) { + FileReadStream = val + }, + enumerable: true, + configurable: true + }) + var FileWriteStream = WriteStream + Object.defineProperty(fs, 'FileWriteStream', { + get: function () { + return FileWriteStream + }, + set: function (val) { + FileWriteStream = val + }, + enumerable: true, + configurable: true + }) + + function ReadStream (path, options) { + if (this instanceof ReadStream) + return fs$ReadStream.apply(this, arguments), this + else + return ReadStream.apply(Object.create(ReadStream.prototype), arguments) + } + + function ReadStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + if (that.autoClose) + that.destroy() + + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + that.read() + } + }) + } + + function WriteStream (path, options) { + if (this instanceof WriteStream) + return fs$WriteStream.apply(this, arguments), this + else + return WriteStream.apply(Object.create(WriteStream.prototype), arguments) + } + + function WriteStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + that.destroy() + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + } + }) + } + + function createReadStream (path, options) { + return new fs.ReadStream(path, options) + } + + function createWriteStream (path, options) { + return new fs.WriteStream(path, options) + } + + var fs$open = fs.open + fs.open = open + function open (path, flags, mode, cb) { + if (typeof mode === 'function') + cb = mode, mode = null + + return go$open(path, flags, mode, cb) + + function go$open (path, flags, mode, cb) { + return fs$open(path, flags, mode, function (err, fd) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$open, [path, flags, mode, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + return fs +} + +function enqueue (elem) { + debug('ENQUEUE', elem[0].name, elem[1]) + global[gracefulQueue].push(elem) +} + +function retry () { + var elem = global[gracefulQueue].shift() + if (elem) { + debug('RETRY', elem[0].name, elem[1]) + elem[0].apply(null, elem[1]) + } +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./clone.js":353,"./legacy-streams.js":355,"./polyfills.js":356,"_process":437,"assert":292,"fs":298,"util":523}],355:[function(require,module,exports){ +(function (process){ +var Stream = require('stream').Stream + +module.exports = legacy + +function legacy (fs) { + return { + ReadStream: ReadStream, + WriteStream: WriteStream + } + + function ReadStream (path, options) { + if (!(this instanceof ReadStream)) return new ReadStream(path, options); + + Stream.call(this); + + var self = this; + + this.path = path; + this.fd = null; + this.readable = true; + this.paused = false; + + this.flags = 'r'; + this.mode = 438; /*=0666*/ + this.bufferSize = 64 * 1024; + + options = options || {}; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } + + if (this.encoding) this.setEncoding(this.encoding); + + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.end === undefined) { + this.end = Infinity; + } else if ('number' !== typeof this.end) { + throw TypeError('end must be a Number'); + } + + if (this.start > this.end) { + throw new Error('start must be <= end'); + } + + this.pos = this.start; + } + + if (this.fd !== null) { + process.nextTick(function() { + self._read(); + }); + return; + } + + fs.open(this.path, this.flags, this.mode, function (err, fd) { + if (err) { + self.emit('error', err); + self.readable = false; + return; + } + + self.fd = fd; + self.emit('open', fd); + self._read(); + }) + } + + function WriteStream (path, options) { + if (!(this instanceof WriteStream)) return new WriteStream(path, options); + + Stream.call(this); + + this.path = path; + this.fd = null; + this.writable = true; + + this.flags = 'w'; + this.encoding = 'binary'; + this.mode = 438; /*=0666*/ + this.bytesWritten = 0; + + options = options || {}; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } + + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.start < 0) { + throw new Error('start must be >= zero'); + } + + this.pos = this.start; + } + + this.busy = false; + this._queue = []; + + if (this.fd === null) { + this._open = fs.open; + this._queue.push([this._open, this.path, this.flags, this.mode, undefined]); + this.flush(); + } + } +} + +}).call(this,require('_process')) +},{"_process":437,"stream":503}],356:[function(require,module,exports){ +(function (process){ +var constants = require('constants') + +var origCwd = process.cwd +var cwd = null + +var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform + +process.cwd = function() { + if (!cwd) + cwd = origCwd.call(process) + return cwd +} +try { + process.cwd() +} catch (er) {} + +var chdir = process.chdir +process.chdir = function(d) { + cwd = null + chdir.call(process, d) +} + +module.exports = patch + +function patch (fs) { + // (re-)implement some things that are known busted or missing. + + // lchmod, broken prior to 0.6.2 + // back-port the fix here. + if (constants.hasOwnProperty('O_SYMLINK') && + process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + patchLchmod(fs) + } + + // lutimes implementation, or no-op + if (!fs.lutimes) { + patchLutimes(fs) + } + + // https://github.com/isaacs/node-graceful-fs/issues/4 + // Chown should not fail on einval or eperm if non-root. + // It should not fail on enosys ever, as this just indicates + // that a fs doesn't support the intended operation. + + fs.chown = chownFix(fs.chown) + fs.fchown = chownFix(fs.fchown) + fs.lchown = chownFix(fs.lchown) + + fs.chmod = chmodFix(fs.chmod) + fs.fchmod = chmodFix(fs.fchmod) + fs.lchmod = chmodFix(fs.lchmod) + + fs.chownSync = chownFixSync(fs.chownSync) + fs.fchownSync = chownFixSync(fs.fchownSync) + fs.lchownSync = chownFixSync(fs.lchownSync) + + fs.chmodSync = chmodFixSync(fs.chmodSync) + fs.fchmodSync = chmodFixSync(fs.fchmodSync) + fs.lchmodSync = chmodFixSync(fs.lchmodSync) + + fs.stat = statFix(fs.stat) + fs.fstat = statFix(fs.fstat) + fs.lstat = statFix(fs.lstat) + + fs.statSync = statFixSync(fs.statSync) + fs.fstatSync = statFixSync(fs.fstatSync) + fs.lstatSync = statFixSync(fs.lstatSync) + + // if lchmod/lchown do not exist, then make them no-ops + if (!fs.lchmod) { + fs.lchmod = function (path, mode, cb) { + if (cb) process.nextTick(cb) + } + fs.lchmodSync = function () {} + } + if (!fs.lchown) { + fs.lchown = function (path, uid, gid, cb) { + if (cb) process.nextTick(cb) + } + fs.lchownSync = function () {} + } + + // on Windows, A/V software can lock the directory, causing this + // to fail with an EACCES or EPERM if the directory contains newly + // created files. Try again on failure, for up to 60 seconds. + + // Set the timeout this long because some Windows Anti-Virus, such as Parity + // bit9, may lock files for up to a minute, causing npm package install + // failures. Also, take care to yield the scheduler. Windows scheduling gives + // CPU to a busy looping process, which can cause the program causing the lock + // contention to be starved of CPU by node, so the contention doesn't resolve. + if (platform === "win32") { + fs.rename = (function (fs$rename) { return function (from, to, cb) { + var start = Date.now() + var backoff = 0; + fs$rename(from, to, function CB (er) { + if (er + && (er.code === "EACCES" || er.code === "EPERM") + && Date.now() - start < 60000) { + setTimeout(function() { + fs.stat(to, function (stater, st) { + if (stater && stater.code === "ENOENT") + fs$rename(from, to, CB); + else + cb(er) + }) + }, backoff) + if (backoff < 100) + backoff += 10; + return; + } + if (cb) cb(er) + }) + }})(fs.rename) + } + + // if read() returns EAGAIN, then just try it again. + fs.read = (function (fs$read) { + function read (fd, buffer, offset, length, position, callback_) { + var callback + if (callback_ && typeof callback_ === 'function') { + var eagCounter = 0 + callback = function (er, _, __) { + if (er && er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + } + callback_.apply(this, arguments) + } + } + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + } + + // This ensures `util.promisify` works as it does for native `fs.read`. + read.__proto__ = fs$read + return read + })(fs.read) + + fs.readSync = (function (fs$readSync) { return function (fd, buffer, offset, length, position) { + var eagCounter = 0 + while (true) { + try { + return fs$readSync.call(fs, fd, buffer, offset, length, position) + } catch (er) { + if (er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + continue + } + throw er + } + } + }})(fs.readSync) + + function patchLchmod (fs) { + fs.lchmod = function (path, mode, callback) { + fs.open( path + , constants.O_WRONLY | constants.O_SYMLINK + , mode + , function (err, fd) { + if (err) { + if (callback) callback(err) + return + } + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + fs.fchmod(fd, mode, function (err) { + fs.close(fd, function(err2) { + if (callback) callback(err || err2) + }) + }) + }) + } + + fs.lchmodSync = function (path, mode) { + var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode) + + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + var threw = true + var ret + try { + ret = fs.fchmodSync(fd, mode) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } + } + + function patchLutimes (fs) { + if (constants.hasOwnProperty("O_SYMLINK")) { + fs.lutimes = function (path, at, mt, cb) { + fs.open(path, constants.O_SYMLINK, function (er, fd) { + if (er) { + if (cb) cb(er) + return + } + fs.futimes(fd, at, mt, function (er) { + fs.close(fd, function (er2) { + if (cb) cb(er || er2) + }) + }) + }) + } + + fs.lutimesSync = function (path, at, mt) { + var fd = fs.openSync(path, constants.O_SYMLINK) + var ret + var threw = true + try { + ret = fs.futimesSync(fd, at, mt) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } + + } else { + fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) } + fs.lutimesSync = function () {} + } + } + + function chmodFix (orig) { + if (!orig) return orig + return function (target, mode, cb) { + return orig.call(fs, target, mode, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } + } + + function chmodFixSync (orig) { + if (!orig) return orig + return function (target, mode) { + try { + return orig.call(fs, target, mode) + } catch (er) { + if (!chownErOk(er)) throw er + } + } + } + + + function chownFix (orig) { + if (!orig) return orig + return function (target, uid, gid, cb) { + return orig.call(fs, target, uid, gid, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } + } + + function chownFixSync (orig) { + if (!orig) return orig + return function (target, uid, gid) { + try { + return orig.call(fs, target, uid, gid) + } catch (er) { + if (!chownErOk(er)) throw er + } + } + } + + function statFix (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } + function callback (er, stats) { + if (stats) { + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + } + if (cb) cb.apply(this, arguments) + } + return options ? orig.call(fs, target, options, callback) + : orig.call(fs, target, callback) + } + } + + function statFixSync (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target, options) { + var stats = options ? orig.call(fs, target, options) + : orig.call(fs, target) + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + return stats; + } + } + + // ENOSYS means that the fs doesn't support the op. Just ignore + // that, because it doesn't matter. + // + // if there's no getuid, or if getuid() is something other + // than 0, and the error is EINVAL or EPERM, then just ignore + // it. + // + // This specific case is a silent failure in cp, install, tar, + // and most other unix tools that manage permissions. + // + // When running as root, or if other types of errors are + // encountered, then it's strict. + function chownErOk (er) { + if (!er) + return true + + if (er.code === "ENOSYS") + return true + + var nonroot = !process.getuid || process.getuid() !== 0 + if (nonroot) { + if (er.code === "EINVAL" || er.code === "EPERM") + return true + } + + return false + } +} + +}).call(this,require('_process')) +},{"_process":437,"constants":39}],357:[function(require,module,exports){ +'use strict'; +const lazy = (mod, fn, id) => mod === undefined ? fn(id) : mod; + +module.exports = fn => { + return id => { + let mod; + + const handler = { + get: (target, property) => { + mod = lazy(mod, fn, id); + return Reflect.get(mod, property); + }, + apply: (target, thisArg, argumentsList) => { + mod = lazy(mod, fn, id); + return Reflect.apply(mod, thisArg, argumentsList); + }, + construct: (target, argumentsList) => { + mod = lazy(mod, fn, id); + return Reflect.construct(mod, argumentsList); + } + }; + + // eslint-disable-next-line prefer-arrow-callback + return new Proxy(function () {}, handler); + }; +}; + +},{}],358:[function(require,module,exports){ +(function (process){ +var wrappy = require('wrappy') +var reqs = Object.create(null) +var once = require('once') + +module.exports = wrappy(inflight) + +function inflight (key, cb) { + if (reqs[key]) { + reqs[key].push(cb) + return null + } else { + reqs[key] = [cb] + return makeres(key) + } +} + +function makeres (key) { + return once(function RES () { + var cbs = reqs[key] + var len = cbs.length + var args = slice(arguments) + + // XXX It's somewhat ambiguous whether a new callback added in this + // pass should be queued for later execution if something in the + // list of callbacks throws, or if it should just be discarded. + // However, it's such an edge case that it hardly matters, and either + // choice is likely as surprising as the other. + // As it happens, we do go ahead and schedule it for later execution. + try { + for (var i = 0; i < len; i++) { + cbs[i].apply(null, args) + } + } finally { + if (cbs.length > len) { + // added more in the interim. + // de-zalgo, just in case, but don't call again. + cbs.splice(0, len) + process.nextTick(function () { + RES.apply(null, args) + }) + } else { + delete reqs[key] + } + } + }) +} + +function slice (args) { + var length = args.length + var array = [] + + for (var i = 0; i < length; i++) array[i] = args[i] + return array +} + +}).call(this,require('_process')) +},{"_process":437,"once":399,"wrappy":531}],359:[function(require,module,exports){ +arguments[4][293][0].apply(exports,arguments) +},{"dup":293}],360:[function(require,module,exports){ +"use strict" + +function iota(n) { + var result = new Array(n) + for(var i=0; i + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} + +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} + +},{}],362:[function(require,module,exports){ +/*! + * is-extglob + * + * Copyright (c) 2014-2016, Jon Schlinkert. + * Licensed under the MIT License. + */ + +module.exports = function isExtglob(str) { + if (typeof str !== 'string' || str === '') { + return false; + } + + var match; + while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) { + if (match[2]) return true; + str = str.slice(match.index + match[0].length); + } + + return false; +}; + +},{}],363:[function(require,module,exports){ +/*! + * is-glob + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +var isExtglob = require('is-extglob'); +var chars = { '{': '}', '(': ')', '[': ']'}; +var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; +var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; + +module.exports = function isGlob(str, options) { + if (typeof str !== 'string' || str === '') { + return false; + } + + if (isExtglob(str)) { + return true; + } + + var regex = strictRegex; + var match; + + // optionally relax regex + if (options && options.strict === false) { + regex = relaxedRegex; + } + + while ((match = regex.exec(str))) { + if (match[2]) return true; + var idx = match.index + match[0].length; + + // if an open bracket/brace/paren is escaped, + // set the index to the next closing character + var open = match[1]; + var close = open ? chars[open] : null; + if (open && close) { + var n = str.indexOf(close, idx); + if (n !== -1) { + idx = n + 1; + } + } + + str = str.slice(idx); + } + return false; +}; + +},{"is-extglob":362}],364:[function(require,module,exports){ +'use strict'; +module.exports = buffer => { + if (!buffer || buffer.length < 3) { + return false; + } + + return buffer[0] === 255 && + buffer[1] === 216 && + buffer[2] === 255; +}; + +},{}],365:[function(require,module,exports){ +'use strict'; + +module.exports = buffer => { + if (!buffer || buffer.length < 8) { + return false; + } + + return ( + buffer[0] === 0x89 && + buffer[1] === 0x50 && + buffer[2] === 0x4E && + buffer[3] === 0x47 && + buffer[4] === 0x0D && + buffer[5] === 0x0A && + buffer[6] === 0x1A && + buffer[7] === 0x0A + ); +}; + +},{}],366:[function(require,module,exports){ +'use strict'; + +var isStream = module.exports = function (stream) { + return stream !== null && typeof stream === 'object' && typeof stream.pipe === 'function'; +}; + +isStream.writable = function (stream) { + return isStream(stream) && stream.writable !== false && typeof stream._write === 'function' && typeof stream._writableState === 'object'; +}; + +isStream.readable = function (stream) { + return isStream(stream) && stream.readable !== false && typeof stream._read === 'function' && typeof stream._readableState === 'object'; +}; + +isStream.duplex = function (stream) { + return isStream.writable(stream) && isStream.readable(stream); +}; + +isStream.transform = function (stream) { + return isStream.duplex(stream) && typeof stream._transform === 'function' && typeof stream._transformState === 'object'; +}; + +},{}],367:[function(require,module,exports){ +module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; +}; + +},{}],368:[function(require,module,exports){ +(function (process,global){ +var fs = require('fs') +var core +if (process.platform === 'win32' || global.TESTING_WINDOWS) { + core = require('./windows.js') +} else { + core = require('./mode.js') +} + +module.exports = isexe +isexe.sync = sync + +function isexe (path, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} + } + + if (!cb) { + if (typeof Promise !== 'function') { + throw new TypeError('callback not provided') + } + + return new Promise(function (resolve, reject) { + isexe(path, options || {}, function (er, is) { + if (er) { + reject(er) + } else { + resolve(is) + } + }) + }) + } + + core(path, options || {}, function (er, is) { + // ignore EACCES because that just means we aren't allowed to run it + if (er) { + if (er.code === 'EACCES' || options && options.ignoreErrors) { + er = null + is = false + } + } + cb(er, is) + }) +} + +function sync (path, options) { + // my kingdom for a filtered catch + try { + return core.sync(path, options || {}) + } catch (er) { + if (options && options.ignoreErrors || er.code === 'EACCES') { + return false + } else { + throw er + } + } +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./mode.js":369,"./windows.js":370,"_process":437,"fs":298}],369:[function(require,module,exports){ +(function (process){ +module.exports = isexe +isexe.sync = sync + +var fs = require('fs') + +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, options)) + }) +} + +function sync (path, options) { + return checkStat(fs.statSync(path), options) +} + +function checkStat (stat, options) { + return stat.isFile() && checkMode(stat, options) +} + +function checkMode (stat, options) { + var mod = stat.mode + var uid = stat.uid + var gid = stat.gid + + var myUid = options.uid !== undefined ? + options.uid : process.getuid && process.getuid() + var myGid = options.gid !== undefined ? + options.gid : process.getgid && process.getgid() + + var u = parseInt('100', 8) + var g = parseInt('010', 8) + var o = parseInt('001', 8) + var ug = u | g + + var ret = (mod & o) || + (mod & g) && gid === myGid || + (mod & u) && uid === myUid || + (mod & ug) && myUid === 0 + + return ret +} + +}).call(this,require('_process')) +},{"_process":437,"fs":298}],370:[function(require,module,exports){ +(function (process){ +module.exports = isexe +isexe.sync = sync + +var fs = require('fs') + +function checkPathExt (path, options) { + var pathext = options.pathExt !== undefined ? + options.pathExt : process.env.PATHEXT + + if (!pathext) { + return true + } + + pathext = pathext.split(';') + if (pathext.indexOf('') !== -1) { + return true + } + for (var i = 0; i < pathext.length; i++) { + var p = pathext[i].toLowerCase() + if (p && path.substr(-p.length).toLowerCase() === p) { + return true + } + } + return false +} + +function checkStat (stat, path, options) { + if (!stat.isSymbolicLink() && !stat.isFile()) { + return false + } + return checkPathExt(path, options) +} + +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, path, options)) + }) +} + +function sync (path, options) { + return checkStat(fs.statSync(path), path, options) +} + +}).call(this,require('_process')) +},{"_process":437,"fs":298}],371:[function(require,module,exports){ +arguments[4][323][0].apply(exports,arguments) +},{"./lib/decoder":372,"./lib/encoder":373,"dup":323}],372:[function(require,module,exports){ +(function (Buffer){ +/* -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* + Copyright 2011 notmasteryet + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// - The JPEG specification can be found in the ITU CCITT Recommendation T.81 +// (www.w3.org/Graphics/JPEG/itu-t81.pdf) +// - The JFIF specification can be found in the JPEG File Interchange Format +// (www.w3.org/Graphics/JPEG/jfif3.pdf) +// - The Adobe Application-Specific JPEG markers in the Supporting the DCT Filters +// in PostScript Level 2, Technical Note #5116 +// (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf) + +var JpegImage = (function jpegImage() { + "use strict"; + var dctZigZag = new Int32Array([ + 0, + 1, 8, + 16, 9, 2, + 3, 10, 17, 24, + 32, 25, 18, 11, 4, + 5, 12, 19, 26, 33, 40, + 48, 41, 34, 27, 20, 13, 6, + 7, 14, 21, 28, 35, 42, 49, 56, + 57, 50, 43, 36, 29, 22, 15, + 23, 30, 37, 44, 51, 58, + 59, 52, 45, 38, 31, + 39, 46, 53, 60, + 61, 54, 47, + 55, 62, + 63 + ]); + + var dctCos1 = 4017 // cos(pi/16) + var dctSin1 = 799 // sin(pi/16) + var dctCos3 = 3406 // cos(3*pi/16) + var dctSin3 = 2276 // sin(3*pi/16) + var dctCos6 = 1567 // cos(6*pi/16) + var dctSin6 = 3784 // sin(6*pi/16) + var dctSqrt2 = 5793 // sqrt(2) + var dctSqrt1d2 = 2896 // sqrt(2) / 2 + + function constructor() { + } + + function buildHuffmanTable(codeLengths, values) { + var k = 0, code = [], i, j, length = 16; + while (length > 0 && !codeLengths[length - 1]) + length--; + code.push({children: [], index: 0}); + var p = code[0], q; + for (i = 0; i < length; i++) { + for (j = 0; j < codeLengths[i]; j++) { + p = code.pop(); + p.children[p.index] = values[k]; + while (p.index > 0) { + if (code.length === 0) + throw new Error('Could not recreate Huffman Table'); + p = code.pop(); + } + p.index++; + code.push(p); + while (code.length <= i) { + code.push(q = {children: [], index: 0}); + p.children[p.index] = q.children; + p = q; + } + k++; + } + if (i + 1 < length) { + // p here points to last code + code.push(q = {children: [], index: 0}); + p.children[p.index] = q.children; + p = q; + } + } + return code[0].children; + } + + function decodeScan(data, offset, + frame, components, resetInterval, + spectralStart, spectralEnd, + successivePrev, successive, opts) { + var precision = frame.precision; + var samplesPerLine = frame.samplesPerLine; + var scanLines = frame.scanLines; + var mcusPerLine = frame.mcusPerLine; + var progressive = frame.progressive; + var maxH = frame.maxH, maxV = frame.maxV; + + var startOffset = offset, bitsData = 0, bitsCount = 0; + function readBit() { + if (bitsCount > 0) { + bitsCount--; + return (bitsData >> bitsCount) & 1; + } + bitsData = data[offset++]; + if (bitsData == 0xFF) { + var nextByte = data[offset++]; + if (nextByte) { + throw new Error("unexpected marker: " + ((bitsData << 8) | nextByte).toString(16)); + } + // unstuff 0 + } + bitsCount = 7; + return bitsData >>> 7; + } + function decodeHuffman(tree) { + var node = tree, bit; + while ((bit = readBit()) !== null) { + node = node[bit]; + if (typeof node === 'number') + return node; + if (typeof node !== 'object') + throw new Error("invalid huffman sequence"); + } + return null; + } + function receive(length) { + var n = 0; + while (length > 0) { + var bit = readBit(); + if (bit === null) return; + n = (n << 1) | bit; + length--; + } + return n; + } + function receiveAndExtend(length) { + var n = receive(length); + if (n >= 1 << (length - 1)) + return n; + return n + (-1 << length) + 1; + } + function decodeBaseline(component, zz) { + var t = decodeHuffman(component.huffmanTableDC); + var diff = t === 0 ? 0 : receiveAndExtend(t); + zz[0]= (component.pred += diff); + var k = 1; + while (k < 64) { + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) + break; + k += 16; + continue; + } + k += r; + var z = dctZigZag[k]; + zz[z] = receiveAndExtend(s); + k++; + } + } + function decodeDCFirst(component, zz) { + var t = decodeHuffman(component.huffmanTableDC); + var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive); + zz[0] = (component.pred += diff); + } + function decodeDCSuccessive(component, zz) { + zz[0] |= readBit() << successive; + } + var eobrun = 0; + function decodeACFirst(component, zz) { + if (eobrun > 0) { + eobrun--; + return; + } + var k = spectralStart, e = spectralEnd; + while (k <= e) { + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r) - 1; + break; + } + k += 16; + continue; + } + k += r; + var z = dctZigZag[k]; + zz[z] = receiveAndExtend(s) * (1 << successive); + k++; + } + } + var successiveACState = 0, successiveACNextValue; + function decodeACSuccessive(component, zz) { + var k = spectralStart, e = spectralEnd, r = 0; + while (k <= e) { + var z = dctZigZag[k]; + var direction = zz[z] < 0 ? -1 : 1; + switch (successiveACState) { + case 0: // initial state + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r); + successiveACState = 4; + } else { + r = 16; + successiveACState = 1; + } + } else { + if (s !== 1) + throw new Error("invalid ACn encoding"); + successiveACNextValue = receiveAndExtend(s); + successiveACState = r ? 2 : 3; + } + continue; + case 1: // skipping r zero items + case 2: + if (zz[z]) + zz[z] += (readBit() << successive) * direction; + else { + r--; + if (r === 0) + successiveACState = successiveACState == 2 ? 3 : 0; + } + break; + case 3: // set value for a zero item + if (zz[z]) + zz[z] += (readBit() << successive) * direction; + else { + zz[z] = successiveACNextValue << successive; + successiveACState = 0; + } + break; + case 4: // eob + if (zz[z]) + zz[z] += (readBit() << successive) * direction; + break; + } + k++; + } + if (successiveACState === 4) { + eobrun--; + if (eobrun === 0) + successiveACState = 0; + } + } + function decodeMcu(component, decode, mcu, row, col) { + var mcuRow = (mcu / mcusPerLine) | 0; + var mcuCol = mcu % mcusPerLine; + var blockRow = mcuRow * component.v + row; + var blockCol = mcuCol * component.h + col; + // If the block is missing and we're in tolerant mode, just skip it. + if (component.blocks[blockRow] === undefined && opts.tolerantDecoding) + return; + decode(component, component.blocks[blockRow][blockCol]); + } + function decodeBlock(component, decode, mcu) { + var blockRow = (mcu / component.blocksPerLine) | 0; + var blockCol = mcu % component.blocksPerLine; + // If the block is missing and we're in tolerant mode, just skip it. + if (component.blocks[blockRow] === undefined && opts.tolerantDecoding) + return; + decode(component, component.blocks[blockRow][blockCol]); + } + + var componentsLength = components.length; + var component, i, j, k, n; + var decodeFn; + if (progressive) { + if (spectralStart === 0) + decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive; + else + decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive; + } else { + decodeFn = decodeBaseline; + } + + var mcu = 0, marker; + var mcuExpected; + if (componentsLength == 1) { + mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn; + } else { + mcuExpected = mcusPerLine * frame.mcusPerColumn; + } + if (!resetInterval) resetInterval = mcuExpected; + + var h, v; + while (mcu < mcuExpected) { + // reset interval stuff + for (i = 0; i < componentsLength; i++) + components[i].pred = 0; + eobrun = 0; + + if (componentsLength == 1) { + component = components[0]; + for (n = 0; n < resetInterval; n++) { + decodeBlock(component, decodeFn, mcu); + mcu++; + } + } else { + for (n = 0; n < resetInterval; n++) { + for (i = 0; i < componentsLength; i++) { + component = components[i]; + h = component.h; + v = component.v; + for (j = 0; j < v; j++) { + for (k = 0; k < h; k++) { + decodeMcu(component, decodeFn, mcu, j, k); + } + } + } + mcu++; + + // If we've reached our expected MCU's, stop decoding + if (mcu === mcuExpected) break; + } + } + + if (mcu === mcuExpected) { + // Skip trailing bytes at the end of the scan - until we reach the next marker + do { + if (data[offset] === 0xFF) { + if (data[offset + 1] !== 0x00) { + break; + } + } + offset += 1; + } while (offset < data.length - 2); + } + + // find marker + bitsCount = 0; + marker = (data[offset] << 8) | data[offset + 1]; + if (marker < 0xFF00) { + throw new Error("marker was not found"); + } + + if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx + offset += 2; + } + else + break; + } + + return offset - startOffset; + } + + function buildComponentData(frame, component) { + var lines = []; + var blocksPerLine = component.blocksPerLine; + var blocksPerColumn = component.blocksPerColumn; + var samplesPerLine = blocksPerLine << 3; + // Only 1 used per invocation of this function and garbage collected after invocation, so no need to account for its memory footprint. + var R = new Int32Array(64), r = new Uint8Array(64); + + // A port of poppler's IDCT method which in turn is taken from: + // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, + // "Practical Fast 1-D DCT Algorithms with 11 Multiplications", + // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, + // 988-991. + function quantizeAndInverse(zz, dataOut, dataIn) { + var qt = component.quantizationTable; + var v0, v1, v2, v3, v4, v5, v6, v7, t; + var p = dataIn; + var i; + + // dequant + for (i = 0; i < 64; i++) + p[i] = zz[i] * qt[i]; + + // inverse DCT on rows + for (i = 0; i < 8; ++i) { + var row = 8 * i; + + // check for all-zero AC coefficients + if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 && + p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 && + p[7 + row] == 0) { + t = (dctSqrt2 * p[0 + row] + 512) >> 10; + p[0 + row] = t; + p[1 + row] = t; + p[2 + row] = t; + p[3 + row] = t; + p[4 + row] = t; + p[5 + row] = t; + p[6 + row] = t; + p[7 + row] = t; + continue; + } + + // stage 4 + v0 = (dctSqrt2 * p[0 + row] + 128) >> 8; + v1 = (dctSqrt2 * p[4 + row] + 128) >> 8; + v2 = p[2 + row]; + v3 = p[6 + row]; + v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8; + v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8; + v5 = p[3 + row] << 4; + v6 = p[5 + row] << 4; + + // stage 3 + t = (v0 - v1+ 1) >> 1; + v0 = (v0 + v1 + 1) >> 1; + v1 = t; + t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; + v3 = t; + t = (v4 - v6 + 1) >> 1; + v4 = (v4 + v6 + 1) >> 1; + v6 = t; + t = (v7 + v5 + 1) >> 1; + v5 = (v7 - v5 + 1) >> 1; + v7 = t; + + // stage 2 + t = (v0 - v3 + 1) >> 1; + v0 = (v0 + v3 + 1) >> 1; + v3 = t; + t = (v1 - v2 + 1) >> 1; + v1 = (v1 + v2 + 1) >> 1; + v2 = t; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + p[0 + row] = v0 + v7; + p[7 + row] = v0 - v7; + p[1 + row] = v1 + v6; + p[6 + row] = v1 - v6; + p[2 + row] = v2 + v5; + p[5 + row] = v2 - v5; + p[3 + row] = v3 + v4; + p[4 + row] = v3 - v4; + } + + // inverse DCT on columns + for (i = 0; i < 8; ++i) { + var col = i; + + // check for all-zero AC coefficients + if (p[1*8 + col] == 0 && p[2*8 + col] == 0 && p[3*8 + col] == 0 && + p[4*8 + col] == 0 && p[5*8 + col] == 0 && p[6*8 + col] == 0 && + p[7*8 + col] == 0) { + t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14; + p[0*8 + col] = t; + p[1*8 + col] = t; + p[2*8 + col] = t; + p[3*8 + col] = t; + p[4*8 + col] = t; + p[5*8 + col] = t; + p[6*8 + col] = t; + p[7*8 + col] = t; + continue; + } + + // stage 4 + v0 = (dctSqrt2 * p[0*8 + col] + 2048) >> 12; + v1 = (dctSqrt2 * p[4*8 + col] + 2048) >> 12; + v2 = p[2*8 + col]; + v3 = p[6*8 + col]; + v4 = (dctSqrt1d2 * (p[1*8 + col] - p[7*8 + col]) + 2048) >> 12; + v7 = (dctSqrt1d2 * (p[1*8 + col] + p[7*8 + col]) + 2048) >> 12; + v5 = p[3*8 + col]; + v6 = p[5*8 + col]; + + // stage 3 + t = (v0 - v1 + 1) >> 1; + v0 = (v0 + v1 + 1) >> 1; + v1 = t; + t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; + v3 = t; + t = (v4 - v6 + 1) >> 1; + v4 = (v4 + v6 + 1) >> 1; + v6 = t; + t = (v7 + v5 + 1) >> 1; + v5 = (v7 - v5 + 1) >> 1; + v7 = t; + + // stage 2 + t = (v0 - v3 + 1) >> 1; + v0 = (v0 + v3 + 1) >> 1; + v3 = t; + t = (v1 - v2 + 1) >> 1; + v1 = (v1 + v2 + 1) >> 1; + v2 = t; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + p[0*8 + col] = v0 + v7; + p[7*8 + col] = v0 - v7; + p[1*8 + col] = v1 + v6; + p[6*8 + col] = v1 - v6; + p[2*8 + col] = v2 + v5; + p[5*8 + col] = v2 - v5; + p[3*8 + col] = v3 + v4; + p[4*8 + col] = v3 - v4; + } + + // convert to 8-bit integers + for (i = 0; i < 64; ++i) { + var sample = 128 + ((p[i] + 8) >> 4); + dataOut[i] = sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample; + } + } + + requestMemoryAllocation(samplesPerLine * blocksPerColumn * 8); + + var i, j; + for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) { + var scanLine = blockRow << 3; + for (i = 0; i < 8; i++) + lines.push(new Uint8Array(samplesPerLine)); + for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) { + quantizeAndInverse(component.blocks[blockRow][blockCol], r, R); + + var offset = 0, sample = blockCol << 3; + for (j = 0; j < 8; j++) { + var line = lines[scanLine + j]; + for (i = 0; i < 8; i++) + line[sample + i] = r[offset++]; + } + } + } + return lines; + } + + function clampTo8bit(a) { + return a < 0 ? 0 : a > 255 ? 255 : a; + } + + constructor.prototype = { + load: function load(path) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", path, true); + xhr.responseType = "arraybuffer"; + xhr.onload = (function() { + // TODO catch parse error + var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer); + this.parse(data); + if (this.onload) + this.onload(); + }).bind(this); + xhr.send(null); + }, + parse: function parse(data) { + var maxResolutionInPixels = this.opts.maxResolutionInMP * 1000 * 1000; + var offset = 0, length = data.length; + function readUint16() { + var value = (data[offset] << 8) | data[offset + 1]; + offset += 2; + return value; + } + function readDataBlock() { + var length = readUint16(); + var array = data.subarray(offset, offset + length - 2); + offset += array.length; + return array; + } + function prepareComponents(frame) { + var maxH = 0, maxV = 0; + var component, componentId; + for (componentId in frame.components) { + if (frame.components.hasOwnProperty(componentId)) { + component = frame.components[componentId]; + if (maxH < component.h) maxH = component.h; + if (maxV < component.v) maxV = component.v; + } + } + var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / maxH); + var mcusPerColumn = Math.ceil(frame.scanLines / 8 / maxV); + for (componentId in frame.components) { + if (frame.components.hasOwnProperty(componentId)) { + component = frame.components[componentId]; + var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / maxH); + var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / maxV); + var blocksPerLineForMcu = mcusPerLine * component.h; + var blocksPerColumnForMcu = mcusPerColumn * component.v; + var blocksToAllocate = blocksPerColumnForMcu * blocksPerLineForMcu; + var blocks = []; + + // Each block is a Int32Array of length 64 (4 x 64 = 256 bytes) + requestMemoryAllocation(blocksToAllocate * 256); + + for (var i = 0; i < blocksPerColumnForMcu; i++) { + var row = []; + for (var j = 0; j < blocksPerLineForMcu; j++) + row.push(new Int32Array(64)); + blocks.push(row); + } + component.blocksPerLine = blocksPerLine; + component.blocksPerColumn = blocksPerColumn; + component.blocks = blocks; + } + } + frame.maxH = maxH; + frame.maxV = maxV; + frame.mcusPerLine = mcusPerLine; + frame.mcusPerColumn = mcusPerColumn; + } + var jfif = null; + var adobe = null; + var pixels = null; + var frame, resetInterval; + var quantizationTables = [], frames = []; + var huffmanTablesAC = [], huffmanTablesDC = []; + var fileMarker = readUint16(); + var malformedDataOffset = -1; + this.comments = []; + if (fileMarker != 0xFFD8) { // SOI (Start of Image) + throw new Error("SOI not found"); + } + + fileMarker = readUint16(); + while (fileMarker != 0xFFD9) { // EOI (End of image) + var i, j, l; + switch(fileMarker) { + case 0xFF00: break; + case 0xFFE0: // APP0 (Application Specific) + case 0xFFE1: // APP1 + case 0xFFE2: // APP2 + case 0xFFE3: // APP3 + case 0xFFE4: // APP4 + case 0xFFE5: // APP5 + case 0xFFE6: // APP6 + case 0xFFE7: // APP7 + case 0xFFE8: // APP8 + case 0xFFE9: // APP9 + case 0xFFEA: // APP10 + case 0xFFEB: // APP11 + case 0xFFEC: // APP12 + case 0xFFED: // APP13 + case 0xFFEE: // APP14 + case 0xFFEF: // APP15 + case 0xFFFE: // COM (Comment) + var appData = readDataBlock(); + + if (fileMarker === 0xFFFE) { + var comment = String.fromCharCode.apply(null, appData); + this.comments.push(comment); + } + + if (fileMarker === 0xFFE0) { + if (appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 && + appData[3] === 0x46 && appData[4] === 0) { // 'JFIF\x00' + jfif = { + version: { major: appData[5], minor: appData[6] }, + densityUnits: appData[7], + xDensity: (appData[8] << 8) | appData[9], + yDensity: (appData[10] << 8) | appData[11], + thumbWidth: appData[12], + thumbHeight: appData[13], + thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13]) + }; + } + } + // TODO APP1 - Exif + if (fileMarker === 0xFFE1) { + if (appData[0] === 0x45 && + appData[1] === 0x78 && + appData[2] === 0x69 && + appData[3] === 0x66 && + appData[4] === 0) { // 'EXIF\x00' + this.exifBuffer = appData.subarray(5, appData.length); + } + } + + if (fileMarker === 0xFFEE) { + if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F && + appData[3] === 0x62 && appData[4] === 0x65 && appData[5] === 0) { // 'Adobe\x00' + adobe = { + version: appData[6], + flags0: (appData[7] << 8) | appData[8], + flags1: (appData[9] << 8) | appData[10], + transformCode: appData[11] + }; + } + } + break; + + case 0xFFDB: // DQT (Define Quantization Tables) + var quantizationTablesLength = readUint16(); + var quantizationTablesEnd = quantizationTablesLength + offset - 2; + while (offset < quantizationTablesEnd) { + var quantizationTableSpec = data[offset++]; + requestMemoryAllocation(64 * 4); + var tableData = new Int32Array(64); + if ((quantizationTableSpec >> 4) === 0) { // 8 bit values + for (j = 0; j < 64; j++) { + var z = dctZigZag[j]; + tableData[z] = data[offset++]; + } + } else if ((quantizationTableSpec >> 4) === 1) { //16 bit + for (j = 0; j < 64; j++) { + var z = dctZigZag[j]; + tableData[z] = readUint16(); + } + } else + throw new Error("DQT: invalid table spec"); + quantizationTables[quantizationTableSpec & 15] = tableData; + } + break; + + case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT) + case 0xFFC1: // SOF1 (Start of Frame, Extended DCT) + case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT) + readUint16(); // skip data length + frame = {}; + frame.extended = (fileMarker === 0xFFC1); + frame.progressive = (fileMarker === 0xFFC2); + frame.precision = data[offset++]; + frame.scanLines = readUint16(); + frame.samplesPerLine = readUint16(); + frame.components = {}; + frame.componentsOrder = []; + + var pixelsInFrame = frame.scanLines * frame.samplesPerLine; + if (pixelsInFrame > maxResolutionInPixels) { + var exceededAmount = Math.ceil((pixelsInFrame - maxResolutionInPixels) / 1e6); + throw new Error(`maxResolutionInMP limit exceeded by ${exceededAmount}MP`); + } + + var componentsCount = data[offset++], componentId; + var maxH = 0, maxV = 0; + for (i = 0; i < componentsCount; i++) { + componentId = data[offset]; + var h = data[offset + 1] >> 4; + var v = data[offset + 1] & 15; + var qId = data[offset + 2]; + frame.componentsOrder.push(componentId); + frame.components[componentId] = { + h: h, + v: v, + quantizationIdx: qId + }; + offset += 3; + } + prepareComponents(frame); + frames.push(frame); + break; + + case 0xFFC4: // DHT (Define Huffman Tables) + var huffmanLength = readUint16(); + for (i = 2; i < huffmanLength;) { + var huffmanTableSpec = data[offset++]; + var codeLengths = new Uint8Array(16); + var codeLengthSum = 0; + for (j = 0; j < 16; j++, offset++) { + codeLengthSum += (codeLengths[j] = data[offset]); + } + requestMemoryAllocation(16 + codeLengthSum); + var huffmanValues = new Uint8Array(codeLengthSum); + for (j = 0; j < codeLengthSum; j++, offset++) + huffmanValues[j] = data[offset]; + i += 17 + codeLengthSum; + + ((huffmanTableSpec >> 4) === 0 ? + huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = + buildHuffmanTable(codeLengths, huffmanValues); + } + break; + + case 0xFFDD: // DRI (Define Restart Interval) + readUint16(); // skip data length + resetInterval = readUint16(); + break; + + case 0xFFDC: // Number of Lines marker + readUint16() // skip data length + readUint16() // Ignore this data since it represents the image height + break; + + case 0xFFDA: // SOS (Start of Scan) + var scanLength = readUint16(); + var selectorsCount = data[offset++]; + var components = [], component; + for (i = 0; i < selectorsCount; i++) { + component = frame.components[data[offset++]]; + var tableSpec = data[offset++]; + component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; + component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; + components.push(component); + } + var spectralStart = data[offset++]; + var spectralEnd = data[offset++]; + var successiveApproximation = data[offset++]; + var processed = decodeScan(data, offset, + frame, components, resetInterval, + spectralStart, spectralEnd, + successiveApproximation >> 4, successiveApproximation & 15, this.opts); + offset += processed; + break; + + case 0xFFFF: // Fill bytes + if (data[offset] !== 0xFF) { // Avoid skipping a valid marker. + offset--; + } + break; + default: + if (data[offset - 3] == 0xFF && + data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) { + // could be incorrect encoding -- last 0xFF byte of the previous + // block was eaten by the encoder + offset -= 3; + break; + } + else if (fileMarker === 0xE0 || fileMarker == 0xE1) { + // Recover from malformed APP1 markers popular in some phone models. + // See https://github.com/eugeneware/jpeg-js/issues/82 + if (malformedDataOffset !== -1) { + throw new Error(`first unknown JPEG marker at offset ${malformedDataOffset.toString(16)}, second unknown JPEG marker ${fileMarker.toString(16)} at offset ${(offset - 1).toString(16)}`); + } + malformedDataOffset = offset - 1; + const nextOffset = readUint16(); + if (data[offset + nextOffset - 2] === 0xFF) { + offset += nextOffset - 2; + break; + } + } + throw new Error("unknown JPEG marker " + fileMarker.toString(16)); + } + fileMarker = readUint16(); + } + if (frames.length != 1) + throw new Error("only single frame JPEGs supported"); + + // set each frame's components quantization table + for (var i = 0; i < frames.length; i++) { + var cp = frames[i].components; + for (var j in cp) { + cp[j].quantizationTable = quantizationTables[cp[j].quantizationIdx]; + delete cp[j].quantizationIdx; + } + } + + this.width = frame.samplesPerLine; + this.height = frame.scanLines; + this.jfif = jfif; + this.adobe = adobe; + this.components = []; + for (var i = 0; i < frame.componentsOrder.length; i++) { + var component = frame.components[frame.componentsOrder[i]]; + this.components.push({ + lines: buildComponentData(frame, component), + scaleX: component.h / frame.maxH, + scaleY: component.v / frame.maxV + }); + } + }, + getData: function getData(width, height) { + var scaleX = this.width / width, scaleY = this.height / height; + + var component1, component2, component3, component4; + var component1Line, component2Line, component3Line, component4Line; + var x, y; + var offset = 0; + var Y, Cb, Cr, K, C, M, Ye, R, G, B; + var colorTransform; + var dataLength = width * height * this.components.length; + requestMemoryAllocation(dataLength); + var data = new Uint8Array(dataLength); + switch (this.components.length) { + case 1: + component1 = this.components[0]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)]; + for (x = 0; x < width; x++) { + Y = component1Line[0 | (x * component1.scaleX * scaleX)]; + + data[offset++] = Y; + } + } + break; + case 2: + // PDF might compress two component data in custom colorspace + component1 = this.components[0]; + component2 = this.components[1]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)]; + component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)]; + for (x = 0; x < width; x++) { + Y = component1Line[0 | (x * component1.scaleX * scaleX)]; + data[offset++] = Y; + Y = component2Line[0 | (x * component2.scaleX * scaleX)]; + data[offset++] = Y; + } + } + break; + case 3: + // The default transform for three components is true + colorTransform = true; + // The adobe transform marker overrides any previous setting + if (this.adobe && this.adobe.transformCode) + colorTransform = true; + else if (typeof this.opts.colorTransform !== 'undefined') + colorTransform = !!this.opts.colorTransform; + + component1 = this.components[0]; + component2 = this.components[1]; + component3 = this.components[2]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)]; + component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)]; + component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)]; + for (x = 0; x < width; x++) { + if (!colorTransform) { + R = component1Line[0 | (x * component1.scaleX * scaleX)]; + G = component2Line[0 | (x * component2.scaleX * scaleX)]; + B = component3Line[0 | (x * component3.scaleX * scaleX)]; + } else { + Y = component1Line[0 | (x * component1.scaleX * scaleX)]; + Cb = component2Line[0 | (x * component2.scaleX * scaleX)]; + Cr = component3Line[0 | (x * component3.scaleX * scaleX)]; + + R = clampTo8bit(Y + 1.402 * (Cr - 128)); + G = clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128)); + B = clampTo8bit(Y + 1.772 * (Cb - 128)); + } + + data[offset++] = R; + data[offset++] = G; + data[offset++] = B; + } + } + break; + case 4: + if (!this.adobe) + throw new Error('Unsupported color mode (4 components)'); + // The default transform for four components is false + colorTransform = false; + // The adobe transform marker overrides any previous setting + if (this.adobe && this.adobe.transformCode) + colorTransform = true; + else if (typeof this.opts.colorTransform !== 'undefined') + colorTransform = !!this.opts.colorTransform; + + component1 = this.components[0]; + component2 = this.components[1]; + component3 = this.components[2]; + component4 = this.components[3]; + for (y = 0; y < height; y++) { + component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)]; + component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)]; + component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)]; + component4Line = component4.lines[0 | (y * component4.scaleY * scaleY)]; + for (x = 0; x < width; x++) { + if (!colorTransform) { + C = component1Line[0 | (x * component1.scaleX * scaleX)]; + M = component2Line[0 | (x * component2.scaleX * scaleX)]; + Ye = component3Line[0 | (x * component3.scaleX * scaleX)]; + K = component4Line[0 | (x * component4.scaleX * scaleX)]; + } else { + Y = component1Line[0 | (x * component1.scaleX * scaleX)]; + Cb = component2Line[0 | (x * component2.scaleX * scaleX)]; + Cr = component3Line[0 | (x * component3.scaleX * scaleX)]; + K = component4Line[0 | (x * component4.scaleX * scaleX)]; + + C = 255 - clampTo8bit(Y + 1.402 * (Cr - 128)); + M = 255 - clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128)); + Ye = 255 - clampTo8bit(Y + 1.772 * (Cb - 128)); + } + data[offset++] = 255-C; + data[offset++] = 255-M; + data[offset++] = 255-Ye; + data[offset++] = 255-K; + } + } + break; + default: + throw new Error('Unsupported color mode'); + } + return data; + }, + copyToImageData: function copyToImageData(imageData, formatAsRGBA) { + var width = imageData.width, height = imageData.height; + var imageDataArray = imageData.data; + var data = this.getData(width, height); + var i = 0, j = 0, x, y; + var Y, K, C, M, R, G, B; + switch (this.components.length) { + case 1: + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + Y = data[i++]; + + imageDataArray[j++] = Y; + imageDataArray[j++] = Y; + imageDataArray[j++] = Y; + if (formatAsRGBA) { + imageDataArray[j++] = 255; + } + } + } + break; + case 3: + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + R = data[i++]; + G = data[i++]; + B = data[i++]; + + imageDataArray[j++] = R; + imageDataArray[j++] = G; + imageDataArray[j++] = B; + if (formatAsRGBA) { + imageDataArray[j++] = 255; + } + } + } + break; + case 4: + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + C = data[i++]; + M = data[i++]; + Y = data[i++]; + K = data[i++]; + + R = 255 - clampTo8bit(C * (1 - K / 255) + K); + G = 255 - clampTo8bit(M * (1 - K / 255) + K); + B = 255 - clampTo8bit(Y * (1 - K / 255) + K); + + imageDataArray[j++] = R; + imageDataArray[j++] = G; + imageDataArray[j++] = B; + if (formatAsRGBA) { + imageDataArray[j++] = 255; + } + } + } + break; + default: + throw new Error('Unsupported color mode'); + } + } + }; + + + // We cap the amount of memory used by jpeg-js to avoid unexpected OOMs from untrusted content. + var totalBytesAllocated = 0; + var maxMemoryUsageBytes = 0; + function requestMemoryAllocation(increaseAmount = 0) { + var totalMemoryImpactBytes = totalBytesAllocated + increaseAmount; + if (totalMemoryImpactBytes > maxMemoryUsageBytes) { + var exceededAmount = Math.ceil((totalMemoryImpactBytes - maxMemoryUsageBytes) / 1024 / 1024); + throw new Error(`maxMemoryUsageInMB limit exceeded by at least ${exceededAmount}MB`); + } + + totalBytesAllocated = totalMemoryImpactBytes; + } + + constructor.resetMaxMemoryUsage = function (maxMemoryUsageBytes_) { + totalBytesAllocated = 0; + maxMemoryUsageBytes = maxMemoryUsageBytes_; + }; + + constructor.getBytesAllocated = function () { + return totalBytesAllocated; + }; + + constructor.requestMemoryAllocation = requestMemoryAllocation; + + return constructor; +})(); + +if (typeof module !== 'undefined') { + module.exports = decode; +} else if (typeof window !== 'undefined') { + window['jpeg-js'] = window['jpeg-js'] || {}; + window['jpeg-js'].decode = decode; +} + +function decode(jpegData, userOpts = {}) { + var defaultOpts = { + // "undefined" means "Choose whether to transform colors based on the image’s color model." + colorTransform: undefined, + useTArray: false, + formatAsRGBA: true, + tolerantDecoding: true, + maxResolutionInMP: 100, // Don't decode more than 100 megapixels + maxMemoryUsageInMB: 512, // Don't decode if memory footprint is more than 512MB + }; + + var opts = {...defaultOpts, ...userOpts}; + var arr = new Uint8Array(jpegData); + var decoder = new JpegImage(); + decoder.opts = opts; + // If this constructor ever supports async decoding this will need to be done differently. + // Until then, treating as singleton limit is fine. + JpegImage.resetMaxMemoryUsage(opts.maxMemoryUsageInMB * 1024 * 1024); + decoder.parse(arr); + + var channels = (opts.formatAsRGBA) ? 4 : 3; + var bytesNeeded = decoder.width * decoder.height * channels; + try { + JpegImage.requestMemoryAllocation(bytesNeeded); + var image = { + width: decoder.width, + height: decoder.height, + exifBuffer: decoder.exifBuffer, + data: opts.useTArray ? + new Uint8Array(bytesNeeded) : + Buffer.alloc(bytesNeeded) + }; + if(decoder.comments.length > 0) { + image["comments"] = decoder.comments; + } + } catch (err){ + if (err instanceof RangeError){ + throw new Error("Could not allocate enough memory for the image. " + + "Required: " + bytesNeeded); + } else { + throw err; + } + } + + decoder.copyToImageData(image, opts.formatAsRGBA); + + return image; +} + +}).call(this,require("buffer").Buffer) +},{"buffer":299}],373:[function(require,module,exports){ +(function (Buffer){ +/* + Copyright (c) 2008, Adobe Systems Incorporated + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Adobe Systems Incorporated nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009 + +Basic GUI blocking jpeg encoder +*/ + +var btoa = btoa || function(buf) { + return Buffer.from(buf).toString('base64'); +}; + +function JPEGEncoder(quality) { + var self = this; + var fround = Math.round; + var ffloor = Math.floor; + var YTable = new Array(64); + var UVTable = new Array(64); + var fdtbl_Y = new Array(64); + var fdtbl_UV = new Array(64); + var YDC_HT; + var UVDC_HT; + var YAC_HT; + var UVAC_HT; + + var bitcode = new Array(65535); + var category = new Array(65535); + var outputfDCTQuant = new Array(64); + var DU = new Array(64); + var byteout = []; + var bytenew = 0; + var bytepos = 7; + + var YDU = new Array(64); + var UDU = new Array(64); + var VDU = new Array(64); + var clt = new Array(256); + var RGB_YUV_TABLE = new Array(2048); + var currentQuality; + + var ZigZag = [ + 0, 1, 5, 6,14,15,27,28, + 2, 4, 7,13,16,26,29,42, + 3, 8,12,17,25,30,41,43, + 9,11,18,24,31,40,44,53, + 10,19,23,32,39,45,52,54, + 20,22,33,38,46,51,55,60, + 21,34,37,47,50,56,59,61, + 35,36,48,49,57,58,62,63 + ]; + + var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0]; + var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11]; + var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d]; + var std_ac_luminance_values = [ + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12, + 0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07, + 0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0, + 0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16, + 0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39, + 0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49, + 0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69, + 0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79, + 0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98, + 0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7, + 0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5, + 0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4, + 0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea, + 0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa + ]; + + var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0]; + var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11]; + var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77]; + var std_ac_chrominance_values = [ + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21, + 0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71, + 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0, + 0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34, + 0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38, + 0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48, + 0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68, + 0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78, + 0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96, + 0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5, + 0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3, + 0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2, + 0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9, + 0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa + ]; + + function initQuantTables(sf){ + var YQT = [ + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68,109,103, 77, + 24, 35, 55, 64, 81,104,113, 92, + 49, 64, 78, 87,103,121,120,101, + 72, 92, 95, 98,112,100,103, 99 + ]; + + for (var i = 0; i < 64; i++) { + var t = ffloor((YQT[i]*sf+50)/100); + if (t < 1) { + t = 1; + } else if (t > 255) { + t = 255; + } + YTable[ZigZag[i]] = t; + } + var UVQT = [ + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + ]; + for (var j = 0; j < 64; j++) { + var u = ffloor((UVQT[j]*sf+50)/100); + if (u < 1) { + u = 1; + } else if (u > 255) { + u = 255; + } + UVTable[ZigZag[j]] = u; + } + var aasf = [ + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + ]; + var k = 0; + for (var row = 0; row < 8; row++) + { + for (var col = 0; col < 8; col++) + { + fdtbl_Y[k] = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0)); + fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0)); + k++; + } + } + } + + function computeHuffmanTbl(nrcodes, std_table){ + var codevalue = 0; + var pos_in_table = 0; + var HT = new Array(); + for (var k = 1; k <= 16; k++) { + for (var j = 1; j <= nrcodes[k]; j++) { + HT[std_table[pos_in_table]] = []; + HT[std_table[pos_in_table]][0] = codevalue; + HT[std_table[pos_in_table]][1] = k; + pos_in_table++; + codevalue++; + } + codevalue*=2; + } + return HT; + } + + function initHuffmanTbl() + { + YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values); + UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values); + YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values); + UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values); + } + + function initCategoryNumber() + { + var nrlower = 1; + var nrupper = 2; + for (var cat = 1; cat <= 15; cat++) { + //Positive numbers + for (var nr = nrlower; nr>0] = 38470 * i; + RGB_YUV_TABLE[(i+ 512)>>0] = 7471 * i + 0x8000; + RGB_YUV_TABLE[(i+ 768)>>0] = -11059 * i; + RGB_YUV_TABLE[(i+1024)>>0] = -21709 * i; + RGB_YUV_TABLE[(i+1280)>>0] = 32768 * i + 0x807FFF; + RGB_YUV_TABLE[(i+1536)>>0] = -27439 * i; + RGB_YUV_TABLE[(i+1792)>>0] = - 5329 * i; + } + } + + // IO functions + function writeBits(bs) + { + var value = bs[0]; + var posval = bs[1]-1; + while ( posval >= 0 ) { + if (value & (1 << posval) ) { + bytenew |= (1 << bytepos); + } + posval--; + bytepos--; + if (bytepos < 0) { + if (bytenew == 0xFF) { + writeByte(0xFF); + writeByte(0); + } + else { + writeByte(bytenew); + } + bytepos=7; + bytenew=0; + } + } + } + + function writeByte(value) + { + //byteout.push(clt[value]); // write char directly instead of converting later + byteout.push(value); + } + + function writeWord(value) + { + writeByte((value>>8)&0xFF); + writeByte((value )&0xFF); + } + + // DCT & quantization core + function fDCTQuant(data, fdtbl) + { + var d0, d1, d2, d3, d4, d5, d6, d7; + /* Pass 1: process rows. */ + var dataOff=0; + var i; + var I8 = 8; + var I64 = 64; + for (i=0; i 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0); + //outputfDCTQuant[i] = fround(fDCTQuant); + + } + return outputfDCTQuant; + } + + function writeAPP0() + { + writeWord(0xFFE0); // marker + writeWord(16); // length + writeByte(0x4A); // J + writeByte(0x46); // F + writeByte(0x49); // I + writeByte(0x46); // F + writeByte(0); // = "JFIF",'\0' + writeByte(1); // versionhi + writeByte(1); // versionlo + writeByte(0); // xyunits + writeWord(1); // xdensity + writeWord(1); // ydensity + writeByte(0); // thumbnwidth + writeByte(0); // thumbnheight + } + + function writeAPP1(exifBuffer) { + if (!exifBuffer) return; + + writeWord(0xFFE1); // APP1 marker + + if (exifBuffer[0] === 0x45 && + exifBuffer[1] === 0x78 && + exifBuffer[2] === 0x69 && + exifBuffer[3] === 0x66) { + // Buffer already starts with EXIF, just use it directly + writeWord(exifBuffer.length + 2); // length is buffer + length itself! + } else { + // Buffer doesn't start with EXIF, write it for them + writeWord(exifBuffer.length + 5 + 2); // length is buffer + EXIF\0 + length itself! + writeByte(0x45); // E + writeByte(0x78); // X + writeByte(0x69); // I + writeByte(0x66); // F + writeByte(0); // = "EXIF",'\0' + } + + for (var i = 0; i < exifBuffer.length; i++) { + writeByte(exifBuffer[i]); + } + } + + function writeSOF0(width, height) + { + writeWord(0xFFC0); // marker + writeWord(17); // length, truecolor YUV JPG + writeByte(8); // precision + writeWord(height); + writeWord(width); + writeByte(3); // nrofcomponents + writeByte(1); // IdY + writeByte(0x11); // HVY + writeByte(0); // QTY + writeByte(2); // IdU + writeByte(0x11); // HVU + writeByte(1); // QTU + writeByte(3); // IdV + writeByte(0x11); // HVV + writeByte(1); // QTV + } + + function writeDQT() + { + writeWord(0xFFDB); // marker + writeWord(132); // length + writeByte(0); + for (var i=0; i<64; i++) { + writeByte(YTable[i]); + } + writeByte(1); + for (var j=0; j<64; j++) { + writeByte(UVTable[j]); + } + } + + function writeDHT() + { + writeWord(0xFFC4); // marker + writeWord(0x01A2); // length + + writeByte(0); // HTYDCinfo + for (var i=0; i<16; i++) { + writeByte(std_dc_luminance_nrcodes[i+1]); + } + for (var j=0; j<=11; j++) { + writeByte(std_dc_luminance_values[j]); + } + + writeByte(0x10); // HTYACinfo + for (var k=0; k<16; k++) { + writeByte(std_ac_luminance_nrcodes[k+1]); + } + for (var l=0; l<=161; l++) { + writeByte(std_ac_luminance_values[l]); + } + + writeByte(1); // HTUDCinfo + for (var m=0; m<16; m++) { + writeByte(std_dc_chrominance_nrcodes[m+1]); + } + for (var n=0; n<=11; n++) { + writeByte(std_dc_chrominance_values[n]); + } + + writeByte(0x11); // HTUACinfo + for (var o=0; o<16; o++) { + writeByte(std_ac_chrominance_nrcodes[o+1]); + } + for (var p=0; p<=161; p++) { + writeByte(std_ac_chrominance_values[p]); + } + } + + function writeSOS() + { + writeWord(0xFFDA); // marker + writeWord(12); // length + writeByte(3); // nrofcomponents + writeByte(1); // IdY + writeByte(0); // HTY + writeByte(2); // IdU + writeByte(0x11); // HTU + writeByte(3); // IdV + writeByte(0x11); // HTV + writeByte(0); // Ss + writeByte(0x3f); // Se + writeByte(0); // Bf + } + + function processDU(CDU, fdtbl, DC, HTDC, HTAC){ + var EOB = HTAC[0x00]; + var M16zeroes = HTAC[0xF0]; + var pos; + var I16 = 16; + var I63 = 63; + var I64 = 64; + var DU_DCT = fDCTQuant(CDU, fdtbl); + //ZigZag reorder + for (var j=0;j0)&&(DU[end0pos]==0); end0pos--) {}; + //end0pos = first element in reverse order !=0 + if ( end0pos == 0) { + writeBits(EOB); + return DC; + } + var i = 1; + var lng; + while ( i <= end0pos ) { + var startpos = i; + for (; (DU[i]==0) && (i<=end0pos); ++i) {} + var nrzeroes = i-startpos; + if ( nrzeroes >= I16 ) { + lng = nrzeroes>>4; + for (var nrmarker=1; nrmarker <= lng; ++nrmarker) + writeBits(M16zeroes); + nrzeroes = nrzeroes&0xF; + } + pos = 32767+DU[i]; + writeBits(HTAC[(nrzeroes<<4)+category[pos]]); + writeBits(bitcode[pos]); + i++; + } + if ( end0pos != I63 ) { + writeBits(EOB); + } + return DC; + } + + function initCharLookupTable(){ + var sfcc = String.fromCharCode; + for(var i=0; i < 256; i++){ ///// ACHTUNG // 255 + clt[i] = sfcc(i); + } + } + + this.encode = function(image,quality) // image data object + { + var time_start = new Date().getTime(); + + if(quality) setQuality(quality); + + // Initialize bit writer + byteout = new Array(); + bytenew=0; + bytepos=7; + + // Add JPEG headers + writeWord(0xFFD8); // SOI + writeAPP0(); + writeAPP1(image.exifBuffer); + writeDQT(); + writeSOF0(image.width,image.height); + writeDHT(); + writeSOS(); + + + // Encode 8x8 macroblocks + var DCY=0; + var DCU=0; + var DCV=0; + + bytenew=0; + bytepos=7; + + + this.encode.displayName = "_encode_"; + + var imageData = image.data; + var width = image.width; + var height = image.height; + + var quadWidth = width*4; + var tripleWidth = width*3; + + var x, y = 0; + var r, g, b; + var start,p, col,row,pos; + while(y < height){ + x = 0; + while(x < quadWidth){ + start = quadWidth * y + x; + p = start; + col = -1; + row = 0; + + for(pos=0; pos < 64; pos++){ + row = pos >> 3;// /8 + col = ( pos & 7 ) * 4; // %8 + p = start + ( row * quadWidth ) + col; + + if(y+row >= height){ // padding bottom + p-= (quadWidth*(y+1+row-height)); + } + + if(x+col >= quadWidth){ // padding right + p-= ((x+col) - quadWidth +4) + } + + r = imageData[ p++ ]; + g = imageData[ p++ ]; + b = imageData[ p++ ]; + + + /* // calculate YUV values dynamically + YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80 + UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b)); + VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b)); + */ + + // use lookup table (slightly faster) + YDU[pos] = ((RGB_YUV_TABLE[r] + RGB_YUV_TABLE[(g + 256)>>0] + RGB_YUV_TABLE[(b + 512)>>0]) >> 16)-128; + UDU[pos] = ((RGB_YUV_TABLE[(r + 768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128; + VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128; + + } + + DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + x+=32; + } + y+=8; + } + + + //////////////////////////////////////////////////////////////// + + // Do the bit alignment of the EOI marker + if ( bytepos >= 0 ) { + var fillbits = []; + fillbits[1] = bytepos+1; + fillbits[0] = (1<<(bytepos+1))-1; + writeBits(fillbits); + } + + writeWord(0xFFD9); //EOI + + if (typeof module === 'undefined') return new Uint8Array(byteout); + return Buffer.from(byteout); + + var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join('')); + + byteout = []; + + // benchmarking + var duration = new Date().getTime() - time_start; + //console.log('Encoding time: '+ duration + 'ms'); + // + + return jpegDataUri + } + + function setQuality(quality){ + if (quality <= 0) { + quality = 1; + } + if (quality > 100) { + quality = 100; + } + + if(currentQuality == quality) return // don't recalc if unchanged + + var sf = 0; + if (quality < 50) { + sf = Math.floor(5000 / quality); + } else { + sf = Math.floor(200 - quality*2); + } + + initQuantTables(sf); + currentQuality = quality; + //console.log('Quality set to: '+quality +'%'); + } + + function init(){ + var time_start = new Date().getTime(); + if(!quality) quality = 50; + // Create tables + initCharLookupTable() + initHuffmanTbl(); + initCategoryNumber(); + initRGBYUVTable(); + + setQuality(quality); + var duration = new Date().getTime() - time_start; + //console.log('Initialization '+ duration + 'ms'); + } + + init(); + +}; + +if (typeof module !== 'undefined') { + module.exports = encode; +} else if (typeof window !== 'undefined') { + window['jpeg-js'] = window['jpeg-js'] || {}; + window['jpeg-js'].encode = encode; +} + +function encode(imgData, qu) { + if (typeof qu === 'undefined') qu = 50; + var encoder = new JPEGEncoder(qu); + var data = encoder.encode(imgData, qu); + return { + data: data, + width: imgData.width, + height: imgData.height + }; +} + +// helper function to get the imageData of an existing image on the current page. +function getImageDataFromImage(idOrElement){ + var theImg = (typeof(idOrElement)=='string')? document.getElementById(idOrElement):idOrElement; + var cvs = document.createElement('canvas'); + cvs.width = theImg.width; + cvs.height = theImg.height; + var ctx = cvs.getContext("2d"); + ctx.drawImage(theImg,0,0); + + return (ctx.getImageData(0, 0, cvs.width, cvs.height)); +} + +}).call(this,require("buffer").Buffer) +},{"buffer":299}],374:[function(require,module,exports){ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["jsQR"] = factory(); + else + root["jsQR"] = factory(); +})(typeof self !== 'undefined' ? self : this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(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, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 3); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +var BitMatrix = /** @class */ (function () { + function BitMatrix(data, width) { + this.width = width; + this.height = data.length / width; + this.data = data; + } + BitMatrix.createEmpty = function (width, height) { + return new BitMatrix(new Uint8ClampedArray(width * height), width); + }; + BitMatrix.prototype.get = function (x, y) { + if (x < 0 || x >= this.width || y < 0 || y >= this.height) { + return false; + } + return !!this.data[y * this.width + x]; + }; + BitMatrix.prototype.set = function (x, y, v) { + this.data[y * this.width + x] = v ? 1 : 0; + }; + BitMatrix.prototype.setRegion = function (left, top, width, height, v) { + for (var y = top; y < top + height; y++) { + for (var x = left; x < left + width; x++) { + this.set(x, y, !!v); + } + } + }; + return BitMatrix; +}()); +exports.BitMatrix = BitMatrix; + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +var GenericGFPoly_1 = __webpack_require__(2); +function addOrSubtractGF(a, b) { + return a ^ b; // tslint:disable-line:no-bitwise +} +exports.addOrSubtractGF = addOrSubtractGF; +var GenericGF = /** @class */ (function () { + function GenericGF(primitive, size, genBase) { + this.primitive = primitive; + this.size = size; + this.generatorBase = genBase; + this.expTable = new Array(this.size); + this.logTable = new Array(this.size); + var x = 1; + for (var i = 0; i < this.size; i++) { + this.expTable[i] = x; + x = x * 2; + if (x >= this.size) { + x = (x ^ this.primitive) & (this.size - 1); // tslint:disable-line:no-bitwise + } + } + for (var i = 0; i < this.size - 1; i++) { + this.logTable[this.expTable[i]] = i; + } + this.zero = new GenericGFPoly_1.default(this, Uint8ClampedArray.from([0])); + this.one = new GenericGFPoly_1.default(this, Uint8ClampedArray.from([1])); + } + GenericGF.prototype.multiply = function (a, b) { + if (a === 0 || b === 0) { + return 0; + } + return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)]; + }; + GenericGF.prototype.inverse = function (a) { + if (a === 0) { + throw new Error("Can't invert 0"); + } + return this.expTable[this.size - this.logTable[a] - 1]; + }; + GenericGF.prototype.buildMonomial = function (degree, coefficient) { + if (degree < 0) { + throw new Error("Invalid monomial degree less than 0"); + } + if (coefficient === 0) { + return this.zero; + } + var coefficients = new Uint8ClampedArray(degree + 1); + coefficients[0] = coefficient; + return new GenericGFPoly_1.default(this, coefficients); + }; + GenericGF.prototype.log = function (a) { + if (a === 0) { + throw new Error("Can't take log(0)"); + } + return this.logTable[a]; + }; + GenericGF.prototype.exp = function (a) { + return this.expTable[a]; + }; + return GenericGF; +}()); +exports.default = GenericGF; + + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +var GenericGF_1 = __webpack_require__(1); +var GenericGFPoly = /** @class */ (function () { + function GenericGFPoly(field, coefficients) { + if (coefficients.length === 0) { + throw new Error("No coefficients."); + } + this.field = field; + var coefficientsLength = coefficients.length; + if (coefficientsLength > 1 && coefficients[0] === 0) { + // Leading term must be non-zero for anything except the constant polynomial "0" + var firstNonZero = 1; + while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) { + firstNonZero++; + } + if (firstNonZero === coefficientsLength) { + this.coefficients = field.zero.coefficients; + } + else { + this.coefficients = new Uint8ClampedArray(coefficientsLength - firstNonZero); + for (var i = 0; i < this.coefficients.length; i++) { + this.coefficients[i] = coefficients[firstNonZero + i]; + } + } + } + else { + this.coefficients = coefficients; + } + } + GenericGFPoly.prototype.degree = function () { + return this.coefficients.length - 1; + }; + GenericGFPoly.prototype.isZero = function () { + return this.coefficients[0] === 0; + }; + GenericGFPoly.prototype.getCoefficient = function (degree) { + return this.coefficients[this.coefficients.length - 1 - degree]; + }; + GenericGFPoly.prototype.addOrSubtract = function (other) { + var _a; + if (this.isZero()) { + return other; + } + if (other.isZero()) { + return this; + } + var smallerCoefficients = this.coefficients; + var largerCoefficients = other.coefficients; + if (smallerCoefficients.length > largerCoefficients.length) { + _a = [largerCoefficients, smallerCoefficients], smallerCoefficients = _a[0], largerCoefficients = _a[1]; + } + var sumDiff = new Uint8ClampedArray(largerCoefficients.length); + var lengthDiff = largerCoefficients.length - smallerCoefficients.length; + for (var i = 0; i < lengthDiff; i++) { + sumDiff[i] = largerCoefficients[i]; + } + for (var i = lengthDiff; i < largerCoefficients.length; i++) { + sumDiff[i] = GenericGF_1.addOrSubtractGF(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); + } + return new GenericGFPoly(this.field, sumDiff); + }; + GenericGFPoly.prototype.multiply = function (scalar) { + if (scalar === 0) { + return this.field.zero; + } + if (scalar === 1) { + return this; + } + var size = this.coefficients.length; + var product = new Uint8ClampedArray(size); + for (var i = 0; i < size; i++) { + product[i] = this.field.multiply(this.coefficients[i], scalar); + } + return new GenericGFPoly(this.field, product); + }; + GenericGFPoly.prototype.multiplyPoly = function (other) { + if (this.isZero() || other.isZero()) { + return this.field.zero; + } + var aCoefficients = this.coefficients; + var aLength = aCoefficients.length; + var bCoefficients = other.coefficients; + var bLength = bCoefficients.length; + var product = new Uint8ClampedArray(aLength + bLength - 1); + for (var i = 0; i < aLength; i++) { + var aCoeff = aCoefficients[i]; + for (var j = 0; j < bLength; j++) { + product[i + j] = GenericGF_1.addOrSubtractGF(product[i + j], this.field.multiply(aCoeff, bCoefficients[j])); + } + } + return new GenericGFPoly(this.field, product); + }; + GenericGFPoly.prototype.multiplyByMonomial = function (degree, coefficient) { + if (degree < 0) { + throw new Error("Invalid degree less than 0"); + } + if (coefficient === 0) { + return this.field.zero; + } + var size = this.coefficients.length; + var product = new Uint8ClampedArray(size + degree); + for (var i = 0; i < size; i++) { + product[i] = this.field.multiply(this.coefficients[i], coefficient); + } + return new GenericGFPoly(this.field, product); + }; + GenericGFPoly.prototype.evaluateAt = function (a) { + var result = 0; + if (a === 0) { + // Just return the x^0 coefficient + return this.getCoefficient(0); + } + var size = this.coefficients.length; + if (a === 1) { + // Just the sum of the coefficients + this.coefficients.forEach(function (coefficient) { + result = GenericGF_1.addOrSubtractGF(result, coefficient); + }); + return result; + } + result = this.coefficients[0]; + for (var i = 1; i < size; i++) { + result = GenericGF_1.addOrSubtractGF(this.field.multiply(a, result), this.coefficients[i]); + } + return result; + }; + return GenericGFPoly; +}()); +exports.default = GenericGFPoly; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +var binarizer_1 = __webpack_require__(4); +var decoder_1 = __webpack_require__(5); +var extractor_1 = __webpack_require__(11); +var locator_1 = __webpack_require__(12); +function scan(matrix) { + var locations = locator_1.locate(matrix); + if (!locations) { + return null; + } + for (var _i = 0, locations_1 = locations; _i < locations_1.length; _i++) { + var location_1 = locations_1[_i]; + var extracted = extractor_1.extract(matrix, location_1); + var decoded = decoder_1.decode(extracted.matrix); + if (decoded) { + return { + binaryData: decoded.bytes, + data: decoded.text, + chunks: decoded.chunks, + version: decoded.version, + location: { + topRightCorner: extracted.mappingFunction(location_1.dimension, 0), + topLeftCorner: extracted.mappingFunction(0, 0), + bottomRightCorner: extracted.mappingFunction(location_1.dimension, location_1.dimension), + bottomLeftCorner: extracted.mappingFunction(0, location_1.dimension), + topRightFinderPattern: location_1.topRight, + topLeftFinderPattern: location_1.topLeft, + bottomLeftFinderPattern: location_1.bottomLeft, + bottomRightAlignmentPattern: location_1.alignmentPattern, + }, + }; + } + } + return null; +} +var defaultOptions = { + inversionAttempts: "attemptBoth", +}; +function jsQR(data, width, height, providedOptions) { + if (providedOptions === void 0) { providedOptions = {}; } + var options = defaultOptions; + Object.keys(options || {}).forEach(function (opt) { + options[opt] = providedOptions[opt] || options[opt]; + }); + var shouldInvert = options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst"; + var tryInvertedFirst = options.inversionAttempts === "onlyInvert" || options.inversionAttempts === "invertFirst"; + var _a = binarizer_1.binarize(data, width, height, shouldInvert), binarized = _a.binarized, inverted = _a.inverted; + var result = scan(tryInvertedFirst ? inverted : binarized); + if (!result && (options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst")) { + result = scan(tryInvertedFirst ? binarized : inverted); + } + return result; +} +jsQR.default = jsQR; +exports.default = jsQR; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +var BitMatrix_1 = __webpack_require__(0); +var REGION_SIZE = 8; +var MIN_DYNAMIC_RANGE = 24; +function numBetween(value, min, max) { + return value < min ? min : value > max ? max : value; +} +// Like BitMatrix but accepts arbitry Uint8 values +var Matrix = /** @class */ (function () { + function Matrix(width, height) { + this.width = width; + this.data = new Uint8ClampedArray(width * height); + } + Matrix.prototype.get = function (x, y) { + return this.data[y * this.width + x]; + }; + Matrix.prototype.set = function (x, y, value) { + this.data[y * this.width + x] = value; + }; + return Matrix; +}()); +function binarize(data, width, height, returnInverted) { + if (data.length !== width * height * 4) { + throw new Error("Malformed data passed to binarizer."); + } + // Convert image to greyscale + var greyscalePixels = new Matrix(width, height); + for (var x = 0; x < width; x++) { + for (var y = 0; y < height; y++) { + var r = data[((y * width + x) * 4) + 0]; + var g = data[((y * width + x) * 4) + 1]; + var b = data[((y * width + x) * 4) + 2]; + greyscalePixels.set(x, y, 0.2126 * r + 0.7152 * g + 0.0722 * b); + } + } + var horizontalRegionCount = Math.ceil(width / REGION_SIZE); + var verticalRegionCount = Math.ceil(height / REGION_SIZE); + var blackPoints = new Matrix(horizontalRegionCount, verticalRegionCount); + for (var verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) { + for (var hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) { + var sum = 0; + var min = Infinity; + var max = 0; + for (var y = 0; y < REGION_SIZE; y++) { + for (var x = 0; x < REGION_SIZE; x++) { + var pixelLumosity = greyscalePixels.get(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y); + sum += pixelLumosity; + min = Math.min(min, pixelLumosity); + max = Math.max(max, pixelLumosity); + } + } + var average = sum / (Math.pow(REGION_SIZE, 2)); + if (max - min <= MIN_DYNAMIC_RANGE) { + // If variation within the block is low, assume this is a block with only light or only + // dark pixels. In that case we do not want to use the average, as it would divide this + // low contrast area into black and white pixels, essentially creating data out of noise. + // + // Default the blackpoint for these blocks to be half the min - effectively white them out + average = min / 2; + if (verticalRegion > 0 && hortizontalRegion > 0) { + // Correct the "white background" assumption for blocks that have neighbors by comparing + // the pixels in this block to the previously calculated black points. This is based on + // the fact that dark barcode symbology is always surrounded by some amount of light + // background for which reasonable black point estimates were made. The bp estimated at + // the boundaries is used for the interior. + // The (min < bp) is arbitrary but works better than other heuristics that were tried. + var averageNeighborBlackPoint = (blackPoints.get(hortizontalRegion, verticalRegion - 1) + + (2 * blackPoints.get(hortizontalRegion - 1, verticalRegion)) + + blackPoints.get(hortizontalRegion - 1, verticalRegion - 1)) / 4; + if (min < averageNeighborBlackPoint) { + average = averageNeighborBlackPoint; + } + } + } + blackPoints.set(hortizontalRegion, verticalRegion, average); + } + } + var binarized = BitMatrix_1.BitMatrix.createEmpty(width, height); + var inverted = null; + if (returnInverted) { + inverted = BitMatrix_1.BitMatrix.createEmpty(width, height); + } + for (var verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) { + for (var hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) { + var left = numBetween(hortizontalRegion, 2, horizontalRegionCount - 3); + var top_1 = numBetween(verticalRegion, 2, verticalRegionCount - 3); + var sum = 0; + for (var xRegion = -2; xRegion <= 2; xRegion++) { + for (var yRegion = -2; yRegion <= 2; yRegion++) { + sum += blackPoints.get(left + xRegion, top_1 + yRegion); + } + } + var threshold = sum / 25; + for (var xRegion = 0; xRegion < REGION_SIZE; xRegion++) { + for (var yRegion = 0; yRegion < REGION_SIZE; yRegion++) { + var x = hortizontalRegion * REGION_SIZE + xRegion; + var y = verticalRegion * REGION_SIZE + yRegion; + var lum = greyscalePixels.get(x, y); + binarized.set(x, y, lum <= threshold); + if (returnInverted) { + inverted.set(x, y, !(lum <= threshold)); + } + } + } + } + } + if (returnInverted) { + return { binarized: binarized, inverted: inverted }; + } + return { binarized: binarized }; +} +exports.binarize = binarize; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +var BitMatrix_1 = __webpack_require__(0); +var decodeData_1 = __webpack_require__(6); +var reedsolomon_1 = __webpack_require__(9); +var version_1 = __webpack_require__(10); +// tslint:disable:no-bitwise +function numBitsDiffering(x, y) { + var z = x ^ y; + var bitCount = 0; + while (z) { + bitCount++; + z &= z - 1; + } + return bitCount; +} +function pushBit(bit, byte) { + return (byte << 1) | bit; +} +// tslint:enable:no-bitwise +var FORMAT_INFO_TABLE = [ + { bits: 0x5412, formatInfo: { errorCorrectionLevel: 1, dataMask: 0 } }, + { bits: 0x5125, formatInfo: { errorCorrectionLevel: 1, dataMask: 1 } }, + { bits: 0x5E7C, formatInfo: { errorCorrectionLevel: 1, dataMask: 2 } }, + { bits: 0x5B4B, formatInfo: { errorCorrectionLevel: 1, dataMask: 3 } }, + { bits: 0x45F9, formatInfo: { errorCorrectionLevel: 1, dataMask: 4 } }, + { bits: 0x40CE, formatInfo: { errorCorrectionLevel: 1, dataMask: 5 } }, + { bits: 0x4F97, formatInfo: { errorCorrectionLevel: 1, dataMask: 6 } }, + { bits: 0x4AA0, formatInfo: { errorCorrectionLevel: 1, dataMask: 7 } }, + { bits: 0x77C4, formatInfo: { errorCorrectionLevel: 0, dataMask: 0 } }, + { bits: 0x72F3, formatInfo: { errorCorrectionLevel: 0, dataMask: 1 } }, + { bits: 0x7DAA, formatInfo: { errorCorrectionLevel: 0, dataMask: 2 } }, + { bits: 0x789D, formatInfo: { errorCorrectionLevel: 0, dataMask: 3 } }, + { bits: 0x662F, formatInfo: { errorCorrectionLevel: 0, dataMask: 4 } }, + { bits: 0x6318, formatInfo: { errorCorrectionLevel: 0, dataMask: 5 } }, + { bits: 0x6C41, formatInfo: { errorCorrectionLevel: 0, dataMask: 6 } }, + { bits: 0x6976, formatInfo: { errorCorrectionLevel: 0, dataMask: 7 } }, + { bits: 0x1689, formatInfo: { errorCorrectionLevel: 3, dataMask: 0 } }, + { bits: 0x13BE, formatInfo: { errorCorrectionLevel: 3, dataMask: 1 } }, + { bits: 0x1CE7, formatInfo: { errorCorrectionLevel: 3, dataMask: 2 } }, + { bits: 0x19D0, formatInfo: { errorCorrectionLevel: 3, dataMask: 3 } }, + { bits: 0x0762, formatInfo: { errorCorrectionLevel: 3, dataMask: 4 } }, + { bits: 0x0255, formatInfo: { errorCorrectionLevel: 3, dataMask: 5 } }, + { bits: 0x0D0C, formatInfo: { errorCorrectionLevel: 3, dataMask: 6 } }, + { bits: 0x083B, formatInfo: { errorCorrectionLevel: 3, dataMask: 7 } }, + { bits: 0x355F, formatInfo: { errorCorrectionLevel: 2, dataMask: 0 } }, + { bits: 0x3068, formatInfo: { errorCorrectionLevel: 2, dataMask: 1 } }, + { bits: 0x3F31, formatInfo: { errorCorrectionLevel: 2, dataMask: 2 } }, + { bits: 0x3A06, formatInfo: { errorCorrectionLevel: 2, dataMask: 3 } }, + { bits: 0x24B4, formatInfo: { errorCorrectionLevel: 2, dataMask: 4 } }, + { bits: 0x2183, formatInfo: { errorCorrectionLevel: 2, dataMask: 5 } }, + { bits: 0x2EDA, formatInfo: { errorCorrectionLevel: 2, dataMask: 6 } }, + { bits: 0x2BED, formatInfo: { errorCorrectionLevel: 2, dataMask: 7 } }, +]; +var DATA_MASKS = [ + function (p) { return ((p.y + p.x) % 2) === 0; }, + function (p) { return (p.y % 2) === 0; }, + function (p) { return p.x % 3 === 0; }, + function (p) { return (p.y + p.x) % 3 === 0; }, + function (p) { return (Math.floor(p.y / 2) + Math.floor(p.x / 3)) % 2 === 0; }, + function (p) { return ((p.x * p.y) % 2) + ((p.x * p.y) % 3) === 0; }, + function (p) { return ((((p.y * p.x) % 2) + (p.y * p.x) % 3) % 2) === 0; }, + function (p) { return ((((p.y + p.x) % 2) + (p.y * p.x) % 3) % 2) === 0; }, +]; +function buildFunctionPatternMask(version) { + var dimension = 17 + 4 * version.versionNumber; + var matrix = BitMatrix_1.BitMatrix.createEmpty(dimension, dimension); + matrix.setRegion(0, 0, 9, 9, true); // Top left finder pattern + separator + format + matrix.setRegion(dimension - 8, 0, 8, 9, true); // Top right finder pattern + separator + format + matrix.setRegion(0, dimension - 8, 9, 8, true); // Bottom left finder pattern + separator + format + // Alignment patterns + for (var _i = 0, _a = version.alignmentPatternCenters; _i < _a.length; _i++) { + var x = _a[_i]; + for (var _b = 0, _c = version.alignmentPatternCenters; _b < _c.length; _b++) { + var y = _c[_b]; + if (!(x === 6 && y === 6 || x === 6 && y === dimension - 7 || x === dimension - 7 && y === 6)) { + matrix.setRegion(x - 2, y - 2, 5, 5, true); + } + } + } + matrix.setRegion(6, 9, 1, dimension - 17, true); // Vertical timing pattern + matrix.setRegion(9, 6, dimension - 17, 1, true); // Horizontal timing pattern + if (version.versionNumber > 6) { + matrix.setRegion(dimension - 11, 0, 3, 6, true); // Version info, top right + matrix.setRegion(0, dimension - 11, 6, 3, true); // Version info, bottom left + } + return matrix; +} +function readCodewords(matrix, version, formatInfo) { + var dataMask = DATA_MASKS[formatInfo.dataMask]; + var dimension = matrix.height; + var functionPatternMask = buildFunctionPatternMask(version); + var codewords = []; + var currentByte = 0; + var bitsRead = 0; + // Read columns in pairs, from right to left + var readingUp = true; + for (var columnIndex = dimension - 1; columnIndex > 0; columnIndex -= 2) { + if (columnIndex === 6) { // Skip whole column with vertical alignment pattern; + columnIndex--; + } + for (var i = 0; i < dimension; i++) { + var y = readingUp ? dimension - 1 - i : i; + for (var columnOffset = 0; columnOffset < 2; columnOffset++) { + var x = columnIndex - columnOffset; + if (!functionPatternMask.get(x, y)) { + bitsRead++; + var bit = matrix.get(x, y); + if (dataMask({ y: y, x: x })) { + bit = !bit; + } + currentByte = pushBit(bit, currentByte); + if (bitsRead === 8) { // Whole bytes + codewords.push(currentByte); + bitsRead = 0; + currentByte = 0; + } + } + } + } + readingUp = !readingUp; + } + return codewords; +} +function readVersion(matrix) { + var dimension = matrix.height; + var provisionalVersion = Math.floor((dimension - 17) / 4); + if (provisionalVersion <= 6) { // 6 and under dont have version info in the QR code + return version_1.VERSIONS[provisionalVersion - 1]; + } + var topRightVersionBits = 0; + for (var y = 5; y >= 0; y--) { + for (var x = dimension - 9; x >= dimension - 11; x--) { + topRightVersionBits = pushBit(matrix.get(x, y), topRightVersionBits); + } + } + var bottomLeftVersionBits = 0; + for (var x = 5; x >= 0; x--) { + for (var y = dimension - 9; y >= dimension - 11; y--) { + bottomLeftVersionBits = pushBit(matrix.get(x, y), bottomLeftVersionBits); + } + } + var bestDifference = Infinity; + var bestVersion; + for (var _i = 0, VERSIONS_1 = version_1.VERSIONS; _i < VERSIONS_1.length; _i++) { + var version = VERSIONS_1[_i]; + if (version.infoBits === topRightVersionBits || version.infoBits === bottomLeftVersionBits) { + return version; + } + var difference = numBitsDiffering(topRightVersionBits, version.infoBits); + if (difference < bestDifference) { + bestVersion = version; + bestDifference = difference; + } + difference = numBitsDiffering(bottomLeftVersionBits, version.infoBits); + if (difference < bestDifference) { + bestVersion = version; + bestDifference = difference; + } + } + // We can tolerate up to 3 bits of error since no two version info codewords will + // differ in less than 8 bits. + if (bestDifference <= 3) { + return bestVersion; + } +} +function readFormatInformation(matrix) { + var topLeftFormatInfoBits = 0; + for (var x = 0; x <= 8; x++) { + if (x !== 6) { // Skip timing pattern bit + topLeftFormatInfoBits = pushBit(matrix.get(x, 8), topLeftFormatInfoBits); + } + } + for (var y = 7; y >= 0; y--) { + if (y !== 6) { // Skip timing pattern bit + topLeftFormatInfoBits = pushBit(matrix.get(8, y), topLeftFormatInfoBits); + } + } + var dimension = matrix.height; + var topRightBottomRightFormatInfoBits = 0; + for (var y = dimension - 1; y >= dimension - 7; y--) { // bottom left + topRightBottomRightFormatInfoBits = pushBit(matrix.get(8, y), topRightBottomRightFormatInfoBits); + } + for (var x = dimension - 8; x < dimension; x++) { // top right + topRightBottomRightFormatInfoBits = pushBit(matrix.get(x, 8), topRightBottomRightFormatInfoBits); + } + var bestDifference = Infinity; + var bestFormatInfo = null; + for (var _i = 0, FORMAT_INFO_TABLE_1 = FORMAT_INFO_TABLE; _i < FORMAT_INFO_TABLE_1.length; _i++) { + var _a = FORMAT_INFO_TABLE_1[_i], bits = _a.bits, formatInfo = _a.formatInfo; + if (bits === topLeftFormatInfoBits || bits === topRightBottomRightFormatInfoBits) { + return formatInfo; + } + var difference = numBitsDiffering(topLeftFormatInfoBits, bits); + if (difference < bestDifference) { + bestFormatInfo = formatInfo; + bestDifference = difference; + } + if (topLeftFormatInfoBits !== topRightBottomRightFormatInfoBits) { // also try the other option + difference = numBitsDiffering(topRightBottomRightFormatInfoBits, bits); + if (difference < bestDifference) { + bestFormatInfo = formatInfo; + bestDifference = difference; + } + } + } + // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits differing means we found a match + if (bestDifference <= 3) { + return bestFormatInfo; + } + return null; +} +function getDataBlocks(codewords, version, ecLevel) { + var ecInfo = version.errorCorrectionLevels[ecLevel]; + var dataBlocks = []; + var totalCodewords = 0; + ecInfo.ecBlocks.forEach(function (block) { + for (var i = 0; i < block.numBlocks; i++) { + dataBlocks.push({ numDataCodewords: block.dataCodewordsPerBlock, codewords: [] }); + totalCodewords += block.dataCodewordsPerBlock + ecInfo.ecCodewordsPerBlock; + } + }); + // In some cases the QR code will be malformed enough that we pull off more or less than we should. + // If we pull off less there's nothing we can do. + // If we pull off more we can safely truncate + if (codewords.length < totalCodewords) { + return null; + } + codewords = codewords.slice(0, totalCodewords); + var shortBlockSize = ecInfo.ecBlocks[0].dataCodewordsPerBlock; + // Pull codewords to fill the blocks up to the minimum size + for (var i = 0; i < shortBlockSize; i++) { + for (var _i = 0, dataBlocks_1 = dataBlocks; _i < dataBlocks_1.length; _i++) { + var dataBlock = dataBlocks_1[_i]; + dataBlock.codewords.push(codewords.shift()); + } + } + // If there are any large blocks, pull codewords to fill the last element of those + if (ecInfo.ecBlocks.length > 1) { + var smallBlockCount = ecInfo.ecBlocks[0].numBlocks; + var largeBlockCount = ecInfo.ecBlocks[1].numBlocks; + for (var i = 0; i < largeBlockCount; i++) { + dataBlocks[smallBlockCount + i].codewords.push(codewords.shift()); + } + } + // Add the rest of the codewords to the blocks. These are the error correction codewords. + while (codewords.length > 0) { + for (var _a = 0, dataBlocks_2 = dataBlocks; _a < dataBlocks_2.length; _a++) { + var dataBlock = dataBlocks_2[_a]; + dataBlock.codewords.push(codewords.shift()); + } + } + return dataBlocks; +} +function decodeMatrix(matrix) { + var version = readVersion(matrix); + if (!version) { + return null; + } + var formatInfo = readFormatInformation(matrix); + if (!formatInfo) { + return null; + } + var codewords = readCodewords(matrix, version, formatInfo); + var dataBlocks = getDataBlocks(codewords, version, formatInfo.errorCorrectionLevel); + if (!dataBlocks) { + return null; + } + // Count total number of data bytes + var totalBytes = dataBlocks.reduce(function (a, b) { return a + b.numDataCodewords; }, 0); + var resultBytes = new Uint8ClampedArray(totalBytes); + var resultIndex = 0; + for (var _i = 0, dataBlocks_3 = dataBlocks; _i < dataBlocks_3.length; _i++) { + var dataBlock = dataBlocks_3[_i]; + var correctedBytes = reedsolomon_1.decode(dataBlock.codewords, dataBlock.codewords.length - dataBlock.numDataCodewords); + if (!correctedBytes) { + return null; + } + for (var i = 0; i < dataBlock.numDataCodewords; i++) { + resultBytes[resultIndex++] = correctedBytes[i]; + } + } + try { + return decodeData_1.decode(resultBytes, version.versionNumber); + } + catch (_a) { + return null; + } +} +function decode(matrix) { + if (matrix == null) { + return null; + } + var result = decodeMatrix(matrix); + if (result) { + return result; + } + // Decoding didn't work, try mirroring the QR across the topLeft -> bottomRight line. + for (var x = 0; x < matrix.width; x++) { + for (var y = x + 1; y < matrix.height; y++) { + if (matrix.get(x, y) !== matrix.get(y, x)) { + matrix.set(x, y, !matrix.get(x, y)); + matrix.set(y, x, !matrix.get(y, x)); + } + } + } + return decodeMatrix(matrix); +} +exports.decode = decode; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +// tslint:disable:no-bitwise +var BitStream_1 = __webpack_require__(7); +var shiftJISTable_1 = __webpack_require__(8); +var Mode; +(function (Mode) { + Mode["Numeric"] = "numeric"; + Mode["Alphanumeric"] = "alphanumeric"; + Mode["Byte"] = "byte"; + Mode["Kanji"] = "kanji"; + Mode["ECI"] = "eci"; +})(Mode = exports.Mode || (exports.Mode = {})); +var ModeByte; +(function (ModeByte) { + ModeByte[ModeByte["Terminator"] = 0] = "Terminator"; + ModeByte[ModeByte["Numeric"] = 1] = "Numeric"; + ModeByte[ModeByte["Alphanumeric"] = 2] = "Alphanumeric"; + ModeByte[ModeByte["Byte"] = 4] = "Byte"; + ModeByte[ModeByte["Kanji"] = 8] = "Kanji"; + ModeByte[ModeByte["ECI"] = 7] = "ECI"; + // StructuredAppend = 0x3, + // FNC1FirstPosition = 0x5, + // FNC1SecondPosition = 0x9, +})(ModeByte || (ModeByte = {})); +function decodeNumeric(stream, size) { + var bytes = []; + var text = ""; + var characterCountSize = [10, 12, 14][size]; + var length = stream.readBits(characterCountSize); + // Read digits in groups of 3 + while (length >= 3) { + var num = stream.readBits(10); + if (num >= 1000) { + throw new Error("Invalid numeric value above 999"); + } + var a = Math.floor(num / 100); + var b = Math.floor(num / 10) % 10; + var c = num % 10; + bytes.push(48 + a, 48 + b, 48 + c); + text += a.toString() + b.toString() + c.toString(); + length -= 3; + } + // If the number of digits aren't a multiple of 3, the remaining digits are special cased. + if (length === 2) { + var num = stream.readBits(7); + if (num >= 100) { + throw new Error("Invalid numeric value above 99"); + } + var a = Math.floor(num / 10); + var b = num % 10; + bytes.push(48 + a, 48 + b); + text += a.toString() + b.toString(); + } + else if (length === 1) { + var num = stream.readBits(4); + if (num >= 10) { + throw new Error("Invalid numeric value above 9"); + } + bytes.push(48 + num); + text += num.toString(); + } + return { bytes: bytes, text: text }; +} +var AlphanumericCharacterCodes = [ + "0", "1", "2", "3", "4", "5", "6", "7", "8", + "9", "A", "B", "C", "D", "E", "F", "G", "H", + "I", "J", "K", "L", "M", "N", "O", "P", "Q", + "R", "S", "T", "U", "V", "W", "X", "Y", "Z", + " ", "$", "%", "*", "+", "-", ".", "/", ":", +]; +function decodeAlphanumeric(stream, size) { + var bytes = []; + var text = ""; + var characterCountSize = [9, 11, 13][size]; + var length = stream.readBits(characterCountSize); + while (length >= 2) { + var v = stream.readBits(11); + var a = Math.floor(v / 45); + var b = v % 45; + bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0), AlphanumericCharacterCodes[b].charCodeAt(0)); + text += AlphanumericCharacterCodes[a] + AlphanumericCharacterCodes[b]; + length -= 2; + } + if (length === 1) { + var a = stream.readBits(6); + bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0)); + text += AlphanumericCharacterCodes[a]; + } + return { bytes: bytes, text: text }; +} +function decodeByte(stream, size) { + var bytes = []; + var text = ""; + var characterCountSize = [8, 16, 16][size]; + var length = stream.readBits(characterCountSize); + for (var i = 0; i < length; i++) { + var b = stream.readBits(8); + bytes.push(b); + } + try { + text += decodeURIComponent(bytes.map(function (b) { return "%" + ("0" + b.toString(16)).substr(-2); }).join("")); + } + catch (_a) { + // failed to decode + } + return { bytes: bytes, text: text }; +} +function decodeKanji(stream, size) { + var bytes = []; + var text = ""; + var characterCountSize = [8, 10, 12][size]; + var length = stream.readBits(characterCountSize); + for (var i = 0; i < length; i++) { + var k = stream.readBits(13); + var c = (Math.floor(k / 0xC0) << 8) | (k % 0xC0); + if (c < 0x1F00) { + c += 0x8140; + } + else { + c += 0xC140; + } + bytes.push(c >> 8, c & 0xFF); + text += String.fromCharCode(shiftJISTable_1.shiftJISTable[c]); + } + return { bytes: bytes, text: text }; +} +function decode(data, version) { + var _a, _b, _c, _d; + var stream = new BitStream_1.BitStream(data); + // There are 3 'sizes' based on the version. 1-9 is small (0), 10-26 is medium (1) and 27-40 is large (2). + var size = version <= 9 ? 0 : version <= 26 ? 1 : 2; + var result = { + text: "", + bytes: [], + chunks: [], + version: version, + }; + while (stream.available() >= 4) { + var mode = stream.readBits(4); + if (mode === ModeByte.Terminator) { + return result; + } + else if (mode === ModeByte.ECI) { + if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(7), + }); + } + else if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(14), + }); + } + else if (stream.readBits(1) === 0) { + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: stream.readBits(21), + }); + } + else { + // ECI data seems corrupted + result.chunks.push({ + type: Mode.ECI, + assignmentNumber: -1, + }); + } + } + else if (mode === ModeByte.Numeric) { + var numericResult = decodeNumeric(stream, size); + result.text += numericResult.text; + (_a = result.bytes).push.apply(_a, numericResult.bytes); + result.chunks.push({ + type: Mode.Numeric, + text: numericResult.text, + }); + } + else if (mode === ModeByte.Alphanumeric) { + var alphanumericResult = decodeAlphanumeric(stream, size); + result.text += alphanumericResult.text; + (_b = result.bytes).push.apply(_b, alphanumericResult.bytes); + result.chunks.push({ + type: Mode.Alphanumeric, + text: alphanumericResult.text, + }); + } + else if (mode === ModeByte.Byte) { + var byteResult = decodeByte(stream, size); + result.text += byteResult.text; + (_c = result.bytes).push.apply(_c, byteResult.bytes); + result.chunks.push({ + type: Mode.Byte, + bytes: byteResult.bytes, + text: byteResult.text, + }); + } + else if (mode === ModeByte.Kanji) { + var kanjiResult = decodeKanji(stream, size); + result.text += kanjiResult.text; + (_d = result.bytes).push.apply(_d, kanjiResult.bytes); + result.chunks.push({ + type: Mode.Kanji, + bytes: kanjiResult.bytes, + text: kanjiResult.text, + }); + } + } + // If there is no data left, or the remaining bits are all 0, then that counts as a termination marker + if (stream.available() === 0 || stream.readBits(stream.available()) === 0) { + return result; + } +} +exports.decode = decode; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// tslint:disable:no-bitwise +Object.defineProperty(exports, "__esModule", { value: true }); +var BitStream = /** @class */ (function () { + function BitStream(bytes) { + this.byteOffset = 0; + this.bitOffset = 0; + this.bytes = bytes; + } + BitStream.prototype.readBits = function (numBits) { + if (numBits < 1 || numBits > 32 || numBits > this.available()) { + throw new Error("Cannot read " + numBits.toString() + " bits"); + } + var result = 0; + // First, read remainder from current byte + if (this.bitOffset > 0) { + var bitsLeft = 8 - this.bitOffset; + var toRead = numBits < bitsLeft ? numBits : bitsLeft; + var bitsToNotRead = bitsLeft - toRead; + var mask = (0xFF >> (8 - toRead)) << bitsToNotRead; + result = (this.bytes[this.byteOffset] & mask) >> bitsToNotRead; + numBits -= toRead; + this.bitOffset += toRead; + if (this.bitOffset === 8) { + this.bitOffset = 0; + this.byteOffset++; + } + } + // Next read whole bytes + if (numBits > 0) { + while (numBits >= 8) { + result = (result << 8) | (this.bytes[this.byteOffset] & 0xFF); + this.byteOffset++; + numBits -= 8; + } + // Finally read a partial byte + if (numBits > 0) { + var bitsToNotRead = 8 - numBits; + var mask = (0xFF >> bitsToNotRead) << bitsToNotRead; + result = (result << numBits) | ((this.bytes[this.byteOffset] & mask) >> bitsToNotRead); + this.bitOffset += numBits; + } + } + return result; + }; + BitStream.prototype.available = function () { + return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset; + }; + return BitStream; +}()); +exports.BitStream = BitStream; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +exports.shiftJISTable = { + 0x20: 0x0020, + 0x21: 0x0021, + 0x22: 0x0022, + 0x23: 0x0023, + 0x24: 0x0024, + 0x25: 0x0025, + 0x26: 0x0026, + 0x27: 0x0027, + 0x28: 0x0028, + 0x29: 0x0029, + 0x2A: 0x002A, + 0x2B: 0x002B, + 0x2C: 0x002C, + 0x2D: 0x002D, + 0x2E: 0x002E, + 0x2F: 0x002F, + 0x30: 0x0030, + 0x31: 0x0031, + 0x32: 0x0032, + 0x33: 0x0033, + 0x34: 0x0034, + 0x35: 0x0035, + 0x36: 0x0036, + 0x37: 0x0037, + 0x38: 0x0038, + 0x39: 0x0039, + 0x3A: 0x003A, + 0x3B: 0x003B, + 0x3C: 0x003C, + 0x3D: 0x003D, + 0x3E: 0x003E, + 0x3F: 0x003F, + 0x40: 0x0040, + 0x41: 0x0041, + 0x42: 0x0042, + 0x43: 0x0043, + 0x44: 0x0044, + 0x45: 0x0045, + 0x46: 0x0046, + 0x47: 0x0047, + 0x48: 0x0048, + 0x49: 0x0049, + 0x4A: 0x004A, + 0x4B: 0x004B, + 0x4C: 0x004C, + 0x4D: 0x004D, + 0x4E: 0x004E, + 0x4F: 0x004F, + 0x50: 0x0050, + 0x51: 0x0051, + 0x52: 0x0052, + 0x53: 0x0053, + 0x54: 0x0054, + 0x55: 0x0055, + 0x56: 0x0056, + 0x57: 0x0057, + 0x58: 0x0058, + 0x59: 0x0059, + 0x5A: 0x005A, + 0x5B: 0x005B, + 0x5C: 0x00A5, + 0x5D: 0x005D, + 0x5E: 0x005E, + 0x5F: 0x005F, + 0x60: 0x0060, + 0x61: 0x0061, + 0x62: 0x0062, + 0x63: 0x0063, + 0x64: 0x0064, + 0x65: 0x0065, + 0x66: 0x0066, + 0x67: 0x0067, + 0x68: 0x0068, + 0x69: 0x0069, + 0x6A: 0x006A, + 0x6B: 0x006B, + 0x6C: 0x006C, + 0x6D: 0x006D, + 0x6E: 0x006E, + 0x6F: 0x006F, + 0x70: 0x0070, + 0x71: 0x0071, + 0x72: 0x0072, + 0x73: 0x0073, + 0x74: 0x0074, + 0x75: 0x0075, + 0x76: 0x0076, + 0x77: 0x0077, + 0x78: 0x0078, + 0x79: 0x0079, + 0x7A: 0x007A, + 0x7B: 0x007B, + 0x7C: 0x007C, + 0x7D: 0x007D, + 0x7E: 0x203E, + 0x8140: 0x3000, + 0x8141: 0x3001, + 0x8142: 0x3002, + 0x8143: 0xFF0C, + 0x8144: 0xFF0E, + 0x8145: 0x30FB, + 0x8146: 0xFF1A, + 0x8147: 0xFF1B, + 0x8148: 0xFF1F, + 0x8149: 0xFF01, + 0x814A: 0x309B, + 0x814B: 0x309C, + 0x814C: 0x00B4, + 0x814D: 0xFF40, + 0x814E: 0x00A8, + 0x814F: 0xFF3E, + 0x8150: 0xFFE3, + 0x8151: 0xFF3F, + 0x8152: 0x30FD, + 0x8153: 0x30FE, + 0x8154: 0x309D, + 0x8155: 0x309E, + 0x8156: 0x3003, + 0x8157: 0x4EDD, + 0x8158: 0x3005, + 0x8159: 0x3006, + 0x815A: 0x3007, + 0x815B: 0x30FC, + 0x815C: 0x2015, + 0x815D: 0x2010, + 0x815E: 0xFF0F, + 0x815F: 0x005C, + 0x8160: 0x301C, + 0x8161: 0x2016, + 0x8162: 0xFF5C, + 0x8163: 0x2026, + 0x8164: 0x2025, + 0x8165: 0x2018, + 0x8166: 0x2019, + 0x8167: 0x201C, + 0x8168: 0x201D, + 0x8169: 0xFF08, + 0x816A: 0xFF09, + 0x816B: 0x3014, + 0x816C: 0x3015, + 0x816D: 0xFF3B, + 0x816E: 0xFF3D, + 0x816F: 0xFF5B, + 0x8170: 0xFF5D, + 0x8171: 0x3008, + 0x8172: 0x3009, + 0x8173: 0x300A, + 0x8174: 0x300B, + 0x8175: 0x300C, + 0x8176: 0x300D, + 0x8177: 0x300E, + 0x8178: 0x300F, + 0x8179: 0x3010, + 0x817A: 0x3011, + 0x817B: 0xFF0B, + 0x817C: 0x2212, + 0x817D: 0x00B1, + 0x817E: 0x00D7, + 0x8180: 0x00F7, + 0x8181: 0xFF1D, + 0x8182: 0x2260, + 0x8183: 0xFF1C, + 0x8184: 0xFF1E, + 0x8185: 0x2266, + 0x8186: 0x2267, + 0x8187: 0x221E, + 0x8188: 0x2234, + 0x8189: 0x2642, + 0x818A: 0x2640, + 0x818B: 0x00B0, + 0x818C: 0x2032, + 0x818D: 0x2033, + 0x818E: 0x2103, + 0x818F: 0xFFE5, + 0x8190: 0xFF04, + 0x8191: 0x00A2, + 0x8192: 0x00A3, + 0x8193: 0xFF05, + 0x8194: 0xFF03, + 0x8195: 0xFF06, + 0x8196: 0xFF0A, + 0x8197: 0xFF20, + 0x8198: 0x00A7, + 0x8199: 0x2606, + 0x819A: 0x2605, + 0x819B: 0x25CB, + 0x819C: 0x25CF, + 0x819D: 0x25CE, + 0x819E: 0x25C7, + 0x819F: 0x25C6, + 0x81A0: 0x25A1, + 0x81A1: 0x25A0, + 0x81A2: 0x25B3, + 0x81A3: 0x25B2, + 0x81A4: 0x25BD, + 0x81A5: 0x25BC, + 0x81A6: 0x203B, + 0x81A7: 0x3012, + 0x81A8: 0x2192, + 0x81A9: 0x2190, + 0x81AA: 0x2191, + 0x81AB: 0x2193, + 0x81AC: 0x3013, + 0x81B8: 0x2208, + 0x81B9: 0x220B, + 0x81BA: 0x2286, + 0x81BB: 0x2287, + 0x81BC: 0x2282, + 0x81BD: 0x2283, + 0x81BE: 0x222A, + 0x81BF: 0x2229, + 0x81C8: 0x2227, + 0x81C9: 0x2228, + 0x81CA: 0x00AC, + 0x81CB: 0x21D2, + 0x81CC: 0x21D4, + 0x81CD: 0x2200, + 0x81CE: 0x2203, + 0x81DA: 0x2220, + 0x81DB: 0x22A5, + 0x81DC: 0x2312, + 0x81DD: 0x2202, + 0x81DE: 0x2207, + 0x81DF: 0x2261, + 0x81E0: 0x2252, + 0x81E1: 0x226A, + 0x81E2: 0x226B, + 0x81E3: 0x221A, + 0x81E4: 0x223D, + 0x81E5: 0x221D, + 0x81E6: 0x2235, + 0x81E7: 0x222B, + 0x81E8: 0x222C, + 0x81F0: 0x212B, + 0x81F1: 0x2030, + 0x81F2: 0x266F, + 0x81F3: 0x266D, + 0x81F4: 0x266A, + 0x81F5: 0x2020, + 0x81F6: 0x2021, + 0x81F7: 0x00B6, + 0x81FC: 0x25EF, + 0x824F: 0xFF10, + 0x8250: 0xFF11, + 0x8251: 0xFF12, + 0x8252: 0xFF13, + 0x8253: 0xFF14, + 0x8254: 0xFF15, + 0x8255: 0xFF16, + 0x8256: 0xFF17, + 0x8257: 0xFF18, + 0x8258: 0xFF19, + 0x8260: 0xFF21, + 0x8261: 0xFF22, + 0x8262: 0xFF23, + 0x8263: 0xFF24, + 0x8264: 0xFF25, + 0x8265: 0xFF26, + 0x8266: 0xFF27, + 0x8267: 0xFF28, + 0x8268: 0xFF29, + 0x8269: 0xFF2A, + 0x826A: 0xFF2B, + 0x826B: 0xFF2C, + 0x826C: 0xFF2D, + 0x826D: 0xFF2E, + 0x826E: 0xFF2F, + 0x826F: 0xFF30, + 0x8270: 0xFF31, + 0x8271: 0xFF32, + 0x8272: 0xFF33, + 0x8273: 0xFF34, + 0x8274: 0xFF35, + 0x8275: 0xFF36, + 0x8276: 0xFF37, + 0x8277: 0xFF38, + 0x8278: 0xFF39, + 0x8279: 0xFF3A, + 0x8281: 0xFF41, + 0x8282: 0xFF42, + 0x8283: 0xFF43, + 0x8284: 0xFF44, + 0x8285: 0xFF45, + 0x8286: 0xFF46, + 0x8287: 0xFF47, + 0x8288: 0xFF48, + 0x8289: 0xFF49, + 0x828A: 0xFF4A, + 0x828B: 0xFF4B, + 0x828C: 0xFF4C, + 0x828D: 0xFF4D, + 0x828E: 0xFF4E, + 0x828F: 0xFF4F, + 0x8290: 0xFF50, + 0x8291: 0xFF51, + 0x8292: 0xFF52, + 0x8293: 0xFF53, + 0x8294: 0xFF54, + 0x8295: 0xFF55, + 0x8296: 0xFF56, + 0x8297: 0xFF57, + 0x8298: 0xFF58, + 0x8299: 0xFF59, + 0x829A: 0xFF5A, + 0x829F: 0x3041, + 0x82A0: 0x3042, + 0x82A1: 0x3043, + 0x82A2: 0x3044, + 0x82A3: 0x3045, + 0x82A4: 0x3046, + 0x82A5: 0x3047, + 0x82A6: 0x3048, + 0x82A7: 0x3049, + 0x82A8: 0x304A, + 0x82A9: 0x304B, + 0x82AA: 0x304C, + 0x82AB: 0x304D, + 0x82AC: 0x304E, + 0x82AD: 0x304F, + 0x82AE: 0x3050, + 0x82AF: 0x3051, + 0x82B0: 0x3052, + 0x82B1: 0x3053, + 0x82B2: 0x3054, + 0x82B3: 0x3055, + 0x82B4: 0x3056, + 0x82B5: 0x3057, + 0x82B6: 0x3058, + 0x82B7: 0x3059, + 0x82B8: 0x305A, + 0x82B9: 0x305B, + 0x82BA: 0x305C, + 0x82BB: 0x305D, + 0x82BC: 0x305E, + 0x82BD: 0x305F, + 0x82BE: 0x3060, + 0x82BF: 0x3061, + 0x82C0: 0x3062, + 0x82C1: 0x3063, + 0x82C2: 0x3064, + 0x82C3: 0x3065, + 0x82C4: 0x3066, + 0x82C5: 0x3067, + 0x82C6: 0x3068, + 0x82C7: 0x3069, + 0x82C8: 0x306A, + 0x82C9: 0x306B, + 0x82CA: 0x306C, + 0x82CB: 0x306D, + 0x82CC: 0x306E, + 0x82CD: 0x306F, + 0x82CE: 0x3070, + 0x82CF: 0x3071, + 0x82D0: 0x3072, + 0x82D1: 0x3073, + 0x82D2: 0x3074, + 0x82D3: 0x3075, + 0x82D4: 0x3076, + 0x82D5: 0x3077, + 0x82D6: 0x3078, + 0x82D7: 0x3079, + 0x82D8: 0x307A, + 0x82D9: 0x307B, + 0x82DA: 0x307C, + 0x82DB: 0x307D, + 0x82DC: 0x307E, + 0x82DD: 0x307F, + 0x82DE: 0x3080, + 0x82DF: 0x3081, + 0x82E0: 0x3082, + 0x82E1: 0x3083, + 0x82E2: 0x3084, + 0x82E3: 0x3085, + 0x82E4: 0x3086, + 0x82E5: 0x3087, + 0x82E6: 0x3088, + 0x82E7: 0x3089, + 0x82E8: 0x308A, + 0x82E9: 0x308B, + 0x82EA: 0x308C, + 0x82EB: 0x308D, + 0x82EC: 0x308E, + 0x82ED: 0x308F, + 0x82EE: 0x3090, + 0x82EF: 0x3091, + 0x82F0: 0x3092, + 0x82F1: 0x3093, + 0x8340: 0x30A1, + 0x8341: 0x30A2, + 0x8342: 0x30A3, + 0x8343: 0x30A4, + 0x8344: 0x30A5, + 0x8345: 0x30A6, + 0x8346: 0x30A7, + 0x8347: 0x30A8, + 0x8348: 0x30A9, + 0x8349: 0x30AA, + 0x834A: 0x30AB, + 0x834B: 0x30AC, + 0x834C: 0x30AD, + 0x834D: 0x30AE, + 0x834E: 0x30AF, + 0x834F: 0x30B0, + 0x8350: 0x30B1, + 0x8351: 0x30B2, + 0x8352: 0x30B3, + 0x8353: 0x30B4, + 0x8354: 0x30B5, + 0x8355: 0x30B6, + 0x8356: 0x30B7, + 0x8357: 0x30B8, + 0x8358: 0x30B9, + 0x8359: 0x30BA, + 0x835A: 0x30BB, + 0x835B: 0x30BC, + 0x835C: 0x30BD, + 0x835D: 0x30BE, + 0x835E: 0x30BF, + 0x835F: 0x30C0, + 0x8360: 0x30C1, + 0x8361: 0x30C2, + 0x8362: 0x30C3, + 0x8363: 0x30C4, + 0x8364: 0x30C5, + 0x8365: 0x30C6, + 0x8366: 0x30C7, + 0x8367: 0x30C8, + 0x8368: 0x30C9, + 0x8369: 0x30CA, + 0x836A: 0x30CB, + 0x836B: 0x30CC, + 0x836C: 0x30CD, + 0x836D: 0x30CE, + 0x836E: 0x30CF, + 0x836F: 0x30D0, + 0x8370: 0x30D1, + 0x8371: 0x30D2, + 0x8372: 0x30D3, + 0x8373: 0x30D4, + 0x8374: 0x30D5, + 0x8375: 0x30D6, + 0x8376: 0x30D7, + 0x8377: 0x30D8, + 0x8378: 0x30D9, + 0x8379: 0x30DA, + 0x837A: 0x30DB, + 0x837B: 0x30DC, + 0x837C: 0x30DD, + 0x837D: 0x30DE, + 0x837E: 0x30DF, + 0x8380: 0x30E0, + 0x8381: 0x30E1, + 0x8382: 0x30E2, + 0x8383: 0x30E3, + 0x8384: 0x30E4, + 0x8385: 0x30E5, + 0x8386: 0x30E6, + 0x8387: 0x30E7, + 0x8388: 0x30E8, + 0x8389: 0x30E9, + 0x838A: 0x30EA, + 0x838B: 0x30EB, + 0x838C: 0x30EC, + 0x838D: 0x30ED, + 0x838E: 0x30EE, + 0x838F: 0x30EF, + 0x8390: 0x30F0, + 0x8391: 0x30F1, + 0x8392: 0x30F2, + 0x8393: 0x30F3, + 0x8394: 0x30F4, + 0x8395: 0x30F5, + 0x8396: 0x30F6, + 0x839F: 0x0391, + 0x83A0: 0x0392, + 0x83A1: 0x0393, + 0x83A2: 0x0394, + 0x83A3: 0x0395, + 0x83A4: 0x0396, + 0x83A5: 0x0397, + 0x83A6: 0x0398, + 0x83A7: 0x0399, + 0x83A8: 0x039A, + 0x83A9: 0x039B, + 0x83AA: 0x039C, + 0x83AB: 0x039D, + 0x83AC: 0x039E, + 0x83AD: 0x039F, + 0x83AE: 0x03A0, + 0x83AF: 0x03A1, + 0x83B0: 0x03A3, + 0x83B1: 0x03A4, + 0x83B2: 0x03A5, + 0x83B3: 0x03A6, + 0x83B4: 0x03A7, + 0x83B5: 0x03A8, + 0x83B6: 0x03A9, + 0x83BF: 0x03B1, + 0x83C0: 0x03B2, + 0x83C1: 0x03B3, + 0x83C2: 0x03B4, + 0x83C3: 0x03B5, + 0x83C4: 0x03B6, + 0x83C5: 0x03B7, + 0x83C6: 0x03B8, + 0x83C7: 0x03B9, + 0x83C8: 0x03BA, + 0x83C9: 0x03BB, + 0x83CA: 0x03BC, + 0x83CB: 0x03BD, + 0x83CC: 0x03BE, + 0x83CD: 0x03BF, + 0x83CE: 0x03C0, + 0x83CF: 0x03C1, + 0x83D0: 0x03C3, + 0x83D1: 0x03C4, + 0x83D2: 0x03C5, + 0x83D3: 0x03C6, + 0x83D4: 0x03C7, + 0x83D5: 0x03C8, + 0x83D6: 0x03C9, + 0x8440: 0x0410, + 0x8441: 0x0411, + 0x8442: 0x0412, + 0x8443: 0x0413, + 0x8444: 0x0414, + 0x8445: 0x0415, + 0x8446: 0x0401, + 0x8447: 0x0416, + 0x8448: 0x0417, + 0x8449: 0x0418, + 0x844A: 0x0419, + 0x844B: 0x041A, + 0x844C: 0x041B, + 0x844D: 0x041C, + 0x844E: 0x041D, + 0x844F: 0x041E, + 0x8450: 0x041F, + 0x8451: 0x0420, + 0x8452: 0x0421, + 0x8453: 0x0422, + 0x8454: 0x0423, + 0x8455: 0x0424, + 0x8456: 0x0425, + 0x8457: 0x0426, + 0x8458: 0x0427, + 0x8459: 0x0428, + 0x845A: 0x0429, + 0x845B: 0x042A, + 0x845C: 0x042B, + 0x845D: 0x042C, + 0x845E: 0x042D, + 0x845F: 0x042E, + 0x8460: 0x042F, + 0x8470: 0x0430, + 0x8471: 0x0431, + 0x8472: 0x0432, + 0x8473: 0x0433, + 0x8474: 0x0434, + 0x8475: 0x0435, + 0x8476: 0x0451, + 0x8477: 0x0436, + 0x8478: 0x0437, + 0x8479: 0x0438, + 0x847A: 0x0439, + 0x847B: 0x043A, + 0x847C: 0x043B, + 0x847D: 0x043C, + 0x847E: 0x043D, + 0x8480: 0x043E, + 0x8481: 0x043F, + 0x8482: 0x0440, + 0x8483: 0x0441, + 0x8484: 0x0442, + 0x8485: 0x0443, + 0x8486: 0x0444, + 0x8487: 0x0445, + 0x8488: 0x0446, + 0x8489: 0x0447, + 0x848A: 0x0448, + 0x848B: 0x0449, + 0x848C: 0x044A, + 0x848D: 0x044B, + 0x848E: 0x044C, + 0x848F: 0x044D, + 0x8490: 0x044E, + 0x8491: 0x044F, + 0x849F: 0x2500, + 0x84A0: 0x2502, + 0x84A1: 0x250C, + 0x84A2: 0x2510, + 0x84A3: 0x2518, + 0x84A4: 0x2514, + 0x84A5: 0x251C, + 0x84A6: 0x252C, + 0x84A7: 0x2524, + 0x84A8: 0x2534, + 0x84A9: 0x253C, + 0x84AA: 0x2501, + 0x84AB: 0x2503, + 0x84AC: 0x250F, + 0x84AD: 0x2513, + 0x84AE: 0x251B, + 0x84AF: 0x2517, + 0x84B0: 0x2523, + 0x84B1: 0x2533, + 0x84B2: 0x252B, + 0x84B3: 0x253B, + 0x84B4: 0x254B, + 0x84B5: 0x2520, + 0x84B6: 0x252F, + 0x84B7: 0x2528, + 0x84B8: 0x2537, + 0x84B9: 0x253F, + 0x84BA: 0x251D, + 0x84BB: 0x2530, + 0x84BC: 0x2525, + 0x84BD: 0x2538, + 0x84BE: 0x2542, + 0x889F: 0x4E9C, + 0x88A0: 0x5516, + 0x88A1: 0x5A03, + 0x88A2: 0x963F, + 0x88A3: 0x54C0, + 0x88A4: 0x611B, + 0x88A5: 0x6328, + 0x88A6: 0x59F6, + 0x88A7: 0x9022, + 0x88A8: 0x8475, + 0x88A9: 0x831C, + 0x88AA: 0x7A50, + 0x88AB: 0x60AA, + 0x88AC: 0x63E1, + 0x88AD: 0x6E25, + 0x88AE: 0x65ED, + 0x88AF: 0x8466, + 0x88B0: 0x82A6, + 0x88B1: 0x9BF5, + 0x88B2: 0x6893, + 0x88B3: 0x5727, + 0x88B4: 0x65A1, + 0x88B5: 0x6271, + 0x88B6: 0x5B9B, + 0x88B7: 0x59D0, + 0x88B8: 0x867B, + 0x88B9: 0x98F4, + 0x88BA: 0x7D62, + 0x88BB: 0x7DBE, + 0x88BC: 0x9B8E, + 0x88BD: 0x6216, + 0x88BE: 0x7C9F, + 0x88BF: 0x88B7, + 0x88C0: 0x5B89, + 0x88C1: 0x5EB5, + 0x88C2: 0x6309, + 0x88C3: 0x6697, + 0x88C4: 0x6848, + 0x88C5: 0x95C7, + 0x88C6: 0x978D, + 0x88C7: 0x674F, + 0x88C8: 0x4EE5, + 0x88C9: 0x4F0A, + 0x88CA: 0x4F4D, + 0x88CB: 0x4F9D, + 0x88CC: 0x5049, + 0x88CD: 0x56F2, + 0x88CE: 0x5937, + 0x88CF: 0x59D4, + 0x88D0: 0x5A01, + 0x88D1: 0x5C09, + 0x88D2: 0x60DF, + 0x88D3: 0x610F, + 0x88D4: 0x6170, + 0x88D5: 0x6613, + 0x88D6: 0x6905, + 0x88D7: 0x70BA, + 0x88D8: 0x754F, + 0x88D9: 0x7570, + 0x88DA: 0x79FB, + 0x88DB: 0x7DAD, + 0x88DC: 0x7DEF, + 0x88DD: 0x80C3, + 0x88DE: 0x840E, + 0x88DF: 0x8863, + 0x88E0: 0x8B02, + 0x88E1: 0x9055, + 0x88E2: 0x907A, + 0x88E3: 0x533B, + 0x88E4: 0x4E95, + 0x88E5: 0x4EA5, + 0x88E6: 0x57DF, + 0x88E7: 0x80B2, + 0x88E8: 0x90C1, + 0x88E9: 0x78EF, + 0x88EA: 0x4E00, + 0x88EB: 0x58F1, + 0x88EC: 0x6EA2, + 0x88ED: 0x9038, + 0x88EE: 0x7A32, + 0x88EF: 0x8328, + 0x88F0: 0x828B, + 0x88F1: 0x9C2F, + 0x88F2: 0x5141, + 0x88F3: 0x5370, + 0x88F4: 0x54BD, + 0x88F5: 0x54E1, + 0x88F6: 0x56E0, + 0x88F7: 0x59FB, + 0x88F8: 0x5F15, + 0x88F9: 0x98F2, + 0x88FA: 0x6DEB, + 0x88FB: 0x80E4, + 0x88FC: 0x852D, + 0x8940: 0x9662, + 0x8941: 0x9670, + 0x8942: 0x96A0, + 0x8943: 0x97FB, + 0x8944: 0x540B, + 0x8945: 0x53F3, + 0x8946: 0x5B87, + 0x8947: 0x70CF, + 0x8948: 0x7FBD, + 0x8949: 0x8FC2, + 0x894A: 0x96E8, + 0x894B: 0x536F, + 0x894C: 0x9D5C, + 0x894D: 0x7ABA, + 0x894E: 0x4E11, + 0x894F: 0x7893, + 0x8950: 0x81FC, + 0x8951: 0x6E26, + 0x8952: 0x5618, + 0x8953: 0x5504, + 0x8954: 0x6B1D, + 0x8955: 0x851A, + 0x8956: 0x9C3B, + 0x8957: 0x59E5, + 0x8958: 0x53A9, + 0x8959: 0x6D66, + 0x895A: 0x74DC, + 0x895B: 0x958F, + 0x895C: 0x5642, + 0x895D: 0x4E91, + 0x895E: 0x904B, + 0x895F: 0x96F2, + 0x8960: 0x834F, + 0x8961: 0x990C, + 0x8962: 0x53E1, + 0x8963: 0x55B6, + 0x8964: 0x5B30, + 0x8965: 0x5F71, + 0x8966: 0x6620, + 0x8967: 0x66F3, + 0x8968: 0x6804, + 0x8969: 0x6C38, + 0x896A: 0x6CF3, + 0x896B: 0x6D29, + 0x896C: 0x745B, + 0x896D: 0x76C8, + 0x896E: 0x7A4E, + 0x896F: 0x9834, + 0x8970: 0x82F1, + 0x8971: 0x885B, + 0x8972: 0x8A60, + 0x8973: 0x92ED, + 0x8974: 0x6DB2, + 0x8975: 0x75AB, + 0x8976: 0x76CA, + 0x8977: 0x99C5, + 0x8978: 0x60A6, + 0x8979: 0x8B01, + 0x897A: 0x8D8A, + 0x897B: 0x95B2, + 0x897C: 0x698E, + 0x897D: 0x53AD, + 0x897E: 0x5186, + 0x8980: 0x5712, + 0x8981: 0x5830, + 0x8982: 0x5944, + 0x8983: 0x5BB4, + 0x8984: 0x5EF6, + 0x8985: 0x6028, + 0x8986: 0x63A9, + 0x8987: 0x63F4, + 0x8988: 0x6CBF, + 0x8989: 0x6F14, + 0x898A: 0x708E, + 0x898B: 0x7114, + 0x898C: 0x7159, + 0x898D: 0x71D5, + 0x898E: 0x733F, + 0x898F: 0x7E01, + 0x8990: 0x8276, + 0x8991: 0x82D1, + 0x8992: 0x8597, + 0x8993: 0x9060, + 0x8994: 0x925B, + 0x8995: 0x9D1B, + 0x8996: 0x5869, + 0x8997: 0x65BC, + 0x8998: 0x6C5A, + 0x8999: 0x7525, + 0x899A: 0x51F9, + 0x899B: 0x592E, + 0x899C: 0x5965, + 0x899D: 0x5F80, + 0x899E: 0x5FDC, + 0x899F: 0x62BC, + 0x89A0: 0x65FA, + 0x89A1: 0x6A2A, + 0x89A2: 0x6B27, + 0x89A3: 0x6BB4, + 0x89A4: 0x738B, + 0x89A5: 0x7FC1, + 0x89A6: 0x8956, + 0x89A7: 0x9D2C, + 0x89A8: 0x9D0E, + 0x89A9: 0x9EC4, + 0x89AA: 0x5CA1, + 0x89AB: 0x6C96, + 0x89AC: 0x837B, + 0x89AD: 0x5104, + 0x89AE: 0x5C4B, + 0x89AF: 0x61B6, + 0x89B0: 0x81C6, + 0x89B1: 0x6876, + 0x89B2: 0x7261, + 0x89B3: 0x4E59, + 0x89B4: 0x4FFA, + 0x89B5: 0x5378, + 0x89B6: 0x6069, + 0x89B7: 0x6E29, + 0x89B8: 0x7A4F, + 0x89B9: 0x97F3, + 0x89BA: 0x4E0B, + 0x89BB: 0x5316, + 0x89BC: 0x4EEE, + 0x89BD: 0x4F55, + 0x89BE: 0x4F3D, + 0x89BF: 0x4FA1, + 0x89C0: 0x4F73, + 0x89C1: 0x52A0, + 0x89C2: 0x53EF, + 0x89C3: 0x5609, + 0x89C4: 0x590F, + 0x89C5: 0x5AC1, + 0x89C6: 0x5BB6, + 0x89C7: 0x5BE1, + 0x89C8: 0x79D1, + 0x89C9: 0x6687, + 0x89CA: 0x679C, + 0x89CB: 0x67B6, + 0x89CC: 0x6B4C, + 0x89CD: 0x6CB3, + 0x89CE: 0x706B, + 0x89CF: 0x73C2, + 0x89D0: 0x798D, + 0x89D1: 0x79BE, + 0x89D2: 0x7A3C, + 0x89D3: 0x7B87, + 0x89D4: 0x82B1, + 0x89D5: 0x82DB, + 0x89D6: 0x8304, + 0x89D7: 0x8377, + 0x89D8: 0x83EF, + 0x89D9: 0x83D3, + 0x89DA: 0x8766, + 0x89DB: 0x8AB2, + 0x89DC: 0x5629, + 0x89DD: 0x8CA8, + 0x89DE: 0x8FE6, + 0x89DF: 0x904E, + 0x89E0: 0x971E, + 0x89E1: 0x868A, + 0x89E2: 0x4FC4, + 0x89E3: 0x5CE8, + 0x89E4: 0x6211, + 0x89E5: 0x7259, + 0x89E6: 0x753B, + 0x89E7: 0x81E5, + 0x89E8: 0x82BD, + 0x89E9: 0x86FE, + 0x89EA: 0x8CC0, + 0x89EB: 0x96C5, + 0x89EC: 0x9913, + 0x89ED: 0x99D5, + 0x89EE: 0x4ECB, + 0x89EF: 0x4F1A, + 0x89F0: 0x89E3, + 0x89F1: 0x56DE, + 0x89F2: 0x584A, + 0x89F3: 0x58CA, + 0x89F4: 0x5EFB, + 0x89F5: 0x5FEB, + 0x89F6: 0x602A, + 0x89F7: 0x6094, + 0x89F8: 0x6062, + 0x89F9: 0x61D0, + 0x89FA: 0x6212, + 0x89FB: 0x62D0, + 0x89FC: 0x6539, + 0x8A40: 0x9B41, + 0x8A41: 0x6666, + 0x8A42: 0x68B0, + 0x8A43: 0x6D77, + 0x8A44: 0x7070, + 0x8A45: 0x754C, + 0x8A46: 0x7686, + 0x8A47: 0x7D75, + 0x8A48: 0x82A5, + 0x8A49: 0x87F9, + 0x8A4A: 0x958B, + 0x8A4B: 0x968E, + 0x8A4C: 0x8C9D, + 0x8A4D: 0x51F1, + 0x8A4E: 0x52BE, + 0x8A4F: 0x5916, + 0x8A50: 0x54B3, + 0x8A51: 0x5BB3, + 0x8A52: 0x5D16, + 0x8A53: 0x6168, + 0x8A54: 0x6982, + 0x8A55: 0x6DAF, + 0x8A56: 0x788D, + 0x8A57: 0x84CB, + 0x8A58: 0x8857, + 0x8A59: 0x8A72, + 0x8A5A: 0x93A7, + 0x8A5B: 0x9AB8, + 0x8A5C: 0x6D6C, + 0x8A5D: 0x99A8, + 0x8A5E: 0x86D9, + 0x8A5F: 0x57A3, + 0x8A60: 0x67FF, + 0x8A61: 0x86CE, + 0x8A62: 0x920E, + 0x8A63: 0x5283, + 0x8A64: 0x5687, + 0x8A65: 0x5404, + 0x8A66: 0x5ED3, + 0x8A67: 0x62E1, + 0x8A68: 0x64B9, + 0x8A69: 0x683C, + 0x8A6A: 0x6838, + 0x8A6B: 0x6BBB, + 0x8A6C: 0x7372, + 0x8A6D: 0x78BA, + 0x8A6E: 0x7A6B, + 0x8A6F: 0x899A, + 0x8A70: 0x89D2, + 0x8A71: 0x8D6B, + 0x8A72: 0x8F03, + 0x8A73: 0x90ED, + 0x8A74: 0x95A3, + 0x8A75: 0x9694, + 0x8A76: 0x9769, + 0x8A77: 0x5B66, + 0x8A78: 0x5CB3, + 0x8A79: 0x697D, + 0x8A7A: 0x984D, + 0x8A7B: 0x984E, + 0x8A7C: 0x639B, + 0x8A7D: 0x7B20, + 0x8A7E: 0x6A2B, + 0x8A80: 0x6A7F, + 0x8A81: 0x68B6, + 0x8A82: 0x9C0D, + 0x8A83: 0x6F5F, + 0x8A84: 0x5272, + 0x8A85: 0x559D, + 0x8A86: 0x6070, + 0x8A87: 0x62EC, + 0x8A88: 0x6D3B, + 0x8A89: 0x6E07, + 0x8A8A: 0x6ED1, + 0x8A8B: 0x845B, + 0x8A8C: 0x8910, + 0x8A8D: 0x8F44, + 0x8A8E: 0x4E14, + 0x8A8F: 0x9C39, + 0x8A90: 0x53F6, + 0x8A91: 0x691B, + 0x8A92: 0x6A3A, + 0x8A93: 0x9784, + 0x8A94: 0x682A, + 0x8A95: 0x515C, + 0x8A96: 0x7AC3, + 0x8A97: 0x84B2, + 0x8A98: 0x91DC, + 0x8A99: 0x938C, + 0x8A9A: 0x565B, + 0x8A9B: 0x9D28, + 0x8A9C: 0x6822, + 0x8A9D: 0x8305, + 0x8A9E: 0x8431, + 0x8A9F: 0x7CA5, + 0x8AA0: 0x5208, + 0x8AA1: 0x82C5, + 0x8AA2: 0x74E6, + 0x8AA3: 0x4E7E, + 0x8AA4: 0x4F83, + 0x8AA5: 0x51A0, + 0x8AA6: 0x5BD2, + 0x8AA7: 0x520A, + 0x8AA8: 0x52D8, + 0x8AA9: 0x52E7, + 0x8AAA: 0x5DFB, + 0x8AAB: 0x559A, + 0x8AAC: 0x582A, + 0x8AAD: 0x59E6, + 0x8AAE: 0x5B8C, + 0x8AAF: 0x5B98, + 0x8AB0: 0x5BDB, + 0x8AB1: 0x5E72, + 0x8AB2: 0x5E79, + 0x8AB3: 0x60A3, + 0x8AB4: 0x611F, + 0x8AB5: 0x6163, + 0x8AB6: 0x61BE, + 0x8AB7: 0x63DB, + 0x8AB8: 0x6562, + 0x8AB9: 0x67D1, + 0x8ABA: 0x6853, + 0x8ABB: 0x68FA, + 0x8ABC: 0x6B3E, + 0x8ABD: 0x6B53, + 0x8ABE: 0x6C57, + 0x8ABF: 0x6F22, + 0x8AC0: 0x6F97, + 0x8AC1: 0x6F45, + 0x8AC2: 0x74B0, + 0x8AC3: 0x7518, + 0x8AC4: 0x76E3, + 0x8AC5: 0x770B, + 0x8AC6: 0x7AFF, + 0x8AC7: 0x7BA1, + 0x8AC8: 0x7C21, + 0x8AC9: 0x7DE9, + 0x8ACA: 0x7F36, + 0x8ACB: 0x7FF0, + 0x8ACC: 0x809D, + 0x8ACD: 0x8266, + 0x8ACE: 0x839E, + 0x8ACF: 0x89B3, + 0x8AD0: 0x8ACC, + 0x8AD1: 0x8CAB, + 0x8AD2: 0x9084, + 0x8AD3: 0x9451, + 0x8AD4: 0x9593, + 0x8AD5: 0x9591, + 0x8AD6: 0x95A2, + 0x8AD7: 0x9665, + 0x8AD8: 0x97D3, + 0x8AD9: 0x9928, + 0x8ADA: 0x8218, + 0x8ADB: 0x4E38, + 0x8ADC: 0x542B, + 0x8ADD: 0x5CB8, + 0x8ADE: 0x5DCC, + 0x8ADF: 0x73A9, + 0x8AE0: 0x764C, + 0x8AE1: 0x773C, + 0x8AE2: 0x5CA9, + 0x8AE3: 0x7FEB, + 0x8AE4: 0x8D0B, + 0x8AE5: 0x96C1, + 0x8AE6: 0x9811, + 0x8AE7: 0x9854, + 0x8AE8: 0x9858, + 0x8AE9: 0x4F01, + 0x8AEA: 0x4F0E, + 0x8AEB: 0x5371, + 0x8AEC: 0x559C, + 0x8AED: 0x5668, + 0x8AEE: 0x57FA, + 0x8AEF: 0x5947, + 0x8AF0: 0x5B09, + 0x8AF1: 0x5BC4, + 0x8AF2: 0x5C90, + 0x8AF3: 0x5E0C, + 0x8AF4: 0x5E7E, + 0x8AF5: 0x5FCC, + 0x8AF6: 0x63EE, + 0x8AF7: 0x673A, + 0x8AF8: 0x65D7, + 0x8AF9: 0x65E2, + 0x8AFA: 0x671F, + 0x8AFB: 0x68CB, + 0x8AFC: 0x68C4, + 0x8B40: 0x6A5F, + 0x8B41: 0x5E30, + 0x8B42: 0x6BC5, + 0x8B43: 0x6C17, + 0x8B44: 0x6C7D, + 0x8B45: 0x757F, + 0x8B46: 0x7948, + 0x8B47: 0x5B63, + 0x8B48: 0x7A00, + 0x8B49: 0x7D00, + 0x8B4A: 0x5FBD, + 0x8B4B: 0x898F, + 0x8B4C: 0x8A18, + 0x8B4D: 0x8CB4, + 0x8B4E: 0x8D77, + 0x8B4F: 0x8ECC, + 0x8B50: 0x8F1D, + 0x8B51: 0x98E2, + 0x8B52: 0x9A0E, + 0x8B53: 0x9B3C, + 0x8B54: 0x4E80, + 0x8B55: 0x507D, + 0x8B56: 0x5100, + 0x8B57: 0x5993, + 0x8B58: 0x5B9C, + 0x8B59: 0x622F, + 0x8B5A: 0x6280, + 0x8B5B: 0x64EC, + 0x8B5C: 0x6B3A, + 0x8B5D: 0x72A0, + 0x8B5E: 0x7591, + 0x8B5F: 0x7947, + 0x8B60: 0x7FA9, + 0x8B61: 0x87FB, + 0x8B62: 0x8ABC, + 0x8B63: 0x8B70, + 0x8B64: 0x63AC, + 0x8B65: 0x83CA, + 0x8B66: 0x97A0, + 0x8B67: 0x5409, + 0x8B68: 0x5403, + 0x8B69: 0x55AB, + 0x8B6A: 0x6854, + 0x8B6B: 0x6A58, + 0x8B6C: 0x8A70, + 0x8B6D: 0x7827, + 0x8B6E: 0x6775, + 0x8B6F: 0x9ECD, + 0x8B70: 0x5374, + 0x8B71: 0x5BA2, + 0x8B72: 0x811A, + 0x8B73: 0x8650, + 0x8B74: 0x9006, + 0x8B75: 0x4E18, + 0x8B76: 0x4E45, + 0x8B77: 0x4EC7, + 0x8B78: 0x4F11, + 0x8B79: 0x53CA, + 0x8B7A: 0x5438, + 0x8B7B: 0x5BAE, + 0x8B7C: 0x5F13, + 0x8B7D: 0x6025, + 0x8B7E: 0x6551, + 0x8B80: 0x673D, + 0x8B81: 0x6C42, + 0x8B82: 0x6C72, + 0x8B83: 0x6CE3, + 0x8B84: 0x7078, + 0x8B85: 0x7403, + 0x8B86: 0x7A76, + 0x8B87: 0x7AAE, + 0x8B88: 0x7B08, + 0x8B89: 0x7D1A, + 0x8B8A: 0x7CFE, + 0x8B8B: 0x7D66, + 0x8B8C: 0x65E7, + 0x8B8D: 0x725B, + 0x8B8E: 0x53BB, + 0x8B8F: 0x5C45, + 0x8B90: 0x5DE8, + 0x8B91: 0x62D2, + 0x8B92: 0x62E0, + 0x8B93: 0x6319, + 0x8B94: 0x6E20, + 0x8B95: 0x865A, + 0x8B96: 0x8A31, + 0x8B97: 0x8DDD, + 0x8B98: 0x92F8, + 0x8B99: 0x6F01, + 0x8B9A: 0x79A6, + 0x8B9B: 0x9B5A, + 0x8B9C: 0x4EA8, + 0x8B9D: 0x4EAB, + 0x8B9E: 0x4EAC, + 0x8B9F: 0x4F9B, + 0x8BA0: 0x4FA0, + 0x8BA1: 0x50D1, + 0x8BA2: 0x5147, + 0x8BA3: 0x7AF6, + 0x8BA4: 0x5171, + 0x8BA5: 0x51F6, + 0x8BA6: 0x5354, + 0x8BA7: 0x5321, + 0x8BA8: 0x537F, + 0x8BA9: 0x53EB, + 0x8BAA: 0x55AC, + 0x8BAB: 0x5883, + 0x8BAC: 0x5CE1, + 0x8BAD: 0x5F37, + 0x8BAE: 0x5F4A, + 0x8BAF: 0x602F, + 0x8BB0: 0x6050, + 0x8BB1: 0x606D, + 0x8BB2: 0x631F, + 0x8BB3: 0x6559, + 0x8BB4: 0x6A4B, + 0x8BB5: 0x6CC1, + 0x8BB6: 0x72C2, + 0x8BB7: 0x72ED, + 0x8BB8: 0x77EF, + 0x8BB9: 0x80F8, + 0x8BBA: 0x8105, + 0x8BBB: 0x8208, + 0x8BBC: 0x854E, + 0x8BBD: 0x90F7, + 0x8BBE: 0x93E1, + 0x8BBF: 0x97FF, + 0x8BC0: 0x9957, + 0x8BC1: 0x9A5A, + 0x8BC2: 0x4EF0, + 0x8BC3: 0x51DD, + 0x8BC4: 0x5C2D, + 0x8BC5: 0x6681, + 0x8BC6: 0x696D, + 0x8BC7: 0x5C40, + 0x8BC8: 0x66F2, + 0x8BC9: 0x6975, + 0x8BCA: 0x7389, + 0x8BCB: 0x6850, + 0x8BCC: 0x7C81, + 0x8BCD: 0x50C5, + 0x8BCE: 0x52E4, + 0x8BCF: 0x5747, + 0x8BD0: 0x5DFE, + 0x8BD1: 0x9326, + 0x8BD2: 0x65A4, + 0x8BD3: 0x6B23, + 0x8BD4: 0x6B3D, + 0x8BD5: 0x7434, + 0x8BD6: 0x7981, + 0x8BD7: 0x79BD, + 0x8BD8: 0x7B4B, + 0x8BD9: 0x7DCA, + 0x8BDA: 0x82B9, + 0x8BDB: 0x83CC, + 0x8BDC: 0x887F, + 0x8BDD: 0x895F, + 0x8BDE: 0x8B39, + 0x8BDF: 0x8FD1, + 0x8BE0: 0x91D1, + 0x8BE1: 0x541F, + 0x8BE2: 0x9280, + 0x8BE3: 0x4E5D, + 0x8BE4: 0x5036, + 0x8BE5: 0x53E5, + 0x8BE6: 0x533A, + 0x8BE7: 0x72D7, + 0x8BE8: 0x7396, + 0x8BE9: 0x77E9, + 0x8BEA: 0x82E6, + 0x8BEB: 0x8EAF, + 0x8BEC: 0x99C6, + 0x8BED: 0x99C8, + 0x8BEE: 0x99D2, + 0x8BEF: 0x5177, + 0x8BF0: 0x611A, + 0x8BF1: 0x865E, + 0x8BF2: 0x55B0, + 0x8BF3: 0x7A7A, + 0x8BF4: 0x5076, + 0x8BF5: 0x5BD3, + 0x8BF6: 0x9047, + 0x8BF7: 0x9685, + 0x8BF8: 0x4E32, + 0x8BF9: 0x6ADB, + 0x8BFA: 0x91E7, + 0x8BFB: 0x5C51, + 0x8BFC: 0x5C48, + 0x8C40: 0x6398, + 0x8C41: 0x7A9F, + 0x8C42: 0x6C93, + 0x8C43: 0x9774, + 0x8C44: 0x8F61, + 0x8C45: 0x7AAA, + 0x8C46: 0x718A, + 0x8C47: 0x9688, + 0x8C48: 0x7C82, + 0x8C49: 0x6817, + 0x8C4A: 0x7E70, + 0x8C4B: 0x6851, + 0x8C4C: 0x936C, + 0x8C4D: 0x52F2, + 0x8C4E: 0x541B, + 0x8C4F: 0x85AB, + 0x8C50: 0x8A13, + 0x8C51: 0x7FA4, + 0x8C52: 0x8ECD, + 0x8C53: 0x90E1, + 0x8C54: 0x5366, + 0x8C55: 0x8888, + 0x8C56: 0x7941, + 0x8C57: 0x4FC2, + 0x8C58: 0x50BE, + 0x8C59: 0x5211, + 0x8C5A: 0x5144, + 0x8C5B: 0x5553, + 0x8C5C: 0x572D, + 0x8C5D: 0x73EA, + 0x8C5E: 0x578B, + 0x8C5F: 0x5951, + 0x8C60: 0x5F62, + 0x8C61: 0x5F84, + 0x8C62: 0x6075, + 0x8C63: 0x6176, + 0x8C64: 0x6167, + 0x8C65: 0x61A9, + 0x8C66: 0x63B2, + 0x8C67: 0x643A, + 0x8C68: 0x656C, + 0x8C69: 0x666F, + 0x8C6A: 0x6842, + 0x8C6B: 0x6E13, + 0x8C6C: 0x7566, + 0x8C6D: 0x7A3D, + 0x8C6E: 0x7CFB, + 0x8C6F: 0x7D4C, + 0x8C70: 0x7D99, + 0x8C71: 0x7E4B, + 0x8C72: 0x7F6B, + 0x8C73: 0x830E, + 0x8C74: 0x834A, + 0x8C75: 0x86CD, + 0x8C76: 0x8A08, + 0x8C77: 0x8A63, + 0x8C78: 0x8B66, + 0x8C79: 0x8EFD, + 0x8C7A: 0x981A, + 0x8C7B: 0x9D8F, + 0x8C7C: 0x82B8, + 0x8C7D: 0x8FCE, + 0x8C7E: 0x9BE8, + 0x8C80: 0x5287, + 0x8C81: 0x621F, + 0x8C82: 0x6483, + 0x8C83: 0x6FC0, + 0x8C84: 0x9699, + 0x8C85: 0x6841, + 0x8C86: 0x5091, + 0x8C87: 0x6B20, + 0x8C88: 0x6C7A, + 0x8C89: 0x6F54, + 0x8C8A: 0x7A74, + 0x8C8B: 0x7D50, + 0x8C8C: 0x8840, + 0x8C8D: 0x8A23, + 0x8C8E: 0x6708, + 0x8C8F: 0x4EF6, + 0x8C90: 0x5039, + 0x8C91: 0x5026, + 0x8C92: 0x5065, + 0x8C93: 0x517C, + 0x8C94: 0x5238, + 0x8C95: 0x5263, + 0x8C96: 0x55A7, + 0x8C97: 0x570F, + 0x8C98: 0x5805, + 0x8C99: 0x5ACC, + 0x8C9A: 0x5EFA, + 0x8C9B: 0x61B2, + 0x8C9C: 0x61F8, + 0x8C9D: 0x62F3, + 0x8C9E: 0x6372, + 0x8C9F: 0x691C, + 0x8CA0: 0x6A29, + 0x8CA1: 0x727D, + 0x8CA2: 0x72AC, + 0x8CA3: 0x732E, + 0x8CA4: 0x7814, + 0x8CA5: 0x786F, + 0x8CA6: 0x7D79, + 0x8CA7: 0x770C, + 0x8CA8: 0x80A9, + 0x8CA9: 0x898B, + 0x8CAA: 0x8B19, + 0x8CAB: 0x8CE2, + 0x8CAC: 0x8ED2, + 0x8CAD: 0x9063, + 0x8CAE: 0x9375, + 0x8CAF: 0x967A, + 0x8CB0: 0x9855, + 0x8CB1: 0x9A13, + 0x8CB2: 0x9E78, + 0x8CB3: 0x5143, + 0x8CB4: 0x539F, + 0x8CB5: 0x53B3, + 0x8CB6: 0x5E7B, + 0x8CB7: 0x5F26, + 0x8CB8: 0x6E1B, + 0x8CB9: 0x6E90, + 0x8CBA: 0x7384, + 0x8CBB: 0x73FE, + 0x8CBC: 0x7D43, + 0x8CBD: 0x8237, + 0x8CBE: 0x8A00, + 0x8CBF: 0x8AFA, + 0x8CC0: 0x9650, + 0x8CC1: 0x4E4E, + 0x8CC2: 0x500B, + 0x8CC3: 0x53E4, + 0x8CC4: 0x547C, + 0x8CC5: 0x56FA, + 0x8CC6: 0x59D1, + 0x8CC7: 0x5B64, + 0x8CC8: 0x5DF1, + 0x8CC9: 0x5EAB, + 0x8CCA: 0x5F27, + 0x8CCB: 0x6238, + 0x8CCC: 0x6545, + 0x8CCD: 0x67AF, + 0x8CCE: 0x6E56, + 0x8CCF: 0x72D0, + 0x8CD0: 0x7CCA, + 0x8CD1: 0x88B4, + 0x8CD2: 0x80A1, + 0x8CD3: 0x80E1, + 0x8CD4: 0x83F0, + 0x8CD5: 0x864E, + 0x8CD6: 0x8A87, + 0x8CD7: 0x8DE8, + 0x8CD8: 0x9237, + 0x8CD9: 0x96C7, + 0x8CDA: 0x9867, + 0x8CDB: 0x9F13, + 0x8CDC: 0x4E94, + 0x8CDD: 0x4E92, + 0x8CDE: 0x4F0D, + 0x8CDF: 0x5348, + 0x8CE0: 0x5449, + 0x8CE1: 0x543E, + 0x8CE2: 0x5A2F, + 0x8CE3: 0x5F8C, + 0x8CE4: 0x5FA1, + 0x8CE5: 0x609F, + 0x8CE6: 0x68A7, + 0x8CE7: 0x6A8E, + 0x8CE8: 0x745A, + 0x8CE9: 0x7881, + 0x8CEA: 0x8A9E, + 0x8CEB: 0x8AA4, + 0x8CEC: 0x8B77, + 0x8CED: 0x9190, + 0x8CEE: 0x4E5E, + 0x8CEF: 0x9BC9, + 0x8CF0: 0x4EA4, + 0x8CF1: 0x4F7C, + 0x8CF2: 0x4FAF, + 0x8CF3: 0x5019, + 0x8CF4: 0x5016, + 0x8CF5: 0x5149, + 0x8CF6: 0x516C, + 0x8CF7: 0x529F, + 0x8CF8: 0x52B9, + 0x8CF9: 0x52FE, + 0x8CFA: 0x539A, + 0x8CFB: 0x53E3, + 0x8CFC: 0x5411, + 0x8D40: 0x540E, + 0x8D41: 0x5589, + 0x8D42: 0x5751, + 0x8D43: 0x57A2, + 0x8D44: 0x597D, + 0x8D45: 0x5B54, + 0x8D46: 0x5B5D, + 0x8D47: 0x5B8F, + 0x8D48: 0x5DE5, + 0x8D49: 0x5DE7, + 0x8D4A: 0x5DF7, + 0x8D4B: 0x5E78, + 0x8D4C: 0x5E83, + 0x8D4D: 0x5E9A, + 0x8D4E: 0x5EB7, + 0x8D4F: 0x5F18, + 0x8D50: 0x6052, + 0x8D51: 0x614C, + 0x8D52: 0x6297, + 0x8D53: 0x62D8, + 0x8D54: 0x63A7, + 0x8D55: 0x653B, + 0x8D56: 0x6602, + 0x8D57: 0x6643, + 0x8D58: 0x66F4, + 0x8D59: 0x676D, + 0x8D5A: 0x6821, + 0x8D5B: 0x6897, + 0x8D5C: 0x69CB, + 0x8D5D: 0x6C5F, + 0x8D5E: 0x6D2A, + 0x8D5F: 0x6D69, + 0x8D60: 0x6E2F, + 0x8D61: 0x6E9D, + 0x8D62: 0x7532, + 0x8D63: 0x7687, + 0x8D64: 0x786C, + 0x8D65: 0x7A3F, + 0x8D66: 0x7CE0, + 0x8D67: 0x7D05, + 0x8D68: 0x7D18, + 0x8D69: 0x7D5E, + 0x8D6A: 0x7DB1, + 0x8D6B: 0x8015, + 0x8D6C: 0x8003, + 0x8D6D: 0x80AF, + 0x8D6E: 0x80B1, + 0x8D6F: 0x8154, + 0x8D70: 0x818F, + 0x8D71: 0x822A, + 0x8D72: 0x8352, + 0x8D73: 0x884C, + 0x8D74: 0x8861, + 0x8D75: 0x8B1B, + 0x8D76: 0x8CA2, + 0x8D77: 0x8CFC, + 0x8D78: 0x90CA, + 0x8D79: 0x9175, + 0x8D7A: 0x9271, + 0x8D7B: 0x783F, + 0x8D7C: 0x92FC, + 0x8D7D: 0x95A4, + 0x8D7E: 0x964D, + 0x8D80: 0x9805, + 0x8D81: 0x9999, + 0x8D82: 0x9AD8, + 0x8D83: 0x9D3B, + 0x8D84: 0x525B, + 0x8D85: 0x52AB, + 0x8D86: 0x53F7, + 0x8D87: 0x5408, + 0x8D88: 0x58D5, + 0x8D89: 0x62F7, + 0x8D8A: 0x6FE0, + 0x8D8B: 0x8C6A, + 0x8D8C: 0x8F5F, + 0x8D8D: 0x9EB9, + 0x8D8E: 0x514B, + 0x8D8F: 0x523B, + 0x8D90: 0x544A, + 0x8D91: 0x56FD, + 0x8D92: 0x7A40, + 0x8D93: 0x9177, + 0x8D94: 0x9D60, + 0x8D95: 0x9ED2, + 0x8D96: 0x7344, + 0x8D97: 0x6F09, + 0x8D98: 0x8170, + 0x8D99: 0x7511, + 0x8D9A: 0x5FFD, + 0x8D9B: 0x60DA, + 0x8D9C: 0x9AA8, + 0x8D9D: 0x72DB, + 0x8D9E: 0x8FBC, + 0x8D9F: 0x6B64, + 0x8DA0: 0x9803, + 0x8DA1: 0x4ECA, + 0x8DA2: 0x56F0, + 0x8DA3: 0x5764, + 0x8DA4: 0x58BE, + 0x8DA5: 0x5A5A, + 0x8DA6: 0x6068, + 0x8DA7: 0x61C7, + 0x8DA8: 0x660F, + 0x8DA9: 0x6606, + 0x8DAA: 0x6839, + 0x8DAB: 0x68B1, + 0x8DAC: 0x6DF7, + 0x8DAD: 0x75D5, + 0x8DAE: 0x7D3A, + 0x8DAF: 0x826E, + 0x8DB0: 0x9B42, + 0x8DB1: 0x4E9B, + 0x8DB2: 0x4F50, + 0x8DB3: 0x53C9, + 0x8DB4: 0x5506, + 0x8DB5: 0x5D6F, + 0x8DB6: 0x5DE6, + 0x8DB7: 0x5DEE, + 0x8DB8: 0x67FB, + 0x8DB9: 0x6C99, + 0x8DBA: 0x7473, + 0x8DBB: 0x7802, + 0x8DBC: 0x8A50, + 0x8DBD: 0x9396, + 0x8DBE: 0x88DF, + 0x8DBF: 0x5750, + 0x8DC0: 0x5EA7, + 0x8DC1: 0x632B, + 0x8DC2: 0x50B5, + 0x8DC3: 0x50AC, + 0x8DC4: 0x518D, + 0x8DC5: 0x6700, + 0x8DC6: 0x54C9, + 0x8DC7: 0x585E, + 0x8DC8: 0x59BB, + 0x8DC9: 0x5BB0, + 0x8DCA: 0x5F69, + 0x8DCB: 0x624D, + 0x8DCC: 0x63A1, + 0x8DCD: 0x683D, + 0x8DCE: 0x6B73, + 0x8DCF: 0x6E08, + 0x8DD0: 0x707D, + 0x8DD1: 0x91C7, + 0x8DD2: 0x7280, + 0x8DD3: 0x7815, + 0x8DD4: 0x7826, + 0x8DD5: 0x796D, + 0x8DD6: 0x658E, + 0x8DD7: 0x7D30, + 0x8DD8: 0x83DC, + 0x8DD9: 0x88C1, + 0x8DDA: 0x8F09, + 0x8DDB: 0x969B, + 0x8DDC: 0x5264, + 0x8DDD: 0x5728, + 0x8DDE: 0x6750, + 0x8DDF: 0x7F6A, + 0x8DE0: 0x8CA1, + 0x8DE1: 0x51B4, + 0x8DE2: 0x5742, + 0x8DE3: 0x962A, + 0x8DE4: 0x583A, + 0x8DE5: 0x698A, + 0x8DE6: 0x80B4, + 0x8DE7: 0x54B2, + 0x8DE8: 0x5D0E, + 0x8DE9: 0x57FC, + 0x8DEA: 0x7895, + 0x8DEB: 0x9DFA, + 0x8DEC: 0x4F5C, + 0x8DED: 0x524A, + 0x8DEE: 0x548B, + 0x8DEF: 0x643E, + 0x8DF0: 0x6628, + 0x8DF1: 0x6714, + 0x8DF2: 0x67F5, + 0x8DF3: 0x7A84, + 0x8DF4: 0x7B56, + 0x8DF5: 0x7D22, + 0x8DF6: 0x932F, + 0x8DF7: 0x685C, + 0x8DF8: 0x9BAD, + 0x8DF9: 0x7B39, + 0x8DFA: 0x5319, + 0x8DFB: 0x518A, + 0x8DFC: 0x5237, + 0x8E40: 0x5BDF, + 0x8E41: 0x62F6, + 0x8E42: 0x64AE, + 0x8E43: 0x64E6, + 0x8E44: 0x672D, + 0x8E45: 0x6BBA, + 0x8E46: 0x85A9, + 0x8E47: 0x96D1, + 0x8E48: 0x7690, + 0x8E49: 0x9BD6, + 0x8E4A: 0x634C, + 0x8E4B: 0x9306, + 0x8E4C: 0x9BAB, + 0x8E4D: 0x76BF, + 0x8E4E: 0x6652, + 0x8E4F: 0x4E09, + 0x8E50: 0x5098, + 0x8E51: 0x53C2, + 0x8E52: 0x5C71, + 0x8E53: 0x60E8, + 0x8E54: 0x6492, + 0x8E55: 0x6563, + 0x8E56: 0x685F, + 0x8E57: 0x71E6, + 0x8E58: 0x73CA, + 0x8E59: 0x7523, + 0x8E5A: 0x7B97, + 0x8E5B: 0x7E82, + 0x8E5C: 0x8695, + 0x8E5D: 0x8B83, + 0x8E5E: 0x8CDB, + 0x8E5F: 0x9178, + 0x8E60: 0x9910, + 0x8E61: 0x65AC, + 0x8E62: 0x66AB, + 0x8E63: 0x6B8B, + 0x8E64: 0x4ED5, + 0x8E65: 0x4ED4, + 0x8E66: 0x4F3A, + 0x8E67: 0x4F7F, + 0x8E68: 0x523A, + 0x8E69: 0x53F8, + 0x8E6A: 0x53F2, + 0x8E6B: 0x55E3, + 0x8E6C: 0x56DB, + 0x8E6D: 0x58EB, + 0x8E6E: 0x59CB, + 0x8E6F: 0x59C9, + 0x8E70: 0x59FF, + 0x8E71: 0x5B50, + 0x8E72: 0x5C4D, + 0x8E73: 0x5E02, + 0x8E74: 0x5E2B, + 0x8E75: 0x5FD7, + 0x8E76: 0x601D, + 0x8E77: 0x6307, + 0x8E78: 0x652F, + 0x8E79: 0x5B5C, + 0x8E7A: 0x65AF, + 0x8E7B: 0x65BD, + 0x8E7C: 0x65E8, + 0x8E7D: 0x679D, + 0x8E7E: 0x6B62, + 0x8E80: 0x6B7B, + 0x8E81: 0x6C0F, + 0x8E82: 0x7345, + 0x8E83: 0x7949, + 0x8E84: 0x79C1, + 0x8E85: 0x7CF8, + 0x8E86: 0x7D19, + 0x8E87: 0x7D2B, + 0x8E88: 0x80A2, + 0x8E89: 0x8102, + 0x8E8A: 0x81F3, + 0x8E8B: 0x8996, + 0x8E8C: 0x8A5E, + 0x8E8D: 0x8A69, + 0x8E8E: 0x8A66, + 0x8E8F: 0x8A8C, + 0x8E90: 0x8AEE, + 0x8E91: 0x8CC7, + 0x8E92: 0x8CDC, + 0x8E93: 0x96CC, + 0x8E94: 0x98FC, + 0x8E95: 0x6B6F, + 0x8E96: 0x4E8B, + 0x8E97: 0x4F3C, + 0x8E98: 0x4F8D, + 0x8E99: 0x5150, + 0x8E9A: 0x5B57, + 0x8E9B: 0x5BFA, + 0x8E9C: 0x6148, + 0x8E9D: 0x6301, + 0x8E9E: 0x6642, + 0x8E9F: 0x6B21, + 0x8EA0: 0x6ECB, + 0x8EA1: 0x6CBB, + 0x8EA2: 0x723E, + 0x8EA3: 0x74BD, + 0x8EA4: 0x75D4, + 0x8EA5: 0x78C1, + 0x8EA6: 0x793A, + 0x8EA7: 0x800C, + 0x8EA8: 0x8033, + 0x8EA9: 0x81EA, + 0x8EAA: 0x8494, + 0x8EAB: 0x8F9E, + 0x8EAC: 0x6C50, + 0x8EAD: 0x9E7F, + 0x8EAE: 0x5F0F, + 0x8EAF: 0x8B58, + 0x8EB0: 0x9D2B, + 0x8EB1: 0x7AFA, + 0x8EB2: 0x8EF8, + 0x8EB3: 0x5B8D, + 0x8EB4: 0x96EB, + 0x8EB5: 0x4E03, + 0x8EB6: 0x53F1, + 0x8EB7: 0x57F7, + 0x8EB8: 0x5931, + 0x8EB9: 0x5AC9, + 0x8EBA: 0x5BA4, + 0x8EBB: 0x6089, + 0x8EBC: 0x6E7F, + 0x8EBD: 0x6F06, + 0x8EBE: 0x75BE, + 0x8EBF: 0x8CEA, + 0x8EC0: 0x5B9F, + 0x8EC1: 0x8500, + 0x8EC2: 0x7BE0, + 0x8EC3: 0x5072, + 0x8EC4: 0x67F4, + 0x8EC5: 0x829D, + 0x8EC6: 0x5C61, + 0x8EC7: 0x854A, + 0x8EC8: 0x7E1E, + 0x8EC9: 0x820E, + 0x8ECA: 0x5199, + 0x8ECB: 0x5C04, + 0x8ECC: 0x6368, + 0x8ECD: 0x8D66, + 0x8ECE: 0x659C, + 0x8ECF: 0x716E, + 0x8ED0: 0x793E, + 0x8ED1: 0x7D17, + 0x8ED2: 0x8005, + 0x8ED3: 0x8B1D, + 0x8ED4: 0x8ECA, + 0x8ED5: 0x906E, + 0x8ED6: 0x86C7, + 0x8ED7: 0x90AA, + 0x8ED8: 0x501F, + 0x8ED9: 0x52FA, + 0x8EDA: 0x5C3A, + 0x8EDB: 0x6753, + 0x8EDC: 0x707C, + 0x8EDD: 0x7235, + 0x8EDE: 0x914C, + 0x8EDF: 0x91C8, + 0x8EE0: 0x932B, + 0x8EE1: 0x82E5, + 0x8EE2: 0x5BC2, + 0x8EE3: 0x5F31, + 0x8EE4: 0x60F9, + 0x8EE5: 0x4E3B, + 0x8EE6: 0x53D6, + 0x8EE7: 0x5B88, + 0x8EE8: 0x624B, + 0x8EE9: 0x6731, + 0x8EEA: 0x6B8A, + 0x8EEB: 0x72E9, + 0x8EEC: 0x73E0, + 0x8EED: 0x7A2E, + 0x8EEE: 0x816B, + 0x8EEF: 0x8DA3, + 0x8EF0: 0x9152, + 0x8EF1: 0x9996, + 0x8EF2: 0x5112, + 0x8EF3: 0x53D7, + 0x8EF4: 0x546A, + 0x8EF5: 0x5BFF, + 0x8EF6: 0x6388, + 0x8EF7: 0x6A39, + 0x8EF8: 0x7DAC, + 0x8EF9: 0x9700, + 0x8EFA: 0x56DA, + 0x8EFB: 0x53CE, + 0x8EFC: 0x5468, + 0x8F40: 0x5B97, + 0x8F41: 0x5C31, + 0x8F42: 0x5DDE, + 0x8F43: 0x4FEE, + 0x8F44: 0x6101, + 0x8F45: 0x62FE, + 0x8F46: 0x6D32, + 0x8F47: 0x79C0, + 0x8F48: 0x79CB, + 0x8F49: 0x7D42, + 0x8F4A: 0x7E4D, + 0x8F4B: 0x7FD2, + 0x8F4C: 0x81ED, + 0x8F4D: 0x821F, + 0x8F4E: 0x8490, + 0x8F4F: 0x8846, + 0x8F50: 0x8972, + 0x8F51: 0x8B90, + 0x8F52: 0x8E74, + 0x8F53: 0x8F2F, + 0x8F54: 0x9031, + 0x8F55: 0x914B, + 0x8F56: 0x916C, + 0x8F57: 0x96C6, + 0x8F58: 0x919C, + 0x8F59: 0x4EC0, + 0x8F5A: 0x4F4F, + 0x8F5B: 0x5145, + 0x8F5C: 0x5341, + 0x8F5D: 0x5F93, + 0x8F5E: 0x620E, + 0x8F5F: 0x67D4, + 0x8F60: 0x6C41, + 0x8F61: 0x6E0B, + 0x8F62: 0x7363, + 0x8F63: 0x7E26, + 0x8F64: 0x91CD, + 0x8F65: 0x9283, + 0x8F66: 0x53D4, + 0x8F67: 0x5919, + 0x8F68: 0x5BBF, + 0x8F69: 0x6DD1, + 0x8F6A: 0x795D, + 0x8F6B: 0x7E2E, + 0x8F6C: 0x7C9B, + 0x8F6D: 0x587E, + 0x8F6E: 0x719F, + 0x8F6F: 0x51FA, + 0x8F70: 0x8853, + 0x8F71: 0x8FF0, + 0x8F72: 0x4FCA, + 0x8F73: 0x5CFB, + 0x8F74: 0x6625, + 0x8F75: 0x77AC, + 0x8F76: 0x7AE3, + 0x8F77: 0x821C, + 0x8F78: 0x99FF, + 0x8F79: 0x51C6, + 0x8F7A: 0x5FAA, + 0x8F7B: 0x65EC, + 0x8F7C: 0x696F, + 0x8F7D: 0x6B89, + 0x8F7E: 0x6DF3, + 0x8F80: 0x6E96, + 0x8F81: 0x6F64, + 0x8F82: 0x76FE, + 0x8F83: 0x7D14, + 0x8F84: 0x5DE1, + 0x8F85: 0x9075, + 0x8F86: 0x9187, + 0x8F87: 0x9806, + 0x8F88: 0x51E6, + 0x8F89: 0x521D, + 0x8F8A: 0x6240, + 0x8F8B: 0x6691, + 0x8F8C: 0x66D9, + 0x8F8D: 0x6E1A, + 0x8F8E: 0x5EB6, + 0x8F8F: 0x7DD2, + 0x8F90: 0x7F72, + 0x8F91: 0x66F8, + 0x8F92: 0x85AF, + 0x8F93: 0x85F7, + 0x8F94: 0x8AF8, + 0x8F95: 0x52A9, + 0x8F96: 0x53D9, + 0x8F97: 0x5973, + 0x8F98: 0x5E8F, + 0x8F99: 0x5F90, + 0x8F9A: 0x6055, + 0x8F9B: 0x92E4, + 0x8F9C: 0x9664, + 0x8F9D: 0x50B7, + 0x8F9E: 0x511F, + 0x8F9F: 0x52DD, + 0x8FA0: 0x5320, + 0x8FA1: 0x5347, + 0x8FA2: 0x53EC, + 0x8FA3: 0x54E8, + 0x8FA4: 0x5546, + 0x8FA5: 0x5531, + 0x8FA6: 0x5617, + 0x8FA7: 0x5968, + 0x8FA8: 0x59BE, + 0x8FA9: 0x5A3C, + 0x8FAA: 0x5BB5, + 0x8FAB: 0x5C06, + 0x8FAC: 0x5C0F, + 0x8FAD: 0x5C11, + 0x8FAE: 0x5C1A, + 0x8FAF: 0x5E84, + 0x8FB0: 0x5E8A, + 0x8FB1: 0x5EE0, + 0x8FB2: 0x5F70, + 0x8FB3: 0x627F, + 0x8FB4: 0x6284, + 0x8FB5: 0x62DB, + 0x8FB6: 0x638C, + 0x8FB7: 0x6377, + 0x8FB8: 0x6607, + 0x8FB9: 0x660C, + 0x8FBA: 0x662D, + 0x8FBB: 0x6676, + 0x8FBC: 0x677E, + 0x8FBD: 0x68A2, + 0x8FBE: 0x6A1F, + 0x8FBF: 0x6A35, + 0x8FC0: 0x6CBC, + 0x8FC1: 0x6D88, + 0x8FC2: 0x6E09, + 0x8FC3: 0x6E58, + 0x8FC4: 0x713C, + 0x8FC5: 0x7126, + 0x8FC6: 0x7167, + 0x8FC7: 0x75C7, + 0x8FC8: 0x7701, + 0x8FC9: 0x785D, + 0x8FCA: 0x7901, + 0x8FCB: 0x7965, + 0x8FCC: 0x79F0, + 0x8FCD: 0x7AE0, + 0x8FCE: 0x7B11, + 0x8FCF: 0x7CA7, + 0x8FD0: 0x7D39, + 0x8FD1: 0x8096, + 0x8FD2: 0x83D6, + 0x8FD3: 0x848B, + 0x8FD4: 0x8549, + 0x8FD5: 0x885D, + 0x8FD6: 0x88F3, + 0x8FD7: 0x8A1F, + 0x8FD8: 0x8A3C, + 0x8FD9: 0x8A54, + 0x8FDA: 0x8A73, + 0x8FDB: 0x8C61, + 0x8FDC: 0x8CDE, + 0x8FDD: 0x91A4, + 0x8FDE: 0x9266, + 0x8FDF: 0x937E, + 0x8FE0: 0x9418, + 0x8FE1: 0x969C, + 0x8FE2: 0x9798, + 0x8FE3: 0x4E0A, + 0x8FE4: 0x4E08, + 0x8FE5: 0x4E1E, + 0x8FE6: 0x4E57, + 0x8FE7: 0x5197, + 0x8FE8: 0x5270, + 0x8FE9: 0x57CE, + 0x8FEA: 0x5834, + 0x8FEB: 0x58CC, + 0x8FEC: 0x5B22, + 0x8FED: 0x5E38, + 0x8FEE: 0x60C5, + 0x8FEF: 0x64FE, + 0x8FF0: 0x6761, + 0x8FF1: 0x6756, + 0x8FF2: 0x6D44, + 0x8FF3: 0x72B6, + 0x8FF4: 0x7573, + 0x8FF5: 0x7A63, + 0x8FF6: 0x84B8, + 0x8FF7: 0x8B72, + 0x8FF8: 0x91B8, + 0x8FF9: 0x9320, + 0x8FFA: 0x5631, + 0x8FFB: 0x57F4, + 0x8FFC: 0x98FE, + 0x9040: 0x62ED, + 0x9041: 0x690D, + 0x9042: 0x6B96, + 0x9043: 0x71ED, + 0x9044: 0x7E54, + 0x9045: 0x8077, + 0x9046: 0x8272, + 0x9047: 0x89E6, + 0x9048: 0x98DF, + 0x9049: 0x8755, + 0x904A: 0x8FB1, + 0x904B: 0x5C3B, + 0x904C: 0x4F38, + 0x904D: 0x4FE1, + 0x904E: 0x4FB5, + 0x904F: 0x5507, + 0x9050: 0x5A20, + 0x9051: 0x5BDD, + 0x9052: 0x5BE9, + 0x9053: 0x5FC3, + 0x9054: 0x614E, + 0x9055: 0x632F, + 0x9056: 0x65B0, + 0x9057: 0x664B, + 0x9058: 0x68EE, + 0x9059: 0x699B, + 0x905A: 0x6D78, + 0x905B: 0x6DF1, + 0x905C: 0x7533, + 0x905D: 0x75B9, + 0x905E: 0x771F, + 0x905F: 0x795E, + 0x9060: 0x79E6, + 0x9061: 0x7D33, + 0x9062: 0x81E3, + 0x9063: 0x82AF, + 0x9064: 0x85AA, + 0x9065: 0x89AA, + 0x9066: 0x8A3A, + 0x9067: 0x8EAB, + 0x9068: 0x8F9B, + 0x9069: 0x9032, + 0x906A: 0x91DD, + 0x906B: 0x9707, + 0x906C: 0x4EBA, + 0x906D: 0x4EC1, + 0x906E: 0x5203, + 0x906F: 0x5875, + 0x9070: 0x58EC, + 0x9071: 0x5C0B, + 0x9072: 0x751A, + 0x9073: 0x5C3D, + 0x9074: 0x814E, + 0x9075: 0x8A0A, + 0x9076: 0x8FC5, + 0x9077: 0x9663, + 0x9078: 0x976D, + 0x9079: 0x7B25, + 0x907A: 0x8ACF, + 0x907B: 0x9808, + 0x907C: 0x9162, + 0x907D: 0x56F3, + 0x907E: 0x53A8, + 0x9080: 0x9017, + 0x9081: 0x5439, + 0x9082: 0x5782, + 0x9083: 0x5E25, + 0x9084: 0x63A8, + 0x9085: 0x6C34, + 0x9086: 0x708A, + 0x9087: 0x7761, + 0x9088: 0x7C8B, + 0x9089: 0x7FE0, + 0x908A: 0x8870, + 0x908B: 0x9042, + 0x908C: 0x9154, + 0x908D: 0x9310, + 0x908E: 0x9318, + 0x908F: 0x968F, + 0x9090: 0x745E, + 0x9091: 0x9AC4, + 0x9092: 0x5D07, + 0x9093: 0x5D69, + 0x9094: 0x6570, + 0x9095: 0x67A2, + 0x9096: 0x8DA8, + 0x9097: 0x96DB, + 0x9098: 0x636E, + 0x9099: 0x6749, + 0x909A: 0x6919, + 0x909B: 0x83C5, + 0x909C: 0x9817, + 0x909D: 0x96C0, + 0x909E: 0x88FE, + 0x909F: 0x6F84, + 0x90A0: 0x647A, + 0x90A1: 0x5BF8, + 0x90A2: 0x4E16, + 0x90A3: 0x702C, + 0x90A4: 0x755D, + 0x90A5: 0x662F, + 0x90A6: 0x51C4, + 0x90A7: 0x5236, + 0x90A8: 0x52E2, + 0x90A9: 0x59D3, + 0x90AA: 0x5F81, + 0x90AB: 0x6027, + 0x90AC: 0x6210, + 0x90AD: 0x653F, + 0x90AE: 0x6574, + 0x90AF: 0x661F, + 0x90B0: 0x6674, + 0x90B1: 0x68F2, + 0x90B2: 0x6816, + 0x90B3: 0x6B63, + 0x90B4: 0x6E05, + 0x90B5: 0x7272, + 0x90B6: 0x751F, + 0x90B7: 0x76DB, + 0x90B8: 0x7CBE, + 0x90B9: 0x8056, + 0x90BA: 0x58F0, + 0x90BB: 0x88FD, + 0x90BC: 0x897F, + 0x90BD: 0x8AA0, + 0x90BE: 0x8A93, + 0x90BF: 0x8ACB, + 0x90C0: 0x901D, + 0x90C1: 0x9192, + 0x90C2: 0x9752, + 0x90C3: 0x9759, + 0x90C4: 0x6589, + 0x90C5: 0x7A0E, + 0x90C6: 0x8106, + 0x90C7: 0x96BB, + 0x90C8: 0x5E2D, + 0x90C9: 0x60DC, + 0x90CA: 0x621A, + 0x90CB: 0x65A5, + 0x90CC: 0x6614, + 0x90CD: 0x6790, + 0x90CE: 0x77F3, + 0x90CF: 0x7A4D, + 0x90D0: 0x7C4D, + 0x90D1: 0x7E3E, + 0x90D2: 0x810A, + 0x90D3: 0x8CAC, + 0x90D4: 0x8D64, + 0x90D5: 0x8DE1, + 0x90D6: 0x8E5F, + 0x90D7: 0x78A9, + 0x90D8: 0x5207, + 0x90D9: 0x62D9, + 0x90DA: 0x63A5, + 0x90DB: 0x6442, + 0x90DC: 0x6298, + 0x90DD: 0x8A2D, + 0x90DE: 0x7A83, + 0x90DF: 0x7BC0, + 0x90E0: 0x8AAC, + 0x90E1: 0x96EA, + 0x90E2: 0x7D76, + 0x90E3: 0x820C, + 0x90E4: 0x8749, + 0x90E5: 0x4ED9, + 0x90E6: 0x5148, + 0x90E7: 0x5343, + 0x90E8: 0x5360, + 0x90E9: 0x5BA3, + 0x90EA: 0x5C02, + 0x90EB: 0x5C16, + 0x90EC: 0x5DDD, + 0x90ED: 0x6226, + 0x90EE: 0x6247, + 0x90EF: 0x64B0, + 0x90F0: 0x6813, + 0x90F1: 0x6834, + 0x90F2: 0x6CC9, + 0x90F3: 0x6D45, + 0x90F4: 0x6D17, + 0x90F5: 0x67D3, + 0x90F6: 0x6F5C, + 0x90F7: 0x714E, + 0x90F8: 0x717D, + 0x90F9: 0x65CB, + 0x90FA: 0x7A7F, + 0x90FB: 0x7BAD, + 0x90FC: 0x7DDA, + 0x9140: 0x7E4A, + 0x9141: 0x7FA8, + 0x9142: 0x817A, + 0x9143: 0x821B, + 0x9144: 0x8239, + 0x9145: 0x85A6, + 0x9146: 0x8A6E, + 0x9147: 0x8CCE, + 0x9148: 0x8DF5, + 0x9149: 0x9078, + 0x914A: 0x9077, + 0x914B: 0x92AD, + 0x914C: 0x9291, + 0x914D: 0x9583, + 0x914E: 0x9BAE, + 0x914F: 0x524D, + 0x9150: 0x5584, + 0x9151: 0x6F38, + 0x9152: 0x7136, + 0x9153: 0x5168, + 0x9154: 0x7985, + 0x9155: 0x7E55, + 0x9156: 0x81B3, + 0x9157: 0x7CCE, + 0x9158: 0x564C, + 0x9159: 0x5851, + 0x915A: 0x5CA8, + 0x915B: 0x63AA, + 0x915C: 0x66FE, + 0x915D: 0x66FD, + 0x915E: 0x695A, + 0x915F: 0x72D9, + 0x9160: 0x758F, + 0x9161: 0x758E, + 0x9162: 0x790E, + 0x9163: 0x7956, + 0x9164: 0x79DF, + 0x9165: 0x7C97, + 0x9166: 0x7D20, + 0x9167: 0x7D44, + 0x9168: 0x8607, + 0x9169: 0x8A34, + 0x916A: 0x963B, + 0x916B: 0x9061, + 0x916C: 0x9F20, + 0x916D: 0x50E7, + 0x916E: 0x5275, + 0x916F: 0x53CC, + 0x9170: 0x53E2, + 0x9171: 0x5009, + 0x9172: 0x55AA, + 0x9173: 0x58EE, + 0x9174: 0x594F, + 0x9175: 0x723D, + 0x9176: 0x5B8B, + 0x9177: 0x5C64, + 0x9178: 0x531D, + 0x9179: 0x60E3, + 0x917A: 0x60F3, + 0x917B: 0x635C, + 0x917C: 0x6383, + 0x917D: 0x633F, + 0x917E: 0x63BB, + 0x9180: 0x64CD, + 0x9181: 0x65E9, + 0x9182: 0x66F9, + 0x9183: 0x5DE3, + 0x9184: 0x69CD, + 0x9185: 0x69FD, + 0x9186: 0x6F15, + 0x9187: 0x71E5, + 0x9188: 0x4E89, + 0x9189: 0x75E9, + 0x918A: 0x76F8, + 0x918B: 0x7A93, + 0x918C: 0x7CDF, + 0x918D: 0x7DCF, + 0x918E: 0x7D9C, + 0x918F: 0x8061, + 0x9190: 0x8349, + 0x9191: 0x8358, + 0x9192: 0x846C, + 0x9193: 0x84BC, + 0x9194: 0x85FB, + 0x9195: 0x88C5, + 0x9196: 0x8D70, + 0x9197: 0x9001, + 0x9198: 0x906D, + 0x9199: 0x9397, + 0x919A: 0x971C, + 0x919B: 0x9A12, + 0x919C: 0x50CF, + 0x919D: 0x5897, + 0x919E: 0x618E, + 0x919F: 0x81D3, + 0x91A0: 0x8535, + 0x91A1: 0x8D08, + 0x91A2: 0x9020, + 0x91A3: 0x4FC3, + 0x91A4: 0x5074, + 0x91A5: 0x5247, + 0x91A6: 0x5373, + 0x91A7: 0x606F, + 0x91A8: 0x6349, + 0x91A9: 0x675F, + 0x91AA: 0x6E2C, + 0x91AB: 0x8DB3, + 0x91AC: 0x901F, + 0x91AD: 0x4FD7, + 0x91AE: 0x5C5E, + 0x91AF: 0x8CCA, + 0x91B0: 0x65CF, + 0x91B1: 0x7D9A, + 0x91B2: 0x5352, + 0x91B3: 0x8896, + 0x91B4: 0x5176, + 0x91B5: 0x63C3, + 0x91B6: 0x5B58, + 0x91B7: 0x5B6B, + 0x91B8: 0x5C0A, + 0x91B9: 0x640D, + 0x91BA: 0x6751, + 0x91BB: 0x905C, + 0x91BC: 0x4ED6, + 0x91BD: 0x591A, + 0x91BE: 0x592A, + 0x91BF: 0x6C70, + 0x91C0: 0x8A51, + 0x91C1: 0x553E, + 0x91C2: 0x5815, + 0x91C3: 0x59A5, + 0x91C4: 0x60F0, + 0x91C5: 0x6253, + 0x91C6: 0x67C1, + 0x91C7: 0x8235, + 0x91C8: 0x6955, + 0x91C9: 0x9640, + 0x91CA: 0x99C4, + 0x91CB: 0x9A28, + 0x91CC: 0x4F53, + 0x91CD: 0x5806, + 0x91CE: 0x5BFE, + 0x91CF: 0x8010, + 0x91D0: 0x5CB1, + 0x91D1: 0x5E2F, + 0x91D2: 0x5F85, + 0x91D3: 0x6020, + 0x91D4: 0x614B, + 0x91D5: 0x6234, + 0x91D6: 0x66FF, + 0x91D7: 0x6CF0, + 0x91D8: 0x6EDE, + 0x91D9: 0x80CE, + 0x91DA: 0x817F, + 0x91DB: 0x82D4, + 0x91DC: 0x888B, + 0x91DD: 0x8CB8, + 0x91DE: 0x9000, + 0x91DF: 0x902E, + 0x91E0: 0x968A, + 0x91E1: 0x9EDB, + 0x91E2: 0x9BDB, + 0x91E3: 0x4EE3, + 0x91E4: 0x53F0, + 0x91E5: 0x5927, + 0x91E6: 0x7B2C, + 0x91E7: 0x918D, + 0x91E8: 0x984C, + 0x91E9: 0x9DF9, + 0x91EA: 0x6EDD, + 0x91EB: 0x7027, + 0x91EC: 0x5353, + 0x91ED: 0x5544, + 0x91EE: 0x5B85, + 0x91EF: 0x6258, + 0x91F0: 0x629E, + 0x91F1: 0x62D3, + 0x91F2: 0x6CA2, + 0x91F3: 0x6FEF, + 0x91F4: 0x7422, + 0x91F5: 0x8A17, + 0x91F6: 0x9438, + 0x91F7: 0x6FC1, + 0x91F8: 0x8AFE, + 0x91F9: 0x8338, + 0x91FA: 0x51E7, + 0x91FB: 0x86F8, + 0x91FC: 0x53EA, + 0x9240: 0x53E9, + 0x9241: 0x4F46, + 0x9242: 0x9054, + 0x9243: 0x8FB0, + 0x9244: 0x596A, + 0x9245: 0x8131, + 0x9246: 0x5DFD, + 0x9247: 0x7AEA, + 0x9248: 0x8FBF, + 0x9249: 0x68DA, + 0x924A: 0x8C37, + 0x924B: 0x72F8, + 0x924C: 0x9C48, + 0x924D: 0x6A3D, + 0x924E: 0x8AB0, + 0x924F: 0x4E39, + 0x9250: 0x5358, + 0x9251: 0x5606, + 0x9252: 0x5766, + 0x9253: 0x62C5, + 0x9254: 0x63A2, + 0x9255: 0x65E6, + 0x9256: 0x6B4E, + 0x9257: 0x6DE1, + 0x9258: 0x6E5B, + 0x9259: 0x70AD, + 0x925A: 0x77ED, + 0x925B: 0x7AEF, + 0x925C: 0x7BAA, + 0x925D: 0x7DBB, + 0x925E: 0x803D, + 0x925F: 0x80C6, + 0x9260: 0x86CB, + 0x9261: 0x8A95, + 0x9262: 0x935B, + 0x9263: 0x56E3, + 0x9264: 0x58C7, + 0x9265: 0x5F3E, + 0x9266: 0x65AD, + 0x9267: 0x6696, + 0x9268: 0x6A80, + 0x9269: 0x6BB5, + 0x926A: 0x7537, + 0x926B: 0x8AC7, + 0x926C: 0x5024, + 0x926D: 0x77E5, + 0x926E: 0x5730, + 0x926F: 0x5F1B, + 0x9270: 0x6065, + 0x9271: 0x667A, + 0x9272: 0x6C60, + 0x9273: 0x75F4, + 0x9274: 0x7A1A, + 0x9275: 0x7F6E, + 0x9276: 0x81F4, + 0x9277: 0x8718, + 0x9278: 0x9045, + 0x9279: 0x99B3, + 0x927A: 0x7BC9, + 0x927B: 0x755C, + 0x927C: 0x7AF9, + 0x927D: 0x7B51, + 0x927E: 0x84C4, + 0x9280: 0x9010, + 0x9281: 0x79E9, + 0x9282: 0x7A92, + 0x9283: 0x8336, + 0x9284: 0x5AE1, + 0x9285: 0x7740, + 0x9286: 0x4E2D, + 0x9287: 0x4EF2, + 0x9288: 0x5B99, + 0x9289: 0x5FE0, + 0x928A: 0x62BD, + 0x928B: 0x663C, + 0x928C: 0x67F1, + 0x928D: 0x6CE8, + 0x928E: 0x866B, + 0x928F: 0x8877, + 0x9290: 0x8A3B, + 0x9291: 0x914E, + 0x9292: 0x92F3, + 0x9293: 0x99D0, + 0x9294: 0x6A17, + 0x9295: 0x7026, + 0x9296: 0x732A, + 0x9297: 0x82E7, + 0x9298: 0x8457, + 0x9299: 0x8CAF, + 0x929A: 0x4E01, + 0x929B: 0x5146, + 0x929C: 0x51CB, + 0x929D: 0x558B, + 0x929E: 0x5BF5, + 0x929F: 0x5E16, + 0x92A0: 0x5E33, + 0x92A1: 0x5E81, + 0x92A2: 0x5F14, + 0x92A3: 0x5F35, + 0x92A4: 0x5F6B, + 0x92A5: 0x5FB4, + 0x92A6: 0x61F2, + 0x92A7: 0x6311, + 0x92A8: 0x66A2, + 0x92A9: 0x671D, + 0x92AA: 0x6F6E, + 0x92AB: 0x7252, + 0x92AC: 0x753A, + 0x92AD: 0x773A, + 0x92AE: 0x8074, + 0x92AF: 0x8139, + 0x92B0: 0x8178, + 0x92B1: 0x8776, + 0x92B2: 0x8ABF, + 0x92B3: 0x8ADC, + 0x92B4: 0x8D85, + 0x92B5: 0x8DF3, + 0x92B6: 0x929A, + 0x92B7: 0x9577, + 0x92B8: 0x9802, + 0x92B9: 0x9CE5, + 0x92BA: 0x52C5, + 0x92BB: 0x6357, + 0x92BC: 0x76F4, + 0x92BD: 0x6715, + 0x92BE: 0x6C88, + 0x92BF: 0x73CD, + 0x92C0: 0x8CC3, + 0x92C1: 0x93AE, + 0x92C2: 0x9673, + 0x92C3: 0x6D25, + 0x92C4: 0x589C, + 0x92C5: 0x690E, + 0x92C6: 0x69CC, + 0x92C7: 0x8FFD, + 0x92C8: 0x939A, + 0x92C9: 0x75DB, + 0x92CA: 0x901A, + 0x92CB: 0x585A, + 0x92CC: 0x6802, + 0x92CD: 0x63B4, + 0x92CE: 0x69FB, + 0x92CF: 0x4F43, + 0x92D0: 0x6F2C, + 0x92D1: 0x67D8, + 0x92D2: 0x8FBB, + 0x92D3: 0x8526, + 0x92D4: 0x7DB4, + 0x92D5: 0x9354, + 0x92D6: 0x693F, + 0x92D7: 0x6F70, + 0x92D8: 0x576A, + 0x92D9: 0x58F7, + 0x92DA: 0x5B2C, + 0x92DB: 0x7D2C, + 0x92DC: 0x722A, + 0x92DD: 0x540A, + 0x92DE: 0x91E3, + 0x92DF: 0x9DB4, + 0x92E0: 0x4EAD, + 0x92E1: 0x4F4E, + 0x92E2: 0x505C, + 0x92E3: 0x5075, + 0x92E4: 0x5243, + 0x92E5: 0x8C9E, + 0x92E6: 0x5448, + 0x92E7: 0x5824, + 0x92E8: 0x5B9A, + 0x92E9: 0x5E1D, + 0x92EA: 0x5E95, + 0x92EB: 0x5EAD, + 0x92EC: 0x5EF7, + 0x92ED: 0x5F1F, + 0x92EE: 0x608C, + 0x92EF: 0x62B5, + 0x92F0: 0x633A, + 0x92F1: 0x63D0, + 0x92F2: 0x68AF, + 0x92F3: 0x6C40, + 0x92F4: 0x7887, + 0x92F5: 0x798E, + 0x92F6: 0x7A0B, + 0x92F7: 0x7DE0, + 0x92F8: 0x8247, + 0x92F9: 0x8A02, + 0x92FA: 0x8AE6, + 0x92FB: 0x8E44, + 0x92FC: 0x9013, + 0x9340: 0x90B8, + 0x9341: 0x912D, + 0x9342: 0x91D8, + 0x9343: 0x9F0E, + 0x9344: 0x6CE5, + 0x9345: 0x6458, + 0x9346: 0x64E2, + 0x9347: 0x6575, + 0x9348: 0x6EF4, + 0x9349: 0x7684, + 0x934A: 0x7B1B, + 0x934B: 0x9069, + 0x934C: 0x93D1, + 0x934D: 0x6EBA, + 0x934E: 0x54F2, + 0x934F: 0x5FB9, + 0x9350: 0x64A4, + 0x9351: 0x8F4D, + 0x9352: 0x8FED, + 0x9353: 0x9244, + 0x9354: 0x5178, + 0x9355: 0x586B, + 0x9356: 0x5929, + 0x9357: 0x5C55, + 0x9358: 0x5E97, + 0x9359: 0x6DFB, + 0x935A: 0x7E8F, + 0x935B: 0x751C, + 0x935C: 0x8CBC, + 0x935D: 0x8EE2, + 0x935E: 0x985B, + 0x935F: 0x70B9, + 0x9360: 0x4F1D, + 0x9361: 0x6BBF, + 0x9362: 0x6FB1, + 0x9363: 0x7530, + 0x9364: 0x96FB, + 0x9365: 0x514E, + 0x9366: 0x5410, + 0x9367: 0x5835, + 0x9368: 0x5857, + 0x9369: 0x59AC, + 0x936A: 0x5C60, + 0x936B: 0x5F92, + 0x936C: 0x6597, + 0x936D: 0x675C, + 0x936E: 0x6E21, + 0x936F: 0x767B, + 0x9370: 0x83DF, + 0x9371: 0x8CED, + 0x9372: 0x9014, + 0x9373: 0x90FD, + 0x9374: 0x934D, + 0x9375: 0x7825, + 0x9376: 0x783A, + 0x9377: 0x52AA, + 0x9378: 0x5EA6, + 0x9379: 0x571F, + 0x937A: 0x5974, + 0x937B: 0x6012, + 0x937C: 0x5012, + 0x937D: 0x515A, + 0x937E: 0x51AC, + 0x9380: 0x51CD, + 0x9381: 0x5200, + 0x9382: 0x5510, + 0x9383: 0x5854, + 0x9384: 0x5858, + 0x9385: 0x5957, + 0x9386: 0x5B95, + 0x9387: 0x5CF6, + 0x9388: 0x5D8B, + 0x9389: 0x60BC, + 0x938A: 0x6295, + 0x938B: 0x642D, + 0x938C: 0x6771, + 0x938D: 0x6843, + 0x938E: 0x68BC, + 0x938F: 0x68DF, + 0x9390: 0x76D7, + 0x9391: 0x6DD8, + 0x9392: 0x6E6F, + 0x9393: 0x6D9B, + 0x9394: 0x706F, + 0x9395: 0x71C8, + 0x9396: 0x5F53, + 0x9397: 0x75D8, + 0x9398: 0x7977, + 0x9399: 0x7B49, + 0x939A: 0x7B54, + 0x939B: 0x7B52, + 0x939C: 0x7CD6, + 0x939D: 0x7D71, + 0x939E: 0x5230, + 0x939F: 0x8463, + 0x93A0: 0x8569, + 0x93A1: 0x85E4, + 0x93A2: 0x8A0E, + 0x93A3: 0x8B04, + 0x93A4: 0x8C46, + 0x93A5: 0x8E0F, + 0x93A6: 0x9003, + 0x93A7: 0x900F, + 0x93A8: 0x9419, + 0x93A9: 0x9676, + 0x93AA: 0x982D, + 0x93AB: 0x9A30, + 0x93AC: 0x95D8, + 0x93AD: 0x50CD, + 0x93AE: 0x52D5, + 0x93AF: 0x540C, + 0x93B0: 0x5802, + 0x93B1: 0x5C0E, + 0x93B2: 0x61A7, + 0x93B3: 0x649E, + 0x93B4: 0x6D1E, + 0x93B5: 0x77B3, + 0x93B6: 0x7AE5, + 0x93B7: 0x80F4, + 0x93B8: 0x8404, + 0x93B9: 0x9053, + 0x93BA: 0x9285, + 0x93BB: 0x5CE0, + 0x93BC: 0x9D07, + 0x93BD: 0x533F, + 0x93BE: 0x5F97, + 0x93BF: 0x5FB3, + 0x93C0: 0x6D9C, + 0x93C1: 0x7279, + 0x93C2: 0x7763, + 0x93C3: 0x79BF, + 0x93C4: 0x7BE4, + 0x93C5: 0x6BD2, + 0x93C6: 0x72EC, + 0x93C7: 0x8AAD, + 0x93C8: 0x6803, + 0x93C9: 0x6A61, + 0x93CA: 0x51F8, + 0x93CB: 0x7A81, + 0x93CC: 0x6934, + 0x93CD: 0x5C4A, + 0x93CE: 0x9CF6, + 0x93CF: 0x82EB, + 0x93D0: 0x5BC5, + 0x93D1: 0x9149, + 0x93D2: 0x701E, + 0x93D3: 0x5678, + 0x93D4: 0x5C6F, + 0x93D5: 0x60C7, + 0x93D6: 0x6566, + 0x93D7: 0x6C8C, + 0x93D8: 0x8C5A, + 0x93D9: 0x9041, + 0x93DA: 0x9813, + 0x93DB: 0x5451, + 0x93DC: 0x66C7, + 0x93DD: 0x920D, + 0x93DE: 0x5948, + 0x93DF: 0x90A3, + 0x93E0: 0x5185, + 0x93E1: 0x4E4D, + 0x93E2: 0x51EA, + 0x93E3: 0x8599, + 0x93E4: 0x8B0E, + 0x93E5: 0x7058, + 0x93E6: 0x637A, + 0x93E7: 0x934B, + 0x93E8: 0x6962, + 0x93E9: 0x99B4, + 0x93EA: 0x7E04, + 0x93EB: 0x7577, + 0x93EC: 0x5357, + 0x93ED: 0x6960, + 0x93EE: 0x8EDF, + 0x93EF: 0x96E3, + 0x93F0: 0x6C5D, + 0x93F1: 0x4E8C, + 0x93F2: 0x5C3C, + 0x93F3: 0x5F10, + 0x93F4: 0x8FE9, + 0x93F5: 0x5302, + 0x93F6: 0x8CD1, + 0x93F7: 0x8089, + 0x93F8: 0x8679, + 0x93F9: 0x5EFF, + 0x93FA: 0x65E5, + 0x93FB: 0x4E73, + 0x93FC: 0x5165, + 0x9440: 0x5982, + 0x9441: 0x5C3F, + 0x9442: 0x97EE, + 0x9443: 0x4EFB, + 0x9444: 0x598A, + 0x9445: 0x5FCD, + 0x9446: 0x8A8D, + 0x9447: 0x6FE1, + 0x9448: 0x79B0, + 0x9449: 0x7962, + 0x944A: 0x5BE7, + 0x944B: 0x8471, + 0x944C: 0x732B, + 0x944D: 0x71B1, + 0x944E: 0x5E74, + 0x944F: 0x5FF5, + 0x9450: 0x637B, + 0x9451: 0x649A, + 0x9452: 0x71C3, + 0x9453: 0x7C98, + 0x9454: 0x4E43, + 0x9455: 0x5EFC, + 0x9456: 0x4E4B, + 0x9457: 0x57DC, + 0x9458: 0x56A2, + 0x9459: 0x60A9, + 0x945A: 0x6FC3, + 0x945B: 0x7D0D, + 0x945C: 0x80FD, + 0x945D: 0x8133, + 0x945E: 0x81BF, + 0x945F: 0x8FB2, + 0x9460: 0x8997, + 0x9461: 0x86A4, + 0x9462: 0x5DF4, + 0x9463: 0x628A, + 0x9464: 0x64AD, + 0x9465: 0x8987, + 0x9466: 0x6777, + 0x9467: 0x6CE2, + 0x9468: 0x6D3E, + 0x9469: 0x7436, + 0x946A: 0x7834, + 0x946B: 0x5A46, + 0x946C: 0x7F75, + 0x946D: 0x82AD, + 0x946E: 0x99AC, + 0x946F: 0x4FF3, + 0x9470: 0x5EC3, + 0x9471: 0x62DD, + 0x9472: 0x6392, + 0x9473: 0x6557, + 0x9474: 0x676F, + 0x9475: 0x76C3, + 0x9476: 0x724C, + 0x9477: 0x80CC, + 0x9478: 0x80BA, + 0x9479: 0x8F29, + 0x947A: 0x914D, + 0x947B: 0x500D, + 0x947C: 0x57F9, + 0x947D: 0x5A92, + 0x947E: 0x6885, + 0x9480: 0x6973, + 0x9481: 0x7164, + 0x9482: 0x72FD, + 0x9483: 0x8CB7, + 0x9484: 0x58F2, + 0x9485: 0x8CE0, + 0x9486: 0x966A, + 0x9487: 0x9019, + 0x9488: 0x877F, + 0x9489: 0x79E4, + 0x948A: 0x77E7, + 0x948B: 0x8429, + 0x948C: 0x4F2F, + 0x948D: 0x5265, + 0x948E: 0x535A, + 0x948F: 0x62CD, + 0x9490: 0x67CF, + 0x9491: 0x6CCA, + 0x9492: 0x767D, + 0x9493: 0x7B94, + 0x9494: 0x7C95, + 0x9495: 0x8236, + 0x9496: 0x8584, + 0x9497: 0x8FEB, + 0x9498: 0x66DD, + 0x9499: 0x6F20, + 0x949A: 0x7206, + 0x949B: 0x7E1B, + 0x949C: 0x83AB, + 0x949D: 0x99C1, + 0x949E: 0x9EA6, + 0x949F: 0x51FD, + 0x94A0: 0x7BB1, + 0x94A1: 0x7872, + 0x94A2: 0x7BB8, + 0x94A3: 0x8087, + 0x94A4: 0x7B48, + 0x94A5: 0x6AE8, + 0x94A6: 0x5E61, + 0x94A7: 0x808C, + 0x94A8: 0x7551, + 0x94A9: 0x7560, + 0x94AA: 0x516B, + 0x94AB: 0x9262, + 0x94AC: 0x6E8C, + 0x94AD: 0x767A, + 0x94AE: 0x9197, + 0x94AF: 0x9AEA, + 0x94B0: 0x4F10, + 0x94B1: 0x7F70, + 0x94B2: 0x629C, + 0x94B3: 0x7B4F, + 0x94B4: 0x95A5, + 0x94B5: 0x9CE9, + 0x94B6: 0x567A, + 0x94B7: 0x5859, + 0x94B8: 0x86E4, + 0x94B9: 0x96BC, + 0x94BA: 0x4F34, + 0x94BB: 0x5224, + 0x94BC: 0x534A, + 0x94BD: 0x53CD, + 0x94BE: 0x53DB, + 0x94BF: 0x5E06, + 0x94C0: 0x642C, + 0x94C1: 0x6591, + 0x94C2: 0x677F, + 0x94C3: 0x6C3E, + 0x94C4: 0x6C4E, + 0x94C5: 0x7248, + 0x94C6: 0x72AF, + 0x94C7: 0x73ED, + 0x94C8: 0x7554, + 0x94C9: 0x7E41, + 0x94CA: 0x822C, + 0x94CB: 0x85E9, + 0x94CC: 0x8CA9, + 0x94CD: 0x7BC4, + 0x94CE: 0x91C6, + 0x94CF: 0x7169, + 0x94D0: 0x9812, + 0x94D1: 0x98EF, + 0x94D2: 0x633D, + 0x94D3: 0x6669, + 0x94D4: 0x756A, + 0x94D5: 0x76E4, + 0x94D6: 0x78D0, + 0x94D7: 0x8543, + 0x94D8: 0x86EE, + 0x94D9: 0x532A, + 0x94DA: 0x5351, + 0x94DB: 0x5426, + 0x94DC: 0x5983, + 0x94DD: 0x5E87, + 0x94DE: 0x5F7C, + 0x94DF: 0x60B2, + 0x94E0: 0x6249, + 0x94E1: 0x6279, + 0x94E2: 0x62AB, + 0x94E3: 0x6590, + 0x94E4: 0x6BD4, + 0x94E5: 0x6CCC, + 0x94E6: 0x75B2, + 0x94E7: 0x76AE, + 0x94E8: 0x7891, + 0x94E9: 0x79D8, + 0x94EA: 0x7DCB, + 0x94EB: 0x7F77, + 0x94EC: 0x80A5, + 0x94ED: 0x88AB, + 0x94EE: 0x8AB9, + 0x94EF: 0x8CBB, + 0x94F0: 0x907F, + 0x94F1: 0x975E, + 0x94F2: 0x98DB, + 0x94F3: 0x6A0B, + 0x94F4: 0x7C38, + 0x94F5: 0x5099, + 0x94F6: 0x5C3E, + 0x94F7: 0x5FAE, + 0x94F8: 0x6787, + 0x94F9: 0x6BD8, + 0x94FA: 0x7435, + 0x94FB: 0x7709, + 0x94FC: 0x7F8E, + 0x9540: 0x9F3B, + 0x9541: 0x67CA, + 0x9542: 0x7A17, + 0x9543: 0x5339, + 0x9544: 0x758B, + 0x9545: 0x9AED, + 0x9546: 0x5F66, + 0x9547: 0x819D, + 0x9548: 0x83F1, + 0x9549: 0x8098, + 0x954A: 0x5F3C, + 0x954B: 0x5FC5, + 0x954C: 0x7562, + 0x954D: 0x7B46, + 0x954E: 0x903C, + 0x954F: 0x6867, + 0x9550: 0x59EB, + 0x9551: 0x5A9B, + 0x9552: 0x7D10, + 0x9553: 0x767E, + 0x9554: 0x8B2C, + 0x9555: 0x4FF5, + 0x9556: 0x5F6A, + 0x9557: 0x6A19, + 0x9558: 0x6C37, + 0x9559: 0x6F02, + 0x955A: 0x74E2, + 0x955B: 0x7968, + 0x955C: 0x8868, + 0x955D: 0x8A55, + 0x955E: 0x8C79, + 0x955F: 0x5EDF, + 0x9560: 0x63CF, + 0x9561: 0x75C5, + 0x9562: 0x79D2, + 0x9563: 0x82D7, + 0x9564: 0x9328, + 0x9565: 0x92F2, + 0x9566: 0x849C, + 0x9567: 0x86ED, + 0x9568: 0x9C2D, + 0x9569: 0x54C1, + 0x956A: 0x5F6C, + 0x956B: 0x658C, + 0x956C: 0x6D5C, + 0x956D: 0x7015, + 0x956E: 0x8CA7, + 0x956F: 0x8CD3, + 0x9570: 0x983B, + 0x9571: 0x654F, + 0x9572: 0x74F6, + 0x9573: 0x4E0D, + 0x9574: 0x4ED8, + 0x9575: 0x57E0, + 0x9576: 0x592B, + 0x9577: 0x5A66, + 0x9578: 0x5BCC, + 0x9579: 0x51A8, + 0x957A: 0x5E03, + 0x957B: 0x5E9C, + 0x957C: 0x6016, + 0x957D: 0x6276, + 0x957E: 0x6577, + 0x9580: 0x65A7, + 0x9581: 0x666E, + 0x9582: 0x6D6E, + 0x9583: 0x7236, + 0x9584: 0x7B26, + 0x9585: 0x8150, + 0x9586: 0x819A, + 0x9587: 0x8299, + 0x9588: 0x8B5C, + 0x9589: 0x8CA0, + 0x958A: 0x8CE6, + 0x958B: 0x8D74, + 0x958C: 0x961C, + 0x958D: 0x9644, + 0x958E: 0x4FAE, + 0x958F: 0x64AB, + 0x9590: 0x6B66, + 0x9591: 0x821E, + 0x9592: 0x8461, + 0x9593: 0x856A, + 0x9594: 0x90E8, + 0x9595: 0x5C01, + 0x9596: 0x6953, + 0x9597: 0x98A8, + 0x9598: 0x847A, + 0x9599: 0x8557, + 0x959A: 0x4F0F, + 0x959B: 0x526F, + 0x959C: 0x5FA9, + 0x959D: 0x5E45, + 0x959E: 0x670D, + 0x959F: 0x798F, + 0x95A0: 0x8179, + 0x95A1: 0x8907, + 0x95A2: 0x8986, + 0x95A3: 0x6DF5, + 0x95A4: 0x5F17, + 0x95A5: 0x6255, + 0x95A6: 0x6CB8, + 0x95A7: 0x4ECF, + 0x95A8: 0x7269, + 0x95A9: 0x9B92, + 0x95AA: 0x5206, + 0x95AB: 0x543B, + 0x95AC: 0x5674, + 0x95AD: 0x58B3, + 0x95AE: 0x61A4, + 0x95AF: 0x626E, + 0x95B0: 0x711A, + 0x95B1: 0x596E, + 0x95B2: 0x7C89, + 0x95B3: 0x7CDE, + 0x95B4: 0x7D1B, + 0x95B5: 0x96F0, + 0x95B6: 0x6587, + 0x95B7: 0x805E, + 0x95B8: 0x4E19, + 0x95B9: 0x4F75, + 0x95BA: 0x5175, + 0x95BB: 0x5840, + 0x95BC: 0x5E63, + 0x95BD: 0x5E73, + 0x95BE: 0x5F0A, + 0x95BF: 0x67C4, + 0x95C0: 0x4E26, + 0x95C1: 0x853D, + 0x95C2: 0x9589, + 0x95C3: 0x965B, + 0x95C4: 0x7C73, + 0x95C5: 0x9801, + 0x95C6: 0x50FB, + 0x95C7: 0x58C1, + 0x95C8: 0x7656, + 0x95C9: 0x78A7, + 0x95CA: 0x5225, + 0x95CB: 0x77A5, + 0x95CC: 0x8511, + 0x95CD: 0x7B86, + 0x95CE: 0x504F, + 0x95CF: 0x5909, + 0x95D0: 0x7247, + 0x95D1: 0x7BC7, + 0x95D2: 0x7DE8, + 0x95D3: 0x8FBA, + 0x95D4: 0x8FD4, + 0x95D5: 0x904D, + 0x95D6: 0x4FBF, + 0x95D7: 0x52C9, + 0x95D8: 0x5A29, + 0x95D9: 0x5F01, + 0x95DA: 0x97AD, + 0x95DB: 0x4FDD, + 0x95DC: 0x8217, + 0x95DD: 0x92EA, + 0x95DE: 0x5703, + 0x95DF: 0x6355, + 0x95E0: 0x6B69, + 0x95E1: 0x752B, + 0x95E2: 0x88DC, + 0x95E3: 0x8F14, + 0x95E4: 0x7A42, + 0x95E5: 0x52DF, + 0x95E6: 0x5893, + 0x95E7: 0x6155, + 0x95E8: 0x620A, + 0x95E9: 0x66AE, + 0x95EA: 0x6BCD, + 0x95EB: 0x7C3F, + 0x95EC: 0x83E9, + 0x95ED: 0x5023, + 0x95EE: 0x4FF8, + 0x95EF: 0x5305, + 0x95F0: 0x5446, + 0x95F1: 0x5831, + 0x95F2: 0x5949, + 0x95F3: 0x5B9D, + 0x95F4: 0x5CF0, + 0x95F5: 0x5CEF, + 0x95F6: 0x5D29, + 0x95F7: 0x5E96, + 0x95F8: 0x62B1, + 0x95F9: 0x6367, + 0x95FA: 0x653E, + 0x95FB: 0x65B9, + 0x95FC: 0x670B, + 0x9640: 0x6CD5, + 0x9641: 0x6CE1, + 0x9642: 0x70F9, + 0x9643: 0x7832, + 0x9644: 0x7E2B, + 0x9645: 0x80DE, + 0x9646: 0x82B3, + 0x9647: 0x840C, + 0x9648: 0x84EC, + 0x9649: 0x8702, + 0x964A: 0x8912, + 0x964B: 0x8A2A, + 0x964C: 0x8C4A, + 0x964D: 0x90A6, + 0x964E: 0x92D2, + 0x964F: 0x98FD, + 0x9650: 0x9CF3, + 0x9651: 0x9D6C, + 0x9652: 0x4E4F, + 0x9653: 0x4EA1, + 0x9654: 0x508D, + 0x9655: 0x5256, + 0x9656: 0x574A, + 0x9657: 0x59A8, + 0x9658: 0x5E3D, + 0x9659: 0x5FD8, + 0x965A: 0x5FD9, + 0x965B: 0x623F, + 0x965C: 0x66B4, + 0x965D: 0x671B, + 0x965E: 0x67D0, + 0x965F: 0x68D2, + 0x9660: 0x5192, + 0x9661: 0x7D21, + 0x9662: 0x80AA, + 0x9663: 0x81A8, + 0x9664: 0x8B00, + 0x9665: 0x8C8C, + 0x9666: 0x8CBF, + 0x9667: 0x927E, + 0x9668: 0x9632, + 0x9669: 0x5420, + 0x966A: 0x982C, + 0x966B: 0x5317, + 0x966C: 0x50D5, + 0x966D: 0x535C, + 0x966E: 0x58A8, + 0x966F: 0x64B2, + 0x9670: 0x6734, + 0x9671: 0x7267, + 0x9672: 0x7766, + 0x9673: 0x7A46, + 0x9674: 0x91E6, + 0x9675: 0x52C3, + 0x9676: 0x6CA1, + 0x9677: 0x6B86, + 0x9678: 0x5800, + 0x9679: 0x5E4C, + 0x967A: 0x5954, + 0x967B: 0x672C, + 0x967C: 0x7FFB, + 0x967D: 0x51E1, + 0x967E: 0x76C6, + 0x9680: 0x6469, + 0x9681: 0x78E8, + 0x9682: 0x9B54, + 0x9683: 0x9EBB, + 0x9684: 0x57CB, + 0x9685: 0x59B9, + 0x9686: 0x6627, + 0x9687: 0x679A, + 0x9688: 0x6BCE, + 0x9689: 0x54E9, + 0x968A: 0x69D9, + 0x968B: 0x5E55, + 0x968C: 0x819C, + 0x968D: 0x6795, + 0x968E: 0x9BAA, + 0x968F: 0x67FE, + 0x9690: 0x9C52, + 0x9691: 0x685D, + 0x9692: 0x4EA6, + 0x9693: 0x4FE3, + 0x9694: 0x53C8, + 0x9695: 0x62B9, + 0x9696: 0x672B, + 0x9697: 0x6CAB, + 0x9698: 0x8FC4, + 0x9699: 0x4FAD, + 0x969A: 0x7E6D, + 0x969B: 0x9EBF, + 0x969C: 0x4E07, + 0x969D: 0x6162, + 0x969E: 0x6E80, + 0x969F: 0x6F2B, + 0x96A0: 0x8513, + 0x96A1: 0x5473, + 0x96A2: 0x672A, + 0x96A3: 0x9B45, + 0x96A4: 0x5DF3, + 0x96A5: 0x7B95, + 0x96A6: 0x5CAC, + 0x96A7: 0x5BC6, + 0x96A8: 0x871C, + 0x96A9: 0x6E4A, + 0x96AA: 0x84D1, + 0x96AB: 0x7A14, + 0x96AC: 0x8108, + 0x96AD: 0x5999, + 0x96AE: 0x7C8D, + 0x96AF: 0x6C11, + 0x96B0: 0x7720, + 0x96B1: 0x52D9, + 0x96B2: 0x5922, + 0x96B3: 0x7121, + 0x96B4: 0x725F, + 0x96B5: 0x77DB, + 0x96B6: 0x9727, + 0x96B7: 0x9D61, + 0x96B8: 0x690B, + 0x96B9: 0x5A7F, + 0x96BA: 0x5A18, + 0x96BB: 0x51A5, + 0x96BC: 0x540D, + 0x96BD: 0x547D, + 0x96BE: 0x660E, + 0x96BF: 0x76DF, + 0x96C0: 0x8FF7, + 0x96C1: 0x9298, + 0x96C2: 0x9CF4, + 0x96C3: 0x59EA, + 0x96C4: 0x725D, + 0x96C5: 0x6EC5, + 0x96C6: 0x514D, + 0x96C7: 0x68C9, + 0x96C8: 0x7DBF, + 0x96C9: 0x7DEC, + 0x96CA: 0x9762, + 0x96CB: 0x9EBA, + 0x96CC: 0x6478, + 0x96CD: 0x6A21, + 0x96CE: 0x8302, + 0x96CF: 0x5984, + 0x96D0: 0x5B5F, + 0x96D1: 0x6BDB, + 0x96D2: 0x731B, + 0x96D3: 0x76F2, + 0x96D4: 0x7DB2, + 0x96D5: 0x8017, + 0x96D6: 0x8499, + 0x96D7: 0x5132, + 0x96D8: 0x6728, + 0x96D9: 0x9ED9, + 0x96DA: 0x76EE, + 0x96DB: 0x6762, + 0x96DC: 0x52FF, + 0x96DD: 0x9905, + 0x96DE: 0x5C24, + 0x96DF: 0x623B, + 0x96E0: 0x7C7E, + 0x96E1: 0x8CB0, + 0x96E2: 0x554F, + 0x96E3: 0x60B6, + 0x96E4: 0x7D0B, + 0x96E5: 0x9580, + 0x96E6: 0x5301, + 0x96E7: 0x4E5F, + 0x96E8: 0x51B6, + 0x96E9: 0x591C, + 0x96EA: 0x723A, + 0x96EB: 0x8036, + 0x96EC: 0x91CE, + 0x96ED: 0x5F25, + 0x96EE: 0x77E2, + 0x96EF: 0x5384, + 0x96F0: 0x5F79, + 0x96F1: 0x7D04, + 0x96F2: 0x85AC, + 0x96F3: 0x8A33, + 0x96F4: 0x8E8D, + 0x96F5: 0x9756, + 0x96F6: 0x67F3, + 0x96F7: 0x85AE, + 0x96F8: 0x9453, + 0x96F9: 0x6109, + 0x96FA: 0x6108, + 0x96FB: 0x6CB9, + 0x96FC: 0x7652, + 0x9740: 0x8AED, + 0x9741: 0x8F38, + 0x9742: 0x552F, + 0x9743: 0x4F51, + 0x9744: 0x512A, + 0x9745: 0x52C7, + 0x9746: 0x53CB, + 0x9747: 0x5BA5, + 0x9748: 0x5E7D, + 0x9749: 0x60A0, + 0x974A: 0x6182, + 0x974B: 0x63D6, + 0x974C: 0x6709, + 0x974D: 0x67DA, + 0x974E: 0x6E67, + 0x974F: 0x6D8C, + 0x9750: 0x7336, + 0x9751: 0x7337, + 0x9752: 0x7531, + 0x9753: 0x7950, + 0x9754: 0x88D5, + 0x9755: 0x8A98, + 0x9756: 0x904A, + 0x9757: 0x9091, + 0x9758: 0x90F5, + 0x9759: 0x96C4, + 0x975A: 0x878D, + 0x975B: 0x5915, + 0x975C: 0x4E88, + 0x975D: 0x4F59, + 0x975E: 0x4E0E, + 0x975F: 0x8A89, + 0x9760: 0x8F3F, + 0x9761: 0x9810, + 0x9762: 0x50AD, + 0x9763: 0x5E7C, + 0x9764: 0x5996, + 0x9765: 0x5BB9, + 0x9766: 0x5EB8, + 0x9767: 0x63DA, + 0x9768: 0x63FA, + 0x9769: 0x64C1, + 0x976A: 0x66DC, + 0x976B: 0x694A, + 0x976C: 0x69D8, + 0x976D: 0x6D0B, + 0x976E: 0x6EB6, + 0x976F: 0x7194, + 0x9770: 0x7528, + 0x9771: 0x7AAF, + 0x9772: 0x7F8A, + 0x9773: 0x8000, + 0x9774: 0x8449, + 0x9775: 0x84C9, + 0x9776: 0x8981, + 0x9777: 0x8B21, + 0x9778: 0x8E0A, + 0x9779: 0x9065, + 0x977A: 0x967D, + 0x977B: 0x990A, + 0x977C: 0x617E, + 0x977D: 0x6291, + 0x977E: 0x6B32, + 0x9780: 0x6C83, + 0x9781: 0x6D74, + 0x9782: 0x7FCC, + 0x9783: 0x7FFC, + 0x9784: 0x6DC0, + 0x9785: 0x7F85, + 0x9786: 0x87BA, + 0x9787: 0x88F8, + 0x9788: 0x6765, + 0x9789: 0x83B1, + 0x978A: 0x983C, + 0x978B: 0x96F7, + 0x978C: 0x6D1B, + 0x978D: 0x7D61, + 0x978E: 0x843D, + 0x978F: 0x916A, + 0x9790: 0x4E71, + 0x9791: 0x5375, + 0x9792: 0x5D50, + 0x9793: 0x6B04, + 0x9794: 0x6FEB, + 0x9795: 0x85CD, + 0x9796: 0x862D, + 0x9797: 0x89A7, + 0x9798: 0x5229, + 0x9799: 0x540F, + 0x979A: 0x5C65, + 0x979B: 0x674E, + 0x979C: 0x68A8, + 0x979D: 0x7406, + 0x979E: 0x7483, + 0x979F: 0x75E2, + 0x97A0: 0x88CF, + 0x97A1: 0x88E1, + 0x97A2: 0x91CC, + 0x97A3: 0x96E2, + 0x97A4: 0x9678, + 0x97A5: 0x5F8B, + 0x97A6: 0x7387, + 0x97A7: 0x7ACB, + 0x97A8: 0x844E, + 0x97A9: 0x63A0, + 0x97AA: 0x7565, + 0x97AB: 0x5289, + 0x97AC: 0x6D41, + 0x97AD: 0x6E9C, + 0x97AE: 0x7409, + 0x97AF: 0x7559, + 0x97B0: 0x786B, + 0x97B1: 0x7C92, + 0x97B2: 0x9686, + 0x97B3: 0x7ADC, + 0x97B4: 0x9F8D, + 0x97B5: 0x4FB6, + 0x97B6: 0x616E, + 0x97B7: 0x65C5, + 0x97B8: 0x865C, + 0x97B9: 0x4E86, + 0x97BA: 0x4EAE, + 0x97BB: 0x50DA, + 0x97BC: 0x4E21, + 0x97BD: 0x51CC, + 0x97BE: 0x5BEE, + 0x97BF: 0x6599, + 0x97C0: 0x6881, + 0x97C1: 0x6DBC, + 0x97C2: 0x731F, + 0x97C3: 0x7642, + 0x97C4: 0x77AD, + 0x97C5: 0x7A1C, + 0x97C6: 0x7CE7, + 0x97C7: 0x826F, + 0x97C8: 0x8AD2, + 0x97C9: 0x907C, + 0x97CA: 0x91CF, + 0x97CB: 0x9675, + 0x97CC: 0x9818, + 0x97CD: 0x529B, + 0x97CE: 0x7DD1, + 0x97CF: 0x502B, + 0x97D0: 0x5398, + 0x97D1: 0x6797, + 0x97D2: 0x6DCB, + 0x97D3: 0x71D0, + 0x97D4: 0x7433, + 0x97D5: 0x81E8, + 0x97D6: 0x8F2A, + 0x97D7: 0x96A3, + 0x97D8: 0x9C57, + 0x97D9: 0x9E9F, + 0x97DA: 0x7460, + 0x97DB: 0x5841, + 0x97DC: 0x6D99, + 0x97DD: 0x7D2F, + 0x97DE: 0x985E, + 0x97DF: 0x4EE4, + 0x97E0: 0x4F36, + 0x97E1: 0x4F8B, + 0x97E2: 0x51B7, + 0x97E3: 0x52B1, + 0x97E4: 0x5DBA, + 0x97E5: 0x601C, + 0x97E6: 0x73B2, + 0x97E7: 0x793C, + 0x97E8: 0x82D3, + 0x97E9: 0x9234, + 0x97EA: 0x96B7, + 0x97EB: 0x96F6, + 0x97EC: 0x970A, + 0x97ED: 0x9E97, + 0x97EE: 0x9F62, + 0x97EF: 0x66A6, + 0x97F0: 0x6B74, + 0x97F1: 0x5217, + 0x97F2: 0x52A3, + 0x97F3: 0x70C8, + 0x97F4: 0x88C2, + 0x97F5: 0x5EC9, + 0x97F6: 0x604B, + 0x97F7: 0x6190, + 0x97F8: 0x6F23, + 0x97F9: 0x7149, + 0x97FA: 0x7C3E, + 0x97FB: 0x7DF4, + 0x97FC: 0x806F, + 0x9840: 0x84EE, + 0x9841: 0x9023, + 0x9842: 0x932C, + 0x9843: 0x5442, + 0x9844: 0x9B6F, + 0x9845: 0x6AD3, + 0x9846: 0x7089, + 0x9847: 0x8CC2, + 0x9848: 0x8DEF, + 0x9849: 0x9732, + 0x984A: 0x52B4, + 0x984B: 0x5A41, + 0x984C: 0x5ECA, + 0x984D: 0x5F04, + 0x984E: 0x6717, + 0x984F: 0x697C, + 0x9850: 0x6994, + 0x9851: 0x6D6A, + 0x9852: 0x6F0F, + 0x9853: 0x7262, + 0x9854: 0x72FC, + 0x9855: 0x7BED, + 0x9856: 0x8001, + 0x9857: 0x807E, + 0x9858: 0x874B, + 0x9859: 0x90CE, + 0x985A: 0x516D, + 0x985B: 0x9E93, + 0x985C: 0x7984, + 0x985D: 0x808B, + 0x985E: 0x9332, + 0x985F: 0x8AD6, + 0x9860: 0x502D, + 0x9861: 0x548C, + 0x9862: 0x8A71, + 0x9863: 0x6B6A, + 0x9864: 0x8CC4, + 0x9865: 0x8107, + 0x9866: 0x60D1, + 0x9867: 0x67A0, + 0x9868: 0x9DF2, + 0x9869: 0x4E99, + 0x986A: 0x4E98, + 0x986B: 0x9C10, + 0x986C: 0x8A6B, + 0x986D: 0x85C1, + 0x986E: 0x8568, + 0x986F: 0x6900, + 0x9870: 0x6E7E, + 0x9871: 0x7897, + 0x9872: 0x8155, + 0x989F: 0x5F0C, + 0x98A0: 0x4E10, + 0x98A1: 0x4E15, + 0x98A2: 0x4E2A, + 0x98A3: 0x4E31, + 0x98A4: 0x4E36, + 0x98A5: 0x4E3C, + 0x98A6: 0x4E3F, + 0x98A7: 0x4E42, + 0x98A8: 0x4E56, + 0x98A9: 0x4E58, + 0x98AA: 0x4E82, + 0x98AB: 0x4E85, + 0x98AC: 0x8C6B, + 0x98AD: 0x4E8A, + 0x98AE: 0x8212, + 0x98AF: 0x5F0D, + 0x98B0: 0x4E8E, + 0x98B1: 0x4E9E, + 0x98B2: 0x4E9F, + 0x98B3: 0x4EA0, + 0x98B4: 0x4EA2, + 0x98B5: 0x4EB0, + 0x98B6: 0x4EB3, + 0x98B7: 0x4EB6, + 0x98B8: 0x4ECE, + 0x98B9: 0x4ECD, + 0x98BA: 0x4EC4, + 0x98BB: 0x4EC6, + 0x98BC: 0x4EC2, + 0x98BD: 0x4ED7, + 0x98BE: 0x4EDE, + 0x98BF: 0x4EED, + 0x98C0: 0x4EDF, + 0x98C1: 0x4EF7, + 0x98C2: 0x4F09, + 0x98C3: 0x4F5A, + 0x98C4: 0x4F30, + 0x98C5: 0x4F5B, + 0x98C6: 0x4F5D, + 0x98C7: 0x4F57, + 0x98C8: 0x4F47, + 0x98C9: 0x4F76, + 0x98CA: 0x4F88, + 0x98CB: 0x4F8F, + 0x98CC: 0x4F98, + 0x98CD: 0x4F7B, + 0x98CE: 0x4F69, + 0x98CF: 0x4F70, + 0x98D0: 0x4F91, + 0x98D1: 0x4F6F, + 0x98D2: 0x4F86, + 0x98D3: 0x4F96, + 0x98D4: 0x5118, + 0x98D5: 0x4FD4, + 0x98D6: 0x4FDF, + 0x98D7: 0x4FCE, + 0x98D8: 0x4FD8, + 0x98D9: 0x4FDB, + 0x98DA: 0x4FD1, + 0x98DB: 0x4FDA, + 0x98DC: 0x4FD0, + 0x98DD: 0x4FE4, + 0x98DE: 0x4FE5, + 0x98DF: 0x501A, + 0x98E0: 0x5028, + 0x98E1: 0x5014, + 0x98E2: 0x502A, + 0x98E3: 0x5025, + 0x98E4: 0x5005, + 0x98E5: 0x4F1C, + 0x98E6: 0x4FF6, + 0x98E7: 0x5021, + 0x98E8: 0x5029, + 0x98E9: 0x502C, + 0x98EA: 0x4FFE, + 0x98EB: 0x4FEF, + 0x98EC: 0x5011, + 0x98ED: 0x5006, + 0x98EE: 0x5043, + 0x98EF: 0x5047, + 0x98F0: 0x6703, + 0x98F1: 0x5055, + 0x98F2: 0x5050, + 0x98F3: 0x5048, + 0x98F4: 0x505A, + 0x98F5: 0x5056, + 0x98F6: 0x506C, + 0x98F7: 0x5078, + 0x98F8: 0x5080, + 0x98F9: 0x509A, + 0x98FA: 0x5085, + 0x98FB: 0x50B4, + 0x98FC: 0x50B2, + 0x9940: 0x50C9, + 0x9941: 0x50CA, + 0x9942: 0x50B3, + 0x9943: 0x50C2, + 0x9944: 0x50D6, + 0x9945: 0x50DE, + 0x9946: 0x50E5, + 0x9947: 0x50ED, + 0x9948: 0x50E3, + 0x9949: 0x50EE, + 0x994A: 0x50F9, + 0x994B: 0x50F5, + 0x994C: 0x5109, + 0x994D: 0x5101, + 0x994E: 0x5102, + 0x994F: 0x5116, + 0x9950: 0x5115, + 0x9951: 0x5114, + 0x9952: 0x511A, + 0x9953: 0x5121, + 0x9954: 0x513A, + 0x9955: 0x5137, + 0x9956: 0x513C, + 0x9957: 0x513B, + 0x9958: 0x513F, + 0x9959: 0x5140, + 0x995A: 0x5152, + 0x995B: 0x514C, + 0x995C: 0x5154, + 0x995D: 0x5162, + 0x995E: 0x7AF8, + 0x995F: 0x5169, + 0x9960: 0x516A, + 0x9961: 0x516E, + 0x9962: 0x5180, + 0x9963: 0x5182, + 0x9964: 0x56D8, + 0x9965: 0x518C, + 0x9966: 0x5189, + 0x9967: 0x518F, + 0x9968: 0x5191, + 0x9969: 0x5193, + 0x996A: 0x5195, + 0x996B: 0x5196, + 0x996C: 0x51A4, + 0x996D: 0x51A6, + 0x996E: 0x51A2, + 0x996F: 0x51A9, + 0x9970: 0x51AA, + 0x9971: 0x51AB, + 0x9972: 0x51B3, + 0x9973: 0x51B1, + 0x9974: 0x51B2, + 0x9975: 0x51B0, + 0x9976: 0x51B5, + 0x9977: 0x51BD, + 0x9978: 0x51C5, + 0x9979: 0x51C9, + 0x997A: 0x51DB, + 0x997B: 0x51E0, + 0x997C: 0x8655, + 0x997D: 0x51E9, + 0x997E: 0x51ED, + 0x9980: 0x51F0, + 0x9981: 0x51F5, + 0x9982: 0x51FE, + 0x9983: 0x5204, + 0x9984: 0x520B, + 0x9985: 0x5214, + 0x9986: 0x520E, + 0x9987: 0x5227, + 0x9988: 0x522A, + 0x9989: 0x522E, + 0x998A: 0x5233, + 0x998B: 0x5239, + 0x998C: 0x524F, + 0x998D: 0x5244, + 0x998E: 0x524B, + 0x998F: 0x524C, + 0x9990: 0x525E, + 0x9991: 0x5254, + 0x9992: 0x526A, + 0x9993: 0x5274, + 0x9994: 0x5269, + 0x9995: 0x5273, + 0x9996: 0x527F, + 0x9997: 0x527D, + 0x9998: 0x528D, + 0x9999: 0x5294, + 0x999A: 0x5292, + 0x999B: 0x5271, + 0x999C: 0x5288, + 0x999D: 0x5291, + 0x999E: 0x8FA8, + 0x999F: 0x8FA7, + 0x99A0: 0x52AC, + 0x99A1: 0x52AD, + 0x99A2: 0x52BC, + 0x99A3: 0x52B5, + 0x99A4: 0x52C1, + 0x99A5: 0x52CD, + 0x99A6: 0x52D7, + 0x99A7: 0x52DE, + 0x99A8: 0x52E3, + 0x99A9: 0x52E6, + 0x99AA: 0x98ED, + 0x99AB: 0x52E0, + 0x99AC: 0x52F3, + 0x99AD: 0x52F5, + 0x99AE: 0x52F8, + 0x99AF: 0x52F9, + 0x99B0: 0x5306, + 0x99B1: 0x5308, + 0x99B2: 0x7538, + 0x99B3: 0x530D, + 0x99B4: 0x5310, + 0x99B5: 0x530F, + 0x99B6: 0x5315, + 0x99B7: 0x531A, + 0x99B8: 0x5323, + 0x99B9: 0x532F, + 0x99BA: 0x5331, + 0x99BB: 0x5333, + 0x99BC: 0x5338, + 0x99BD: 0x5340, + 0x99BE: 0x5346, + 0x99BF: 0x5345, + 0x99C0: 0x4E17, + 0x99C1: 0x5349, + 0x99C2: 0x534D, + 0x99C3: 0x51D6, + 0x99C4: 0x535E, + 0x99C5: 0x5369, + 0x99C6: 0x536E, + 0x99C7: 0x5918, + 0x99C8: 0x537B, + 0x99C9: 0x5377, + 0x99CA: 0x5382, + 0x99CB: 0x5396, + 0x99CC: 0x53A0, + 0x99CD: 0x53A6, + 0x99CE: 0x53A5, + 0x99CF: 0x53AE, + 0x99D0: 0x53B0, + 0x99D1: 0x53B6, + 0x99D2: 0x53C3, + 0x99D3: 0x7C12, + 0x99D4: 0x96D9, + 0x99D5: 0x53DF, + 0x99D6: 0x66FC, + 0x99D7: 0x71EE, + 0x99D8: 0x53EE, + 0x99D9: 0x53E8, + 0x99DA: 0x53ED, + 0x99DB: 0x53FA, + 0x99DC: 0x5401, + 0x99DD: 0x543D, + 0x99DE: 0x5440, + 0x99DF: 0x542C, + 0x99E0: 0x542D, + 0x99E1: 0x543C, + 0x99E2: 0x542E, + 0x99E3: 0x5436, + 0x99E4: 0x5429, + 0x99E5: 0x541D, + 0x99E6: 0x544E, + 0x99E7: 0x548F, + 0x99E8: 0x5475, + 0x99E9: 0x548E, + 0x99EA: 0x545F, + 0x99EB: 0x5471, + 0x99EC: 0x5477, + 0x99ED: 0x5470, + 0x99EE: 0x5492, + 0x99EF: 0x547B, + 0x99F0: 0x5480, + 0x99F1: 0x5476, + 0x99F2: 0x5484, + 0x99F3: 0x5490, + 0x99F4: 0x5486, + 0x99F5: 0x54C7, + 0x99F6: 0x54A2, + 0x99F7: 0x54B8, + 0x99F8: 0x54A5, + 0x99F9: 0x54AC, + 0x99FA: 0x54C4, + 0x99FB: 0x54C8, + 0x99FC: 0x54A8, + 0x9A40: 0x54AB, + 0x9A41: 0x54C2, + 0x9A42: 0x54A4, + 0x9A43: 0x54BE, + 0x9A44: 0x54BC, + 0x9A45: 0x54D8, + 0x9A46: 0x54E5, + 0x9A47: 0x54E6, + 0x9A48: 0x550F, + 0x9A49: 0x5514, + 0x9A4A: 0x54FD, + 0x9A4B: 0x54EE, + 0x9A4C: 0x54ED, + 0x9A4D: 0x54FA, + 0x9A4E: 0x54E2, + 0x9A4F: 0x5539, + 0x9A50: 0x5540, + 0x9A51: 0x5563, + 0x9A52: 0x554C, + 0x9A53: 0x552E, + 0x9A54: 0x555C, + 0x9A55: 0x5545, + 0x9A56: 0x5556, + 0x9A57: 0x5557, + 0x9A58: 0x5538, + 0x9A59: 0x5533, + 0x9A5A: 0x555D, + 0x9A5B: 0x5599, + 0x9A5C: 0x5580, + 0x9A5D: 0x54AF, + 0x9A5E: 0x558A, + 0x9A5F: 0x559F, + 0x9A60: 0x557B, + 0x9A61: 0x557E, + 0x9A62: 0x5598, + 0x9A63: 0x559E, + 0x9A64: 0x55AE, + 0x9A65: 0x557C, + 0x9A66: 0x5583, + 0x9A67: 0x55A9, + 0x9A68: 0x5587, + 0x9A69: 0x55A8, + 0x9A6A: 0x55DA, + 0x9A6B: 0x55C5, + 0x9A6C: 0x55DF, + 0x9A6D: 0x55C4, + 0x9A6E: 0x55DC, + 0x9A6F: 0x55E4, + 0x9A70: 0x55D4, + 0x9A71: 0x5614, + 0x9A72: 0x55F7, + 0x9A73: 0x5616, + 0x9A74: 0x55FE, + 0x9A75: 0x55FD, + 0x9A76: 0x561B, + 0x9A77: 0x55F9, + 0x9A78: 0x564E, + 0x9A79: 0x5650, + 0x9A7A: 0x71DF, + 0x9A7B: 0x5634, + 0x9A7C: 0x5636, + 0x9A7D: 0x5632, + 0x9A7E: 0x5638, + 0x9A80: 0x566B, + 0x9A81: 0x5664, + 0x9A82: 0x562F, + 0x9A83: 0x566C, + 0x9A84: 0x566A, + 0x9A85: 0x5686, + 0x9A86: 0x5680, + 0x9A87: 0x568A, + 0x9A88: 0x56A0, + 0x9A89: 0x5694, + 0x9A8A: 0x568F, + 0x9A8B: 0x56A5, + 0x9A8C: 0x56AE, + 0x9A8D: 0x56B6, + 0x9A8E: 0x56B4, + 0x9A8F: 0x56C2, + 0x9A90: 0x56BC, + 0x9A91: 0x56C1, + 0x9A92: 0x56C3, + 0x9A93: 0x56C0, + 0x9A94: 0x56C8, + 0x9A95: 0x56CE, + 0x9A96: 0x56D1, + 0x9A97: 0x56D3, + 0x9A98: 0x56D7, + 0x9A99: 0x56EE, + 0x9A9A: 0x56F9, + 0x9A9B: 0x5700, + 0x9A9C: 0x56FF, + 0x9A9D: 0x5704, + 0x9A9E: 0x5709, + 0x9A9F: 0x5708, + 0x9AA0: 0x570B, + 0x9AA1: 0x570D, + 0x9AA2: 0x5713, + 0x9AA3: 0x5718, + 0x9AA4: 0x5716, + 0x9AA5: 0x55C7, + 0x9AA6: 0x571C, + 0x9AA7: 0x5726, + 0x9AA8: 0x5737, + 0x9AA9: 0x5738, + 0x9AAA: 0x574E, + 0x9AAB: 0x573B, + 0x9AAC: 0x5740, + 0x9AAD: 0x574F, + 0x9AAE: 0x5769, + 0x9AAF: 0x57C0, + 0x9AB0: 0x5788, + 0x9AB1: 0x5761, + 0x9AB2: 0x577F, + 0x9AB3: 0x5789, + 0x9AB4: 0x5793, + 0x9AB5: 0x57A0, + 0x9AB6: 0x57B3, + 0x9AB7: 0x57A4, + 0x9AB8: 0x57AA, + 0x9AB9: 0x57B0, + 0x9ABA: 0x57C3, + 0x9ABB: 0x57C6, + 0x9ABC: 0x57D4, + 0x9ABD: 0x57D2, + 0x9ABE: 0x57D3, + 0x9ABF: 0x580A, + 0x9AC0: 0x57D6, + 0x9AC1: 0x57E3, + 0x9AC2: 0x580B, + 0x9AC3: 0x5819, + 0x9AC4: 0x581D, + 0x9AC5: 0x5872, + 0x9AC6: 0x5821, + 0x9AC7: 0x5862, + 0x9AC8: 0x584B, + 0x9AC9: 0x5870, + 0x9ACA: 0x6BC0, + 0x9ACB: 0x5852, + 0x9ACC: 0x583D, + 0x9ACD: 0x5879, + 0x9ACE: 0x5885, + 0x9ACF: 0x58B9, + 0x9AD0: 0x589F, + 0x9AD1: 0x58AB, + 0x9AD2: 0x58BA, + 0x9AD3: 0x58DE, + 0x9AD4: 0x58BB, + 0x9AD5: 0x58B8, + 0x9AD6: 0x58AE, + 0x9AD7: 0x58C5, + 0x9AD8: 0x58D3, + 0x9AD9: 0x58D1, + 0x9ADA: 0x58D7, + 0x9ADB: 0x58D9, + 0x9ADC: 0x58D8, + 0x9ADD: 0x58E5, + 0x9ADE: 0x58DC, + 0x9ADF: 0x58E4, + 0x9AE0: 0x58DF, + 0x9AE1: 0x58EF, + 0x9AE2: 0x58FA, + 0x9AE3: 0x58F9, + 0x9AE4: 0x58FB, + 0x9AE5: 0x58FC, + 0x9AE6: 0x58FD, + 0x9AE7: 0x5902, + 0x9AE8: 0x590A, + 0x9AE9: 0x5910, + 0x9AEA: 0x591B, + 0x9AEB: 0x68A6, + 0x9AEC: 0x5925, + 0x9AED: 0x592C, + 0x9AEE: 0x592D, + 0x9AEF: 0x5932, + 0x9AF0: 0x5938, + 0x9AF1: 0x593E, + 0x9AF2: 0x7AD2, + 0x9AF3: 0x5955, + 0x9AF4: 0x5950, + 0x9AF5: 0x594E, + 0x9AF6: 0x595A, + 0x9AF7: 0x5958, + 0x9AF8: 0x5962, + 0x9AF9: 0x5960, + 0x9AFA: 0x5967, + 0x9AFB: 0x596C, + 0x9AFC: 0x5969, + 0x9B40: 0x5978, + 0x9B41: 0x5981, + 0x9B42: 0x599D, + 0x9B43: 0x4F5E, + 0x9B44: 0x4FAB, + 0x9B45: 0x59A3, + 0x9B46: 0x59B2, + 0x9B47: 0x59C6, + 0x9B48: 0x59E8, + 0x9B49: 0x59DC, + 0x9B4A: 0x598D, + 0x9B4B: 0x59D9, + 0x9B4C: 0x59DA, + 0x9B4D: 0x5A25, + 0x9B4E: 0x5A1F, + 0x9B4F: 0x5A11, + 0x9B50: 0x5A1C, + 0x9B51: 0x5A09, + 0x9B52: 0x5A1A, + 0x9B53: 0x5A40, + 0x9B54: 0x5A6C, + 0x9B55: 0x5A49, + 0x9B56: 0x5A35, + 0x9B57: 0x5A36, + 0x9B58: 0x5A62, + 0x9B59: 0x5A6A, + 0x9B5A: 0x5A9A, + 0x9B5B: 0x5ABC, + 0x9B5C: 0x5ABE, + 0x9B5D: 0x5ACB, + 0x9B5E: 0x5AC2, + 0x9B5F: 0x5ABD, + 0x9B60: 0x5AE3, + 0x9B61: 0x5AD7, + 0x9B62: 0x5AE6, + 0x9B63: 0x5AE9, + 0x9B64: 0x5AD6, + 0x9B65: 0x5AFA, + 0x9B66: 0x5AFB, + 0x9B67: 0x5B0C, + 0x9B68: 0x5B0B, + 0x9B69: 0x5B16, + 0x9B6A: 0x5B32, + 0x9B6B: 0x5AD0, + 0x9B6C: 0x5B2A, + 0x9B6D: 0x5B36, + 0x9B6E: 0x5B3E, + 0x9B6F: 0x5B43, + 0x9B70: 0x5B45, + 0x9B71: 0x5B40, + 0x9B72: 0x5B51, + 0x9B73: 0x5B55, + 0x9B74: 0x5B5A, + 0x9B75: 0x5B5B, + 0x9B76: 0x5B65, + 0x9B77: 0x5B69, + 0x9B78: 0x5B70, + 0x9B79: 0x5B73, + 0x9B7A: 0x5B75, + 0x9B7B: 0x5B78, + 0x9B7C: 0x6588, + 0x9B7D: 0x5B7A, + 0x9B7E: 0x5B80, + 0x9B80: 0x5B83, + 0x9B81: 0x5BA6, + 0x9B82: 0x5BB8, + 0x9B83: 0x5BC3, + 0x9B84: 0x5BC7, + 0x9B85: 0x5BC9, + 0x9B86: 0x5BD4, + 0x9B87: 0x5BD0, + 0x9B88: 0x5BE4, + 0x9B89: 0x5BE6, + 0x9B8A: 0x5BE2, + 0x9B8B: 0x5BDE, + 0x9B8C: 0x5BE5, + 0x9B8D: 0x5BEB, + 0x9B8E: 0x5BF0, + 0x9B8F: 0x5BF6, + 0x9B90: 0x5BF3, + 0x9B91: 0x5C05, + 0x9B92: 0x5C07, + 0x9B93: 0x5C08, + 0x9B94: 0x5C0D, + 0x9B95: 0x5C13, + 0x9B96: 0x5C20, + 0x9B97: 0x5C22, + 0x9B98: 0x5C28, + 0x9B99: 0x5C38, + 0x9B9A: 0x5C39, + 0x9B9B: 0x5C41, + 0x9B9C: 0x5C46, + 0x9B9D: 0x5C4E, + 0x9B9E: 0x5C53, + 0x9B9F: 0x5C50, + 0x9BA0: 0x5C4F, + 0x9BA1: 0x5B71, + 0x9BA2: 0x5C6C, + 0x9BA3: 0x5C6E, + 0x9BA4: 0x4E62, + 0x9BA5: 0x5C76, + 0x9BA6: 0x5C79, + 0x9BA7: 0x5C8C, + 0x9BA8: 0x5C91, + 0x9BA9: 0x5C94, + 0x9BAA: 0x599B, + 0x9BAB: 0x5CAB, + 0x9BAC: 0x5CBB, + 0x9BAD: 0x5CB6, + 0x9BAE: 0x5CBC, + 0x9BAF: 0x5CB7, + 0x9BB0: 0x5CC5, + 0x9BB1: 0x5CBE, + 0x9BB2: 0x5CC7, + 0x9BB3: 0x5CD9, + 0x9BB4: 0x5CE9, + 0x9BB5: 0x5CFD, + 0x9BB6: 0x5CFA, + 0x9BB7: 0x5CED, + 0x9BB8: 0x5D8C, + 0x9BB9: 0x5CEA, + 0x9BBA: 0x5D0B, + 0x9BBB: 0x5D15, + 0x9BBC: 0x5D17, + 0x9BBD: 0x5D5C, + 0x9BBE: 0x5D1F, + 0x9BBF: 0x5D1B, + 0x9BC0: 0x5D11, + 0x9BC1: 0x5D14, + 0x9BC2: 0x5D22, + 0x9BC3: 0x5D1A, + 0x9BC4: 0x5D19, + 0x9BC5: 0x5D18, + 0x9BC6: 0x5D4C, + 0x9BC7: 0x5D52, + 0x9BC8: 0x5D4E, + 0x9BC9: 0x5D4B, + 0x9BCA: 0x5D6C, + 0x9BCB: 0x5D73, + 0x9BCC: 0x5D76, + 0x9BCD: 0x5D87, + 0x9BCE: 0x5D84, + 0x9BCF: 0x5D82, + 0x9BD0: 0x5DA2, + 0x9BD1: 0x5D9D, + 0x9BD2: 0x5DAC, + 0x9BD3: 0x5DAE, + 0x9BD4: 0x5DBD, + 0x9BD5: 0x5D90, + 0x9BD6: 0x5DB7, + 0x9BD7: 0x5DBC, + 0x9BD8: 0x5DC9, + 0x9BD9: 0x5DCD, + 0x9BDA: 0x5DD3, + 0x9BDB: 0x5DD2, + 0x9BDC: 0x5DD6, + 0x9BDD: 0x5DDB, + 0x9BDE: 0x5DEB, + 0x9BDF: 0x5DF2, + 0x9BE0: 0x5DF5, + 0x9BE1: 0x5E0B, + 0x9BE2: 0x5E1A, + 0x9BE3: 0x5E19, + 0x9BE4: 0x5E11, + 0x9BE5: 0x5E1B, + 0x9BE6: 0x5E36, + 0x9BE7: 0x5E37, + 0x9BE8: 0x5E44, + 0x9BE9: 0x5E43, + 0x9BEA: 0x5E40, + 0x9BEB: 0x5E4E, + 0x9BEC: 0x5E57, + 0x9BED: 0x5E54, + 0x9BEE: 0x5E5F, + 0x9BEF: 0x5E62, + 0x9BF0: 0x5E64, + 0x9BF1: 0x5E47, + 0x9BF2: 0x5E75, + 0x9BF3: 0x5E76, + 0x9BF4: 0x5E7A, + 0x9BF5: 0x9EBC, + 0x9BF6: 0x5E7F, + 0x9BF7: 0x5EA0, + 0x9BF8: 0x5EC1, + 0x9BF9: 0x5EC2, + 0x9BFA: 0x5EC8, + 0x9BFB: 0x5ED0, + 0x9BFC: 0x5ECF, + 0x9C40: 0x5ED6, + 0x9C41: 0x5EE3, + 0x9C42: 0x5EDD, + 0x9C43: 0x5EDA, + 0x9C44: 0x5EDB, + 0x9C45: 0x5EE2, + 0x9C46: 0x5EE1, + 0x9C47: 0x5EE8, + 0x9C48: 0x5EE9, + 0x9C49: 0x5EEC, + 0x9C4A: 0x5EF1, + 0x9C4B: 0x5EF3, + 0x9C4C: 0x5EF0, + 0x9C4D: 0x5EF4, + 0x9C4E: 0x5EF8, + 0x9C4F: 0x5EFE, + 0x9C50: 0x5F03, + 0x9C51: 0x5F09, + 0x9C52: 0x5F5D, + 0x9C53: 0x5F5C, + 0x9C54: 0x5F0B, + 0x9C55: 0x5F11, + 0x9C56: 0x5F16, + 0x9C57: 0x5F29, + 0x9C58: 0x5F2D, + 0x9C59: 0x5F38, + 0x9C5A: 0x5F41, + 0x9C5B: 0x5F48, + 0x9C5C: 0x5F4C, + 0x9C5D: 0x5F4E, + 0x9C5E: 0x5F2F, + 0x9C5F: 0x5F51, + 0x9C60: 0x5F56, + 0x9C61: 0x5F57, + 0x9C62: 0x5F59, + 0x9C63: 0x5F61, + 0x9C64: 0x5F6D, + 0x9C65: 0x5F73, + 0x9C66: 0x5F77, + 0x9C67: 0x5F83, + 0x9C68: 0x5F82, + 0x9C69: 0x5F7F, + 0x9C6A: 0x5F8A, + 0x9C6B: 0x5F88, + 0x9C6C: 0x5F91, + 0x9C6D: 0x5F87, + 0x9C6E: 0x5F9E, + 0x9C6F: 0x5F99, + 0x9C70: 0x5F98, + 0x9C71: 0x5FA0, + 0x9C72: 0x5FA8, + 0x9C73: 0x5FAD, + 0x9C74: 0x5FBC, + 0x9C75: 0x5FD6, + 0x9C76: 0x5FFB, + 0x9C77: 0x5FE4, + 0x9C78: 0x5FF8, + 0x9C79: 0x5FF1, + 0x9C7A: 0x5FDD, + 0x9C7B: 0x60B3, + 0x9C7C: 0x5FFF, + 0x9C7D: 0x6021, + 0x9C7E: 0x6060, + 0x9C80: 0x6019, + 0x9C81: 0x6010, + 0x9C82: 0x6029, + 0x9C83: 0x600E, + 0x9C84: 0x6031, + 0x9C85: 0x601B, + 0x9C86: 0x6015, + 0x9C87: 0x602B, + 0x9C88: 0x6026, + 0x9C89: 0x600F, + 0x9C8A: 0x603A, + 0x9C8B: 0x605A, + 0x9C8C: 0x6041, + 0x9C8D: 0x606A, + 0x9C8E: 0x6077, + 0x9C8F: 0x605F, + 0x9C90: 0x604A, + 0x9C91: 0x6046, + 0x9C92: 0x604D, + 0x9C93: 0x6063, + 0x9C94: 0x6043, + 0x9C95: 0x6064, + 0x9C96: 0x6042, + 0x9C97: 0x606C, + 0x9C98: 0x606B, + 0x9C99: 0x6059, + 0x9C9A: 0x6081, + 0x9C9B: 0x608D, + 0x9C9C: 0x60E7, + 0x9C9D: 0x6083, + 0x9C9E: 0x609A, + 0x9C9F: 0x6084, + 0x9CA0: 0x609B, + 0x9CA1: 0x6096, + 0x9CA2: 0x6097, + 0x9CA3: 0x6092, + 0x9CA4: 0x60A7, + 0x9CA5: 0x608B, + 0x9CA6: 0x60E1, + 0x9CA7: 0x60B8, + 0x9CA8: 0x60E0, + 0x9CA9: 0x60D3, + 0x9CAA: 0x60B4, + 0x9CAB: 0x5FF0, + 0x9CAC: 0x60BD, + 0x9CAD: 0x60C6, + 0x9CAE: 0x60B5, + 0x9CAF: 0x60D8, + 0x9CB0: 0x614D, + 0x9CB1: 0x6115, + 0x9CB2: 0x6106, + 0x9CB3: 0x60F6, + 0x9CB4: 0x60F7, + 0x9CB5: 0x6100, + 0x9CB6: 0x60F4, + 0x9CB7: 0x60FA, + 0x9CB8: 0x6103, + 0x9CB9: 0x6121, + 0x9CBA: 0x60FB, + 0x9CBB: 0x60F1, + 0x9CBC: 0x610D, + 0x9CBD: 0x610E, + 0x9CBE: 0x6147, + 0x9CBF: 0x613E, + 0x9CC0: 0x6128, + 0x9CC1: 0x6127, + 0x9CC2: 0x614A, + 0x9CC3: 0x613F, + 0x9CC4: 0x613C, + 0x9CC5: 0x612C, + 0x9CC6: 0x6134, + 0x9CC7: 0x613D, + 0x9CC8: 0x6142, + 0x9CC9: 0x6144, + 0x9CCA: 0x6173, + 0x9CCB: 0x6177, + 0x9CCC: 0x6158, + 0x9CCD: 0x6159, + 0x9CCE: 0x615A, + 0x9CCF: 0x616B, + 0x9CD0: 0x6174, + 0x9CD1: 0x616F, + 0x9CD2: 0x6165, + 0x9CD3: 0x6171, + 0x9CD4: 0x615F, + 0x9CD5: 0x615D, + 0x9CD6: 0x6153, + 0x9CD7: 0x6175, + 0x9CD8: 0x6199, + 0x9CD9: 0x6196, + 0x9CDA: 0x6187, + 0x9CDB: 0x61AC, + 0x9CDC: 0x6194, + 0x9CDD: 0x619A, + 0x9CDE: 0x618A, + 0x9CDF: 0x6191, + 0x9CE0: 0x61AB, + 0x9CE1: 0x61AE, + 0x9CE2: 0x61CC, + 0x9CE3: 0x61CA, + 0x9CE4: 0x61C9, + 0x9CE5: 0x61F7, + 0x9CE6: 0x61C8, + 0x9CE7: 0x61C3, + 0x9CE8: 0x61C6, + 0x9CE9: 0x61BA, + 0x9CEA: 0x61CB, + 0x9CEB: 0x7F79, + 0x9CEC: 0x61CD, + 0x9CED: 0x61E6, + 0x9CEE: 0x61E3, + 0x9CEF: 0x61F6, + 0x9CF0: 0x61FA, + 0x9CF1: 0x61F4, + 0x9CF2: 0x61FF, + 0x9CF3: 0x61FD, + 0x9CF4: 0x61FC, + 0x9CF5: 0x61FE, + 0x9CF6: 0x6200, + 0x9CF7: 0x6208, + 0x9CF8: 0x6209, + 0x9CF9: 0x620D, + 0x9CFA: 0x620C, + 0x9CFB: 0x6214, + 0x9CFC: 0x621B, + 0x9D40: 0x621E, + 0x9D41: 0x6221, + 0x9D42: 0x622A, + 0x9D43: 0x622E, + 0x9D44: 0x6230, + 0x9D45: 0x6232, + 0x9D46: 0x6233, + 0x9D47: 0x6241, + 0x9D48: 0x624E, + 0x9D49: 0x625E, + 0x9D4A: 0x6263, + 0x9D4B: 0x625B, + 0x9D4C: 0x6260, + 0x9D4D: 0x6268, + 0x9D4E: 0x627C, + 0x9D4F: 0x6282, + 0x9D50: 0x6289, + 0x9D51: 0x627E, + 0x9D52: 0x6292, + 0x9D53: 0x6293, + 0x9D54: 0x6296, + 0x9D55: 0x62D4, + 0x9D56: 0x6283, + 0x9D57: 0x6294, + 0x9D58: 0x62D7, + 0x9D59: 0x62D1, + 0x9D5A: 0x62BB, + 0x9D5B: 0x62CF, + 0x9D5C: 0x62FF, + 0x9D5D: 0x62C6, + 0x9D5E: 0x64D4, + 0x9D5F: 0x62C8, + 0x9D60: 0x62DC, + 0x9D61: 0x62CC, + 0x9D62: 0x62CA, + 0x9D63: 0x62C2, + 0x9D64: 0x62C7, + 0x9D65: 0x629B, + 0x9D66: 0x62C9, + 0x9D67: 0x630C, + 0x9D68: 0x62EE, + 0x9D69: 0x62F1, + 0x9D6A: 0x6327, + 0x9D6B: 0x6302, + 0x9D6C: 0x6308, + 0x9D6D: 0x62EF, + 0x9D6E: 0x62F5, + 0x9D6F: 0x6350, + 0x9D70: 0x633E, + 0x9D71: 0x634D, + 0x9D72: 0x641C, + 0x9D73: 0x634F, + 0x9D74: 0x6396, + 0x9D75: 0x638E, + 0x9D76: 0x6380, + 0x9D77: 0x63AB, + 0x9D78: 0x6376, + 0x9D79: 0x63A3, + 0x9D7A: 0x638F, + 0x9D7B: 0x6389, + 0x9D7C: 0x639F, + 0x9D7D: 0x63B5, + 0x9D7E: 0x636B, + 0x9D80: 0x6369, + 0x9D81: 0x63BE, + 0x9D82: 0x63E9, + 0x9D83: 0x63C0, + 0x9D84: 0x63C6, + 0x9D85: 0x63E3, + 0x9D86: 0x63C9, + 0x9D87: 0x63D2, + 0x9D88: 0x63F6, + 0x9D89: 0x63C4, + 0x9D8A: 0x6416, + 0x9D8B: 0x6434, + 0x9D8C: 0x6406, + 0x9D8D: 0x6413, + 0x9D8E: 0x6426, + 0x9D8F: 0x6436, + 0x9D90: 0x651D, + 0x9D91: 0x6417, + 0x9D92: 0x6428, + 0x9D93: 0x640F, + 0x9D94: 0x6467, + 0x9D95: 0x646F, + 0x9D96: 0x6476, + 0x9D97: 0x644E, + 0x9D98: 0x652A, + 0x9D99: 0x6495, + 0x9D9A: 0x6493, + 0x9D9B: 0x64A5, + 0x9D9C: 0x64A9, + 0x9D9D: 0x6488, + 0x9D9E: 0x64BC, + 0x9D9F: 0x64DA, + 0x9DA0: 0x64D2, + 0x9DA1: 0x64C5, + 0x9DA2: 0x64C7, + 0x9DA3: 0x64BB, + 0x9DA4: 0x64D8, + 0x9DA5: 0x64C2, + 0x9DA6: 0x64F1, + 0x9DA7: 0x64E7, + 0x9DA8: 0x8209, + 0x9DA9: 0x64E0, + 0x9DAA: 0x64E1, + 0x9DAB: 0x62AC, + 0x9DAC: 0x64E3, + 0x9DAD: 0x64EF, + 0x9DAE: 0x652C, + 0x9DAF: 0x64F6, + 0x9DB0: 0x64F4, + 0x9DB1: 0x64F2, + 0x9DB2: 0x64FA, + 0x9DB3: 0x6500, + 0x9DB4: 0x64FD, + 0x9DB5: 0x6518, + 0x9DB6: 0x651C, + 0x9DB7: 0x6505, + 0x9DB8: 0x6524, + 0x9DB9: 0x6523, + 0x9DBA: 0x652B, + 0x9DBB: 0x6534, + 0x9DBC: 0x6535, + 0x9DBD: 0x6537, + 0x9DBE: 0x6536, + 0x9DBF: 0x6538, + 0x9DC0: 0x754B, + 0x9DC1: 0x6548, + 0x9DC2: 0x6556, + 0x9DC3: 0x6555, + 0x9DC4: 0x654D, + 0x9DC5: 0x6558, + 0x9DC6: 0x655E, + 0x9DC7: 0x655D, + 0x9DC8: 0x6572, + 0x9DC9: 0x6578, + 0x9DCA: 0x6582, + 0x9DCB: 0x6583, + 0x9DCC: 0x8B8A, + 0x9DCD: 0x659B, + 0x9DCE: 0x659F, + 0x9DCF: 0x65AB, + 0x9DD0: 0x65B7, + 0x9DD1: 0x65C3, + 0x9DD2: 0x65C6, + 0x9DD3: 0x65C1, + 0x9DD4: 0x65C4, + 0x9DD5: 0x65CC, + 0x9DD6: 0x65D2, + 0x9DD7: 0x65DB, + 0x9DD8: 0x65D9, + 0x9DD9: 0x65E0, + 0x9DDA: 0x65E1, + 0x9DDB: 0x65F1, + 0x9DDC: 0x6772, + 0x9DDD: 0x660A, + 0x9DDE: 0x6603, + 0x9DDF: 0x65FB, + 0x9DE0: 0x6773, + 0x9DE1: 0x6635, + 0x9DE2: 0x6636, + 0x9DE3: 0x6634, + 0x9DE4: 0x661C, + 0x9DE5: 0x664F, + 0x9DE6: 0x6644, + 0x9DE7: 0x6649, + 0x9DE8: 0x6641, + 0x9DE9: 0x665E, + 0x9DEA: 0x665D, + 0x9DEB: 0x6664, + 0x9DEC: 0x6667, + 0x9DED: 0x6668, + 0x9DEE: 0x665F, + 0x9DEF: 0x6662, + 0x9DF0: 0x6670, + 0x9DF1: 0x6683, + 0x9DF2: 0x6688, + 0x9DF3: 0x668E, + 0x9DF4: 0x6689, + 0x9DF5: 0x6684, + 0x9DF6: 0x6698, + 0x9DF7: 0x669D, + 0x9DF8: 0x66C1, + 0x9DF9: 0x66B9, + 0x9DFA: 0x66C9, + 0x9DFB: 0x66BE, + 0x9DFC: 0x66BC, + 0x9E40: 0x66C4, + 0x9E41: 0x66B8, + 0x9E42: 0x66D6, + 0x9E43: 0x66DA, + 0x9E44: 0x66E0, + 0x9E45: 0x663F, + 0x9E46: 0x66E6, + 0x9E47: 0x66E9, + 0x9E48: 0x66F0, + 0x9E49: 0x66F5, + 0x9E4A: 0x66F7, + 0x9E4B: 0x670F, + 0x9E4C: 0x6716, + 0x9E4D: 0x671E, + 0x9E4E: 0x6726, + 0x9E4F: 0x6727, + 0x9E50: 0x9738, + 0x9E51: 0x672E, + 0x9E52: 0x673F, + 0x9E53: 0x6736, + 0x9E54: 0x6741, + 0x9E55: 0x6738, + 0x9E56: 0x6737, + 0x9E57: 0x6746, + 0x9E58: 0x675E, + 0x9E59: 0x6760, + 0x9E5A: 0x6759, + 0x9E5B: 0x6763, + 0x9E5C: 0x6764, + 0x9E5D: 0x6789, + 0x9E5E: 0x6770, + 0x9E5F: 0x67A9, + 0x9E60: 0x677C, + 0x9E61: 0x676A, + 0x9E62: 0x678C, + 0x9E63: 0x678B, + 0x9E64: 0x67A6, + 0x9E65: 0x67A1, + 0x9E66: 0x6785, + 0x9E67: 0x67B7, + 0x9E68: 0x67EF, + 0x9E69: 0x67B4, + 0x9E6A: 0x67EC, + 0x9E6B: 0x67B3, + 0x9E6C: 0x67E9, + 0x9E6D: 0x67B8, + 0x9E6E: 0x67E4, + 0x9E6F: 0x67DE, + 0x9E70: 0x67DD, + 0x9E71: 0x67E2, + 0x9E72: 0x67EE, + 0x9E73: 0x67B9, + 0x9E74: 0x67CE, + 0x9E75: 0x67C6, + 0x9E76: 0x67E7, + 0x9E77: 0x6A9C, + 0x9E78: 0x681E, + 0x9E79: 0x6846, + 0x9E7A: 0x6829, + 0x9E7B: 0x6840, + 0x9E7C: 0x684D, + 0x9E7D: 0x6832, + 0x9E7E: 0x684E, + 0x9E80: 0x68B3, + 0x9E81: 0x682B, + 0x9E82: 0x6859, + 0x9E83: 0x6863, + 0x9E84: 0x6877, + 0x9E85: 0x687F, + 0x9E86: 0x689F, + 0x9E87: 0x688F, + 0x9E88: 0x68AD, + 0x9E89: 0x6894, + 0x9E8A: 0x689D, + 0x9E8B: 0x689B, + 0x9E8C: 0x6883, + 0x9E8D: 0x6AAE, + 0x9E8E: 0x68B9, + 0x9E8F: 0x6874, + 0x9E90: 0x68B5, + 0x9E91: 0x68A0, + 0x9E92: 0x68BA, + 0x9E93: 0x690F, + 0x9E94: 0x688D, + 0x9E95: 0x687E, + 0x9E96: 0x6901, + 0x9E97: 0x68CA, + 0x9E98: 0x6908, + 0x9E99: 0x68D8, + 0x9E9A: 0x6922, + 0x9E9B: 0x6926, + 0x9E9C: 0x68E1, + 0x9E9D: 0x690C, + 0x9E9E: 0x68CD, + 0x9E9F: 0x68D4, + 0x9EA0: 0x68E7, + 0x9EA1: 0x68D5, + 0x9EA2: 0x6936, + 0x9EA3: 0x6912, + 0x9EA4: 0x6904, + 0x9EA5: 0x68D7, + 0x9EA6: 0x68E3, + 0x9EA7: 0x6925, + 0x9EA8: 0x68F9, + 0x9EA9: 0x68E0, + 0x9EAA: 0x68EF, + 0x9EAB: 0x6928, + 0x9EAC: 0x692A, + 0x9EAD: 0x691A, + 0x9EAE: 0x6923, + 0x9EAF: 0x6921, + 0x9EB0: 0x68C6, + 0x9EB1: 0x6979, + 0x9EB2: 0x6977, + 0x9EB3: 0x695C, + 0x9EB4: 0x6978, + 0x9EB5: 0x696B, + 0x9EB6: 0x6954, + 0x9EB7: 0x697E, + 0x9EB8: 0x696E, + 0x9EB9: 0x6939, + 0x9EBA: 0x6974, + 0x9EBB: 0x693D, + 0x9EBC: 0x6959, + 0x9EBD: 0x6930, + 0x9EBE: 0x6961, + 0x9EBF: 0x695E, + 0x9EC0: 0x695D, + 0x9EC1: 0x6981, + 0x9EC2: 0x696A, + 0x9EC3: 0x69B2, + 0x9EC4: 0x69AE, + 0x9EC5: 0x69D0, + 0x9EC6: 0x69BF, + 0x9EC7: 0x69C1, + 0x9EC8: 0x69D3, + 0x9EC9: 0x69BE, + 0x9ECA: 0x69CE, + 0x9ECB: 0x5BE8, + 0x9ECC: 0x69CA, + 0x9ECD: 0x69DD, + 0x9ECE: 0x69BB, + 0x9ECF: 0x69C3, + 0x9ED0: 0x69A7, + 0x9ED1: 0x6A2E, + 0x9ED2: 0x6991, + 0x9ED3: 0x69A0, + 0x9ED4: 0x699C, + 0x9ED5: 0x6995, + 0x9ED6: 0x69B4, + 0x9ED7: 0x69DE, + 0x9ED8: 0x69E8, + 0x9ED9: 0x6A02, + 0x9EDA: 0x6A1B, + 0x9EDB: 0x69FF, + 0x9EDC: 0x6B0A, + 0x9EDD: 0x69F9, + 0x9EDE: 0x69F2, + 0x9EDF: 0x69E7, + 0x9EE0: 0x6A05, + 0x9EE1: 0x69B1, + 0x9EE2: 0x6A1E, + 0x9EE3: 0x69ED, + 0x9EE4: 0x6A14, + 0x9EE5: 0x69EB, + 0x9EE6: 0x6A0A, + 0x9EE7: 0x6A12, + 0x9EE8: 0x6AC1, + 0x9EE9: 0x6A23, + 0x9EEA: 0x6A13, + 0x9EEB: 0x6A44, + 0x9EEC: 0x6A0C, + 0x9EED: 0x6A72, + 0x9EEE: 0x6A36, + 0x9EEF: 0x6A78, + 0x9EF0: 0x6A47, + 0x9EF1: 0x6A62, + 0x9EF2: 0x6A59, + 0x9EF3: 0x6A66, + 0x9EF4: 0x6A48, + 0x9EF5: 0x6A38, + 0x9EF6: 0x6A22, + 0x9EF7: 0x6A90, + 0x9EF8: 0x6A8D, + 0x9EF9: 0x6AA0, + 0x9EFA: 0x6A84, + 0x9EFB: 0x6AA2, + 0x9EFC: 0x6AA3, + 0x9F40: 0x6A97, + 0x9F41: 0x8617, + 0x9F42: 0x6ABB, + 0x9F43: 0x6AC3, + 0x9F44: 0x6AC2, + 0x9F45: 0x6AB8, + 0x9F46: 0x6AB3, + 0x9F47: 0x6AAC, + 0x9F48: 0x6ADE, + 0x9F49: 0x6AD1, + 0x9F4A: 0x6ADF, + 0x9F4B: 0x6AAA, + 0x9F4C: 0x6ADA, + 0x9F4D: 0x6AEA, + 0x9F4E: 0x6AFB, + 0x9F4F: 0x6B05, + 0x9F50: 0x8616, + 0x9F51: 0x6AFA, + 0x9F52: 0x6B12, + 0x9F53: 0x6B16, + 0x9F54: 0x9B31, + 0x9F55: 0x6B1F, + 0x9F56: 0x6B38, + 0x9F57: 0x6B37, + 0x9F58: 0x76DC, + 0x9F59: 0x6B39, + 0x9F5A: 0x98EE, + 0x9F5B: 0x6B47, + 0x9F5C: 0x6B43, + 0x9F5D: 0x6B49, + 0x9F5E: 0x6B50, + 0x9F5F: 0x6B59, + 0x9F60: 0x6B54, + 0x9F61: 0x6B5B, + 0x9F62: 0x6B5F, + 0x9F63: 0x6B61, + 0x9F64: 0x6B78, + 0x9F65: 0x6B79, + 0x9F66: 0x6B7F, + 0x9F67: 0x6B80, + 0x9F68: 0x6B84, + 0x9F69: 0x6B83, + 0x9F6A: 0x6B8D, + 0x9F6B: 0x6B98, + 0x9F6C: 0x6B95, + 0x9F6D: 0x6B9E, + 0x9F6E: 0x6BA4, + 0x9F6F: 0x6BAA, + 0x9F70: 0x6BAB, + 0x9F71: 0x6BAF, + 0x9F72: 0x6BB2, + 0x9F73: 0x6BB1, + 0x9F74: 0x6BB3, + 0x9F75: 0x6BB7, + 0x9F76: 0x6BBC, + 0x9F77: 0x6BC6, + 0x9F78: 0x6BCB, + 0x9F79: 0x6BD3, + 0x9F7A: 0x6BDF, + 0x9F7B: 0x6BEC, + 0x9F7C: 0x6BEB, + 0x9F7D: 0x6BF3, + 0x9F7E: 0x6BEF, + 0x9F80: 0x9EBE, + 0x9F81: 0x6C08, + 0x9F82: 0x6C13, + 0x9F83: 0x6C14, + 0x9F84: 0x6C1B, + 0x9F85: 0x6C24, + 0x9F86: 0x6C23, + 0x9F87: 0x6C5E, + 0x9F88: 0x6C55, + 0x9F89: 0x6C62, + 0x9F8A: 0x6C6A, + 0x9F8B: 0x6C82, + 0x9F8C: 0x6C8D, + 0x9F8D: 0x6C9A, + 0x9F8E: 0x6C81, + 0x9F8F: 0x6C9B, + 0x9F90: 0x6C7E, + 0x9F91: 0x6C68, + 0x9F92: 0x6C73, + 0x9F93: 0x6C92, + 0x9F94: 0x6C90, + 0x9F95: 0x6CC4, + 0x9F96: 0x6CF1, + 0x9F97: 0x6CD3, + 0x9F98: 0x6CBD, + 0x9F99: 0x6CD7, + 0x9F9A: 0x6CC5, + 0x9F9B: 0x6CDD, + 0x9F9C: 0x6CAE, + 0x9F9D: 0x6CB1, + 0x9F9E: 0x6CBE, + 0x9F9F: 0x6CBA, + 0x9FA0: 0x6CDB, + 0x9FA1: 0x6CEF, + 0x9FA2: 0x6CD9, + 0x9FA3: 0x6CEA, + 0x9FA4: 0x6D1F, + 0x9FA5: 0x884D, + 0x9FA6: 0x6D36, + 0x9FA7: 0x6D2B, + 0x9FA8: 0x6D3D, + 0x9FA9: 0x6D38, + 0x9FAA: 0x6D19, + 0x9FAB: 0x6D35, + 0x9FAC: 0x6D33, + 0x9FAD: 0x6D12, + 0x9FAE: 0x6D0C, + 0x9FAF: 0x6D63, + 0x9FB0: 0x6D93, + 0x9FB1: 0x6D64, + 0x9FB2: 0x6D5A, + 0x9FB3: 0x6D79, + 0x9FB4: 0x6D59, + 0x9FB5: 0x6D8E, + 0x9FB6: 0x6D95, + 0x9FB7: 0x6FE4, + 0x9FB8: 0x6D85, + 0x9FB9: 0x6DF9, + 0x9FBA: 0x6E15, + 0x9FBB: 0x6E0A, + 0x9FBC: 0x6DB5, + 0x9FBD: 0x6DC7, + 0x9FBE: 0x6DE6, + 0x9FBF: 0x6DB8, + 0x9FC0: 0x6DC6, + 0x9FC1: 0x6DEC, + 0x9FC2: 0x6DDE, + 0x9FC3: 0x6DCC, + 0x9FC4: 0x6DE8, + 0x9FC5: 0x6DD2, + 0x9FC6: 0x6DC5, + 0x9FC7: 0x6DFA, + 0x9FC8: 0x6DD9, + 0x9FC9: 0x6DE4, + 0x9FCA: 0x6DD5, + 0x9FCB: 0x6DEA, + 0x9FCC: 0x6DEE, + 0x9FCD: 0x6E2D, + 0x9FCE: 0x6E6E, + 0x9FCF: 0x6E2E, + 0x9FD0: 0x6E19, + 0x9FD1: 0x6E72, + 0x9FD2: 0x6E5F, + 0x9FD3: 0x6E3E, + 0x9FD4: 0x6E23, + 0x9FD5: 0x6E6B, + 0x9FD6: 0x6E2B, + 0x9FD7: 0x6E76, + 0x9FD8: 0x6E4D, + 0x9FD9: 0x6E1F, + 0x9FDA: 0x6E43, + 0x9FDB: 0x6E3A, + 0x9FDC: 0x6E4E, + 0x9FDD: 0x6E24, + 0x9FDE: 0x6EFF, + 0x9FDF: 0x6E1D, + 0x9FE0: 0x6E38, + 0x9FE1: 0x6E82, + 0x9FE2: 0x6EAA, + 0x9FE3: 0x6E98, + 0x9FE4: 0x6EC9, + 0x9FE5: 0x6EB7, + 0x9FE6: 0x6ED3, + 0x9FE7: 0x6EBD, + 0x9FE8: 0x6EAF, + 0x9FE9: 0x6EC4, + 0x9FEA: 0x6EB2, + 0x9FEB: 0x6ED4, + 0x9FEC: 0x6ED5, + 0x9FED: 0x6E8F, + 0x9FEE: 0x6EA5, + 0x9FEF: 0x6EC2, + 0x9FF0: 0x6E9F, + 0x9FF1: 0x6F41, + 0x9FF2: 0x6F11, + 0x9FF3: 0x704C, + 0x9FF4: 0x6EEC, + 0x9FF5: 0x6EF8, + 0x9FF6: 0x6EFE, + 0x9FF7: 0x6F3F, + 0x9FF8: 0x6EF2, + 0x9FF9: 0x6F31, + 0x9FFA: 0x6EEF, + 0x9FFB: 0x6F32, + 0x9FFC: 0x6ECC, + 0xA1: 0xFF61, + 0xA2: 0xFF62, + 0xA3: 0xFF63, + 0xA4: 0xFF64, + 0xA5: 0xFF65, + 0xA6: 0xFF66, + 0xA7: 0xFF67, + 0xA8: 0xFF68, + 0xA9: 0xFF69, + 0xAA: 0xFF6A, + 0xAB: 0xFF6B, + 0xAC: 0xFF6C, + 0xAD: 0xFF6D, + 0xAE: 0xFF6E, + 0xAF: 0xFF6F, + 0xB0: 0xFF70, + 0xB1: 0xFF71, + 0xB2: 0xFF72, + 0xB3: 0xFF73, + 0xB4: 0xFF74, + 0xB5: 0xFF75, + 0xB6: 0xFF76, + 0xB7: 0xFF77, + 0xB8: 0xFF78, + 0xB9: 0xFF79, + 0xBA: 0xFF7A, + 0xBB: 0xFF7B, + 0xBC: 0xFF7C, + 0xBD: 0xFF7D, + 0xBE: 0xFF7E, + 0xBF: 0xFF7F, + 0xC0: 0xFF80, + 0xC1: 0xFF81, + 0xC2: 0xFF82, + 0xC3: 0xFF83, + 0xC4: 0xFF84, + 0xC5: 0xFF85, + 0xC6: 0xFF86, + 0xC7: 0xFF87, + 0xC8: 0xFF88, + 0xC9: 0xFF89, + 0xCA: 0xFF8A, + 0xCB: 0xFF8B, + 0xCC: 0xFF8C, + 0xCD: 0xFF8D, + 0xCE: 0xFF8E, + 0xCF: 0xFF8F, + 0xD0: 0xFF90, + 0xD1: 0xFF91, + 0xD2: 0xFF92, + 0xD3: 0xFF93, + 0xD4: 0xFF94, + 0xD5: 0xFF95, + 0xD6: 0xFF96, + 0xD7: 0xFF97, + 0xD8: 0xFF98, + 0xD9: 0xFF99, + 0xDA: 0xFF9A, + 0xDB: 0xFF9B, + 0xDC: 0xFF9C, + 0xDD: 0xFF9D, + 0xDE: 0xFF9E, + 0xDF: 0xFF9F, + 0xE040: 0x6F3E, + 0xE041: 0x6F13, + 0xE042: 0x6EF7, + 0xE043: 0x6F86, + 0xE044: 0x6F7A, + 0xE045: 0x6F78, + 0xE046: 0x6F81, + 0xE047: 0x6F80, + 0xE048: 0x6F6F, + 0xE049: 0x6F5B, + 0xE04A: 0x6FF3, + 0xE04B: 0x6F6D, + 0xE04C: 0x6F82, + 0xE04D: 0x6F7C, + 0xE04E: 0x6F58, + 0xE04F: 0x6F8E, + 0xE050: 0x6F91, + 0xE051: 0x6FC2, + 0xE052: 0x6F66, + 0xE053: 0x6FB3, + 0xE054: 0x6FA3, + 0xE055: 0x6FA1, + 0xE056: 0x6FA4, + 0xE057: 0x6FB9, + 0xE058: 0x6FC6, + 0xE059: 0x6FAA, + 0xE05A: 0x6FDF, + 0xE05B: 0x6FD5, + 0xE05C: 0x6FEC, + 0xE05D: 0x6FD4, + 0xE05E: 0x6FD8, + 0xE05F: 0x6FF1, + 0xE060: 0x6FEE, + 0xE061: 0x6FDB, + 0xE062: 0x7009, + 0xE063: 0x700B, + 0xE064: 0x6FFA, + 0xE065: 0x7011, + 0xE066: 0x7001, + 0xE067: 0x700F, + 0xE068: 0x6FFE, + 0xE069: 0x701B, + 0xE06A: 0x701A, + 0xE06B: 0x6F74, + 0xE06C: 0x701D, + 0xE06D: 0x7018, + 0xE06E: 0x701F, + 0xE06F: 0x7030, + 0xE070: 0x703E, + 0xE071: 0x7032, + 0xE072: 0x7051, + 0xE073: 0x7063, + 0xE074: 0x7099, + 0xE075: 0x7092, + 0xE076: 0x70AF, + 0xE077: 0x70F1, + 0xE078: 0x70AC, + 0xE079: 0x70B8, + 0xE07A: 0x70B3, + 0xE07B: 0x70AE, + 0xE07C: 0x70DF, + 0xE07D: 0x70CB, + 0xE07E: 0x70DD, + 0xE080: 0x70D9, + 0xE081: 0x7109, + 0xE082: 0x70FD, + 0xE083: 0x711C, + 0xE084: 0x7119, + 0xE085: 0x7165, + 0xE086: 0x7155, + 0xE087: 0x7188, + 0xE088: 0x7166, + 0xE089: 0x7162, + 0xE08A: 0x714C, + 0xE08B: 0x7156, + 0xE08C: 0x716C, + 0xE08D: 0x718F, + 0xE08E: 0x71FB, + 0xE08F: 0x7184, + 0xE090: 0x7195, + 0xE091: 0x71A8, + 0xE092: 0x71AC, + 0xE093: 0x71D7, + 0xE094: 0x71B9, + 0xE095: 0x71BE, + 0xE096: 0x71D2, + 0xE097: 0x71C9, + 0xE098: 0x71D4, + 0xE099: 0x71CE, + 0xE09A: 0x71E0, + 0xE09B: 0x71EC, + 0xE09C: 0x71E7, + 0xE09D: 0x71F5, + 0xE09E: 0x71FC, + 0xE09F: 0x71F9, + 0xE0A0: 0x71FF, + 0xE0A1: 0x720D, + 0xE0A2: 0x7210, + 0xE0A3: 0x721B, + 0xE0A4: 0x7228, + 0xE0A5: 0x722D, + 0xE0A6: 0x722C, + 0xE0A7: 0x7230, + 0xE0A8: 0x7232, + 0xE0A9: 0x723B, + 0xE0AA: 0x723C, + 0xE0AB: 0x723F, + 0xE0AC: 0x7240, + 0xE0AD: 0x7246, + 0xE0AE: 0x724B, + 0xE0AF: 0x7258, + 0xE0B0: 0x7274, + 0xE0B1: 0x727E, + 0xE0B2: 0x7282, + 0xE0B3: 0x7281, + 0xE0B4: 0x7287, + 0xE0B5: 0x7292, + 0xE0B6: 0x7296, + 0xE0B7: 0x72A2, + 0xE0B8: 0x72A7, + 0xE0B9: 0x72B9, + 0xE0BA: 0x72B2, + 0xE0BB: 0x72C3, + 0xE0BC: 0x72C6, + 0xE0BD: 0x72C4, + 0xE0BE: 0x72CE, + 0xE0BF: 0x72D2, + 0xE0C0: 0x72E2, + 0xE0C1: 0x72E0, + 0xE0C2: 0x72E1, + 0xE0C3: 0x72F9, + 0xE0C4: 0x72F7, + 0xE0C5: 0x500F, + 0xE0C6: 0x7317, + 0xE0C7: 0x730A, + 0xE0C8: 0x731C, + 0xE0C9: 0x7316, + 0xE0CA: 0x731D, + 0xE0CB: 0x7334, + 0xE0CC: 0x732F, + 0xE0CD: 0x7329, + 0xE0CE: 0x7325, + 0xE0CF: 0x733E, + 0xE0D0: 0x734E, + 0xE0D1: 0x734F, + 0xE0D2: 0x9ED8, + 0xE0D3: 0x7357, + 0xE0D4: 0x736A, + 0xE0D5: 0x7368, + 0xE0D6: 0x7370, + 0xE0D7: 0x7378, + 0xE0D8: 0x7375, + 0xE0D9: 0x737B, + 0xE0DA: 0x737A, + 0xE0DB: 0x73C8, + 0xE0DC: 0x73B3, + 0xE0DD: 0x73CE, + 0xE0DE: 0x73BB, + 0xE0DF: 0x73C0, + 0xE0E0: 0x73E5, + 0xE0E1: 0x73EE, + 0xE0E2: 0x73DE, + 0xE0E3: 0x74A2, + 0xE0E4: 0x7405, + 0xE0E5: 0x746F, + 0xE0E6: 0x7425, + 0xE0E7: 0x73F8, + 0xE0E8: 0x7432, + 0xE0E9: 0x743A, + 0xE0EA: 0x7455, + 0xE0EB: 0x743F, + 0xE0EC: 0x745F, + 0xE0ED: 0x7459, + 0xE0EE: 0x7441, + 0xE0EF: 0x745C, + 0xE0F0: 0x7469, + 0xE0F1: 0x7470, + 0xE0F2: 0x7463, + 0xE0F3: 0x746A, + 0xE0F4: 0x7476, + 0xE0F5: 0x747E, + 0xE0F6: 0x748B, + 0xE0F7: 0x749E, + 0xE0F8: 0x74A7, + 0xE0F9: 0x74CA, + 0xE0FA: 0x74CF, + 0xE0FB: 0x74D4, + 0xE0FC: 0x73F1, + 0xE140: 0x74E0, + 0xE141: 0x74E3, + 0xE142: 0x74E7, + 0xE143: 0x74E9, + 0xE144: 0x74EE, + 0xE145: 0x74F2, + 0xE146: 0x74F0, + 0xE147: 0x74F1, + 0xE148: 0x74F8, + 0xE149: 0x74F7, + 0xE14A: 0x7504, + 0xE14B: 0x7503, + 0xE14C: 0x7505, + 0xE14D: 0x750C, + 0xE14E: 0x750E, + 0xE14F: 0x750D, + 0xE150: 0x7515, + 0xE151: 0x7513, + 0xE152: 0x751E, + 0xE153: 0x7526, + 0xE154: 0x752C, + 0xE155: 0x753C, + 0xE156: 0x7544, + 0xE157: 0x754D, + 0xE158: 0x754A, + 0xE159: 0x7549, + 0xE15A: 0x755B, + 0xE15B: 0x7546, + 0xE15C: 0x755A, + 0xE15D: 0x7569, + 0xE15E: 0x7564, + 0xE15F: 0x7567, + 0xE160: 0x756B, + 0xE161: 0x756D, + 0xE162: 0x7578, + 0xE163: 0x7576, + 0xE164: 0x7586, + 0xE165: 0x7587, + 0xE166: 0x7574, + 0xE167: 0x758A, + 0xE168: 0x7589, + 0xE169: 0x7582, + 0xE16A: 0x7594, + 0xE16B: 0x759A, + 0xE16C: 0x759D, + 0xE16D: 0x75A5, + 0xE16E: 0x75A3, + 0xE16F: 0x75C2, + 0xE170: 0x75B3, + 0xE171: 0x75C3, + 0xE172: 0x75B5, + 0xE173: 0x75BD, + 0xE174: 0x75B8, + 0xE175: 0x75BC, + 0xE176: 0x75B1, + 0xE177: 0x75CD, + 0xE178: 0x75CA, + 0xE179: 0x75D2, + 0xE17A: 0x75D9, + 0xE17B: 0x75E3, + 0xE17C: 0x75DE, + 0xE17D: 0x75FE, + 0xE17E: 0x75FF, + 0xE180: 0x75FC, + 0xE181: 0x7601, + 0xE182: 0x75F0, + 0xE183: 0x75FA, + 0xE184: 0x75F2, + 0xE185: 0x75F3, + 0xE186: 0x760B, + 0xE187: 0x760D, + 0xE188: 0x7609, + 0xE189: 0x761F, + 0xE18A: 0x7627, + 0xE18B: 0x7620, + 0xE18C: 0x7621, + 0xE18D: 0x7622, + 0xE18E: 0x7624, + 0xE18F: 0x7634, + 0xE190: 0x7630, + 0xE191: 0x763B, + 0xE192: 0x7647, + 0xE193: 0x7648, + 0xE194: 0x7646, + 0xE195: 0x765C, + 0xE196: 0x7658, + 0xE197: 0x7661, + 0xE198: 0x7662, + 0xE199: 0x7668, + 0xE19A: 0x7669, + 0xE19B: 0x766A, + 0xE19C: 0x7667, + 0xE19D: 0x766C, + 0xE19E: 0x7670, + 0xE19F: 0x7672, + 0xE1A0: 0x7676, + 0xE1A1: 0x7678, + 0xE1A2: 0x767C, + 0xE1A3: 0x7680, + 0xE1A4: 0x7683, + 0xE1A5: 0x7688, + 0xE1A6: 0x768B, + 0xE1A7: 0x768E, + 0xE1A8: 0x7696, + 0xE1A9: 0x7693, + 0xE1AA: 0x7699, + 0xE1AB: 0x769A, + 0xE1AC: 0x76B0, + 0xE1AD: 0x76B4, + 0xE1AE: 0x76B8, + 0xE1AF: 0x76B9, + 0xE1B0: 0x76BA, + 0xE1B1: 0x76C2, + 0xE1B2: 0x76CD, + 0xE1B3: 0x76D6, + 0xE1B4: 0x76D2, + 0xE1B5: 0x76DE, + 0xE1B6: 0x76E1, + 0xE1B7: 0x76E5, + 0xE1B8: 0x76E7, + 0xE1B9: 0x76EA, + 0xE1BA: 0x862F, + 0xE1BB: 0x76FB, + 0xE1BC: 0x7708, + 0xE1BD: 0x7707, + 0xE1BE: 0x7704, + 0xE1BF: 0x7729, + 0xE1C0: 0x7724, + 0xE1C1: 0x771E, + 0xE1C2: 0x7725, + 0xE1C3: 0x7726, + 0xE1C4: 0x771B, + 0xE1C5: 0x7737, + 0xE1C6: 0x7738, + 0xE1C7: 0x7747, + 0xE1C8: 0x775A, + 0xE1C9: 0x7768, + 0xE1CA: 0x776B, + 0xE1CB: 0x775B, + 0xE1CC: 0x7765, + 0xE1CD: 0x777F, + 0xE1CE: 0x777E, + 0xE1CF: 0x7779, + 0xE1D0: 0x778E, + 0xE1D1: 0x778B, + 0xE1D2: 0x7791, + 0xE1D3: 0x77A0, + 0xE1D4: 0x779E, + 0xE1D5: 0x77B0, + 0xE1D6: 0x77B6, + 0xE1D7: 0x77B9, + 0xE1D8: 0x77BF, + 0xE1D9: 0x77BC, + 0xE1DA: 0x77BD, + 0xE1DB: 0x77BB, + 0xE1DC: 0x77C7, + 0xE1DD: 0x77CD, + 0xE1DE: 0x77D7, + 0xE1DF: 0x77DA, + 0xE1E0: 0x77DC, + 0xE1E1: 0x77E3, + 0xE1E2: 0x77EE, + 0xE1E3: 0x77FC, + 0xE1E4: 0x780C, + 0xE1E5: 0x7812, + 0xE1E6: 0x7926, + 0xE1E7: 0x7820, + 0xE1E8: 0x792A, + 0xE1E9: 0x7845, + 0xE1EA: 0x788E, + 0xE1EB: 0x7874, + 0xE1EC: 0x7886, + 0xE1ED: 0x787C, + 0xE1EE: 0x789A, + 0xE1EF: 0x788C, + 0xE1F0: 0x78A3, + 0xE1F1: 0x78B5, + 0xE1F2: 0x78AA, + 0xE1F3: 0x78AF, + 0xE1F4: 0x78D1, + 0xE1F5: 0x78C6, + 0xE1F6: 0x78CB, + 0xE1F7: 0x78D4, + 0xE1F8: 0x78BE, + 0xE1F9: 0x78BC, + 0xE1FA: 0x78C5, + 0xE1FB: 0x78CA, + 0xE1FC: 0x78EC, + 0xE240: 0x78E7, + 0xE241: 0x78DA, + 0xE242: 0x78FD, + 0xE243: 0x78F4, + 0xE244: 0x7907, + 0xE245: 0x7912, + 0xE246: 0x7911, + 0xE247: 0x7919, + 0xE248: 0x792C, + 0xE249: 0x792B, + 0xE24A: 0x7940, + 0xE24B: 0x7960, + 0xE24C: 0x7957, + 0xE24D: 0x795F, + 0xE24E: 0x795A, + 0xE24F: 0x7955, + 0xE250: 0x7953, + 0xE251: 0x797A, + 0xE252: 0x797F, + 0xE253: 0x798A, + 0xE254: 0x799D, + 0xE255: 0x79A7, + 0xE256: 0x9F4B, + 0xE257: 0x79AA, + 0xE258: 0x79AE, + 0xE259: 0x79B3, + 0xE25A: 0x79B9, + 0xE25B: 0x79BA, + 0xE25C: 0x79C9, + 0xE25D: 0x79D5, + 0xE25E: 0x79E7, + 0xE25F: 0x79EC, + 0xE260: 0x79E1, + 0xE261: 0x79E3, + 0xE262: 0x7A08, + 0xE263: 0x7A0D, + 0xE264: 0x7A18, + 0xE265: 0x7A19, + 0xE266: 0x7A20, + 0xE267: 0x7A1F, + 0xE268: 0x7980, + 0xE269: 0x7A31, + 0xE26A: 0x7A3B, + 0xE26B: 0x7A3E, + 0xE26C: 0x7A37, + 0xE26D: 0x7A43, + 0xE26E: 0x7A57, + 0xE26F: 0x7A49, + 0xE270: 0x7A61, + 0xE271: 0x7A62, + 0xE272: 0x7A69, + 0xE273: 0x9F9D, + 0xE274: 0x7A70, + 0xE275: 0x7A79, + 0xE276: 0x7A7D, + 0xE277: 0x7A88, + 0xE278: 0x7A97, + 0xE279: 0x7A95, + 0xE27A: 0x7A98, + 0xE27B: 0x7A96, + 0xE27C: 0x7AA9, + 0xE27D: 0x7AC8, + 0xE27E: 0x7AB0, + 0xE280: 0x7AB6, + 0xE281: 0x7AC5, + 0xE282: 0x7AC4, + 0xE283: 0x7ABF, + 0xE284: 0x9083, + 0xE285: 0x7AC7, + 0xE286: 0x7ACA, + 0xE287: 0x7ACD, + 0xE288: 0x7ACF, + 0xE289: 0x7AD5, + 0xE28A: 0x7AD3, + 0xE28B: 0x7AD9, + 0xE28C: 0x7ADA, + 0xE28D: 0x7ADD, + 0xE28E: 0x7AE1, + 0xE28F: 0x7AE2, + 0xE290: 0x7AE6, + 0xE291: 0x7AED, + 0xE292: 0x7AF0, + 0xE293: 0x7B02, + 0xE294: 0x7B0F, + 0xE295: 0x7B0A, + 0xE296: 0x7B06, + 0xE297: 0x7B33, + 0xE298: 0x7B18, + 0xE299: 0x7B19, + 0xE29A: 0x7B1E, + 0xE29B: 0x7B35, + 0xE29C: 0x7B28, + 0xE29D: 0x7B36, + 0xE29E: 0x7B50, + 0xE29F: 0x7B7A, + 0xE2A0: 0x7B04, + 0xE2A1: 0x7B4D, + 0xE2A2: 0x7B0B, + 0xE2A3: 0x7B4C, + 0xE2A4: 0x7B45, + 0xE2A5: 0x7B75, + 0xE2A6: 0x7B65, + 0xE2A7: 0x7B74, + 0xE2A8: 0x7B67, + 0xE2A9: 0x7B70, + 0xE2AA: 0x7B71, + 0xE2AB: 0x7B6C, + 0xE2AC: 0x7B6E, + 0xE2AD: 0x7B9D, + 0xE2AE: 0x7B98, + 0xE2AF: 0x7B9F, + 0xE2B0: 0x7B8D, + 0xE2B1: 0x7B9C, + 0xE2B2: 0x7B9A, + 0xE2B3: 0x7B8B, + 0xE2B4: 0x7B92, + 0xE2B5: 0x7B8F, + 0xE2B6: 0x7B5D, + 0xE2B7: 0x7B99, + 0xE2B8: 0x7BCB, + 0xE2B9: 0x7BC1, + 0xE2BA: 0x7BCC, + 0xE2BB: 0x7BCF, + 0xE2BC: 0x7BB4, + 0xE2BD: 0x7BC6, + 0xE2BE: 0x7BDD, + 0xE2BF: 0x7BE9, + 0xE2C0: 0x7C11, + 0xE2C1: 0x7C14, + 0xE2C2: 0x7BE6, + 0xE2C3: 0x7BE5, + 0xE2C4: 0x7C60, + 0xE2C5: 0x7C00, + 0xE2C6: 0x7C07, + 0xE2C7: 0x7C13, + 0xE2C8: 0x7BF3, + 0xE2C9: 0x7BF7, + 0xE2CA: 0x7C17, + 0xE2CB: 0x7C0D, + 0xE2CC: 0x7BF6, + 0xE2CD: 0x7C23, + 0xE2CE: 0x7C27, + 0xE2CF: 0x7C2A, + 0xE2D0: 0x7C1F, + 0xE2D1: 0x7C37, + 0xE2D2: 0x7C2B, + 0xE2D3: 0x7C3D, + 0xE2D4: 0x7C4C, + 0xE2D5: 0x7C43, + 0xE2D6: 0x7C54, + 0xE2D7: 0x7C4F, + 0xE2D8: 0x7C40, + 0xE2D9: 0x7C50, + 0xE2DA: 0x7C58, + 0xE2DB: 0x7C5F, + 0xE2DC: 0x7C64, + 0xE2DD: 0x7C56, + 0xE2DE: 0x7C65, + 0xE2DF: 0x7C6C, + 0xE2E0: 0x7C75, + 0xE2E1: 0x7C83, + 0xE2E2: 0x7C90, + 0xE2E3: 0x7CA4, + 0xE2E4: 0x7CAD, + 0xE2E5: 0x7CA2, + 0xE2E6: 0x7CAB, + 0xE2E7: 0x7CA1, + 0xE2E8: 0x7CA8, + 0xE2E9: 0x7CB3, + 0xE2EA: 0x7CB2, + 0xE2EB: 0x7CB1, + 0xE2EC: 0x7CAE, + 0xE2ED: 0x7CB9, + 0xE2EE: 0x7CBD, + 0xE2EF: 0x7CC0, + 0xE2F0: 0x7CC5, + 0xE2F1: 0x7CC2, + 0xE2F2: 0x7CD8, + 0xE2F3: 0x7CD2, + 0xE2F4: 0x7CDC, + 0xE2F5: 0x7CE2, + 0xE2F6: 0x9B3B, + 0xE2F7: 0x7CEF, + 0xE2F8: 0x7CF2, + 0xE2F9: 0x7CF4, + 0xE2FA: 0x7CF6, + 0xE2FB: 0x7CFA, + 0xE2FC: 0x7D06, + 0xE340: 0x7D02, + 0xE341: 0x7D1C, + 0xE342: 0x7D15, + 0xE343: 0x7D0A, + 0xE344: 0x7D45, + 0xE345: 0x7D4B, + 0xE346: 0x7D2E, + 0xE347: 0x7D32, + 0xE348: 0x7D3F, + 0xE349: 0x7D35, + 0xE34A: 0x7D46, + 0xE34B: 0x7D73, + 0xE34C: 0x7D56, + 0xE34D: 0x7D4E, + 0xE34E: 0x7D72, + 0xE34F: 0x7D68, + 0xE350: 0x7D6E, + 0xE351: 0x7D4F, + 0xE352: 0x7D63, + 0xE353: 0x7D93, + 0xE354: 0x7D89, + 0xE355: 0x7D5B, + 0xE356: 0x7D8F, + 0xE357: 0x7D7D, + 0xE358: 0x7D9B, + 0xE359: 0x7DBA, + 0xE35A: 0x7DAE, + 0xE35B: 0x7DA3, + 0xE35C: 0x7DB5, + 0xE35D: 0x7DC7, + 0xE35E: 0x7DBD, + 0xE35F: 0x7DAB, + 0xE360: 0x7E3D, + 0xE361: 0x7DA2, + 0xE362: 0x7DAF, + 0xE363: 0x7DDC, + 0xE364: 0x7DB8, + 0xE365: 0x7D9F, + 0xE366: 0x7DB0, + 0xE367: 0x7DD8, + 0xE368: 0x7DDD, + 0xE369: 0x7DE4, + 0xE36A: 0x7DDE, + 0xE36B: 0x7DFB, + 0xE36C: 0x7DF2, + 0xE36D: 0x7DE1, + 0xE36E: 0x7E05, + 0xE36F: 0x7E0A, + 0xE370: 0x7E23, + 0xE371: 0x7E21, + 0xE372: 0x7E12, + 0xE373: 0x7E31, + 0xE374: 0x7E1F, + 0xE375: 0x7E09, + 0xE376: 0x7E0B, + 0xE377: 0x7E22, + 0xE378: 0x7E46, + 0xE379: 0x7E66, + 0xE37A: 0x7E3B, + 0xE37B: 0x7E35, + 0xE37C: 0x7E39, + 0xE37D: 0x7E43, + 0xE37E: 0x7E37, + 0xE380: 0x7E32, + 0xE381: 0x7E3A, + 0xE382: 0x7E67, + 0xE383: 0x7E5D, + 0xE384: 0x7E56, + 0xE385: 0x7E5E, + 0xE386: 0x7E59, + 0xE387: 0x7E5A, + 0xE388: 0x7E79, + 0xE389: 0x7E6A, + 0xE38A: 0x7E69, + 0xE38B: 0x7E7C, + 0xE38C: 0x7E7B, + 0xE38D: 0x7E83, + 0xE38E: 0x7DD5, + 0xE38F: 0x7E7D, + 0xE390: 0x8FAE, + 0xE391: 0x7E7F, + 0xE392: 0x7E88, + 0xE393: 0x7E89, + 0xE394: 0x7E8C, + 0xE395: 0x7E92, + 0xE396: 0x7E90, + 0xE397: 0x7E93, + 0xE398: 0x7E94, + 0xE399: 0x7E96, + 0xE39A: 0x7E8E, + 0xE39B: 0x7E9B, + 0xE39C: 0x7E9C, + 0xE39D: 0x7F38, + 0xE39E: 0x7F3A, + 0xE39F: 0x7F45, + 0xE3A0: 0x7F4C, + 0xE3A1: 0x7F4D, + 0xE3A2: 0x7F4E, + 0xE3A3: 0x7F50, + 0xE3A4: 0x7F51, + 0xE3A5: 0x7F55, + 0xE3A6: 0x7F54, + 0xE3A7: 0x7F58, + 0xE3A8: 0x7F5F, + 0xE3A9: 0x7F60, + 0xE3AA: 0x7F68, + 0xE3AB: 0x7F69, + 0xE3AC: 0x7F67, + 0xE3AD: 0x7F78, + 0xE3AE: 0x7F82, + 0xE3AF: 0x7F86, + 0xE3B0: 0x7F83, + 0xE3B1: 0x7F88, + 0xE3B2: 0x7F87, + 0xE3B3: 0x7F8C, + 0xE3B4: 0x7F94, + 0xE3B5: 0x7F9E, + 0xE3B6: 0x7F9D, + 0xE3B7: 0x7F9A, + 0xE3B8: 0x7FA3, + 0xE3B9: 0x7FAF, + 0xE3BA: 0x7FB2, + 0xE3BB: 0x7FB9, + 0xE3BC: 0x7FAE, + 0xE3BD: 0x7FB6, + 0xE3BE: 0x7FB8, + 0xE3BF: 0x8B71, + 0xE3C0: 0x7FC5, + 0xE3C1: 0x7FC6, + 0xE3C2: 0x7FCA, + 0xE3C3: 0x7FD5, + 0xE3C4: 0x7FD4, + 0xE3C5: 0x7FE1, + 0xE3C6: 0x7FE6, + 0xE3C7: 0x7FE9, + 0xE3C8: 0x7FF3, + 0xE3C9: 0x7FF9, + 0xE3CA: 0x98DC, + 0xE3CB: 0x8006, + 0xE3CC: 0x8004, + 0xE3CD: 0x800B, + 0xE3CE: 0x8012, + 0xE3CF: 0x8018, + 0xE3D0: 0x8019, + 0xE3D1: 0x801C, + 0xE3D2: 0x8021, + 0xE3D3: 0x8028, + 0xE3D4: 0x803F, + 0xE3D5: 0x803B, + 0xE3D6: 0x804A, + 0xE3D7: 0x8046, + 0xE3D8: 0x8052, + 0xE3D9: 0x8058, + 0xE3DA: 0x805A, + 0xE3DB: 0x805F, + 0xE3DC: 0x8062, + 0xE3DD: 0x8068, + 0xE3DE: 0x8073, + 0xE3DF: 0x8072, + 0xE3E0: 0x8070, + 0xE3E1: 0x8076, + 0xE3E2: 0x8079, + 0xE3E3: 0x807D, + 0xE3E4: 0x807F, + 0xE3E5: 0x8084, + 0xE3E6: 0x8086, + 0xE3E7: 0x8085, + 0xE3E8: 0x809B, + 0xE3E9: 0x8093, + 0xE3EA: 0x809A, + 0xE3EB: 0x80AD, + 0xE3EC: 0x5190, + 0xE3ED: 0x80AC, + 0xE3EE: 0x80DB, + 0xE3EF: 0x80E5, + 0xE3F0: 0x80D9, + 0xE3F1: 0x80DD, + 0xE3F2: 0x80C4, + 0xE3F3: 0x80DA, + 0xE3F4: 0x80D6, + 0xE3F5: 0x8109, + 0xE3F6: 0x80EF, + 0xE3F7: 0x80F1, + 0xE3F8: 0x811B, + 0xE3F9: 0x8129, + 0xE3FA: 0x8123, + 0xE3FB: 0x812F, + 0xE3FC: 0x814B, + 0xE440: 0x968B, + 0xE441: 0x8146, + 0xE442: 0x813E, + 0xE443: 0x8153, + 0xE444: 0x8151, + 0xE445: 0x80FC, + 0xE446: 0x8171, + 0xE447: 0x816E, + 0xE448: 0x8165, + 0xE449: 0x8166, + 0xE44A: 0x8174, + 0xE44B: 0x8183, + 0xE44C: 0x8188, + 0xE44D: 0x818A, + 0xE44E: 0x8180, + 0xE44F: 0x8182, + 0xE450: 0x81A0, + 0xE451: 0x8195, + 0xE452: 0x81A4, + 0xE453: 0x81A3, + 0xE454: 0x815F, + 0xE455: 0x8193, + 0xE456: 0x81A9, + 0xE457: 0x81B0, + 0xE458: 0x81B5, + 0xE459: 0x81BE, + 0xE45A: 0x81B8, + 0xE45B: 0x81BD, + 0xE45C: 0x81C0, + 0xE45D: 0x81C2, + 0xE45E: 0x81BA, + 0xE45F: 0x81C9, + 0xE460: 0x81CD, + 0xE461: 0x81D1, + 0xE462: 0x81D9, + 0xE463: 0x81D8, + 0xE464: 0x81C8, + 0xE465: 0x81DA, + 0xE466: 0x81DF, + 0xE467: 0x81E0, + 0xE468: 0x81E7, + 0xE469: 0x81FA, + 0xE46A: 0x81FB, + 0xE46B: 0x81FE, + 0xE46C: 0x8201, + 0xE46D: 0x8202, + 0xE46E: 0x8205, + 0xE46F: 0x8207, + 0xE470: 0x820A, + 0xE471: 0x820D, + 0xE472: 0x8210, + 0xE473: 0x8216, + 0xE474: 0x8229, + 0xE475: 0x822B, + 0xE476: 0x8238, + 0xE477: 0x8233, + 0xE478: 0x8240, + 0xE479: 0x8259, + 0xE47A: 0x8258, + 0xE47B: 0x825D, + 0xE47C: 0x825A, + 0xE47D: 0x825F, + 0xE47E: 0x8264, + 0xE480: 0x8262, + 0xE481: 0x8268, + 0xE482: 0x826A, + 0xE483: 0x826B, + 0xE484: 0x822E, + 0xE485: 0x8271, + 0xE486: 0x8277, + 0xE487: 0x8278, + 0xE488: 0x827E, + 0xE489: 0x828D, + 0xE48A: 0x8292, + 0xE48B: 0x82AB, + 0xE48C: 0x829F, + 0xE48D: 0x82BB, + 0xE48E: 0x82AC, + 0xE48F: 0x82E1, + 0xE490: 0x82E3, + 0xE491: 0x82DF, + 0xE492: 0x82D2, + 0xE493: 0x82F4, + 0xE494: 0x82F3, + 0xE495: 0x82FA, + 0xE496: 0x8393, + 0xE497: 0x8303, + 0xE498: 0x82FB, + 0xE499: 0x82F9, + 0xE49A: 0x82DE, + 0xE49B: 0x8306, + 0xE49C: 0x82DC, + 0xE49D: 0x8309, + 0xE49E: 0x82D9, + 0xE49F: 0x8335, + 0xE4A0: 0x8334, + 0xE4A1: 0x8316, + 0xE4A2: 0x8332, + 0xE4A3: 0x8331, + 0xE4A4: 0x8340, + 0xE4A5: 0x8339, + 0xE4A6: 0x8350, + 0xE4A7: 0x8345, + 0xE4A8: 0x832F, + 0xE4A9: 0x832B, + 0xE4AA: 0x8317, + 0xE4AB: 0x8318, + 0xE4AC: 0x8385, + 0xE4AD: 0x839A, + 0xE4AE: 0x83AA, + 0xE4AF: 0x839F, + 0xE4B0: 0x83A2, + 0xE4B1: 0x8396, + 0xE4B2: 0x8323, + 0xE4B3: 0x838E, + 0xE4B4: 0x8387, + 0xE4B5: 0x838A, + 0xE4B6: 0x837C, + 0xE4B7: 0x83B5, + 0xE4B8: 0x8373, + 0xE4B9: 0x8375, + 0xE4BA: 0x83A0, + 0xE4BB: 0x8389, + 0xE4BC: 0x83A8, + 0xE4BD: 0x83F4, + 0xE4BE: 0x8413, + 0xE4BF: 0x83EB, + 0xE4C0: 0x83CE, + 0xE4C1: 0x83FD, + 0xE4C2: 0x8403, + 0xE4C3: 0x83D8, + 0xE4C4: 0x840B, + 0xE4C5: 0x83C1, + 0xE4C6: 0x83F7, + 0xE4C7: 0x8407, + 0xE4C8: 0x83E0, + 0xE4C9: 0x83F2, + 0xE4CA: 0x840D, + 0xE4CB: 0x8422, + 0xE4CC: 0x8420, + 0xE4CD: 0x83BD, + 0xE4CE: 0x8438, + 0xE4CF: 0x8506, + 0xE4D0: 0x83FB, + 0xE4D1: 0x846D, + 0xE4D2: 0x842A, + 0xE4D3: 0x843C, + 0xE4D4: 0x855A, + 0xE4D5: 0x8484, + 0xE4D6: 0x8477, + 0xE4D7: 0x846B, + 0xE4D8: 0x84AD, + 0xE4D9: 0x846E, + 0xE4DA: 0x8482, + 0xE4DB: 0x8469, + 0xE4DC: 0x8446, + 0xE4DD: 0x842C, + 0xE4DE: 0x846F, + 0xE4DF: 0x8479, + 0xE4E0: 0x8435, + 0xE4E1: 0x84CA, + 0xE4E2: 0x8462, + 0xE4E3: 0x84B9, + 0xE4E4: 0x84BF, + 0xE4E5: 0x849F, + 0xE4E6: 0x84D9, + 0xE4E7: 0x84CD, + 0xE4E8: 0x84BB, + 0xE4E9: 0x84DA, + 0xE4EA: 0x84D0, + 0xE4EB: 0x84C1, + 0xE4EC: 0x84C6, + 0xE4ED: 0x84D6, + 0xE4EE: 0x84A1, + 0xE4EF: 0x8521, + 0xE4F0: 0x84FF, + 0xE4F1: 0x84F4, + 0xE4F2: 0x8517, + 0xE4F3: 0x8518, + 0xE4F4: 0x852C, + 0xE4F5: 0x851F, + 0xE4F6: 0x8515, + 0xE4F7: 0x8514, + 0xE4F8: 0x84FC, + 0xE4F9: 0x8540, + 0xE4FA: 0x8563, + 0xE4FB: 0x8558, + 0xE4FC: 0x8548, + 0xE540: 0x8541, + 0xE541: 0x8602, + 0xE542: 0x854B, + 0xE543: 0x8555, + 0xE544: 0x8580, + 0xE545: 0x85A4, + 0xE546: 0x8588, + 0xE547: 0x8591, + 0xE548: 0x858A, + 0xE549: 0x85A8, + 0xE54A: 0x856D, + 0xE54B: 0x8594, + 0xE54C: 0x859B, + 0xE54D: 0x85EA, + 0xE54E: 0x8587, + 0xE54F: 0x859C, + 0xE550: 0x8577, + 0xE551: 0x857E, + 0xE552: 0x8590, + 0xE553: 0x85C9, + 0xE554: 0x85BA, + 0xE555: 0x85CF, + 0xE556: 0x85B9, + 0xE557: 0x85D0, + 0xE558: 0x85D5, + 0xE559: 0x85DD, + 0xE55A: 0x85E5, + 0xE55B: 0x85DC, + 0xE55C: 0x85F9, + 0xE55D: 0x860A, + 0xE55E: 0x8613, + 0xE55F: 0x860B, + 0xE560: 0x85FE, + 0xE561: 0x85FA, + 0xE562: 0x8606, + 0xE563: 0x8622, + 0xE564: 0x861A, + 0xE565: 0x8630, + 0xE566: 0x863F, + 0xE567: 0x864D, + 0xE568: 0x4E55, + 0xE569: 0x8654, + 0xE56A: 0x865F, + 0xE56B: 0x8667, + 0xE56C: 0x8671, + 0xE56D: 0x8693, + 0xE56E: 0x86A3, + 0xE56F: 0x86A9, + 0xE570: 0x86AA, + 0xE571: 0x868B, + 0xE572: 0x868C, + 0xE573: 0x86B6, + 0xE574: 0x86AF, + 0xE575: 0x86C4, + 0xE576: 0x86C6, + 0xE577: 0x86B0, + 0xE578: 0x86C9, + 0xE579: 0x8823, + 0xE57A: 0x86AB, + 0xE57B: 0x86D4, + 0xE57C: 0x86DE, + 0xE57D: 0x86E9, + 0xE57E: 0x86EC, + 0xE580: 0x86DF, + 0xE581: 0x86DB, + 0xE582: 0x86EF, + 0xE583: 0x8712, + 0xE584: 0x8706, + 0xE585: 0x8708, + 0xE586: 0x8700, + 0xE587: 0x8703, + 0xE588: 0x86FB, + 0xE589: 0x8711, + 0xE58A: 0x8709, + 0xE58B: 0x870D, + 0xE58C: 0x86F9, + 0xE58D: 0x870A, + 0xE58E: 0x8734, + 0xE58F: 0x873F, + 0xE590: 0x8737, + 0xE591: 0x873B, + 0xE592: 0x8725, + 0xE593: 0x8729, + 0xE594: 0x871A, + 0xE595: 0x8760, + 0xE596: 0x875F, + 0xE597: 0x8778, + 0xE598: 0x874C, + 0xE599: 0x874E, + 0xE59A: 0x8774, + 0xE59B: 0x8757, + 0xE59C: 0x8768, + 0xE59D: 0x876E, + 0xE59E: 0x8759, + 0xE59F: 0x8753, + 0xE5A0: 0x8763, + 0xE5A1: 0x876A, + 0xE5A2: 0x8805, + 0xE5A3: 0x87A2, + 0xE5A4: 0x879F, + 0xE5A5: 0x8782, + 0xE5A6: 0x87AF, + 0xE5A7: 0x87CB, + 0xE5A8: 0x87BD, + 0xE5A9: 0x87C0, + 0xE5AA: 0x87D0, + 0xE5AB: 0x96D6, + 0xE5AC: 0x87AB, + 0xE5AD: 0x87C4, + 0xE5AE: 0x87B3, + 0xE5AF: 0x87C7, + 0xE5B0: 0x87C6, + 0xE5B1: 0x87BB, + 0xE5B2: 0x87EF, + 0xE5B3: 0x87F2, + 0xE5B4: 0x87E0, + 0xE5B5: 0x880F, + 0xE5B6: 0x880D, + 0xE5B7: 0x87FE, + 0xE5B8: 0x87F6, + 0xE5B9: 0x87F7, + 0xE5BA: 0x880E, + 0xE5BB: 0x87D2, + 0xE5BC: 0x8811, + 0xE5BD: 0x8816, + 0xE5BE: 0x8815, + 0xE5BF: 0x8822, + 0xE5C0: 0x8821, + 0xE5C1: 0x8831, + 0xE5C2: 0x8836, + 0xE5C3: 0x8839, + 0xE5C4: 0x8827, + 0xE5C5: 0x883B, + 0xE5C6: 0x8844, + 0xE5C7: 0x8842, + 0xE5C8: 0x8852, + 0xE5C9: 0x8859, + 0xE5CA: 0x885E, + 0xE5CB: 0x8862, + 0xE5CC: 0x886B, + 0xE5CD: 0x8881, + 0xE5CE: 0x887E, + 0xE5CF: 0x889E, + 0xE5D0: 0x8875, + 0xE5D1: 0x887D, + 0xE5D2: 0x88B5, + 0xE5D3: 0x8872, + 0xE5D4: 0x8882, + 0xE5D5: 0x8897, + 0xE5D6: 0x8892, + 0xE5D7: 0x88AE, + 0xE5D8: 0x8899, + 0xE5D9: 0x88A2, + 0xE5DA: 0x888D, + 0xE5DB: 0x88A4, + 0xE5DC: 0x88B0, + 0xE5DD: 0x88BF, + 0xE5DE: 0x88B1, + 0xE5DF: 0x88C3, + 0xE5E0: 0x88C4, + 0xE5E1: 0x88D4, + 0xE5E2: 0x88D8, + 0xE5E3: 0x88D9, + 0xE5E4: 0x88DD, + 0xE5E5: 0x88F9, + 0xE5E6: 0x8902, + 0xE5E7: 0x88FC, + 0xE5E8: 0x88F4, + 0xE5E9: 0x88E8, + 0xE5EA: 0x88F2, + 0xE5EB: 0x8904, + 0xE5EC: 0x890C, + 0xE5ED: 0x890A, + 0xE5EE: 0x8913, + 0xE5EF: 0x8943, + 0xE5F0: 0x891E, + 0xE5F1: 0x8925, + 0xE5F2: 0x892A, + 0xE5F3: 0x892B, + 0xE5F4: 0x8941, + 0xE5F5: 0x8944, + 0xE5F6: 0x893B, + 0xE5F7: 0x8936, + 0xE5F8: 0x8938, + 0xE5F9: 0x894C, + 0xE5FA: 0x891D, + 0xE5FB: 0x8960, + 0xE5FC: 0x895E, + 0xE640: 0x8966, + 0xE641: 0x8964, + 0xE642: 0x896D, + 0xE643: 0x896A, + 0xE644: 0x896F, + 0xE645: 0x8974, + 0xE646: 0x8977, + 0xE647: 0x897E, + 0xE648: 0x8983, + 0xE649: 0x8988, + 0xE64A: 0x898A, + 0xE64B: 0x8993, + 0xE64C: 0x8998, + 0xE64D: 0x89A1, + 0xE64E: 0x89A9, + 0xE64F: 0x89A6, + 0xE650: 0x89AC, + 0xE651: 0x89AF, + 0xE652: 0x89B2, + 0xE653: 0x89BA, + 0xE654: 0x89BD, + 0xE655: 0x89BF, + 0xE656: 0x89C0, + 0xE657: 0x89DA, + 0xE658: 0x89DC, + 0xE659: 0x89DD, + 0xE65A: 0x89E7, + 0xE65B: 0x89F4, + 0xE65C: 0x89F8, + 0xE65D: 0x8A03, + 0xE65E: 0x8A16, + 0xE65F: 0x8A10, + 0xE660: 0x8A0C, + 0xE661: 0x8A1B, + 0xE662: 0x8A1D, + 0xE663: 0x8A25, + 0xE664: 0x8A36, + 0xE665: 0x8A41, + 0xE666: 0x8A5B, + 0xE667: 0x8A52, + 0xE668: 0x8A46, + 0xE669: 0x8A48, + 0xE66A: 0x8A7C, + 0xE66B: 0x8A6D, + 0xE66C: 0x8A6C, + 0xE66D: 0x8A62, + 0xE66E: 0x8A85, + 0xE66F: 0x8A82, + 0xE670: 0x8A84, + 0xE671: 0x8AA8, + 0xE672: 0x8AA1, + 0xE673: 0x8A91, + 0xE674: 0x8AA5, + 0xE675: 0x8AA6, + 0xE676: 0x8A9A, + 0xE677: 0x8AA3, + 0xE678: 0x8AC4, + 0xE679: 0x8ACD, + 0xE67A: 0x8AC2, + 0xE67B: 0x8ADA, + 0xE67C: 0x8AEB, + 0xE67D: 0x8AF3, + 0xE67E: 0x8AE7, + 0xE680: 0x8AE4, + 0xE681: 0x8AF1, + 0xE682: 0x8B14, + 0xE683: 0x8AE0, + 0xE684: 0x8AE2, + 0xE685: 0x8AF7, + 0xE686: 0x8ADE, + 0xE687: 0x8ADB, + 0xE688: 0x8B0C, + 0xE689: 0x8B07, + 0xE68A: 0x8B1A, + 0xE68B: 0x8AE1, + 0xE68C: 0x8B16, + 0xE68D: 0x8B10, + 0xE68E: 0x8B17, + 0xE68F: 0x8B20, + 0xE690: 0x8B33, + 0xE691: 0x97AB, + 0xE692: 0x8B26, + 0xE693: 0x8B2B, + 0xE694: 0x8B3E, + 0xE695: 0x8B28, + 0xE696: 0x8B41, + 0xE697: 0x8B4C, + 0xE698: 0x8B4F, + 0xE699: 0x8B4E, + 0xE69A: 0x8B49, + 0xE69B: 0x8B56, + 0xE69C: 0x8B5B, + 0xE69D: 0x8B5A, + 0xE69E: 0x8B6B, + 0xE69F: 0x8B5F, + 0xE6A0: 0x8B6C, + 0xE6A1: 0x8B6F, + 0xE6A2: 0x8B74, + 0xE6A3: 0x8B7D, + 0xE6A4: 0x8B80, + 0xE6A5: 0x8B8C, + 0xE6A6: 0x8B8E, + 0xE6A7: 0x8B92, + 0xE6A8: 0x8B93, + 0xE6A9: 0x8B96, + 0xE6AA: 0x8B99, + 0xE6AB: 0x8B9A, + 0xE6AC: 0x8C3A, + 0xE6AD: 0x8C41, + 0xE6AE: 0x8C3F, + 0xE6AF: 0x8C48, + 0xE6B0: 0x8C4C, + 0xE6B1: 0x8C4E, + 0xE6B2: 0x8C50, + 0xE6B3: 0x8C55, + 0xE6B4: 0x8C62, + 0xE6B5: 0x8C6C, + 0xE6B6: 0x8C78, + 0xE6B7: 0x8C7A, + 0xE6B8: 0x8C82, + 0xE6B9: 0x8C89, + 0xE6BA: 0x8C85, + 0xE6BB: 0x8C8A, + 0xE6BC: 0x8C8D, + 0xE6BD: 0x8C8E, + 0xE6BE: 0x8C94, + 0xE6BF: 0x8C7C, + 0xE6C0: 0x8C98, + 0xE6C1: 0x621D, + 0xE6C2: 0x8CAD, + 0xE6C3: 0x8CAA, + 0xE6C4: 0x8CBD, + 0xE6C5: 0x8CB2, + 0xE6C6: 0x8CB3, + 0xE6C7: 0x8CAE, + 0xE6C8: 0x8CB6, + 0xE6C9: 0x8CC8, + 0xE6CA: 0x8CC1, + 0xE6CB: 0x8CE4, + 0xE6CC: 0x8CE3, + 0xE6CD: 0x8CDA, + 0xE6CE: 0x8CFD, + 0xE6CF: 0x8CFA, + 0xE6D0: 0x8CFB, + 0xE6D1: 0x8D04, + 0xE6D2: 0x8D05, + 0xE6D3: 0x8D0A, + 0xE6D4: 0x8D07, + 0xE6D5: 0x8D0F, + 0xE6D6: 0x8D0D, + 0xE6D7: 0x8D10, + 0xE6D8: 0x9F4E, + 0xE6D9: 0x8D13, + 0xE6DA: 0x8CCD, + 0xE6DB: 0x8D14, + 0xE6DC: 0x8D16, + 0xE6DD: 0x8D67, + 0xE6DE: 0x8D6D, + 0xE6DF: 0x8D71, + 0xE6E0: 0x8D73, + 0xE6E1: 0x8D81, + 0xE6E2: 0x8D99, + 0xE6E3: 0x8DC2, + 0xE6E4: 0x8DBE, + 0xE6E5: 0x8DBA, + 0xE6E6: 0x8DCF, + 0xE6E7: 0x8DDA, + 0xE6E8: 0x8DD6, + 0xE6E9: 0x8DCC, + 0xE6EA: 0x8DDB, + 0xE6EB: 0x8DCB, + 0xE6EC: 0x8DEA, + 0xE6ED: 0x8DEB, + 0xE6EE: 0x8DDF, + 0xE6EF: 0x8DE3, + 0xE6F0: 0x8DFC, + 0xE6F1: 0x8E08, + 0xE6F2: 0x8E09, + 0xE6F3: 0x8DFF, + 0xE6F4: 0x8E1D, + 0xE6F5: 0x8E1E, + 0xE6F6: 0x8E10, + 0xE6F7: 0x8E1F, + 0xE6F8: 0x8E42, + 0xE6F9: 0x8E35, + 0xE6FA: 0x8E30, + 0xE6FB: 0x8E34, + 0xE6FC: 0x8E4A, + 0xE740: 0x8E47, + 0xE741: 0x8E49, + 0xE742: 0x8E4C, + 0xE743: 0x8E50, + 0xE744: 0x8E48, + 0xE745: 0x8E59, + 0xE746: 0x8E64, + 0xE747: 0x8E60, + 0xE748: 0x8E2A, + 0xE749: 0x8E63, + 0xE74A: 0x8E55, + 0xE74B: 0x8E76, + 0xE74C: 0x8E72, + 0xE74D: 0x8E7C, + 0xE74E: 0x8E81, + 0xE74F: 0x8E87, + 0xE750: 0x8E85, + 0xE751: 0x8E84, + 0xE752: 0x8E8B, + 0xE753: 0x8E8A, + 0xE754: 0x8E93, + 0xE755: 0x8E91, + 0xE756: 0x8E94, + 0xE757: 0x8E99, + 0xE758: 0x8EAA, + 0xE759: 0x8EA1, + 0xE75A: 0x8EAC, + 0xE75B: 0x8EB0, + 0xE75C: 0x8EC6, + 0xE75D: 0x8EB1, + 0xE75E: 0x8EBE, + 0xE75F: 0x8EC5, + 0xE760: 0x8EC8, + 0xE761: 0x8ECB, + 0xE762: 0x8EDB, + 0xE763: 0x8EE3, + 0xE764: 0x8EFC, + 0xE765: 0x8EFB, + 0xE766: 0x8EEB, + 0xE767: 0x8EFE, + 0xE768: 0x8F0A, + 0xE769: 0x8F05, + 0xE76A: 0x8F15, + 0xE76B: 0x8F12, + 0xE76C: 0x8F19, + 0xE76D: 0x8F13, + 0xE76E: 0x8F1C, + 0xE76F: 0x8F1F, + 0xE770: 0x8F1B, + 0xE771: 0x8F0C, + 0xE772: 0x8F26, + 0xE773: 0x8F33, + 0xE774: 0x8F3B, + 0xE775: 0x8F39, + 0xE776: 0x8F45, + 0xE777: 0x8F42, + 0xE778: 0x8F3E, + 0xE779: 0x8F4C, + 0xE77A: 0x8F49, + 0xE77B: 0x8F46, + 0xE77C: 0x8F4E, + 0xE77D: 0x8F57, + 0xE77E: 0x8F5C, + 0xE780: 0x8F62, + 0xE781: 0x8F63, + 0xE782: 0x8F64, + 0xE783: 0x8F9C, + 0xE784: 0x8F9F, + 0xE785: 0x8FA3, + 0xE786: 0x8FAD, + 0xE787: 0x8FAF, + 0xE788: 0x8FB7, + 0xE789: 0x8FDA, + 0xE78A: 0x8FE5, + 0xE78B: 0x8FE2, + 0xE78C: 0x8FEA, + 0xE78D: 0x8FEF, + 0xE78E: 0x9087, + 0xE78F: 0x8FF4, + 0xE790: 0x9005, + 0xE791: 0x8FF9, + 0xE792: 0x8FFA, + 0xE793: 0x9011, + 0xE794: 0x9015, + 0xE795: 0x9021, + 0xE796: 0x900D, + 0xE797: 0x901E, + 0xE798: 0x9016, + 0xE799: 0x900B, + 0xE79A: 0x9027, + 0xE79B: 0x9036, + 0xE79C: 0x9035, + 0xE79D: 0x9039, + 0xE79E: 0x8FF8, + 0xE79F: 0x904F, + 0xE7A0: 0x9050, + 0xE7A1: 0x9051, + 0xE7A2: 0x9052, + 0xE7A3: 0x900E, + 0xE7A4: 0x9049, + 0xE7A5: 0x903E, + 0xE7A6: 0x9056, + 0xE7A7: 0x9058, + 0xE7A8: 0x905E, + 0xE7A9: 0x9068, + 0xE7AA: 0x906F, + 0xE7AB: 0x9076, + 0xE7AC: 0x96A8, + 0xE7AD: 0x9072, + 0xE7AE: 0x9082, + 0xE7AF: 0x907D, + 0xE7B0: 0x9081, + 0xE7B1: 0x9080, + 0xE7B2: 0x908A, + 0xE7B3: 0x9089, + 0xE7B4: 0x908F, + 0xE7B5: 0x90A8, + 0xE7B6: 0x90AF, + 0xE7B7: 0x90B1, + 0xE7B8: 0x90B5, + 0xE7B9: 0x90E2, + 0xE7BA: 0x90E4, + 0xE7BB: 0x6248, + 0xE7BC: 0x90DB, + 0xE7BD: 0x9102, + 0xE7BE: 0x9112, + 0xE7BF: 0x9119, + 0xE7C0: 0x9132, + 0xE7C1: 0x9130, + 0xE7C2: 0x914A, + 0xE7C3: 0x9156, + 0xE7C4: 0x9158, + 0xE7C5: 0x9163, + 0xE7C6: 0x9165, + 0xE7C7: 0x9169, + 0xE7C8: 0x9173, + 0xE7C9: 0x9172, + 0xE7CA: 0x918B, + 0xE7CB: 0x9189, + 0xE7CC: 0x9182, + 0xE7CD: 0x91A2, + 0xE7CE: 0x91AB, + 0xE7CF: 0x91AF, + 0xE7D0: 0x91AA, + 0xE7D1: 0x91B5, + 0xE7D2: 0x91B4, + 0xE7D3: 0x91BA, + 0xE7D4: 0x91C0, + 0xE7D5: 0x91C1, + 0xE7D6: 0x91C9, + 0xE7D7: 0x91CB, + 0xE7D8: 0x91D0, + 0xE7D9: 0x91D6, + 0xE7DA: 0x91DF, + 0xE7DB: 0x91E1, + 0xE7DC: 0x91DB, + 0xE7DD: 0x91FC, + 0xE7DE: 0x91F5, + 0xE7DF: 0x91F6, + 0xE7E0: 0x921E, + 0xE7E1: 0x91FF, + 0xE7E2: 0x9214, + 0xE7E3: 0x922C, + 0xE7E4: 0x9215, + 0xE7E5: 0x9211, + 0xE7E6: 0x925E, + 0xE7E7: 0x9257, + 0xE7E8: 0x9245, + 0xE7E9: 0x9249, + 0xE7EA: 0x9264, + 0xE7EB: 0x9248, + 0xE7EC: 0x9295, + 0xE7ED: 0x923F, + 0xE7EE: 0x924B, + 0xE7EF: 0x9250, + 0xE7F0: 0x929C, + 0xE7F1: 0x9296, + 0xE7F2: 0x9293, + 0xE7F3: 0x929B, + 0xE7F4: 0x925A, + 0xE7F5: 0x92CF, + 0xE7F6: 0x92B9, + 0xE7F7: 0x92B7, + 0xE7F8: 0x92E9, + 0xE7F9: 0x930F, + 0xE7FA: 0x92FA, + 0xE7FB: 0x9344, + 0xE7FC: 0x932E, + 0xE840: 0x9319, + 0xE841: 0x9322, + 0xE842: 0x931A, + 0xE843: 0x9323, + 0xE844: 0x933A, + 0xE845: 0x9335, + 0xE846: 0x933B, + 0xE847: 0x935C, + 0xE848: 0x9360, + 0xE849: 0x937C, + 0xE84A: 0x936E, + 0xE84B: 0x9356, + 0xE84C: 0x93B0, + 0xE84D: 0x93AC, + 0xE84E: 0x93AD, + 0xE84F: 0x9394, + 0xE850: 0x93B9, + 0xE851: 0x93D6, + 0xE852: 0x93D7, + 0xE853: 0x93E8, + 0xE854: 0x93E5, + 0xE855: 0x93D8, + 0xE856: 0x93C3, + 0xE857: 0x93DD, + 0xE858: 0x93D0, + 0xE859: 0x93C8, + 0xE85A: 0x93E4, + 0xE85B: 0x941A, + 0xE85C: 0x9414, + 0xE85D: 0x9413, + 0xE85E: 0x9403, + 0xE85F: 0x9407, + 0xE860: 0x9410, + 0xE861: 0x9436, + 0xE862: 0x942B, + 0xE863: 0x9435, + 0xE864: 0x9421, + 0xE865: 0x943A, + 0xE866: 0x9441, + 0xE867: 0x9452, + 0xE868: 0x9444, + 0xE869: 0x945B, + 0xE86A: 0x9460, + 0xE86B: 0x9462, + 0xE86C: 0x945E, + 0xE86D: 0x946A, + 0xE86E: 0x9229, + 0xE86F: 0x9470, + 0xE870: 0x9475, + 0xE871: 0x9477, + 0xE872: 0x947D, + 0xE873: 0x945A, + 0xE874: 0x947C, + 0xE875: 0x947E, + 0xE876: 0x9481, + 0xE877: 0x947F, + 0xE878: 0x9582, + 0xE879: 0x9587, + 0xE87A: 0x958A, + 0xE87B: 0x9594, + 0xE87C: 0x9596, + 0xE87D: 0x9598, + 0xE87E: 0x9599, + 0xE880: 0x95A0, + 0xE881: 0x95A8, + 0xE882: 0x95A7, + 0xE883: 0x95AD, + 0xE884: 0x95BC, + 0xE885: 0x95BB, + 0xE886: 0x95B9, + 0xE887: 0x95BE, + 0xE888: 0x95CA, + 0xE889: 0x6FF6, + 0xE88A: 0x95C3, + 0xE88B: 0x95CD, + 0xE88C: 0x95CC, + 0xE88D: 0x95D5, + 0xE88E: 0x95D4, + 0xE88F: 0x95D6, + 0xE890: 0x95DC, + 0xE891: 0x95E1, + 0xE892: 0x95E5, + 0xE893: 0x95E2, + 0xE894: 0x9621, + 0xE895: 0x9628, + 0xE896: 0x962E, + 0xE897: 0x962F, + 0xE898: 0x9642, + 0xE899: 0x964C, + 0xE89A: 0x964F, + 0xE89B: 0x964B, + 0xE89C: 0x9677, + 0xE89D: 0x965C, + 0xE89E: 0x965E, + 0xE89F: 0x965D, + 0xE8A0: 0x965F, + 0xE8A1: 0x9666, + 0xE8A2: 0x9672, + 0xE8A3: 0x966C, + 0xE8A4: 0x968D, + 0xE8A5: 0x9698, + 0xE8A6: 0x9695, + 0xE8A7: 0x9697, + 0xE8A8: 0x96AA, + 0xE8A9: 0x96A7, + 0xE8AA: 0x96B1, + 0xE8AB: 0x96B2, + 0xE8AC: 0x96B0, + 0xE8AD: 0x96B4, + 0xE8AE: 0x96B6, + 0xE8AF: 0x96B8, + 0xE8B0: 0x96B9, + 0xE8B1: 0x96CE, + 0xE8B2: 0x96CB, + 0xE8B3: 0x96C9, + 0xE8B4: 0x96CD, + 0xE8B5: 0x894D, + 0xE8B6: 0x96DC, + 0xE8B7: 0x970D, + 0xE8B8: 0x96D5, + 0xE8B9: 0x96F9, + 0xE8BA: 0x9704, + 0xE8BB: 0x9706, + 0xE8BC: 0x9708, + 0xE8BD: 0x9713, + 0xE8BE: 0x970E, + 0xE8BF: 0x9711, + 0xE8C0: 0x970F, + 0xE8C1: 0x9716, + 0xE8C2: 0x9719, + 0xE8C3: 0x9724, + 0xE8C4: 0x972A, + 0xE8C5: 0x9730, + 0xE8C6: 0x9739, + 0xE8C7: 0x973D, + 0xE8C8: 0x973E, + 0xE8C9: 0x9744, + 0xE8CA: 0x9746, + 0xE8CB: 0x9748, + 0xE8CC: 0x9742, + 0xE8CD: 0x9749, + 0xE8CE: 0x975C, + 0xE8CF: 0x9760, + 0xE8D0: 0x9764, + 0xE8D1: 0x9766, + 0xE8D2: 0x9768, + 0xE8D3: 0x52D2, + 0xE8D4: 0x976B, + 0xE8D5: 0x9771, + 0xE8D6: 0x9779, + 0xE8D7: 0x9785, + 0xE8D8: 0x977C, + 0xE8D9: 0x9781, + 0xE8DA: 0x977A, + 0xE8DB: 0x9786, + 0xE8DC: 0x978B, + 0xE8DD: 0x978F, + 0xE8DE: 0x9790, + 0xE8DF: 0x979C, + 0xE8E0: 0x97A8, + 0xE8E1: 0x97A6, + 0xE8E2: 0x97A3, + 0xE8E3: 0x97B3, + 0xE8E4: 0x97B4, + 0xE8E5: 0x97C3, + 0xE8E6: 0x97C6, + 0xE8E7: 0x97C8, + 0xE8E8: 0x97CB, + 0xE8E9: 0x97DC, + 0xE8EA: 0x97ED, + 0xE8EB: 0x9F4F, + 0xE8EC: 0x97F2, + 0xE8ED: 0x7ADF, + 0xE8EE: 0x97F6, + 0xE8EF: 0x97F5, + 0xE8F0: 0x980F, + 0xE8F1: 0x980C, + 0xE8F2: 0x9838, + 0xE8F3: 0x9824, + 0xE8F4: 0x9821, + 0xE8F5: 0x9837, + 0xE8F6: 0x983D, + 0xE8F7: 0x9846, + 0xE8F8: 0x984F, + 0xE8F9: 0x984B, + 0xE8FA: 0x986B, + 0xE8FB: 0x986F, + 0xE8FC: 0x9870, + 0xE940: 0x9871, + 0xE941: 0x9874, + 0xE942: 0x9873, + 0xE943: 0x98AA, + 0xE944: 0x98AF, + 0xE945: 0x98B1, + 0xE946: 0x98B6, + 0xE947: 0x98C4, + 0xE948: 0x98C3, + 0xE949: 0x98C6, + 0xE94A: 0x98E9, + 0xE94B: 0x98EB, + 0xE94C: 0x9903, + 0xE94D: 0x9909, + 0xE94E: 0x9912, + 0xE94F: 0x9914, + 0xE950: 0x9918, + 0xE951: 0x9921, + 0xE952: 0x991D, + 0xE953: 0x991E, + 0xE954: 0x9924, + 0xE955: 0x9920, + 0xE956: 0x992C, + 0xE957: 0x992E, + 0xE958: 0x993D, + 0xE959: 0x993E, + 0xE95A: 0x9942, + 0xE95B: 0x9949, + 0xE95C: 0x9945, + 0xE95D: 0x9950, + 0xE95E: 0x994B, + 0xE95F: 0x9951, + 0xE960: 0x9952, + 0xE961: 0x994C, + 0xE962: 0x9955, + 0xE963: 0x9997, + 0xE964: 0x9998, + 0xE965: 0x99A5, + 0xE966: 0x99AD, + 0xE967: 0x99AE, + 0xE968: 0x99BC, + 0xE969: 0x99DF, + 0xE96A: 0x99DB, + 0xE96B: 0x99DD, + 0xE96C: 0x99D8, + 0xE96D: 0x99D1, + 0xE96E: 0x99ED, + 0xE96F: 0x99EE, + 0xE970: 0x99F1, + 0xE971: 0x99F2, + 0xE972: 0x99FB, + 0xE973: 0x99F8, + 0xE974: 0x9A01, + 0xE975: 0x9A0F, + 0xE976: 0x9A05, + 0xE977: 0x99E2, + 0xE978: 0x9A19, + 0xE979: 0x9A2B, + 0xE97A: 0x9A37, + 0xE97B: 0x9A45, + 0xE97C: 0x9A42, + 0xE97D: 0x9A40, + 0xE97E: 0x9A43, + 0xE980: 0x9A3E, + 0xE981: 0x9A55, + 0xE982: 0x9A4D, + 0xE983: 0x9A5B, + 0xE984: 0x9A57, + 0xE985: 0x9A5F, + 0xE986: 0x9A62, + 0xE987: 0x9A65, + 0xE988: 0x9A64, + 0xE989: 0x9A69, + 0xE98A: 0x9A6B, + 0xE98B: 0x9A6A, + 0xE98C: 0x9AAD, + 0xE98D: 0x9AB0, + 0xE98E: 0x9ABC, + 0xE98F: 0x9AC0, + 0xE990: 0x9ACF, + 0xE991: 0x9AD1, + 0xE992: 0x9AD3, + 0xE993: 0x9AD4, + 0xE994: 0x9ADE, + 0xE995: 0x9ADF, + 0xE996: 0x9AE2, + 0xE997: 0x9AE3, + 0xE998: 0x9AE6, + 0xE999: 0x9AEF, + 0xE99A: 0x9AEB, + 0xE99B: 0x9AEE, + 0xE99C: 0x9AF4, + 0xE99D: 0x9AF1, + 0xE99E: 0x9AF7, + 0xE99F: 0x9AFB, + 0xE9A0: 0x9B06, + 0xE9A1: 0x9B18, + 0xE9A2: 0x9B1A, + 0xE9A3: 0x9B1F, + 0xE9A4: 0x9B22, + 0xE9A5: 0x9B23, + 0xE9A6: 0x9B25, + 0xE9A7: 0x9B27, + 0xE9A8: 0x9B28, + 0xE9A9: 0x9B29, + 0xE9AA: 0x9B2A, + 0xE9AB: 0x9B2E, + 0xE9AC: 0x9B2F, + 0xE9AD: 0x9B32, + 0xE9AE: 0x9B44, + 0xE9AF: 0x9B43, + 0xE9B0: 0x9B4F, + 0xE9B1: 0x9B4D, + 0xE9B2: 0x9B4E, + 0xE9B3: 0x9B51, + 0xE9B4: 0x9B58, + 0xE9B5: 0x9B74, + 0xE9B6: 0x9B93, + 0xE9B7: 0x9B83, + 0xE9B8: 0x9B91, + 0xE9B9: 0x9B96, + 0xE9BA: 0x9B97, + 0xE9BB: 0x9B9F, + 0xE9BC: 0x9BA0, + 0xE9BD: 0x9BA8, + 0xE9BE: 0x9BB4, + 0xE9BF: 0x9BC0, + 0xE9C0: 0x9BCA, + 0xE9C1: 0x9BB9, + 0xE9C2: 0x9BC6, + 0xE9C3: 0x9BCF, + 0xE9C4: 0x9BD1, + 0xE9C5: 0x9BD2, + 0xE9C6: 0x9BE3, + 0xE9C7: 0x9BE2, + 0xE9C8: 0x9BE4, + 0xE9C9: 0x9BD4, + 0xE9CA: 0x9BE1, + 0xE9CB: 0x9C3A, + 0xE9CC: 0x9BF2, + 0xE9CD: 0x9BF1, + 0xE9CE: 0x9BF0, + 0xE9CF: 0x9C15, + 0xE9D0: 0x9C14, + 0xE9D1: 0x9C09, + 0xE9D2: 0x9C13, + 0xE9D3: 0x9C0C, + 0xE9D4: 0x9C06, + 0xE9D5: 0x9C08, + 0xE9D6: 0x9C12, + 0xE9D7: 0x9C0A, + 0xE9D8: 0x9C04, + 0xE9D9: 0x9C2E, + 0xE9DA: 0x9C1B, + 0xE9DB: 0x9C25, + 0xE9DC: 0x9C24, + 0xE9DD: 0x9C21, + 0xE9DE: 0x9C30, + 0xE9DF: 0x9C47, + 0xE9E0: 0x9C32, + 0xE9E1: 0x9C46, + 0xE9E2: 0x9C3E, + 0xE9E3: 0x9C5A, + 0xE9E4: 0x9C60, + 0xE9E5: 0x9C67, + 0xE9E6: 0x9C76, + 0xE9E7: 0x9C78, + 0xE9E8: 0x9CE7, + 0xE9E9: 0x9CEC, + 0xE9EA: 0x9CF0, + 0xE9EB: 0x9D09, + 0xE9EC: 0x9D08, + 0xE9ED: 0x9CEB, + 0xE9EE: 0x9D03, + 0xE9EF: 0x9D06, + 0xE9F0: 0x9D2A, + 0xE9F1: 0x9D26, + 0xE9F2: 0x9DAF, + 0xE9F3: 0x9D23, + 0xE9F4: 0x9D1F, + 0xE9F5: 0x9D44, + 0xE9F6: 0x9D15, + 0xE9F7: 0x9D12, + 0xE9F8: 0x9D41, + 0xE9F9: 0x9D3F, + 0xE9FA: 0x9D3E, + 0xE9FB: 0x9D46, + 0xE9FC: 0x9D48, + 0xEA40: 0x9D5D, + 0xEA41: 0x9D5E, + 0xEA42: 0x9D64, + 0xEA43: 0x9D51, + 0xEA44: 0x9D50, + 0xEA45: 0x9D59, + 0xEA46: 0x9D72, + 0xEA47: 0x9D89, + 0xEA48: 0x9D87, + 0xEA49: 0x9DAB, + 0xEA4A: 0x9D6F, + 0xEA4B: 0x9D7A, + 0xEA4C: 0x9D9A, + 0xEA4D: 0x9DA4, + 0xEA4E: 0x9DA9, + 0xEA4F: 0x9DB2, + 0xEA50: 0x9DC4, + 0xEA51: 0x9DC1, + 0xEA52: 0x9DBB, + 0xEA53: 0x9DB8, + 0xEA54: 0x9DBA, + 0xEA55: 0x9DC6, + 0xEA56: 0x9DCF, + 0xEA57: 0x9DC2, + 0xEA58: 0x9DD9, + 0xEA59: 0x9DD3, + 0xEA5A: 0x9DF8, + 0xEA5B: 0x9DE6, + 0xEA5C: 0x9DED, + 0xEA5D: 0x9DEF, + 0xEA5E: 0x9DFD, + 0xEA5F: 0x9E1A, + 0xEA60: 0x9E1B, + 0xEA61: 0x9E1E, + 0xEA62: 0x9E75, + 0xEA63: 0x9E79, + 0xEA64: 0x9E7D, + 0xEA65: 0x9E81, + 0xEA66: 0x9E88, + 0xEA67: 0x9E8B, + 0xEA68: 0x9E8C, + 0xEA69: 0x9E92, + 0xEA6A: 0x9E95, + 0xEA6B: 0x9E91, + 0xEA6C: 0x9E9D, + 0xEA6D: 0x9EA5, + 0xEA6E: 0x9EA9, + 0xEA6F: 0x9EB8, + 0xEA70: 0x9EAA, + 0xEA71: 0x9EAD, + 0xEA72: 0x9761, + 0xEA73: 0x9ECC, + 0xEA74: 0x9ECE, + 0xEA75: 0x9ECF, + 0xEA76: 0x9ED0, + 0xEA77: 0x9ED4, + 0xEA78: 0x9EDC, + 0xEA79: 0x9EDE, + 0xEA7A: 0x9EDD, + 0xEA7B: 0x9EE0, + 0xEA7C: 0x9EE5, + 0xEA7D: 0x9EE8, + 0xEA7E: 0x9EEF, + 0xEA80: 0x9EF4, + 0xEA81: 0x9EF6, + 0xEA82: 0x9EF7, + 0xEA83: 0x9EF9, + 0xEA84: 0x9EFB, + 0xEA85: 0x9EFC, + 0xEA86: 0x9EFD, + 0xEA87: 0x9F07, + 0xEA88: 0x9F08, + 0xEA89: 0x76B7, + 0xEA8A: 0x9F15, + 0xEA8B: 0x9F21, + 0xEA8C: 0x9F2C, + 0xEA8D: 0x9F3E, + 0xEA8E: 0x9F4A, + 0xEA8F: 0x9F52, + 0xEA90: 0x9F54, + 0xEA91: 0x9F63, + 0xEA92: 0x9F5F, + 0xEA93: 0x9F60, + 0xEA94: 0x9F61, + 0xEA95: 0x9F66, + 0xEA96: 0x9F67, + 0xEA97: 0x9F6C, + 0xEA98: 0x9F6A, + 0xEA99: 0x9F77, + 0xEA9A: 0x9F72, + 0xEA9B: 0x9F76, + 0xEA9C: 0x9F95, + 0xEA9D: 0x9F9C, + 0xEA9E: 0x9FA0, + 0xEA9F: 0x582F, + 0xEAA0: 0x69C7, + 0xEAA1: 0x9059, + 0xEAA2: 0x7464, + 0xEAA3: 0x51DC, + 0xEAA4: 0x7199, +}; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +var GenericGF_1 = __webpack_require__(1); +var GenericGFPoly_1 = __webpack_require__(2); +function runEuclideanAlgorithm(field, a, b, R) { + var _a; + // Assume a's degree is >= b's + if (a.degree() < b.degree()) { + _a = [b, a], a = _a[0], b = _a[1]; + } + var rLast = a; + var r = b; + var tLast = field.zero; + var t = field.one; + // Run Euclidean algorithm until r's degree is less than R/2 + while (r.degree() >= R / 2) { + var rLastLast = rLast; + var tLastLast = tLast; + rLast = r; + tLast = t; + // Divide rLastLast by rLast, with quotient in q and remainder in r + if (rLast.isZero()) { + // Euclidean algorithm already terminated? + return null; + } + r = rLastLast; + var q = field.zero; + var denominatorLeadingTerm = rLast.getCoefficient(rLast.degree()); + var dltInverse = field.inverse(denominatorLeadingTerm); + while (r.degree() >= rLast.degree() && !r.isZero()) { + var degreeDiff = r.degree() - rLast.degree(); + var scale = field.multiply(r.getCoefficient(r.degree()), dltInverse); + q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale)); + r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale)); + } + t = q.multiplyPoly(tLast).addOrSubtract(tLastLast); + if (r.degree() >= rLast.degree()) { + return null; + } + } + var sigmaTildeAtZero = t.getCoefficient(0); + if (sigmaTildeAtZero === 0) { + return null; + } + var inverse = field.inverse(sigmaTildeAtZero); + return [t.multiply(inverse), r.multiply(inverse)]; +} +function findErrorLocations(field, errorLocator) { + // This is a direct application of Chien's search + var numErrors = errorLocator.degree(); + if (numErrors === 1) { + return [errorLocator.getCoefficient(1)]; + } + var result = new Array(numErrors); + var errorCount = 0; + for (var i = 1; i < field.size && errorCount < numErrors; i++) { + if (errorLocator.evaluateAt(i) === 0) { + result[errorCount] = field.inverse(i); + errorCount++; + } + } + if (errorCount !== numErrors) { + return null; + } + return result; +} +function findErrorMagnitudes(field, errorEvaluator, errorLocations) { + // This is directly applying Forney's Formula + var s = errorLocations.length; + var result = new Array(s); + for (var i = 0; i < s; i++) { + var xiInverse = field.inverse(errorLocations[i]); + var denominator = 1; + for (var j = 0; j < s; j++) { + if (i !== j) { + denominator = field.multiply(denominator, GenericGF_1.addOrSubtractGF(1, field.multiply(errorLocations[j], xiInverse))); + } + } + result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator)); + if (field.generatorBase !== 0) { + result[i] = field.multiply(result[i], xiInverse); + } + } + return result; +} +function decode(bytes, twoS) { + var outputBytes = new Uint8ClampedArray(bytes.length); + outputBytes.set(bytes); + var field = new GenericGF_1.default(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1 + var poly = new GenericGFPoly_1.default(field, outputBytes); + var syndromeCoefficients = new Uint8ClampedArray(twoS); + var error = false; + for (var s = 0; s < twoS; s++) { + var evaluation = poly.evaluateAt(field.exp(s + field.generatorBase)); + syndromeCoefficients[syndromeCoefficients.length - 1 - s] = evaluation; + if (evaluation !== 0) { + error = true; + } + } + if (!error) { + return outputBytes; + } + var syndrome = new GenericGFPoly_1.default(field, syndromeCoefficients); + var sigmaOmega = runEuclideanAlgorithm(field, field.buildMonomial(twoS, 1), syndrome, twoS); + if (sigmaOmega === null) { + return null; + } + var errorLocations = findErrorLocations(field, sigmaOmega[0]); + if (errorLocations == null) { + return null; + } + var errorMagnitudes = findErrorMagnitudes(field, sigmaOmega[1], errorLocations); + for (var i = 0; i < errorLocations.length; i++) { + var position = outputBytes.length - 1 - field.log(errorLocations[i]); + if (position < 0) { + return null; + } + outputBytes[position] = GenericGF_1.addOrSubtractGF(outputBytes[position], errorMagnitudes[i]); + } + return outputBytes; +} +exports.decode = decode; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VERSIONS = [ + { + infoBits: null, + versionNumber: 1, + alignmentPatternCenters: [], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 7, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 19 }], + }, + { + ecCodewordsPerBlock: 10, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }], + }, + { + ecCodewordsPerBlock: 13, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 13 }], + }, + { + ecCodewordsPerBlock: 17, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 9 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 2, + alignmentPatternCenters: [6, 18], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 10, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 34 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 28 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 22 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 3, + alignmentPatternCenters: [6, 22], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 15, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 55 }], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 44 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 17 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 13 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 4, + alignmentPatternCenters: [6, 26], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 80 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 32 }], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 24 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 9 }], + }, + ], + }, + { + infoBits: null, + versionNumber: 5, + alignmentPatternCenters: [6, 30], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 108 }], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 43 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + { numBlocks: 2, dataCodewordsPerBlock: 16 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 11 }, + { numBlocks: 2, dataCodewordsPerBlock: 12 }, + ], + }, + ], + }, + { + infoBits: null, + versionNumber: 6, + alignmentPatternCenters: [6, 34], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 68 }], + }, + { + ecCodewordsPerBlock: 16, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 27 }], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 19 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 15 }], + }, + ], + }, + { + infoBits: 0x07C94, + versionNumber: 7, + alignmentPatternCenters: [6, 22, 38], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 78 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 31 }], + }, + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 4, dataCodewordsPerBlock: 15 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 13 }, + { numBlocks: 1, dataCodewordsPerBlock: 14 }, + ], + }, + ], + }, + { + infoBits: 0x085BC, + versionNumber: 8, + alignmentPatternCenters: [6, 24, 42], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 97 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 38 }, + { numBlocks: 2, dataCodewordsPerBlock: 39 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 18 }, + { numBlocks: 2, dataCodewordsPerBlock: 19 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 14 }, + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x09A99, + versionNumber: 9, + alignmentPatternCenters: [6, 26, 46], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 116 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 36 }, + { numBlocks: 2, dataCodewordsPerBlock: 37 }, + ], + }, + { + ecCodewordsPerBlock: 20, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 16 }, + { numBlocks: 4, dataCodewordsPerBlock: 17 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 12 }, + { numBlocks: 4, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0A4D3, + versionNumber: 10, + alignmentPatternCenters: [6, 28, 50], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 18, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 68 }, + { numBlocks: 2, dataCodewordsPerBlock: 69 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 43 }, + { numBlocks: 1, dataCodewordsPerBlock: 44 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 19 }, + { numBlocks: 2, dataCodewordsPerBlock: 20 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 15 }, + { numBlocks: 2, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x0BBF6, + versionNumber: 11, + alignmentPatternCenters: [6, 30, 54], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 20, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 81 }], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 50 }, + { numBlocks: 4, dataCodewordsPerBlock: 51 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 22 }, + { numBlocks: 4, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 12 }, + { numBlocks: 8, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0C762, + versionNumber: 12, + alignmentPatternCenters: [6, 32, 58], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 92 }, + { numBlocks: 2, dataCodewordsPerBlock: 93 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 36 }, + { numBlocks: 2, dataCodewordsPerBlock: 37 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 20 }, + { numBlocks: 6, dataCodewordsPerBlock: 21 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 14 }, + { numBlocks: 4, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x0D847, + versionNumber: 13, + alignmentPatternCenters: [6, 34, 62], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 107 }], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 37 }, + { numBlocks: 1, dataCodewordsPerBlock: 38 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 20 }, + { numBlocks: 4, dataCodewordsPerBlock: 21 }, + ], + }, + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 11 }, + { numBlocks: 4, dataCodewordsPerBlock: 12 }, + ], + }, + ], + }, + { + infoBits: 0x0E60D, + versionNumber: 14, + alignmentPatternCenters: [6, 26, 46, 66], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 115 }, + { numBlocks: 1, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 40 }, + { numBlocks: 5, dataCodewordsPerBlock: 41 }, + ], + }, + { + ecCodewordsPerBlock: 20, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 16 }, + { numBlocks: 5, dataCodewordsPerBlock: 17 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 12 }, + { numBlocks: 5, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x0F928, + versionNumber: 15, + alignmentPatternCenters: [6, 26, 48, 70], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 22, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 87 }, + { numBlocks: 1, dataCodewordsPerBlock: 88 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 41 }, + { numBlocks: 5, dataCodewordsPerBlock: 42 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 24 }, + { numBlocks: 7, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 12 }, + { numBlocks: 7, dataCodewordsPerBlock: 13 }, + ], + }, + ], + }, + { + infoBits: 0x10B78, + versionNumber: 16, + alignmentPatternCenters: [6, 26, 50, 74], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 98 }, + { numBlocks: 1, dataCodewordsPerBlock: 99 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 45 }, + { numBlocks: 3, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 19 }, + { numBlocks: 2, dataCodewordsPerBlock: 20 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 15 }, + { numBlocks: 13, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1145D, + versionNumber: 17, + alignmentPatternCenters: [6, 30, 54, 78], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 107 }, + { numBlocks: 5, dataCodewordsPerBlock: 108 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 46 }, + { numBlocks: 1, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 22 }, + { numBlocks: 15, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 17, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x12A17, + versionNumber: 18, + alignmentPatternCenters: [6, 30, 56, 82], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 120 }, + { numBlocks: 1, dataCodewordsPerBlock: 121 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 9, dataCodewordsPerBlock: 43 }, + { numBlocks: 4, dataCodewordsPerBlock: 44 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 22 }, + { numBlocks: 1, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 14 }, + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + ], + }, + ], + }, + { + infoBits: 0x13532, + versionNumber: 19, + alignmentPatternCenters: [6, 30, 58, 86], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 113 }, + { numBlocks: 4, dataCodewordsPerBlock: 114 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 44 }, + { numBlocks: 11, dataCodewordsPerBlock: 45 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 21 }, + { numBlocks: 4, dataCodewordsPerBlock: 22 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 9, dataCodewordsPerBlock: 13 }, + { numBlocks: 16, dataCodewordsPerBlock: 14 }, + ], + }, + ], + }, + { + infoBits: 0x149A6, + versionNumber: 20, + alignmentPatternCenters: [6, 34, 62, 90], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 107 }, + { numBlocks: 5, dataCodewordsPerBlock: 108 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 41 }, + { numBlocks: 13, dataCodewordsPerBlock: 42 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 24 }, + { numBlocks: 5, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 15 }, + { numBlocks: 10, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x15683, + versionNumber: 21, + alignmentPatternCenters: [6, 28, 50, 72, 94], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 116 }, + { numBlocks: 4, dataCodewordsPerBlock: 117 }, + ], + }, + { + ecCodewordsPerBlock: 26, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 42 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 22 }, + { numBlocks: 6, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 16 }, + { numBlocks: 6, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x168C9, + versionNumber: 22, + alignmentPatternCenters: [6, 26, 50, 74, 98], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 111 }, + { numBlocks: 7, dataCodewordsPerBlock: 112 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 46 }], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 24 }, + { numBlocks: 16, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 24, + ecBlocks: [{ numBlocks: 34, dataCodewordsPerBlock: 13 }], + }, + ], + }, + { + infoBits: 0x177EC, + versionNumber: 23, + alignmentPatternCenters: [6, 30, 54, 74, 102], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 121 }, + { numBlocks: 5, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 47 }, + { numBlocks: 14, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 16, dataCodewordsPerBlock: 15 }, + { numBlocks: 14, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x18EC4, + versionNumber: 24, + alignmentPatternCenters: [6, 28, 54, 80, 106], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 117 }, + { numBlocks: 4, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 45 }, + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 24 }, + { numBlocks: 16, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 30, dataCodewordsPerBlock: 16 }, + { numBlocks: 2, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x191E1, + versionNumber: 25, + alignmentPatternCenters: [6, 32, 58, 84, 110], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 26, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 106 }, + { numBlocks: 4, dataCodewordsPerBlock: 107 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 47 }, + { numBlocks: 13, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 24 }, + { numBlocks: 22, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 15 }, + { numBlocks: 13, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1AFAB, + versionNumber: 26, + alignmentPatternCenters: [6, 30, 58, 86, 114], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 114 }, + { numBlocks: 2, dataCodewordsPerBlock: 115 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 46 }, + { numBlocks: 4, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 28, dataCodewordsPerBlock: 22 }, + { numBlocks: 6, dataCodewordsPerBlock: 23 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 33, dataCodewordsPerBlock: 16 }, + { numBlocks: 4, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x1B08E, + versionNumber: 27, + alignmentPatternCenters: [6, 34, 62, 90, 118], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 122 }, + { numBlocks: 4, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 45 }, + { numBlocks: 3, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 8, dataCodewordsPerBlock: 23 }, + { numBlocks: 26, dataCodewordsPerBlock: 24 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 15 }, + { numBlocks: 28, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1CC1A, + versionNumber: 28, + alignmentPatternCenters: [6, 26, 50, 74, 98, 122], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 117 }, + { numBlocks: 10, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 3, dataCodewordsPerBlock: 45 }, + { numBlocks: 23, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 24 }, + { numBlocks: 31, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 15 }, + { numBlocks: 31, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1D33F, + versionNumber: 29, + alignmentPatternCenters: [6, 30, 54, 78, 102, 126], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 7, dataCodewordsPerBlock: 116 }, + { numBlocks: 7, dataCodewordsPerBlock: 117 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 21, dataCodewordsPerBlock: 45 }, + { numBlocks: 7, dataCodewordsPerBlock: 46 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 1, dataCodewordsPerBlock: 23 }, + { numBlocks: 37, dataCodewordsPerBlock: 24 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + { numBlocks: 26, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1ED75, + versionNumber: 30, + alignmentPatternCenters: [6, 26, 52, 78, 104, 130], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 5, dataCodewordsPerBlock: 115 }, + { numBlocks: 10, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 47 }, + { numBlocks: 10, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 15, dataCodewordsPerBlock: 24 }, + { numBlocks: 25, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 23, dataCodewordsPerBlock: 15 }, + { numBlocks: 25, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x1F250, + versionNumber: 31, + alignmentPatternCenters: [6, 30, 56, 82, 108, 134], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 115 }, + { numBlocks: 3, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 46 }, + { numBlocks: 29, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 42, dataCodewordsPerBlock: 24 }, + { numBlocks: 1, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 23, dataCodewordsPerBlock: 15 }, + { numBlocks: 28, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x209D5, + versionNumber: 32, + alignmentPatternCenters: [6, 34, 60, 86, 112, 138], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 115 }], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 46 }, + { numBlocks: 23, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 24 }, + { numBlocks: 35, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 15 }, + { numBlocks: 35, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x216F0, + versionNumber: 33, + alignmentPatternCenters: [6, 30, 58, 86, 114, 142], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 115 }, + { numBlocks: 1, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + { numBlocks: 21, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 29, dataCodewordsPerBlock: 24 }, + { numBlocks: 19, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 11, dataCodewordsPerBlock: 15 }, + { numBlocks: 46, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x228BA, + versionNumber: 34, + alignmentPatternCenters: [6, 34, 62, 90, 118, 146], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 115 }, + { numBlocks: 6, dataCodewordsPerBlock: 116 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 14, dataCodewordsPerBlock: 46 }, + { numBlocks: 23, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 44, dataCodewordsPerBlock: 24 }, + { numBlocks: 7, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 59, dataCodewordsPerBlock: 16 }, + { numBlocks: 1, dataCodewordsPerBlock: 17 }, + ], + }, + ], + }, + { + infoBits: 0x2379F, + versionNumber: 35, + alignmentPatternCenters: [6, 30, 54, 78, 102, 126, 150], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 121 }, + { numBlocks: 7, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 12, dataCodewordsPerBlock: 47 }, + { numBlocks: 26, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 39, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 22, dataCodewordsPerBlock: 15 }, + { numBlocks: 41, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x24B0B, + versionNumber: 36, + alignmentPatternCenters: [6, 24, 50, 76, 102, 128, 154], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 121 }, + { numBlocks: 14, dataCodewordsPerBlock: 122 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 6, dataCodewordsPerBlock: 47 }, + { numBlocks: 34, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 46, dataCodewordsPerBlock: 24 }, + { numBlocks: 10, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 2, dataCodewordsPerBlock: 15 }, + { numBlocks: 64, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x2542E, + versionNumber: 37, + alignmentPatternCenters: [6, 28, 54, 80, 106, 132, 158], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 17, dataCodewordsPerBlock: 122 }, + { numBlocks: 4, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 29, dataCodewordsPerBlock: 46 }, + { numBlocks: 14, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 49, dataCodewordsPerBlock: 24 }, + { numBlocks: 10, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 24, dataCodewordsPerBlock: 15 }, + { numBlocks: 46, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x26A64, + versionNumber: 38, + alignmentPatternCenters: [6, 32, 58, 84, 110, 136, 162], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 4, dataCodewordsPerBlock: 122 }, + { numBlocks: 18, dataCodewordsPerBlock: 123 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 13, dataCodewordsPerBlock: 46 }, + { numBlocks: 32, dataCodewordsPerBlock: 47 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 48, dataCodewordsPerBlock: 24 }, + { numBlocks: 14, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 42, dataCodewordsPerBlock: 15 }, + { numBlocks: 32, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x27541, + versionNumber: 39, + alignmentPatternCenters: [6, 26, 54, 82, 110, 138, 166], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 20, dataCodewordsPerBlock: 117 }, + { numBlocks: 4, dataCodewordsPerBlock: 118 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 40, dataCodewordsPerBlock: 47 }, + { numBlocks: 7, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 43, dataCodewordsPerBlock: 24 }, + { numBlocks: 22, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 10, dataCodewordsPerBlock: 15 }, + { numBlocks: 67, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, + { + infoBits: 0x28C69, + versionNumber: 40, + alignmentPatternCenters: [6, 30, 58, 86, 114, 142, 170], + errorCorrectionLevels: [ + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 19, dataCodewordsPerBlock: 118 }, + { numBlocks: 6, dataCodewordsPerBlock: 119 }, + ], + }, + { + ecCodewordsPerBlock: 28, + ecBlocks: [ + { numBlocks: 18, dataCodewordsPerBlock: 47 }, + { numBlocks: 31, dataCodewordsPerBlock: 48 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 34, dataCodewordsPerBlock: 24 }, + { numBlocks: 34, dataCodewordsPerBlock: 25 }, + ], + }, + { + ecCodewordsPerBlock: 30, + ecBlocks: [ + { numBlocks: 20, dataCodewordsPerBlock: 15 }, + { numBlocks: 61, dataCodewordsPerBlock: 16 }, + ], + }, + ], + }, +]; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +var BitMatrix_1 = __webpack_require__(0); +function squareToQuadrilateral(p1, p2, p3, p4) { + var dx3 = p1.x - p2.x + p3.x - p4.x; + var dy3 = p1.y - p2.y + p3.y - p4.y; + if (dx3 === 0 && dy3 === 0) { // Affine + return { + a11: p2.x - p1.x, + a12: p2.y - p1.y, + a13: 0, + a21: p3.x - p2.x, + a22: p3.y - p2.y, + a23: 0, + a31: p1.x, + a32: p1.y, + a33: 1, + }; + } + else { + var dx1 = p2.x - p3.x; + var dx2 = p4.x - p3.x; + var dy1 = p2.y - p3.y; + var dy2 = p4.y - p3.y; + var denominator = dx1 * dy2 - dx2 * dy1; + var a13 = (dx3 * dy2 - dx2 * dy3) / denominator; + var a23 = (dx1 * dy3 - dx3 * dy1) / denominator; + return { + a11: p2.x - p1.x + a13 * p2.x, + a12: p2.y - p1.y + a13 * p2.y, + a13: a13, + a21: p4.x - p1.x + a23 * p4.x, + a22: p4.y - p1.y + a23 * p4.y, + a23: a23, + a31: p1.x, + a32: p1.y, + a33: 1, + }; + } +} +function quadrilateralToSquare(p1, p2, p3, p4) { + // Here, the adjoint serves as the inverse: + var sToQ = squareToQuadrilateral(p1, p2, p3, p4); + return { + a11: sToQ.a22 * sToQ.a33 - sToQ.a23 * sToQ.a32, + a12: sToQ.a13 * sToQ.a32 - sToQ.a12 * sToQ.a33, + a13: sToQ.a12 * sToQ.a23 - sToQ.a13 * sToQ.a22, + a21: sToQ.a23 * sToQ.a31 - sToQ.a21 * sToQ.a33, + a22: sToQ.a11 * sToQ.a33 - sToQ.a13 * sToQ.a31, + a23: sToQ.a13 * sToQ.a21 - sToQ.a11 * sToQ.a23, + a31: sToQ.a21 * sToQ.a32 - sToQ.a22 * sToQ.a31, + a32: sToQ.a12 * sToQ.a31 - sToQ.a11 * sToQ.a32, + a33: sToQ.a11 * sToQ.a22 - sToQ.a12 * sToQ.a21, + }; +} +function times(a, b) { + return { + a11: a.a11 * b.a11 + a.a21 * b.a12 + a.a31 * b.a13, + a12: a.a12 * b.a11 + a.a22 * b.a12 + a.a32 * b.a13, + a13: a.a13 * b.a11 + a.a23 * b.a12 + a.a33 * b.a13, + a21: a.a11 * b.a21 + a.a21 * b.a22 + a.a31 * b.a23, + a22: a.a12 * b.a21 + a.a22 * b.a22 + a.a32 * b.a23, + a23: a.a13 * b.a21 + a.a23 * b.a22 + a.a33 * b.a23, + a31: a.a11 * b.a31 + a.a21 * b.a32 + a.a31 * b.a33, + a32: a.a12 * b.a31 + a.a22 * b.a32 + a.a32 * b.a33, + a33: a.a13 * b.a31 + a.a23 * b.a32 + a.a33 * b.a33, + }; +} +function extract(image, location) { + var qToS = quadrilateralToSquare({ x: 3.5, y: 3.5 }, { x: location.dimension - 3.5, y: 3.5 }, { x: location.dimension - 6.5, y: location.dimension - 6.5 }, { x: 3.5, y: location.dimension - 3.5 }); + var sToQ = squareToQuadrilateral(location.topLeft, location.topRight, location.alignmentPattern, location.bottomLeft); + var transform = times(sToQ, qToS); + var matrix = BitMatrix_1.BitMatrix.createEmpty(location.dimension, location.dimension); + var mappingFunction = function (x, y) { + var denominator = transform.a13 * x + transform.a23 * y + transform.a33; + return { + x: (transform.a11 * x + transform.a21 * y + transform.a31) / denominator, + y: (transform.a12 * x + transform.a22 * y + transform.a32) / denominator, + }; + }; + for (var y = 0; y < location.dimension; y++) { + for (var x = 0; x < location.dimension; x++) { + var xValue = x + 0.5; + var yValue = y + 0.5; + var sourcePixel = mappingFunction(xValue, yValue); + matrix.set(x, y, image.get(Math.floor(sourcePixel.x), Math.floor(sourcePixel.y))); + } + } + return { + matrix: matrix, + mappingFunction: mappingFunction, + }; +} +exports.extract = extract; + + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +var MAX_FINDERPATTERNS_TO_SEARCH = 4; +var MIN_QUAD_RATIO = 0.5; +var MAX_QUAD_RATIO = 1.5; +var distance = function (a, b) { return Math.sqrt(Math.pow((b.x - a.x), 2) + Math.pow((b.y - a.y), 2)); }; +function sum(values) { + return values.reduce(function (a, b) { return a + b; }); +} +// Takes three finder patterns and organizes them into topLeft, topRight, etc +function reorderFinderPatterns(pattern1, pattern2, pattern3) { + var _a, _b, _c, _d; + // Find distances between pattern centers + var oneTwoDistance = distance(pattern1, pattern2); + var twoThreeDistance = distance(pattern2, pattern3); + var oneThreeDistance = distance(pattern1, pattern3); + var bottomLeft; + var topLeft; + var topRight; + // Assume one closest to other two is B; A and C will just be guesses at first + if (twoThreeDistance >= oneTwoDistance && twoThreeDistance >= oneThreeDistance) { + _a = [pattern2, pattern1, pattern3], bottomLeft = _a[0], topLeft = _a[1], topRight = _a[2]; + } + else if (oneThreeDistance >= twoThreeDistance && oneThreeDistance >= oneTwoDistance) { + _b = [pattern1, pattern2, pattern3], bottomLeft = _b[0], topLeft = _b[1], topRight = _b[2]; + } + else { + _c = [pattern1, pattern3, pattern2], bottomLeft = _c[0], topLeft = _c[1], topRight = _c[2]; + } + // Use cross product to figure out whether bottomLeft (A) and topRight (C) are correct or flipped in relation to topLeft (B) + // This asks whether BC x BA has a positive z component, which is the arrangement we want. If it's negative, then + // we've got it flipped around and should swap topRight and bottomLeft. + if (((topRight.x - topLeft.x) * (bottomLeft.y - topLeft.y)) - ((topRight.y - topLeft.y) * (bottomLeft.x - topLeft.x)) < 0) { + _d = [topRight, bottomLeft], bottomLeft = _d[0], topRight = _d[1]; + } + return { bottomLeft: bottomLeft, topLeft: topLeft, topRight: topRight }; +} +// Computes the dimension (number of modules on a side) of the QR Code based on the position of the finder patterns +function computeDimension(topLeft, topRight, bottomLeft, matrix) { + var moduleSize = (sum(countBlackWhiteRun(topLeft, bottomLeft, matrix, 5)) / 7 + // Divide by 7 since the ratio is 1:1:3:1:1 + sum(countBlackWhiteRun(topLeft, topRight, matrix, 5)) / 7 + + sum(countBlackWhiteRun(bottomLeft, topLeft, matrix, 5)) / 7 + + sum(countBlackWhiteRun(topRight, topLeft, matrix, 5)) / 7) / 4; + if (moduleSize < 1) { + throw new Error("Invalid module size"); + } + var topDimension = Math.round(distance(topLeft, topRight) / moduleSize); + var sideDimension = Math.round(distance(topLeft, bottomLeft) / moduleSize); + var dimension = Math.floor((topDimension + sideDimension) / 2) + 7; + switch (dimension % 4) { + case 0: + dimension++; + break; + case 2: + dimension--; + break; + } + return { dimension: dimension, moduleSize: moduleSize }; +} +// Takes an origin point and an end point and counts the sizes of the black white run from the origin towards the end point. +// Returns an array of elements, representing the pixel size of the black white run. +// Uses a variant of http://en.wikipedia.org/wiki/Bresenham's_line_algorithm +function countBlackWhiteRunTowardsPoint(origin, end, matrix, length) { + var switchPoints = [{ x: Math.floor(origin.x), y: Math.floor(origin.y) }]; + var steep = Math.abs(end.y - origin.y) > Math.abs(end.x - origin.x); + var fromX; + var fromY; + var toX; + var toY; + if (steep) { + fromX = Math.floor(origin.y); + fromY = Math.floor(origin.x); + toX = Math.floor(end.y); + toY = Math.floor(end.x); + } + else { + fromX = Math.floor(origin.x); + fromY = Math.floor(origin.y); + toX = Math.floor(end.x); + toY = Math.floor(end.y); + } + var dx = Math.abs(toX - fromX); + var dy = Math.abs(toY - fromY); + var error = Math.floor(-dx / 2); + var xStep = fromX < toX ? 1 : -1; + var yStep = fromY < toY ? 1 : -1; + var currentPixel = true; + // Loop up until x == toX, but not beyond + for (var x = fromX, y = fromY; x !== toX + xStep; x += xStep) { + // Does current pixel mean we have moved white to black or vice versa? + // Scanning black in state 0,2 and white in state 1, so if we find the wrong + // color, advance to next state or end if we are in state 2 already + var realX = steep ? y : x; + var realY = steep ? x : y; + if (matrix.get(realX, realY) !== currentPixel) { + currentPixel = !currentPixel; + switchPoints.push({ x: realX, y: realY }); + if (switchPoints.length === length + 1) { + break; + } + } + error += dy; + if (error > 0) { + if (y === toY) { + break; + } + y += yStep; + error -= dx; + } + } + var distances = []; + for (var i = 0; i < length; i++) { + if (switchPoints[i] && switchPoints[i + 1]) { + distances.push(distance(switchPoints[i], switchPoints[i + 1])); + } + else { + distances.push(0); + } + } + return distances; +} +// Takes an origin point and an end point and counts the sizes of the black white run in the origin point +// along the line that intersects with the end point. Returns an array of elements, representing the pixel sizes +// of the black white run. Takes a length which represents the number of switches from black to white to look for. +function countBlackWhiteRun(origin, end, matrix, length) { + var _a; + var rise = end.y - origin.y; + var run = end.x - origin.x; + var towardsEnd = countBlackWhiteRunTowardsPoint(origin, end, matrix, Math.ceil(length / 2)); + var awayFromEnd = countBlackWhiteRunTowardsPoint(origin, { x: origin.x - run, y: origin.y - rise }, matrix, Math.ceil(length / 2)); + var middleValue = towardsEnd.shift() + awayFromEnd.shift() - 1; // Substract one so we don't double count a pixel + return (_a = awayFromEnd.concat(middleValue)).concat.apply(_a, towardsEnd); +} +// Takes in a black white run and an array of expected ratios. Returns the average size of the run as well as the "error" - +// that is the amount the run diverges from the expected ratio +function scoreBlackWhiteRun(sequence, ratios) { + var averageSize = sum(sequence) / sum(ratios); + var error = 0; + ratios.forEach(function (ratio, i) { + error += Math.pow((sequence[i] - ratio * averageSize), 2); + }); + return { averageSize: averageSize, error: error }; +} +// Takes an X,Y point and an array of sizes and scores the point against those ratios. +// For example for a finder pattern takes the ratio list of 1:1:3:1:1 and checks horizontal, vertical and diagonal ratios +// against that. +function scorePattern(point, ratios, matrix) { + try { + var horizontalRun = countBlackWhiteRun(point, { x: -1, y: point.y }, matrix, ratios.length); + var verticalRun = countBlackWhiteRun(point, { x: point.x, y: -1 }, matrix, ratios.length); + var topLeftPoint = { + x: Math.max(0, point.x - point.y) - 1, + y: Math.max(0, point.y - point.x) - 1, + }; + var topLeftBottomRightRun = countBlackWhiteRun(point, topLeftPoint, matrix, ratios.length); + var bottomLeftPoint = { + x: Math.min(matrix.width, point.x + point.y) + 1, + y: Math.min(matrix.height, point.y + point.x) + 1, + }; + var bottomLeftTopRightRun = countBlackWhiteRun(point, bottomLeftPoint, matrix, ratios.length); + var horzError = scoreBlackWhiteRun(horizontalRun, ratios); + var vertError = scoreBlackWhiteRun(verticalRun, ratios); + var diagDownError = scoreBlackWhiteRun(topLeftBottomRightRun, ratios); + var diagUpError = scoreBlackWhiteRun(bottomLeftTopRightRun, ratios); + var ratioError = Math.sqrt(horzError.error * horzError.error + + vertError.error * vertError.error + + diagDownError.error * diagDownError.error + + diagUpError.error * diagUpError.error); + var avgSize = (horzError.averageSize + vertError.averageSize + diagDownError.averageSize + diagUpError.averageSize) / 4; + var sizeError = (Math.pow((horzError.averageSize - avgSize), 2) + + Math.pow((vertError.averageSize - avgSize), 2) + + Math.pow((diagDownError.averageSize - avgSize), 2) + + Math.pow((diagUpError.averageSize - avgSize), 2)) / avgSize; + return ratioError + sizeError; + } + catch (_a) { + return Infinity; + } +} +function recenterLocation(matrix, p) { + var leftX = Math.round(p.x); + while (matrix.get(leftX, Math.round(p.y))) { + leftX--; + } + var rightX = Math.round(p.x); + while (matrix.get(rightX, Math.round(p.y))) { + rightX++; + } + var x = (leftX + rightX) / 2; + var topY = Math.round(p.y); + while (matrix.get(Math.round(x), topY)) { + topY--; + } + var bottomY = Math.round(p.y); + while (matrix.get(Math.round(x), bottomY)) { + bottomY++; + } + var y = (topY + bottomY) / 2; + return { x: x, y: y }; +} +function locate(matrix) { + var finderPatternQuads = []; + var activeFinderPatternQuads = []; + var alignmentPatternQuads = []; + var activeAlignmentPatternQuads = []; + var _loop_1 = function (y) { + var length_1 = 0; + var lastBit = false; + var scans = [0, 0, 0, 0, 0]; + var _loop_2 = function (x) { + var v = matrix.get(x, y); + if (v === lastBit) { + length_1++; + } + else { + scans = [scans[1], scans[2], scans[3], scans[4], length_1]; + length_1 = 1; + lastBit = v; + // Do the last 5 color changes ~ match the expected ratio for a finder pattern? 1:1:3:1:1 of b:w:b:w:b + var averageFinderPatternBlocksize = sum(scans) / 7; + var validFinderPattern = Math.abs(scans[0] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[1] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[2] - 3 * averageFinderPatternBlocksize) < 3 * averageFinderPatternBlocksize && + Math.abs(scans[3] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + Math.abs(scans[4] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize && + !v; // And make sure the current pixel is white since finder patterns are bordered in white + // Do the last 3 color changes ~ match the expected ratio for an alignment pattern? 1:1:1 of w:b:w + var averageAlignmentPatternBlocksize = sum(scans.slice(-3)) / 3; + var validAlignmentPattern = Math.abs(scans[2] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + Math.abs(scans[3] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + Math.abs(scans[4] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize && + v; // Is the current pixel black since alignment patterns are bordered in black + if (validFinderPattern) { + // Compute the start and end x values of the large center black square + var endX_1 = x - scans[3] - scans[4]; + var startX_1 = endX_1 - scans[2]; + var line = { startX: startX_1, endX: endX_1, y: y }; + // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with + // that line as the starting point. + var matchingQuads = activeFinderPatternQuads.filter(function (q) { + return (startX_1 >= q.bottom.startX && startX_1 <= q.bottom.endX) || + (endX_1 >= q.bottom.startX && startX_1 <= q.bottom.endX) || + (startX_1 <= q.bottom.startX && endX_1 >= q.bottom.endX && ((scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO && + (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO)); + }); + if (matchingQuads.length > 0) { + matchingQuads[0].bottom = line; + } + else { + activeFinderPatternQuads.push({ top: line, bottom: line }); + } + } + if (validAlignmentPattern) { + // Compute the start and end x values of the center black square + var endX_2 = x - scans[4]; + var startX_2 = endX_2 - scans[3]; + var line = { startX: startX_2, y: y, endX: endX_2 }; + // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with + // that line as the starting point. + var matchingQuads = activeAlignmentPatternQuads.filter(function (q) { + return (startX_2 >= q.bottom.startX && startX_2 <= q.bottom.endX) || + (endX_2 >= q.bottom.startX && startX_2 <= q.bottom.endX) || + (startX_2 <= q.bottom.startX && endX_2 >= q.bottom.endX && ((scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO && + (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO)); + }); + if (matchingQuads.length > 0) { + matchingQuads[0].bottom = line; + } + else { + activeAlignmentPatternQuads.push({ top: line, bottom: line }); + } + } + } + }; + for (var x = -1; x <= matrix.width; x++) { + _loop_2(x); + } + finderPatternQuads.push.apply(finderPatternQuads, activeFinderPatternQuads.filter(function (q) { return q.bottom.y !== y && q.bottom.y - q.top.y >= 2; })); + activeFinderPatternQuads = activeFinderPatternQuads.filter(function (q) { return q.bottom.y === y; }); + alignmentPatternQuads.push.apply(alignmentPatternQuads, activeAlignmentPatternQuads.filter(function (q) { return q.bottom.y !== y; })); + activeAlignmentPatternQuads = activeAlignmentPatternQuads.filter(function (q) { return q.bottom.y === y; }); + }; + for (var y = 0; y <= matrix.height; y++) { + _loop_1(y); + } + finderPatternQuads.push.apply(finderPatternQuads, activeFinderPatternQuads.filter(function (q) { return q.bottom.y - q.top.y >= 2; })); + alignmentPatternQuads.push.apply(alignmentPatternQuads, activeAlignmentPatternQuads); + var finderPatternGroups = finderPatternQuads + .filter(function (q) { return q.bottom.y - q.top.y >= 2; }) // All quads must be at least 2px tall since the center square is larger than a block + .map(function (q) { + var x = (q.top.startX + q.top.endX + q.bottom.startX + q.bottom.endX) / 4; + var y = (q.top.y + q.bottom.y + 1) / 2; + if (!matrix.get(Math.round(x), Math.round(y))) { + return; + } + var lengths = [q.top.endX - q.top.startX, q.bottom.endX - q.bottom.startX, q.bottom.y - q.top.y + 1]; + var size = sum(lengths) / lengths.length; + var score = scorePattern({ x: Math.round(x), y: Math.round(y) }, [1, 1, 3, 1, 1], matrix); + return { score: score, x: x, y: y, size: size }; + }) + .filter(function (q) { return !!q; }) // Filter out any rejected quads from above + .sort(function (a, b) { return a.score - b.score; }) + // Now take the top finder pattern options and try to find 2 other options with a similar size. + .map(function (point, i, finderPatterns) { + if (i > MAX_FINDERPATTERNS_TO_SEARCH) { + return null; + } + var otherPoints = finderPatterns + .filter(function (p, ii) { return i !== ii; }) + .map(function (p) { return ({ x: p.x, y: p.y, score: p.score + (Math.pow((p.size - point.size), 2)) / point.size, size: p.size }); }) + .sort(function (a, b) { return a.score - b.score; }); + if (otherPoints.length < 2) { + return null; + } + var score = point.score + otherPoints[0].score + otherPoints[1].score; + return { points: [point].concat(otherPoints.slice(0, 2)), score: score }; + }) + .filter(function (q) { return !!q; }) // Filter out any rejected finder patterns from above + .sort(function (a, b) { return a.score - b.score; }); + if (finderPatternGroups.length === 0) { + return null; + } + var _a = reorderFinderPatterns(finderPatternGroups[0].points[0], finderPatternGroups[0].points[1], finderPatternGroups[0].points[2]), topRight = _a.topRight, topLeft = _a.topLeft, bottomLeft = _a.bottomLeft; + var alignment = findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft); + var result = []; + if (alignment) { + result.push({ + alignmentPattern: { x: alignment.alignmentPattern.x, y: alignment.alignmentPattern.y }, + bottomLeft: { x: bottomLeft.x, y: bottomLeft.y }, + dimension: alignment.dimension, + topLeft: { x: topLeft.x, y: topLeft.y }, + topRight: { x: topRight.x, y: topRight.y }, + }); + } + // We normally use the center of the quads as the location of the tracking points, which is optimal for most cases and will account + // for a skew in the image. However, In some cases, a slight skew might not be real and instead be caused by image compression + // errors and/or low resolution. For those cases, we'd be better off centering the point exactly in the middle of the black area. We + // compute and return the location data for the naively centered points as it is little additional work and allows for multiple + // attempts at decoding harder images. + var midTopRight = recenterLocation(matrix, topRight); + var midTopLeft = recenterLocation(matrix, topLeft); + var midBottomLeft = recenterLocation(matrix, bottomLeft); + var centeredAlignment = findAlignmentPattern(matrix, alignmentPatternQuads, midTopRight, midTopLeft, midBottomLeft); + if (centeredAlignment) { + result.push({ + alignmentPattern: { x: centeredAlignment.alignmentPattern.x, y: centeredAlignment.alignmentPattern.y }, + bottomLeft: { x: midBottomLeft.x, y: midBottomLeft.y }, + topLeft: { x: midTopLeft.x, y: midTopLeft.y }, + topRight: { x: midTopRight.x, y: midTopRight.y }, + dimension: centeredAlignment.dimension, + }); + } + if (result.length === 0) { + return null; + } + return result; +} +exports.locate = locate; +function findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft) { + var _a; + // Now that we've found the three finder patterns we can determine the blockSize and the size of the QR code. + // We'll use these to help find the alignment pattern but also later when we do the extraction. + var dimension; + var moduleSize; + try { + (_a = computeDimension(topLeft, topRight, bottomLeft, matrix), dimension = _a.dimension, moduleSize = _a.moduleSize); + } + catch (e) { + return null; + } + // Now find the alignment pattern + var bottomRightFinderPattern = { + x: topRight.x - topLeft.x + bottomLeft.x, + y: topRight.y - topLeft.y + bottomLeft.y, + }; + var modulesBetweenFinderPatterns = ((distance(topLeft, bottomLeft) + distance(topLeft, topRight)) / 2 / moduleSize); + var correctionToTopLeft = 1 - (3 / modulesBetweenFinderPatterns); + var expectedAlignmentPattern = { + x: topLeft.x + correctionToTopLeft * (bottomRightFinderPattern.x - topLeft.x), + y: topLeft.y + correctionToTopLeft * (bottomRightFinderPattern.y - topLeft.y), + }; + var alignmentPatterns = alignmentPatternQuads + .map(function (q) { + var x = (q.top.startX + q.top.endX + q.bottom.startX + q.bottom.endX) / 4; + var y = (q.top.y + q.bottom.y + 1) / 2; + if (!matrix.get(Math.floor(x), Math.floor(y))) { + return; + } + var lengths = [q.top.endX - q.top.startX, q.bottom.endX - q.bottom.startX, (q.bottom.y - q.top.y + 1)]; + var size = sum(lengths) / lengths.length; + var sizeScore = scorePattern({ x: Math.floor(x), y: Math.floor(y) }, [1, 1, 1], matrix); + var score = sizeScore + distance({ x: x, y: y }, expectedAlignmentPattern); + return { x: x, y: y, score: score }; + }) + .filter(function (v) { return !!v; }) + .sort(function (a, b) { return a.score - b.score; }); + // If there are less than 15 modules between finder patterns it's a version 1 QR code and as such has no alignmemnt pattern + // so we can only use our best guess. + var alignmentPattern = modulesBetweenFinderPatterns >= 15 && alignmentPatterns.length ? alignmentPatterns[0] : expectedAlignmentPattern; + return { alignmentPattern: alignmentPattern, dimension: dimension }; +} + + +/***/ }) +/******/ ])["default"]; +}); +},{}],375:[function(require,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; + +},{}],376:[function(require,module,exports){ +(function (global){ +/** + * @license + * Lodash + * Copyright OpenJS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ +;(function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used as the semantic version number. */ + var VERSION = '4.17.21'; + + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + + /** Error message constants. */ + var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', + FUNC_ERROR_TEXT = 'Expected a function', + INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; + + /** Used to compose bitmasks for cloning. */ + var CLONE_DEEP_FLAG = 1, + CLONE_FLAT_FLAG = 2, + CLONE_SYMBOLS_FLAG = 4; + + /** Used to compose bitmasks for value comparisons. */ + var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_BOUND_FLAG = 4, + WRAP_CURRY_FLAG = 8, + WRAP_CURRY_RIGHT_FLAG = 16, + WRAP_PARTIAL_FLAG = 32, + WRAP_PARTIAL_RIGHT_FLAG = 64, + WRAP_ARY_FLAG = 128, + WRAP_REARG_FLAG = 256, + WRAP_FLIP_FLAG = 512; + + /** Used as default options for `_.truncate`. */ + var DEFAULT_TRUNC_LENGTH = 30, + DEFAULT_TRUNC_OMISSION = '...'; + + /** Used to detect hot functions by number of calls within a span of milliseconds. */ + var HOT_COUNT = 800, + HOT_SPAN = 16; + + /** Used to indicate the type of lazy iteratees. */ + var LAZY_FILTER_FLAG = 1, + LAZY_MAP_FLAG = 2, + LAZY_WHILE_FLAG = 3; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991, + MAX_INTEGER = 1.7976931348623157e+308, + NAN = 0 / 0; + + /** Used as references for the maximum length and index of an array. */ + var MAX_ARRAY_LENGTH = 4294967295, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + + /** Used to associate wrap methods with their bit flags. */ + var wrapFlags = [ + ['ary', WRAP_ARY_FLAG], + ['bind', WRAP_BIND_FLAG], + ['bindKey', WRAP_BIND_KEY_FLAG], + ['curry', WRAP_CURRY_FLAG], + ['curryRight', WRAP_CURRY_RIGHT_FLAG], + ['flip', WRAP_FLIP_FLAG], + ['partial', WRAP_PARTIAL_FLAG], + ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], + ['rearg', WRAP_REARG_FLAG] + ]; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + asyncTag = '[object AsyncFunction]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + domExcTag = '[object DOMException]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + nullTag = '[object Null]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + proxyTag = '[object Proxy]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + undefinedTag = '[object Undefined]', + weakMapTag = '[object WeakMap]', + weakSetTag = '[object WeakSet]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to match empty string literals in compiled template source. */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match HTML entities and HTML characters. */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g, + reHasEscapedHtml = RegExp(reEscapedHtml.source), + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to match template delimiters. */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to match property names within property paths. */ + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, + reHasRegExpChar = RegExp(reRegExpChar.source); + + /** Used to match leading whitespace. */ + var reTrimStart = /^\s+/; + + /** Used to match a single whitespace character. */ + var reWhitespace = /\s/; + + /** Used to match wrap detail comments. */ + var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, + reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, + reSplitDetails = /,? & /; + + /** Used to match words composed of alphanumeric characters. */ + var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + + /** + * Used to validate the `validate` option in `_.template` variable. + * + * Forbids characters which could potentially change the meaning of the function argument definition: + * - "()," (modification of function parameters) + * - "=" (default value) + * - "[]{}" (destructuring of function parameters) + * - "/" (beginning of a comment) + * - whitespace + */ + var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/; + + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + + /** + * Used to match + * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). + */ + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + + /** Used to match `RegExp` flags from their coerced string values. */ + var reFlags = /\w*$/; + + /** Used to detect bad signed hexadecimal string values. */ + var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + + /** Used to detect binary string values. */ + var reIsBinary = /^0b[01]+$/i; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Used to detect octal string values. */ + var reIsOctal = /^0o[0-7]+$/i; + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to match Latin Unicode letters (excluding mathematical operators). */ + var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + + /** Used to ensure capturing order of template delimiters. */ + var reNoMatch = /($^)/; + + /** Used to match unescaped characters in compiled string literals. */ + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + + /** Used to compose unicode character classes. */ + var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsDingbatRange = '\\u2700-\\u27bf', + rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', + rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', + rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', + rsPunctuationRange = '\\u2000-\\u206f', + rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + rsVarRange = '\\ufe0e\\ufe0f', + rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + + /** Used to compose unicode capture groups. */ + var rsApos = "['\u2019]", + rsAstral = '[' + rsAstralRange + ']', + rsBreak = '[' + rsBreakRange + ']', + rsCombo = '[' + rsComboRange + ']', + rsDigits = '\\d+', + rsDingbat = '[' + rsDingbatRange + ']', + rsLower = '[' + rsLowerRange + ']', + rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsUpper = '[' + rsUpperRange + ']', + rsZWJ = '\\u200d'; + + /** Used to compose unicode regexes. */ + var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')', + rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')', + rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', + rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', + reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])', + rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + + /** Used to match apostrophes. */ + var reApos = RegExp(rsApos, 'g'); + + /** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and + * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). + */ + var reComboMark = RegExp(rsCombo, 'g'); + + /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ + var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + + /** Used to match complex or compound words. */ + var reUnicodeWord = RegExp([ + rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', + rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, + rsUpper + '+' + rsOptContrUpper, + rsOrdUpper, + rsOrdLower, + rsDigits, + rsEmoji + ].join('|'), 'g'); + + /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ + var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + + /** Used to detect strings that need a more robust regexp to match words. */ + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + + /** Used to assign default `context` object properties. */ + var contextProps = [ + 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', + 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' + ]; + + /** Used to make template sourceURLs easier to identify. */ + var templateCounter = -1; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; + + /** Used to identify `toStringTag` values supported by `_.clone`. */ + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = + cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = + cloneableTags[boolTag] = cloneableTags[dateTag] = + cloneableTags[float32Tag] = cloneableTags[float64Tag] = + cloneableTags[int8Tag] = cloneableTags[int16Tag] = + cloneableTags[int32Tag] = cloneableTags[mapTag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[setTag] = + cloneableTags[stringTag] = cloneableTags[symbolTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = + cloneableTags[weakMapTag] = false; + + /** Used to map Latin Unicode letters to basic Latin letters. */ + var deburredLetters = { + // Latin-1 Supplement block. + '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', + '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', + '\xc7': 'C', '\xe7': 'c', + '\xd0': 'D', '\xf0': 'd', + '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', + '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xd1': 'N', '\xf1': 'n', + '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', + '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', + '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', + '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', + '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', + '\xc6': 'Ae', '\xe6': 'ae', + '\xde': 'Th', '\xfe': 'th', + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 's' + }; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to map HTML entities to characters. */ + var htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'" + }; + + /** Used to escape characters for inclusion in compiled string literals. */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /** Built-in method references without a dependency on `root`. */ + var freeParseFloat = parseFloat, + freeParseInt = parseInt; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; + + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule && freeModule.require && freeModule.require('util').types; + + if (types) { + return types; + } + + // Legacy `process.binding('util')` for Node.js < 10. + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} + }()); + + /* Node.js helper references. */ + var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, + nodeIsDate = nodeUtil && nodeUtil.isDate, + nodeIsMap = nodeUtil && nodeUtil.isMap, + nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, + nodeIsSet = nodeUtil && nodeUtil.isSet, + nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + + /*--------------------------------------------------------------------------*/ + + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + + /** + * A specialized version of `baseAggregator` for arrays. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function arrayAggregator(array, setter, iteratee, accumulator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + var value = array[index]; + setter(accumulator, value, iteratee(value), array); + } + return accumulator; + } + + /** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEach(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.forEachRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEachRight(array, iteratee) { + var length = array == null ? 0 : array.length; + + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.every` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ + function arrayEvery(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + + /** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludes(array, value) { + var length = array == null ? 0 : array.length; + return !!length && baseIndexOf(array, value, 0) > -1; + } + + /** + * This function is like `arrayIncludes` except that it accepts a comparator. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; + } + + /** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + + /** + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, + length = array == null ? 0 : array.length; + + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + + /** + * A specialized version of `_.reduceRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the last element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduceRight(array, iteratee, accumulator, initAccum) { + var length = array == null ? 0 : array.length; + if (initAccum && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + + /** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + + /** + * Gets the size of an ASCII `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + var asciiSize = baseProperty('length'); + + /** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function asciiToArray(string) { + return string.split(''); + } + + /** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function asciiWords(string) { + return string.match(reAsciiWord) || []; + } + + /** + * The base implementation of methods like `_.findKey` and `_.findLastKey`, + * without support for iteratee shorthands, which iterates over `collection` + * using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFindKey(collection, predicate, eachFunc) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = key; + return false; + } + }); + return result; + } + + /** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOf(array, value, fromIndex) { + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); + } + + /** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ + function baseIsNaN(value) { + return value !== value; + } + + /** + * The base implementation of `_.mean` and `_.meanBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the mean. + */ + function baseMean(array, iteratee) { + var length = array == null ? 0 : array.length; + return length ? (baseSum(array, iteratee) / length) : NAN; + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.sortBy` which uses `comparer` to define the + * sort order of `array` and replaces criteria objects with their corresponding + * values. + * + * @private + * @param {Array} array The array to sort. + * @param {Function} comparer The function to define sort order. + * @returns {Array} Returns `array`. + */ + function baseSortBy(array, comparer) { + var length = array.length; + + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + + /** + * The base implementation of `_.sum` and `_.sumBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the sum. + */ + function baseSum(array, iteratee) { + var result, + index = -1, + length = array.length; + + while (++index < length) { + var current = iteratee(array[index]); + if (current !== undefined) { + result = result === undefined ? current : (result + current); + } + } + return result; + } + + /** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ + function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } + + /** + * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array + * of key-value pairs for `object` corresponding to the property names of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the key-value pairs. + */ + function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); + } + + /** + * The base implementation of `_.trim`. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ + function baseTrim(string) { + return string + ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') + : string; + } + + /** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ + function baseUnary(func) { + return function(value) { + return func(value); + }; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + return arrayMap(props, function(key) { + return object[key]; + }); + } + + /** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function cacheHas(cache, key) { + return cache.has(key); + } + + /** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ + function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ + function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Gets the number of `placeholder` occurrences in `array`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} placeholder The placeholder to search for. + * @returns {number} Returns the placeholder count. + */ + function countHolders(array, placeholder) { + var length = array.length, + result = 0; + + while (length--) { + if (array[length] === placeholder) { + ++result; + } + } + return result; + } + + /** + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. + * + * @private + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. + */ + var deburrLetter = basePropertyOf(deburredLetters); + + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + var escapeHtmlChar = basePropertyOf(htmlEscapes); + + /** + * Used by `_.template` to escape characters for inclusion in compiled string literals. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; + } + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + /** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ + function hasUnicode(string) { + return reHasUnicode.test(string); + } + + /** + * Checks if `string` contains a word composed of Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. + */ + function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); + } + + /** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ + function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; + } + + /** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ + function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + /** + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. + * + * @private + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. + */ + function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value === placeholder || value === PLACEHOLDER) { + array[index] = PLACEHOLDER; + result[resIndex++] = index; + } + } + return result; + } + + /** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ + function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; + } + + /** + * Converts `set` to its value-value pairs. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the value-value pairs. + */ + function setToPairs(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; + } + + /** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + + /** + * Gets the number of symbols in `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the string size. + */ + function stringSize(string) { + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); + } + + /** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function stringToArray(string) { + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); + } + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedEndIndex(string) { + var index = string.length; + + while (index-- && reWhitespace.test(string.charAt(index))) {} + return index; + } + + /** + * Used by `_.unescape` to convert HTML entities to characters. + * + * @private + * @param {string} chr The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ + var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + + /** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + ++result; + } + return result; + } + + /** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function unicodeToArray(string) { + return string.match(reUnicode) || []; + } + + /** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function unicodeWords(string) { + return string.match(reUnicodeWord) || []; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Create a new pristine `lodash` function using the `context` object. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Util + * @param {Object} [context=root] The context object. + * @returns {Function} Returns a new `lodash` function. + * @example + * + * _.mixin({ 'foo': _.constant('foo') }); + * + * var lodash = _.runInContext(); + * lodash.mixin({ 'bar': lodash.constant('bar') }); + * + * _.isFunction(_.foo); + * // => true + * _.isFunction(_.bar); + * // => false + * + * lodash.isFunction(lodash.foo); + * // => false + * lodash.isFunction(lodash.bar); + * // => true + * + * // Create a suped-up `defer` in Node.js. + * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; + */ + var runInContext = (function runInContext(context) { + context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps)); + + /** Built-in constructor references. */ + var Array = context.Array, + Date = context.Date, + Error = context.Error, + Function = context.Function, + Math = context.Math, + Object = context.Object, + RegExp = context.RegExp, + String = context.String, + TypeError = context.TypeError; + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to detect overreaching core-js shims. */ + var coreJsData = context['__core-js_shared__']; + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString = objectProto.toString; + + /** Used to infer the `Object` constructor. */ + var objectCtorString = funcToString.call(Object); + + /** Used to restore the original `_` reference in `_.noConflict`. */ + var oldDash = root._; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** Built-in value references. */ + var Buffer = moduleExports ? context.Buffer : undefined, + Symbol = context.Symbol, + Uint8Array = context.Uint8Array, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, + getPrototype = overArg(Object.getPrototypeOf, Object), + objectCreate = Object.create, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, + symIterator = Symbol ? Symbol.iterator : undefined, + symToStringTag = Symbol ? Symbol.toStringTag : undefined; + + var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} + }()); + + /** Mocked built-ins. */ + var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, + ctxNow = Date && Date.now !== root.Date.now && Date.now, + ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeCeil = Math.ceil, + nativeFloor = Math.floor, + nativeGetSymbols = Object.getOwnPropertySymbols, + nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, + nativeIsFinite = context.isFinite, + nativeJoin = arrayProto.join, + nativeKeys = overArg(Object.keys, Object), + nativeMax = Math.max, + nativeMin = Math.min, + nativeNow = Date.now, + nativeParseInt = context.parseInt, + nativeRandom = Math.random, + nativeReverse = arrayProto.reverse; + + /* Built-in method references that are verified to be native. */ + var DataView = getNative(context, 'DataView'), + Map = getNative(context, 'Map'), + Promise = getNative(context, 'Promise'), + Set = getNative(context, 'Set'), + WeakMap = getNative(context, 'WeakMap'), + nativeCreate = getNative(Object, 'create'); + + /** Used to store function metadata. */ + var metaMap = WeakMap && new WeakMap; + + /** Used to lookup unminified function names. */ + var realNames = {}; + + /** Used to detect maps, sets, and weakmaps. */ + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. + * + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array and iteratees accept only + * one argument. The heuristic for whether a section qualifies for shortcut + * fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, + * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, + * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // Returns an unwrapped value. + * wrapped.reduce(_.add); + * // => 6 + * + * // Returns a wrapped value. + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + /** + * The function whose prototype chain sequence wrappers inherit from. + * + * @private + */ + function baseLodash() { + // No operation performed. + } + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined; + } + + /** + * By default, the template delimiters used by lodash are like those in + * embedded Ruby (ERB) as well as ES2015 template strings. Change the + * following template settings to use alternative delimiters. + * + * @static + * @memberOf _ + * @type {Object} + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'escape': reEscape, + + /** + * Used to detect code to be evaluated. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'evaluate': reEvaluate, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @memberOf _.templateSettings + * @type {string} + */ + 'variable': '', + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type {Object} + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type {Function} + */ + '_': lodash + } + }; + + // Ensure wrappers are instances of `baseLodash`. + lodash.prototype = baseLodash.prototype; + lodash.prototype.constructor = lodash; + + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. + * + * @private + * @constructor + * @param {*} value The value to wrap. + */ + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = MAX_ARRAY_LENGTH; + this.__views__ = []; + } + + /** + * Creates a clone of the lazy wrapper object. + * + * @private + * @name clone + * @memberOf LazyWrapper + * @returns {Object} Returns the cloned `LazyWrapper` object. + */ + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = copyArray(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = copyArray(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = copyArray(this.__views__); + return result; + } + + /** + * Reverses the direction of lazy iteration. + * + * @private + * @name reverse + * @memberOf LazyWrapper + * @returns {Object} Returns the new reversed `LazyWrapper` object. + */ + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + + /** + * Extracts the unwrapped value from its lazy wrapper. + * + * @private + * @name value + * @memberOf LazyWrapper + * @returns {*} Returns the unwrapped value. + */ + function lazyValue() { + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), + isRight = dir < 0, + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), + start = view.start, + end = view.end, + length = end - start, + index = isRight ? end : (start - 1), + iteratees = this.__iteratees__, + iterLength = iteratees.length, + resIndex = 0, + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || (!isRight && arrLength == length && takeCount == length)) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + + outer: + while (length-- && resIndex < takeCount) { + index += dir; + + var iterIndex = -1, + value = array[index]; + + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], + iteratee = data.iteratee, + type = data.type, + computed = iteratee(value); + + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + + // Ensure `LazyWrapper` is an instance of `baseLodash`. + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); + } + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; + } + + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ + function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } + } + + /** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; + } + + /** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ + function setCacheHas(value) { + return this.__data__.has(value); + } + + // Add methods to `SetCache`. + SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; + SetCache.prototype.has = setCacheHas; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } + + /** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ + function stackClear() { + this.__data__ = new ListCache; + this.size = 0; + } + + /** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; + } + + /** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function stackGet(key) { + return this.__data__.get(key); + } + + /** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function stackHas(key) { + return this.__data__.has(key); + } + + /** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } + + // Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; + } + + /** + * A specialized version of `_.sample` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. + */ + function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined; + } + + /** + * A specialized version of `_.sampleSize` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function arraySampleSize(array, n) { + return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); + } + + /** + * A specialized version of `_.shuffle` for arrays. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); + } + + /** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + /** + * Aggregates elements of `collection` on `accumulator` with keys transformed + * by `iteratee` and values set by `setter`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function baseAggregator(collection, setter, iteratee, accumulator) { + baseEach(collection, function(value, key, collection) { + setter(accumulator, value, iteratee(value), collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); + } + + /** + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); + } + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + + /** + * The base implementation of `_.at` without support for individual paths. + * + * @private + * @param {Object} object The object to iterate over. + * @param {string[]} paths The property paths to pick. + * @returns {Array} Returns the picked elements. + */ + function baseAt(object, paths) { + var index = -1, + length = paths.length, + result = Array(length), + skip = object == null; + + while (++index < length) { + result[index] = skip ? undefined : get(object, paths[index]); + } + return result; + } + + /** + * The base implementation of `_.clamp` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + */ + function baseClamp(number, lower, upper) { + if (number === number) { + if (upper !== undefined) { + number = number <= upper ? number : upper; + } + if (lower !== undefined) { + number = number >= lower ? number : lower; + } + } + return number; + } + + /** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ + function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG; + + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = (isFlat || isFunc) ? {} : initCloneObject(value); + if (!isDeep) { + return isFlat + ? copySymbolsIn(value, baseAssignIn(result, value)) + : copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + if (isSet(value)) { + value.forEach(function(subValue) { + result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); + }); + } else if (isMap(value)) { + value.forEach(function(subValue, key) { + result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + } + + var keysFunc = isFull + ? (isFlat ? getAllKeysIn : getAllKeys) + : (isFlat ? keysIn : keys); + + var props = isArr ? undefined : keysFunc(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + return result; + } + + /** + * The base implementation of `_.conforms` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new spec function. + */ + function baseConforms(source) { + var props = keys(source); + return function(object) { + return baseConformsTo(object, source, props); + }; + } + + /** + * The base implementation of `_.conformsTo` which accepts `props` to check. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + */ + function baseConformsTo(object, source, props) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length], + predicate = source[key], + value = object[key]; + + if ((value === undefined && !(key in object)) || !predicate(value)) { + return false; + } + } + return true; + } + + /** + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. + */ + function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * The base implementation of methods like `_.difference` without support + * for excluding multiple arrays or iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + */ + function baseDifference(array, values, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + isCommon = true, + length = array.length, + result = [], + valuesLength = values.length; + + if (!length) { + return result; + } + if (iteratee) { + values = arrayMap(values, baseUnary(iteratee)); + } + if (comparator) { + includes = arrayIncludesWith; + isCommon = false; + } + else if (values.length >= LARGE_ARRAY_SIZE) { + includes = cacheHas; + isCommon = false; + values = new SetCache(values); + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee == null ? value : iteratee(value); + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === computed) { + continue outer; + } + } + result.push(value); + } + else if (!includes(values, computed, comparator)) { + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEach = createBaseEach(baseForOwn); + + /** + * The base implementation of `_.forEachRight` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEachRight = createBaseEach(baseForOwnRight, true); + + /** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !isSymbol(current)) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; + } + + /** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function baseFill(array, value, start, end) { + var length = array.length; + + start = toInteger(start); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (end === undefined || end > length) ? length : toInteger(end); + if (end < 0) { + end += length; + } + end = start > end ? 0 : toLength(end); + while (start < end) { + array[start++] = value; + } + return array; + } + + /** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + /** + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseForRight = createBaseFor(true); + + /** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.forOwnRight` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwnRight(object, iteratee) { + return object && baseForRight(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from `props`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the function names. + */ + function baseFunctions(object, props) { + return arrayFilter(props, function(key) { + return isFunction(object[key]); + }); + } + + /** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ + function baseGet(object, path) { + path = castPath(path, object); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; + } + + /** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); + } + + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); + } + + /** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ + function baseGt(value, other) { + return value > other; + } + + /** + * The base implementation of `_.has` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHas(object, key) { + return object != null && hasOwnProperty.call(object, key); + } + + /** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHasIn(object, key) { + return object != null && key in Object(object); + } + + /** + * The base implementation of `_.inRange` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to check. + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ + function baseInRange(number, start, end) { + return number >= nativeMin(start, end) && number < nativeMax(start, end); + } + + /** + * The base implementation of methods like `_.intersection`, without support + * for iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + */ + function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith : arrayIncludes, + length = arrays[0].length, + othLength = arrays.length, + othIndex = othLength, + caches = Array(othLength), + maxLength = Infinity, + result = []; + + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee) { + array = arrayMap(array, baseUnary(iteratee)); + } + maxLength = nativeMin(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) + ? new SetCache(othIndex && array) + : undefined; + } + array = arrays[0]; + + var index = -1, + seen = caches[0]; + + outer: + while (++index < length && result.length < maxLength) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (!(seen + ? cacheHas(seen, computed) + : includes(result, computed, comparator) + )) { + othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache + ? cacheHas(cache, computed) + : includes(arrays[othIndex], computed, comparator)) + ) { + continue outer; + } + } + if (seen) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.invert` and `_.invertBy` which inverts + * `object` with values transformed by `iteratee` and set by `setter`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform values. + * @param {Object} accumulator The initial inverted object. + * @returns {Function} Returns `accumulator`. + */ + function baseInverter(object, setter, iteratee, accumulator) { + baseForOwn(object, function(value, key, object) { + setter(accumulator, iteratee(value), key, object); + }); + return accumulator; + } + + /** + * The base implementation of `_.invoke` without support for individual + * method arguments. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {Array} args The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + */ + function baseInvoke(object, path, args) { + path = castPath(path, object); + object = parent(object, path); + var func = object == null ? object : object[toKey(last(path))]; + return func == null ? undefined : apply(func, object, args); + } + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; + } + + /** + * The base implementation of `_.isArrayBuffer` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + */ + function baseIsArrayBuffer(value) { + return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; + } + + /** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ + function baseIsDate(value) { + return isObjectLike(value) && baseGetTag(value) == dateTag; + } + + /** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); + } + + /** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ + function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; + } + + /** + * The base implementation of `_.isMatch` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ + function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; + + if (object == null) { + return !length; + } + object = Object(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; + + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) + : result + )) { + return false; + } + } + } + return true; + } + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + /** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ + function baseIsRegExp(value) { + return isObjectLike(value) && baseGetTag(value) == regexpTag; + } + + /** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ + function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; + } + + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; + } + + /** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ + function baseIteratee(value) { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); + } + + /** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ + function baseLt(value, other) { + return value < other; + } + + /** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + + /** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); + } + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; + } + + /** + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); + }; + } + + /** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + stack || (stack = new Stack); + if (isObject(srcValue)) { + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); + } + + /** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = safeGet(object, key), + srcValue = safeGet(source, key), + stacked = stack.get(srcValue); + + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || isFunction(objValue)) { + newValue = initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue(object, key, newValue); + } + + /** + * The base implementation of `_.nth` which doesn't coerce arguments. + * + * @private + * @param {Array} array The array to query. + * @param {number} n The index of the element to return. + * @returns {*} Returns the nth element of `array`. + */ + function baseNth(array, n) { + var length = array.length; + if (!length) { + return; + } + n += n < 0 ? length : 0; + return isIndex(n, length) ? array[n] : undefined; + } + + /** + * The base implementation of `_.orderBy` without param guards. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. + * @param {string[]} orders The sort orders of `iteratees`. + * @returns {Array} Returns the new sorted array. + */ + function baseOrderBy(collection, iteratees, orders) { + if (iteratees.length) { + iteratees = arrayMap(iteratees, function(iteratee) { + if (isArray(iteratee)) { + return function(value) { + return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee); + } + } + return iteratee; + }); + } else { + iteratees = [identity]; + } + + var index = -1; + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + + var result = baseMap(collection, function(value, key, collection) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { 'criteria': criteria, 'index': ++index, 'value': value }; + }); + + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + + /** + * The base implementation of `_.pick` without support for individual + * property identifiers. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @returns {Object} Returns the new object. + */ + function basePick(object, paths) { + return basePickBy(object, paths, function(value, path) { + return hasIn(object, path); + }); + } + + /** + * The base implementation of `_.pickBy` without support for iteratee shorthands. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @param {Function} predicate The function invoked per property. + * @returns {Object} Returns the new object. + */ + function basePickBy(object, paths, predicate) { + var index = -1, + length = paths.length, + result = {}; + + while (++index < length) { + var path = paths[index], + value = baseGet(object, path); + + if (predicate(value, path)) { + baseSet(result, castPath(path, object), value); + } + } + return result; + } + + /** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; + } + + /** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + */ + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, + length = values.length, + seen = array; + + if (array === values) { + values = copyArray(values); + } + if (iteratee) { + seen = arrayMap(array, baseUnary(iteratee)); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; + + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice.call(seen, fromIndex, 1); + } + splice.call(array, fromIndex, 1); + } + } + return array; + } + + /** + * The base implementation of `_.pullAt` without support for individual + * indexes or capturing the removed elements. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns `array`. + */ + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0, + lastIndex = length - 1; + + while (length--) { + var index = indexes[length]; + if (length == lastIndex || index !== previous) { + var previous = index; + if (isIndex(index)) { + splice.call(array, index, 1); + } else { + baseUnset(array, index); + } + } + } + return array; + } + + /** + * The base implementation of `_.random` without support for returning + * floating-point numbers. + * + * @private + * @param {number} lower The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the random number. + */ + function baseRandom(lower, upper) { + return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); + } + + /** + * The base implementation of `_.range` and `_.rangeRight` which doesn't + * coerce arguments. + * + * @private + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @param {number} step The value to increment or decrement by. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the range of numbers. + */ + function baseRange(start, end, step, fromRight) { + var index = -1, + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), + result = Array(length); + + while (length--) { + result[fromRight ? length : ++index] = start; + start += step; + } + return result; + } + + /** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ + function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; + } + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + /** + * The base implementation of `_.sample`. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + */ + function baseSample(collection) { + return arraySample(values(collection)); + } + + /** + * The base implementation of `_.sampleSize` without param guards. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function baseSampleSize(collection, n) { + var array = values(collection); + return shuffleSelf(array, baseClamp(n, 0, array.length)); + } + + /** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = castPath(path, object); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = toKey(path[index]), + newValue = value; + + if (key === '__proto__' || key === 'constructor' || key === 'prototype') { + return object; + } + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; + } + + /** + * The base implementation of `setData` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + /** + * The base implementation of `_.shuffle`. + * + * @private + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function baseShuffle(collection) { + return shuffleSelf(values(collection)); + } + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which + * performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndex(array, value, retHighest) { + var low = 0, + high = array == null ? low : array.length; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if (computed !== null && !isSymbol(computed) && + (retHighest ? (computed <= value) : (computed < value))) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return baseSortedIndexBy(array, value, identity, retHighest); + } + + /** + * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` + * which invokes `iteratee` for `value` and each element of `array` to compute + * their sort ranking. The iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The iteratee invoked per element. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndexBy(array, value, iteratee, retHighest) { + var low = 0, + high = array == null ? 0 : array.length; + if (high === 0) { + return 0; + } + + value = iteratee(value); + var valIsNaN = value !== value, + valIsNull = value === null, + valIsSymbol = isSymbol(value), + valIsUndefined = value === undefined; + + while (low < high) { + var mid = nativeFloor((low + high) / 2), + computed = iteratee(array[mid]), + othIsDefined = computed !== undefined, + othIsNull = computed === null, + othIsReflexive = computed === computed, + othIsSymbol = isSymbol(computed); + + if (valIsNaN) { + var setLow = retHighest || othIsReflexive; + } else if (valIsUndefined) { + setLow = othIsReflexive && (retHighest || othIsDefined); + } else if (valIsNull) { + setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); + } else if (valIsSymbol) { + setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); + } else if (othIsNull || othIsSymbol) { + setLow = false; + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + + /** + * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseSortedUniq(array, iteratee) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + if (!index || !eq(computed, seen)) { + var seen = computed; + result[resIndex++] = value === 0 ? 0 : value; + } + } + return result; + } + + /** + * The base implementation of `_.toNumber` which doesn't ensure correct + * conversions of binary, hexadecimal, or octal string values. + * + * @private + * @param {*} value The value to process. + * @returns {number} Returns the number. + */ + function baseToNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + return +value; + } + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * The base implementation of `_.uniqBy` without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseUniq(array, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + length = array.length, + isCommon = true, + result = [], + seen = result; + + if (comparator) { + isCommon = false; + includes = arrayIncludesWith; + } + else if (length >= LARGE_ARRAY_SIZE) { + var set = iteratee ? null : createSet(array); + if (set) { + return setToArray(set); + } + isCommon = false; + includes = cacheHas; + seen = new SetCache; + } + else { + seen = iteratee ? [] : result; + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } + else if (!includes(seen, computed, comparator)) { + if (seen !== result) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.unset`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The property path to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + */ + function baseUnset(object, path) { + path = castPath(path, object); + object = parent(object, path); + return object == null || delete object[toKey(last(path))]; + } + + /** + * The base implementation of `_.update`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to update. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseUpdate(object, path, updater, customizer) { + return baseSet(object, path, updater(baseGet(object, path)), customizer); + } + + /** + * The base implementation of methods like `_.dropWhile` and `_.takeWhile` + * without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to query. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [isDrop] Specify dropping elements instead of taking them. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the slice of `array`. + */ + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length) && + predicate(array[index], index, array)) {} + + return isDrop + ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) + : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + return arrayReduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); + } + + /** + * The base implementation of methods like `_.xor`, without support for + * iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of values. + */ + function baseXor(arrays, iteratee, comparator) { + var length = arrays.length; + if (length < 2) { + return length ? baseUniq(arrays[0]) : []; + } + var index = -1, + result = Array(length); + + while (++index < length) { + var array = arrays[index], + othIndex = -1; + + while (++othIndex < length) { + if (othIndex != index) { + result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator); + } + } + } + return baseUniq(baseFlatten(result, 1), iteratee, comparator); + } + + /** + * This base implementation of `_.zipObject` which assigns values using `assignFunc`. + * + * @private + * @param {Array} props The property identifiers. + * @param {Array} values The property values. + * @param {Function} assignFunc The function to assign values. + * @returns {Object} Returns the new object. + */ + function baseZipObject(props, values, assignFunc) { + var index = -1, + length = props.length, + valsLength = values.length, + result = {}; + + while (++index < length) { + var value = index < valsLength ? values[index] : undefined; + assignFunc(result, props[index], value); + } + return result; + } + + /** + * Casts `value` to an empty array if it's not an array like object. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array|Object} Returns the cast array-like object. + */ + function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; + } + + /** + * Casts `value` to `identity` if it's not a function. + * + * @private + * @param {*} value The value to inspect. + * @returns {Function} Returns cast function. + */ + function castFunction(value) { + return typeof value == 'function' ? value : identity; + } + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @param {Object} [object] The object to query keys on. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); + } + + /** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + var castRest = baseRest; + + /** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ + function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); + } + + /** + * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). + * + * @private + * @param {number|Object} id The timer id or timeout object of the timer to clear. + */ + var clearTimeout = ctxClearTimeout || function(id) { + return root.clearTimeout(id); + }; + + /** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; + } + + /** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; + } + + /** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ + function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); + } + + /** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ + function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; + } + + /** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ + function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; + } + + /** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = isSymbol(value); + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = isSymbol(other); + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; + } + + /** + * Used by `_.orderBy` to compare multiple properties of a value to another + * and stable sort them. + * + * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, + * specify an order of "desc" for descending or "asc" for ascending sort order + * of corresponding values. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {boolean[]|string[]} orders The order to sort by for each property. + * @returns {number} Returns the sort order indicator for `object`. + */ + function compareMultiple(object, other, orders) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length, + ordersLength = orders.length; + + while (++index < length) { + var result = compareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order == 'desc' ? -1 : 1); + } + } + // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. + // + // This also ensures a stable sort in V8 and other engines. + // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; + } + + /** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgs(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersLength = holders.length, + leftIndex = -1, + leftLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(leftLength + rangeLength), + isUncurried = !isCurried; + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + } + while (rangeLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + + /** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgsRight(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersIndex = -1, + holdersLength = holders.length, + rightIndex = -1, + rightLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(rangeLength + rightLength), + isUncurried = !isCurried; + + while (++argsIndex < rangeLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + } + return result; + } + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + /** + * Copies own symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); + } + + /** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); + } + + /** + * Creates a function like `_.groupBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} [initializer] The accumulator object initializer. + * @returns {Function} Returns the new aggregator function. + */ + function createAggregator(setter, initializer) { + return function(collection, iteratee) { + var func = isArray(collection) ? arrayAggregator : baseAggregator, + accumulator = initializer ? initializer() : {}; + + return func(collection, setter, getIteratee(iteratee, 2), accumulator); + }; + } + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + /** + * Creates a function that wraps `func` to invoke it with the optional `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createBind(func, bitmask, thisArg) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; + } + + /** + * Creates a function like `_.lowerFirst`. + * + * @private + * @param {string} methodName The name of the `String` case method to use. + * @returns {Function} Returns the new case function. + */ + function createCaseFirst(methodName) { + return function(string) { + string = toString(string); + + var strSymbols = hasUnicode(string) + ? stringToArray(string) + : undefined; + + var chr = strSymbols + ? strSymbols[0] + : string.charAt(0); + + var trailing = strSymbols + ? castSlice(strSymbols, 1).join('') + : string.slice(1); + + return chr[methodName]() + trailing; + }; + } + + /** + * Creates a function like `_.camelCase`. + * + * @private + * @param {Function} callback The function to combine each word. + * @returns {Function} Returns the new compounder function. + */ + function createCompounder(callback) { + return function(string) { + return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + case 3: return new Ctor(args[0], args[1], args[2]); + case 4: return new Ctor(args[0], args[1], args[2], args[3]); + case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a function that wraps `func` to enable currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {number} arity The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length, + placeholder = getHolder(wrapper); + + while (index--) { + args[index] = arguments[index]; + } + var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) + ? [] + : replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, undefined, + args, holders, undefined, undefined, arity - length); + } + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return apply(fn, this, args); + } + return wrapper; + } + + /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = getIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; + } + + /** + * Creates a `_.flow` or `_.flowRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new flow function. + */ + function createFlow(fromRight) { + return flatRest(function(funcs) { + var length = funcs.length, + index = length, + prereq = LodashWrapper.prototype.thru; + + if (fromRight) { + funcs.reverse(); + } + while (index--) { + var func = funcs[index]; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (prereq && !wrapper && getFuncName(func) == 'wrapper') { + var wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? index : length; + while (++index < length) { + func = funcs[index]; + + var funcName = getFuncName(func), + data = funcName == 'wrapper' ? getData(func) : undefined; + + if (data && isLaziable(data[0]) && + data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && + !data[4].length && data[9] == 1 + ) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = (func.length == 1 && isLaziable(func)) + ? wrapper[funcName]() + : wrapper.thru(func); + } + } + return function() { + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && isArray(value)) { + return wrapper.plant(value).value(); + } + var index = 0, + result = length ? funcs[index].apply(this, args) : value; + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }); + } + + /** + * Creates a function that wraps `func` to invoke it with optional `this` + * binding of `thisArg`, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided + * to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & WRAP_ARY_FLAG, + isBind = bitmask & WRAP_BIND_FLAG, + isBindKey = bitmask & WRAP_BIND_KEY_FLAG, + isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), + isFlip = bitmask & WRAP_FLIP_FLAG, + Ctor = isBindKey ? undefined : createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length; + + while (index--) { + args[index] = arguments[index]; + } + if (isCurried) { + var placeholder = getHolder(wrapper), + holdersCount = countHolders(args, placeholder); + } + if (partials) { + args = composeArgs(args, partials, holders, isCurried); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight, isCurried); + } + length -= holdersCount; + if (isCurried && length < arity) { + var newHolders = replaceHolders(args, placeholder); + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, thisArg, + args, newHolders, argPos, ary, arity - length + ); + } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + + length = args.length; + if (argPos) { + args = reorder(args, argPos); + } else if (isFlip && length > 1) { + args.reverse(); + } + if (isAry && ary < length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtor(fn); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + + /** + * Creates a function like `_.invertBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} toIteratee The function to resolve iteratees. + * @returns {Function} Returns the new inverter function. + */ + function createInverter(setter, toIteratee) { + return function(object, iteratee) { + return baseInverter(object, setter, toIteratee(iteratee), {}); + }; + } + + /** + * Creates a function that performs a mathematical operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @param {number} [defaultValue] The value used for `undefined` arguments. + * @returns {Function} Returns the new mathematical operation function. + */ + function createMathOperation(operator, defaultValue) { + return function(value, other) { + var result; + if (value === undefined && other === undefined) { + return defaultValue; + } + if (value !== undefined) { + result = value; + } + if (other !== undefined) { + if (result === undefined) { + return other; + } + if (typeof value == 'string' || typeof other == 'string') { + value = baseToString(value); + other = baseToString(other); + } else { + value = baseToNumber(value); + other = baseToNumber(other); + } + result = operator(value, other); + } + return result; + }; + } + + /** + * Creates a function like `_.over`. + * + * @private + * @param {Function} arrayFunc The function to iterate over iteratees. + * @returns {Function} Returns the new over function. + */ + function createOver(arrayFunc) { + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + return baseRest(function(args) { + var thisArg = this; + return arrayFunc(iteratees, function(iteratee) { + return apply(iteratee, thisArg, args); + }); + }); + }); + } + + /** + * Creates the padding for `string` based on `length`. The `chars` string + * is truncated if the number of characters exceeds `length`. + * + * @private + * @param {number} length The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padding for `string`. + */ + function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); + + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; + } + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); + return hasUnicode(chars) + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); + } + + /** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ + function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return apply(fn, isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * Creates a `_.range` or `_.rangeRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new range function. + */ + function createRange(fromRight) { + return function(start, end, step) { + if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { + end = step = undefined; + } + // Ensure the sign of `-0` is preserved. + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); + return baseRange(start, end, step, fromRight); + }; + } + + /** + * Creates a function that performs a relational operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @returns {Function} Returns the new relational operation function. + */ + function createRelationalOperation(operator) { + return function(value, other) { + if (!(typeof value == 'string' && typeof other == 'string')) { + value = toNumber(value); + other = toNumber(other); + } + return operator(value, other); + }; + } + + /** + * Creates a function that wraps `func` to continue currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {Function} wrapFunc The function to create the `func` wrapper. + * @param {*} placeholder The placeholder value. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & WRAP_CURRY_FLAG, + newHolders = isCurry ? holders : undefined, + newHoldersRight = isCurry ? undefined : holders, + newPartials = isCurry ? partials : undefined, + newPartialsRight = isCurry ? undefined : partials; + + bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); + + if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { + bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); + } + var newData = [ + func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, + newHoldersRight, argPos, ary, arity + ]; + + var result = wrapFunc.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return setWrapToString(result, func, bitmask); + } + + /** + * Creates a function like `_.round`. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + number = toNumber(number); + precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); + if (precision && nativeIsFinite(number)) { + // Shift with exponential notation to avoid floating-point issues. + // See [MDN](https://mdn.io/round#Examples) for more details. + var pair = (toString(number) + 'e').split('e'), + value = func(pair[0] + 'e' + (+pair[1] + precision)); + + pair = (toString(value) + 'e').split('e'); + return +(pair[0] + 'e' + (+pair[1] - precision)); + } + return func(number); + }; + } + + /** + * Creates a set object of `values`. + * + * @private + * @param {Array} values The values to add to the set. + * @returns {Object} Returns the new set. + */ + var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { + return new Set(values); + }; + + /** + * Creates a `_.toPairs` or `_.toPairsIn` function. + * + * @private + * @param {Function} keysFunc The function to get the keys of a given object. + * @returns {Function} Returns the new pairs function. + */ + function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; + } + + /** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * 512 - `_.flip` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); + arity = arity === undefined ? arity : toInteger(arity); + length -= holders ? holders.length : 0; + + if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func); + + var newData = [ + func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, + argPos, ary, arity + ]; + + if (data) { + mergeData(newData, data); + } + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] === undefined + ? (isBindKey ? 0 : func.length) + : nativeMax(newData[9] - length, 0); + + if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { + bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); + } + if (!bitmask || bitmask == WRAP_BIND_FLAG) { + var result = createBind(func, bitmask, thisArg); + } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { + result = createCurry(func, bitmask, arity); + } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { + result = createPartial(func, bitmask, thisArg, partials); + } else { + result = createHybrid.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setWrapToString(setter(result, newData), func, bitmask); + } + + /** + * Used by `_.defaults` to customize its `_.assignIn` use to assign properties + * of source objects to the destination object for all destination properties + * that resolve to `undefined`. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ + function customDefaultsAssignIn(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; + } + + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source + * objects into destination objects that are passed thru. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to merge. + * @param {Object} object The parent object of `objValue`. + * @param {Object} source The parent object of `srcValue`. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + * @returns {*} Returns the value to assign. + */ + function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack); + stack['delete'](srcValue); + } + return objValue; + } + + /** + * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain + * objects. + * + * @private + * @param {*} value The value to inspect. + * @param {string} key The key of the property to inspect. + * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`. + */ + function customOmitClone(value) { + return isPlainObject(value) ? undefined : value; + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Check that cyclic values are equal. + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Check that cyclic values are equal. + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + /** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } + + /** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + + /** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ + function getFuncName(func) { + var result = (func.name + ''), + array = realNames[result], + length = hasOwnProperty.call(realNames, result) ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + + /** + * Gets the argument placeholder value for `func`. + * + * @private + * @param {Function} func The function to inspect. + * @returns {*} Returns the placeholder value. + */ + function getHolder(func) { + var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; + return object.placeholder; + } + + /** + * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, + * this function returns the custom method, otherwise it returns `baseIteratee`. + * If arguments are provided, the chosen function is invoked with them and + * its result is returned. + * + * @private + * @param {*} [value] The value to convert to an iteratee. + * @param {number} [arity] The arity of the created iteratee. + * @returns {Function} Returns the chosen function or its result. + */ + function getIteratee() { + var result = lodash.iteratee || iteratee; + result = result === iteratee ? baseIteratee : result; + return arguments.length ? result(arguments[0], arguments[1]) : result; + } + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + /** + * Gets the property names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ + function getMatchData(object) { + var result = keys(object), + length = result.length; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; + } + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + /** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; + } + + /** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); + }; + + /** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; + }; + + /** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + var getTag = baseGetTag; + + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; + } + + /** + * Gets the view, applying any `transforms` to the `start` and `end` positions. + * + * @private + * @param {number} start The start of the view. + * @param {number} end The end of the view. + * @param {Array} transforms The transformations to apply to the view. + * @returns {Object} Returns an object containing the `start` and `end` + * positions of the view. + */ + function getView(start, end, transforms) { + var index = -1, + length = transforms.length; + + while (++index < length) { + var data = transforms[index], + size = data.size; + + switch (data.type) { + case 'drop': start += size; break; + case 'dropRight': end -= size; break; + case 'take': end = nativeMin(end, start + size); break; + case 'takeRight': start = nativeMax(start, end - size); break; + } + } + return { 'start': start, 'end': end }; + } + + /** + * Extracts wrapper details from the `source` body comment. + * + * @private + * @param {string} source The source to inspect. + * @returns {Array} Returns the wrapper details. + */ + function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; + } + + /** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ + function hasPath(object, path, hasFunc) { + path = castPath(path, object); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); + } + + /** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ + function initCloneArray(array) { + var length = array.length, + result = new array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; + } + + /** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return new Ctor; + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return new Ctor; + + case symbolTag: + return cloneSymbol(object); + } + } + + /** + * Inserts wrapper `details` in a comment at the top of the `source` body. + * + * @private + * @param {string} source The source to modify. + * @returns {Array} details The details to insert. + * @returns {string} Returns the modified source. + */ + function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; + details = details.join(length > 2 ? ', ' : ' '); + return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); + } + + /** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ + function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); + } + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + /** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); + } + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + /** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, + * else `false`. + */ + function isLaziable(func) { + var funcName = getFuncName(func), + other = lodash[funcName]; + + if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + /** + * Checks if `func` is capable of being masked. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `func` is maskable, else `false`. + */ + var isMaskable = coreJsData ? isFunction : stubFalse; + + /** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ + function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; + } + + /** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ + function isStrictComparable(value) { + return value === value && !isObject(value); + } + + /** + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; + } + + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + + /** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers used to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and + * `_.rearg` modify function arguments, making the order in which they are + * executed important, preventing the merging of metadata. However, we make + * an exception for a safe combined case where curried functions have `_.ary` + * and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ + function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); + + var isCombo = + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) || + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) || + ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & WRAP_BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = value; + } + // Use source `ary` if it's smaller. + if (srcBitmask & WRAP_ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; + } + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + + /** + * Gets the parent value at `path` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} path The path to get the parent value of. + * @returns {*} Returns the parent value. + */ + function parent(object, path) { + return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); + } + + /** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ + function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = copyArray(array); + + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + + /** + * Gets the value at `key`, unless `key` is "__proto__" or "constructor". + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function safeGet(object, key) { + if (key === 'constructor' && typeof object[key] === 'function') { + return; + } + + if (key == '__proto__') { + return; + } + + return object[key]; + } + + /** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses in V8. See + * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var setData = shortOut(baseSetData); + + /** + * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @returns {number|Object} Returns the timer id or timeout object. + */ + var setTimeout = ctxSetTimeout || function(func, wait) { + return root.setTimeout(func, wait); + }; + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + /** + * Sets the `toString` method of `wrapper` to mimic the source of `reference` + * with wrapper details in a comment at the top of the source body. + * + * @private + * @param {Function} wrapper The function to modify. + * @param {Function} reference The reference function. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Function} Returns `wrapper`. + */ + function setWrapToString(wrapper, reference, bitmask) { + var source = (reference + ''); + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + /** + * A specialized version of `_.shuffle` which mutates and sets the size of `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @param {number} [size=array.length] The size of `array`. + * @returns {Array} Returns `array`. + */ + function shuffleSelf(array, size) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + size = size === undefined ? length : size; + while (++index < size) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + array.length = size; + return array; + } + + /** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ + var stringToPath = memoizeCapped(function(string) { + var result = []; + if (string.charCodeAt(0) === 46 /* . */) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, subString) { + result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; + }); + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + /** + * Updates wrapper `details` based on `bitmask` flags. + * + * @private + * @returns {Array} details The details to modify. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Array} Returns `details`. + */ + function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = '_.' + pair[0]; + if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); + } + + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + result.__index__ = wrapper.__index__; + result.__values__ = wrapper.__values__; + return result; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of elements split into groups the length of `size`. + * If `array` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to process. + * @param {number} [size=1] The length of each chunk + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the new array of chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, size, guard) { + if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { + size = 1; + } else { + size = nativeMax(toInteger(size), 0); + } + var length = array == null ? 0 : array.length; + if (!length || size < 1) { + return []; + } + var index = 0, + resIndex = 0, + result = Array(nativeCeil(length / size)); + + while (index < length) { + result[resIndex++] = baseSlice(array, index, (index += size)); + } + return result; + } + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } + + /** + * Creates an array of `array` values not included in the other given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * **Note:** Unlike `_.pullAll`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.without, _.xor + * @example + * + * _.difference([2, 1], [2, 3]); + * // => [1] + */ + var difference = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `iteratee` which + * is invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * **Note:** Unlike `_.pullAllBy`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2] + * + * // The `_.property` iteratee shorthand. + * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var differenceBy = baseRest(function(array, values) { + var iteratee = last(values); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `comparator` + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator + * is invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.pullAllWith`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * + * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); + * // => [{ 'x': 2, 'y': 1 }] + */ + var differenceWith = baseRest(function(array, values) { + var comparator = last(values); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) + : []; + }); + + /** + * Creates a slice of `array` with `n` elements dropped from the beginning. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.drop([1, 2, 3]); + * // => [2, 3] + * + * _.drop([1, 2, 3], 2); + * // => [3] + * + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function drop(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with `n` elements dropped from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRight([1, 2, 3]); + * // => [1, 2] + * + * _.dropRight([1, 2, 3], 2); + * // => [1] + * + * _.dropRight([1, 2, 3], 5); + * // => [] + * + * _.dropRight([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function dropRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.dropRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney'] + * + * // The `_.matches` iteratee shorthand. + * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropRightWhile(users, ['active', false]); + * // => objects for ['barney'] + * + * // The `_.property` iteratee shorthand. + * _.dropRightWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true, true) + : []; + } + + /** + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.dropWhile(users, function(o) { return !o.active; }); + * // => objects for ['pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.dropWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropWhile(users, ['active', false]); + * // => objects for ['pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.dropWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true) + : []; + } + + /** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * **Note:** This method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Array + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.fill(array, 'a'); + * console.log(array); + * // => ['a', 'a', 'a'] + * + * _.fill(Array(3), 2); + * // => [2, 2, 2] + * + * _.fill([4, 6, 8, 10], '*', 1, 3); + * // => [4, '*', '*', 10] + */ + function fill(array, value, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + + /** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ + function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, getIteratee(predicate, 3), index); + } + + /** + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); + * // => 2 + * + * // The `_.matches` iteratee shorthand. + * _.findLastIndex(users, { 'user': 'barney', 'active': true }); + * // => 0 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastIndex(users, ['active', false]); + * // => 2 + * + * // The `_.property` iteratee shorthand. + * _.findLastIndex(users, 'active'); + * // => 0 + */ + function findLastIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length - 1; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = fromIndex < 0 + ? nativeMax(length + index, 0) + : nativeMin(index, length - 1); + } + return baseFindIndex(array, getIteratee(predicate, 3), index, true); + } + + /** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ + function flatten(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, 1) : []; + } + + /** + * Recursively flattens `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, [3, [4]], 5]]); + * // => [1, 2, 3, 4, 5] + */ + function flattenDeep(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, INFINITY) : []; + } + + /** + * Recursively flatten `array` up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Array + * @param {Array} array The array to flatten. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * var array = [1, [2, [3, [4]], 5]]; + * + * _.flattenDepth(array, 1); + * // => [1, 2, [3, [4]], 5] + * + * _.flattenDepth(array, 2); + * // => [1, 2, 3, [4], 5] + */ + function flattenDepth(array, depth) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(array, depth); + } + + /** + * The inverse of `_.toPairs`; this method returns an object composed + * from key-value `pairs`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} pairs The key-value pairs. + * @returns {Object} Returns the new object. + * @example + * + * _.fromPairs([['a', 1], ['b', 2]]); + * // => { 'a': 1, 'b': 2 } + */ + function fromPairs(pairs) { + var index = -1, + length = pairs == null ? 0 : pairs.length, + result = {}; + + while (++index < length) { + var pair = pairs[index]; + result[pair[0]] = pair[1]; + } + return result; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ + function head(array) { + return (array && array.length) ? array[0] : undefined; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseIndexOf(array, value, index); + } + + /** + * Gets all but the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + */ + function initial(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 0, -1) : []; + } + + /** + * Creates an array of unique values that are included in all given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersection([2, 1], [2, 3]); + * // => [2] + */ + var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `iteratee` + * which is invoked for each element of each `arrays` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [2.1] + * + * // The `_.property` iteratee shorthand. + * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }] + */ + var intersectionBy = baseRest(function(arrays) { + var iteratee = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + if (iteratee === last(mapped)) { + iteratee = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `comparator` + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.intersectionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }] + */ + var intersectionWith = baseRest(function(arrays) { + var comparator = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + comparator = typeof comparator == 'function' ? comparator : undefined; + if (comparator) { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, undefined, comparator) + : []; + }); + + /** + * Converts all elements in `array` into a string separated by `separator`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to convert. + * @param {string} [separator=','] The element separator. + * @returns {string} Returns the joined string. + * @example + * + * _.join(['a', 'b', 'c'], '~'); + * // => 'a~b~c' + */ + function join(array, separator) { + return array == null ? '' : nativeJoin.call(array, separator); + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : undefined; + } + + /** + * This method is like `_.indexOf` except that it iterates over elements of + * `array` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.lastIndexOf([1, 2, 1, 2], 2); + * // => 3 + * + * // Search from the `fromIndex`. + * _.lastIndexOf([1, 2, 1, 2], 2, 2); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); + } + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); + } + + /** + * Gets the element at index `n` of `array`. If `n` is negative, the nth + * element from the end is returned. + * + * @static + * @memberOf _ + * @since 4.11.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=0] The index of the element to return. + * @returns {*} Returns the nth element of `array`. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * + * _.nth(array, 1); + * // => 'b' + * + * _.nth(array, -2); + * // => 'c'; + */ + function nth(array, n) { + return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; + } + + /** + * Removes all given values from `array` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` + * to remove elements from an array by predicate. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pull(array, 'a', 'c'); + * console.log(array); + * // => ['b', 'b'] + */ + var pull = baseRest(pullAll); + + /** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pullAll(array, ['a', 'c']); + * console.log(array); + * // => ['b', 'b'] + */ + function pullAll(array, values) { + return (array && array.length && values && values.length) + ? basePullAll(array, values) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `iteratee` which is + * invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The iteratee is invoked with one argument: (value). + * + * **Note:** Unlike `_.differenceBy`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; + * + * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); + * console.log(array); + * // => [{ 'x': 2 }] + */ + function pullAllBy(array, values, iteratee) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, getIteratee(iteratee, 2)) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `comparator` which + * is invoked to compare elements of `array` to `values`. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.differenceWith`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; + * + * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); + * console.log(array); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] + */ + function pullAllWith(array, values, comparator) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, undefined, comparator) + : array; + } + + /** + * Removes elements from `array` corresponding to `indexes` and returns an + * array of removed elements. + * + * **Note:** Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...(number|number[])} [indexes] The indexes of elements to remove. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * var pulled = _.pullAt(array, [1, 3]); + * + * console.log(array); + * // => ['a', 'c'] + * + * console.log(pulled); + * // => ['b', 'd'] + */ + var pullAt = flatRest(function(array, indexes) { + var length = array == null ? 0 : array.length, + result = baseAt(array, indexes); + + basePullAt(array, arrayMap(indexes, function(index) { + return isIndex(index, length) ? +index : index; + }).sort(compareAscending)); + + return result; + }); + + /** + * Removes all elements from `array` that `predicate` returns truthy for + * and returns an array of the removed elements. The predicate is invoked + * with three arguments: (value, index, array). + * + * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` + * to pull elements from an array by value. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [1, 2, 3, 4]; + * var evens = _.remove(array, function(n) { + * return n % 2 == 0; + * }); + * + * console.log(array); + * // => [1, 3] + * + * console.log(evens); + * // => [2, 4] + */ + function remove(array, predicate) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, + indexes = [], + length = array.length; + + predicate = getIteratee(predicate, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + + /** + * Reverses `array` so that the first element becomes the last, the second + * element becomes the second to last, and so on. + * + * **Note:** This method mutates `array` and is based on + * [`Array#reverse`](https://mdn.io/Array/reverse). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.reverse(array); + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function reverse(array) { + return array == null ? array : nativeReverse.call(array); + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This method is used instead of + * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are + * returned. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + else { + start = start == null ? 0 : toInteger(start); + end = end === undefined ? length : toInteger(end); + } + return baseSlice(array, start, end); + } + + /** + * Uses a binary search to determine the lowest index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedIndex([30, 50], 40); + * // => 1 + */ + function sortedIndex(array, value) { + return baseSortedIndex(array, value); + } + + /** + * This method is like `_.sortedIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.sortedIndexBy(objects, { 'x': 4 }, 'x'); + * // => 0 + */ + function sortedIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2)); + } + + /** + * This method is like `_.indexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedIndexOf([4, 5, 5, 5, 6], 5); + * // => 1 + */ + function sortedIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value); + if (index < length && eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.sortedIndex` except that it returns the highest + * index at which `value` should be inserted into `array` in order to + * maintain its sort order. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedLastIndex([4, 5, 5, 5, 6], 5); + * // => 4 + */ + function sortedLastIndex(array, value) { + return baseSortedIndex(array, value, true); + } + + /** + * This method is like `_.sortedLastIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 1 + * + * // The `_.property` iteratee shorthand. + * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x'); + * // => 1 + */ + function sortedLastIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true); + } + + /** + * This method is like `_.lastIndexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5); + * // => 3 + */ + function sortedLastIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value, true) - 1; + if (eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.uniq` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniq([1, 1, 2]); + * // => [1, 2] + */ + function sortedUniq(array) { + return (array && array.length) + ? baseSortedUniq(array) + : []; + } + + /** + * This method is like `_.uniqBy` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); + * // => [1.1, 2.3] + */ + function sortedUniqBy(array, iteratee) { + return (array && array.length) + ? baseSortedUniq(array, getIteratee(iteratee, 2)) + : []; + } + + /** + * Gets all but the first element of `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.tail([1, 2, 3]); + * // => [2, 3] + */ + function tail(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 1, length) : []; + } + + /** + * Creates a slice of `array` with `n` elements taken from the beginning. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.take([1, 2, 3]); + * // => [1] + * + * _.take([1, 2, 3], 2); + * // => [1, 2] + * + * _.take([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.take([1, 2, 3], 0); + * // => [] + */ + function take(array, n, guard) { + if (!(array && array.length)) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` with `n` elements taken from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRight([1, 2, 3]); + * // => [3] + * + * _.takeRight([1, 2, 3], 2); + * // => [2, 3] + * + * _.takeRight([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.takeRight([1, 2, 3], 0); + * // => [] + */ + function takeRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.takeRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeRightWhile(users, ['active', false]); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.takeRightWhile(users, 'active'); + * // => [] + */ + function takeRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), false, true) + : []; + } + + /** + * Creates a slice of `array` with elements taken from the beginning. Elements + * are taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.takeWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matches` iteratee shorthand. + * _.takeWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeWhile(users, ['active', false]); + * // => objects for ['barney', 'fred'] + * + * // The `_.property` iteratee shorthand. + * _.takeWhile(users, 'active'); + * // => [] + */ + function takeWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3)) + : []; + } + + /** + * Creates an array of unique values, in order, from all given arrays using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.union([2], [1, 2]); + * // => [2, 1] + */ + var union = baseRest(function(arrays) { + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); + }); + + /** + * This method is like `_.union` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which uniqueness is computed. Result values are chosen from the first + * array in which the value occurs. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.unionBy([2.1], [1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + var unionBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.union` except that it accepts `comparator` which + * is invoked to compare elements of `arrays`. Result values are chosen from + * the first array in which the value occurs. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.unionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var unionWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); + }); + + /** + * Creates a duplicate-free version of an array, using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons, in which only the first occurrence of each element + * is kept. The order of result values is determined by the order they occur + * in the array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniq([2, 1, 2]); + * // => [2, 1] + */ + function uniq(array) { + return (array && array.length) ? baseUniq(array) : []; + } + + /** + * This method is like `_.uniq` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * uniqueness is computed. The order of result values is determined by the + * order they occur in the array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniqBy([2.1, 1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniqBy(array, iteratee) { + return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : []; + } + + /** + * This method is like `_.uniq` except that it accepts `comparator` which + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array.The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.uniqWith(objects, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] + */ + function uniqWith(array, comparator) { + comparator = typeof comparator == 'function' ? comparator : undefined; + return (array && array.length) ? baseUniq(array, undefined, comparator) : []; + } + + /** + * This method is like `_.zip` except that it accepts an array of grouped + * elements and creates an array regrouping the elements to their pre-zip + * configuration. + * + * @static + * @memberOf _ + * @since 1.2.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + * + * _.unzip(zipped); + * // => [['a', 'b'], [1, 2], [true, false]] + */ + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLikeObject(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + return baseTimes(length, function(index) { + return arrayMap(array, baseProperty(index)); + }); + } + + /** + * This method is like `_.unzip` except that it accepts `iteratee` to specify + * how regrouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @param {Function} [iteratee=_.identity] The function to combine + * regrouped values. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip([1, 2], [10, 20], [100, 200]); + * // => [[1, 10, 100], [2, 20, 200]] + * + * _.unzipWith(zipped, _.add); + * // => [3, 30, 300] + */ + function unzipWith(array, iteratee) { + if (!(array && array.length)) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + return arrayMap(result, function(group) { + return apply(iteratee, undefined, group); + }); + } + + /** + * Creates an array excluding all given values using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.pull`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...*} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.xor + * @example + * + * _.without([2, 1, 2, 3], 1, 2); + * // => [3] + */ + var without = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, values) + : []; + }); + + /** + * Creates an array of unique values that is the + * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the given arrays. The order of result values is determined by the order + * they occur in the arrays. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.without + * @example + * + * _.xor([2, 1], [2, 3]); + * // => [1, 3] + */ + var xor = baseRest(function(arrays) { + return baseXor(arrayFilter(arrays, isArrayLikeObject)); + }); + + /** + * This method is like `_.xor` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which by which they're compared. The order of result values is determined + * by the order they occur in the arrays. The iteratee is invoked with one + * argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2, 3.4] + * + * // The `_.property` iteratee shorthand. + * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var xorBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.xor` except that it accepts `comparator` which is + * invoked to compare elements of `arrays`. The order of result values is + * determined by the order they occur in the arrays. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.xorWith(objects, others, _.isEqual); + * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var xorWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); + }); + + /** + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the + * second elements of the given arrays, and so on. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + */ + var zip = baseRest(unzip); + + /** + * This method is like `_.fromPairs` except that it accepts two arrays, + * one of property identifiers and one of corresponding values. + * + * @static + * @memberOf _ + * @since 0.4.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObject(['a', 'b'], [1, 2]); + * // => { 'a': 1, 'b': 2 } + */ + function zipObject(props, values) { + return baseZipObject(props || [], values || [], assignValue); + } + + /** + * This method is like `_.zipObject` except that it supports property paths. + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]); + * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } } + */ + function zipObjectDeep(props, values) { + return baseZipObject(props || [], values || [], baseSet); + } + + /** + * This method is like `_.zip` except that it accepts `iteratee` to specify + * how grouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @param {Function} [iteratee=_.identity] The function to combine + * grouped values. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { + * return a + b + c; + * }); + * // => [111, 222] + */ + var zipWith = baseRest(function(arrays) { + var length = arrays.length, + iteratee = length > 1 ? arrays[length - 1] : undefined; + + iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; + return unzipWith(arrays, iteratee); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor + * is invoked with one argument; (value). The purpose of this method is to + * "tap into" a method chain sequence in order to modify intermediate results. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * // Mutate input array. + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor) { + interceptor(value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * The purpose of this method is to "pass thru" values replacing intermediate + * results in a method chain sequence. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _(' abc ') + * .chain() + * .trim() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => ['abc'] + */ + function thru(value, interceptor) { + return interceptor(value); + } + + /** + * This method is the wrapper version of `_.at`. + * + * @name at + * @memberOf _ + * @since 1.0.0 + * @category Seq + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _(object).at(['a[0].b.c', 'a[1]']).value(); + * // => [3, 4] + */ + var wrapperAt = flatRest(function(paths) { + var length = paths.length, + start = length ? paths[0] : 0, + value = this.__wrapped__, + interceptor = function(object) { return baseAt(object, paths); }; + + if (length > 1 || this.__actions__.length || + !(value instanceof LazyWrapper) || !isIndex(start)) { + return this.thru(interceptor); + } + value = value.slice(start, +start + (length ? 1 : 0)); + value.__actions__.push({ + 'func': thru, + 'args': [interceptor], + 'thisArg': undefined + }); + return new LodashWrapper(value, this.__chain__).thru(function(array) { + if (length && !array.length) { + array.push(undefined); + } + return array; + }); + }); + + /** + * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. + * + * @name chain + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // A sequence without explicit chaining. + * _(users).head(); + * // => { 'user': 'barney', 'age': 36 } + * + * // A sequence with explicit chaining. + * _(users) + * .chain() + * .head() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chain sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapped = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapped = wrapped.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapped.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + + /** + * Gets the next value on a wrapped object following the + * [iterator protocol](https://mdn.io/iteration_protocols#iterator). + * + * @name next + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the next iterator value. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped.next(); + * // => { 'done': false, 'value': 1 } + * + * wrapped.next(); + * // => { 'done': false, 'value': 2 } + * + * wrapped.next(); + * // => { 'done': true, 'value': undefined } + */ + function wrapperNext() { + if (this.__values__ === undefined) { + this.__values__ = toArray(this.value()); + } + var done = this.__index__ >= this.__values__.length, + value = done ? undefined : this.__values__[this.__index__++]; + + return { 'done': done, 'value': value }; + } + + /** + * Enables the wrapper to be iterable. + * + * @name Symbol.iterator + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the wrapper object. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped[Symbol.iterator]() === wrapped; + * // => true + * + * Array.from(wrapped); + * // => [1, 2] + */ + function wrapperToIterator() { + return this; + } + + /** + * Creates a clone of the chain sequence planting `value` as the wrapped value. + * + * @name plant + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @param {*} value The value to plant. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2]).map(square); + * var other = wrapped.plant([3, 4]); + * + * other.value(); + * // => [9, 16] + * + * wrapped.value(); + * // => [1, 4] + */ + function wrapperPlant(value) { + var result, + parent = this; + + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + clone.__index__ = 0; + clone.__values__ = undefined; + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + + /** + * This method is the wrapper version of `_.reverse`. + * + * **Note:** This method mutates the wrapped array. + * + * @name reverse + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2, 3]; + * + * _(array).reverse().value() + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function wrapperReverse() { + var value = this.__wrapped__; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + 'func': thru, + 'args': [reverse], + 'thisArg': undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(reverse); + } + + /** + * Executes the chain sequence to resolve the unwrapped value. + * + * @name value + * @memberOf _ + * @since 0.1.0 + * @alias toJSON, valueOf + * @category Seq + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the number of times the key was returned by `iteratee`. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': 1, '6': 2 } + * + * // The `_.property` iteratee shorthand. + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + var countBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } + }); + + /** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ + function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.reject + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.filter(users, 'active'); + * // => objects for ['barney'] + * + * // Combining several predicates using `_.overEvery` or `_.overSome`. + * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]])); + * // => objects for ['fred', 'barney'] + */ + function filter(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ + var find = createFind(findIndex); + + /** + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=collection.length-1] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * _.findLast([1, 2, 3, 4], function(n) { + * return n % 2 == 1; + * }); + * // => 3 + */ + var findLast = createFind(findLastIndex); + + /** + * Creates a flattened array of values by running each element in `collection` + * thru `iteratee` and flattening the mapped results. The iteratee is invoked + * with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [n, n]; + * } + * + * _.flatMap([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMap(collection, iteratee) { + return baseFlatten(map(collection, iteratee), 1); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDeep([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMapDeep(collection, iteratee) { + return baseFlatten(map(collection, iteratee), INFINITY); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDepth([1, 2], duplicate, 2); + * // => [[1, 1], [2, 2]] + */ + function flatMapDepth(collection, iteratee, depth) { + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(map(collection, iteratee), depth); + } + + /** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forEach(collection, iteratee) { + var func = isArray(collection) ? arrayEach : baseEach; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @alias eachRight + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEach + * @example + * + * _.forEachRight([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `2` then `1`. + */ + function forEachRight(collection, iteratee) { + var func = isArray(collection) ? arrayEachRight : baseEachRight; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The order of grouped values + * is determined by the order they occur in `collection`. The corresponding + * value of each key is an array of elements responsible for generating the + * key. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': [4.2], '6': [6.1, 6.3] } + * + * // The `_.property` iteratee shorthand. + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + baseAssignValue(result, key, [value]); + } + }); + + /** + * Checks if `value` is in `collection`. If `collection` is a string, it's + * checked for a substring of `value`, otherwise + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * is used for equality comparisons. If `fromIndex` is negative, it's used as + * the offset from the end of `collection`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {boolean} Returns `true` if `value` is found, else `false`. + * @example + * + * _.includes([1, 2, 3], 1); + * // => true + * + * _.includes([1, 2, 3], 1, 2); + * // => false + * + * _.includes({ 'a': 1, 'b': 2 }, 1); + * // => true + * + * _.includes('abcd', 'bc'); + * // => true + */ + function includes(collection, value, fromIndex, guard) { + collection = isArrayLike(collection) ? collection : values(collection); + fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; + + var length = collection.length; + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); + } + return isString(collection) + ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) + : (!!length && baseIndexOf(collection, value, fromIndex) > -1); + } + + /** + * Invokes the method at `path` of each element in `collection`, returning + * an array of the results of each invoked method. Any additional arguments + * are provided to each invoked method. If `path` is a function, it's invoked + * for, and `this` bound to, each element in `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array|Function|string} path The path of the method to invoke or + * the function invoked per iteration. + * @param {...*} [args] The arguments to invoke each method with. + * @returns {Array} Returns the array of results. + * @example + * + * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invokeMap([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + var invokeMap = baseRest(function(collection, path, args) { + var index = -1, + isFunc = typeof path == 'function', + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value) { + result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); + }); + return result; + }); + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the last element responsible for generating the key. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var array = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.keyBy(array, function(o) { + * return String.fromCharCode(o.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * + * _.keyBy(array, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + */ + var keyBy = createAggregator(function(result, value, key) { + baseAssignValue(result, key, value); + }); + + /** + * Creates an array of values by running each element in `collection` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // The `_.property` iteratee shorthand. + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ + function map(collection, iteratee) { + var func = isArray(collection) ? arrayMap : baseMap; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.sortBy` except that it allows specifying the sort + * orders of the iteratees to sort by. If `orders` is unspecified, all values + * are sorted in ascending order. Otherwise, specify an order of "desc" for + * descending or "asc" for ascending sort order of corresponding values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] + * The iteratees to sort by. + * @param {string[]} [orders] The sort orders of `iteratees`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 34 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 36 } + * ]; + * + * // Sort by `user` in ascending order and by `age` in descending order. + * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + */ + function orderBy(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [iteratees]; + } + orders = guard ? undefined : orders; + if (!isArray(orders)) { + orders = orders == null ? [] : [orders]; + } + return baseOrderBy(collection, iteratees, orders); + } + + /** + * Creates an array of elements split into two groups, the first of which + * contains elements `predicate` returns truthy for, the second of which + * contains elements `predicate` returns falsey for. The predicate is + * invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the array of grouped elements. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * _.partition(users, function(o) { return o.active; }); + * // => objects for [['fred'], ['barney', 'pebbles']] + * + * // The `_.matches` iteratee shorthand. + * _.partition(users, { 'age': 1, 'active': false }); + * // => objects for [['pebbles'], ['barney', 'fred']] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.partition(users, ['active', false]); + * // => objects for [['barney', 'pebbles'], ['fred']] + * + * // The `_.property` iteratee shorthand. + * _.partition(users, 'active'); + * // => objects for [['fred'], ['barney', 'pebbles']] + */ + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { return [[], []]; }); + + /** + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` thru `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not given, the first element of `collection` is used as the initial + * value. The iteratee is invoked with four arguments: + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, + * and `sortBy` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduceRight + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; + * }, 0); + * // => 3 + * + * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * return result; + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) + */ + function reduce(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduce : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); + } + + /** + * This method is like `_.reduce` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduce + * @example + * + * var array = [[0, 1], [2, 3], [4, 5]]; + * + * _.reduceRight(array, function(flattened, other) { + * return flattened.concat(other); + * }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduceRight : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); + } + + /** + * The opposite of `_.filter`; this method returns the elements of `collection` + * that `predicate` does **not** return truthy for. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.filter + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } + * ]; + * + * _.reject(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.reject(users, { 'age': 40, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.reject(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.reject(users, 'active'); + * // => objects for ['barney'] + */ + function reject(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, negate(getIteratee(predicate, 3))); + } + + /** + * Gets a random element from `collection`. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + * @example + * + * _.sample([1, 2, 3, 4]); + * // => 2 + */ + function sample(collection) { + var func = isArray(collection) ? arraySample : baseSample; + return func(collection); + } + + /** + * Gets `n` random elements at unique keys from `collection` up to the + * size of `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @param {number} [n=1] The number of elements to sample. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the random elements. + * @example + * + * _.sampleSize([1, 2, 3], 2); + * // => [3, 1] + * + * _.sampleSize([1, 2, 3], 4); + * // => [2, 3, 1] + */ + function sampleSize(collection, n, guard) { + if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + var func = isArray(collection) ? arraySampleSize : baseSampleSize; + return func(collection, n); + } + + /** + * Creates an array of shuffled values, using a version of the + * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + * @example + * + * _.shuffle([1, 2, 3, 4]); + * // => [4, 1, 3, 2] + */ + function shuffle(collection) { + var func = isArray(collection) ? arrayShuffle : baseShuffle; + return func(collection); + } + + /** + * Gets the size of `collection` by returning its length for array-like + * values or the number of own enumerable string keyed properties for objects. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @returns {number} Returns the collection size. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ + function size(collection) { + if (collection == null) { + return 0; + } + if (isArrayLike(collection)) { + return isString(collection) ? stringSize(collection) : collection.length; + } + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; + } + return baseKeys(collection).length; + } + + /** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * Iteration is stopped once `predicate` returns truthy. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.some(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.some(users, 'active'); + * // => true + */ + function some(collection, predicate, guard) { + var func = isArray(collection) ? arraySome : baseSome; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection thru each iteratee. This method + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The iteratees are invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to sort by. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 30 }, + * { 'user': 'barney', 'age': 34 } + * ]; + * + * _.sortBy(users, [function(o) { return o.user; }]); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]] + * + * _.sortBy(users, ['user', 'age']); + * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]] + */ + var sortBy = baseRest(function(collection, iteratees) { + if (collection == null) { + return []; + } + var length = iteratees.length; + if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { + iteratees = []; + } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { + iteratees = [iteratees[0]]; + } + return baseOrderBy(collection, baseFlatten(iteratees, 1), []); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ + var now = ctxNow || function() { + return root.Date.now(); + }; + + /*------------------------------------------------------------------------*/ + + /** + * The opposite of `_.before`; this method creates a function that invokes + * `func` once it's called `n` or more times. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {number} n The number of calls before `func` is invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('done saving!'); + * }); + * + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => Logs 'done saving!' after the two async saves have completed. + */ + function after(n, func) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that invokes `func`, with up to `n` arguments, + * ignoring any additional arguments. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @param {number} [n=func.length] The arity cap. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.ary(parseInt, 1)); + * // => [6, 8, 10] + */ + function ary(func, n, guard) { + n = guard ? undefined : n; + n = (func && n == null) ? func.length : n; + return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ + function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind = baseRest(function(func, thisArg, partials) { + var bitmask = WRAP_BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bind)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(func, bitmask, thisArg, partials, holders); + }); + + /** + * Creates a function that invokes the method at `object[key]` with `partials` + * prepended to the arguments it receives. + * + * This method differs from `_.bind` by allowing bound functions to reference + * methods that may be redefined or don't yet exist. See + * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) + * for more details. + * + * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Function + * @param {Object} object The object to invoke the method on. + * @param {string} key The key of the method. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'user': 'fred', + * 'greet': function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * }; + * + * var bound = _.bindKey(object, 'greet', 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * object.greet = function(greeting, punctuation) { + * return greeting + 'ya ' + this.user + punctuation; + * }; + * + * bound('!'); + * // => 'hiya fred!' + * + * // Bound with placeholders. + * var bound = _.bindKey(object, 'greet', _, '!'); + * bound('hi'); + * // => 'hiya fred!' + */ + var bindKey = baseRest(function(object, key, partials) { + var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bindKey)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(key, bitmask, object, partials, holders); + }); + + /** + * Creates a function that accepts arguments of `func` and either invokes + * `func` returning its result, if at least `arity` number of arguments have + * been provided, or returns a function that accepts the remaining `func` + * arguments, and so on. The arity of `func` may be specified if `func.length` + * is not sufficient. + * + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curry(abc); + * + * curried(1)(2)(3); + * // => [1, 2, 3] + * + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(1)(_, 3)(2); + * // => [1, 2, 3] + */ + function curry(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curry.placeholder; + return result; + } + + /** + * This method is like `_.curry` except that arguments are applied to `func` + * in the manner of `_.partialRight` instead of `_.partial`. + * + * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curryRight(abc); + * + * curried(3)(2)(1); + * // => [1, 2, 3] + * + * curried(2, 3)(1); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(3)(1, _)(2); + * // => [1, 2, 3] + */ + function curryRight(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryRight.placeholder; + return result; + } + + /** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ + function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + timeWaiting = wait - timeSinceLastCall; + + return maxing + ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) + : timeWaiting; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + clearTimeout(timerId); + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; + } + + /** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // => Logs 'deferred' after one millisecond. + */ + var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); + }); + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => Logs 'later' after one second. + */ + var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + + /** + * Creates a function that invokes `func` with arguments reversed. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to flip arguments for. + * @returns {Function} Returns the new flipped function. + * @example + * + * var flipped = _.flip(function() { + * return _.toArray(arguments); + * }); + * + * flipped('a', 'b', 'c', 'd'); + * // => ['d', 'c', 'b', 'a'] + */ + function flip(func) { + return createWrap(func, WRAP_FLIP_FLAG); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `clear`, `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; + } + + // Expose `MapCache`. + memoize.Cache = MapCache; + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new negated function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var args = arguments; + switch (args.length) { + case 0: return !predicate.call(this); + case 1: return !predicate.call(this, args[0]); + case 2: return !predicate.call(this, args[0], args[1]); + case 3: return !predicate.call(this, args[0], args[1], args[2]); + } + return !predicate.apply(this, args); + }; + } + + /** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // => `createApplication` is invoked once + */ + function once(func) { + return before(2, func); + } + + /** + * Creates a function that invokes `func` with its arguments transformed. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms=[_.identity]] + * The argument transforms. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var func = _.overArgs(function(x, y) { + * return [x, y]; + * }, [square, doubled]); + * + * func(9, 3); + * // => [81, 6] + * + * func(10, 5); + * // => [100, 10] + */ + var overArgs = castRest(function(func, transforms) { + transforms = (transforms.length == 1 && isArray(transforms[0])) + ? arrayMap(transforms[0], baseUnary(getIteratee())) + : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); + + var funcsLength = transforms.length; + return baseRest(function(args) { + var index = -1, + length = nativeMin(args.length, funcsLength); + + while (++index < length) { + args[index] = transforms[index].call(this, args[index]); + } + return apply(func, this, args); + }); + }); + + /** + * Creates a function that invokes `func` with `partials` prepended to the + * arguments it receives. This method is like `_.bind` except it does **not** + * alter the `this` binding. + * + * The `_.partial.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 0.2.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' + * + * // Partially applied with placeholders. + * var greetFred = _.partial(greet, _, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + */ + var partial = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partial)); + return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders); + }); + + /** + * This method is like `_.partial` except that partially applied arguments + * are appended to the arguments it receives. + * + * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + * + * // Partially applied with placeholders. + * var sayHelloTo = _.partialRight(greet, 'hello', _); + * sayHelloTo('fred'); + * // => 'hello fred' + */ + var partialRight = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partialRight)); + return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders); + }); + + /** + * Creates a function that invokes `func` with arguments arranged according + * to the specified `indexes` where the argument value at the first index is + * provided as the first argument, the argument value at the second index is + * provided as the second argument, and so on. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to rearrange arguments for. + * @param {...(number|number[])} indexes The arranged argument indexes. + * @returns {Function} Returns the new function. + * @example + * + * var rearged = _.rearg(function(a, b, c) { + * return [a, b, c]; + * }, [2, 0, 1]); + * + * rearged('b', 'c', 'a') + * // => ['a', 'b', 'c'] + */ + var rearg = flatRest(function(func, indexes) { + return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes); + }); + + /** + * Creates a function that invokes `func` with the `this` binding of the + * created function and arguments from `start` and beyond provided as + * an array. + * + * **Note:** This method is based on the + * [rest parameter](https://mdn.io/rest_parameters). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.rest(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ + function rest(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start === undefined ? start : toInteger(start); + return baseRest(func, start); + } + + /** + * Creates a function that invokes `func` with the `this` binding of the + * create function and an array of arguments much like + * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). + * + * **Note:** This method is based on the + * [spread operator](https://mdn.io/spread_operator). + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Function + * @param {Function} func The function to spread arguments over. + * @param {number} [start=0] The start position of the spread. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.spread(function(who, what) { + * return who + ' says ' + what; + * }); + * + * say(['fred', 'hello']); + * // => 'fred says hello' + * + * var numbers = Promise.all([ + * Promise.resolve(40), + * Promise.resolve(36) + * ]); + * + * numbers.then(_.spread(function(x, y) { + * return x + y; + * })); + * // => a Promise of 76 + */ + function spread(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start == null ? 0 : nativeMax(toInteger(start), 0); + return baseRest(function(args) { + var array = args[start], + otherArgs = castSlice(args, 0, start); + + if (array) { + arrayPush(otherArgs, array); + } + return apply(func, this, otherArgs); + }); + } + + /** + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.throttle` and `_.debounce`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // Avoid excessively updating the position while scrolling. + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); + * + * // Cancel the trailing throttled invocation. + * jQuery(window).on('popstate', throttled.cancel); + */ + function throttle(func, wait, options) { + var leading = true, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + 'leading': leading, + 'maxWait': wait, + 'trailing': trailing + }); + } + + /** + * Creates a function that accepts up to one argument, ignoring any + * additional arguments. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.unary(parseInt)); + * // => [6, 8, 10] + */ + function unary(func) { + return ary(func, 1); + } + + /** + * Creates a function that provides `value` to `wrapper` as its first + * argument. Any additional arguments provided to the function are appended + * to those provided to the `wrapper`. The wrapper is invoked with the `this` + * binding of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {*} value The value to wrap. + * @param {Function} [wrapper=identity] The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var p = _.wrap(_.escape, function(func, text) { + * return '

' + func(text) + '

'; + * }); + * + * p('fred, barney, & pebbles'); + * // => '

fred, barney, & pebbles

' + */ + function wrap(value, wrapper) { + return partial(castFunction(wrapper), value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Casts `value` as an array if it's not one. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Lang + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast array. + * @example + * + * _.castArray(1); + * // => [1] + * + * _.castArray({ 'a': 1 }); + * // => [{ 'a': 1 }] + * + * _.castArray('abc'); + * // => ['abc'] + * + * _.castArray(null); + * // => [null] + * + * _.castArray(undefined); + * // => [undefined] + * + * _.castArray(); + * // => [] + * + * var array = [1, 2, 3]; + * console.log(_.castArray(array) === array); + * // => true + */ + function castArray() { + if (!arguments.length) { + return []; + } + var value = arguments[0]; + return isArray(value) ? value : [value]; + } + + /** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ + function clone(value) { + return baseClone(value, CLONE_SYMBOLS_FLAG); + } + + /** + * This method is like `_.clone` except that it accepts `customizer` which + * is invoked to produce the cloned value. If `customizer` returns `undefined`, + * cloning is handled by the method instead. The `customizer` is invoked with + * up to four arguments; (value [, index|key, object, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the cloned value. + * @see _.cloneDeepWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(false); + * } + * } + * + * var el = _.cloneWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 0 + */ + function cloneWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @see _.clone + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ + function cloneDeep(value) { + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); + } + + /** + * This method is like `_.cloneWith` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the deep cloned value. + * @see _.cloneWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * } + * + * var el = _.cloneDeepWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 20 + */ + function cloneDeepWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * Checks if `object` conforms to `source` by invoking the predicate + * properties of `source` with the corresponding property values of `object`. + * + * **Note:** This method is equivalent to `_.conforms` when `source` is + * partially applied. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); + * // => true + * + * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); + * // => false + */ + function conformsTo(object, source) { + return source == null || baseConformsTo(object, source, keys(source)); + } + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + * @see _.lt + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ + var gt = createRelationalOperation(baseGt); + + /** + * Checks if `value` is greater than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than or equal to + * `other`, else `false`. + * @see _.lte + * @example + * + * _.gte(3, 1); + * // => true + * + * _.gte(3, 3); + * // => true + * + * _.gte(1, 3); + * // => false + */ + var gte = createRelationalOperation(function(value, other) { + return value >= other; + }); + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is classified as an `ArrayBuffer` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + * @example + * + * _.isArrayBuffer(new ArrayBuffer(2)); + * // => true + * + * _.isArrayBuffer(new Array(2)); + * // => false + */ + var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + /** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ + function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); + } + + /** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && baseGetTag(value) == boolTag); + } + + /** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + var isBuffer = nativeIsBuffer || stubFalse; + + /** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ + var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; + + /** + * Checks if `value` is likely a DOM element. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + * + * _.isElement(''); + * // => false + */ + function isElement(value) { + return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); + } + + /** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && + (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || + isBuffer(value) || isTypedArray(value) || isArguments(value))) { + return !value.length; + } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (isPrototype(value)) { + return !baseKeys(value).length; + } + for (var key in value) { + if (hasOwnProperty.call(value, key)) { + return false; + } + } + return true; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ + function isEqual(value, other) { + return baseIsEqual(value, other); + } + + /** + * This method is like `_.isEqual` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with up to + * six arguments: (objValue, othValue [, index|key, object, other, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, othValue) { + * if (isGreeting(objValue) && isGreeting(othValue)) { + * return true; + * } + * } + * + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqualWith(array, other, customizer); + * // => true + */ + function isEqualWith(value, other, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result; + } + + /** + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. + * @example + * + * _.isError(new Error); + * // => true + * + * _.isError(Error); + * // => false + */ + function isError(value) { + if (!isObjectLike(value)) { + return false; + } + var tag = baseGetTag(value); + return tag == errorTag || tag == domExcTag || + (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value)); + } + + /** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MIN_VALUE); + * // => true + * + * _.isFinite(Infinity); + * // => false + * + * _.isFinite('3'); + * // => false + */ + function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); + } + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; + } + + /** + * Checks if `value` is an integer. + * + * **Note:** This method is based on + * [`Number.isInteger`](https://mdn.io/Number/isInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an integer, else `false`. + * @example + * + * _.isInteger(3); + * // => true + * + * _.isInteger(Number.MIN_VALUE); + * // => false + * + * _.isInteger(Infinity); + * // => false + * + * _.isInteger('3'); + * // => false + */ + function isInteger(value) { + return typeof value == 'number' && value == toInteger(value); + } + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + /** + * Checks if `value` is classified as a `Map` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + * @example + * + * _.isMap(new Map); + * // => true + * + * _.isMap(new WeakMap); + * // => false + */ + var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + + /** + * Performs a partial deep comparison between `object` and `source` to + * determine if `object` contains equivalent property values. + * + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.isMatch(object, { 'b': 2 }); + * // => true + * + * _.isMatch(object, { 'b': 1 }); + * // => false + */ + function isMatch(object, source) { + return object === source || baseIsMatch(object, source, getMatchData(source)); + } + + /** + * This method is like `_.isMatch` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with five + * arguments: (objValue, srcValue, index|key, object, source). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, srcValue) { + * if (isGreeting(objValue) && isGreeting(srcValue)) { + * return true; + * } + * } + * + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; + * + * _.isMatchWith(object, source, customizer); + * // => true + */ + function isMatchWith(object, source, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseIsMatch(object, source, getMatchData(source), customizer); + } + + /** + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. + return isNumber(value) && value != +value; + } + + /** + * Checks if `value` is a pristine native function. + * + * **Note:** This method can't reliably detect native functions in the presence + * of the core-js package because core-js circumvents this kind of detection. + * Despite multiple requests, the core-js maintainer has made it clear: any + * attempt to fix the detection will be obstructed. As a result, we're left + * with little choice but to throw an error. Unfortunately, this also affects + * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), + * which rely on core-js. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ + function isNative(value) { + if (isMaskable(value)) { + throw new Error(CORE_ERROR_TEXT); + } + return baseIsNative(value); + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is `null` or `undefined`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is nullish, else `false`. + * @example + * + * _.isNil(null); + * // => true + * + * _.isNil(void 0); + * // => true + * + * _.isNil(NaN); + * // => false + */ + function isNil(value) { + return value == null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ + function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag); + } + + /** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ + function isPlainObject(value) { + if (!isObjectLike(value) || baseGetTag(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString.call(Ctor) == objectCtorString; + } + + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; + + /** + * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 + * double precision number which isn't the result of a rounded unsafe integer. + * + * **Note:** This method is based on + * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. + * @example + * + * _.isSafeInteger(3); + * // => true + * + * _.isSafeInteger(Number.MIN_VALUE); + * // => false + * + * _.isSafeInteger(Infinity); + * // => false + * + * _.isSafeInteger('3'); + * // => false + */ + function isSafeInteger(value) { + return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is classified as a `Set` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + * @example + * + * _.isSet(new Set); + * // => true + * + * _.isSet(new WeakSet); + * // => false + */ + var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + + /** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); + } + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); + } + + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + + /** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Checks if `value` is classified as a `WeakMap` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. + * @example + * + * _.isWeakMap(new WeakMap); + * // => true + * + * _.isWeakMap(new Map); + * // => false + */ + function isWeakMap(value) { + return isObjectLike(value) && getTag(value) == weakMapTag; + } + + /** + * Checks if `value` is classified as a `WeakSet` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. + * @example + * + * _.isWeakSet(new WeakSet); + * // => true + * + * _.isWeakSet(new Set); + * // => false + */ + function isWeakSet(value) { + return isObjectLike(value) && baseGetTag(value) == weakSetTag; + } + + /** + * Checks if `value` is less than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + * @see _.gt + * @example + * + * _.lt(1, 3); + * // => true + * + * _.lt(3, 3); + * // => false + * + * _.lt(3, 1); + * // => false + */ + var lt = createRelationalOperation(baseLt); + + /** + * Checks if `value` is less than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than or equal to + * `other`, else `false`. + * @see _.gte + * @example + * + * _.lte(1, 3); + * // => true + * + * _.lte(3, 3); + * // => true + * + * _.lte(3, 1); + * // => false + */ + var lte = createRelationalOperation(function(value, other) { + return value <= other; + }); + + /** + * Converts `value` to an array. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ + function toArray(value) { + if (!value) { + return []; + } + if (isArrayLike(value)) { + return isString(value) ? stringToArray(value) : copyArray(value); + } + if (symIterator && value[symIterator]) { + return iteratorToArray(value[symIterator]()); + } + var tag = getTag(value), + func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); + + return func(value); + } + + /** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted number. + * @example + * + * _.toFinite(3.2); + * // => 3.2 + * + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toFinite(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toFinite('3.2'); + * // => 3.2 + */ + function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + return value === value ? value : 0; + } + + /** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ + function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; + } + + /** + * Converts `value` to an integer suitable for use as the length of an + * array-like object. + * + * **Note:** This method is based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toLength(3.2); + * // => 3 + * + * _.toLength(Number.MIN_VALUE); + * // => 0 + * + * _.toLength(Infinity); + * // => 4294967295 + * + * _.toLength('3.2'); + * // => 3 + */ + function toLength(value) { + return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; + } + + /** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ + function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = baseTrim(value); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); + } + + /** + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ + function toPlainObject(value) { + return copyObject(value, keysIn(value)); + } + + /** + * Converts `value` to a safe integer. A safe integer can be compared and + * represented correctly. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toSafeInteger(3.2); + * // => 3 + * + * _.toSafeInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toSafeInteger(Infinity); + * // => 9007199254740991 + * + * _.toSafeInteger('3.2'); + * // => 3 + */ + function toSafeInteger(value) { + return value + ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) + : (value === 0 ? value : 0); + } + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + return value == null ? '' : baseToString(value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ + var assign = createAssigner(function(object, source) { + if (isPrototype(source) || isArrayLike(source)) { + copyObject(source, keys(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + assignValue(object, key, source[key]); + } + } + }); + + /** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assign + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } + */ + var assignIn = createAssigner(function(object, source) { + copyObject(source, keysIn(source), object); + }); + + /** + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); + }); + + /** + * This method is like `_.assign` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignInWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keys(source), object, customizer); + }); + + /** + * Creates an array of values corresponding to `paths` of `object`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Array} Returns the picked values. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _.at(object, ['a[0].b.c', 'a[1]']); + * // => [3, 4] + */ + var at = flatRest(baseAt); + + /** + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties == null ? result : baseAssign(result, properties); + } + + /** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var defaults = baseRest(function(object, sources) { + object = Object(object); + + var index = -1; + var length = sources.length; + var guard = length > 2 ? sources[2] : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + length = 1; + } + + while (++index < length) { + var source = sources[index]; + var props = keysIn(source); + var propsIndex = -1; + var propsLength = props.length; + + while (++propsIndex < propsLength) { + var key = props[propsIndex]; + var value = object[key]; + + if (value === undefined || + (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { + object[key] = source[key]; + } + } + } + + return object; + }); + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaults + * @example + * + * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); + * // => { 'a': { 'b': 2, 'c': 3 } } + */ + var defaultsDeep = baseRest(function(args) { + args.push(undefined, customDefaultsMerge); + return apply(mergeWith, undefined, args); + }); + + /** + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(o) { return o.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // The `_.matches` iteratee shorthand. + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findKey(users, 'active'); + * // => 'barney' + */ + function findKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); + } + + /** + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findLastKey(users, function(o) { return o.age < 40; }); + * // => returns 'pebbles' assuming `_.findKey` returns 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.findLastKey(users, { 'age': 36, 'active': true }); + * // => 'barney' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findLastKey(users, 'active'); + * // => 'pebbles' + */ + function findLastKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); + } + + /** + * Iterates over own and inherited enumerable string keyed properties of an + * object and invokes `iteratee` for each property. The iteratee is invoked + * with three arguments: (value, key, object). Iteratee functions may exit + * iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forInRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forIn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). + */ + function forIn(object, iteratee) { + return object == null + ? object + : baseFor(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * This method is like `_.forIn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forIn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forInRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. + */ + function forInRight(object, iteratee) { + return object == null + ? object + : baseForRight(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * Iterates over own enumerable string keyed properties of an object and + * invokes `iteratee` for each property. The iteratee is invoked with three + * arguments: (value, key, object). Iteratee functions may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwnRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forOwn(object, iteratee) { + return object && baseForOwn(object, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forOwn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwnRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. + */ + function forOwnRight(object, iteratee) { + return object && baseForOwnRight(object, getIteratee(iteratee, 3)); + } + + /** + * Creates an array of function property names from own enumerable properties + * of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functionsIn + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functions(new Foo); + * // => ['a', 'b'] + */ + function functions(object) { + return object == null ? [] : baseFunctions(object, keys(object)); + } + + /** + * Creates an array of function property names from own and inherited + * enumerable properties of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functions + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functionsIn(new Foo); + * // => ['a', 'b', 'c'] + */ + function functionsIn(object) { + return object == null ? [] : baseFunctions(object, keysIn(object)); + } + + /** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; + } + + /** + * Checks if `path` is a direct property of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b'); + * // => true + * + * _.has(object, ['a', 'b']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ + function has(object, path) { + return object != null && hasPath(object, path, baseHas); + } + + /** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b'); + * // => true + * + * _.hasIn(object, ['a', 'b']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ + function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); + } + + /** + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite + * property assignments of previous values. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Object + * @param {Object} object The object to invert. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invert(object); + * // => { '1': 'c', '2': 'b' } + */ + var invert = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString.call(value); + } + + result[value] = key; + }, constant(identity)); + + /** + * This method is like `_.invert` except that the inverted object is generated + * from the results of running each element of `object` thru `iteratee`. The + * corresponding inverted value of each inverted key is an array of keys + * responsible for generating the inverted value. The iteratee is invoked + * with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Object + * @param {Object} object The object to invert. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invertBy(object); + * // => { '1': ['a', 'c'], '2': ['b'] } + * + * _.invertBy(object, function(value) { + * return 'group' + value; + * }); + * // => { 'group1': ['a', 'c'], 'group2': ['b'] } + */ + var invertBy = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString.call(value); + } + + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } + }, getIteratee); + + /** + * Invokes the method at `path` of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + * @example + * + * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; + * + * _.invoke(object, 'a[0].b.c.slice', 1, 3); + * // => [2, 3] + */ + var invoke = baseRest(baseInvoke); + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); + } + + /** + * The opposite of `_.mapValues`; this method creates an object with the + * same values as `object` and keys generated by running each own enumerable + * string keyed property of `object` thru `iteratee`. The iteratee is invoked + * with three arguments: (value, key, object). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapValues + * @example + * + * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { + * return key + value; + * }); + * // => { 'a1': 1, 'b2': 2 } + */ + function mapKeys(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, iteratee(value, key, object), value); + }); + return result; + } + + /** + * Creates an object with the same keys as `object` and values generated + * by running each own enumerable string keyed property of `object` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, key, object). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapKeys + * @example + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * _.mapValues(users, function(o) { return o.age; }); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * + * // The `_.property` iteratee shorthand. + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + */ + function mapValues(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, key, iteratee(value, key, object)); + }); + return result; + } + + /** + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; + * + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; + * + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } + */ + var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); + }); + + /** + * This method is like `_.merge` except that it accepts `customizer` which + * is invoked to produce the merged values of the destination and source + * properties. If `customizer` returns `undefined`, merging is handled by the + * method instead. The `customizer` is invoked with six arguments: + * (objValue, srcValue, key, object, source, stack). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} customizer The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * function customizer(objValue, srcValue) { + * if (_.isArray(objValue)) { + * return objValue.concat(srcValue); + * } + * } + * + * var object = { 'a': [1], 'b': [2] }; + * var other = { 'a': [3], 'b': [4] }; + * + * _.mergeWith(object, other, customizer); + * // => { 'a': [1, 3], 'b': [2, 4] } + */ + var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { + baseMerge(object, source, srcIndex, customizer); + }); + + /** + * The opposite of `_.pick`; this method creates an object composed of the + * own and inherited enumerable property paths of `object` that are not omitted. + * + * **Note:** This method is considerably slower than `_.pick`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to omit. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omit(object, ['a', 'c']); + * // => { 'b': '2' } + */ + var omit = flatRest(function(object, paths) { + var result = {}; + if (object == null) { + return result; + } + var isDeep = false; + paths = arrayMap(paths, function(path) { + path = castPath(path, object); + isDeep || (isDeep = path.length > 1); + return path; + }); + copyObject(object, getAllKeysIn(object), result); + if (isDeep) { + result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); + } + var length = paths.length; + while (length--) { + baseUnset(result, paths[length]); + } + return result; + }); + + /** + * The opposite of `_.pickBy`; this method creates an object composed of + * the own and inherited enumerable string keyed properties of `object` that + * `predicate` doesn't return truthy for. The predicate is invoked with two + * arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omitBy(object, _.isNumber); + * // => { 'b': '2' } + */ + function omitBy(object, predicate) { + return pickBy(object, negate(getIteratee(predicate))); + } + + /** + * Creates an object composed of the picked `object` properties. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pick(object, ['a', 'c']); + * // => { 'a': 1, 'c': 3 } + */ + var pick = flatRest(function(object, paths) { + return object == null ? {} : basePick(object, paths); + }); + + /** + * Creates an object composed of the `object` properties `predicate` returns + * truthy for. The predicate is invoked with two arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pickBy(object, _.isNumber); + * // => { 'a': 1, 'c': 3 } + */ + function pickBy(object, predicate) { + if (object == null) { + return {}; + } + var props = arrayMap(getAllKeysIn(object), function(prop) { + return [prop]; + }); + predicate = getIteratee(predicate); + return basePickBy(object, props, function(value, path) { + return predicate(value, path[0]); + }); + } + + /** + * This method is like `_.get` except that if the resolved value is a + * function it's invoked with the `this` binding of its parent object and + * its result is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to resolve. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; + * + * _.result(object, 'a[0].b.c1'); + * // => 3 + * + * _.result(object, 'a[0].b.c2'); + * // => 4 + * + * _.result(object, 'a[0].b.c3', 'default'); + * // => 'default' + * + * _.result(object, 'a[0].b.c3', _.constant('default')); + * // => 'default' + */ + function result(object, path, defaultValue) { + path = castPath(path, object); + + var index = -1, + length = path.length; + + // Ensure the loop is entered when path is empty. + if (!length) { + length = 1; + object = undefined; + } + while (++index < length) { + var value = object == null ? undefined : object[toKey(path[index])]; + if (value === undefined) { + index = length; + value = defaultValue; + } + object = isFunction(value) ? value.call(object) : value; + } + return object; + } + + /** + * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, + * it's created. Arrays are created for missing index properties while objects + * are created for all other missing properties. Use `_.setWith` to customize + * `path` creation. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.set(object, 'a[0].b.c', 4); + * console.log(object.a[0].b.c); + * // => 4 + * + * _.set(object, ['x', '0', 'y', 'z'], 5); + * console.log(object.x[0].y.z); + * // => 5 + */ + function set(object, path, value) { + return object == null ? object : baseSet(object, path, value); + } + + /** + * This method is like `_.set` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.setWith(object, '[0][1]', 'a', Object); + * // => { '0': { '1': 'a' } } + */ + function setWith(object, path, value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseSet(object, path, value, customizer); + } + + /** + * Creates an array of own enumerable string keyed-value pairs for `object` + * which can be consumed by `_.fromPairs`. If `object` is a map or set, its + * entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entries + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairs(new Foo); + * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) + */ + var toPairs = createToPairs(keys); + + /** + * Creates an array of own and inherited enumerable string keyed-value pairs + * for `object` which can be consumed by `_.fromPairs`. If `object` is a map + * or set, its entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entriesIn + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairsIn(new Foo); + * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) + */ + var toPairsIn = createToPairs(keysIn); + + /** + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own + * enumerable string keyed properties thru `iteratee`, with each invocation + * potentially mutating the `accumulator` object. If `accumulator` is not + * provided, a new object with the same `[[Prototype]]` will be used. The + * iteratee is invoked with four arguments: (accumulator, value, key, object). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @returns {*} Returns the accumulated value. + * @example + * + * _.transform([2, 3, 4], function(result, n) { + * result.push(n *= n); + * return n % 2 == 0; + * }, []); + * // => [4, 9] + * + * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } + */ + function transform(object, iteratee, accumulator) { + var isArr = isArray(object), + isArrLike = isArr || isBuffer(object) || isTypedArray(object); + + iteratee = getIteratee(iteratee, 4); + if (accumulator == null) { + var Ctor = object && object.constructor; + if (isArrLike) { + accumulator = isArr ? new Ctor : []; + } + else if (isObject(object)) { + accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; + } + else { + accumulator = {}; + } + } + (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + + /** + * Removes the property at `path` of `object`. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 7 } }] }; + * _.unset(object, 'a[0].b.c'); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + * + * _.unset(object, ['a', '0', 'b', 'c']); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + */ + function unset(object, path) { + return object == null ? true : baseUnset(object, path); + } + + /** + * This method is like `_.set` except that accepts `updater` to produce the + * value to set. Use `_.updateWith` to customize `path` creation. The `updater` + * is invoked with one argument: (value). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.update(object, 'a[0].b.c', function(n) { return n * n; }); + * console.log(object.a[0].b.c); + * // => 9 + * + * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); + * console.log(object.x[0].y.z); + * // => 0 + */ + function update(object, path, updater) { + return object == null ? object : baseUpdate(object, path, castFunction(updater)); + } + + /** + * This method is like `_.update` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.updateWith(object, '[0][1]', _.constant('a'), Object); + * // => { '0': { '1': 'a' } } + */ + function updateWith(object, path, updater, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); + } + + /** + * Creates an array of the own enumerable string keyed property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ + function values(object) { + return object == null ? [] : baseValues(object, keys(object)); + } + + /** + * Creates an array of the own and inherited enumerable string keyed property + * values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.valuesIn(new Foo); + * // => [1, 2, 3] (iteration order is not guaranteed) + */ + function valuesIn(object) { + return object == null ? [] : baseValues(object, keysIn(object)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Clamps `number` within the inclusive `lower` and `upper` bounds. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Number + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + * @example + * + * _.clamp(-10, -5, 5); + * // => -5 + * + * _.clamp(10, -5, 5); + * // => 5 + */ + function clamp(number, lower, upper) { + if (upper === undefined) { + upper = lower; + lower = undefined; + } + if (upper !== undefined) { + upper = toNumber(upper); + upper = upper === upper ? upper : 0; + } + if (lower !== undefined) { + lower = toNumber(lower); + lower = lower === lower ? lower : 0; + } + return baseClamp(toNumber(number), lower, upper); + } + + /** + * Checks if `n` is between `start` and up to, but not including, `end`. If + * `end` is not specified, it's set to `start` with `start` then set to `0`. + * If `start` is greater than `end` the params are swapped to support + * negative ranges. + * + * @static + * @memberOf _ + * @since 3.3.0 + * @category Number + * @param {number} number The number to check. + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + * @see _.range, _.rangeRight + * @example + * + * _.inRange(3, 2, 4); + * // => true + * + * _.inRange(4, 8); + * // => true + * + * _.inRange(4, 2); + * // => false + * + * _.inRange(2, 2); + * // => false + * + * _.inRange(1.2, 2); + * // => true + * + * _.inRange(5.2, 4); + * // => false + * + * _.inRange(-3, -2, -6); + * // => true + */ + function inRange(number, start, end) { + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + number = toNumber(number); + return baseInRange(number, start, end); + } + + /** + * Produces a random number between the inclusive `lower` and `upper` bounds. + * If only one argument is provided a number between `0` and the given number + * is returned. If `floating` is `true`, or either `lower` or `upper` are + * floats, a floating-point number is returned instead of an integer. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Number + * @param {number} [lower=0] The lower bound. + * @param {number} [upper=1] The upper bound. + * @param {boolean} [floating] Specify returning a floating-point number. + * @returns {number} Returns the random number. + * @example + * + * _.random(0, 5); + * // => an integer between 0 and 5 + * + * _.random(5); + * // => also an integer between 0 and 5 + * + * _.random(5, true); + * // => a floating-point number between 0 and 5 + * + * _.random(1.2, 5.2); + * // => a floating-point number between 1.2 and 5.2 + */ + function random(lower, upper, floating) { + if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { + upper = floating = undefined; + } + if (floating === undefined) { + if (typeof upper == 'boolean') { + floating = upper; + upper = undefined; + } + else if (typeof lower == 'boolean') { + floating = lower; + lower = undefined; + } + } + if (lower === undefined && upper === undefined) { + lower = 0; + upper = 1; + } + else { + lower = toFinite(lower); + if (upper === undefined) { + upper = lower; + lower = 0; + } else { + upper = toFinite(upper); + } + } + if (lower > upper) { + var temp = lower; + lower = upper; + upper = temp; + } + if (floating || lower % 1 || upper % 1) { + var rand = nativeRandom(); + return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); + } + return baseRandom(lower, upper); + } + + /*------------------------------------------------------------------------*/ + + /** + * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the camel cased string. + * @example + * + * _.camelCase('Foo Bar'); + * // => 'fooBar' + * + * _.camelCase('--foo-bar--'); + * // => 'fooBar' + * + * _.camelCase('__FOO_BAR__'); + * // => 'fooBar' + */ + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? capitalize(word) : word); + }); + + /** + * Converts the first character of `string` to upper case and the remaining + * to lower case. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example + * + * _.capitalize('FRED'); + * // => 'Fred' + */ + function capitalize(string) { + return upperFirst(toString(string).toLowerCase()); + } + + /** + * Deburrs `string` by converting + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing + * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to deburr. + * @returns {string} Returns the deburred string. + * @example + * + * _.deburr('déjà vu'); + * // => 'deja vu' + */ + function deburr(string) { + string = toString(string); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); + } + + /** + * Checks if `string` ends with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search up to. + * @returns {boolean} Returns `true` if `string` ends with `target`, + * else `false`. + * @example + * + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true + */ + function endsWith(string, target, position) { + string = toString(string); + target = baseToString(target); + + var length = string.length; + position = position === undefined + ? length + : baseClamp(toInteger(position), 0, length); + + var end = position; + position -= target.length; + return position >= 0 && string.slice(position, end) == target; + } + + /** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /** + * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", + * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' + */ + function escapeRegExp(string) { + string = toString(string); + return (string && reHasRegExpChar.test(string)) + ? string.replace(reRegExpChar, '\\$&') + : string; + } + + /** + * Converts `string` to + * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. + * @example + * + * _.kebabCase('Foo Bar'); + * // => 'foo-bar' + * + * _.kebabCase('fooBar'); + * // => 'foo-bar' + * + * _.kebabCase('__FOO_BAR__'); + * // => 'foo-bar' + */ + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); + }); + + /** + * Converts `string`, as space separated words, to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the lower cased string. + * @example + * + * _.lowerCase('--Foo-Bar--'); + * // => 'foo bar' + * + * _.lowerCase('fooBar'); + * // => 'foo bar' + * + * _.lowerCase('__FOO_BAR__'); + * // => 'foo bar' + */ + var lowerCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + word.toLowerCase(); + }); + + /** + * Converts the first character of `string` to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.lowerFirst('Fred'); + * // => 'fred' + * + * _.lowerFirst('FRED'); + * // => 'fRED' + */ + var lowerFirst = createCaseFirst('toLowerCase'); + + /** + * Pads `string` on the left and right sides if it's shorter than `length`. + * Padding characters are truncated if they can't be evenly divided by `length`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.pad('abc', 8); + * // => ' abc ' + * + * _.pad('abc', 8, '_-'); + * // => '_-abc_-_' + * + * _.pad('abc', 3); + * // => 'abc' + */ + function pad(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + if (!length || strLength >= length) { + return string; + } + var mid = (length - strLength) / 2; + return ( + createPadding(nativeFloor(mid), chars) + + string + + createPadding(nativeCeil(mid), chars) + ); + } + + /** + * Pads `string` on the right side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padEnd('abc', 6); + * // => 'abc ' + * + * _.padEnd('abc', 6, '_-'); + * // => 'abc_-_' + * + * _.padEnd('abc', 3); + * // => 'abc' + */ + function padEnd(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (string + createPadding(length - strLength, chars)) + : string; + } + + /** + * Pads `string` on the left side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padStart('abc', 6); + * // => ' abc' + * + * _.padStart('abc', 6, '_-'); + * // => '_-_abc' + * + * _.padStart('abc', 3); + * // => 'abc' + */ + function padStart(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (createPadding(length - strLength, chars) + string) + : string; + } + + /** + * Converts `string` to an integer of the specified radix. If `radix` is + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a + * hexadecimal, in which case a `radix` of `16` is used. + * + * **Note:** This method aligns with the + * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category String + * @param {string} string The string to convert. + * @param {number} [radix=10] The radix to interpret `value` by. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {number} Returns the converted integer. + * @example + * + * _.parseInt('08'); + * // => 8 + * + * _.map(['6', '08', '10'], _.parseInt); + * // => [6, 8, 10] + */ + function parseInt(string, radix, guard) { + if (guard || radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0); + } + + /** + * Repeats the given string `n` times. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to repeat. + * @param {number} [n=1] The number of times to repeat the string. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the repeated string. + * @example + * + * _.repeat('*', 3); + * // => '***' + * + * _.repeat('abc', 2); + * // => 'abcabc' + * + * _.repeat('abc', 0); + * // => '' + */ + function repeat(string, n, guard) { + if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + return baseRepeat(toString(string), n); + } + + /** + * Replaces matches for `pattern` in `string` with `replacement`. + * + * **Note:** This method is based on + * [`String#replace`](https://mdn.io/String/replace). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to modify. + * @param {RegExp|string} pattern The pattern to replace. + * @param {Function|string} replacement The match replacement. + * @returns {string} Returns the modified string. + * @example + * + * _.replace('Hi Fred', 'Fred', 'Barney'); + * // => 'Hi Barney' + */ + function replace() { + var args = arguments, + string = toString(args[0]); + + return args.length < 3 ? string : string.replace(args[1], args[2]); + } + + /** + * Converts `string` to + * [snake case](https://en.wikipedia.org/wiki/Snake_case). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the snake cased string. + * @example + * + * _.snakeCase('Foo Bar'); + * // => 'foo_bar' + * + * _.snakeCase('fooBar'); + * // => 'foo_bar' + * + * _.snakeCase('--FOO-BAR--'); + * // => 'foo_bar' + */ + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); + + /** + * Splits `string` by `separator`. + * + * **Note:** This method is based on + * [`String#split`](https://mdn.io/String/split). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to split. + * @param {RegExp|string} separator The separator pattern to split by. + * @param {number} [limit] The length to truncate results to. + * @returns {Array} Returns the string segments. + * @example + * + * _.split('a-b-c', '-', 2); + * // => ['a', 'b'] + */ + function split(string, separator, limit) { + if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { + separator = limit = undefined; + } + limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; + if (!limit) { + return []; + } + string = toString(string); + if (string && ( + typeof separator == 'string' || + (separator != null && !isRegExp(separator)) + )) { + separator = baseToString(separator); + if (!separator && hasUnicode(string)) { + return castSlice(stringToArray(string), 0, limit); + } + } + return string.split(separator, limit); + } + + /** + * Converts `string` to + * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). + * + * @static + * @memberOf _ + * @since 3.1.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the start cased string. + * @example + * + * _.startCase('--foo-bar--'); + * // => 'Foo Bar' + * + * _.startCase('fooBar'); + * // => 'Foo Bar' + * + * _.startCase('__FOO_BAR__'); + * // => 'FOO BAR' + */ + var startCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + upperFirst(word); + }); + + /** + * Checks if `string` starts with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=0] The position to search from. + * @returns {boolean} Returns `true` if `string` starts with `target`, + * else `false`. + * @example + * + * _.startsWith('abc', 'a'); + * // => true + * + * _.startsWith('abc', 'b'); + * // => false + * + * _.startsWith('abc', 'b', 1); + * // => true + */ + function startsWith(string, target, position) { + string = toString(string); + position = position == null + ? 0 + : baseClamp(toInteger(position), 0, string.length); + + target = baseToString(target); + return string.slice(position, position + target.length) == target; + } + + /** + * Creates a compiled template function that can interpolate data properties + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is given, it takes precedence over `_.templateSettings` values. + * + * **Note:** In the development build `_.template` utilizes + * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for easier debugging. + * + * For more information on precompiling templates see + * [lodash's custom builds documentation](https://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The template string. + * @param {Object} [options={}] The options object. + * @param {RegExp} [options.escape=_.templateSettings.escape] + * The HTML "escape" delimiter. + * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] + * The "evaluate" delimiter. + * @param {Object} [options.imports=_.templateSettings.imports] + * An object to import into the template as free variables. + * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] + * The "interpolate" delimiter. + * @param {string} [options.sourceURL='lodash.templateSources[n]'] + * The sourceURL of the compiled template. + * @param {string} [options.variable='obj'] + * The data object variable name. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the compiled template function. + * @example + * + * // Use the "interpolate" delimiter to create a compiled template. + * var compiled = _.template('hello <%= user %>!'); + * compiled({ 'user': 'fred' }); + * // => 'hello fred!' + * + * // Use the HTML "escape" delimiter to escape data property values. + * var compiled = _.template('<%- value %>'); + * compiled({ 'value': '