You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
54148 lines
1.5 MiB
54148 lines
1.5 MiB
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var $ = require('./util/preconditions');
|
|
var errors = require('./errors');
|
|
var Base58Check = require('./encoding/base58check');
|
|
var Networks = require('./networks');
|
|
var Hash = require('./crypto/hash');
|
|
var JSUtil = require('./util/js');
|
|
var PublicKey = require('./publickey');
|
|
|
|
/**
|
|
* Instantiate an address from an address String or Buffer, a public key or script hash Buffer,
|
|
* or an instance of {@link PublicKey} or {@link Script}.
|
|
*
|
|
* This is an immutable class, and if the first parameter provided to this constructor is an
|
|
* `Address` instance, the same argument will be returned.
|
|
*
|
|
* An address has two key properties: `network` and `type`. The type is either
|
|
* `Address.PayToPublicKeyHash` (value is the `'pubkeyhash'` string)
|
|
* or `Address.PayToScriptHash` (the string `'scripthash'`). The network is an instance of {@link Network}.
|
|
* You can quickly check whether an address is of a given kind by using the methods
|
|
* `isPayToPublicKeyHash` and `isPayToScriptHash`
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* // validate that an input field is valid
|
|
* var error = Address.getValidationError(input, 'testnet');
|
|
* if (!error) {
|
|
* var address = Address(input, 'testnet');
|
|
* } else {
|
|
* // invalid network or checksum (typo?)
|
|
* var message = error.messsage;
|
|
* }
|
|
*
|
|
* // get an address from a public key
|
|
* var address = Address(publicKey, 'testnet').toString();
|
|
* ```
|
|
*
|
|
* @param {*} data - The encoded data in various formats
|
|
* @param {Network|String|number=} network - The network: 'livenet' or 'testnet'
|
|
* @param {string=} type - The type of address: 'script' or 'pubkey'
|
|
* @returns {Address} A new valid and frozen instance of an Address
|
|
* @constructor
|
|
*/
|
|
function Address(data, network, type) {
|
|
/* jshint maxcomplexity: 12 */
|
|
/* jshint maxstatements: 20 */
|
|
|
|
if (!(this instanceof Address)) {
|
|
return new Address(data, network, type);
|
|
}
|
|
|
|
if (_.isArray(data) && _.isNumber(network)) {
|
|
return Address.createMultisig(data, network, type);
|
|
}
|
|
|
|
if (data instanceof Address) {
|
|
// Immutable instance
|
|
return data;
|
|
}
|
|
|
|
$.checkArgument(data, 'First argument is required, please include address data.', 'guide/address.html');
|
|
|
|
if (network && !Networks.get(network)) {
|
|
throw new TypeError('Second argument must be "livenet" or "testnet".');
|
|
}
|
|
|
|
if (type && (type !== Address.PayToPublicKeyHash && type !== Address.PayToScriptHash)) {
|
|
throw new TypeError('Third argument must be "pubkeyhash" or "scripthash".');
|
|
}
|
|
|
|
var info = this._classifyArguments(data, network, type);
|
|
|
|
// set defaults if not set
|
|
info.network = info.network || Networks.get(network) || Networks.defaultNetwork;
|
|
info.type = info.type || type || Address.PayToPublicKeyHash;
|
|
|
|
JSUtil.defineImmutable(this, {
|
|
hashBuffer: info.hashBuffer,
|
|
network: info.network,
|
|
type: info.type
|
|
});
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Internal function used to split different kinds of arguments of the constructor
|
|
* @param {*} data - The encoded data in various formats
|
|
* @param {Network|String|number=} network - The network: 'livenet' or 'testnet'
|
|
* @param {string=} type - The type of address: 'script' or 'pubkey'
|
|
* @returns {Object} An "info" object with "type", "network", and "hashBuffer"
|
|
*/
|
|
Address.prototype._classifyArguments = function(data, network, type) {
|
|
/* jshint maxcomplexity: 10 */
|
|
// transform and validate input data
|
|
if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 20) {
|
|
return Address._transformHash(data);
|
|
} else if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 21) {
|
|
return Address._transformBuffer(data, network, type);
|
|
} else if (data instanceof PublicKey) {
|
|
return Address._transformPublicKey(data);
|
|
} else if (data instanceof Script) {
|
|
return Address._transformScript(data, network);
|
|
} else if (typeof(data) === 'string') {
|
|
return Address._transformString(data, network, type);
|
|
} else if (_.isObject(data)) {
|
|
return Address._transformObject(data);
|
|
} else {
|
|
throw new TypeError('First argument is an unrecognized data format.');
|
|
}
|
|
};
|
|
|
|
/** @static */
|
|
Address.PayToPublicKeyHash = 'pubkeyhash';
|
|
/** @static */
|
|
Address.PayToScriptHash = 'scripthash';
|
|
|
|
/**
|
|
* @param {Buffer} hash - An instance of a hash Buffer
|
|
* @returns {Object} An object with keys: hashBuffer
|
|
* @private
|
|
*/
|
|
Address._transformHash = function(hash) {
|
|
var info = {};
|
|
if (!(hash instanceof Buffer) && !(hash instanceof Uint8Array)) {
|
|
throw new TypeError('Address supplied is not a buffer.');
|
|
}
|
|
if (hash.length !== 20) {
|
|
throw new TypeError('Address hashbuffers must be exactly 20 bytes.');
|
|
}
|
|
info.hashBuffer = hash;
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Deserializes an address serialized through `Address#toObject()`
|
|
* @param {Object} data
|
|
* @param {string} data.hash - the hash that this address encodes
|
|
* @param {string} data.type - either 'pubkeyhash' or 'scripthash'
|
|
* @param {Network=} data.network - the name of the network associated
|
|
* @return {Address}
|
|
*/
|
|
Address._transformObject = function(data) {
|
|
$.checkArgument(data.hash || data.hashBuffer, 'Must provide a `hash` or `hashBuffer` property');
|
|
$.checkArgument(data.type, 'Must provide a `type` property');
|
|
return {
|
|
hashBuffer: data.hash ? new Buffer(data.hash, 'hex') : data.hashBuffer,
|
|
network: Networks.get(data.network) || Networks.defaultNetwork,
|
|
type: data.type
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Internal function to discover the network and type based on the first data byte
|
|
*
|
|
* @param {Buffer} buffer - An instance of a hex encoded address Buffer
|
|
* @returns {Object} An object with keys: network and type
|
|
* @private
|
|
*/
|
|
Address._classifyFromVersion = function(buffer) {
|
|
var version = {};
|
|
|
|
var pubkeyhashNetwork = Networks.get(buffer[0], 'pubkeyhash');
|
|
var scripthashNetwork = Networks.get(buffer[0], 'scripthash');
|
|
|
|
if (pubkeyhashNetwork) {
|
|
version.network = pubkeyhashNetwork;
|
|
version.type = Address.PayToPublicKeyHash;
|
|
} else if (scripthashNetwork) {
|
|
version.network = scripthashNetwork;
|
|
version.type = Address.PayToScriptHash;
|
|
}
|
|
|
|
return version;
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a bitcoin address buffer
|
|
*
|
|
* @param {Buffer} buffer - An instance of a hex encoded address Buffer
|
|
* @param {string=} network - The network: 'livenet' or 'testnet'
|
|
* @param {string=} type - The type: 'pubkeyhash' or 'scripthash'
|
|
* @returns {Object} An object with keys: hashBuffer, network and type
|
|
* @private
|
|
*/
|
|
Address._transformBuffer = function(buffer, network, type) {
|
|
/* jshint maxcomplexity: 9 */
|
|
var info = {};
|
|
if (!(buffer instanceof Buffer) && !(buffer instanceof Uint8Array)) {
|
|
throw new TypeError('Address supplied is not a buffer.');
|
|
}
|
|
if (buffer.length !== 1 + 20) {
|
|
throw new TypeError('Address buffers must be exactly 21 bytes.');
|
|
}
|
|
|
|
var networkObj = Networks.get(network);
|
|
var bufferVersion = Address._classifyFromVersion(buffer);
|
|
|
|
if (network && !networkObj) {
|
|
throw new TypeError('Unknown network');
|
|
}
|
|
|
|
if (!bufferVersion.network || (networkObj && networkObj !== bufferVersion.network)) {
|
|
throw new TypeError('Address has mismatched network type.');
|
|
}
|
|
|
|
if (!bufferVersion.type || (type && type !== bufferVersion.type)) {
|
|
throw new TypeError('Address has mismatched type.');
|
|
}
|
|
|
|
info.hashBuffer = buffer.slice(1);
|
|
info.network = bufferVersion.network;
|
|
info.type = bufferVersion.type;
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a {@link PublicKey}
|
|
*
|
|
* @param {PublicKey} pubkey - An instance of PublicKey
|
|
* @returns {Object} An object with keys: hashBuffer, type
|
|
* @private
|
|
*/
|
|
Address._transformPublicKey = function(pubkey) {
|
|
var info = {};
|
|
if (!(pubkey instanceof PublicKey)) {
|
|
throw new TypeError('Address must be an instance of PublicKey.');
|
|
}
|
|
info.hashBuffer = Hash.sha256ripemd160(pubkey.toBuffer());
|
|
info.type = Address.PayToPublicKeyHash;
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a {@link Script} into a `info` object.
|
|
*
|
|
* @param {Script} script - An instance of Script
|
|
* @returns {Object} An object with keys: hashBuffer, type
|
|
* @private
|
|
*/
|
|
Address._transformScript = function(script, network) {
|
|
$.checkArgument(script instanceof Script, 'script must be a Script instance');
|
|
var info = script.getAddressInfo(network);
|
|
if (!info) {
|
|
throw new errors.Script.CantDeriveAddress(script);
|
|
}
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Creates a P2SH address from a set of public keys and a threshold.
|
|
*
|
|
* The addresses will be sorted lexicographically, as that is the trend in bitcoin.
|
|
* To create an address from unsorted public keys, use the {@link Script#buildMultisigOut}
|
|
* interface.
|
|
*
|
|
* @param {Array} publicKeys - a set of public keys to create an address
|
|
* @param {number} threshold - the number of signatures needed to release the funds
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @return {Address}
|
|
*/
|
|
Address.createMultisig = function(publicKeys, threshold, network) {
|
|
network = network || publicKeys[0].network || Networks.defaultNetwork;
|
|
return Address.payingTo(Script.buildMultisigOut(publicKeys, threshold), network);
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a bitcoin address string
|
|
*
|
|
* @param {string} data
|
|
* @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @param {string=} type - The type: 'pubkeyhash' or 'scripthash'
|
|
* @returns {Object} An object with keys: hashBuffer, network and type
|
|
* @private
|
|
*/
|
|
Address._transformString = function(data, network, type) {
|
|
if (typeof(data) !== 'string') {
|
|
throw new TypeError('data parameter supplied is not a string.');
|
|
}
|
|
data = data.trim();
|
|
var addressBuffer = Base58Check.decode(data);
|
|
var info = Address._transformBuffer(addressBuffer, network, type);
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Instantiate an address from a PublicKey instance
|
|
*
|
|
* @param {PublicKey} data
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @returns {Address} A new valid and frozen instance of an Address
|
|
*/
|
|
Address.fromPublicKey = function(data, network) {
|
|
var info = Address._transformPublicKey(data);
|
|
network = network || Networks.defaultNetwork;
|
|
return new Address(info.hashBuffer, network, info.type);
|
|
};
|
|
|
|
/**
|
|
* Instantiate an address from a ripemd160 public key hash
|
|
*
|
|
* @param {Buffer} hash - An instance of buffer of the hash
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @returns {Address} A new valid and frozen instance of an Address
|
|
*/
|
|
Address.fromPublicKeyHash = function(hash, network) {
|
|
var info = Address._transformHash(hash);
|
|
return new Address(info.hashBuffer, network, Address.PayToPublicKeyHash);
|
|
};
|
|
|
|
/**
|
|
* Instantiate an address from a ripemd160 script hash
|
|
*
|
|
* @param {Buffer} hash - An instance of buffer of the hash
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @returns {Address} A new valid and frozen instance of an Address
|
|
*/
|
|
Address.fromScriptHash = function(hash, network) {
|
|
$.checkArgument(hash, 'hash parameter is required');
|
|
var info = Address._transformHash(hash);
|
|
return new Address(info.hashBuffer, network, Address.PayToScriptHash);
|
|
};
|
|
|
|
/**
|
|
* Builds a p2sh address paying to script. This will hash the script and
|
|
* use that to create the address.
|
|
* If you want to extract an address associated with a script instead,
|
|
* see {{Address#fromScript}}
|
|
*
|
|
* @param {Script} script - An instance of Script
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @returns {Address} A new valid and frozen instance of an Address
|
|
*/
|
|
Address.payingTo = function(script, network) {
|
|
$.checkArgument(script, 'script is required');
|
|
$.checkArgument(script instanceof Script, 'script must be instance of Script');
|
|
|
|
return Address.fromScriptHash(Hash.sha256ripemd160(script.toBuffer()), network);
|
|
};
|
|
|
|
/**
|
|
* Extract address from a Script. The script must be of one
|
|
* of the following types: p2pkh input, p2pkh output, p2sh input
|
|
* or p2sh output.
|
|
* This will analyze the script and extract address information from it.
|
|
* If you want to transform any script to a p2sh Address paying
|
|
* to that script's hash instead, use {{Address#payingTo}}
|
|
*
|
|
* @param {Script} script - An instance of Script
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @returns {Address} A new valid and frozen instance of an Address
|
|
*/
|
|
Address.fromScript = function(script, network) {
|
|
$.checkArgument(script instanceof Script, 'script must be a Script instance');
|
|
var info = Address._transformScript(script, network);
|
|
return new Address(info.hashBuffer, network, info.type);
|
|
};
|
|
|
|
/**
|
|
* Instantiate an address from a buffer of the address
|
|
*
|
|
* @param {Buffer} buffer - An instance of buffer of the address
|
|
* @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @param {string=} type - The type of address: 'script' or 'pubkey'
|
|
* @returns {Address} A new valid and frozen instance of an Address
|
|
*/
|
|
Address.fromBuffer = function(buffer, network, type) {
|
|
var info = Address._transformBuffer(buffer, network, type);
|
|
return new Address(info.hashBuffer, info.network, info.type);
|
|
};
|
|
|
|
/**
|
|
* Instantiate an address from an address string
|
|
*
|
|
* @param {string} str - An string of the bitcoin address
|
|
* @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @param {string=} type - The type of address: 'script' or 'pubkey'
|
|
* @returns {Address} A new valid and frozen instance of an Address
|
|
*/
|
|
Address.fromString = function(str, network, type) {
|
|
var info = Address._transformString(str, network, type);
|
|
return new Address(info.hashBuffer, info.network, info.type);
|
|
};
|
|
|
|
/**
|
|
* Instantiate an address from an Object
|
|
*
|
|
* @param {string} json - An JSON string or Object with keys: hash, network and type
|
|
* @returns {Address} A new valid instance of an Address
|
|
*/
|
|
Address.fromObject = function fromObject(obj) {
|
|
$.checkState(
|
|
JSUtil.isHexa(obj.hash),
|
|
'Unexpected hash property, "' + obj.hash + '", expected to be hex.'
|
|
);
|
|
var hashBuffer = new Buffer(obj.hash, 'hex');
|
|
return new Address(hashBuffer, obj.network, obj.type);
|
|
};
|
|
|
|
/**
|
|
* Will return a validation error if exists
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* // a network mismatch error
|
|
* var error = Address.getValidationError('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'testnet');
|
|
* ```
|
|
*
|
|
* @param {string} data - The encoded data
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @param {string} type - The type of address: 'script' or 'pubkey'
|
|
* @returns {null|Error} The corresponding error message
|
|
*/
|
|
Address.getValidationError = function(data, network, type) {
|
|
var error;
|
|
try {
|
|
/* jshint nonew: false */
|
|
new Address(data, network, type);
|
|
} catch (e) {
|
|
error = e;
|
|
}
|
|
return error;
|
|
};
|
|
|
|
/**
|
|
* Will return a boolean if an address is valid
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* assert(Address.isValid('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'livenet'));
|
|
* ```
|
|
*
|
|
* @param {string} data - The encoded data
|
|
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet'
|
|
* @param {string} type - The type of address: 'script' or 'pubkey'
|
|
* @returns {boolean} The corresponding error message
|
|
*/
|
|
Address.isValid = function(data, network, type) {
|
|
return !Address.getValidationError(data, network, type);
|
|
};
|
|
|
|
/**
|
|
* Returns true if an address is of pay to public key hash type
|
|
* @return boolean
|
|
*/
|
|
Address.prototype.isPayToPublicKeyHash = function() {
|
|
return this.type === Address.PayToPublicKeyHash;
|
|
};
|
|
|
|
/**
|
|
* Returns true if an address is of pay to script hash type
|
|
* @return boolean
|
|
*/
|
|
Address.prototype.isPayToScriptHash = function() {
|
|
return this.type === Address.PayToScriptHash;
|
|
};
|
|
|
|
/**
|
|
* Will return a buffer representation of the address
|
|
*
|
|
* @returns {Buffer} Bitcoin address buffer
|
|
*/
|
|
Address.prototype.toBuffer = function() {
|
|
var version = new Buffer([this.network[this.type]]);
|
|
var buf = Buffer.concat([version, this.hashBuffer]);
|
|
return buf;
|
|
};
|
|
|
|
/**
|
|
* @returns {Object} A plain object with the address information
|
|
*/
|
|
Address.prototype.toObject = Address.prototype.toJSON = function toObject() {
|
|
return {
|
|
hash: this.hashBuffer.toString('hex'),
|
|
type: this.type,
|
|
network: this.network.toString()
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Will return a the string representation of the address
|
|
*
|
|
* @returns {string} Bitcoin address
|
|
*/
|
|
Address.prototype.toString = function() {
|
|
return Base58Check.encode(this.toBuffer());
|
|
};
|
|
|
|
/**
|
|
* Will return a string formatted for the console
|
|
*
|
|
* @returns {string} Bitcoin address
|
|
*/
|
|
Address.prototype.inspect = function() {
|
|
return '<Address: ' + this.toString() + ', type: ' + this.type + ', network: ' + this.network + '>';
|
|
};
|
|
|
|
module.exports = Address;
|
|
|
|
var Script = require('./script');
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./crypto/hash":8,"./encoding/base58check":13,"./errors":17,"./networks":21,"./publickey":24,"./script":25,"./util/js":43,"./util/preconditions":44,"buffer":47,"lodash":319}],2:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var BlockHeader = require('./blockheader');
|
|
var BN = require('../crypto/bn');
|
|
var BufferUtil = require('../util/buffer');
|
|
var BufferReader = require('../encoding/bufferreader');
|
|
var BufferWriter = require('../encoding/bufferwriter');
|
|
var Hash = require('../crypto/hash');
|
|
var Transaction = require('../transaction');
|
|
var $ = require('../util/preconditions');
|
|
|
|
/**
|
|
* Instantiate a Block from a Buffer, JSON object, or Object with
|
|
* the properties of the Block
|
|
*
|
|
* @param {*} - A Buffer, JSON string, or Object
|
|
* @returns {Block}
|
|
* @constructor
|
|
*/
|
|
function Block(arg) {
|
|
if (!(this instanceof Block)) {
|
|
return new Block(arg);
|
|
}
|
|
_.extend(this, Block._from(arg));
|
|
return this;
|
|
}
|
|
|
|
// https://github.com/bitcoin/bitcoin/blob/b5fa132329f0377d787a4a21c1686609c2bfaece/src/primitives/block.h#L14
|
|
Block.MAX_BLOCK_SIZE = 1000000;
|
|
|
|
/**
|
|
* @param {*} - A Buffer, JSON string or Object
|
|
* @returns {Object} - An object representing block data
|
|
* @throws {TypeError} - If the argument was not recognized
|
|
* @private
|
|
*/
|
|
Block._from = function _from(arg) {
|
|
var info = {};
|
|
if (BufferUtil.isBuffer(arg)) {
|
|
info = Block._fromBufferReader(BufferReader(arg));
|
|
} else if (_.isObject(arg)) {
|
|
info = Block._fromObject(arg);
|
|
} else {
|
|
throw new TypeError('Unrecognized argument for Block');
|
|
}
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* @param {Object} - A plain JavaScript object
|
|
* @returns {Object} - An object representing block data
|
|
* @private
|
|
*/
|
|
Block._fromObject = function _fromObject(data) {
|
|
var transactions = [];
|
|
data.transactions.forEach(function(tx) {
|
|
if (tx instanceof Transaction) {
|
|
transactions.push(tx);
|
|
} else {
|
|
transactions.push(Transaction().fromObject(tx));
|
|
}
|
|
});
|
|
var info = {
|
|
header: BlockHeader.fromObject(data.header),
|
|
transactions: transactions
|
|
};
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* @param {Object} - A plain JavaScript object
|
|
* @returns {Block} - An instance of block
|
|
*/
|
|
Block.fromObject = function fromObject(obj) {
|
|
var info = Block._fromObject(obj);
|
|
return new Block(info);
|
|
};
|
|
|
|
/**
|
|
* @param {BufferReader} - Block data
|
|
* @returns {Object} - An object representing the block data
|
|
* @private
|
|
*/
|
|
Block._fromBufferReader = function _fromBufferReader(br) {
|
|
var info = {};
|
|
$.checkState(!br.finished(), 'No block data received');
|
|
info.header = BlockHeader.fromBufferReader(br);
|
|
var transactions = br.readVarintNum();
|
|
info.transactions = [];
|
|
for (var i = 0; i < transactions; i++) {
|
|
info.transactions.push(Transaction().fromBufferReader(br));
|
|
}
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* @param {BufferReader} - A buffer reader of the block
|
|
* @returns {Block} - An instance of block
|
|
*/
|
|
Block.fromBufferReader = function fromBufferReader(br) {
|
|
$.checkArgument(br, 'br is required');
|
|
var info = Block._fromBufferReader(br);
|
|
return new Block(info);
|
|
};
|
|
|
|
/**
|
|
* @param {Buffer} - A buffer of the block
|
|
* @returns {Block} - An instance of block
|
|
*/
|
|
Block.fromBuffer = function fromBuffer(buf) {
|
|
return Block.fromBufferReader(new BufferReader(buf));
|
|
};
|
|
|
|
/**
|
|
* @param {string} - str - A hex encoded string of the block
|
|
* @returns {Block} - A hex encoded string of the block
|
|
*/
|
|
Block.fromString = function fromString(str) {
|
|
var buf = new Buffer(str, 'hex');
|
|
return Block.fromBuffer(buf);
|
|
};
|
|
|
|
/**
|
|
* @param {Binary} - Raw block binary data or buffer
|
|
* @returns {Block} - An instance of block
|
|
*/
|
|
Block.fromRawBlock = function fromRawBlock(data) {
|
|
if (!BufferUtil.isBuffer(data)) {
|
|
data = new Buffer(data, 'binary');
|
|
}
|
|
var br = BufferReader(data);
|
|
br.pos = Block.Values.START_OF_BLOCK;
|
|
var info = Block._fromBufferReader(br);
|
|
return new Block(info);
|
|
};
|
|
|
|
/**
|
|
* @returns {Object} - A plain object with the block properties
|
|
*/
|
|
Block.prototype.toObject = Block.prototype.toJSON = function toObject() {
|
|
var transactions = [];
|
|
this.transactions.forEach(function(tx) {
|
|
transactions.push(tx.toObject());
|
|
});
|
|
return {
|
|
header: this.header.toObject(),
|
|
transactions: transactions
|
|
};
|
|
};
|
|
|
|
/**
|
|
* @returns {Buffer} - A buffer of the block
|
|
*/
|
|
Block.prototype.toBuffer = function toBuffer() {
|
|
return this.toBufferWriter().concat();
|
|
};
|
|
|
|
/**
|
|
* @returns {string} - A hex encoded string of the block
|
|
*/
|
|
Block.prototype.toString = function toString() {
|
|
return this.toBuffer().toString('hex');
|
|
};
|
|
|
|
/**
|
|
* @param {BufferWriter} - An existing instance of BufferWriter
|
|
* @returns {BufferWriter} - An instance of BufferWriter representation of the Block
|
|
*/
|
|
Block.prototype.toBufferWriter = function toBufferWriter(bw) {
|
|
if (!bw) {
|
|
bw = new BufferWriter();
|
|
}
|
|
bw.write(this.header.toBuffer());
|
|
bw.writeVarintNum(this.transactions.length);
|
|
for (var i = 0; i < this.transactions.length; i++) {
|
|
this.transactions[i].toBufferWriter(bw);
|
|
}
|
|
return bw;
|
|
};
|
|
|
|
/**
|
|
* Will iterate through each transaction and return an array of hashes
|
|
* @returns {Array} - An array with transaction hashes
|
|
*/
|
|
Block.prototype.getTransactionHashes = function getTransactionHashes() {
|
|
var hashes = [];
|
|
if (this.transactions.length === 0) {
|
|
return [Block.Values.NULL_HASH];
|
|
}
|
|
for (var t = 0; t < this.transactions.length; t++) {
|
|
hashes.push(this.transactions[t]._getHash());
|
|
}
|
|
return hashes;
|
|
};
|
|
|
|
/**
|
|
* Will build a merkle tree of all the transactions, ultimately arriving at
|
|
* a single point, the merkle root.
|
|
* @link https://en.bitcoin.it/wiki/Protocol_specification#Merkle_Trees
|
|
* @returns {Array} - An array with each level of the tree after the other.
|
|
*/
|
|
Block.prototype.getMerkleTree = function getMerkleTree() {
|
|
|
|
var tree = this.getTransactionHashes();
|
|
|
|
var j = 0;
|
|
for (var size = this.transactions.length; size > 1; size = Math.floor((size + 1) / 2)) {
|
|
for (var i = 0; i < size; i += 2) {
|
|
var i2 = Math.min(i + 1, size - 1);
|
|
var buf = Buffer.concat([tree[j + i], tree[j + i2]]);
|
|
tree.push(Hash.sha256sha256(buf));
|
|
}
|
|
j += size;
|
|
}
|
|
|
|
return tree;
|
|
};
|
|
|
|
/**
|
|
* Calculates the merkleRoot from the transactions.
|
|
* @returns {Buffer} - A buffer of the merkle root hash
|
|
*/
|
|
Block.prototype.getMerkleRoot = function getMerkleRoot() {
|
|
var tree = this.getMerkleTree();
|
|
return tree[tree.length - 1];
|
|
};
|
|
|
|
/**
|
|
* Verifies that the transactions in the block match the header merkle root
|
|
* @returns {Boolean} - If the merkle roots match
|
|
*/
|
|
Block.prototype.validMerkleRoot = function validMerkleRoot() {
|
|
|
|
var h = new BN(this.header.merkleRoot.toString('hex'), 'hex');
|
|
var c = new BN(this.getMerkleRoot().toString('hex'), 'hex');
|
|
|
|
if (h.cmp(c) !== 0) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* @returns {Buffer} - The little endian hash buffer of the header
|
|
*/
|
|
Block.prototype._getHash = function() {
|
|
return this.header._getHash();
|
|
};
|
|
|
|
var idProperty = {
|
|
configurable: false,
|
|
enumerable: true,
|
|
/**
|
|
* @returns {string} - The big endian hash buffer of the header
|
|
*/
|
|
get: function() {
|
|
if (!this._id) {
|
|
this._id = this.header.id;
|
|
}
|
|
return this._id;
|
|
},
|
|
set: _.noop
|
|
};
|
|
Object.defineProperty(Block.prototype, 'id', idProperty);
|
|
Object.defineProperty(Block.prototype, 'hash', idProperty);
|
|
|
|
/**
|
|
* @returns {string} - A string formatted for the console
|
|
*/
|
|
Block.prototype.inspect = function inspect() {
|
|
return '<Block ' + this.id + '>';
|
|
};
|
|
|
|
Block.Values = {
|
|
START_OF_BLOCK: 8, // Start of block in raw block data
|
|
NULL_HASH: new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
|
|
};
|
|
|
|
module.exports = Block;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../crypto/bn":6,"../crypto/hash":8,"../encoding/bufferreader":14,"../encoding/bufferwriter":15,"../transaction":28,"../util/buffer":42,"../util/preconditions":44,"./blockheader":3,"buffer":47,"lodash":319}],3:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var BN = require('../crypto/bn');
|
|
var BufferUtil = require('../util/buffer');
|
|
var BufferReader = require('../encoding/bufferreader');
|
|
var BufferWriter = require('../encoding/bufferwriter');
|
|
var Hash = require('../crypto/hash');
|
|
var JSUtil = require('../util/js');
|
|
var $ = require('../util/preconditions');
|
|
|
|
var GENESIS_BITS = 0x1d00ffff;
|
|
|
|
/**
|
|
* Instantiate a BlockHeader from a Buffer, JSON object, or Object with
|
|
* the properties of the BlockHeader
|
|
*
|
|
* @param {*} - A Buffer, JSON string, or Object
|
|
* @returns {BlockHeader} - An instance of block header
|
|
* @constructor
|
|
*/
|
|
var BlockHeader = function BlockHeader(arg) {
|
|
if (!(this instanceof BlockHeader)) {
|
|
return new BlockHeader(arg);
|
|
}
|
|
var info = BlockHeader._from(arg);
|
|
this.version = info.version;
|
|
this.prevHash = info.prevHash;
|
|
this.merkleRoot = info.merkleRoot;
|
|
this.time = info.time;
|
|
this.timestamp = info.time;
|
|
this.bits = info.bits;
|
|
this.nonce = info.nonce;
|
|
|
|
if (info.hash) {
|
|
$.checkState(
|
|
this.hash === info.hash,
|
|
'Argument object hash property does not match block hash.'
|
|
);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* @param {*} - A Buffer, JSON string or Object
|
|
* @returns {Object} - An object representing block header data
|
|
* @throws {TypeError} - If the argument was not recognized
|
|
* @private
|
|
*/
|
|
BlockHeader._from = function _from(arg) {
|
|
var info = {};
|
|
if (BufferUtil.isBuffer(arg)) {
|
|
info = BlockHeader._fromBufferReader(BufferReader(arg));
|
|
} else if (_.isObject(arg)) {
|
|
info = BlockHeader._fromObject(arg);
|
|
} else {
|
|
throw new TypeError('Unrecognized argument for BlockHeader');
|
|
}
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* @param {Object} - A JSON string
|
|
* @returns {Object} - An object representing block header data
|
|
* @private
|
|
*/
|
|
BlockHeader._fromObject = function _fromObject(data) {
|
|
$.checkArgument(data, 'data is required');
|
|
var prevHash = data.prevHash;
|
|
var merkleRoot = data.merkleRoot;
|
|
if (_.isString(data.prevHash)) {
|
|
prevHash = BufferUtil.reverse(new Buffer(data.prevHash, 'hex'));
|
|
}
|
|
if (_.isString(data.merkleRoot)) {
|
|
merkleRoot = BufferUtil.reverse(new Buffer(data.merkleRoot, 'hex'));
|
|
}
|
|
var info = {
|
|
hash: data.hash,
|
|
version: data.version,
|
|
prevHash: prevHash,
|
|
merkleRoot: merkleRoot,
|
|
time: data.time,
|
|
timestamp: data.time,
|
|
bits: data.bits,
|
|
nonce: data.nonce
|
|
};
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* @param {Object} - A plain JavaScript object
|
|
* @returns {BlockHeader} - An instance of block header
|
|
*/
|
|
BlockHeader.fromObject = function fromObject(obj) {
|
|
var info = BlockHeader._fromObject(obj);
|
|
return new BlockHeader(info);
|
|
};
|
|
|
|
/**
|
|
* @param {Binary} - Raw block binary data or buffer
|
|
* @returns {BlockHeader} - An instance of block header
|
|
*/
|
|
BlockHeader.fromRawBlock = function fromRawBlock(data) {
|
|
if (!BufferUtil.isBuffer(data)) {
|
|
data = new Buffer(data, 'binary');
|
|
}
|
|
var br = BufferReader(data);
|
|
br.pos = BlockHeader.Constants.START_OF_HEADER;
|
|
var info = BlockHeader._fromBufferReader(br);
|
|
return new BlockHeader(info);
|
|
};
|
|
|
|
/**
|
|
* @param {Buffer} - A buffer of the block header
|
|
* @returns {BlockHeader} - An instance of block header
|
|
*/
|
|
BlockHeader.fromBuffer = function fromBuffer(buf) {
|
|
var info = BlockHeader._fromBufferReader(BufferReader(buf));
|
|
return new BlockHeader(info);
|
|
};
|
|
|
|
/**
|
|
* @param {string} - A hex encoded buffer of the block header
|
|
* @returns {BlockHeader} - An instance of block header
|
|
*/
|
|
BlockHeader.fromString = function fromString(str) {
|
|
var buf = new Buffer(str, 'hex');
|
|
return BlockHeader.fromBuffer(buf);
|
|
};
|
|
|
|
/**
|
|
* @param {BufferReader} - A BufferReader of the block header
|
|
* @returns {Object} - An object representing block header data
|
|
* @private
|
|
*/
|
|
BlockHeader._fromBufferReader = function _fromBufferReader(br) {
|
|
var info = {};
|
|
info.version = br.readInt32LE();
|
|
info.prevHash = br.read(32);
|
|
info.merkleRoot = br.read(32);
|
|
info.time = br.readUInt32LE();
|
|
info.bits = br.readUInt32LE();
|
|
info.nonce = br.readUInt32LE();
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* @param {BufferReader} - A BufferReader of the block header
|
|
* @returns {BlockHeader} - An instance of block header
|
|
*/
|
|
BlockHeader.fromBufferReader = function fromBufferReader(br) {
|
|
var info = BlockHeader._fromBufferReader(br);
|
|
return new BlockHeader(info);
|
|
};
|
|
|
|
/**
|
|
* @returns {Object} - A plain object of the BlockHeader
|
|
*/
|
|
BlockHeader.prototype.toObject = BlockHeader.prototype.toJSON = function toObject() {
|
|
return {
|
|
hash: this.hash,
|
|
version: this.version,
|
|
prevHash: BufferUtil.reverse(this.prevHash).toString('hex'),
|
|
merkleRoot: BufferUtil.reverse(this.merkleRoot).toString('hex'),
|
|
time: this.time,
|
|
bits: this.bits,
|
|
nonce: this.nonce
|
|
};
|
|
};
|
|
|
|
/**
|
|
* @returns {Buffer} - A Buffer of the BlockHeader
|
|
*/
|
|
BlockHeader.prototype.toBuffer = function toBuffer() {
|
|
return this.toBufferWriter().concat();
|
|
};
|
|
|
|
/**
|
|
* @returns {string} - A hex encoded string of the BlockHeader
|
|
*/
|
|
BlockHeader.prototype.toString = function toString() {
|
|
return this.toBuffer().toString('hex');
|
|
};
|
|
|
|
/**
|
|
* @param {BufferWriter} - An existing instance BufferWriter
|
|
* @returns {BufferWriter} - An instance of BufferWriter representation of the BlockHeader
|
|
*/
|
|
BlockHeader.prototype.toBufferWriter = function toBufferWriter(bw) {
|
|
if (!bw) {
|
|
bw = new BufferWriter();
|
|
}
|
|
bw.writeInt32LE(this.version);
|
|
bw.write(this.prevHash);
|
|
bw.write(this.merkleRoot);
|
|
bw.writeUInt32LE(this.time);
|
|
bw.writeUInt32LE(this.bits);
|
|
bw.writeUInt32LE(this.nonce);
|
|
return bw;
|
|
};
|
|
|
|
/**
|
|
* Returns the target difficulty for this block
|
|
* @param {Number} bits
|
|
* @returns {BN} An instance of BN with the decoded difficulty bits
|
|
*/
|
|
BlockHeader.prototype.getTargetDifficulty = function getTargetDifficulty(bits) {
|
|
bits = bits || this.bits;
|
|
|
|
var target = new BN(bits & 0xffffff);
|
|
var mov = 8 * ((bits >>> 24) - 3);
|
|
while (mov-- > 0) {
|
|
target = target.mul(new BN(2));
|
|
}
|
|
return target;
|
|
};
|
|
|
|
/**
|
|
* @link https://en.bitcoin.it/wiki/Difficulty
|
|
* @return {Number}
|
|
*/
|
|
BlockHeader.prototype.getDifficulty = function getDifficulty() {
|
|
var difficulty1TargetBN = this.getTargetDifficulty(GENESIS_BITS).mul(new BN(Math.pow(10, 8)));
|
|
var currentTargetBN = this.getTargetDifficulty();
|
|
|
|
var difficultyString = difficulty1TargetBN.div(currentTargetBN).toString(10);
|
|
var decimalPos = difficultyString.length - 8;
|
|
difficultyString = difficultyString.slice(0, decimalPos) + '.' + difficultyString.slice(decimalPos);
|
|
|
|
return parseFloat(difficultyString);
|
|
};
|
|
|
|
/**
|
|
* @returns {Buffer} - The little endian hash buffer of the header
|
|
*/
|
|
BlockHeader.prototype._getHash = function hash() {
|
|
var buf = this.toBuffer();
|
|
return Hash.sha256sha256(buf);
|
|
};
|
|
|
|
var idProperty = {
|
|
configurable: false,
|
|
enumerable: true,
|
|
/**
|
|
* @returns {string} - The big endian hash buffer of the header
|
|
*/
|
|
get: function() {
|
|
if (!this._id) {
|
|
this._id = BufferReader(this._getHash()).readReverse().toString('hex');
|
|
}
|
|
return this._id;
|
|
},
|
|
set: _.noop
|
|
};
|
|
Object.defineProperty(BlockHeader.prototype, 'id', idProperty);
|
|
Object.defineProperty(BlockHeader.prototype, 'hash', idProperty);
|
|
|
|
/**
|
|
* @returns {Boolean} - If timestamp is not too far in the future
|
|
*/
|
|
BlockHeader.prototype.validTimestamp = function validTimestamp() {
|
|
var currentTime = Math.round(new Date().getTime() / 1000);
|
|
if (this.time > currentTime + BlockHeader.Constants.MAX_TIME_OFFSET) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* @returns {Boolean} - If the proof-of-work hash satisfies the target difficulty
|
|
*/
|
|
BlockHeader.prototype.validProofOfWork = function validProofOfWork() {
|
|
var pow = new BN(this.id, 'hex');
|
|
var target = this.getTargetDifficulty();
|
|
|
|
if (pow.cmp(target) > 0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* @returns {string} - A string formatted for the console
|
|
*/
|
|
BlockHeader.prototype.inspect = function inspect() {
|
|
return '<BlockHeader ' + this.id + '>';
|
|
};
|
|
|
|
BlockHeader.Constants = {
|
|
START_OF_HEADER: 8, // Start buffer position in raw block data
|
|
MAX_TIME_OFFSET: 2 * 60 * 60, // The max a timestamp can be in the future
|
|
LARGEST_HASH: new BN('10000000000000000000000000000000000000000000000000000000000000000', 'hex')
|
|
};
|
|
|
|
module.exports = BlockHeader;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../crypto/bn":6,"../crypto/hash":8,"../encoding/bufferreader":14,"../encoding/bufferwriter":15,"../util/buffer":42,"../util/js":43,"../util/preconditions":44,"buffer":47,"lodash":319}],4:[function(require,module,exports){
|
|
module.exports = require('./block');
|
|
|
|
module.exports.BlockHeader = require('./blockheader');
|
|
module.exports.MerkleBlock = require('./merkleblock');
|
|
|
|
},{"./block":2,"./blockheader":3,"./merkleblock":5}],5:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var BlockHeader = require('./blockheader');
|
|
var BufferUtil = require('../util/buffer');
|
|
var BufferReader = require('../encoding/bufferreader');
|
|
var BufferWriter = require('../encoding/bufferwriter');
|
|
var Hash = require('../crypto/hash');
|
|
var JSUtil = require('../util/js');
|
|
var Transaction = require('../transaction');
|
|
var errors = require('../errors');
|
|
var $ = require('../util/preconditions');
|
|
|
|
/**
|
|
* Instantiate a MerkleBlock from a Buffer, JSON object, or Object with
|
|
* the properties of the Block
|
|
*
|
|
* @param {*} - A Buffer, JSON string, or Object representing a MerkleBlock
|
|
* @returns {MerkleBlock}
|
|
* @constructor
|
|
*/
|
|
function MerkleBlock(arg) {
|
|
/* jshint maxstatements: 18 */
|
|
|
|
if (!(this instanceof MerkleBlock)) {
|
|
return new MerkleBlock(arg);
|
|
}
|
|
|
|
var info = {};
|
|
if (BufferUtil.isBuffer(arg)) {
|
|
info = MerkleBlock._fromBufferReader(BufferReader(arg));
|
|
} else if (_.isObject(arg)) {
|
|
var header;
|
|
if(arg.header instanceof BlockHeader) {
|
|
header = arg.header;
|
|
} else {
|
|
header = BlockHeader.fromObject(arg.header);
|
|
}
|
|
info = {
|
|
/**
|
|
* @name MerkleBlock#header
|
|
* @type {BlockHeader}
|
|
*/
|
|
header: header,
|
|
/**
|
|
* @name MerkleBlock#numTransactions
|
|
* @type {Number}
|
|
*/
|
|
numTransactions: arg.numTransactions,
|
|
/**
|
|
* @name MerkleBlock#hashes
|
|
* @type {String[]}
|
|
*/
|
|
hashes: arg.hashes,
|
|
/**
|
|
* @name MerkleBlock#flags
|
|
* @type {Number[]}
|
|
*/
|
|
flags: arg.flags
|
|
};
|
|
} else {
|
|
throw new TypeError('Unrecognized argument for MerkleBlock');
|
|
}
|
|
_.extend(this,info);
|
|
this._flagBitsUsed = 0;
|
|
this._hashesUsed = 0;
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @param {Buffer} - MerkleBlock data in a Buffer object
|
|
* @returns {MerkleBlock} - A MerkleBlock object
|
|
*/
|
|
MerkleBlock.fromBuffer = function fromBuffer(buf) {
|
|
return MerkleBlock.fromBufferReader(BufferReader(buf));
|
|
};
|
|
|
|
/**
|
|
* @param {BufferReader} - MerkleBlock data in a BufferReader object
|
|
* @returns {MerkleBlock} - A MerkleBlock object
|
|
*/
|
|
MerkleBlock.fromBufferReader = function fromBufferReader(br) {
|
|
return new MerkleBlock(MerkleBlock._fromBufferReader(br));
|
|
};
|
|
|
|
/**
|
|
* @returns {Buffer} - A buffer of the block
|
|
*/
|
|
MerkleBlock.prototype.toBuffer = function toBuffer() {
|
|
return this.toBufferWriter().concat();
|
|
};
|
|
|
|
/**
|
|
* @param {BufferWriter} - An existing instance of BufferWriter
|
|
* @returns {BufferWriter} - An instance of BufferWriter representation of the MerkleBlock
|
|
*/
|
|
MerkleBlock.prototype.toBufferWriter = function toBufferWriter(bw) {
|
|
if (!bw) {
|
|
bw = new BufferWriter();
|
|
}
|
|
bw.write(this.header.toBuffer());
|
|
bw.writeUInt32LE(this.numTransactions);
|
|
bw.writeVarintNum(this.hashes.length);
|
|
for (var i = 0; i < this.hashes.length; i++) {
|
|
bw.write(new Buffer(this.hashes[i], 'hex'));
|
|
}
|
|
bw.writeVarintNum(this.flags.length);
|
|
for (i = 0; i < this.flags.length; i++) {
|
|
bw.writeUInt8(this.flags[i]);
|
|
}
|
|
return bw;
|
|
};
|
|
|
|
/**
|
|
* @returns {Object} - A plain object with the MerkleBlock properties
|
|
*/
|
|
MerkleBlock.prototype.toObject = MerkleBlock.prototype.toJSON = function toObject() {
|
|
return {
|
|
header: this.header.toObject(),
|
|
numTransactions: this.numTransactions,
|
|
hashes: this.hashes,
|
|
flags: this.flags
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Verify that the MerkleBlock is valid
|
|
* @returns {Boolean} - True/False whether this MerkleBlock is Valid
|
|
*/
|
|
MerkleBlock.prototype.validMerkleTree = function validMerkleTree() {
|
|
$.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array');
|
|
$.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array');
|
|
|
|
// Can't have more hashes than numTransactions
|
|
if(this.hashes.length > this.numTransactions) {
|
|
return false;
|
|
}
|
|
|
|
// Can't have more flag bits than num hashes
|
|
if(this.flags.length * 8 < this.hashes.length) {
|
|
return false;
|
|
}
|
|
|
|
var height = this._calcTreeHeight();
|
|
var opts = { hashesUsed: 0, flagBitsUsed: 0 };
|
|
var root = this._traverseMerkleTree(height, 0, opts);
|
|
if(opts.hashesUsed !== this.hashes.length) {
|
|
return false;
|
|
}
|
|
return BufferUtil.equals(root, this.header.merkleRoot);
|
|
};
|
|
|
|
/**
|
|
* Return a list of all the txs hash that match the filter
|
|
* @returns {Array} - txs hash that match the filter
|
|
*/
|
|
MerkleBlock.prototype.filterdTxsHash = function filterdTxsHash() {
|
|
$.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array');
|
|
$.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array');
|
|
|
|
// Can't have more hashes than numTransactions
|
|
if(this.hashes.length > this.numTransactions) {
|
|
throw new errors.MerkleBlock.InvalidMerkleTree();
|
|
}
|
|
|
|
// Can't have more flag bits than num hashes
|
|
if(this.flags.length * 8 < this.hashes.length) {
|
|
throw new errors.MerkleBlock.InvalidMerkleTree();
|
|
}
|
|
|
|
// If there is only one hash the filter do not match any txs in the block
|
|
if(this.hashes.length === 1) {
|
|
return [];
|
|
};
|
|
|
|
var height = this._calcTreeHeight();
|
|
var opts = { hashesUsed: 0, flagBitsUsed: 0 };
|
|
var txs = this._traverseMerkleTree(height, 0, opts, true);
|
|
if(opts.hashesUsed !== this.hashes.length) {
|
|
throw new errors.MerkleBlock.InvalidMerkleTree();
|
|
}
|
|
return txs;
|
|
};
|
|
|
|
/**
|
|
* Traverse a the tree in this MerkleBlock, validating it along the way
|
|
* Modeled after Bitcoin Core merkleblock.cpp TraverseAndExtract()
|
|
* @param {Number} - depth - Current height
|
|
* @param {Number} - pos - Current position in the tree
|
|
* @param {Object} - opts - Object with values that need to be mutated throughout the traversal
|
|
* @param {Boolean} - checkForTxs - if true return opts.txs else return the Merkle Hash
|
|
* @param {Number} - opts.flagBitsUsed - Number of flag bits used, should start at 0
|
|
* @param {Number} - opts.hashesUsed - Number of hashes used, should start at 0
|
|
* @param {Array} - opts.txs - Will finish populated by transactions found during traversal that match the filter
|
|
* @returns {Buffer|null} - Buffer containing the Merkle Hash for that height
|
|
* @returns {Array} - transactions found during traversal that match the filter
|
|
* @private
|
|
*/
|
|
MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, pos, opts, checkForTxs) {
|
|
/* jshint maxcomplexity: 12*/
|
|
/* jshint maxstatements: 20 */
|
|
|
|
opts = opts || {};
|
|
opts.txs = opts.txs || [];
|
|
opts.flagBitsUsed = opts.flagBitsUsed || 0;
|
|
opts.hashesUsed = opts.hashesUsed || 0;
|
|
var checkForTxs = checkForTxs || false;
|
|
|
|
if(opts.flagBitsUsed > this.flags.length * 8) {
|
|
return null;
|
|
}
|
|
var isParentOfMatch = (this.flags[opts.flagBitsUsed >> 3] >>> (opts.flagBitsUsed++ & 7)) & 1;
|
|
if(depth === 0 || !isParentOfMatch) {
|
|
if(opts.hashesUsed >= this.hashes.length) {
|
|
return null;
|
|
}
|
|
var hash = this.hashes[opts.hashesUsed++];
|
|
if(depth === 0 && isParentOfMatch) {
|
|
opts.txs.push(hash);
|
|
}
|
|
return new Buffer(hash, 'hex');
|
|
} else {
|
|
var left = this._traverseMerkleTree(depth-1, pos*2, opts);
|
|
var right = left;
|
|
if(pos*2+1 < this._calcTreeWidth(depth-1)) {
|
|
right = this._traverseMerkleTree(depth-1, pos*2+1, opts);
|
|
}
|
|
if (checkForTxs){
|
|
return opts.txs;
|
|
} else {
|
|
return Hash.sha256sha256(new Buffer.concat([left, right]));
|
|
};
|
|
}
|
|
};
|
|
|
|
/** Calculates the width of a merkle tree at a given height.
|
|
* Modeled after Bitcoin Core merkleblock.h CalcTreeWidth()
|
|
* @param {Number} - Height at which we want the tree width
|
|
* @returns {Number} - Width of the tree at a given height
|
|
* @private
|
|
*/
|
|
MerkleBlock.prototype._calcTreeWidth = function calcTreeWidth(height) {
|
|
return (this.numTransactions + (1 << height) - 1) >> height;
|
|
};
|
|
|
|
/** Calculates the height of the merkle tree in this MerkleBlock
|
|
* @param {Number} - Height at which we want the tree width
|
|
* @returns {Number} - Height of the merkle tree in this MerkleBlock
|
|
* @private
|
|
*/
|
|
MerkleBlock.prototype._calcTreeHeight = function calcTreeHeight() {
|
|
var height = 0;
|
|
while (this._calcTreeWidth(height) > 1) {
|
|
height++;
|
|
}
|
|
return height;
|
|
};
|
|
|
|
/**
|
|
* @param {Transaction|String} - Transaction or Transaction ID Hash
|
|
* @returns {Boolean} - return true/false if this MerkleBlock has the TX or not
|
|
* @private
|
|
*/
|
|
MerkleBlock.prototype.hasTransaction = function hasTransaction(tx) {
|
|
$.checkArgument(!_.isUndefined(tx), 'tx cannot be undefined');
|
|
$.checkArgument(tx instanceof Transaction || typeof tx === 'string',
|
|
'Invalid tx given, tx must be a "string" or "Transaction"');
|
|
|
|
var hash = tx;
|
|
if(tx instanceof Transaction) {
|
|
// We need to reverse the id hash for the lookup
|
|
hash = BufferUtil.reverse(new Buffer(tx.id, 'hex')).toString('hex');
|
|
}
|
|
|
|
var txs = [];
|
|
var height = this._calcTreeHeight();
|
|
this._traverseMerkleTree(height, 0, { txs: txs });
|
|
return txs.indexOf(hash) !== -1;
|
|
};
|
|
|
|
/**
|
|
* @param {Buffer} - MerkleBlock data
|
|
* @returns {Object} - An Object representing merkleblock data
|
|
* @private
|
|
*/
|
|
MerkleBlock._fromBufferReader = function _fromBufferReader(br) {
|
|
$.checkState(!br.finished(), 'No merkleblock data received');
|
|
var info = {};
|
|
info.header = BlockHeader.fromBufferReader(br);
|
|
info.numTransactions = br.readUInt32LE();
|
|
var numHashes = br.readVarintNum();
|
|
info.hashes = [];
|
|
for (var i = 0; i < numHashes; i++) {
|
|
info.hashes.push(br.read(32).toString('hex'));
|
|
}
|
|
var numFlags = br.readVarintNum();
|
|
info.flags = [];
|
|
for (i = 0; i < numFlags; i++) {
|
|
info.flags.push(br.readUInt8());
|
|
}
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* @param {Object} - A plain JavaScript object
|
|
* @returns {Block} - An instance of block
|
|
*/
|
|
MerkleBlock.fromObject = function fromObject(obj) {
|
|
return new MerkleBlock(obj);
|
|
};
|
|
|
|
module.exports = MerkleBlock;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../crypto/hash":8,"../encoding/bufferreader":14,"../encoding/bufferwriter":15,"../errors":17,"../transaction":28,"../util/buffer":42,"../util/js":43,"../util/preconditions":44,"./blockheader":3,"buffer":47,"lodash":319}],6:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var BN = require('bn.js');
|
|
var $ = require('../util/preconditions');
|
|
var _ = require('lodash');
|
|
|
|
var reversebuf = function(buf) {
|
|
var buf2 = new Buffer(buf.length);
|
|
for (var i = 0; i < buf.length; i++) {
|
|
buf2[i] = buf[buf.length - 1 - i];
|
|
}
|
|
return buf2;
|
|
};
|
|
|
|
BN.Zero = new BN(0);
|
|
BN.One = new BN(1);
|
|
BN.Minus1 = new BN(-1);
|
|
|
|
BN.fromNumber = function(n) {
|
|
$.checkArgument(_.isNumber(n));
|
|
return new BN(n);
|
|
};
|
|
|
|
BN.fromString = function(str, base) {
|
|
$.checkArgument(_.isString(str));
|
|
return new BN(str, base);
|
|
};
|
|
|
|
BN.fromBuffer = function(buf, opts) {
|
|
if (typeof opts !== 'undefined' && opts.endian === 'little') {
|
|
buf = reversebuf(buf);
|
|
}
|
|
var hex = buf.toString('hex');
|
|
var bn = new BN(hex, 16);
|
|
return bn;
|
|
};
|
|
|
|
/**
|
|
* Instantiate a BigNumber from a "signed magnitude buffer"
|
|
* (a buffer where the most significant bit represents the sign (0 = positive, -1 = negative))
|
|
*/
|
|
BN.fromSM = function(buf, opts) {
|
|
var ret;
|
|
if (buf.length === 0) {
|
|
return BN.fromBuffer(new Buffer([0]));
|
|
}
|
|
|
|
var endian = 'big';
|
|
if (opts) {
|
|
endian = opts.endian;
|
|
}
|
|
if (endian === 'little') {
|
|
buf = reversebuf(buf);
|
|
}
|
|
|
|
if (buf[0] & 0x80) {
|
|
buf[0] = buf[0] & 0x7f;
|
|
ret = BN.fromBuffer(buf);
|
|
ret.neg().copy(ret);
|
|
} else {
|
|
ret = BN.fromBuffer(buf);
|
|
}
|
|
return ret;
|
|
};
|
|
|
|
|
|
BN.prototype.toNumber = function() {
|
|
return parseInt(this.toString(10), 10);
|
|
};
|
|
|
|
BN.prototype.toBuffer = function(opts) {
|
|
var buf, hex;
|
|
if (opts && opts.size) {
|
|
hex = this.toString(16, 2);
|
|
var natlen = hex.length / 2;
|
|
buf = new Buffer(hex, 'hex');
|
|
|
|
if (natlen === opts.size) {
|
|
buf = buf;
|
|
} else if (natlen > opts.size) {
|
|
buf = BN.trim(buf, natlen);
|
|
} else if (natlen < opts.size) {
|
|
buf = BN.pad(buf, natlen, opts.size);
|
|
}
|
|
} else {
|
|
hex = this.toString(16, 2);
|
|
buf = new Buffer(hex, 'hex');
|
|
}
|
|
|
|
if (typeof opts !== 'undefined' && opts.endian === 'little') {
|
|
buf = reversebuf(buf);
|
|
}
|
|
|
|
return buf;
|
|
};
|
|
|
|
BN.prototype.toSMBigEndian = function() {
|
|
var buf;
|
|
if (this.cmp(BN.Zero) === -1) {
|
|
buf = this.neg().toBuffer();
|
|
if (buf[0] & 0x80) {
|
|
buf = Buffer.concat([new Buffer([0x80]), buf]);
|
|
} else {
|
|
buf[0] = buf[0] | 0x80;
|
|
}
|
|
} else {
|
|
buf = this.toBuffer();
|
|
if (buf[0] & 0x80) {
|
|
buf = Buffer.concat([new Buffer([0x00]), buf]);
|
|
}
|
|
}
|
|
|
|
if (buf.length === 1 & buf[0] === 0) {
|
|
buf = new Buffer([]);
|
|
}
|
|
return buf;
|
|
};
|
|
|
|
BN.prototype.toSM = function(opts) {
|
|
var endian = opts ? opts.endian : 'big';
|
|
var buf = this.toSMBigEndian();
|
|
|
|
if (endian === 'little') {
|
|
buf = reversebuf(buf);
|
|
}
|
|
return buf;
|
|
};
|
|
|
|
/**
|
|
* Create a BN from a "ScriptNum":
|
|
* This is analogous to the constructor for CScriptNum in bitcoind. Many ops in
|
|
* bitcoind's script interpreter use CScriptNum, which is not really a proper
|
|
* bignum. Instead, an error is thrown if trying to input a number bigger than
|
|
* 4 bytes. We copy that behavior here. A third argument, `size`, is provided to
|
|
* extend the hard limit of 4 bytes, as some usages require more than 4 bytes.
|
|
*/
|
|
BN.fromScriptNumBuffer = function(buf, fRequireMinimal, size) {
|
|
var nMaxNumSize = size || 4;
|
|
$.checkArgument(buf.length <= nMaxNumSize, new Error('script number overflow'));
|
|
if (fRequireMinimal && buf.length > 0) {
|
|
// Check that the number is encoded with the minimum possible
|
|
// number of bytes.
|
|
//
|
|
// If the most-significant-byte - excluding the sign bit - is zero
|
|
// then we're not minimal. Note how this test also rejects the
|
|
// negative-zero encoding, 0x80.
|
|
if ((buf[buf.length - 1] & 0x7f) === 0) {
|
|
// One exception: if there's more than one byte and the most
|
|
// significant bit of the second-most-significant-byte is set
|
|
// it would conflict with the sign bit. An example of this case
|
|
// is +-255, which encode to 0xff00 and 0xff80 respectively.
|
|
// (big-endian).
|
|
if (buf.length <= 1 || (buf[buf.length - 2] & 0x80) === 0) {
|
|
throw new Error('non-minimally encoded script number');
|
|
}
|
|
}
|
|
}
|
|
return BN.fromSM(buf, {
|
|
endian: 'little'
|
|
});
|
|
};
|
|
|
|
/**
|
|
* The corollary to the above, with the notable exception that we do not throw
|
|
* an error if the output is larger than four bytes. (Which can happen if
|
|
* performing a numerical operation that results in an overflow to more than 4
|
|
* bytes).
|
|
*/
|
|
BN.prototype.toScriptNumBuffer = function() {
|
|
return this.toSM({
|
|
endian: 'little'
|
|
});
|
|
};
|
|
|
|
BN.prototype.gt = function(b) {
|
|
return this.cmp(b) > 0;
|
|
};
|
|
|
|
BN.prototype.gte = function(b) {
|
|
return this.cmp(b) >= 0;
|
|
};
|
|
|
|
BN.prototype.lt = function(b) {
|
|
return this.cmp(b) < 0;
|
|
};
|
|
|
|
BN.trim = function(buf, natlen) {
|
|
return buf.slice(natlen - buf.length, buf.length);
|
|
};
|
|
|
|
BN.pad = function(buf, natlen, size) {
|
|
var rbuf = new Buffer(size);
|
|
for (var i = 0; i < buf.length; i++) {
|
|
rbuf[rbuf.length - 1 - i] = buf[buf.length - 1 - i];
|
|
}
|
|
for (i = 0; i < size - natlen; i++) {
|
|
rbuf[i] = 0;
|
|
}
|
|
return rbuf;
|
|
};
|
|
|
|
module.exports = BN;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../util/preconditions":44,"bn.js":280,"buffer":47,"lodash":319}],7:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var BN = require('./bn');
|
|
var Point = require('./point');
|
|
var Signature = require('./signature');
|
|
var PublicKey = require('../publickey');
|
|
var Random = require('./random');
|
|
var Hash = require('./hash');
|
|
var BufferUtil = require('../util/buffer');
|
|
var _ = require('lodash');
|
|
var $ = require('../util/preconditions');
|
|
|
|
var ECDSA = function ECDSA(obj) {
|
|
if (!(this instanceof ECDSA)) {
|
|
return new ECDSA(obj);
|
|
}
|
|
if (obj) {
|
|
this.set(obj);
|
|
}
|
|
};
|
|
|
|
/* jshint maxcomplexity: 9 */
|
|
ECDSA.prototype.set = function(obj) {
|
|
this.hashbuf = obj.hashbuf || this.hashbuf;
|
|
this.endian = obj.endian || this.endian; //the endianness of hashbuf
|
|
this.privkey = obj.privkey || this.privkey;
|
|
this.pubkey = obj.pubkey || (this.privkey ? this.privkey.publicKey : this.pubkey);
|
|
this.sig = obj.sig || this.sig;
|
|
this.k = obj.k || this.k;
|
|
this.verified = obj.verified || this.verified;
|
|
return this;
|
|
};
|
|
|
|
ECDSA.prototype.privkey2pubkey = function() {
|
|
this.pubkey = this.privkey.toPublicKey();
|
|
};
|
|
|
|
ECDSA.prototype.calci = function() {
|
|
for (var i = 0; i < 4; i++) {
|
|
this.sig.i = i;
|
|
var Qprime;
|
|
try {
|
|
Qprime = this.toPublicKey();
|
|
} catch (e) {
|
|
console.error(e);
|
|
continue;
|
|
}
|
|
|
|
if (Qprime.point.eq(this.pubkey.point)) {
|
|
this.sig.compressed = this.pubkey.compressed;
|
|
return this;
|
|
}
|
|
}
|
|
|
|
this.sig.i = undefined;
|
|
throw new Error('Unable to find valid recovery factor');
|
|
};
|
|
|
|
ECDSA.fromString = function(str) {
|
|
var obj = JSON.parse(str);
|
|
return new ECDSA(obj);
|
|
};
|
|
|
|
ECDSA.prototype.randomK = function() {
|
|
var N = Point.getN();
|
|
var k;
|
|
do {
|
|
k = BN.fromBuffer(Random.getRandomBuffer(32));
|
|
} while (!(k.lt(N) && k.gt(BN.Zero)));
|
|
this.k = k;
|
|
return this;
|
|
};
|
|
|
|
|
|
// https://tools.ietf.org/html/rfc6979#section-3.2
|
|
ECDSA.prototype.deterministicK = function(badrs) {
|
|
/* jshint maxstatements: 25 */
|
|
// if r or s were invalid when this function was used in signing,
|
|
// we do not want to actually compute r, s here for efficiency, so,
|
|
// we can increment badrs. explained at end of RFC 6979 section 3.2
|
|
if (_.isUndefined(badrs)) {
|
|
badrs = 0;
|
|
}
|
|
var v = new Buffer(32);
|
|
v.fill(0x01);
|
|
var k = new Buffer(32);
|
|
k.fill(0x00);
|
|
var x = this.privkey.bn.toBuffer({
|
|
size: 32
|
|
});
|
|
var hashbuf = this.endian === 'little' ? BufferUtil.reverse(this.hashbuf) : this.hashbuf
|
|
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x00]), x, hashbuf]), k);
|
|
v = Hash.sha256hmac(v, k);
|
|
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x01]), x, hashbuf]), k);
|
|
v = Hash.sha256hmac(v, k);
|
|
v = Hash.sha256hmac(v, k);
|
|
var T = BN.fromBuffer(v);
|
|
var N = Point.getN();
|
|
|
|
// also explained in 3.2, we must ensure T is in the proper range (0, N)
|
|
for (var i = 0; i < badrs || !(T.lt(N) && T.gt(BN.Zero)); i++) {
|
|
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x00])]), k);
|
|
v = Hash.sha256hmac(v, k);
|
|
v = Hash.sha256hmac(v, k);
|
|
T = BN.fromBuffer(v);
|
|
}
|
|
|
|
this.k = T;
|
|
return this;
|
|
};
|
|
|
|
// Information about public key recovery:
|
|
// https://bitcointalk.org/index.php?topic=6430.0
|
|
// http://stackoverflow.com/questions/19665491/how-do-i-get-an-ecdsa-public-key-from-just-a-bitcoin-signature-sec1-4-1-6-k
|
|
ECDSA.prototype.toPublicKey = function() {
|
|
/* jshint maxstatements: 25 */
|
|
var i = this.sig.i;
|
|
$.checkArgument(i === 0 || i === 1 || i === 2 || i === 3, new Error('i must be equal to 0, 1, 2, or 3'));
|
|
|
|
var e = BN.fromBuffer(this.hashbuf);
|
|
var r = this.sig.r;
|
|
var s = this.sig.s;
|
|
|
|
// A set LSB signifies that the y-coordinate is odd
|
|
var isYOdd = i & 1;
|
|
|
|
// The more significant bit specifies whether we should use the
|
|
// first or second candidate key.
|
|
var isSecondKey = i >> 1;
|
|
|
|
var n = Point.getN();
|
|
var G = Point.getG();
|
|
|
|
// 1.1 Let x = r + jn
|
|
var x = isSecondKey ? r.add(n) : r;
|
|
var R = Point.fromX(isYOdd, x);
|
|
|
|
// 1.4 Check that nR is at infinity
|
|
var nR = R.mul(n);
|
|
|
|
if (!nR.isInfinity()) {
|
|
throw new Error('nR is not a valid curve point');
|
|
}
|
|
|
|
// Compute -e from e
|
|
var eNeg = e.neg().umod(n);
|
|
|
|
// 1.6.1 Compute Q = r^-1 (sR - eG)
|
|
// Q = r^-1 (sR + -eG)
|
|
var rInv = r.invm(n);
|
|
|
|
//var Q = R.multiplyTwo(s, G, eNeg).mul(rInv);
|
|
var Q = R.mul(s).add(G.mul(eNeg)).mul(rInv);
|
|
|
|
var pubkey = PublicKey.fromPoint(Q, this.sig.compressed);
|
|
|
|
return pubkey;
|
|
};
|
|
|
|
ECDSA.prototype.sigError = function() {
|
|
/* jshint maxstatements: 25 */
|
|
if (!BufferUtil.isBuffer(this.hashbuf) || this.hashbuf.length !== 32) {
|
|
return 'hashbuf must be a 32 byte buffer';
|
|
}
|
|
|
|
var r = this.sig.r;
|
|
var s = this.sig.s;
|
|
if (!(r.gt(BN.Zero) && r.lt(Point.getN())) || !(s.gt(BN.Zero) && s.lt(Point.getN()))) {
|
|
return 'r and s not in range';
|
|
}
|
|
|
|
var e = BN.fromBuffer(this.hashbuf, this.endian ? {
|
|
endian: this.endian
|
|
} : undefined);
|
|
var n = Point.getN();
|
|
var sinv = s.invm(n);
|
|
var u1 = sinv.mul(e).umod(n);
|
|
var u2 = sinv.mul(r).umod(n);
|
|
|
|
var p = Point.getG().mulAdd(u1, this.pubkey.point, u2);
|
|
if (p.isInfinity()) {
|
|
return 'p is infinity';
|
|
}
|
|
|
|
if (p.getX().umod(n).cmp(r) !== 0) {
|
|
return 'Invalid signature';
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
ECDSA.toLowS = function(s) {
|
|
//enforce low s
|
|
//see BIP 62, "low S values in signatures"
|
|
if (s.gt(BN.fromBuffer(new Buffer('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex')))) {
|
|
s = Point.getN().sub(s);
|
|
}
|
|
return s;
|
|
};
|
|
|
|
ECDSA.prototype._findSignature = function(d, e) {
|
|
var N = Point.getN();
|
|
var G = Point.getG();
|
|
// try different values of k until r, s are valid
|
|
var badrs = 0;
|
|
var k, Q, r, s;
|
|
do {
|
|
if (!this.k || badrs > 0) {
|
|
this.deterministicK(badrs);
|
|
}
|
|
badrs++;
|
|
k = this.k;
|
|
Q = G.mul(k);
|
|
r = Q.x.umod(N);
|
|
s = k.invm(N).mul(e.add(d.mul(r))).umod(N);
|
|
} while (r.cmp(BN.Zero) <= 0 || s.cmp(BN.Zero) <= 0);
|
|
|
|
s = ECDSA.toLowS(s);
|
|
return {
|
|
s: s,
|
|
r: r
|
|
};
|
|
|
|
};
|
|
|
|
ECDSA.prototype.sign = function() {
|
|
var hashbuf = this.hashbuf;
|
|
var privkey = this.privkey;
|
|
var d = privkey.bn;
|
|
|
|
$.checkState(hashbuf && privkey && d, new Error('invalid parameters'));
|
|
$.checkState(BufferUtil.isBuffer(hashbuf) && hashbuf.length === 32, new Error('hashbuf must be a 32 byte buffer'));
|
|
|
|
var e = BN.fromBuffer(hashbuf, this.endian ? {
|
|
endian: this.endian
|
|
} : undefined);
|
|
|
|
var obj = this._findSignature(d, e);
|
|
obj.compressed = this.pubkey.compressed;
|
|
|
|
this.sig = new Signature(obj);
|
|
return this;
|
|
};
|
|
|
|
ECDSA.prototype.signRandomK = function() {
|
|
this.randomK();
|
|
return this.sign();
|
|
};
|
|
|
|
ECDSA.prototype.toString = function() {
|
|
var obj = {};
|
|
if (this.hashbuf) {
|
|
obj.hashbuf = this.hashbuf.toString('hex');
|
|
}
|
|
if (this.privkey) {
|
|
obj.privkey = this.privkey.toString();
|
|
}
|
|
if (this.pubkey) {
|
|
obj.pubkey = this.pubkey.toString();
|
|
}
|
|
if (this.sig) {
|
|
obj.sig = this.sig.toString();
|
|
}
|
|
if (this.k) {
|
|
obj.k = this.k.toString();
|
|
}
|
|
return JSON.stringify(obj);
|
|
};
|
|
|
|
ECDSA.prototype.verify = function() {
|
|
if (!this.sigError()) {
|
|
this.verified = true;
|
|
} else {
|
|
this.verified = false;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
ECDSA.sign = function(hashbuf, privkey, endian) {
|
|
return ECDSA().set({
|
|
hashbuf: hashbuf,
|
|
endian: endian,
|
|
privkey: privkey
|
|
}).sign().sig;
|
|
};
|
|
|
|
ECDSA.verify = function(hashbuf, sig, pubkey, endian) {
|
|
return ECDSA().set({
|
|
hashbuf: hashbuf,
|
|
endian: endian,
|
|
sig: sig,
|
|
pubkey: pubkey
|
|
}).verify().verified;
|
|
};
|
|
|
|
module.exports = ECDSA;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../publickey":24,"../util/buffer":42,"../util/preconditions":44,"./bn":6,"./hash":8,"./point":9,"./random":10,"./signature":11,"buffer":47,"lodash":319}],8:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var crypto = require('crypto');
|
|
var BufferUtil = require('../util/buffer');
|
|
var $ = require('../util/preconditions');
|
|
|
|
var Hash = module.exports;
|
|
|
|
Hash.sha1 = function(buf) {
|
|
$.checkArgument(BufferUtil.isBuffer(buf));
|
|
return crypto.createHash('sha1').update(buf).digest();
|
|
};
|
|
|
|
Hash.sha1.blocksize = 512;
|
|
|
|
Hash.sha256 = function(buf) {
|
|
$.checkArgument(BufferUtil.isBuffer(buf));
|
|
return crypto.createHash('sha256').update(buf).digest();
|
|
};
|
|
|
|
Hash.sha256.blocksize = 512;
|
|
|
|
Hash.sha256sha256 = function(buf) {
|
|
$.checkArgument(BufferUtil.isBuffer(buf));
|
|
return Hash.sha256(Hash.sha256(buf));
|
|
};
|
|
|
|
Hash.ripemd160 = function(buf) {
|
|
$.checkArgument(BufferUtil.isBuffer(buf));
|
|
return crypto.createHash('ripemd160').update(buf).digest();
|
|
};
|
|
|
|
Hash.sha256ripemd160 = function(buf) {
|
|
$.checkArgument(BufferUtil.isBuffer(buf));
|
|
return Hash.ripemd160(Hash.sha256(buf));
|
|
};
|
|
|
|
Hash.sha512 = function(buf) {
|
|
$.checkArgument(BufferUtil.isBuffer(buf));
|
|
return crypto.createHash('sha512').update(buf).digest();
|
|
};
|
|
|
|
Hash.sha512.blocksize = 1024;
|
|
|
|
Hash.hmac = function(hashf, data, key) {
|
|
//http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
|
|
//http://tools.ietf.org/html/rfc4868#section-2
|
|
$.checkArgument(BufferUtil.isBuffer(data));
|
|
$.checkArgument(BufferUtil.isBuffer(key));
|
|
$.checkArgument(hashf.blocksize);
|
|
|
|
var blocksize = hashf.blocksize / 8;
|
|
|
|
if (key.length > blocksize) {
|
|
key = hashf(key);
|
|
} else if (key < blocksize) {
|
|
var fill = new Buffer(blocksize);
|
|
fill.fill(0);
|
|
key.copy(fill);
|
|
key = fill;
|
|
}
|
|
|
|
var o_key = new Buffer(blocksize);
|
|
o_key.fill(0x5c);
|
|
|
|
var i_key = new Buffer(blocksize);
|
|
i_key.fill(0x36);
|
|
|
|
var o_key_pad = new Buffer(blocksize);
|
|
var i_key_pad = new Buffer(blocksize);
|
|
for (var i = 0; i < blocksize; i++) {
|
|
o_key_pad[i] = o_key[i] ^ key[i];
|
|
i_key_pad[i] = i_key[i] ^ key[i];
|
|
}
|
|
|
|
return hashf(Buffer.concat([o_key_pad, hashf(Buffer.concat([i_key_pad, data]))]));
|
|
};
|
|
|
|
Hash.sha256hmac = function(data, key) {
|
|
return Hash.hmac(Hash.sha256, data, key);
|
|
};
|
|
|
|
Hash.sha512hmac = function(data, key) {
|
|
return Hash.hmac(Hash.sha512, data, key);
|
|
};
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../util/buffer":42,"../util/preconditions":44,"buffer":47,"crypto":51}],9:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var BN = require('./bn');
|
|
var BufferUtil = require('../util/buffer');
|
|
|
|
var EC = require('elliptic').ec;
|
|
var ec = new EC('secp256k1');
|
|
var ecPoint = ec.curve.point.bind(ec.curve);
|
|
var ecPointFromX = ec.curve.pointFromX.bind(ec.curve);
|
|
|
|
/**
|
|
*
|
|
* Instantiate a valid secp256k1 Point from the X and Y coordinates.
|
|
*
|
|
* @param {BN|String} x - The X coordinate
|
|
* @param {BN|String} y - The Y coordinate
|
|
* @link https://github.com/indutny/elliptic
|
|
* @augments elliptic.curve.point
|
|
* @throws {Error} A validation error if exists
|
|
* @returns {Point} An instance of Point
|
|
* @constructor
|
|
*/
|
|
var Point = function Point(x, y, isRed) {
|
|
try {
|
|
var point = ecPoint(x, y, isRed);
|
|
} catch (e) {
|
|
throw new Error('Invalid Point');
|
|
}
|
|
point.validate();
|
|
return point;
|
|
};
|
|
|
|
Point.prototype = Object.getPrototypeOf(ec.curve.point());
|
|
|
|
/**
|
|
*
|
|
* Instantiate a valid secp256k1 Point from only the X coordinate
|
|
*
|
|
* @param {boolean} odd - If the Y coordinate is odd
|
|
* @param {BN|String} x - The X coordinate
|
|
* @throws {Error} A validation error if exists
|
|
* @returns {Point} An instance of Point
|
|
*/
|
|
Point.fromX = function fromX(odd, x){
|
|
try {
|
|
var point = ecPointFromX(x, odd);
|
|
} catch (e) {
|
|
throw new Error('Invalid X');
|
|
}
|
|
point.validate();
|
|
return point;
|
|
};
|
|
|
|
/**
|
|
*
|
|
* Will return a secp256k1 ECDSA base point.
|
|
*
|
|
* @link https://en.bitcoin.it/wiki/Secp256k1
|
|
* @returns {Point} An instance of the base point.
|
|
*/
|
|
Point.getG = function getG() {
|
|
return ec.curve.g;
|
|
};
|
|
|
|
/**
|
|
*
|
|
* Will return the max of range of valid private keys as governed by the secp256k1 ECDSA standard.
|
|
*
|
|
* @link https://en.bitcoin.it/wiki/Private_key#Range_of_valid_ECDSA_private_keys
|
|
* @returns {BN} A BN instance of the number of points on the curve
|
|
*/
|
|
Point.getN = function getN() {
|
|
return new BN(ec.curve.n.toArray());
|
|
};
|
|
|
|
Point.prototype._getX = Point.prototype.getX;
|
|
|
|
/**
|
|
*
|
|
* Will return the X coordinate of the Point
|
|
*
|
|
* @returns {BN} A BN instance of the X coordinate
|
|
*/
|
|
Point.prototype.getX = function getX() {
|
|
return new BN(this._getX().toArray());
|
|
};
|
|
|
|
Point.prototype._getY = Point.prototype.getY;
|
|
|
|
/**
|
|
*
|
|
* Will return the Y coordinate of the Point
|
|
*
|
|
* @returns {BN} A BN instance of the Y coordinate
|
|
*/
|
|
Point.prototype.getY = function getY() {
|
|
return new BN(this._getY().toArray());
|
|
};
|
|
|
|
/**
|
|
*
|
|
* Will determine if the point is valid
|
|
*
|
|
* @link https://www.iacr.org/archive/pkc2003/25670211/25670211.pdf
|
|
* @param {Point} An instance of Point
|
|
* @throws {Error} A validation error if exists
|
|
* @returns {Point} An instance of the same Point
|
|
*/
|
|
Point.prototype.validate = function validate() {
|
|
|
|
if (this.isInfinity()){
|
|
throw new Error('Point cannot be equal to Infinity');
|
|
}
|
|
|
|
var p2;
|
|
try {
|
|
p2 = ecPointFromX(this.getX(), this.getY().isOdd());
|
|
} catch (e) {
|
|
throw new Error('Point does not lie on the curve');
|
|
}
|
|
|
|
if (p2.y.cmp(this.y) !== 0) {
|
|
throw new Error('Invalid y value for curve.');
|
|
}
|
|
|
|
|
|
//todo: needs test case
|
|
if (!(this.mul(Point.getN()).isInfinity())) {
|
|
throw new Error('Point times N must be infinity');
|
|
}
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
Point.pointToCompressed = function pointToCompressed(point) {
|
|
var xbuf = point.getX().toBuffer({size: 32});
|
|
var ybuf = point.getY().toBuffer({size: 32});
|
|
|
|
var prefix;
|
|
var odd = ybuf[ybuf.length - 1] % 2;
|
|
if (odd) {
|
|
prefix = new Buffer([0x03]);
|
|
} else {
|
|
prefix = new Buffer([0x02]);
|
|
}
|
|
return BufferUtil.concat([prefix, xbuf]);
|
|
};
|
|
|
|
module.exports = Point;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../util/buffer":42,"./bn":6,"buffer":47,"elliptic":285}],10:[function(require,module,exports){
|
|
(function (process,Buffer){
|
|
'use strict';
|
|
|
|
function Random() {
|
|
}
|
|
|
|
/* secure random bytes that sometimes throws an error due to lack of entropy */
|
|
Random.getRandomBuffer = function(size) {
|
|
if (process.browser)
|
|
return Random.getRandomBufferBrowser(size);
|
|
else
|
|
return Random.getRandomBufferNode(size);
|
|
};
|
|
|
|
Random.getRandomBufferNode = function(size) {
|
|
var crypto = require('crypto');
|
|
return crypto.randomBytes(size);
|
|
};
|
|
|
|
Random.getRandomBufferBrowser = function(size) {
|
|
if (!window.crypto && !window.msCrypto)
|
|
throw new Error('window.crypto not available');
|
|
|
|
if (window.crypto && window.crypto.getRandomValues)
|
|
var crypto = window.crypto;
|
|
else if (window.msCrypto && window.msCrypto.getRandomValues) //internet explorer
|
|
var crypto = window.msCrypto;
|
|
else
|
|
throw new Error('window.crypto.getRandomValues not available');
|
|
|
|
var bbuf = new Uint8Array(size);
|
|
crypto.getRandomValues(bbuf);
|
|
var buf = new Buffer(bbuf);
|
|
|
|
return buf;
|
|
};
|
|
|
|
/* insecure random bytes, but it never fails */
|
|
Random.getPseudoRandomBuffer = function(size) {
|
|
var b32 = 0x100000000;
|
|
var b = new Buffer(size);
|
|
var r;
|
|
|
|
for (var i = 0; i <= size; i++) {
|
|
var j = Math.floor(i / 4);
|
|
var k = i - j * 4;
|
|
if (k === 0) {
|
|
r = Math.random() * b32;
|
|
b[i] = r & 0xff;
|
|
} else {
|
|
b[i] = (r = r >>> 8) & 0xff;
|
|
}
|
|
}
|
|
|
|
return b;
|
|
};
|
|
|
|
module.exports = Random;
|
|
|
|
}).call(this,require('_process'),require("buffer").Buffer)
|
|
},{"_process":247,"buffer":47,"crypto":51}],11:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var BN = require('./bn');
|
|
var _ = require('lodash');
|
|
var $ = require('../util/preconditions');
|
|
var BufferUtil = require('../util/buffer');
|
|
var JSUtil = require('../util/js');
|
|
|
|
var Signature = function Signature(r, s) {
|
|
if (!(this instanceof Signature)) {
|
|
return new Signature(r, s);
|
|
}
|
|
if (r instanceof BN) {
|
|
this.set({
|
|
r: r,
|
|
s: s
|
|
});
|
|
} else if (r) {
|
|
var obj = r;
|
|
this.set(obj);
|
|
}
|
|
};
|
|
|
|
/* jshint maxcomplexity: 7 */
|
|
Signature.prototype.set = function(obj) {
|
|
this.r = obj.r || this.r || undefined;
|
|
this.s = obj.s || this.s || undefined;
|
|
|
|
this.i = typeof obj.i !== 'undefined' ? obj.i : this.i; //public key recovery parameter in range [0, 3]
|
|
this.compressed = typeof obj.compressed !== 'undefined' ?
|
|
obj.compressed : this.compressed; //whether the recovered pubkey is compressed
|
|
this.nhashtype = obj.nhashtype || this.nhashtype || undefined;
|
|
return this;
|
|
};
|
|
|
|
Signature.fromCompact = function(buf) {
|
|
$.checkArgument(BufferUtil.isBuffer(buf), 'Argument is expected to be a Buffer');
|
|
|
|
var sig = new Signature();
|
|
|
|
var compressed = true;
|
|
var i = buf.slice(0, 1)[0] - 27 - 4;
|
|
if (i < 0) {
|
|
compressed = false;
|
|
i = i + 4;
|
|
}
|
|
|
|
var b2 = buf.slice(1, 33);
|
|
var b3 = buf.slice(33, 65);
|
|
|
|
$.checkArgument(i === 0 || i === 1 || i === 2 || i === 3, new Error('i must be 0, 1, 2, or 3'));
|
|
$.checkArgument(b2.length === 32, new Error('r must be 32 bytes'));
|
|
$.checkArgument(b3.length === 32, new Error('s must be 32 bytes'));
|
|
|
|
sig.compressed = compressed;
|
|
sig.i = i;
|
|
sig.r = BN.fromBuffer(b2);
|
|
sig.s = BN.fromBuffer(b3);
|
|
|
|
return sig;
|
|
};
|
|
|
|
Signature.fromDER = Signature.fromBuffer = function(buf, strict) {
|
|
var obj = Signature.parseDER(buf, strict);
|
|
var sig = new Signature();
|
|
|
|
sig.r = obj.r;
|
|
sig.s = obj.s;
|
|
|
|
return sig;
|
|
};
|
|
|
|
// The format used in a tx
|
|
Signature.fromTxFormat = function(buf) {
|
|
var nhashtype = buf.readUInt8(buf.length - 1);
|
|
var derbuf = buf.slice(0, buf.length - 1);
|
|
var sig = new Signature.fromDER(derbuf, false);
|
|
sig.nhashtype = nhashtype;
|
|
return sig;
|
|
};
|
|
|
|
Signature.fromString = function(str) {
|
|
var buf = new Buffer(str, 'hex');
|
|
return Signature.fromDER(buf);
|
|
};
|
|
|
|
|
|
/**
|
|
* In order to mimic the non-strict DER encoding of OpenSSL, set strict = false.
|
|
*/
|
|
Signature.parseDER = function(buf, strict) {
|
|
$.checkArgument(BufferUtil.isBuffer(buf), new Error('DER formatted signature should be a buffer'));
|
|
if (_.isUndefined(strict)) {
|
|
strict = true;
|
|
}
|
|
|
|
var header = buf[0];
|
|
$.checkArgument(header === 0x30, new Error('Header byte should be 0x30'));
|
|
|
|
var length = buf[1];
|
|
var buflength = buf.slice(2).length;
|
|
$.checkArgument(!strict || length === buflength, new Error('Length byte should length of what follows'));
|
|
|
|
length = length < buflength ? length : buflength;
|
|
|
|
var rheader = buf[2 + 0];
|
|
$.checkArgument(rheader === 0x02, new Error('Integer byte for r should be 0x02'));
|
|
|
|
var rlength = buf[2 + 1];
|
|
var rbuf = buf.slice(2 + 2, 2 + 2 + rlength);
|
|
var r = BN.fromBuffer(rbuf);
|
|
var rneg = buf[2 + 1 + 1] === 0x00 ? true : false;
|
|
$.checkArgument(rlength === rbuf.length, new Error('Length of r incorrect'));
|
|
|
|
var sheader = buf[2 + 2 + rlength + 0];
|
|
$.checkArgument(sheader === 0x02, new Error('Integer byte for s should be 0x02'));
|
|
|
|
var slength = buf[2 + 2 + rlength + 1];
|
|
var sbuf = buf.slice(2 + 2 + rlength + 2, 2 + 2 + rlength + 2 + slength);
|
|
var s = BN.fromBuffer(sbuf);
|
|
var sneg = buf[2 + 2 + rlength + 2 + 2] === 0x00 ? true : false;
|
|
$.checkArgument(slength === sbuf.length, new Error('Length of s incorrect'));
|
|
|
|
var sumlength = 2 + 2 + rlength + 2 + slength;
|
|
$.checkArgument(length === sumlength - 2, new Error('Length of signature incorrect'));
|
|
|
|
var obj = {
|
|
header: header,
|
|
length: length,
|
|
rheader: rheader,
|
|
rlength: rlength,
|
|
rneg: rneg,
|
|
rbuf: rbuf,
|
|
r: r,
|
|
sheader: sheader,
|
|
slength: slength,
|
|
sneg: sneg,
|
|
sbuf: sbuf,
|
|
s: s
|
|
};
|
|
|
|
return obj;
|
|
};
|
|
|
|
|
|
Signature.prototype.toCompact = function(i, compressed) {
|
|
i = typeof i === 'number' ? i : this.i;
|
|
compressed = typeof compressed === 'boolean' ? compressed : this.compressed;
|
|
|
|
if (!(i === 0 || i === 1 || i === 2 || i === 3)) {
|
|
throw new Error('i must be equal to 0, 1, 2, or 3');
|
|
}
|
|
|
|
var val = i + 27 + 4;
|
|
if (compressed === false) {
|
|
val = val - 4;
|
|
}
|
|
var b1 = new Buffer([val]);
|
|
var b2 = this.r.toBuffer({
|
|
size: 32
|
|
});
|
|
var b3 = this.s.toBuffer({
|
|
size: 32
|
|
});
|
|
return Buffer.concat([b1, b2, b3]);
|
|
};
|
|
|
|
Signature.prototype.toBuffer = Signature.prototype.toDER = function() {
|
|
var rnbuf = this.r.toBuffer();
|
|
var snbuf = this.s.toBuffer();
|
|
|
|
var rneg = rnbuf[0] & 0x80 ? true : false;
|
|
var sneg = snbuf[0] & 0x80 ? true : false;
|
|
|
|
var rbuf = rneg ? Buffer.concat([new Buffer([0x00]), rnbuf]) : rnbuf;
|
|
var sbuf = sneg ? Buffer.concat([new Buffer([0x00]), snbuf]) : snbuf;
|
|
|
|
var rlength = rbuf.length;
|
|
var slength = sbuf.length;
|
|
var length = 2 + rlength + 2 + slength;
|
|
var rheader = 0x02;
|
|
var sheader = 0x02;
|
|
var header = 0x30;
|
|
|
|
var der = Buffer.concat([new Buffer([header, length, rheader, rlength]), rbuf, new Buffer([sheader, slength]), sbuf]);
|
|
return der;
|
|
};
|
|
|
|
Signature.prototype.toString = function() {
|
|
var buf = this.toDER();
|
|
return buf.toString('hex');
|
|
};
|
|
|
|
/**
|
|
* This function is translated from bitcoind's IsDERSignature and is used in
|
|
* the script interpreter. This "DER" format actually includes an extra byte,
|
|
* the nhashtype, at the end. It is really the tx format, not DER format.
|
|
*
|
|
* A canonical signature exists of: [30] [total len] [02] [len R] [R] [02] [len S] [S] [hashtype]
|
|
* Where R and S are not negative (their first byte has its highest bit not set), and not
|
|
* excessively padded (do not start with a 0 byte, unless an otherwise negative number follows,
|
|
* in which case a single 0 byte is necessary and even required).
|
|
*
|
|
* See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
|
|
*/
|
|
Signature.isTxDER = function(buf) {
|
|
if (buf.length < 9) {
|
|
// Non-canonical signature: too short
|
|
return false;
|
|
}
|
|
if (buf.length > 73) {
|
|
// Non-canonical signature: too long
|
|
return false;
|
|
}
|
|
if (buf[0] !== 0x30) {
|
|
// Non-canonical signature: wrong type
|
|
return false;
|
|
}
|
|
if (buf[1] !== buf.length - 3) {
|
|
// Non-canonical signature: wrong length marker
|
|
return false;
|
|
}
|
|
var nLenR = buf[3];
|
|
if (5 + nLenR >= buf.length) {
|
|
// Non-canonical signature: S length misplaced
|
|
return false;
|
|
}
|
|
var nLenS = buf[5 + nLenR];
|
|
if ((nLenR + nLenS + 7) !== buf.length) {
|
|
// Non-canonical signature: R+S length mismatch
|
|
return false;
|
|
}
|
|
|
|
var R = buf.slice(4);
|
|
if (buf[4 - 2] !== 0x02) {
|
|
// Non-canonical signature: R value type mismatch
|
|
return false;
|
|
}
|
|
if (nLenR === 0) {
|
|
// Non-canonical signature: R length is zero
|
|
return false;
|
|
}
|
|
if (R[0] & 0x80) {
|
|
// Non-canonical signature: R value negative
|
|
return false;
|
|
}
|
|
if (nLenR > 1 && (R[0] === 0x00) && !(R[1] & 0x80)) {
|
|
// Non-canonical signature: R value excessively padded
|
|
return false;
|
|
}
|
|
|
|
var S = buf.slice(6 + nLenR);
|
|
if (buf[6 + nLenR - 2] !== 0x02) {
|
|
// Non-canonical signature: S value type mismatch
|
|
return false;
|
|
}
|
|
if (nLenS === 0) {
|
|
// Non-canonical signature: S length is zero
|
|
return false;
|
|
}
|
|
if (S[0] & 0x80) {
|
|
// Non-canonical signature: S value negative
|
|
return false;
|
|
}
|
|
if (nLenS > 1 && (S[0] === 0x00) && !(S[1] & 0x80)) {
|
|
// Non-canonical signature: S value excessively padded
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Compares to bitcoind's IsLowDERSignature
|
|
* See also ECDSA signature algorithm which enforces this.
|
|
* See also BIP 62, "low S values in signatures"
|
|
*/
|
|
Signature.prototype.hasLowS = function() {
|
|
if (this.s.lt(new BN(1)) ||
|
|
this.s.gt(new BN('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex'))) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* @returns true if the nhashtype is exactly equal to one of the standard options or combinations thereof.
|
|
* Translated from bitcoind's IsDefinedHashtypeSignature
|
|
*/
|
|
Signature.prototype.hasDefinedHashtype = function() {
|
|
if (!JSUtil.isNaturalNumber(this.nhashtype)) {
|
|
return false;
|
|
}
|
|
// accept with or without Signature.SIGHASH_ANYONECANPAY by ignoring the bit
|
|
var temp = this.nhashtype & ~Signature.SIGHASH_ANYONECANPAY;
|
|
if (temp < Signature.SIGHASH_ALL || temp > Signature.SIGHASH_SINGLE) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
Signature.prototype.toTxFormat = function() {
|
|
var derbuf = this.toDER();
|
|
var buf = new Buffer(1);
|
|
buf.writeUInt8(this.nhashtype, 0);
|
|
return Buffer.concat([derbuf, buf]);
|
|
};
|
|
|
|
Signature.SIGHASH_ALL = 0x01;
|
|
Signature.SIGHASH_NONE = 0x02;
|
|
Signature.SIGHASH_SINGLE = 0x03;
|
|
Signature.SIGHASH_ANYONECANPAY = 0x80;
|
|
|
|
module.exports = Signature;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../util/buffer":42,"../util/js":43,"../util/preconditions":44,"./bn":6,"buffer":47,"lodash":319}],12:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var bs58 = require('bs58');
|
|
var buffer = require('buffer');
|
|
|
|
var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'.split('');
|
|
|
|
var Base58 = function Base58(obj) {
|
|
/* jshint maxcomplexity: 8 */
|
|
if (!(this instanceof Base58)) {
|
|
return new Base58(obj);
|
|
}
|
|
if (Buffer.isBuffer(obj)) {
|
|
var buf = obj;
|
|
this.fromBuffer(buf);
|
|
} else if (typeof obj === 'string') {
|
|
var str = obj;
|
|
this.fromString(str);
|
|
} else if (obj) {
|
|
this.set(obj);
|
|
}
|
|
};
|
|
|
|
Base58.validCharacters = function validCharacters(chars) {
|
|
if (buffer.Buffer.isBuffer(chars)) {
|
|
chars = chars.toString();
|
|
}
|
|
return _.every(_.map(chars, function(char) { return _.includes(ALPHABET, char); }));
|
|
};
|
|
|
|
Base58.prototype.set = function(obj) {
|
|
this.buf = obj.buf || this.buf || undefined;
|
|
return this;
|
|
};
|
|
|
|
Base58.encode = function(buf) {
|
|
if (!buffer.Buffer.isBuffer(buf)) {
|
|
throw new Error('Input should be a buffer');
|
|
}
|
|
return bs58.encode(buf);
|
|
};
|
|
|
|
Base58.decode = function(str) {
|
|
if (typeof str !== 'string') {
|
|
throw new Error('Input should be a string');
|
|
}
|
|
return new Buffer(bs58.decode(str));
|
|
};
|
|
|
|
Base58.prototype.fromBuffer = function(buf) {
|
|
this.buf = buf;
|
|
return this;
|
|
};
|
|
|
|
Base58.prototype.fromString = function(str) {
|
|
var buf = Base58.decode(str);
|
|
this.buf = buf;
|
|
return this;
|
|
};
|
|
|
|
Base58.prototype.toBuffer = function() {
|
|
return this.buf;
|
|
};
|
|
|
|
Base58.prototype.toString = function() {
|
|
return Base58.encode(this.buf);
|
|
};
|
|
|
|
module.exports = Base58;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"bs58":281,"buffer":47,"lodash":319}],13:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var Base58 = require('./base58');
|
|
var buffer = require('buffer');
|
|
var sha256sha256 = require('../crypto/hash').sha256sha256;
|
|
|
|
var Base58Check = function Base58Check(obj) {
|
|
if (!(this instanceof Base58Check))
|
|
return new Base58Check(obj);
|
|
if (Buffer.isBuffer(obj)) {
|
|
var buf = obj;
|
|
this.fromBuffer(buf);
|
|
} else if (typeof obj === 'string') {
|
|
var str = obj;
|
|
this.fromString(str);
|
|
} else if (obj) {
|
|
this.set(obj);
|
|
}
|
|
};
|
|
|
|
Base58Check.prototype.set = function(obj) {
|
|
this.buf = obj.buf || this.buf || undefined;
|
|
return this;
|
|
};
|
|
|
|
Base58Check.validChecksum = function validChecksum(data, checksum) {
|
|
if (_.isString(data)) {
|
|
data = new buffer.Buffer(Base58.decode(data));
|
|
}
|
|
if (_.isString(checksum)) {
|
|
checksum = new buffer.Buffer(Base58.decode(checksum));
|
|
}
|
|
if (!checksum) {
|
|
checksum = data.slice(-4);
|
|
data = data.slice(0, -4);
|
|
}
|
|
return Base58Check.checksum(data).toString('hex') === checksum.toString('hex');
|
|
};
|
|
|
|
Base58Check.decode = function(s) {
|
|
if (typeof s !== 'string')
|
|
throw new Error('Input must be a string');
|
|
|
|
var buf = new Buffer(Base58.decode(s));
|
|
|
|
if (buf.length < 4)
|
|
throw new Error("Input string too short");
|
|
|
|
var data = buf.slice(0, -4);
|
|
var csum = buf.slice(-4);
|
|
|
|
var hash = sha256sha256(data);
|
|
var hash4 = hash.slice(0, 4);
|
|
|
|
if (csum.toString('hex') !== hash4.toString('hex'))
|
|
throw new Error("Checksum mismatch");
|
|
|
|
return data;
|
|
};
|
|
|
|
Base58Check.checksum = function(buffer) {
|
|
return sha256sha256(buffer).slice(0, 4);
|
|
};
|
|
|
|
Base58Check.encode = function(buf) {
|
|
if (!Buffer.isBuffer(buf))
|
|
throw new Error('Input must be a buffer');
|
|
var checkedBuf = new Buffer(buf.length + 4);
|
|
var hash = Base58Check.checksum(buf);
|
|
buf.copy(checkedBuf);
|
|
hash.copy(checkedBuf, buf.length);
|
|
return Base58.encode(checkedBuf);
|
|
};
|
|
|
|
Base58Check.prototype.fromBuffer = function(buf) {
|
|
this.buf = buf;
|
|
return this;
|
|
};
|
|
|
|
Base58Check.prototype.fromString = function(str) {
|
|
var buf = Base58Check.decode(str);
|
|
this.buf = buf;
|
|
return this;
|
|
};
|
|
|
|
Base58Check.prototype.toBuffer = function() {
|
|
return this.buf;
|
|
};
|
|
|
|
Base58Check.prototype.toString = function() {
|
|
return Base58Check.encode(this.buf);
|
|
};
|
|
|
|
module.exports = Base58Check;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../crypto/hash":8,"./base58":12,"buffer":47,"lodash":319}],14:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var $ = require('../util/preconditions');
|
|
var BufferUtil = require('../util/buffer');
|
|
var BN = require('../crypto/bn');
|
|
|
|
var BufferReader = function BufferReader(buf) {
|
|
if (!(this instanceof BufferReader)) {
|
|
return new BufferReader(buf);
|
|
}
|
|
if (_.isUndefined(buf)) {
|
|
return;
|
|
}
|
|
if (Buffer.isBuffer(buf)) {
|
|
this.set({
|
|
buf: buf
|
|
});
|
|
} else if (_.isString(buf)) {
|
|
this.set({
|
|
buf: new Buffer(buf, 'hex'),
|
|
});
|
|
} else if (_.isObject(buf)) {
|
|
var obj = buf;
|
|
this.set(obj);
|
|
} else {
|
|
throw new TypeError('Unrecognized argument for BufferReader');
|
|
}
|
|
};
|
|
|
|
BufferReader.prototype.set = function(obj) {
|
|
this.buf = obj.buf || this.buf || undefined;
|
|
this.pos = obj.pos || this.pos || 0;
|
|
return this;
|
|
};
|
|
|
|
BufferReader.prototype.eof = function() {
|
|
return this.pos >= this.buf.length;
|
|
};
|
|
|
|
BufferReader.prototype.finished = BufferReader.prototype.eof;
|
|
|
|
BufferReader.prototype.read = function(len) {
|
|
$.checkArgument(!_.isUndefined(len), 'Must specify a length');
|
|
var buf = this.buf.slice(this.pos, this.pos + len);
|
|
this.pos = this.pos + len;
|
|
return buf;
|
|
};
|
|
|
|
BufferReader.prototype.readAll = function() {
|
|
var buf = this.buf.slice(this.pos, this.buf.length);
|
|
this.pos = this.buf.length;
|
|
return buf;
|
|
};
|
|
|
|
BufferReader.prototype.readUInt8 = function() {
|
|
var val = this.buf.readUInt8(this.pos);
|
|
this.pos = this.pos + 1;
|
|
return val;
|
|
};
|
|
|
|
BufferReader.prototype.readUInt16BE = function() {
|
|
var val = this.buf.readUInt16BE(this.pos);
|
|
this.pos = this.pos + 2;
|
|
return val;
|
|
};
|
|
|
|
BufferReader.prototype.readUInt16LE = function() {
|
|
var val = this.buf.readUInt16LE(this.pos);
|
|
this.pos = this.pos + 2;
|
|
return val;
|
|
};
|
|
|
|
BufferReader.prototype.readUInt32BE = function() {
|
|
var val = this.buf.readUInt32BE(this.pos);
|
|
this.pos = this.pos + 4;
|
|
return val;
|
|
};
|
|
|
|
BufferReader.prototype.readUInt32LE = function() {
|
|
var val = this.buf.readUInt32LE(this.pos);
|
|
this.pos = this.pos + 4;
|
|
return val;
|
|
};
|
|
|
|
BufferReader.prototype.readInt32LE = function() {
|
|
var val = this.buf.readInt32LE(this.pos);
|
|
this.pos = this.pos + 4;
|
|
return val;
|
|
};
|
|
|
|
BufferReader.prototype.readUInt64BEBN = function() {
|
|
var buf = this.buf.slice(this.pos, this.pos + 8);
|
|
var bn = BN.fromBuffer(buf);
|
|
this.pos = this.pos + 8;
|
|
return bn;
|
|
};
|
|
|
|
BufferReader.prototype.readUInt64LEBN = function() {
|
|
var second = this.buf.readUInt32LE(this.pos);
|
|
var first = this.buf.readUInt32LE(this.pos + 4);
|
|
var combined = (first * 0x100000000) + second;
|
|
// Instantiating an instance of BN with a number is faster than with an
|
|
// array or string. However, the maximum safe number for a double precision
|
|
// floating point is 2 ^ 52 - 1 (0x1fffffffffffff), thus we can safely use
|
|
// non-floating point numbers less than this amount (52 bits). And in the case
|
|
// that the number is larger, we can instatiate an instance of BN by passing
|
|
// an array from the buffer (slower) and specifying the endianness.
|
|
var bn;
|
|
if (combined <= 0x1fffffffffffff) {
|
|
bn = new BN(combined);
|
|
} else {
|
|
var data = Array.prototype.slice.call(this.buf, this.pos, this.pos + 8);
|
|
bn = new BN(data, 10, 'le');
|
|
}
|
|
this.pos = this.pos + 8;
|
|
return bn;
|
|
};
|
|
|
|
BufferReader.prototype.readVarintNum = function() {
|
|
var first = this.readUInt8();
|
|
switch (first) {
|
|
case 0xFD:
|
|
return this.readUInt16LE();
|
|
case 0xFE:
|
|
return this.readUInt32LE();
|
|
case 0xFF:
|
|
var bn = this.readUInt64LEBN();
|
|
var n = bn.toNumber();
|
|
if (n <= Math.pow(2, 53)) {
|
|
return n;
|
|
} else {
|
|
throw new Error('number too large to retain precision - use readVarintBN');
|
|
}
|
|
break;
|
|
default:
|
|
return first;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* reads a length prepended buffer
|
|
*/
|
|
BufferReader.prototype.readVarLengthBuffer = function() {
|
|
var len = this.readVarintNum();
|
|
var buf = this.read(len);
|
|
$.checkState(buf.length === len, 'Invalid length while reading varlength buffer. ' +
|
|
'Expected to read: ' + len + ' and read ' + buf.length);
|
|
return buf;
|
|
};
|
|
|
|
BufferReader.prototype.readVarintBuf = function() {
|
|
var first = this.buf.readUInt8(this.pos);
|
|
switch (first) {
|
|
case 0xFD:
|
|
return this.read(1 + 2);
|
|
case 0xFE:
|
|
return this.read(1 + 4);
|
|
case 0xFF:
|
|
return this.read(1 + 8);
|
|
default:
|
|
return this.read(1);
|
|
}
|
|
};
|
|
|
|
BufferReader.prototype.readVarintBN = function() {
|
|
var first = this.readUInt8();
|
|
switch (first) {
|
|
case 0xFD:
|
|
return new BN(this.readUInt16LE());
|
|
case 0xFE:
|
|
return new BN(this.readUInt32LE());
|
|
case 0xFF:
|
|
return this.readUInt64LEBN();
|
|
default:
|
|
return new BN(first);
|
|
}
|
|
};
|
|
|
|
BufferReader.prototype.reverse = function() {
|
|
var buf = new Buffer(this.buf.length);
|
|
for (var i = 0; i < buf.length; i++) {
|
|
buf[i] = this.buf[this.buf.length - 1 - i];
|
|
}
|
|
this.buf = buf;
|
|
return this;
|
|
};
|
|
|
|
BufferReader.prototype.readReverse = function(len) {
|
|
if (_.isUndefined(len)) {
|
|
len = this.buf.length;
|
|
}
|
|
var buf = this.buf.slice(this.pos, this.pos + len);
|
|
this.pos = this.pos + len;
|
|
return BufferUtil.reverse(buf);
|
|
};
|
|
|
|
module.exports = BufferReader;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../crypto/bn":6,"../util/buffer":42,"../util/preconditions":44,"buffer":47,"lodash":319}],15:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var bufferUtil = require('../util/buffer');
|
|
var assert = require('assert');
|
|
|
|
var BufferWriter = function BufferWriter(obj) {
|
|
if (!(this instanceof BufferWriter))
|
|
return new BufferWriter(obj);
|
|
if (obj)
|
|
this.set(obj);
|
|
else
|
|
this.bufs = [];
|
|
};
|
|
|
|
BufferWriter.prototype.set = function(obj) {
|
|
this.bufs = obj.bufs || this.bufs || [];
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.toBuffer = function() {
|
|
return this.concat();
|
|
};
|
|
|
|
BufferWriter.prototype.concat = function() {
|
|
return Buffer.concat(this.bufs);
|
|
};
|
|
|
|
BufferWriter.prototype.write = function(buf) {
|
|
assert(bufferUtil.isBuffer(buf));
|
|
this.bufs.push(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeReverse = function(buf) {
|
|
assert(bufferUtil.isBuffer(buf));
|
|
this.bufs.push(bufferUtil.reverse(buf));
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeUInt8 = function(n) {
|
|
var buf = new Buffer(1);
|
|
buf.writeUInt8(n, 0);
|
|
this.write(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeUInt16BE = function(n) {
|
|
var buf = new Buffer(2);
|
|
buf.writeUInt16BE(n, 0);
|
|
this.write(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeUInt16LE = function(n) {
|
|
var buf = new Buffer(2);
|
|
buf.writeUInt16LE(n, 0);
|
|
this.write(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeUInt32BE = function(n) {
|
|
var buf = new Buffer(4);
|
|
buf.writeUInt32BE(n, 0);
|
|
this.write(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeInt32LE = function(n) {
|
|
var buf = new Buffer(4);
|
|
buf.writeInt32LE(n, 0);
|
|
this.write(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeUInt32LE = function(n) {
|
|
var buf = new Buffer(4);
|
|
buf.writeUInt32LE(n, 0);
|
|
this.write(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeUInt64BEBN = function(bn) {
|
|
var buf = bn.toBuffer({size: 8});
|
|
this.write(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeUInt64LEBN = function(bn) {
|
|
var buf = bn.toBuffer({size: 8});
|
|
this.writeReverse(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeVarintNum = function(n) {
|
|
var buf = BufferWriter.varintBufNum(n);
|
|
this.write(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.prototype.writeVarintBN = function(bn) {
|
|
var buf = BufferWriter.varintBufBN(bn);
|
|
this.write(buf);
|
|
return this;
|
|
};
|
|
|
|
BufferWriter.varintBufNum = function(n) {
|
|
var buf = undefined;
|
|
if (n < 253) {
|
|
buf = new Buffer(1);
|
|
buf.writeUInt8(n, 0);
|
|
} else if (n < 0x10000) {
|
|
buf = new Buffer(1 + 2);
|
|
buf.writeUInt8(253, 0);
|
|
buf.writeUInt16LE(n, 1);
|
|
} else if (n < 0x100000000) {
|
|
buf = new Buffer(1 + 4);
|
|
buf.writeUInt8(254, 0);
|
|
buf.writeUInt32LE(n, 1);
|
|
} else {
|
|
buf = new Buffer(1 + 8);
|
|
buf.writeUInt8(255, 0);
|
|
buf.writeInt32LE(n & -1, 1);
|
|
buf.writeUInt32LE(Math.floor(n / 0x100000000), 5);
|
|
}
|
|
return buf;
|
|
};
|
|
|
|
BufferWriter.varintBufBN = function(bn) {
|
|
var buf = undefined;
|
|
var n = bn.toNumber();
|
|
if (n < 253) {
|
|
buf = new Buffer(1);
|
|
buf.writeUInt8(n, 0);
|
|
} else if (n < 0x10000) {
|
|
buf = new Buffer(1 + 2);
|
|
buf.writeUInt8(253, 0);
|
|
buf.writeUInt16LE(n, 1);
|
|
} else if (n < 0x100000000) {
|
|
buf = new Buffer(1 + 4);
|
|
buf.writeUInt8(254, 0);
|
|
buf.writeUInt32LE(n, 1);
|
|
} else {
|
|
var bw = new BufferWriter();
|
|
bw.writeUInt8(255);
|
|
bw.writeUInt64LEBN(bn);
|
|
var buf = bw.concat();
|
|
}
|
|
return buf;
|
|
};
|
|
|
|
module.exports = BufferWriter;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../util/buffer":42,"assert":45,"buffer":47}],16:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var BufferWriter = require('./bufferwriter');
|
|
var BufferReader = require('./bufferreader');
|
|
var BN = require('../crypto/bn');
|
|
|
|
var Varint = function Varint(buf) {
|
|
if (!(this instanceof Varint))
|
|
return new Varint(buf);
|
|
if (Buffer.isBuffer(buf)) {
|
|
this.buf = buf;
|
|
} else if (typeof buf === 'number') {
|
|
var num = buf;
|
|
this.fromNumber(num);
|
|
} else if (buf instanceof BN) {
|
|
var bn = buf;
|
|
this.fromBN(bn);
|
|
} else if (buf) {
|
|
var obj = buf;
|
|
this.set(obj);
|
|
}
|
|
};
|
|
|
|
Varint.prototype.set = function(obj) {
|
|
this.buf = obj.buf || this.buf;
|
|
return this;
|
|
};
|
|
|
|
Varint.prototype.fromString = function(str) {
|
|
this.set({
|
|
buf: new Buffer(str, 'hex')
|
|
});
|
|
return this;
|
|
};
|
|
|
|
Varint.prototype.toString = function() {
|
|
return this.buf.toString('hex');
|
|
};
|
|
|
|
Varint.prototype.fromBuffer = function(buf) {
|
|
this.buf = buf;
|
|
return this;
|
|
};
|
|
|
|
Varint.prototype.fromBufferReader = function(br) {
|
|
this.buf = br.readVarintBuf();
|
|
return this;
|
|
};
|
|
|
|
Varint.prototype.fromBN = function(bn) {
|
|
this.buf = BufferWriter().writeVarintBN(bn).concat();
|
|
return this;
|
|
};
|
|
|
|
Varint.prototype.fromNumber = function(num) {
|
|
this.buf = BufferWriter().writeVarintNum(num).concat();
|
|
return this;
|
|
};
|
|
|
|
Varint.prototype.toBuffer = function() {
|
|
return this.buf;
|
|
};
|
|
|
|
Varint.prototype.toBN = function() {
|
|
return BufferReader(this.buf).readVarintBN();
|
|
};
|
|
|
|
Varint.prototype.toNumber = function() {
|
|
return BufferReader(this.buf).readVarintNum();
|
|
};
|
|
|
|
module.exports = Varint;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../crypto/bn":6,"./bufferreader":14,"./bufferwriter":15,"buffer":47}],17:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
|
|
function format(message, args) {
|
|
return message
|
|
.replace('{0}', args[0])
|
|
.replace('{1}', args[1])
|
|
.replace('{2}', args[2]);
|
|
}
|
|
var traverseNode = function(parent, errorDefinition) {
|
|
var NodeError = function() {
|
|
if (_.isString(errorDefinition.message)) {
|
|
this.message = format(errorDefinition.message, arguments);
|
|
} else if (_.isFunction(errorDefinition.message)) {
|
|
this.message = errorDefinition.message.apply(null, arguments);
|
|
} else {
|
|
throw new Error('Invalid error definition for ' + errorDefinition.name);
|
|
}
|
|
this.stack = this.message + '\n' + (new Error()).stack;
|
|
};
|
|
NodeError.prototype = Object.create(parent.prototype);
|
|
NodeError.prototype.name = parent.prototype.name + errorDefinition.name;
|
|
parent[errorDefinition.name] = NodeError;
|
|
if (errorDefinition.errors) {
|
|
childDefinitions(NodeError, errorDefinition.errors);
|
|
}
|
|
return NodeError;
|
|
};
|
|
|
|
/* jshint latedef: false */
|
|
var childDefinitions = function(parent, childDefinitions) {
|
|
_.each(childDefinitions, function(childDefinition) {
|
|
traverseNode(parent, childDefinition);
|
|
});
|
|
};
|
|
/* jshint latedef: true */
|
|
|
|
var traverseRoot = function(parent, errorsDefinition) {
|
|
childDefinitions(parent, errorsDefinition);
|
|
return parent;
|
|
};
|
|
|
|
|
|
var bitcore = {};
|
|
bitcore.Error = function() {
|
|
this.message = 'Internal error';
|
|
this.stack = this.message + '\n' + (new Error()).stack;
|
|
};
|
|
bitcore.Error.prototype = Object.create(Error.prototype);
|
|
bitcore.Error.prototype.name = 'bitcore.Error';
|
|
|
|
|
|
var data = require('./spec');
|
|
traverseRoot(bitcore.Error, data);
|
|
|
|
module.exports = bitcore.Error;
|
|
|
|
module.exports.extend = function(spec) {
|
|
return traverseNode(bitcore.Error, spec);
|
|
};
|
|
|
|
},{"./spec":18,"lodash":319}],18:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var docsURL = 'http://bitcore.io/';
|
|
|
|
module.exports = [{
|
|
name: 'InvalidB58Char',
|
|
message: 'Invalid Base58 character: {0} in {1}'
|
|
}, {
|
|
name: 'InvalidB58Checksum',
|
|
message: 'Invalid Base58 checksum for {0}'
|
|
}, {
|
|
name: 'InvalidNetwork',
|
|
message: 'Invalid version for network: got {0}'
|
|
}, {
|
|
name: 'InvalidState',
|
|
message: 'Invalid state: {0}'
|
|
}, {
|
|
name: 'NotImplemented',
|
|
message: 'Function {0} was not implemented yet'
|
|
}, {
|
|
name: 'InvalidNetworkArgument',
|
|
message: 'Invalid network: must be "livenet" or "testnet", got {0}'
|
|
}, {
|
|
name: 'InvalidArgument',
|
|
message: function() {
|
|
return 'Invalid Argument' + (arguments[0] ? (': ' + arguments[0]) : '') +
|
|
(arguments[1] ? (' Documentation: ' + docsURL + arguments[1]) : '');
|
|
}
|
|
}, {
|
|
name: 'AbstractMethodInvoked',
|
|
message: 'Abstract Method Invocation: {0}'
|
|
}, {
|
|
name: 'InvalidArgumentType',
|
|
message: function() {
|
|
return 'Invalid Argument for ' + arguments[2] + ', expected ' + arguments[1] + ' but got ' + typeof arguments[0];
|
|
}
|
|
}, {
|
|
name: 'Unit',
|
|
message: 'Internal Error on Unit {0}',
|
|
errors: [{
|
|
'name': 'UnknownCode',
|
|
'message': 'Unrecognized unit code: {0}'
|
|
}, {
|
|
'name': 'InvalidRate',
|
|
'message': 'Invalid exchange rate: {0}'
|
|
}]
|
|
}, {
|
|
name: 'MerkleBlock',
|
|
message: 'Internal Error on MerkleBlock {0}',
|
|
errors: [{
|
|
'name': 'InvalidMerkleTree',
|
|
'message': 'This MerkleBlock contain an invalid Merkle Tree'
|
|
}]
|
|
}, {
|
|
name: 'Transaction',
|
|
message: 'Internal Error on Transaction {0}',
|
|
errors: [{
|
|
name: 'Input',
|
|
message: 'Internal Error on Input {0}',
|
|
errors: [{
|
|
name: 'MissingScript',
|
|
message: 'Need a script to create an input'
|
|
}, {
|
|
name: 'UnsupportedScript',
|
|
message: 'Unsupported input script type: {0}'
|
|
}, {
|
|
name: 'MissingPreviousOutput',
|
|
message: 'No previous output information.'
|
|
}]
|
|
}, {
|
|
name: 'NeedMoreInfo',
|
|
message: '{0}'
|
|
}, {
|
|
name: 'InvalidSorting',
|
|
message: 'The sorting function provided did not return the change output as one of the array elements'
|
|
}, {
|
|
name: 'InvalidOutputAmountSum',
|
|
message: '{0}'
|
|
}, {
|
|
name: 'MissingSignatures',
|
|
message: 'Some inputs have not been fully signed'
|
|
}, {
|
|
name: 'InvalidIndex',
|
|
message: 'Invalid index: {0} is not between 0, {1}'
|
|
}, {
|
|
name: 'UnableToVerifySignature',
|
|
message: 'Unable to verify signature: {0}'
|
|
}, {
|
|
name: 'DustOutputs',
|
|
message: 'Dust amount detected in one output'
|
|
}, {
|
|
name: 'InvalidSatoshis',
|
|
message: 'Output satoshis are invalid',
|
|
}, {
|
|
name: 'FeeError',
|
|
message: 'Internal Error on Fee {0}',
|
|
errors: [{
|
|
name: 'TooSmall',
|
|
message: 'Fee is too small: {0}',
|
|
}, {
|
|
name: 'TooLarge',
|
|
message: 'Fee is too large: {0}',
|
|
}, {
|
|
name: 'Different',
|
|
message: 'Unspent value is different from specified fee: {0}',
|
|
}]
|
|
}, {
|
|
name: 'ChangeAddressMissing',
|
|
message: 'Change address is missing'
|
|
}, {
|
|
name: 'BlockHeightTooHigh',
|
|
message: 'Block Height can be at most 2^32 -1'
|
|
}, {
|
|
name: 'NLockTimeOutOfRange',
|
|
message: 'Block Height can only be between 0 and 499 999 999'
|
|
}, {
|
|
name: 'LockTimeTooEarly',
|
|
message: 'Lock Time can\'t be earlier than UNIX date 500 000 000'
|
|
}]
|
|
}, {
|
|
name: 'Script',
|
|
message: 'Internal Error on Script {0}',
|
|
errors: [{
|
|
name: 'UnrecognizedAddress',
|
|
message: 'Expected argument {0} to be an address'
|
|
}, {
|
|
name: 'CantDeriveAddress',
|
|
message: 'Can\'t derive address associated with script {0}, needs to be p2pkh in, p2pkh out, p2sh in, or p2sh out.'
|
|
}, {
|
|
name: 'InvalidBuffer',
|
|
message: 'Invalid script buffer: can\'t parse valid script from given buffer {0}'
|
|
}]
|
|
}, {
|
|
name: 'HDPrivateKey',
|
|
message: 'Internal Error on HDPrivateKey {0}',
|
|
errors: [{
|
|
name: 'InvalidDerivationArgument',
|
|
message: 'Invalid derivation argument {0}, expected string, or number and boolean'
|
|
}, {
|
|
name: 'InvalidEntropyArgument',
|
|
message: 'Invalid entropy: must be an hexa string or binary buffer, got {0}',
|
|
errors: [{
|
|
name: 'TooMuchEntropy',
|
|
message: 'Invalid entropy: more than 512 bits is non standard, got "{0}"'
|
|
}, {
|
|
name: 'NotEnoughEntropy',
|
|
message: 'Invalid entropy: at least 128 bits needed, got "{0}"'
|
|
}]
|
|
}, {
|
|
name: 'InvalidLength',
|
|
message: 'Invalid length for xprivkey string in {0}'
|
|
}, {
|
|
name: 'InvalidPath',
|
|
message: 'Invalid derivation path: {0}'
|
|
}, {
|
|
name: 'UnrecognizedArgument',
|
|
message: 'Invalid argument: creating a HDPrivateKey requires a string, buffer, json or object, got "{0}"'
|
|
}]
|
|
}, {
|
|
name: 'HDPublicKey',
|
|
message: 'Internal Error on HDPublicKey {0}',
|
|
errors: [{
|
|
name: 'ArgumentIsPrivateExtended',
|
|
message: 'Argument is an extended private key: {0}'
|
|
}, {
|
|
name: 'InvalidDerivationArgument',
|
|
message: 'Invalid derivation argument: got {0}'
|
|
}, {
|
|
name: 'InvalidLength',
|
|
message: 'Invalid length for xpubkey: got "{0}"'
|
|
}, {
|
|
name: 'InvalidPath',
|
|
message: 'Invalid derivation path, it should look like: "m/1/100", got "{0}"'
|
|
}, {
|
|
name: 'InvalidIndexCantDeriveHardened',
|
|
message: 'Invalid argument: creating a hardened path requires an HDPrivateKey'
|
|
}, {
|
|
name: 'MustSupplyArgument',
|
|
message: 'Must supply an argument to create a HDPublicKey'
|
|
}, {
|
|
name: 'UnrecognizedArgument',
|
|
message: 'Invalid argument for creation, must be string, json, buffer, or object'
|
|
}]
|
|
}];
|
|
|
|
},{}],19:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
|
|
var assert = require('assert');
|
|
var buffer = require('buffer');
|
|
var _ = require('lodash');
|
|
var $ = require('./util/preconditions');
|
|
|
|
var BN = require('./crypto/bn');
|
|
var Base58 = require('./encoding/base58');
|
|
var Base58Check = require('./encoding/base58check');
|
|
var Hash = require('./crypto/hash');
|
|
var Network = require('./networks');
|
|
var Point = require('./crypto/point');
|
|
var PrivateKey = require('./privatekey');
|
|
var Random = require('./crypto/random');
|
|
|
|
var errors = require('./errors');
|
|
var hdErrors = errors.HDPrivateKey;
|
|
var BufferUtil = require('./util/buffer');
|
|
var JSUtil = require('./util/js');
|
|
|
|
var MINIMUM_ENTROPY_BITS = 128;
|
|
var BITS_TO_BYTES = 1 / 8;
|
|
var MAXIMUM_ENTROPY_BITS = 512;
|
|
|
|
|
|
/**
|
|
* Represents an instance of an hierarchically derived private key.
|
|
*
|
|
* More info on https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
|
|
*
|
|
* @constructor
|
|
* @param {string|Buffer|Object} arg
|
|
*/
|
|
function HDPrivateKey(arg) {
|
|
/* jshint maxcomplexity: 10 */
|
|
if (arg instanceof HDPrivateKey) {
|
|
return arg;
|
|
}
|
|
if (!(this instanceof HDPrivateKey)) {
|
|
return new HDPrivateKey(arg);
|
|
}
|
|
if (!arg) {
|
|
return this._generateRandomly();
|
|
}
|
|
|
|
if (Network.get(arg)) {
|
|
return this._generateRandomly(arg);
|
|
} else if (_.isString(arg) || BufferUtil.isBuffer(arg)) {
|
|
if (HDPrivateKey.isValidSerialized(arg)) {
|
|
this._buildFromSerialized(arg);
|
|
} else if (JSUtil.isValidJSON(arg)) {
|
|
this._buildFromJSON(arg);
|
|
} else if (BufferUtil.isBuffer(arg) && HDPrivateKey.isValidSerialized(arg.toString())) {
|
|
this._buildFromSerialized(arg.toString());
|
|
} else {
|
|
throw HDPrivateKey.getSerializedError(arg);
|
|
}
|
|
} else if (_.isObject(arg)) {
|
|
this._buildFromObject(arg);
|
|
} else {
|
|
throw new hdErrors.UnrecognizedArgument(arg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verifies that a given path is valid.
|
|
*
|
|
* @param {string|number} arg
|
|
* @param {boolean?} hardened
|
|
* @return {boolean}
|
|
*/
|
|
HDPrivateKey.isValidPath = function(arg, hardened) {
|
|
if (_.isString(arg)) {
|
|
var indexes = HDPrivateKey._getDerivationIndexes(arg);
|
|
return indexes !== null && _.every(indexes, HDPrivateKey.isValidPath);
|
|
}
|
|
|
|
if (_.isNumber(arg)) {
|
|
if (arg < HDPrivateKey.Hardened && hardened === true) {
|
|
arg += HDPrivateKey.Hardened;
|
|
}
|
|
return arg >= 0 && arg < HDPrivateKey.MaxIndex;
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Internal function that splits a string path into a derivation index array.
|
|
* It will return null if the string path is malformed.
|
|
* It does not validate if indexes are in bounds.
|
|
*
|
|
* @param {string} path
|
|
* @return {Array}
|
|
*/
|
|
HDPrivateKey._getDerivationIndexes = function(path) {
|
|
var steps = path.split('/');
|
|
|
|
// Special cases:
|
|
if (_.includes(HDPrivateKey.RootElementAlias, path)) {
|
|
return [];
|
|
}
|
|
|
|
if (!_.includes(HDPrivateKey.RootElementAlias, steps[0])) {
|
|
return null;
|
|
}
|
|
|
|
var indexes = steps.slice(1).map(function(step) {
|
|
var isHardened = step.slice(-1) === '\'';
|
|
if (isHardened) {
|
|
step = step.slice(0, -1);
|
|
}
|
|
if (!step || step[0] === '-') {
|
|
return NaN;
|
|
}
|
|
var index = +step; // cast to number
|
|
if (isHardened) {
|
|
index += HDPrivateKey.Hardened;
|
|
}
|
|
|
|
return index;
|
|
});
|
|
|
|
return _.some(indexes, isNaN) ? null : indexes;
|
|
};
|
|
|
|
/**
|
|
* WARNING: This method is deprecated. Use deriveChild or deriveNonCompliantChild instead. This is not BIP32 compliant
|
|
*
|
|
*
|
|
* Get a derived child based on a string or number.
|
|
*
|
|
* If the first argument is a string, it's parsed as the full path of
|
|
* derivation. Valid values for this argument include "m" (which returns the
|
|
* same private key), "m/0/1/40/2'/1000", where the ' quote means a hardened
|
|
* derivation.
|
|
*
|
|
* If the first argument is a number, the child with that index will be
|
|
* derived. If the second argument is truthy, the hardened version will be
|
|
* derived. See the example usage for clarification.
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* var parent = new HDPrivateKey('xprv...');
|
|
* var child_0_1_2h = parent.derive(0).derive(1).derive(2, true);
|
|
* var copy_of_child_0_1_2h = parent.derive("m/0/1/2'");
|
|
* assert(child_0_1_2h.xprivkey === copy_of_child_0_1_2h);
|
|
* ```
|
|
*
|
|
* @param {string|number} arg
|
|
* @param {boolean?} hardened
|
|
*/
|
|
HDPrivateKey.prototype.derive = function(arg, hardened) {
|
|
return this.deriveNonCompliantChild(arg, hardened);
|
|
};
|
|
|
|
/**
|
|
* WARNING: This method will not be officially supported until v1.0.0.
|
|
*
|
|
*
|
|
* Get a derived child based on a string or number.
|
|
*
|
|
* If the first argument is a string, it's parsed as the full path of
|
|
* derivation. Valid values for this argument include "m" (which returns the
|
|
* same private key), "m/0/1/40/2'/1000", where the ' quote means a hardened
|
|
* derivation.
|
|
*
|
|
* If the first argument is a number, the child with that index will be
|
|
* derived. If the second argument is truthy, the hardened version will be
|
|
* derived. See the example usage for clarification.
|
|
*
|
|
* WARNING: The `nonCompliant` option should NOT be used, except for older implementation
|
|
* that used a derivation strategy that used a non-zero padded private key.
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* var parent = new HDPrivateKey('xprv...');
|
|
* var child_0_1_2h = parent.deriveChild(0).deriveChild(1).deriveChild(2, true);
|
|
* var copy_of_child_0_1_2h = parent.deriveChild("m/0/1/2'");
|
|
* assert(child_0_1_2h.xprivkey === copy_of_child_0_1_2h);
|
|
* ```
|
|
*
|
|
* @param {string|number} arg
|
|
* @param {boolean?} hardened
|
|
*/
|
|
HDPrivateKey.prototype.deriveChild = function(arg, hardened) {
|
|
if (_.isNumber(arg)) {
|
|
return this._deriveWithNumber(arg, hardened);
|
|
} else if (_.isString(arg)) {
|
|
return this._deriveFromString(arg);
|
|
} else {
|
|
throw new hdErrors.InvalidDerivationArgument(arg);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* WARNING: This method will not be officially supported until v1.0.0
|
|
*
|
|
*
|
|
* WARNING: If this is a new implementation you should NOT use this method, you should be using
|
|
* `derive` instead.
|
|
*
|
|
* This method is explicitly for use and compatibility with an implementation that
|
|
* was not compliant with BIP32 regarding the derivation algorithm. The private key
|
|
* must be 32 bytes hashing, and this implementation will use the non-zero padded
|
|
* serialization of a private key, such that it's still possible to derive the privateKey
|
|
* to recover those funds.
|
|
*
|
|
* @param {string|number} arg
|
|
* @param {boolean?} hardened
|
|
*/
|
|
HDPrivateKey.prototype.deriveNonCompliantChild = function(arg, hardened) {
|
|
if (_.isNumber(arg)) {
|
|
return this._deriveWithNumber(arg, hardened, true);
|
|
} else if (_.isString(arg)) {
|
|
return this._deriveFromString(arg, true);
|
|
} else {
|
|
throw new hdErrors.InvalidDerivationArgument(arg);
|
|
}
|
|
};
|
|
|
|
HDPrivateKey.prototype._deriveWithNumber = function(index, hardened, nonCompliant) {
|
|
/* jshint maxstatements: 20 */
|
|
/* jshint maxcomplexity: 10 */
|
|
if (!HDPrivateKey.isValidPath(index, hardened)) {
|
|
throw new hdErrors.InvalidPath(index);
|
|
}
|
|
|
|
hardened = index >= HDPrivateKey.Hardened ? true : hardened;
|
|
if (index < HDPrivateKey.Hardened && hardened === true) {
|
|
index += HDPrivateKey.Hardened;
|
|
}
|
|
|
|
var indexBuffer = BufferUtil.integerAsBuffer(index);
|
|
var data;
|
|
if (hardened && nonCompliant) {
|
|
// The private key serialization in this case will not be exactly 32 bytes and can be
|
|
// any value less, and the value is not zero-padded.
|
|
var nonZeroPadded = this.privateKey.bn.toBuffer();
|
|
data = BufferUtil.concat([new buffer.Buffer([0]), nonZeroPadded, indexBuffer]);
|
|
} else if (hardened) {
|
|
// This will use a 32 byte zero padded serialization of the private key
|
|
var privateKeyBuffer = this.privateKey.bn.toBuffer({size: 32});
|
|
assert(privateKeyBuffer.length === 32, 'length of private key buffer is expected to be 32 bytes');
|
|
data = BufferUtil.concat([new buffer.Buffer([0]), privateKeyBuffer, indexBuffer]);
|
|
} else {
|
|
data = BufferUtil.concat([this.publicKey.toBuffer(), indexBuffer]);
|
|
}
|
|
var hash = Hash.sha512hmac(data, this._buffers.chainCode);
|
|
var leftPart = BN.fromBuffer(hash.slice(0, 32), {
|
|
size: 32
|
|
});
|
|
var chainCode = hash.slice(32, 64);
|
|
|
|
var privateKey = leftPart.add(this.privateKey.toBigNumber()).umod(Point.getN()).toBuffer({
|
|
size: 32
|
|
});
|
|
|
|
if (!PrivateKey.isValid(privateKey)) {
|
|
// Index at this point is already hardened, we can pass null as the hardened arg
|
|
return this._deriveWithNumber(index + 1, null, nonCompliant);
|
|
}
|
|
|
|
var derived = new HDPrivateKey({
|
|
network: this.network,
|
|
depth: this.depth + 1,
|
|
parentFingerPrint: this.fingerPrint,
|
|
childIndex: index,
|
|
chainCode: chainCode,
|
|
privateKey: privateKey
|
|
});
|
|
|
|
return derived;
|
|
};
|
|
|
|
HDPrivateKey.prototype._deriveFromString = function(path, nonCompliant) {
|
|
if (!HDPrivateKey.isValidPath(path)) {
|
|
throw new hdErrors.InvalidPath(path);
|
|
}
|
|
|
|
var indexes = HDPrivateKey._getDerivationIndexes(path);
|
|
var derived = indexes.reduce(function(prev, index) {
|
|
return prev._deriveWithNumber(index, null, nonCompliant);
|
|
}, this);
|
|
|
|
return derived;
|
|
};
|
|
|
|
/**
|
|
* Verifies that a given serialized private key in base58 with checksum format
|
|
* is valid.
|
|
*
|
|
* @param {string|Buffer} data - the serialized private key
|
|
* @param {string|Network=} network - optional, if present, checks that the
|
|
* network provided matches the network serialized.
|
|
* @return {boolean}
|
|
*/
|
|
HDPrivateKey.isValidSerialized = function(data, network) {
|
|
return !HDPrivateKey.getSerializedError(data, network);
|
|
};
|
|
|
|
/**
|
|
* Checks what's the error that causes the validation of a serialized private key
|
|
* in base58 with checksum to fail.
|
|
*
|
|
* @param {string|Buffer} data - the serialized private key
|
|
* @param {string|Network=} network - optional, if present, checks that the
|
|
* network provided matches the network serialized.
|
|
* @return {errors.InvalidArgument|null}
|
|
*/
|
|
HDPrivateKey.getSerializedError = function(data, network) {
|
|
/* jshint maxcomplexity: 10 */
|
|
if (!(_.isString(data) || BufferUtil.isBuffer(data))) {
|
|
return new hdErrors.UnrecognizedArgument('Expected string or buffer');
|
|
}
|
|
if (!Base58.validCharacters(data)) {
|
|
return new errors.InvalidB58Char('(unknown)', data);
|
|
}
|
|
try {
|
|
data = Base58Check.decode(data);
|
|
} catch (e) {
|
|
return new errors.InvalidB58Checksum(data);
|
|
}
|
|
if (data.length !== HDPrivateKey.DataLength) {
|
|
return new hdErrors.InvalidLength(data);
|
|
}
|
|
if (!_.isUndefined(network)) {
|
|
var error = HDPrivateKey._validateNetwork(data, network);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
HDPrivateKey._validateNetwork = function(data, networkArg) {
|
|
var network = Network.get(networkArg);
|
|
if (!network) {
|
|
return new errors.InvalidNetworkArgument(networkArg);
|
|
}
|
|
var version = data.slice(0, 4);
|
|
if (BufferUtil.integerFromBuffer(version) !== network.xprivkey) {
|
|
return new errors.InvalidNetwork(version);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
HDPrivateKey.fromString = function(arg) {
|
|
$.checkArgument(_.isString(arg), 'No valid string was provided');
|
|
return new HDPrivateKey(arg);
|
|
};
|
|
|
|
HDPrivateKey.fromObject = function(arg) {
|
|
$.checkArgument(_.isObject(arg), 'No valid argument was provided');
|
|
return new HDPrivateKey(arg);
|
|
};
|
|
|
|
HDPrivateKey.prototype._buildFromJSON = function(arg) {
|
|
return this._buildFromObject(JSON.parse(arg));
|
|
};
|
|
|
|
HDPrivateKey.prototype._buildFromObject = function(arg) {
|
|
/* jshint maxcomplexity: 12 */
|
|
// TODO: Type validation
|
|
var buffers = {
|
|
version: arg.network ? BufferUtil.integerAsBuffer(Network.get(arg.network).xprivkey) : arg.version,
|
|
depth: _.isNumber(arg.depth) ? BufferUtil.integerAsSingleByteBuffer(arg.depth) : arg.depth,
|
|
parentFingerPrint: _.isNumber(arg.parentFingerPrint) ? BufferUtil.integerAsBuffer(arg.parentFingerPrint) : arg.parentFingerPrint,
|
|
childIndex: _.isNumber(arg.childIndex) ? BufferUtil.integerAsBuffer(arg.childIndex) : arg.childIndex,
|
|
chainCode: _.isString(arg.chainCode) ? BufferUtil.hexToBuffer(arg.chainCode) : arg.chainCode,
|
|
privateKey: (_.isString(arg.privateKey) && JSUtil.isHexa(arg.privateKey)) ? BufferUtil.hexToBuffer(arg.privateKey) : arg.privateKey,
|
|
checksum: arg.checksum ? (arg.checksum.length ? arg.checksum : BufferUtil.integerAsBuffer(arg.checksum)) : undefined
|
|
};
|
|
return this._buildFromBuffers(buffers);
|
|
};
|
|
|
|
HDPrivateKey.prototype._buildFromSerialized = function(arg) {
|
|
var decoded = Base58Check.decode(arg);
|
|
var buffers = {
|
|
version: decoded.slice(HDPrivateKey.VersionStart, HDPrivateKey.VersionEnd),
|
|
depth: decoded.slice(HDPrivateKey.DepthStart, HDPrivateKey.DepthEnd),
|
|
parentFingerPrint: decoded.slice(HDPrivateKey.ParentFingerPrintStart,
|
|
HDPrivateKey.ParentFingerPrintEnd),
|
|
childIndex: decoded.slice(HDPrivateKey.ChildIndexStart, HDPrivateKey.ChildIndexEnd),
|
|
chainCode: decoded.slice(HDPrivateKey.ChainCodeStart, HDPrivateKey.ChainCodeEnd),
|
|
privateKey: decoded.slice(HDPrivateKey.PrivateKeyStart, HDPrivateKey.PrivateKeyEnd),
|
|
checksum: decoded.slice(HDPrivateKey.ChecksumStart, HDPrivateKey.ChecksumEnd),
|
|
xprivkey: arg
|
|
};
|
|
return this._buildFromBuffers(buffers);
|
|
};
|
|
|
|
HDPrivateKey.prototype._generateRandomly = function(network) {
|
|
return HDPrivateKey.fromSeed(Random.getRandomBuffer(64), network);
|
|
};
|
|
|
|
/**
|
|
* Generate a private key from a seed, as described in BIP32
|
|
*
|
|
* @param {string|Buffer} hexa
|
|
* @param {*} network
|
|
* @return HDPrivateKey
|
|
*/
|
|
HDPrivateKey.fromSeed = function(hexa, network) {
|
|
/* jshint maxcomplexity: 8 */
|
|
if (JSUtil.isHexaString(hexa)) {
|
|
hexa = BufferUtil.hexToBuffer(hexa);
|
|
}
|
|
if (!Buffer.isBuffer(hexa)) {
|
|
throw new hdErrors.InvalidEntropyArgument(hexa);
|
|
}
|
|
if (hexa.length < MINIMUM_ENTROPY_BITS * BITS_TO_BYTES) {
|
|
throw new hdErrors.InvalidEntropyArgument.NotEnoughEntropy(hexa);
|
|
}
|
|
if (hexa.length > MAXIMUM_ENTROPY_BITS * BITS_TO_BYTES) {
|
|
throw new hdErrors.InvalidEntropyArgument.TooMuchEntropy(hexa);
|
|
}
|
|
var hash = Hash.sha512hmac(hexa, new buffer.Buffer('Bitcoin seed'));
|
|
|
|
return new HDPrivateKey({
|
|
network: Network.get(network) || Network.defaultNetwork,
|
|
depth: 0,
|
|
parentFingerPrint: 0,
|
|
childIndex: 0,
|
|
privateKey: hash.slice(0, 32),
|
|
chainCode: hash.slice(32, 64)
|
|
});
|
|
};
|
|
|
|
|
|
|
|
HDPrivateKey.prototype._calcHDPublicKey = function() {
|
|
if (!this._hdPublicKey) {
|
|
var HDPublicKey = require('./hdpublickey');
|
|
this._hdPublicKey = new HDPublicKey(this);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Receives a object with buffers in all the properties and populates the
|
|
* internal structure
|
|
*
|
|
* @param {Object} arg
|
|
* @param {buffer.Buffer} arg.version
|
|
* @param {buffer.Buffer} arg.depth
|
|
* @param {buffer.Buffer} arg.parentFingerPrint
|
|
* @param {buffer.Buffer} arg.childIndex
|
|
* @param {buffer.Buffer} arg.chainCode
|
|
* @param {buffer.Buffer} arg.privateKey
|
|
* @param {buffer.Buffer} arg.checksum
|
|
* @param {string=} arg.xprivkey - if set, don't recalculate the base58
|
|
* representation
|
|
* @return {HDPrivateKey} this
|
|
*/
|
|
HDPrivateKey.prototype._buildFromBuffers = function(arg) {
|
|
/* jshint maxcomplexity: 8 */
|
|
/* jshint maxstatements: 20 */
|
|
|
|
HDPrivateKey._validateBufferArguments(arg);
|
|
|
|
JSUtil.defineImmutable(this, {
|
|
_buffers: arg
|
|
});
|
|
|
|
var sequence = [
|
|
arg.version, arg.depth, arg.parentFingerPrint, arg.childIndex, arg.chainCode,
|
|
BufferUtil.emptyBuffer(1), arg.privateKey
|
|
];
|
|
var concat = buffer.Buffer.concat(sequence);
|
|
if (!arg.checksum || !arg.checksum.length) {
|
|
arg.checksum = Base58Check.checksum(concat);
|
|
} else {
|
|
if (arg.checksum.toString() !== Base58Check.checksum(concat).toString()) {
|
|
throw new errors.InvalidB58Checksum(concat);
|
|
}
|
|
}
|
|
|
|
var network = Network.get(BufferUtil.integerFromBuffer(arg.version));
|
|
var xprivkey;
|
|
xprivkey = Base58Check.encode(buffer.Buffer.concat(sequence));
|
|
arg.xprivkey = new Buffer(xprivkey);
|
|
|
|
var privateKey = new PrivateKey(BN.fromBuffer(arg.privateKey), network);
|
|
var publicKey = privateKey.toPublicKey();
|
|
var size = HDPrivateKey.ParentFingerPrintSize;
|
|
var fingerPrint = Hash.sha256ripemd160(publicKey.toBuffer()).slice(0, size);
|
|
|
|
JSUtil.defineImmutable(this, {
|
|
xprivkey: xprivkey,
|
|
network: network,
|
|
depth: BufferUtil.integerFromSingleByteBuffer(arg.depth),
|
|
privateKey: privateKey,
|
|
publicKey: publicKey,
|
|
fingerPrint: fingerPrint
|
|
});
|
|
|
|
this._hdPublicKey = null;
|
|
|
|
Object.defineProperty(this, 'hdPublicKey', {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
this._calcHDPublicKey();
|
|
return this._hdPublicKey;
|
|
}
|
|
});
|
|
Object.defineProperty(this, 'xpubkey', {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
this._calcHDPublicKey();
|
|
return this._hdPublicKey.xpubkey;
|
|
}
|
|
});
|
|
return this;
|
|
};
|
|
|
|
HDPrivateKey._validateBufferArguments = function(arg) {
|
|
var checkBuffer = function(name, size) {
|
|
var buff = arg[name];
|
|
assert(BufferUtil.isBuffer(buff), name + ' argument is not a buffer');
|
|
assert(
|
|
buff.length === size,
|
|
name + ' has not the expected size: found ' + buff.length + ', expected ' + size
|
|
);
|
|
};
|
|
checkBuffer('version', HDPrivateKey.VersionSize);
|
|
checkBuffer('depth', HDPrivateKey.DepthSize);
|
|
checkBuffer('parentFingerPrint', HDPrivateKey.ParentFingerPrintSize);
|
|
checkBuffer('childIndex', HDPrivateKey.ChildIndexSize);
|
|
checkBuffer('chainCode', HDPrivateKey.ChainCodeSize);
|
|
checkBuffer('privateKey', HDPrivateKey.PrivateKeySize);
|
|
if (arg.checksum && arg.checksum.length) {
|
|
checkBuffer('checksum', HDPrivateKey.CheckSumSize);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Returns the string representation of this private key (a string starting
|
|
* with "xprv..."
|
|
*
|
|
* @return string
|
|
*/
|
|
HDPrivateKey.prototype.toString = function() {
|
|
return this.xprivkey;
|
|
};
|
|
|
|
/**
|
|
* Returns the console representation of this extended private key.
|
|
* @return string
|
|
*/
|
|
HDPrivateKey.prototype.inspect = function() {
|
|
return '<HDPrivateKey: ' + this.xprivkey + '>';
|
|
};
|
|
|
|
/**
|
|
* Returns a plain object with a representation of this private key.
|
|
*
|
|
* Fields include:<ul>
|
|
* <li> network: either 'livenet' or 'testnet'
|
|
* <li> depth: a number ranging from 0 to 255
|
|
* <li> fingerPrint: a number ranging from 0 to 2^32-1, taken from the hash of the
|
|
* <li> associated public key
|
|
* <li> parentFingerPrint: a number ranging from 0 to 2^32-1, taken from the hash
|
|
* <li> of this parent's associated public key or zero.
|
|
* <li> childIndex: the index from which this child was derived (or zero)
|
|
* <li> chainCode: an hexa string representing a number used in the derivation
|
|
* <li> privateKey: the private key associated, in hexa representation
|
|
* <li> xprivkey: the representation of this extended private key in checksum
|
|
* <li> base58 format
|
|
* <li> checksum: the base58 checksum of xprivkey
|
|
* </ul>
|
|
* @return {Object}
|
|
*/
|
|
HDPrivateKey.prototype.toObject = HDPrivateKey.prototype.toJSON = function toObject() {
|
|
return {
|
|
network: Network.get(BufferUtil.integerFromBuffer(this._buffers.version), 'xprivkey').name,
|
|
depth: BufferUtil.integerFromSingleByteBuffer(this._buffers.depth),
|
|
fingerPrint: BufferUtil.integerFromBuffer(this.fingerPrint),
|
|
parentFingerPrint: BufferUtil.integerFromBuffer(this._buffers.parentFingerPrint),
|
|
childIndex: BufferUtil.integerFromBuffer(this._buffers.childIndex),
|
|
chainCode: BufferUtil.bufferToHex(this._buffers.chainCode),
|
|
privateKey: this.privateKey.toBuffer().toString('hex'),
|
|
checksum: BufferUtil.integerFromBuffer(this._buffers.checksum),
|
|
xprivkey: this.xprivkey
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Build a HDPrivateKey from a buffer
|
|
*
|
|
* @param {Buffer} arg
|
|
* @return {HDPrivateKey}
|
|
*/
|
|
HDPrivateKey.fromBuffer = function(arg) {
|
|
return new HDPrivateKey(arg.toString());
|
|
};
|
|
|
|
/**
|
|
* Returns a buffer representation of the HDPrivateKey
|
|
*
|
|
* @return {string}
|
|
*/
|
|
HDPrivateKey.prototype.toBuffer = function() {
|
|
return BufferUtil.copy(this._buffers.xprivkey);
|
|
};
|
|
|
|
HDPrivateKey.DefaultDepth = 0;
|
|
HDPrivateKey.DefaultFingerprint = 0;
|
|
HDPrivateKey.DefaultChildIndex = 0;
|
|
HDPrivateKey.Hardened = 0x80000000;
|
|
HDPrivateKey.MaxIndex = 2 * HDPrivateKey.Hardened;
|
|
|
|
HDPrivateKey.RootElementAlias = ['m', 'M', 'm\'', 'M\''];
|
|
|
|
HDPrivateKey.VersionSize = 4;
|
|
HDPrivateKey.DepthSize = 1;
|
|
HDPrivateKey.ParentFingerPrintSize = 4;
|
|
HDPrivateKey.ChildIndexSize = 4;
|
|
HDPrivateKey.ChainCodeSize = 32;
|
|
HDPrivateKey.PrivateKeySize = 32;
|
|
HDPrivateKey.CheckSumSize = 4;
|
|
|
|
HDPrivateKey.DataLength = 78;
|
|
HDPrivateKey.SerializedByteSize = 82;
|
|
|
|
HDPrivateKey.VersionStart = 0;
|
|
HDPrivateKey.VersionEnd = HDPrivateKey.VersionStart + HDPrivateKey.VersionSize;
|
|
HDPrivateKey.DepthStart = HDPrivateKey.VersionEnd;
|
|
HDPrivateKey.DepthEnd = HDPrivateKey.DepthStart + HDPrivateKey.DepthSize;
|
|
HDPrivateKey.ParentFingerPrintStart = HDPrivateKey.DepthEnd;
|
|
HDPrivateKey.ParentFingerPrintEnd = HDPrivateKey.ParentFingerPrintStart + HDPrivateKey.ParentFingerPrintSize;
|
|
HDPrivateKey.ChildIndexStart = HDPrivateKey.ParentFingerPrintEnd;
|
|
HDPrivateKey.ChildIndexEnd = HDPrivateKey.ChildIndexStart + HDPrivateKey.ChildIndexSize;
|
|
HDPrivateKey.ChainCodeStart = HDPrivateKey.ChildIndexEnd;
|
|
HDPrivateKey.ChainCodeEnd = HDPrivateKey.ChainCodeStart + HDPrivateKey.ChainCodeSize;
|
|
HDPrivateKey.PrivateKeyStart = HDPrivateKey.ChainCodeEnd + 1;
|
|
HDPrivateKey.PrivateKeyEnd = HDPrivateKey.PrivateKeyStart + HDPrivateKey.PrivateKeySize;
|
|
HDPrivateKey.ChecksumStart = HDPrivateKey.PrivateKeyEnd;
|
|
HDPrivateKey.ChecksumEnd = HDPrivateKey.ChecksumStart + HDPrivateKey.CheckSumSize;
|
|
|
|
assert(HDPrivateKey.ChecksumEnd === HDPrivateKey.SerializedByteSize);
|
|
|
|
module.exports = HDPrivateKey;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./crypto/bn":6,"./crypto/hash":8,"./crypto/point":9,"./crypto/random":10,"./encoding/base58":12,"./encoding/base58check":13,"./errors":17,"./hdpublickey":20,"./networks":21,"./privatekey":23,"./util/buffer":42,"./util/js":43,"./util/preconditions":44,"assert":45,"buffer":47,"lodash":319}],20:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var $ = require('./util/preconditions');
|
|
|
|
var BN = require('./crypto/bn');
|
|
var Base58 = require('./encoding/base58');
|
|
var Base58Check = require('./encoding/base58check');
|
|
var Hash = require('./crypto/hash');
|
|
var HDPrivateKey = require('./hdprivatekey');
|
|
var Network = require('./networks');
|
|
var Point = require('./crypto/point');
|
|
var PublicKey = require('./publickey');
|
|
|
|
var bitcoreErrors = require('./errors');
|
|
var errors = bitcoreErrors;
|
|
var hdErrors = bitcoreErrors.HDPublicKey;
|
|
var assert = require('assert');
|
|
|
|
var JSUtil = require('./util/js');
|
|
var BufferUtil = require('./util/buffer');
|
|
|
|
/**
|
|
* The representation of an hierarchically derived public key.
|
|
*
|
|
* See https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
|
|
*
|
|
* @constructor
|
|
* @param {Object|string|Buffer} arg
|
|
*/
|
|
function HDPublicKey(arg) {
|
|
/* jshint maxcomplexity: 12 */
|
|
/* jshint maxstatements: 20 */
|
|
if (arg instanceof HDPublicKey) {
|
|
return arg;
|
|
}
|
|
if (!(this instanceof HDPublicKey)) {
|
|
return new HDPublicKey(arg);
|
|
}
|
|
if (arg) {
|
|
if (_.isString(arg) || BufferUtil.isBuffer(arg)) {
|
|
var error = HDPublicKey.getSerializedError(arg);
|
|
if (!error) {
|
|
return this._buildFromSerialized(arg);
|
|
} else if (BufferUtil.isBuffer(arg) && !HDPublicKey.getSerializedError(arg.toString())) {
|
|
return this._buildFromSerialized(arg.toString());
|
|
} else {
|
|
if (error instanceof hdErrors.ArgumentIsPrivateExtended) {
|
|
return new HDPrivateKey(arg).hdPublicKey;
|
|
}
|
|
throw error;
|
|
}
|
|
} else {
|
|
if (_.isObject(arg)) {
|
|
if (arg instanceof HDPrivateKey) {
|
|
return this._buildFromPrivate(arg);
|
|
} else {
|
|
return this._buildFromObject(arg);
|
|
}
|
|
} else {
|
|
throw new hdErrors.UnrecognizedArgument(arg);
|
|
}
|
|
}
|
|
} else {
|
|
throw new hdErrors.MustSupplyArgument();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verifies that a given path is valid.
|
|
*
|
|
* @param {string|number} arg
|
|
* @return {boolean}
|
|
*/
|
|
HDPublicKey.isValidPath = function(arg) {
|
|
if (_.isString(arg)) {
|
|
var indexes = HDPrivateKey._getDerivationIndexes(arg);
|
|
return indexes !== null && _.every(indexes, HDPublicKey.isValidPath);
|
|
}
|
|
|
|
if (_.isNumber(arg)) {
|
|
return arg >= 0 && arg < HDPublicKey.Hardened;
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* WARNING: This method is deprecated. Use deriveChild instead.
|
|
*
|
|
*
|
|
* Get a derivated child based on a string or number.
|
|
*
|
|
* If the first argument is a string, it's parsed as the full path of
|
|
* derivation. Valid values for this argument include "m" (which returns the
|
|
* same public key), "m/0/1/40/2/1000".
|
|
*
|
|
* Note that hardened keys can't be derived from a public extended key.
|
|
*
|
|
* If the first argument is a number, the child with that index will be
|
|
* derived. See the example usage for clarification.
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* var parent = new HDPublicKey('xpub...');
|
|
* var child_0_1_2 = parent.derive(0).derive(1).derive(2);
|
|
* var copy_of_child_0_1_2 = parent.derive("m/0/1/2");
|
|
* assert(child_0_1_2.xprivkey === copy_of_child_0_1_2);
|
|
* ```
|
|
*
|
|
* @param {string|number} arg
|
|
*/
|
|
HDPublicKey.prototype.derive = function(arg, hardened) {
|
|
return this.deriveChild(arg, hardened);
|
|
};
|
|
|
|
/**
|
|
* WARNING: This method will not be officially supported until v1.0.0.
|
|
*
|
|
*
|
|
* Get a derivated child based on a string or number.
|
|
*
|
|
* If the first argument is a string, it's parsed as the full path of
|
|
* derivation. Valid values for this argument include "m" (which returns the
|
|
* same public key), "m/0/1/40/2/1000".
|
|
*
|
|
* Note that hardened keys can't be derived from a public extended key.
|
|
*
|
|
* If the first argument is a number, the child with that index will be
|
|
* derived. See the example usage for clarification.
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* var parent = new HDPublicKey('xpub...');
|
|
* var child_0_1_2 = parent.deriveChild(0).deriveChild(1).deriveChild(2);
|
|
* var copy_of_child_0_1_2 = parent.deriveChild("m/0/1/2");
|
|
* assert(child_0_1_2.xprivkey === copy_of_child_0_1_2);
|
|
* ```
|
|
*
|
|
* @param {string|number} arg
|
|
*/
|
|
HDPublicKey.prototype.deriveChild = function(arg, hardened) {
|
|
if (_.isNumber(arg)) {
|
|
return this._deriveWithNumber(arg, hardened);
|
|
} else if (_.isString(arg)) {
|
|
return this._deriveFromString(arg);
|
|
} else {
|
|
throw new hdErrors.InvalidDerivationArgument(arg);
|
|
}
|
|
};
|
|
|
|
HDPublicKey.prototype._deriveWithNumber = function(index, hardened) {
|
|
if (index >= HDPublicKey.Hardened || hardened) {
|
|
throw new hdErrors.InvalidIndexCantDeriveHardened();
|
|
}
|
|
if (index < 0) {
|
|
throw new hdErrors.InvalidPath(index);
|
|
}
|
|
|
|
var indexBuffer = BufferUtil.integerAsBuffer(index);
|
|
var data = BufferUtil.concat([this.publicKey.toBuffer(), indexBuffer]);
|
|
var hash = Hash.sha512hmac(data, this._buffers.chainCode);
|
|
var leftPart = BN.fromBuffer(hash.slice(0, 32), {size: 32});
|
|
var chainCode = hash.slice(32, 64);
|
|
|
|
var publicKey;
|
|
try {
|
|
publicKey = PublicKey.fromPoint(Point.getG().mul(leftPart).add(this.publicKey.point));
|
|
} catch (e) {
|
|
return this._deriveWithNumber(index + 1);
|
|
}
|
|
|
|
var derived = new HDPublicKey({
|
|
network: this.network,
|
|
depth: this.depth + 1,
|
|
parentFingerPrint: this.fingerPrint,
|
|
childIndex: index,
|
|
chainCode: chainCode,
|
|
publicKey: publicKey
|
|
});
|
|
|
|
return derived;
|
|
};
|
|
|
|
HDPublicKey.prototype._deriveFromString = function(path) {
|
|
/* jshint maxcomplexity: 8 */
|
|
if (_.includes(path, "'")) {
|
|
throw new hdErrors.InvalidIndexCantDeriveHardened();
|
|
} else if (!HDPublicKey.isValidPath(path)) {
|
|
throw new hdErrors.InvalidPath(path);
|
|
}
|
|
|
|
var indexes = HDPrivateKey._getDerivationIndexes(path);
|
|
var derived = indexes.reduce(function(prev, index) {
|
|
return prev._deriveWithNumber(index);
|
|
}, this);
|
|
|
|
return derived;
|
|
};
|
|
|
|
/**
|
|
* Verifies that a given serialized public key in base58 with checksum format
|
|
* is valid.
|
|
*
|
|
* @param {string|Buffer} data - the serialized public key
|
|
* @param {string|Network=} network - optional, if present, checks that the
|
|
* network provided matches the network serialized.
|
|
* @return {boolean}
|
|
*/
|
|
HDPublicKey.isValidSerialized = function(data, network) {
|
|
return _.isNull(HDPublicKey.getSerializedError(data, network));
|
|
};
|
|
|
|
/**
|
|
* Checks what's the error that causes the validation of a serialized public key
|
|
* in base58 with checksum to fail.
|
|
*
|
|
* @param {string|Buffer} data - the serialized public key
|
|
* @param {string|Network=} network - optional, if present, checks that the
|
|
* network provided matches the network serialized.
|
|
* @return {errors|null}
|
|
*/
|
|
HDPublicKey.getSerializedError = function(data, network) {
|
|
/* jshint maxcomplexity: 10 */
|
|
/* jshint maxstatements: 20 */
|
|
if (!(_.isString(data) || BufferUtil.isBuffer(data))) {
|
|
return new hdErrors.UnrecognizedArgument('expected buffer or string');
|
|
}
|
|
if (!Base58.validCharacters(data)) {
|
|
return new errors.InvalidB58Char('(unknown)', data);
|
|
}
|
|
try {
|
|
data = Base58Check.decode(data);
|
|
} catch (e) {
|
|
return new errors.InvalidB58Checksum(data);
|
|
}
|
|
if (data.length !== HDPublicKey.DataSize) {
|
|
return new hdErrors.InvalidLength(data);
|
|
}
|
|
if (!_.isUndefined(network)) {
|
|
var error = HDPublicKey._validateNetwork(data, network);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
}
|
|
var version = BufferUtil.integerFromBuffer(data.slice(0, 4));
|
|
if (version === Network.livenet.xprivkey || version === Network.testnet.xprivkey ) {
|
|
return new hdErrors.ArgumentIsPrivateExtended();
|
|
}
|
|
return null;
|
|
};
|
|
|
|
HDPublicKey._validateNetwork = function(data, networkArg) {
|
|
var network = Network.get(networkArg);
|
|
if (!network) {
|
|
return new errors.InvalidNetworkArgument(networkArg);
|
|
}
|
|
var version = data.slice(HDPublicKey.VersionStart, HDPublicKey.VersionEnd);
|
|
if (BufferUtil.integerFromBuffer(version) !== network.xpubkey) {
|
|
return new errors.InvalidNetwork(version);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
HDPublicKey.prototype._buildFromPrivate = function (arg) {
|
|
var args = _.clone(arg._buffers);
|
|
var point = Point.getG().mul(BN.fromBuffer(args.privateKey));
|
|
args.publicKey = Point.pointToCompressed(point);
|
|
args.version = BufferUtil.integerAsBuffer(Network.get(BufferUtil.integerFromBuffer(args.version)).xpubkey);
|
|
args.privateKey = undefined;
|
|
args.checksum = undefined;
|
|
args.xprivkey = undefined;
|
|
return this._buildFromBuffers(args);
|
|
};
|
|
|
|
HDPublicKey.prototype._buildFromObject = function(arg) {
|
|
/* jshint maxcomplexity: 10 */
|
|
// TODO: Type validation
|
|
var buffers = {
|
|
version: arg.network ? BufferUtil.integerAsBuffer(Network.get(arg.network).xpubkey) : arg.version,
|
|
depth: _.isNumber(arg.depth) ? BufferUtil.integerAsSingleByteBuffer(arg.depth) : arg.depth,
|
|
parentFingerPrint: _.isNumber(arg.parentFingerPrint) ? BufferUtil.integerAsBuffer(arg.parentFingerPrint) : arg.parentFingerPrint,
|
|
childIndex: _.isNumber(arg.childIndex) ? BufferUtil.integerAsBuffer(arg.childIndex) : arg.childIndex,
|
|
chainCode: _.isString(arg.chainCode) ? BufferUtil.hexToBuffer(arg.chainCode) : arg.chainCode,
|
|
publicKey: _.isString(arg.publicKey) ? BufferUtil.hexToBuffer(arg.publicKey) :
|
|
BufferUtil.isBuffer(arg.publicKey) ? arg.publicKey : arg.publicKey.toBuffer(),
|
|
checksum: _.isNumber(arg.checksum) ? BufferUtil.integerAsBuffer(arg.checksum) : arg.checksum
|
|
};
|
|
return this._buildFromBuffers(buffers);
|
|
};
|
|
|
|
HDPublicKey.prototype._buildFromSerialized = function(arg) {
|
|
var decoded = Base58Check.decode(arg);
|
|
var buffers = {
|
|
version: decoded.slice(HDPublicKey.VersionStart, HDPublicKey.VersionEnd),
|
|
depth: decoded.slice(HDPublicKey.DepthStart, HDPublicKey.DepthEnd),
|
|
parentFingerPrint: decoded.slice(HDPublicKey.ParentFingerPrintStart,
|
|
HDPublicKey.ParentFingerPrintEnd),
|
|
childIndex: decoded.slice(HDPublicKey.ChildIndexStart, HDPublicKey.ChildIndexEnd),
|
|
chainCode: decoded.slice(HDPublicKey.ChainCodeStart, HDPublicKey.ChainCodeEnd),
|
|
publicKey: decoded.slice(HDPublicKey.PublicKeyStart, HDPublicKey.PublicKeyEnd),
|
|
checksum: decoded.slice(HDPublicKey.ChecksumStart, HDPublicKey.ChecksumEnd),
|
|
xpubkey: arg
|
|
};
|
|
return this._buildFromBuffers(buffers);
|
|
};
|
|
|
|
/**
|
|
* Receives a object with buffers in all the properties and populates the
|
|
* internal structure
|
|
*
|
|
* @param {Object} arg
|
|
* @param {buffer.Buffer} arg.version
|
|
* @param {buffer.Buffer} arg.depth
|
|
* @param {buffer.Buffer} arg.parentFingerPrint
|
|
* @param {buffer.Buffer} arg.childIndex
|
|
* @param {buffer.Buffer} arg.chainCode
|
|
* @param {buffer.Buffer} arg.publicKey
|
|
* @param {buffer.Buffer} arg.checksum
|
|
* @param {string=} arg.xpubkey - if set, don't recalculate the base58
|
|
* representation
|
|
* @return {HDPublicKey} this
|
|
*/
|
|
HDPublicKey.prototype._buildFromBuffers = function(arg) {
|
|
/* jshint maxcomplexity: 8 */
|
|
/* jshint maxstatements: 20 */
|
|
|
|
HDPublicKey._validateBufferArguments(arg);
|
|
|
|
JSUtil.defineImmutable(this, {
|
|
_buffers: arg
|
|
});
|
|
|
|
var sequence = [
|
|
arg.version, arg.depth, arg.parentFingerPrint, arg.childIndex, arg.chainCode,
|
|
arg.publicKey
|
|
];
|
|
var concat = BufferUtil.concat(sequence);
|
|
var checksum = Base58Check.checksum(concat);
|
|
if (!arg.checksum || !arg.checksum.length) {
|
|
arg.checksum = checksum;
|
|
} else {
|
|
if (arg.checksum.toString('hex') !== checksum.toString('hex')) {
|
|
throw new errors.InvalidB58Checksum(concat, checksum);
|
|
}
|
|
}
|
|
var network = Network.get(BufferUtil.integerFromBuffer(arg.version));
|
|
|
|
var xpubkey;
|
|
xpubkey = Base58Check.encode(BufferUtil.concat(sequence));
|
|
arg.xpubkey = new Buffer(xpubkey);
|
|
|
|
var publicKey = new PublicKey(arg.publicKey, {network: network});
|
|
var size = HDPublicKey.ParentFingerPrintSize;
|
|
var fingerPrint = Hash.sha256ripemd160(publicKey.toBuffer()).slice(0, size);
|
|
|
|
JSUtil.defineImmutable(this, {
|
|
xpubkey: xpubkey,
|
|
network: network,
|
|
depth: BufferUtil.integerFromSingleByteBuffer(arg.depth),
|
|
publicKey: publicKey,
|
|
fingerPrint: fingerPrint
|
|
});
|
|
|
|
return this;
|
|
};
|
|
|
|
HDPublicKey._validateBufferArguments = function(arg) {
|
|
var checkBuffer = function(name, size) {
|
|
var buff = arg[name];
|
|
assert(BufferUtil.isBuffer(buff), name + ' argument is not a buffer, it\'s ' + typeof buff);
|
|
assert(
|
|
buff.length === size,
|
|
name + ' has not the expected size: found ' + buff.length + ', expected ' + size
|
|
);
|
|
};
|
|
checkBuffer('version', HDPublicKey.VersionSize);
|
|
checkBuffer('depth', HDPublicKey.DepthSize);
|
|
checkBuffer('parentFingerPrint', HDPublicKey.ParentFingerPrintSize);
|
|
checkBuffer('childIndex', HDPublicKey.ChildIndexSize);
|
|
checkBuffer('chainCode', HDPublicKey.ChainCodeSize);
|
|
checkBuffer('publicKey', HDPublicKey.PublicKeySize);
|
|
if (arg.checksum && arg.checksum.length) {
|
|
checkBuffer('checksum', HDPublicKey.CheckSumSize);
|
|
}
|
|
};
|
|
|
|
HDPublicKey.fromString = function(arg) {
|
|
$.checkArgument(_.isString(arg), 'No valid string was provided');
|
|
return new HDPublicKey(arg);
|
|
};
|
|
|
|
HDPublicKey.fromObject = function(arg) {
|
|
$.checkArgument(_.isObject(arg), 'No valid argument was provided');
|
|
return new HDPublicKey(arg);
|
|
};
|
|
|
|
/**
|
|
* Returns the base58 checked representation of the public key
|
|
* @return {string} a string starting with "xpub..." in livenet
|
|
*/
|
|
HDPublicKey.prototype.toString = function() {
|
|
return this.xpubkey;
|
|
};
|
|
|
|
/**
|
|
* Returns the console representation of this extended public key.
|
|
* @return string
|
|
*/
|
|
HDPublicKey.prototype.inspect = function() {
|
|
return '<HDPublicKey: ' + this.xpubkey + '>';
|
|
};
|
|
|
|
/**
|
|
* Returns a plain JavaScript object with information to reconstruct a key.
|
|
*
|
|
* Fields are: <ul>
|
|
* <li> network: 'livenet' or 'testnet'
|
|
* <li> depth: a number from 0 to 255, the depth to the master extended key
|
|
* <li> fingerPrint: a number of 32 bits taken from the hash of the public key
|
|
* <li> fingerPrint: a number of 32 bits taken from the hash of this key's
|
|
* <li> parent's public key
|
|
* <li> childIndex: index with which this key was derived
|
|
* <li> chainCode: string in hexa encoding used for derivation
|
|
* <li> publicKey: string, hexa encoded, in compressed key format
|
|
* <li> checksum: BufferUtil.integerFromBuffer(this._buffers.checksum),
|
|
* <li> xpubkey: the string with the base58 representation of this extended key
|
|
* <li> checksum: the base58 checksum of xpubkey
|
|
* </ul>
|
|
*/
|
|
HDPublicKey.prototype.toObject = HDPublicKey.prototype.toJSON = function toObject() {
|
|
return {
|
|
network: Network.get(BufferUtil.integerFromBuffer(this._buffers.version)).name,
|
|
depth: BufferUtil.integerFromSingleByteBuffer(this._buffers.depth),
|
|
fingerPrint: BufferUtil.integerFromBuffer(this.fingerPrint),
|
|
parentFingerPrint: BufferUtil.integerFromBuffer(this._buffers.parentFingerPrint),
|
|
childIndex: BufferUtil.integerFromBuffer(this._buffers.childIndex),
|
|
chainCode: BufferUtil.bufferToHex(this._buffers.chainCode),
|
|
publicKey: this.publicKey.toString(),
|
|
checksum: BufferUtil.integerFromBuffer(this._buffers.checksum),
|
|
xpubkey: this.xpubkey
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Create a HDPublicKey from a buffer argument
|
|
*
|
|
* @param {Buffer} arg
|
|
* @return {HDPublicKey}
|
|
*/
|
|
HDPublicKey.fromBuffer = function(arg) {
|
|
return new HDPublicKey(arg);
|
|
};
|
|
|
|
/**
|
|
* Return a buffer representation of the xpubkey
|
|
*
|
|
* @return {Buffer}
|
|
*/
|
|
HDPublicKey.prototype.toBuffer = function() {
|
|
return BufferUtil.copy(this._buffers.xpubkey);
|
|
};
|
|
|
|
HDPublicKey.Hardened = 0x80000000;
|
|
HDPublicKey.RootElementAlias = ['m', 'M'];
|
|
|
|
HDPublicKey.VersionSize = 4;
|
|
HDPublicKey.DepthSize = 1;
|
|
HDPublicKey.ParentFingerPrintSize = 4;
|
|
HDPublicKey.ChildIndexSize = 4;
|
|
HDPublicKey.ChainCodeSize = 32;
|
|
HDPublicKey.PublicKeySize = 33;
|
|
HDPublicKey.CheckSumSize = 4;
|
|
|
|
HDPublicKey.DataSize = 78;
|
|
HDPublicKey.SerializedByteSize = 82;
|
|
|
|
HDPublicKey.VersionStart = 0;
|
|
HDPublicKey.VersionEnd = HDPublicKey.VersionStart + HDPublicKey.VersionSize;
|
|
HDPublicKey.DepthStart = HDPublicKey.VersionEnd;
|
|
HDPublicKey.DepthEnd = HDPublicKey.DepthStart + HDPublicKey.DepthSize;
|
|
HDPublicKey.ParentFingerPrintStart = HDPublicKey.DepthEnd;
|
|
HDPublicKey.ParentFingerPrintEnd = HDPublicKey.ParentFingerPrintStart + HDPublicKey.ParentFingerPrintSize;
|
|
HDPublicKey.ChildIndexStart = HDPublicKey.ParentFingerPrintEnd;
|
|
HDPublicKey.ChildIndexEnd = HDPublicKey.ChildIndexStart + HDPublicKey.ChildIndexSize;
|
|
HDPublicKey.ChainCodeStart = HDPublicKey.ChildIndexEnd;
|
|
HDPublicKey.ChainCodeEnd = HDPublicKey.ChainCodeStart + HDPublicKey.ChainCodeSize;
|
|
HDPublicKey.PublicKeyStart = HDPublicKey.ChainCodeEnd;
|
|
HDPublicKey.PublicKeyEnd = HDPublicKey.PublicKeyStart + HDPublicKey.PublicKeySize;
|
|
HDPublicKey.ChecksumStart = HDPublicKey.PublicKeyEnd;
|
|
HDPublicKey.ChecksumEnd = HDPublicKey.ChecksumStart + HDPublicKey.CheckSumSize;
|
|
|
|
assert(HDPublicKey.PublicKeyEnd === HDPublicKey.DataSize);
|
|
assert(HDPublicKey.ChecksumEnd === HDPublicKey.SerializedByteSize);
|
|
|
|
module.exports = HDPublicKey;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./crypto/bn":6,"./crypto/hash":8,"./crypto/point":9,"./encoding/base58":12,"./encoding/base58check":13,"./errors":17,"./hdprivatekey":19,"./networks":21,"./publickey":24,"./util/buffer":42,"./util/js":43,"./util/preconditions":44,"assert":45,"buffer":47,"lodash":319}],21:[function(require,module,exports){
|
|
'use strict';
|
|
var _ = require('lodash');
|
|
|
|
var BufferUtil = require('./util/buffer');
|
|
var JSUtil = require('./util/js');
|
|
var networks = [];
|
|
var networkMaps = {};
|
|
|
|
/**
|
|
* A network is merely a map containing values that correspond to version
|
|
* numbers for each bitcoin network. Currently only supporting "livenet"
|
|
* (a.k.a. "mainnet") and "testnet".
|
|
* @constructor
|
|
*/
|
|
function Network() {}
|
|
|
|
Network.prototype.toString = function toString() {
|
|
return this.name;
|
|
};
|
|
|
|
/**
|
|
* @function
|
|
* @member Networks#get
|
|
* Retrieves the network associated with a magic number or string.
|
|
* @param {string|number|Network} arg
|
|
* @param {string|Array} keys - if set, only check if the magic number associated with this name matches
|
|
* @return Network
|
|
*/
|
|
function get(arg, keys) {
|
|
if (~networks.indexOf(arg)) {
|
|
return arg;
|
|
}
|
|
if (keys) {
|
|
if (!_.isArray(keys)) {
|
|
keys = [keys];
|
|
}
|
|
var containsArg = function(key) {
|
|
return networks[index][key] === arg;
|
|
};
|
|
for (var index in networks) {
|
|
if (_.some(keys, containsArg)) {
|
|
return networks[index];
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
return networkMaps[arg];
|
|
}
|
|
|
|
/**
|
|
* @function
|
|
* @member Networks#add
|
|
* Will add a custom Network
|
|
* @param {Object} data
|
|
* @param {string} data.name - The name of the network
|
|
* @param {string} data.alias - The aliased name of the network
|
|
* @param {Number} data.pubkeyhash - The publickey hash prefix
|
|
* @param {Number} data.privatekey - The privatekey prefix
|
|
* @param {Number} data.scripthash - The scripthash prefix
|
|
* @param {Number} data.xpubkey - The extended public key magic
|
|
* @param {Number} data.xprivkey - The extended private key magic
|
|
* @param {Number} data.networkMagic - The network magic number
|
|
* @param {Number} data.port - The network port
|
|
* @param {Array} data.dnsSeeds - An array of dns seeds
|
|
* @return Network
|
|
*/
|
|
function addNetwork(data) {
|
|
|
|
var network = new Network();
|
|
|
|
JSUtil.defineImmutable(network, {
|
|
name: data.name,
|
|
alias: data.alias,
|
|
pubkeyhash: data.pubkeyhash,
|
|
privatekey: data.privatekey,
|
|
scripthash: data.scripthash,
|
|
xpubkey: data.xpubkey,
|
|
xprivkey: data.xprivkey
|
|
});
|
|
|
|
if (data.networkMagic) {
|
|
JSUtil.defineImmutable(network, {
|
|
networkMagic: BufferUtil.integerAsBuffer(data.networkMagic)
|
|
});
|
|
}
|
|
|
|
if (data.port) {
|
|
JSUtil.defineImmutable(network, {
|
|
port: data.port
|
|
});
|
|
}
|
|
|
|
if (data.dnsSeeds) {
|
|
JSUtil.defineImmutable(network, {
|
|
dnsSeeds: data.dnsSeeds
|
|
});
|
|
}
|
|
_.each(network, function(value) {
|
|
if (!_.isUndefined(value) && !_.isObject(value)) {
|
|
networkMaps[value] = network;
|
|
}
|
|
});
|
|
|
|
networks.push(network);
|
|
|
|
return network;
|
|
|
|
}
|
|
|
|
/**
|
|
* @function
|
|
* @member Networks#remove
|
|
* Will remove a custom network
|
|
* @param {Network} network
|
|
*/
|
|
function removeNetwork(network) {
|
|
for (var i = 0; i < networks.length; i++) {
|
|
if (networks[i] === network) {
|
|
networks.splice(i, 1);
|
|
}
|
|
}
|
|
for (var key in networkMaps) {
|
|
if (networkMaps[key] === network) {
|
|
delete networkMaps[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
addNetwork({
|
|
name: 'livenet',
|
|
alias: 'mainnet',
|
|
pubkeyhash: 0x00,
|
|
privatekey: 0x80,
|
|
scripthash: 0x05,
|
|
xpubkey: 0x0488b21e,
|
|
xprivkey: 0x0488ade4,
|
|
networkMagic: 0xf9beb4d9,
|
|
port: 8333,
|
|
dnsSeeds: [
|
|
'seed.bitcoin.sipa.be',
|
|
'dnsseed.bluematt.me',
|
|
'dnsseed.bitcoin.dashjr.org',
|
|
'seed.bitcoinstats.com',
|
|
'seed.bitnodes.io',
|
|
'bitseed.xf2.org'
|
|
]
|
|
});
|
|
|
|
/**
|
|
* @instance
|
|
* @member Networks#livenet
|
|
*/
|
|
var livenet = get('livenet');
|
|
|
|
addNetwork({
|
|
name: 'testnet',
|
|
alias: 'regtest',
|
|
pubkeyhash: 0x6f,
|
|
privatekey: 0xef,
|
|
scripthash: 0xc4,
|
|
xpubkey: 0x043587cf,
|
|
xprivkey: 0x04358394
|
|
});
|
|
|
|
/**
|
|
* @instance
|
|
* @member Networks#testnet
|
|
*/
|
|
var testnet = get('testnet');
|
|
|
|
// Add configurable values for testnet/regtest
|
|
|
|
var TESTNET = {
|
|
PORT: 18333,
|
|
NETWORK_MAGIC: BufferUtil.integerAsBuffer(0x0b110907),
|
|
DNS_SEEDS: [
|
|
'testnet-seed.bitcoin.petertodd.org',
|
|
'testnet-seed.bluematt.me',
|
|
'testnet-seed.alexykot.me',
|
|
'testnet-seed.bitcoin.schildbach.de'
|
|
]
|
|
};
|
|
|
|
for (var key in TESTNET) {
|
|
if (!_.isObject(TESTNET[key])) {
|
|
networkMaps[TESTNET[key]] = testnet;
|
|
}
|
|
}
|
|
|
|
var REGTEST = {
|
|
PORT: 18444,
|
|
NETWORK_MAGIC: BufferUtil.integerAsBuffer(0xfabfb5da),
|
|
DNS_SEEDS: []
|
|
};
|
|
|
|
for (var key in REGTEST) {
|
|
if (!_.isObject(REGTEST[key])) {
|
|
networkMaps[REGTEST[key]] = testnet;
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(testnet, 'port', {
|
|
enumerable: true,
|
|
configurable: false,
|
|
get: function() {
|
|
if (this.regtestEnabled) {
|
|
return REGTEST.PORT;
|
|
} else {
|
|
return TESTNET.PORT;
|
|
}
|
|
}
|
|
});
|
|
|
|
Object.defineProperty(testnet, 'networkMagic', {
|
|
enumerable: true,
|
|
configurable: false,
|
|
get: function() {
|
|
if (this.regtestEnabled) {
|
|
return REGTEST.NETWORK_MAGIC;
|
|
} else {
|
|
return TESTNET.NETWORK_MAGIC;
|
|
}
|
|
}
|
|
});
|
|
|
|
Object.defineProperty(testnet, 'dnsSeeds', {
|
|
enumerable: true,
|
|
configurable: false,
|
|
get: function() {
|
|
if (this.regtestEnabled) {
|
|
return REGTEST.DNS_SEEDS;
|
|
} else {
|
|
return TESTNET.DNS_SEEDS;
|
|
}
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @function
|
|
* @member Networks#enableRegtest
|
|
* Will enable regtest features for testnet
|
|
*/
|
|
function enableRegtest() {
|
|
testnet.regtestEnabled = true;
|
|
}
|
|
|
|
/**
|
|
* @function
|
|
* @member Networks#disableRegtest
|
|
* Will disable regtest features for testnet
|
|
*/
|
|
function disableRegtest() {
|
|
testnet.regtestEnabled = false;
|
|
}
|
|
|
|
/**
|
|
* @namespace Networks
|
|
*/
|
|
module.exports = {
|
|
add: addNetwork,
|
|
remove: removeNetwork,
|
|
defaultNetwork: livenet,
|
|
livenet: livenet,
|
|
mainnet: livenet,
|
|
testnet: testnet,
|
|
get: get,
|
|
enableRegtest: enableRegtest,
|
|
disableRegtest: disableRegtest
|
|
};
|
|
|
|
},{"./util/buffer":42,"./util/js":43,"lodash":319}],22:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var $ = require('./util/preconditions');
|
|
var BufferUtil = require('./util/buffer');
|
|
var JSUtil = require('./util/js');
|
|
|
|
function Opcode(num) {
|
|
if (!(this instanceof Opcode)) {
|
|
return new Opcode(num);
|
|
}
|
|
|
|
var value;
|
|
|
|
if (_.isNumber(num)) {
|
|
value = num;
|
|
} else if (_.isString(num)) {
|
|
value = Opcode.map[num];
|
|
} else {
|
|
throw new TypeError('Unrecognized num type: "' + typeof(num) + '" for Opcode');
|
|
}
|
|
|
|
JSUtil.defineImmutable(this, {
|
|
num: value
|
|
});
|
|
|
|
return this;
|
|
}
|
|
|
|
Opcode.fromBuffer = function(buf) {
|
|
$.checkArgument(BufferUtil.isBuffer(buf));
|
|
return new Opcode(Number('0x' + buf.toString('hex')));
|
|
};
|
|
|
|
Opcode.fromNumber = function(num) {
|
|
$.checkArgument(_.isNumber(num));
|
|
return new Opcode(num);
|
|
};
|
|
|
|
Opcode.fromString = function(str) {
|
|
$.checkArgument(_.isString(str));
|
|
var value = Opcode.map[str];
|
|
if (typeof value === 'undefined') {
|
|
throw new TypeError('Invalid opcodestr');
|
|
}
|
|
return new Opcode(value);
|
|
};
|
|
|
|
Opcode.prototype.toHex = function() {
|
|
return this.num.toString(16);
|
|
};
|
|
|
|
Opcode.prototype.toBuffer = function() {
|
|
return new Buffer(this.toHex(), 'hex');
|
|
};
|
|
|
|
Opcode.prototype.toNumber = function() {
|
|
return this.num;
|
|
};
|
|
|
|
Opcode.prototype.toString = function() {
|
|
var str = Opcode.reverseMap[this.num];
|
|
if (typeof str === 'undefined') {
|
|
throw new Error('Opcode does not have a string representation');
|
|
}
|
|
return str;
|
|
};
|
|
|
|
Opcode.smallInt = function(n) {
|
|
$.checkArgument(_.isNumber(n), 'Invalid Argument: n should be number');
|
|
$.checkArgument(n >= 0 && n <= 16, 'Invalid Argument: n must be between 0 and 16');
|
|
if (n === 0) {
|
|
return Opcode('OP_0');
|
|
}
|
|
return new Opcode(Opcode.map.OP_1 + n - 1);
|
|
};
|
|
|
|
Opcode.map = {
|
|
// push value
|
|
OP_FALSE: 0,
|
|
OP_0: 0,
|
|
OP_PUSHDATA1: 76,
|
|
OP_PUSHDATA2: 77,
|
|
OP_PUSHDATA4: 78,
|
|
OP_1NEGATE: 79,
|
|
OP_RESERVED: 80,
|
|
OP_TRUE: 81,
|
|
OP_1: 81,
|
|
OP_2: 82,
|
|
OP_3: 83,
|
|
OP_4: 84,
|
|
OP_5: 85,
|
|
OP_6: 86,
|
|
OP_7: 87,
|
|
OP_8: 88,
|
|
OP_9: 89,
|
|
OP_10: 90,
|
|
OP_11: 91,
|
|
OP_12: 92,
|
|
OP_13: 93,
|
|
OP_14: 94,
|
|
OP_15: 95,
|
|
OP_16: 96,
|
|
|
|
// control
|
|
OP_NOP: 97,
|
|
OP_VER: 98,
|
|
OP_IF: 99,
|
|
OP_NOTIF: 100,
|
|
OP_VERIF: 101,
|
|
OP_VERNOTIF: 102,
|
|
OP_ELSE: 103,
|
|
OP_ENDIF: 104,
|
|
OP_VERIFY: 105,
|
|
OP_RETURN: 106,
|
|
|
|
// stack ops
|
|
OP_TOALTSTACK: 107,
|
|
OP_FROMALTSTACK: 108,
|
|
OP_2DROP: 109,
|
|
OP_2DUP: 110,
|
|
OP_3DUP: 111,
|
|
OP_2OVER: 112,
|
|
OP_2ROT: 113,
|
|
OP_2SWAP: 114,
|
|
OP_IFDUP: 115,
|
|
OP_DEPTH: 116,
|
|
OP_DROP: 117,
|
|
OP_DUP: 118,
|
|
OP_NIP: 119,
|
|
OP_OVER: 120,
|
|
OP_PICK: 121,
|
|
OP_ROLL: 122,
|
|
OP_ROT: 123,
|
|
OP_SWAP: 124,
|
|
OP_TUCK: 125,
|
|
|
|
// splice ops
|
|
OP_CAT: 126,
|
|
OP_SUBSTR: 127,
|
|
OP_LEFT: 128,
|
|
OP_RIGHT: 129,
|
|
OP_SIZE: 130,
|
|
|
|
// bit logic
|
|
OP_INVERT: 131,
|
|
OP_AND: 132,
|
|
OP_OR: 133,
|
|
OP_XOR: 134,
|
|
OP_EQUAL: 135,
|
|
OP_EQUALVERIFY: 136,
|
|
OP_RESERVED1: 137,
|
|
OP_RESERVED2: 138,
|
|
|
|
// numeric
|
|
OP_1ADD: 139,
|
|
OP_1SUB: 140,
|
|
OP_2MUL: 141,
|
|
OP_2DIV: 142,
|
|
OP_NEGATE: 143,
|
|
OP_ABS: 144,
|
|
OP_NOT: 145,
|
|
OP_0NOTEQUAL: 146,
|
|
|
|
OP_ADD: 147,
|
|
OP_SUB: 148,
|
|
OP_MUL: 149,
|
|
OP_DIV: 150,
|
|
OP_MOD: 151,
|
|
OP_LSHIFT: 152,
|
|
OP_RSHIFT: 153,
|
|
|
|
OP_BOOLAND: 154,
|
|
OP_BOOLOR: 155,
|
|
OP_NUMEQUAL: 156,
|
|
OP_NUMEQUALVERIFY: 157,
|
|
OP_NUMNOTEQUAL: 158,
|
|
OP_LESSTHAN: 159,
|
|
OP_GREATERTHAN: 160,
|
|
OP_LESSTHANOREQUAL: 161,
|
|
OP_GREATERTHANOREQUAL: 162,
|
|
OP_MIN: 163,
|
|
OP_MAX: 164,
|
|
|
|
OP_WITHIN: 165,
|
|
|
|
// crypto
|
|
OP_RIPEMD160: 166,
|
|
OP_SHA1: 167,
|
|
OP_SHA256: 168,
|
|
OP_HASH160: 169,
|
|
OP_HASH256: 170,
|
|
OP_CODESEPARATOR: 171,
|
|
OP_CHECKSIG: 172,
|
|
OP_CHECKSIGVERIFY: 173,
|
|
OP_CHECKMULTISIG: 174,
|
|
OP_CHECKMULTISIGVERIFY: 175,
|
|
|
|
OP_CHECKLOCKTIMEVERIFY: 177,
|
|
|
|
// expansion
|
|
OP_NOP1: 176,
|
|
OP_NOP2: 177,
|
|
OP_NOP3: 178,
|
|
OP_NOP4: 179,
|
|
OP_NOP5: 180,
|
|
OP_NOP6: 181,
|
|
OP_NOP7: 182,
|
|
OP_NOP8: 183,
|
|
OP_NOP9: 184,
|
|
OP_NOP10: 185,
|
|
|
|
// template matching params
|
|
OP_PUBKEYHASH: 253,
|
|
OP_PUBKEY: 254,
|
|
OP_INVALIDOPCODE: 255
|
|
};
|
|
|
|
Opcode.reverseMap = [];
|
|
|
|
for (var k in Opcode.map) {
|
|
Opcode.reverseMap[Opcode.map[k]] = k;
|
|
}
|
|
|
|
// Easier access to opcodes
|
|
_.extend(Opcode, Opcode.map);
|
|
|
|
/**
|
|
* @returns true if opcode is one of OP_0, OP_1, ..., OP_16
|
|
*/
|
|
Opcode.isSmallIntOp = function(opcode) {
|
|
if (opcode instanceof Opcode) {
|
|
opcode = opcode.toNumber();
|
|
}
|
|
return ((opcode === Opcode.map.OP_0) ||
|
|
((opcode >= Opcode.map.OP_1) && (opcode <= Opcode.map.OP_16)));
|
|
};
|
|
|
|
/**
|
|
* Will return a string formatted for the console
|
|
*
|
|
* @returns {string} Script opcode
|
|
*/
|
|
Opcode.prototype.inspect = function() {
|
|
return '<Opcode: ' + this.toString() + ', hex: '+this.toHex()+', decimal: '+this.num+'>';
|
|
};
|
|
|
|
module.exports = Opcode;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./util/buffer":42,"./util/js":43,"./util/preconditions":44,"buffer":47,"lodash":319}],23:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var Address = require('./address');
|
|
var Base58Check = require('./encoding/base58check');
|
|
var BN = require('./crypto/bn');
|
|
var JSUtil = require('./util/js');
|
|
var Networks = require('./networks');
|
|
var Point = require('./crypto/point');
|
|
var PublicKey = require('./publickey');
|
|
var Random = require('./crypto/random');
|
|
var $ = require('./util/preconditions');
|
|
|
|
/**
|
|
* Instantiate a PrivateKey from a BN, Buffer and WIF.
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* // generate a new random key
|
|
* var key = PrivateKey();
|
|
*
|
|
* // get the associated address
|
|
* var address = key.toAddress();
|
|
*
|
|
* // encode into wallet export format
|
|
* var exported = key.toWIF();
|
|
*
|
|
* // instantiate from the exported (and saved) private key
|
|
* var imported = PrivateKey.fromWIF(exported);
|
|
* ```
|
|
*
|
|
* @param {string} data - The encoded data in various formats
|
|
* @param {Network|string=} network - a {@link Network} object, or a string with the network name
|
|
* @returns {PrivateKey} A new valid instance of an PrivateKey
|
|
* @constructor
|
|
*/
|
|
function PrivateKey(data, network) {
|
|
/* jshint maxstatements: 20 */
|
|
/* jshint maxcomplexity: 8 */
|
|
|
|
if (!(this instanceof PrivateKey)) {
|
|
return new PrivateKey(data, network);
|
|
}
|
|
if (data instanceof PrivateKey) {
|
|
return data;
|
|
}
|
|
|
|
var info = this._classifyArguments(data, network);
|
|
|
|
// validation
|
|
if (!info.bn || info.bn.cmp(new BN(0)) === 0){
|
|
throw new TypeError('Number can not be equal to zero, undefined, null or false');
|
|
}
|
|
if (!info.bn.lt(Point.getN())) {
|
|
throw new TypeError('Number must be less than N');
|
|
}
|
|
if (typeof(info.network) === 'undefined') {
|
|
throw new TypeError('Must specify the network ("livenet" or "testnet")');
|
|
}
|
|
|
|
JSUtil.defineImmutable(this, {
|
|
bn: info.bn,
|
|
compressed: info.compressed,
|
|
network: info.network
|
|
});
|
|
|
|
Object.defineProperty(this, 'publicKey', {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: this.toPublicKey.bind(this)
|
|
});
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
/**
|
|
* Internal helper to instantiate PrivateKey internal `info` object from
|
|
* different kinds of arguments passed to the constructor.
|
|
*
|
|
* @param {*} data
|
|
* @param {Network|string=} network - a {@link Network} object, or a string with the network name
|
|
* @return {Object}
|
|
*/
|
|
PrivateKey.prototype._classifyArguments = function(data, network) {
|
|
/* jshint maxcomplexity: 10 */
|
|
var info = {
|
|
compressed: true,
|
|
network: network ? Networks.get(network) : Networks.defaultNetwork
|
|
};
|
|
|
|
// detect type of data
|
|
if (_.isUndefined(data) || _.isNull(data)){
|
|
info.bn = PrivateKey._getRandomBN();
|
|
} else if (data instanceof BN) {
|
|
info.bn = data;
|
|
} else if (data instanceof Buffer || data instanceof Uint8Array) {
|
|
info = PrivateKey._transformBuffer(data, network);
|
|
} else if (data.bn && data.network){
|
|
info = PrivateKey._transformObject(data);
|
|
} else if (!network && Networks.get(data)) {
|
|
info.bn = PrivateKey._getRandomBN();
|
|
info.network = Networks.get(data);
|
|
} else if (typeof(data) === 'string'){
|
|
if (JSUtil.isHexa(data)) {
|
|
info.bn = new BN(new Buffer(data, 'hex'));
|
|
} else {
|
|
info = PrivateKey._transformWIF(data, network);
|
|
}
|
|
} else {
|
|
throw new TypeError('First argument is an unrecognized data type.');
|
|
}
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Internal function to get a random Big Number (BN)
|
|
*
|
|
* @returns {BN} A new randomly generated BN
|
|
* @private
|
|
*/
|
|
PrivateKey._getRandomBN = function(){
|
|
var condition;
|
|
var bn;
|
|
do {
|
|
var privbuf = Random.getRandomBuffer(32);
|
|
bn = BN.fromBuffer(privbuf);
|
|
condition = bn.lt(Point.getN());
|
|
} while (!condition);
|
|
return bn;
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a WIF Buffer into a private key
|
|
*
|
|
* @param {Buffer} buf - An WIF string
|
|
* @param {Network|string=} network - a {@link Network} object, or a string with the network name
|
|
* @returns {Object} An object with keys: bn, network and compressed
|
|
* @private
|
|
*/
|
|
PrivateKey._transformBuffer = function(buf, network) {
|
|
|
|
var info = {};
|
|
|
|
if (buf.length === 32) {
|
|
return PrivateKey._transformBNBuffer(buf, network);
|
|
}
|
|
|
|
info.network = Networks.get(buf[0], 'privatekey');
|
|
|
|
if (!info.network) {
|
|
throw new Error('Invalid network');
|
|
}
|
|
|
|
if (network && info.network !== Networks.get(network)) {
|
|
throw new TypeError('Private key network mismatch');
|
|
}
|
|
|
|
if (buf.length === 1 + 32 + 1 && buf[1 + 32 + 1 - 1] === 1) {
|
|
info.compressed = true;
|
|
} else if (buf.length === 1 + 32) {
|
|
info.compressed = false;
|
|
} else {
|
|
throw new Error('Length of buffer must be 33 (uncompressed) or 34 (compressed)');
|
|
}
|
|
|
|
info.bn = BN.fromBuffer(buf.slice(1, 32 + 1));
|
|
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a BN buffer into a private key
|
|
*
|
|
* @param {Buffer} buf
|
|
* @param {Network|string=} network - a {@link Network} object, or a string with the network name
|
|
* @returns {object} an Object with keys: bn, network, and compressed
|
|
* @private
|
|
*/
|
|
PrivateKey._transformBNBuffer = function(buf, network) {
|
|
var info = {};
|
|
info.network = Networks.get(network) || Networks.defaultNetwork;
|
|
info.bn = BN.fromBuffer(buf);
|
|
info.compressed = false;
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a WIF string into a private key
|
|
*
|
|
* @param {string} buf - An WIF string
|
|
* @returns {Object} An object with keys: bn, network and compressed
|
|
* @private
|
|
*/
|
|
PrivateKey._transformWIF = function(str, network) {
|
|
return PrivateKey._transformBuffer(Base58Check.decode(str), network);
|
|
};
|
|
|
|
/**
|
|
* Instantiate a PrivateKey from a Buffer with the DER or WIF representation
|
|
*
|
|
* @param {Buffer} arg
|
|
* @param {Network} network
|
|
* @return {PrivateKey}
|
|
*/
|
|
PrivateKey.fromBuffer = function(arg, network) {
|
|
return new PrivateKey(arg, network);
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a JSON string on plain object into a private key
|
|
* return this.
|
|
*
|
|
* @param {string} json - A JSON string or plain object
|
|
* @returns {Object} An object with keys: bn, network and compressed
|
|
* @private
|
|
*/
|
|
PrivateKey._transformObject = function(json) {
|
|
var bn = new BN(json.bn, 'hex');
|
|
var network = Networks.get(json.network);
|
|
return {
|
|
bn: bn,
|
|
network: network,
|
|
compressed: json.compressed
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Instantiate a PrivateKey from a WIF string
|
|
*
|
|
* @param {string} str - The WIF encoded private key string
|
|
* @returns {PrivateKey} A new valid instance of PrivateKey
|
|
*/
|
|
PrivateKey.fromString = PrivateKey.fromWIF = function(str) {
|
|
$.checkArgument(_.isString(str), 'First argument is expected to be a string.');
|
|
return new PrivateKey(str);
|
|
};
|
|
|
|
/**
|
|
* Instantiate a PrivateKey from a plain JavaScript object
|
|
*
|
|
* @param {Object} obj - The output from privateKey.toObject()
|
|
*/
|
|
PrivateKey.fromObject = function(obj) {
|
|
$.checkArgument(_.isObject(obj), 'First argument is expected to be an object.');
|
|
return new PrivateKey(obj);
|
|
};
|
|
|
|
/**
|
|
* Instantiate a PrivateKey from random bytes
|
|
*
|
|
* @param {string=} network - Either "livenet" or "testnet"
|
|
* @returns {PrivateKey} A new valid instance of PrivateKey
|
|
*/
|
|
PrivateKey.fromRandom = function(network) {
|
|
var bn = PrivateKey._getRandomBN();
|
|
return new PrivateKey(bn, network);
|
|
};
|
|
|
|
/**
|
|
* Check if there would be any errors when initializing a PrivateKey
|
|
*
|
|
* @param {string} data - The encoded data in various formats
|
|
* @param {string=} network - Either "livenet" or "testnet"
|
|
* @returns {null|Error} An error if exists
|
|
*/
|
|
|
|
PrivateKey.getValidationError = function(data, network) {
|
|
var error;
|
|
try {
|
|
/* jshint nonew: false */
|
|
new PrivateKey(data, network);
|
|
} catch (e) {
|
|
error = e;
|
|
}
|
|
return error;
|
|
};
|
|
|
|
/**
|
|
* Check if the parameters are valid
|
|
*
|
|
* @param {string} data - The encoded data in various formats
|
|
* @param {string=} network - Either "livenet" or "testnet"
|
|
* @returns {Boolean} If the private key is would be valid
|
|
*/
|
|
PrivateKey.isValid = function(data, network){
|
|
if (!data) {
|
|
return false;
|
|
}
|
|
return !PrivateKey.getValidationError(data, network);
|
|
};
|
|
|
|
/**
|
|
* Will output the PrivateKey encoded as hex string
|
|
*
|
|
* @returns {string}
|
|
*/
|
|
PrivateKey.prototype.toString = function() {
|
|
return this.toBuffer().toString('hex');
|
|
};
|
|
|
|
/**
|
|
* Will output the PrivateKey to a WIF string
|
|
*
|
|
* @returns {string} A WIP representation of the private key
|
|
*/
|
|
PrivateKey.prototype.toWIF = function() {
|
|
var network = this.network;
|
|
var compressed = this.compressed;
|
|
|
|
var buf;
|
|
if (compressed) {
|
|
buf = Buffer.concat([new Buffer([network.privatekey]),
|
|
this.bn.toBuffer({size: 32}),
|
|
new Buffer([0x01])]);
|
|
} else {
|
|
buf = Buffer.concat([new Buffer([network.privatekey]),
|
|
this.bn.toBuffer({size: 32})]);
|
|
}
|
|
|
|
return Base58Check.encode(buf);
|
|
};
|
|
|
|
/**
|
|
* Will return the private key as a BN instance
|
|
*
|
|
* @returns {BN} A BN instance of the private key
|
|
*/
|
|
PrivateKey.prototype.toBigNumber = function(){
|
|
return this.bn;
|
|
};
|
|
|
|
/**
|
|
* Will return the private key as a BN buffer
|
|
*
|
|
* @returns {Buffer} A buffer of the private key
|
|
*/
|
|
PrivateKey.prototype.toBuffer = function(){
|
|
// TODO: use `return this.bn.toBuffer({ size: 32 })` in v1.0.0
|
|
return this.bn.toBuffer();
|
|
};
|
|
|
|
/**
|
|
* WARNING: This method will not be officially supported until v1.0.0.
|
|
*
|
|
*
|
|
* Will return the private key as a BN buffer without leading zero padding
|
|
*
|
|
* @returns {Buffer} A buffer of the private key
|
|
*/
|
|
PrivateKey.prototype.toBufferNoPadding = function() {
|
|
return this.bn.toBuffer();
|
|
};
|
|
|
|
/**
|
|
* Will return the corresponding public key
|
|
*
|
|
* @returns {PublicKey} A public key generated from the private key
|
|
*/
|
|
PrivateKey.prototype.toPublicKey = function(){
|
|
if (!this._pubkey) {
|
|
this._pubkey = PublicKey.fromPrivateKey(this);
|
|
}
|
|
return this._pubkey;
|
|
};
|
|
|
|
/**
|
|
* Will return an address for the private key
|
|
* @param {Network=} network - optional parameter specifying
|
|
* the desired network for the address
|
|
*
|
|
* @returns {Address} An address generated from the private key
|
|
*/
|
|
PrivateKey.prototype.toAddress = function(network) {
|
|
var pubkey = this.toPublicKey();
|
|
return Address.fromPublicKey(pubkey, network || this.network);
|
|
};
|
|
|
|
/**
|
|
* @returns {Object} A plain object representation
|
|
*/
|
|
PrivateKey.prototype.toObject = PrivateKey.prototype.toJSON = function toObject() {
|
|
return {
|
|
bn: this.bn.toString('hex'),
|
|
compressed: this.compressed,
|
|
network: this.network.toString()
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Will return a string formatted for the console
|
|
*
|
|
* @returns {string} Private key
|
|
*/
|
|
PrivateKey.prototype.inspect = function() {
|
|
var uncompressed = !this.compressed ? ', uncompressed' : '';
|
|
return '<PrivateKey: ' + this.toString() + ', network: ' + this.network + uncompressed + '>';
|
|
};
|
|
|
|
module.exports = PrivateKey;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./address":1,"./crypto/bn":6,"./crypto/point":9,"./crypto/random":10,"./encoding/base58check":13,"./networks":21,"./publickey":24,"./util/js":43,"./util/preconditions":44,"buffer":47,"lodash":319}],24:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var BN = require('./crypto/bn');
|
|
var Point = require('./crypto/point');
|
|
var Hash = require('./crypto/hash');
|
|
var JSUtil = require('./util/js');
|
|
var Network = require('./networks');
|
|
var _ = require('lodash');
|
|
var $ = require('./util/preconditions');
|
|
|
|
/**
|
|
* Instantiate a PublicKey from a {@link PrivateKey}, {@link Point}, `string`, or `Buffer`.
|
|
*
|
|
* There are two internal properties, `network` and `compressed`, that deal with importing
|
|
* a PublicKey from a PrivateKey in WIF format. More details described on {@link PrivateKey}
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* // instantiate from a private key
|
|
* var key = PublicKey(privateKey, true);
|
|
*
|
|
* // export to as a DER hex encoded string
|
|
* var exported = key.toString();
|
|
*
|
|
* // import the public key
|
|
* var imported = PublicKey.fromString(exported);
|
|
* ```
|
|
*
|
|
* @param {string} data - The encoded data in various formats
|
|
* @param {Object} extra - additional options
|
|
* @param {Network=} extra.network - Which network should the address for this public key be for
|
|
* @param {String=} extra.compressed - If the public key is compressed
|
|
* @returns {PublicKey} A new valid instance of an PublicKey
|
|
* @constructor
|
|
*/
|
|
function PublicKey(data, extra) {
|
|
|
|
if (!(this instanceof PublicKey)) {
|
|
return new PublicKey(data, extra);
|
|
}
|
|
|
|
$.checkArgument(data, 'First argument is required, please include public key data.');
|
|
|
|
if (data instanceof PublicKey) {
|
|
// Return copy, but as it's an immutable object, return same argument
|
|
return data;
|
|
}
|
|
extra = extra || {};
|
|
|
|
var info = this._classifyArgs(data, extra);
|
|
|
|
// validation
|
|
info.point.validate();
|
|
|
|
JSUtil.defineImmutable(this, {
|
|
point: info.point,
|
|
compressed: info.compressed,
|
|
network: info.network || Network.defaultNetwork
|
|
});
|
|
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Internal function to differentiate between arguments passed to the constructor
|
|
* @param {*} data
|
|
* @param {Object} extra
|
|
*/
|
|
PublicKey.prototype._classifyArgs = function(data, extra) {
|
|
/* jshint maxcomplexity: 10 */
|
|
var info = {
|
|
compressed: _.isUndefined(extra.compressed) || extra.compressed
|
|
};
|
|
|
|
// detect type of data
|
|
if (data instanceof Point) {
|
|
info.point = data;
|
|
} else if (data.x && data.y) {
|
|
info = PublicKey._transformObject(data);
|
|
} else if (typeof(data) === 'string') {
|
|
info = PublicKey._transformDER(new Buffer(data, 'hex'));
|
|
} else if (PublicKey._isBuffer(data)) {
|
|
info = PublicKey._transformDER(data);
|
|
} else if (PublicKey._isPrivateKey(data)) {
|
|
info = PublicKey._transformPrivateKey(data);
|
|
} else {
|
|
throw new TypeError('First argument is an unrecognized data format.');
|
|
}
|
|
if (!info.network) {
|
|
info.network = _.isUndefined(extra.network) ? undefined : Network.get(extra.network);
|
|
}
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Internal function to detect if an object is a {@link PrivateKey}
|
|
*
|
|
* @param {*} param - object to test
|
|
* @returns {boolean}
|
|
* @private
|
|
*/
|
|
PublicKey._isPrivateKey = function(param) {
|
|
var PrivateKey = require('./privatekey');
|
|
return param instanceof PrivateKey;
|
|
};
|
|
|
|
/**
|
|
* Internal function to detect if an object is a Buffer
|
|
*
|
|
* @param {*} param - object to test
|
|
* @returns {boolean}
|
|
* @private
|
|
*/
|
|
PublicKey._isBuffer = function(param) {
|
|
return (param instanceof Buffer) || (param instanceof Uint8Array);
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a private key into a public key point
|
|
*
|
|
* @param {PrivateKey} privkey - An instance of PrivateKey
|
|
* @returns {Object} An object with keys: point and compressed
|
|
* @private
|
|
*/
|
|
PublicKey._transformPrivateKey = function(privkey) {
|
|
$.checkArgument(PublicKey._isPrivateKey(privkey), 'Must be an instance of PrivateKey');
|
|
var info = {};
|
|
info.point = Point.getG().mul(privkey.bn);
|
|
info.compressed = privkey.compressed;
|
|
info.network = privkey.network;
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform DER into a public key point
|
|
*
|
|
* @param {Buffer} buf - An hex encoded buffer
|
|
* @param {bool=} strict - if set to false, will loosen some conditions
|
|
* @returns {Object} An object with keys: point and compressed
|
|
* @private
|
|
*/
|
|
PublicKey._transformDER = function(buf, strict) {
|
|
/* jshint maxstatements: 30 */
|
|
/* jshint maxcomplexity: 12 */
|
|
$.checkArgument(PublicKey._isBuffer(buf), 'Must be a hex buffer of DER encoded public key');
|
|
var info = {};
|
|
|
|
strict = _.isUndefined(strict) ? true : strict;
|
|
|
|
var x;
|
|
var y;
|
|
var xbuf;
|
|
var ybuf;
|
|
|
|
if (buf[0] === 0x04 || (!strict && (buf[0] === 0x06 || buf[0] === 0x07))) {
|
|
xbuf = buf.slice(1, 33);
|
|
ybuf = buf.slice(33, 65);
|
|
if (xbuf.length !== 32 || ybuf.length !== 32 || buf.length !== 65) {
|
|
throw new TypeError('Length of x and y must be 32 bytes');
|
|
}
|
|
x = new BN(xbuf);
|
|
y = new BN(ybuf);
|
|
info.point = new Point(x, y);
|
|
info.compressed = false;
|
|
} else if (buf[0] === 0x03) {
|
|
xbuf = buf.slice(1);
|
|
x = new BN(xbuf);
|
|
info = PublicKey._transformX(true, x);
|
|
info.compressed = true;
|
|
} else if (buf[0] === 0x02) {
|
|
xbuf = buf.slice(1);
|
|
x = new BN(xbuf);
|
|
info = PublicKey._transformX(false, x);
|
|
info.compressed = true;
|
|
} else {
|
|
throw new TypeError('Invalid DER format public key');
|
|
}
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform X into a public key point
|
|
*
|
|
* @param {Boolean} odd - If the point is above or below the x axis
|
|
* @param {Point} x - The x point
|
|
* @returns {Object} An object with keys: point and compressed
|
|
* @private
|
|
*/
|
|
PublicKey._transformX = function(odd, x) {
|
|
$.checkArgument(typeof odd === 'boolean', 'Must specify whether y is odd or not (true or false)');
|
|
var info = {};
|
|
info.point = Point.fromX(odd, x);
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a JSON into a public key point
|
|
*
|
|
* @param {String|Object} json - a JSON string or plain object
|
|
* @returns {Object} An object with keys: point and compressed
|
|
* @private
|
|
*/
|
|
PublicKey._transformObject = function(json) {
|
|
var x = new BN(json.x, 'hex');
|
|
var y = new BN(json.y, 'hex');
|
|
var point = new Point(x, y);
|
|
return new PublicKey(point, {
|
|
compressed: json.compressed
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Instantiate a PublicKey from a PrivateKey
|
|
*
|
|
* @param {PrivateKey} privkey - An instance of PrivateKey
|
|
* @returns {PublicKey} A new valid instance of PublicKey
|
|
*/
|
|
PublicKey.fromPrivateKey = function(privkey) {
|
|
$.checkArgument(PublicKey._isPrivateKey(privkey), 'Must be an instance of PrivateKey');
|
|
var info = PublicKey._transformPrivateKey(privkey);
|
|
return new PublicKey(info.point, {
|
|
compressed: info.compressed,
|
|
network: info.network
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Instantiate a PublicKey from a Buffer
|
|
* @param {Buffer} buf - A DER hex buffer
|
|
* @param {bool=} strict - if set to false, will loosen some conditions
|
|
* @returns {PublicKey} A new valid instance of PublicKey
|
|
*/
|
|
PublicKey.fromDER = PublicKey.fromBuffer = function(buf, strict) {
|
|
$.checkArgument(PublicKey._isBuffer(buf), 'Must be a hex buffer of DER encoded public key');
|
|
var info = PublicKey._transformDER(buf, strict);
|
|
return new PublicKey(info.point, {
|
|
compressed: info.compressed
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Instantiate a PublicKey from a Point
|
|
*
|
|
* @param {Point} point - A Point instance
|
|
* @param {boolean=} compressed - whether to store this public key as compressed format
|
|
* @returns {PublicKey} A new valid instance of PublicKey
|
|
*/
|
|
PublicKey.fromPoint = function(point, compressed) {
|
|
$.checkArgument(point instanceof Point, 'First argument must be an instance of Point.');
|
|
return new PublicKey(point, {
|
|
compressed: compressed
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Instantiate a PublicKey from a DER hex encoded string
|
|
*
|
|
* @param {string} str - A DER hex string
|
|
* @param {String=} encoding - The type of string encoding
|
|
* @returns {PublicKey} A new valid instance of PublicKey
|
|
*/
|
|
PublicKey.fromString = function(str, encoding) {
|
|
var buf = new Buffer(str, encoding || 'hex');
|
|
var info = PublicKey._transformDER(buf);
|
|
return new PublicKey(info.point, {
|
|
compressed: info.compressed
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Instantiate a PublicKey from an X Point
|
|
*
|
|
* @param {Boolean} odd - If the point is above or below the x axis
|
|
* @param {Point} x - The x point
|
|
* @returns {PublicKey} A new valid instance of PublicKey
|
|
*/
|
|
PublicKey.fromX = function(odd, x) {
|
|
var info = PublicKey._transformX(odd, x);
|
|
return new PublicKey(info.point, {
|
|
compressed: info.compressed
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Check if there would be any errors when initializing a PublicKey
|
|
*
|
|
* @param {string} data - The encoded data in various formats
|
|
* @returns {null|Error} An error if exists
|
|
*/
|
|
PublicKey.getValidationError = function(data) {
|
|
var error;
|
|
try {
|
|
/* jshint nonew: false */
|
|
new PublicKey(data);
|
|
} catch (e) {
|
|
error = e;
|
|
}
|
|
return error;
|
|
};
|
|
|
|
/**
|
|
* Check if the parameters are valid
|
|
*
|
|
* @param {string} data - The encoded data in various formats
|
|
* @returns {Boolean} If the public key would be valid
|
|
*/
|
|
PublicKey.isValid = function(data) {
|
|
return !PublicKey.getValidationError(data);
|
|
};
|
|
|
|
/**
|
|
* @returns {Object} A plain object of the PublicKey
|
|
*/
|
|
PublicKey.prototype.toObject = PublicKey.prototype.toJSON = function toObject() {
|
|
return {
|
|
x: this.point.getX().toString('hex', 2),
|
|
y: this.point.getY().toString('hex', 2),
|
|
compressed: this.compressed
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Will output the PublicKey to a DER Buffer
|
|
*
|
|
* @returns {Buffer} A DER hex encoded buffer
|
|
*/
|
|
PublicKey.prototype.toBuffer = PublicKey.prototype.toDER = function() {
|
|
var x = this.point.getX();
|
|
var y = this.point.getY();
|
|
|
|
var xbuf = x.toBuffer({
|
|
size: 32
|
|
});
|
|
var ybuf = y.toBuffer({
|
|
size: 32
|
|
});
|
|
|
|
var prefix;
|
|
if (!this.compressed) {
|
|
prefix = new Buffer([0x04]);
|
|
return Buffer.concat([prefix, xbuf, ybuf]);
|
|
} else {
|
|
var odd = ybuf[ybuf.length - 1] % 2;
|
|
if (odd) {
|
|
prefix = new Buffer([0x03]);
|
|
} else {
|
|
prefix = new Buffer([0x02]);
|
|
}
|
|
return Buffer.concat([prefix, xbuf]);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Will return a sha256 + ripemd160 hash of the serialized public key
|
|
* @see https://github.com/bitcoin/bitcoin/blob/master/src/pubkey.h#L141
|
|
* @returns {Buffer}
|
|
*/
|
|
PublicKey.prototype._getID = function _getID() {
|
|
return Hash.sha256ripemd160(this.toBuffer());
|
|
};
|
|
|
|
/**
|
|
* Will return an address for the public key
|
|
*
|
|
* @param {String|Network=} network - Which network should the address be for
|
|
* @returns {Address} An address generated from the public key
|
|
*/
|
|
PublicKey.prototype.toAddress = function(network) {
|
|
var Address = require('./address');
|
|
return Address.fromPublicKey(this, network || this.network);
|
|
};
|
|
|
|
/**
|
|
* Will output the PublicKey to a DER encoded hex string
|
|
*
|
|
* @returns {string} A DER hex encoded string
|
|
*/
|
|
PublicKey.prototype.toString = function() {
|
|
return this.toDER().toString('hex');
|
|
};
|
|
|
|
/**
|
|
* Will return a string formatted for the console
|
|
*
|
|
* @returns {string} Public key
|
|
*/
|
|
PublicKey.prototype.inspect = function() {
|
|
return '<PublicKey: ' + this.toString() +
|
|
(this.compressed ? '' : ', uncompressed') + '>';
|
|
};
|
|
|
|
|
|
module.exports = PublicKey;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./address":1,"./crypto/bn":6,"./crypto/hash":8,"./crypto/point":9,"./networks":21,"./privatekey":23,"./util/js":43,"./util/preconditions":44,"buffer":47,"lodash":319}],25:[function(require,module,exports){
|
|
module.exports = require('./script');
|
|
|
|
module.exports.Interpreter = require('./interpreter');
|
|
|
|
},{"./interpreter":26,"./script":27}],26:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
|
|
var Script = require('./script');
|
|
var Opcode = require('../opcode');
|
|
var BN = require('../crypto/bn');
|
|
var Hash = require('../crypto/hash');
|
|
var Signature = require('../crypto/signature');
|
|
var PublicKey = require('../publickey');
|
|
|
|
/**
|
|
* Bitcoin transactions contain scripts. Each input has a script called the
|
|
* scriptSig, and each output has a script called the scriptPubkey. To validate
|
|
* an input, the input's script is concatenated with the referenced output script,
|
|
* and the result is executed. If at the end of execution the stack contains a
|
|
* "true" value, then the transaction is valid.
|
|
*
|
|
* The primary way to use this class is via the verify function.
|
|
* e.g., Interpreter().verify( ... );
|
|
*/
|
|
var Interpreter = function Interpreter(obj) {
|
|
if (!(this instanceof Interpreter)) {
|
|
return new Interpreter(obj);
|
|
}
|
|
if (obj) {
|
|
this.initialize();
|
|
this.set(obj);
|
|
} else {
|
|
this.initialize();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Verifies a Script by executing it and returns true if it is valid.
|
|
* This function needs to be provided with the scriptSig and the scriptPubkey
|
|
* separately.
|
|
* @param {Script} scriptSig - the script's first part (corresponding to the tx input)
|
|
* @param {Script} scriptPubkey - the script's last part (corresponding to the tx output)
|
|
* @param {Transaction=} tx - the Transaction containing the scriptSig in one input (used
|
|
* to check signature validity for some opcodes like OP_CHECKSIG)
|
|
* @param {number} nin - index of the transaction input containing the scriptSig verified.
|
|
* @param {number} flags - evaluation flags. See Interpreter.SCRIPT_* constants
|
|
*
|
|
* Translated from bitcoind's VerifyScript
|
|
*/
|
|
Interpreter.prototype.verify = function(scriptSig, scriptPubkey, tx, nin, flags) {
|
|
var Transaction = require('../transaction');
|
|
if (_.isUndefined(tx)) {
|
|
tx = new Transaction();
|
|
}
|
|
if (_.isUndefined(nin)) {
|
|
nin = 0;
|
|
}
|
|
if (_.isUndefined(flags)) {
|
|
flags = 0;
|
|
}
|
|
this.set({
|
|
script: scriptSig,
|
|
tx: tx,
|
|
nin: nin,
|
|
flags: flags
|
|
});
|
|
var stackCopy;
|
|
|
|
if ((flags & Interpreter.SCRIPT_VERIFY_SIGPUSHONLY) !== 0 && !scriptSig.isPushOnly()) {
|
|
this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY';
|
|
return false;
|
|
}
|
|
|
|
// evaluate scriptSig
|
|
if (!this.evaluate()) {
|
|
return false;
|
|
}
|
|
|
|
if (flags & Interpreter.SCRIPT_VERIFY_P2SH) {
|
|
stackCopy = this.stack.slice();
|
|
}
|
|
|
|
var stack = this.stack;
|
|
this.initialize();
|
|
this.set({
|
|
script: scriptPubkey,
|
|
stack: stack,
|
|
tx: tx,
|
|
nin: nin,
|
|
flags: flags
|
|
});
|
|
|
|
// evaluate scriptPubkey
|
|
if (!this.evaluate()) {
|
|
return false;
|
|
}
|
|
|
|
if (this.stack.length === 0) {
|
|
this.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_RESULT';
|
|
return false;
|
|
}
|
|
|
|
var buf = this.stack[this.stack.length - 1];
|
|
if (!Interpreter.castToBool(buf)) {
|
|
this.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_STACK';
|
|
return false;
|
|
}
|
|
|
|
// Additional validation for spend-to-script-hash transactions:
|
|
if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) && scriptPubkey.isScriptHashOut()) {
|
|
// scriptSig must be literals-only or validation fails
|
|
if (!scriptSig.isPushOnly()) {
|
|
this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY';
|
|
return false;
|
|
}
|
|
|
|
// stackCopy cannot be empty here, because if it was the
|
|
// P2SH HASH <> EQUAL scriptPubKey would be evaluated with
|
|
// an empty stack and the EvalScript above would return false.
|
|
if (stackCopy.length === 0) {
|
|
throw new Error('internal error - stack copy empty');
|
|
}
|
|
|
|
var redeemScriptSerialized = stackCopy[stackCopy.length - 1];
|
|
var redeemScript = Script.fromBuffer(redeemScriptSerialized);
|
|
stackCopy.pop();
|
|
|
|
this.initialize();
|
|
this.set({
|
|
script: redeemScript,
|
|
stack: stackCopy,
|
|
tx: tx,
|
|
nin: nin,
|
|
flags: flags
|
|
});
|
|
|
|
// evaluate redeemScript
|
|
if (!this.evaluate()) {
|
|
return false;
|
|
}
|
|
|
|
if (stackCopy.length === 0) {
|
|
this.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_P2SH_STACK';
|
|
return false;
|
|
}
|
|
|
|
if (!Interpreter.castToBool(stackCopy[stackCopy.length - 1])) {
|
|
this.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_P2SH_STACK';
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
module.exports = Interpreter;
|
|
|
|
Interpreter.prototype.initialize = function(obj) {
|
|
this.stack = [];
|
|
this.altstack = [];
|
|
this.pc = 0;
|
|
this.pbegincodehash = 0;
|
|
this.nOpCount = 0;
|
|
this.vfExec = [];
|
|
this.errstr = '';
|
|
this.flags = 0;
|
|
};
|
|
|
|
Interpreter.prototype.set = function(obj) {
|
|
this.script = obj.script || this.script;
|
|
this.tx = obj.tx || this.tx;
|
|
this.nin = typeof obj.nin !== 'undefined' ? obj.nin : this.nin;
|
|
this.stack = obj.stack || this.stack;
|
|
this.altstack = obj.altack || this.altstack;
|
|
this.pc = typeof obj.pc !== 'undefined' ? obj.pc : this.pc;
|
|
this.pbegincodehash = typeof obj.pbegincodehash !== 'undefined' ? obj.pbegincodehash : this.pbegincodehash;
|
|
this.nOpCount = typeof obj.nOpCount !== 'undefined' ? obj.nOpCount : this.nOpCount;
|
|
this.vfExec = obj.vfExec || this.vfExec;
|
|
this.errstr = obj.errstr || this.errstr;
|
|
this.flags = typeof obj.flags !== 'undefined' ? obj.flags : this.flags;
|
|
};
|
|
|
|
Interpreter.true = new Buffer([1]);
|
|
Interpreter.false = new Buffer([]);
|
|
|
|
Interpreter.MAX_SCRIPT_ELEMENT_SIZE = 520;
|
|
|
|
Interpreter.LOCKTIME_THRESHOLD = 500000000;
|
|
Interpreter.LOCKTIME_THRESHOLD_BN = new BN(Interpreter.LOCKTIME_THRESHOLD);
|
|
|
|
// flags taken from bitcoind
|
|
// bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
|
|
Interpreter.SCRIPT_VERIFY_NONE = 0;
|
|
|
|
// Evaluate P2SH subscripts (softfork safe, BIP16).
|
|
Interpreter.SCRIPT_VERIFY_P2SH = (1 << 0);
|
|
|
|
// Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
|
|
// Passing a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) to checksig causes that pubkey to be
|
|
// skipped (not softfork safe: this flag can widen the validity of OP_CHECKSIG OP_NOT).
|
|
Interpreter.SCRIPT_VERIFY_STRICTENC = (1 << 1);
|
|
|
|
// Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1)
|
|
Interpreter.SCRIPT_VERIFY_DERSIG = (1 << 2);
|
|
|
|
// Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
|
|
// (softfork safe, BIP62 rule 5).
|
|
Interpreter.SCRIPT_VERIFY_LOW_S = (1 << 3);
|
|
|
|
// verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7).
|
|
Interpreter.SCRIPT_VERIFY_NULLDUMMY = (1 << 4);
|
|
|
|
// Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2).
|
|
Interpreter.SCRIPT_VERIFY_SIGPUSHONLY = (1 << 5);
|
|
|
|
// Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct
|
|
// pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating
|
|
// any other push causes the script to fail (BIP62 rule 3).
|
|
// In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4).
|
|
// (softfork safe)
|
|
Interpreter.SCRIPT_VERIFY_MINIMALDATA = (1 << 6);
|
|
|
|
// Discourage use of NOPs reserved for upgrades (NOP1-10)
|
|
//
|
|
// Provided so that nodes can avoid accepting or mining transactions
|
|
// containing executed NOP's whose meaning may change after a soft-fork,
|
|
// thus rendering the script invalid; with this flag set executing
|
|
// discouraged NOPs fails the script. This verification flag will never be
|
|
// a mandatory flag applied to scripts in a block. NOPs that are not
|
|
// executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected.
|
|
Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1 << 7);
|
|
|
|
// CLTV See BIP65 for details.
|
|
Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1 << 9);
|
|
|
|
Interpreter.castToBool = function(buf) {
|
|
for (var i = 0; i < buf.length; i++) {
|
|
if (buf[i] !== 0) {
|
|
// can be negative zero
|
|
if (i === buf.length - 1 && buf[i] === 0x80) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Translated from bitcoind's CheckSignatureEncoding
|
|
*/
|
|
Interpreter.prototype.checkSignatureEncoding = function(buf) {
|
|
var sig;
|
|
if ((this.flags & (Interpreter.SCRIPT_VERIFY_DERSIG | Interpreter.SCRIPT_VERIFY_LOW_S | Interpreter.SCRIPT_VERIFY_STRICTENC)) !== 0 && !Signature.isTxDER(buf)) {
|
|
this.errstr = 'SCRIPT_ERR_SIG_DER_INVALID_FORMAT';
|
|
return false;
|
|
} else if ((this.flags & Interpreter.SCRIPT_VERIFY_LOW_S) !== 0) {
|
|
sig = Signature.fromTxFormat(buf);
|
|
if (!sig.hasLowS()) {
|
|
this.errstr = 'SCRIPT_ERR_SIG_DER_HIGH_S';
|
|
return false;
|
|
}
|
|
} else if ((this.flags & Interpreter.SCRIPT_VERIFY_STRICTENC) !== 0) {
|
|
sig = Signature.fromTxFormat(buf);
|
|
if (!sig.hasDefinedHashtype()) {
|
|
this.errstr = 'SCRIPT_ERR_SIG_HASHTYPE';
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Translated from bitcoind's CheckPubKeyEncoding
|
|
*/
|
|
Interpreter.prototype.checkPubkeyEncoding = function(buf) {
|
|
if ((this.flags & Interpreter.SCRIPT_VERIFY_STRICTENC) !== 0 && !PublicKey.isValid(buf)) {
|
|
this.errstr = 'SCRIPT_ERR_PUBKEYTYPE';
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Based on bitcoind's EvalScript function, with the inner loop moved to
|
|
* Interpreter.prototype.step()
|
|
* bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
|
|
*/
|
|
Interpreter.prototype.evaluate = function() {
|
|
if (this.script.toBuffer().length > 10000) {
|
|
this.errstr = 'SCRIPT_ERR_SCRIPT_SIZE';
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
while (this.pc < this.script.chunks.length) {
|
|
var fSuccess = this.step();
|
|
if (!fSuccess) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Size limits
|
|
if (this.stack.length + this.altstack.length > 1000) {
|
|
this.errstr = 'SCRIPT_ERR_STACK_SIZE';
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
this.errstr = 'SCRIPT_ERR_UNKNOWN_ERROR: ' + e;
|
|
return false;
|
|
}
|
|
|
|
if (this.vfExec.length > 0) {
|
|
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Checks a locktime parameter with the transaction's locktime.
|
|
* There are two times of nLockTime: lock-by-blockheight and lock-by-blocktime,
|
|
* distinguished by whether nLockTime < LOCKTIME_THRESHOLD = 500000000
|
|
*
|
|
* See the corresponding code on bitcoin core:
|
|
* https://github.com/bitcoin/bitcoin/blob/ffd75adce01a78b3461b3ff05bcc2b530a9ce994/src/script/interpreter.cpp#L1129
|
|
*
|
|
* @param {BN} nLockTime the locktime read from the script
|
|
* @return {boolean} true if the transaction's locktime is less than or equal to
|
|
* the transaction's locktime
|
|
*/
|
|
Interpreter.prototype.checkLockTime = function(nLockTime) {
|
|
|
|
// We want to compare apples to apples, so fail the script
|
|
// unless the type of nLockTime being tested is the same as
|
|
// the nLockTime in the transaction.
|
|
if (!(
|
|
(this.tx.nLockTime < Interpreter.LOCKTIME_THRESHOLD && nLockTime.lt(Interpreter.LOCKTIME_THRESHOLD_BN)) ||
|
|
(this.tx.nLockTime >= Interpreter.LOCKTIME_THRESHOLD && nLockTime.gte(Interpreter.LOCKTIME_THRESHOLD_BN))
|
|
)) {
|
|
return false;
|
|
}
|
|
|
|
// Now that we know we're comparing apples-to-apples, the
|
|
// comparison is a simple numeric one.
|
|
if (nLockTime.gt(new BN(this.tx.nLockTime))) {
|
|
return false;
|
|
}
|
|
|
|
// Finally the nLockTime feature can be disabled and thus
|
|
// CHECKLOCKTIMEVERIFY bypassed if every txin has been
|
|
// finalized by setting nSequence to maxint. The
|
|
// transaction would be allowed into the blockchain, making
|
|
// the opcode ineffective.
|
|
//
|
|
// Testing if this vin is not final is sufficient to
|
|
// prevent this condition. Alternatively we could test all
|
|
// inputs, but testing just this input minimizes the data
|
|
// required to prove correct CHECKLOCKTIMEVERIFY execution.
|
|
if (!this.tx.inputs[this.nin].isFinal()) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Based on the inner loop of bitcoind's EvalScript function
|
|
* bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
|
|
*/
|
|
Interpreter.prototype.step = function() {
|
|
|
|
var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0;
|
|
|
|
//bool fExec = !count(vfExec.begin(), vfExec.end(), false);
|
|
var fExec = (this.vfExec.indexOf(false) === -1);
|
|
var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript;
|
|
var sig, pubkey;
|
|
var fValue, fSuccess;
|
|
|
|
// Read instruction
|
|
var chunk = this.script.chunks[this.pc];
|
|
this.pc++;
|
|
var opcodenum = chunk.opcodenum;
|
|
if (_.isUndefined(opcodenum)) {
|
|
this.errstr = 'SCRIPT_ERR_UNDEFINED_OPCODE';
|
|
return false;
|
|
}
|
|
if (chunk.buf && chunk.buf.length > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) {
|
|
this.errstr = 'SCRIPT_ERR_PUSH_SIZE';
|
|
return false;
|
|
}
|
|
|
|
// Note how Opcode.OP_RESERVED does not count towards the opcode limit.
|
|
if (opcodenum > Opcode.OP_16 && ++(this.nOpCount) > 201) {
|
|
this.errstr = 'SCRIPT_ERR_OP_COUNT';
|
|
return false;
|
|
}
|
|
|
|
|
|
if (opcodenum === Opcode.OP_CAT ||
|
|
opcodenum === Opcode.OP_SUBSTR ||
|
|
opcodenum === Opcode.OP_LEFT ||
|
|
opcodenum === Opcode.OP_RIGHT ||
|
|
opcodenum === Opcode.OP_INVERT ||
|
|
opcodenum === Opcode.OP_AND ||
|
|
opcodenum === Opcode.OP_OR ||
|
|
opcodenum === Opcode.OP_XOR ||
|
|
opcodenum === Opcode.OP_2MUL ||
|
|
opcodenum === Opcode.OP_2DIV ||
|
|
opcodenum === Opcode.OP_MUL ||
|
|
opcodenum === Opcode.OP_DIV ||
|
|
opcodenum === Opcode.OP_MOD ||
|
|
opcodenum === Opcode.OP_LSHIFT ||
|
|
opcodenum === Opcode.OP_RSHIFT) {
|
|
this.errstr = 'SCRIPT_ERR_DISABLED_OPCODE';
|
|
return false;
|
|
}
|
|
|
|
if (fExec && 0 <= opcodenum && opcodenum <= Opcode.OP_PUSHDATA4) {
|
|
if (fRequireMinimal && !this.script.checkMinimalPush(this.pc - 1)) {
|
|
this.errstr = 'SCRIPT_ERR_MINIMALDATA';
|
|
return false;
|
|
}
|
|
if (!chunk.buf) {
|
|
this.stack.push(Interpreter.false);
|
|
} else if (chunk.len !== chunk.buf.length) {
|
|
throw new Error('Length of push value not equal to length of data');
|
|
} else {
|
|
this.stack.push(chunk.buf);
|
|
}
|
|
} else if (fExec || (Opcode.OP_IF <= opcodenum && opcodenum <= Opcode.OP_ENDIF)) {
|
|
switch (opcodenum) {
|
|
// Push value
|
|
case Opcode.OP_1NEGATE:
|
|
case Opcode.OP_1:
|
|
case Opcode.OP_2:
|
|
case Opcode.OP_3:
|
|
case Opcode.OP_4:
|
|
case Opcode.OP_5:
|
|
case Opcode.OP_6:
|
|
case Opcode.OP_7:
|
|
case Opcode.OP_8:
|
|
case Opcode.OP_9:
|
|
case Opcode.OP_10:
|
|
case Opcode.OP_11:
|
|
case Opcode.OP_12:
|
|
case Opcode.OP_13:
|
|
case Opcode.OP_14:
|
|
case Opcode.OP_15:
|
|
case Opcode.OP_16:
|
|
{
|
|
// ( -- value)
|
|
// ScriptNum bn((int)opcode - (int)(Opcode.OP_1 - 1));
|
|
n = opcodenum - (Opcode.OP_1 - 1);
|
|
buf = new BN(n).toScriptNumBuffer();
|
|
this.stack.push(buf);
|
|
// The result of these opcodes should always be the minimal way to push the data
|
|
// they push, so no need for a CheckMinimalPush here.
|
|
}
|
|
break;
|
|
|
|
|
|
//
|
|
// Control
|
|
//
|
|
case Opcode.OP_NOP:
|
|
break;
|
|
|
|
case Opcode.OP_NOP2:
|
|
case Opcode.OP_CHECKLOCKTIMEVERIFY:
|
|
|
|
if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
|
|
// not enabled; treat as a NOP2
|
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS';
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
|
|
// Note that elsewhere numeric opcodes are limited to
|
|
// operands in the range -2**31+1 to 2**31-1, however it is
|
|
// legal for opcodes to produce results exceeding that
|
|
// range. This limitation is implemented by CScriptNum's
|
|
// default 4-byte limit.
|
|
//
|
|
// If we kept to that limit we'd have a year 2038 problem,
|
|
// even though the nLockTime field in transactions
|
|
// themselves is uint32 which only becomes meaningless
|
|
// after the year 2106.
|
|
//
|
|
// Thus as a special case we tell CScriptNum to accept up
|
|
// to 5-byte bignums, which are good until 2**39-1, well
|
|
// beyond the 2**32-1 limit of the nLockTime field itself.
|
|
var nLockTime = BN.fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal, 5);
|
|
|
|
// In the rare event that the argument may be < 0 due to
|
|
// some arithmetic being done first, you can always use
|
|
// 0 MAX CHECKLOCKTIMEVERIFY.
|
|
if (nLockTime.lt(new BN(0))) {
|
|
this.errstr = 'SCRIPT_ERR_NEGATIVE_LOCKTIME';
|
|
return false;
|
|
}
|
|
|
|
// Actually compare the specified lock time with the transaction.
|
|
if (!this.checkLockTime(nLockTime)) {
|
|
this.errstr = 'SCRIPT_ERR_UNSATISFIED_LOCKTIME';
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_NOP1:
|
|
case Opcode.OP_NOP3:
|
|
case Opcode.OP_NOP4:
|
|
case Opcode.OP_NOP5:
|
|
case Opcode.OP_NOP6:
|
|
case Opcode.OP_NOP7:
|
|
case Opcode.OP_NOP8:
|
|
case Opcode.OP_NOP9:
|
|
case Opcode.OP_NOP10:
|
|
{
|
|
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
|
|
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS';
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_IF:
|
|
case Opcode.OP_NOTIF:
|
|
{
|
|
// <expression> if [statements] [else [statements]] endif
|
|
// bool fValue = false;
|
|
fValue = false;
|
|
if (fExec) {
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
|
|
return false;
|
|
}
|
|
buf = this.stack.pop();
|
|
fValue = Interpreter.castToBool(buf);
|
|
if (opcodenum === Opcode.OP_NOTIF) {
|
|
fValue = !fValue;
|
|
}
|
|
}
|
|
this.vfExec.push(fValue);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_ELSE:
|
|
{
|
|
if (this.vfExec.length === 0) {
|
|
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
|
|
return false;
|
|
}
|
|
this.vfExec[this.vfExec.length - 1] = !this.vfExec[this.vfExec.length - 1];
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_ENDIF:
|
|
{
|
|
if (this.vfExec.length === 0) {
|
|
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
|
|
return false;
|
|
}
|
|
this.vfExec.pop();
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_VERIFY:
|
|
{
|
|
// (true -- ) or
|
|
// (false -- false) and return
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
buf = this.stack[this.stack.length - 1];
|
|
fValue = Interpreter.castToBool(buf);
|
|
if (fValue) {
|
|
this.stack.pop();
|
|
} else {
|
|
this.errstr = 'SCRIPT_ERR_VERIFY';
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_RETURN:
|
|
{
|
|
this.errstr = 'SCRIPT_ERR_OP_RETURN';
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
|
|
//
|
|
// Stack ops
|
|
//
|
|
case Opcode.OP_TOALTSTACK:
|
|
{
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
this.altstack.push(this.stack.pop());
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_FROMALTSTACK:
|
|
{
|
|
if (this.altstack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_ALTSTACK_OPERATION';
|
|
return false;
|
|
}
|
|
this.stack.push(this.altstack.pop());
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_2DROP:
|
|
{
|
|
// (x1 x2 -- )
|
|
if (this.stack.length < 2) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
this.stack.pop();
|
|
this.stack.pop();
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_2DUP:
|
|
{
|
|
// (x1 x2 -- x1 x2 x1 x2)
|
|
if (this.stack.length < 2) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
buf1 = this.stack[this.stack.length - 2];
|
|
buf2 = this.stack[this.stack.length - 1];
|
|
this.stack.push(buf1);
|
|
this.stack.push(buf2);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_3DUP:
|
|
{
|
|
// (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
|
|
if (this.stack.length < 3) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
buf1 = this.stack[this.stack.length - 3];
|
|
buf2 = this.stack[this.stack.length - 2];
|
|
var buf3 = this.stack[this.stack.length - 1];
|
|
this.stack.push(buf1);
|
|
this.stack.push(buf2);
|
|
this.stack.push(buf3);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_2OVER:
|
|
{
|
|
// (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
|
|
if (this.stack.length < 4) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
buf1 = this.stack[this.stack.length - 4];
|
|
buf2 = this.stack[this.stack.length - 3];
|
|
this.stack.push(buf1);
|
|
this.stack.push(buf2);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_2ROT:
|
|
{
|
|
// (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
|
|
if (this.stack.length < 6) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
spliced = this.stack.splice(this.stack.length - 6, 2);
|
|
this.stack.push(spliced[0]);
|
|
this.stack.push(spliced[1]);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_2SWAP:
|
|
{
|
|
// (x1 x2 x3 x4 -- x3 x4 x1 x2)
|
|
if (this.stack.length < 4) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
spliced = this.stack.splice(this.stack.length - 4, 2);
|
|
this.stack.push(spliced[0]);
|
|
this.stack.push(spliced[1]);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_IFDUP:
|
|
{
|
|
// (x - 0 | x x)
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
buf = this.stack[this.stack.length - 1];
|
|
fValue = Interpreter.castToBool(buf);
|
|
if (fValue) {
|
|
this.stack.push(buf);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_DEPTH:
|
|
{
|
|
// -- stacksize
|
|
buf = new BN(this.stack.length).toScriptNumBuffer();
|
|
this.stack.push(buf);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_DROP:
|
|
{
|
|
// (x -- )
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
this.stack.pop();
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_DUP:
|
|
{
|
|
// (x -- x x)
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
this.stack.push(this.stack[this.stack.length - 1]);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_NIP:
|
|
{
|
|
// (x1 x2 -- x2)
|
|
if (this.stack.length < 2) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
this.stack.splice(this.stack.length - 2, 1);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_OVER:
|
|
{
|
|
// (x1 x2 -- x1 x2 x1)
|
|
if (this.stack.length < 2) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
this.stack.push(this.stack[this.stack.length - 2]);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_PICK:
|
|
case Opcode.OP_ROLL:
|
|
{
|
|
// (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
|
|
// (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
|
|
if (this.stack.length < 2) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
buf = this.stack[this.stack.length - 1];
|
|
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal);
|
|
n = bn.toNumber();
|
|
this.stack.pop();
|
|
if (n < 0 || n >= this.stack.length) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
buf = this.stack[this.stack.length - n - 1];
|
|
if (opcodenum === Opcode.OP_ROLL) {
|
|
this.stack.splice(this.stack.length - n - 1, 1);
|
|
}
|
|
this.stack.push(buf);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_ROT:
|
|
{
|
|
// (x1 x2 x3 -- x2 x3 x1)
|
|
// x2 x1 x3 after first swap
|
|
// x2 x3 x1 after second swap
|
|
if (this.stack.length < 3) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
x1 = this.stack[this.stack.length - 3];
|
|
x2 = this.stack[this.stack.length - 2];
|
|
var x3 = this.stack[this.stack.length - 1];
|
|
this.stack[this.stack.length - 3] = x2;
|
|
this.stack[this.stack.length - 2] = x3;
|
|
this.stack[this.stack.length - 1] = x1;
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_SWAP:
|
|
{
|
|
// (x1 x2 -- x2 x1)
|
|
if (this.stack.length < 2) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
x1 = this.stack[this.stack.length - 2];
|
|
x2 = this.stack[this.stack.length - 1];
|
|
this.stack[this.stack.length - 2] = x2;
|
|
this.stack[this.stack.length - 1] = x1;
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_TUCK:
|
|
{
|
|
// (x1 x2 -- x2 x1 x2)
|
|
if (this.stack.length < 2) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
this.stack.splice(this.stack.length - 2, 0, this.stack[this.stack.length - 1]);
|
|
}
|
|
break;
|
|
|
|
|
|
case Opcode.OP_SIZE:
|
|
{
|
|
// (in -- in size)
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
bn = new BN(this.stack[this.stack.length - 1].length);
|
|
this.stack.push(bn.toScriptNumBuffer());
|
|
}
|
|
break;
|
|
|
|
|
|
//
|
|
// Bitwise logic
|
|
//
|
|
case Opcode.OP_EQUAL:
|
|
case Opcode.OP_EQUALVERIFY:
|
|
//case Opcode.OP_NOTEQUAL: // use Opcode.OP_NUMNOTEQUAL
|
|
{
|
|
// (x1 x2 - bool)
|
|
if (this.stack.length < 2) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
buf1 = this.stack[this.stack.length - 2];
|
|
buf2 = this.stack[this.stack.length - 1];
|
|
var fEqual = buf1.toString('hex') === buf2.toString('hex');
|
|
this.stack.pop();
|
|
this.stack.pop();
|
|
this.stack.push(fEqual ? Interpreter.true : Interpreter.false);
|
|
if (opcodenum === Opcode.OP_EQUALVERIFY) {
|
|
if (fEqual) {
|
|
this.stack.pop();
|
|
} else {
|
|
this.errstr = 'SCRIPT_ERR_EQUALVERIFY';
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
//
|
|
// Numeric
|
|
//
|
|
case Opcode.OP_1ADD:
|
|
case Opcode.OP_1SUB:
|
|
case Opcode.OP_NEGATE:
|
|
case Opcode.OP_ABS:
|
|
case Opcode.OP_NOT:
|
|
case Opcode.OP_0NOTEQUAL:
|
|
{
|
|
// (in -- out)
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
buf = this.stack[this.stack.length - 1];
|
|
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal);
|
|
switch (opcodenum) {
|
|
case Opcode.OP_1ADD:
|
|
bn = bn.add(BN.One);
|
|
break;
|
|
case Opcode.OP_1SUB:
|
|
bn = bn.sub(BN.One);
|
|
break;
|
|
case Opcode.OP_NEGATE:
|
|
bn = bn.neg();
|
|
break;
|
|
case Opcode.OP_ABS:
|
|
if (bn.cmp(BN.Zero) < 0) {
|
|
bn = bn.neg();
|
|
}
|
|
break;
|
|
case Opcode.OP_NOT:
|
|
bn = new BN((bn.cmp(BN.Zero) === 0) + 0);
|
|
break;
|
|
case Opcode.OP_0NOTEQUAL:
|
|
bn = new BN((bn.cmp(BN.Zero) !== 0) + 0);
|
|
break;
|
|
//default: assert(!'invalid opcode'); break; // TODO: does this ever occur?
|
|
}
|
|
this.stack.pop();
|
|
this.stack.push(bn.toScriptNumBuffer());
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_ADD:
|
|
case Opcode.OP_SUB:
|
|
case Opcode.OP_BOOLAND:
|
|
case Opcode.OP_BOOLOR:
|
|
case Opcode.OP_NUMEQUAL:
|
|
case Opcode.OP_NUMEQUALVERIFY:
|
|
case Opcode.OP_NUMNOTEQUAL:
|
|
case Opcode.OP_LESSTHAN:
|
|
case Opcode.OP_GREATERTHAN:
|
|
case Opcode.OP_LESSTHANOREQUAL:
|
|
case Opcode.OP_GREATERTHANOREQUAL:
|
|
case Opcode.OP_MIN:
|
|
case Opcode.OP_MAX:
|
|
{
|
|
// (x1 x2 -- out)
|
|
if (this.stack.length < 2) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
bn1 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
|
|
bn2 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
|
|
bn = new BN(0);
|
|
|
|
switch (opcodenum) {
|
|
case Opcode.OP_ADD:
|
|
bn = bn1.add(bn2);
|
|
break;
|
|
|
|
case Opcode.OP_SUB:
|
|
bn = bn1.sub(bn2);
|
|
break;
|
|
|
|
// case Opcode.OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break;
|
|
case Opcode.OP_BOOLAND:
|
|
bn = new BN(((bn1.cmp(BN.Zero) !== 0) && (bn2.cmp(BN.Zero) !== 0)) + 0);
|
|
break;
|
|
// case Opcode.OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break;
|
|
case Opcode.OP_BOOLOR:
|
|
bn = new BN(((bn1.cmp(BN.Zero) !== 0) || (bn2.cmp(BN.Zero) !== 0)) + 0);
|
|
break;
|
|
// case Opcode.OP_NUMEQUAL: bn = (bn1 == bn2); break;
|
|
case Opcode.OP_NUMEQUAL:
|
|
bn = new BN((bn1.cmp(bn2) === 0) + 0);
|
|
break;
|
|
// case Opcode.OP_NUMEQUALVERIFY: bn = (bn1 == bn2); break;
|
|
case Opcode.OP_NUMEQUALVERIFY:
|
|
bn = new BN((bn1.cmp(bn2) === 0) + 0);
|
|
break;
|
|
// case Opcode.OP_NUMNOTEQUAL: bn = (bn1 != bn2); break;
|
|
case Opcode.OP_NUMNOTEQUAL:
|
|
bn = new BN((bn1.cmp(bn2) !== 0) + 0);
|
|
break;
|
|
// case Opcode.OP_LESSTHAN: bn = (bn1 < bn2); break;
|
|
case Opcode.OP_LESSTHAN:
|
|
bn = new BN((bn1.cmp(bn2) < 0) + 0);
|
|
break;
|
|
// case Opcode.OP_GREATERTHAN: bn = (bn1 > bn2); break;
|
|
case Opcode.OP_GREATERTHAN:
|
|
bn = new BN((bn1.cmp(bn2) > 0) + 0);
|
|
break;
|
|
// case Opcode.OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break;
|
|
case Opcode.OP_LESSTHANOREQUAL:
|
|
bn = new BN((bn1.cmp(bn2) <= 0) + 0);
|
|
break;
|
|
// case Opcode.OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break;
|
|
case Opcode.OP_GREATERTHANOREQUAL:
|
|
bn = new BN((bn1.cmp(bn2) >= 0) + 0);
|
|
break;
|
|
case Opcode.OP_MIN:
|
|
bn = (bn1.cmp(bn2) < 0 ? bn1 : bn2);
|
|
break;
|
|
case Opcode.OP_MAX:
|
|
bn = (bn1.cmp(bn2) > 0 ? bn1 : bn2);
|
|
break;
|
|
// default: assert(!'invalid opcode'); break; //TODO: does this ever occur?
|
|
}
|
|
this.stack.pop();
|
|
this.stack.pop();
|
|
this.stack.push(bn.toScriptNumBuffer());
|
|
|
|
if (opcodenum === Opcode.OP_NUMEQUALVERIFY) {
|
|
// if (CastToBool(stacktop(-1)))
|
|
if (Interpreter.castToBool(this.stack[this.stack.length - 1])) {
|
|
this.stack.pop();
|
|
} else {
|
|
this.errstr = 'SCRIPT_ERR_NUMEQUALVERIFY';
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_WITHIN:
|
|
{
|
|
// (x min max -- out)
|
|
if (this.stack.length < 3) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
bn1 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 3], fRequireMinimal);
|
|
bn2 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
|
|
var bn3 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
|
|
//bool fValue = (bn2 <= bn1 && bn1 < bn3);
|
|
fValue = (bn2.cmp(bn1) <= 0) && (bn1.cmp(bn3) < 0);
|
|
this.stack.pop();
|
|
this.stack.pop();
|
|
this.stack.pop();
|
|
this.stack.push(fValue ? Interpreter.true : Interpreter.false);
|
|
}
|
|
break;
|
|
|
|
|
|
//
|
|
// Crypto
|
|
//
|
|
case Opcode.OP_RIPEMD160:
|
|
case Opcode.OP_SHA1:
|
|
case Opcode.OP_SHA256:
|
|
case Opcode.OP_HASH160:
|
|
case Opcode.OP_HASH256:
|
|
{
|
|
// (in -- hash)
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
buf = this.stack[this.stack.length - 1];
|
|
//valtype vchHash((opcode == Opcode.OP_RIPEMD160 ||
|
|
// opcode == Opcode.OP_SHA1 || opcode == Opcode.OP_HASH160) ? 20 : 32);
|
|
var bufHash;
|
|
if (opcodenum === Opcode.OP_RIPEMD160) {
|
|
bufHash = Hash.ripemd160(buf);
|
|
} else if (opcodenum === Opcode.OP_SHA1) {
|
|
bufHash = Hash.sha1(buf);
|
|
} else if (opcodenum === Opcode.OP_SHA256) {
|
|
bufHash = Hash.sha256(buf);
|
|
} else if (opcodenum === Opcode.OP_HASH160) {
|
|
bufHash = Hash.sha256ripemd160(buf);
|
|
} else if (opcodenum === Opcode.OP_HASH256) {
|
|
bufHash = Hash.sha256sha256(buf);
|
|
}
|
|
this.stack.pop();
|
|
this.stack.push(bufHash);
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_CODESEPARATOR:
|
|
{
|
|
// Hash starts after the code separator
|
|
this.pbegincodehash = this.pc;
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_CHECKSIG:
|
|
case Opcode.OP_CHECKSIGVERIFY:
|
|
{
|
|
// (sig pubkey -- bool)
|
|
if (this.stack.length < 2) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
|
|
bufSig = this.stack[this.stack.length - 2];
|
|
bufPubkey = this.stack[this.stack.length - 1];
|
|
|
|
// Subset of script starting at the most recent codeseparator
|
|
// CScript scriptCode(pbegincodehash, pend);
|
|
subscript = new Script().set({
|
|
chunks: this.script.chunks.slice(this.pbegincodehash)
|
|
});
|
|
|
|
// Drop the signature, since there's no way for a signature to sign itself
|
|
var tmpScript = new Script().add(bufSig);
|
|
subscript.findAndDelete(tmpScript);
|
|
|
|
if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
sig = Signature.fromTxFormat(bufSig);
|
|
pubkey = PublicKey.fromBuffer(bufPubkey, false);
|
|
fSuccess = this.tx.verifySignature(sig, pubkey, this.nin, subscript);
|
|
} catch (e) {
|
|
//invalid sig or pubkey
|
|
fSuccess = false;
|
|
}
|
|
|
|
this.stack.pop();
|
|
this.stack.pop();
|
|
// stack.push_back(fSuccess ? vchTrue : vchFalse);
|
|
this.stack.push(fSuccess ? Interpreter.true : Interpreter.false);
|
|
if (opcodenum === Opcode.OP_CHECKSIGVERIFY) {
|
|
if (fSuccess) {
|
|
this.stack.pop();
|
|
} else {
|
|
this.errstr = 'SCRIPT_ERR_CHECKSIGVERIFY';
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Opcode.OP_CHECKMULTISIG:
|
|
case Opcode.OP_CHECKMULTISIGVERIFY:
|
|
{
|
|
// ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
|
|
|
|
var i = 1;
|
|
if (this.stack.length < i) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
|
|
var nKeysCount = BN.fromScriptNumBuffer(this.stack[this.stack.length - i], fRequireMinimal).toNumber();
|
|
if (nKeysCount < 0 || nKeysCount > 20) {
|
|
this.errstr = 'SCRIPT_ERR_PUBKEY_COUNT';
|
|
return false;
|
|
}
|
|
this.nOpCount += nKeysCount;
|
|
if (this.nOpCount > 201) {
|
|
this.errstr = 'SCRIPT_ERR_OP_COUNT';
|
|
return false;
|
|
}
|
|
// int ikey = ++i;
|
|
var ikey = ++i;
|
|
i += nKeysCount;
|
|
if (this.stack.length < i) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
|
|
var nSigsCount = BN.fromScriptNumBuffer(this.stack[this.stack.length - i], fRequireMinimal).toNumber();
|
|
if (nSigsCount < 0 || nSigsCount > nKeysCount) {
|
|
this.errstr = 'SCRIPT_ERR_SIG_COUNT';
|
|
return false;
|
|
}
|
|
// int isig = ++i;
|
|
var isig = ++i;
|
|
i += nSigsCount;
|
|
if (this.stack.length < i) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
|
|
// Subset of script starting at the most recent codeseparator
|
|
subscript = new Script().set({
|
|
chunks: this.script.chunks.slice(this.pbegincodehash)
|
|
});
|
|
|
|
// Drop the signatures, since there's no way for a signature to sign itself
|
|
for (var k = 0; k < nSigsCount; k++) {
|
|
bufSig = this.stack[this.stack.length - isig - k];
|
|
subscript.findAndDelete(new Script().add(bufSig));
|
|
}
|
|
|
|
fSuccess = true;
|
|
while (fSuccess && nSigsCount > 0) {
|
|
// valtype& vchSig = stacktop(-isig);
|
|
bufSig = this.stack[this.stack.length - isig];
|
|
// valtype& vchPubKey = stacktop(-ikey);
|
|
bufPubkey = this.stack[this.stack.length - ikey];
|
|
|
|
if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) {
|
|
return false;
|
|
}
|
|
|
|
var fOk;
|
|
try {
|
|
sig = Signature.fromTxFormat(bufSig);
|
|
pubkey = PublicKey.fromBuffer(bufPubkey, false);
|
|
fOk = this.tx.verifySignature(sig, pubkey, this.nin, subscript);
|
|
} catch (e) {
|
|
//invalid sig or pubkey
|
|
fOk = false;
|
|
}
|
|
|
|
if (fOk) {
|
|
isig++;
|
|
nSigsCount--;
|
|
}
|
|
ikey++;
|
|
nKeysCount--;
|
|
|
|
// If there are more signatures left than keys left,
|
|
// then too many signatures have failed
|
|
if (nSigsCount > nKeysCount) {
|
|
fSuccess = false;
|
|
}
|
|
}
|
|
|
|
// Clean up stack of actual arguments
|
|
while (i-- > 1) {
|
|
this.stack.pop();
|
|
}
|
|
|
|
// A bug causes CHECKMULTISIG to consume one extra argument
|
|
// whose contents were not checked in any way.
|
|
//
|
|
// Unfortunately this is a potential source of mutability,
|
|
// so optionally verify it is exactly equal to zero prior
|
|
// to removing it from the stack.
|
|
if (this.stack.length < 1) {
|
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
|
|
return false;
|
|
}
|
|
if ((this.flags & Interpreter.SCRIPT_VERIFY_NULLDUMMY) && this.stack[this.stack.length - 1].length) {
|
|
this.errstr = 'SCRIPT_ERR_SIG_NULLDUMMY';
|
|
return false;
|
|
}
|
|
this.stack.pop();
|
|
|
|
this.stack.push(fSuccess ? Interpreter.true : Interpreter.false);
|
|
|
|
if (opcodenum === Opcode.OP_CHECKMULTISIGVERIFY) {
|
|
if (fSuccess) {
|
|
this.stack.pop();
|
|
} else {
|
|
this.errstr = 'SCRIPT_ERR_CHECKMULTISIGVERIFY';
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
this.errstr = 'SCRIPT_ERR_BAD_OPCODE';
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../crypto/bn":6,"../crypto/hash":8,"../crypto/signature":11,"../opcode":22,"../publickey":24,"../transaction":28,"./script":27,"buffer":47,"lodash":319}],27:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var Address = require('../address');
|
|
var BufferReader = require('../encoding/bufferreader');
|
|
var BufferWriter = require('../encoding/bufferwriter');
|
|
var Hash = require('../crypto/hash');
|
|
var Opcode = require('../opcode');
|
|
var PublicKey = require('../publickey');
|
|
var Signature = require('../crypto/signature');
|
|
var Networks = require('../networks');
|
|
var $ = require('../util/preconditions');
|
|
var _ = require('lodash');
|
|
var errors = require('../errors');
|
|
var buffer = require('buffer');
|
|
var BufferUtil = require('../util/buffer');
|
|
var JSUtil = require('../util/js');
|
|
|
|
/**
|
|
* A bitcoin transaction script. Each transaction's inputs and outputs
|
|
* has a script that is evaluated to validate it's spending.
|
|
*
|
|
* See https://en.bitcoin.it/wiki/Script
|
|
*
|
|
* @constructor
|
|
* @param {Object|string|Buffer=} from optional data to populate script
|
|
*/
|
|
var Script = function Script(from) {
|
|
if (!(this instanceof Script)) {
|
|
return new Script(from);
|
|
}
|
|
this.chunks = [];
|
|
|
|
if (BufferUtil.isBuffer(from)) {
|
|
return Script.fromBuffer(from);
|
|
} else if (from instanceof Address) {
|
|
return Script.fromAddress(from);
|
|
} else if (from instanceof Script) {
|
|
return Script.fromBuffer(from.toBuffer());
|
|
} else if (_.isString(from)) {
|
|
return Script.fromString(from);
|
|
} else if (_.isObject(from) && _.isArray(from.chunks)) {
|
|
this.set(from);
|
|
}
|
|
};
|
|
|
|
Script.prototype.set = function(obj) {
|
|
$.checkArgument(_.isObject(obj));
|
|
$.checkArgument(_.isArray(obj.chunks));
|
|
this.chunks = obj.chunks;
|
|
return this;
|
|
};
|
|
|
|
Script.fromBuffer = function(buffer) {
|
|
var script = new Script();
|
|
script.chunks = [];
|
|
|
|
var br = new BufferReader(buffer);
|
|
while (!br.finished()) {
|
|
try {
|
|
var opcodenum = br.readUInt8();
|
|
|
|
var len, buf;
|
|
if (opcodenum > 0 && opcodenum < Opcode.OP_PUSHDATA1) {
|
|
len = opcodenum;
|
|
script.chunks.push({
|
|
buf: br.read(len),
|
|
len: len,
|
|
opcodenum: opcodenum
|
|
});
|
|
} else if (opcodenum === Opcode.OP_PUSHDATA1) {
|
|
len = br.readUInt8();
|
|
buf = br.read(len);
|
|
script.chunks.push({
|
|
buf: buf,
|
|
len: len,
|
|
opcodenum: opcodenum
|
|
});
|
|
} else if (opcodenum === Opcode.OP_PUSHDATA2) {
|
|
len = br.readUInt16LE();
|
|
buf = br.read(len);
|
|
script.chunks.push({
|
|
buf: buf,
|
|
len: len,
|
|
opcodenum: opcodenum
|
|
});
|
|
} else if (opcodenum === Opcode.OP_PUSHDATA4) {
|
|
len = br.readUInt32LE();
|
|
buf = br.read(len);
|
|
script.chunks.push({
|
|
buf: buf,
|
|
len: len,
|
|
opcodenum: opcodenum
|
|
});
|
|
} else {
|
|
script.chunks.push({
|
|
opcodenum: opcodenum
|
|
});
|
|
}
|
|
} catch (e) {
|
|
if (e instanceof RangeError) {
|
|
throw new errors.Script.InvalidBuffer(buffer.toString('hex'));
|
|
}
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
return script;
|
|
};
|
|
|
|
Script.prototype.toBuffer = function() {
|
|
var bw = new BufferWriter();
|
|
|
|
for (var i = 0; i < this.chunks.length; i++) {
|
|
var chunk = this.chunks[i];
|
|
var opcodenum = chunk.opcodenum;
|
|
bw.writeUInt8(chunk.opcodenum);
|
|
if (chunk.buf) {
|
|
if (opcodenum < Opcode.OP_PUSHDATA1) {
|
|
bw.write(chunk.buf);
|
|
} else if (opcodenum === Opcode.OP_PUSHDATA1) {
|
|
bw.writeUInt8(chunk.len);
|
|
bw.write(chunk.buf);
|
|
} else if (opcodenum === Opcode.OP_PUSHDATA2) {
|
|
bw.writeUInt16LE(chunk.len);
|
|
bw.write(chunk.buf);
|
|
} else if (opcodenum === Opcode.OP_PUSHDATA4) {
|
|
bw.writeUInt32LE(chunk.len);
|
|
bw.write(chunk.buf);
|
|
}
|
|
}
|
|
}
|
|
|
|
return bw.concat();
|
|
};
|
|
|
|
Script.fromASM = function(str) {
|
|
var script = new Script();
|
|
script.chunks = [];
|
|
|
|
var tokens = str.split(' ');
|
|
var i = 0;
|
|
while (i < tokens.length) {
|
|
var token = tokens[i];
|
|
var opcode = Opcode(token);
|
|
var opcodenum = opcode.toNumber();
|
|
|
|
if (_.isUndefined(opcodenum)) {
|
|
var buf = new Buffer(tokens[i], 'hex');
|
|
script.chunks.push({
|
|
buf: buf,
|
|
len: buf.length,
|
|
opcodenum: buf.length
|
|
});
|
|
i = i + 1;
|
|
} else if (opcodenum === Opcode.OP_PUSHDATA1 ||
|
|
opcodenum === Opcode.OP_PUSHDATA2 ||
|
|
opcodenum === Opcode.OP_PUSHDATA4) {
|
|
script.chunks.push({
|
|
buf: new Buffer(tokens[i + 2], 'hex'),
|
|
len: parseInt(tokens[i + 1]),
|
|
opcodenum: opcodenum
|
|
});
|
|
i = i + 3;
|
|
} else {
|
|
script.chunks.push({
|
|
opcodenum: opcodenum
|
|
});
|
|
i = i + 1;
|
|
}
|
|
}
|
|
return script;
|
|
};
|
|
|
|
Script.fromHex = function(str) {
|
|
return new Script(new buffer.Buffer(str, 'hex'));
|
|
};
|
|
|
|
Script.fromString = function(str) {
|
|
if (JSUtil.isHexa(str) || str.length === 0) {
|
|
return new Script(new buffer.Buffer(str, 'hex'));
|
|
}
|
|
var script = new Script();
|
|
script.chunks = [];
|
|
|
|
var tokens = str.split(' ');
|
|
var i = 0;
|
|
while (i < tokens.length) {
|
|
var token = tokens[i];
|
|
var opcode = Opcode(token);
|
|
var opcodenum = opcode.toNumber();
|
|
|
|
if (_.isUndefined(opcodenum)) {
|
|
opcodenum = parseInt(token);
|
|
if (opcodenum > 0 && opcodenum < Opcode.OP_PUSHDATA1) {
|
|
script.chunks.push({
|
|
buf: new Buffer(tokens[i + 1].slice(2), 'hex'),
|
|
len: opcodenum,
|
|
opcodenum: opcodenum
|
|
});
|
|
i = i + 2;
|
|
} else {
|
|
throw new Error('Invalid script: ' + JSON.stringify(str));
|
|
}
|
|
} else if (opcodenum === Opcode.OP_PUSHDATA1 ||
|
|
opcodenum === Opcode.OP_PUSHDATA2 ||
|
|
opcodenum === Opcode.OP_PUSHDATA4) {
|
|
if (tokens[i + 2].slice(0, 2) !== '0x') {
|
|
throw new Error('Pushdata data must start with 0x');
|
|
}
|
|
script.chunks.push({
|
|
buf: new Buffer(tokens[i + 2].slice(2), 'hex'),
|
|
len: parseInt(tokens[i + 1]),
|
|
opcodenum: opcodenum
|
|
});
|
|
i = i + 3;
|
|
} else {
|
|
script.chunks.push({
|
|
opcodenum: opcodenum
|
|
});
|
|
i = i + 1;
|
|
}
|
|
}
|
|
return script;
|
|
};
|
|
|
|
Script.prototype._chunkToString = function(chunk, type) {
|
|
var opcodenum = chunk.opcodenum;
|
|
var asm = (type === 'asm');
|
|
var str = '';
|
|
if (!chunk.buf) {
|
|
// no data chunk
|
|
if (typeof Opcode.reverseMap[opcodenum] !== 'undefined') {
|
|
if (asm) {
|
|
// A few cases where the opcode name differs from reverseMap
|
|
// aside from 1 to 16 data pushes.
|
|
if (opcodenum === 0) {
|
|
// OP_0 -> 0
|
|
str = str + ' 0';
|
|
} else if(opcodenum === 79) {
|
|
// OP_1NEGATE -> 1
|
|
str = str + ' -1';
|
|
} else {
|
|
str = str + ' ' + Opcode(opcodenum).toString();
|
|
}
|
|
} else {
|
|
str = str + ' ' + Opcode(opcodenum).toString();
|
|
}
|
|
} else {
|
|
var numstr = opcodenum.toString(16);
|
|
if (numstr.length % 2 !== 0) {
|
|
numstr = '0' + numstr;
|
|
}
|
|
if (asm) {
|
|
str = str + ' ' + numstr;
|
|
} else {
|
|
str = str + ' ' + '0x' + numstr;
|
|
}
|
|
}
|
|
} else {
|
|
// data chunk
|
|
if (!asm && opcodenum === Opcode.OP_PUSHDATA1 ||
|
|
opcodenum === Opcode.OP_PUSHDATA2 ||
|
|
opcodenum === Opcode.OP_PUSHDATA4) {
|
|
str = str + ' ' + Opcode(opcodenum).toString();
|
|
}
|
|
if (chunk.len > 0) {
|
|
if (asm) {
|
|
str = str + ' ' + chunk.buf.toString('hex');
|
|
} else {
|
|
str = str + ' ' + chunk.len + ' ' + '0x' + chunk.buf.toString('hex');
|
|
}
|
|
}
|
|
}
|
|
return str;
|
|
};
|
|
|
|
Script.prototype.toASM = function() {
|
|
var str = '';
|
|
for (var i = 0; i < this.chunks.length; i++) {
|
|
var chunk = this.chunks[i];
|
|
str += this._chunkToString(chunk, 'asm');
|
|
}
|
|
|
|
return str.substr(1);
|
|
};
|
|
|
|
Script.prototype.toString = function() {
|
|
var str = '';
|
|
for (var i = 0; i < this.chunks.length; i++) {
|
|
var chunk = this.chunks[i];
|
|
str += this._chunkToString(chunk);
|
|
}
|
|
|
|
return str.substr(1);
|
|
};
|
|
|
|
Script.prototype.toHex = function() {
|
|
return this.toBuffer().toString('hex');
|
|
};
|
|
|
|
Script.prototype.inspect = function() {
|
|
return '<Script: ' + this.toString() + '>';
|
|
};
|
|
|
|
// script classification methods
|
|
|
|
/**
|
|
* @returns {boolean} if this is a pay to pubkey hash output script
|
|
*/
|
|
Script.prototype.isPublicKeyHashOut = function() {
|
|
return !!(this.chunks.length === 5 &&
|
|
this.chunks[0].opcodenum === Opcode.OP_DUP &&
|
|
this.chunks[1].opcodenum === Opcode.OP_HASH160 &&
|
|
this.chunks[2].buf &&
|
|
this.chunks[2].buf.length === 20 &&
|
|
this.chunks[3].opcodenum === Opcode.OP_EQUALVERIFY &&
|
|
this.chunks[4].opcodenum === Opcode.OP_CHECKSIG);
|
|
};
|
|
|
|
/**
|
|
* @returns {boolean} if this is a pay to public key hash input script
|
|
*/
|
|
Script.prototype.isPublicKeyHashIn = function() {
|
|
if (this.chunks.length === 2) {
|
|
var signatureBuf = this.chunks[0].buf;
|
|
var pubkeyBuf = this.chunks[1].buf;
|
|
if (signatureBuf &&
|
|
signatureBuf.length &&
|
|
signatureBuf[0] === 0x30 &&
|
|
pubkeyBuf &&
|
|
pubkeyBuf.length
|
|
) {
|
|
var version = pubkeyBuf[0];
|
|
if ((version === 0x04 ||
|
|
version === 0x06 ||
|
|
version === 0x07) && pubkeyBuf.length === 65) {
|
|
return true;
|
|
} else if ((version === 0x03 || version === 0x02) && pubkeyBuf.length === 33) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
Script.prototype.getPublicKey = function() {
|
|
$.checkState(this.isPublicKeyOut(), 'Can\'t retrieve PublicKey from a non-PK output');
|
|
return this.chunks[0].buf;
|
|
};
|
|
|
|
Script.prototype.getPublicKeyHash = function() {
|
|
$.checkState(this.isPublicKeyHashOut(), 'Can\'t retrieve PublicKeyHash from a non-PKH output');
|
|
return this.chunks[2].buf;
|
|
};
|
|
|
|
/**
|
|
* @returns {boolean} if this is a public key output script
|
|
*/
|
|
Script.prototype.isPublicKeyOut = function() {
|
|
if (this.chunks.length === 2 &&
|
|
this.chunks[0].buf &&
|
|
this.chunks[0].buf.length &&
|
|
this.chunks[1].opcodenum === Opcode.OP_CHECKSIG) {
|
|
var pubkeyBuf = this.chunks[0].buf;
|
|
var version = pubkeyBuf[0];
|
|
var isVersion = false;
|
|
if ((version === 0x04 ||
|
|
version === 0x06 ||
|
|
version === 0x07) && pubkeyBuf.length === 65) {
|
|
isVersion = true;
|
|
} else if ((version === 0x03 || version === 0x02) && pubkeyBuf.length === 33) {
|
|
isVersion = true;
|
|
}
|
|
if (isVersion) {
|
|
return PublicKey.isValid(pubkeyBuf);
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* @returns {boolean} if this is a pay to public key input script
|
|
*/
|
|
Script.prototype.isPublicKeyIn = function() {
|
|
if (this.chunks.length === 1) {
|
|
var signatureBuf = this.chunks[0].buf;
|
|
if (signatureBuf &&
|
|
signatureBuf.length &&
|
|
signatureBuf[0] === 0x30) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* @returns {boolean} if this is a p2sh output script
|
|
*/
|
|
Script.prototype.isScriptHashOut = function() {
|
|
var buf = this.toBuffer();
|
|
return (buf.length === 23 &&
|
|
buf[0] === Opcode.OP_HASH160 &&
|
|
buf[1] === 0x14 &&
|
|
buf[buf.length - 1] === Opcode.OP_EQUAL);
|
|
};
|
|
|
|
/**
|
|
* @returns {boolean} if this is a p2sh input script
|
|
* Note that these are frequently indistinguishable from pubkeyhashin
|
|
*/
|
|
Script.prototype.isScriptHashIn = function() {
|
|
if (this.chunks.length <= 1) {
|
|
return false;
|
|
}
|
|
var redeemChunk = this.chunks[this.chunks.length - 1];
|
|
var redeemBuf = redeemChunk.buf;
|
|
if (!redeemBuf) {
|
|
return false;
|
|
}
|
|
|
|
var redeemScript;
|
|
try {
|
|
redeemScript = Script.fromBuffer(redeemBuf);
|
|
} catch (e) {
|
|
if (e instanceof errors.Script.InvalidBuffer) {
|
|
return false;
|
|
}
|
|
throw e;
|
|
}
|
|
var type = redeemScript.classify();
|
|
return type !== Script.types.UNKNOWN;
|
|
};
|
|
|
|
/**
|
|
* @returns {boolean} if this is a mutlsig output script
|
|
*/
|
|
Script.prototype.isMultisigOut = function() {
|
|
return (this.chunks.length > 3 &&
|
|
Opcode.isSmallIntOp(this.chunks[0].opcodenum) &&
|
|
this.chunks.slice(1, this.chunks.length - 2).every(function(obj) {
|
|
return obj.buf && BufferUtil.isBuffer(obj.buf);
|
|
}) &&
|
|
Opcode.isSmallIntOp(this.chunks[this.chunks.length - 2].opcodenum) &&
|
|
this.chunks[this.chunks.length - 1].opcodenum === Opcode.OP_CHECKMULTISIG);
|
|
};
|
|
|
|
|
|
/**
|
|
* @returns {boolean} if this is a multisig input script
|
|
*/
|
|
Script.prototype.isMultisigIn = function() {
|
|
return this.chunks.length >= 2 &&
|
|
this.chunks[0].opcodenum === 0 &&
|
|
this.chunks.slice(1, this.chunks.length).every(function(obj) {
|
|
return obj.buf &&
|
|
BufferUtil.isBuffer(obj.buf) &&
|
|
Signature.isTxDER(obj.buf);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* @returns {boolean} true if this is a valid standard OP_RETURN output
|
|
*/
|
|
Script.prototype.isDataOut = function() {
|
|
return this.chunks.length >= 1 &&
|
|
this.chunks[0].opcodenum === Opcode.OP_RETURN &&
|
|
(this.chunks.length === 1 ||
|
|
(this.chunks.length === 2 &&
|
|
this.chunks[1].buf &&
|
|
this.chunks[1].buf.length <= Script.OP_RETURN_STANDARD_SIZE &&
|
|
this.chunks[1].length === this.chunks.len));
|
|
};
|
|
|
|
/**
|
|
* Retrieve the associated data for this script.
|
|
* In the case of a pay to public key hash or P2SH, return the hash.
|
|
* In the case of a standard OP_RETURN, return the data
|
|
* @returns {Buffer}
|
|
*/
|
|
Script.prototype.getData = function() {
|
|
if (this.isDataOut() || this.isScriptHashOut()) {
|
|
if (_.isUndefined(this.chunks[1])) {
|
|
return new Buffer(0);
|
|
} else {
|
|
return new Buffer(this.chunks[1].buf);
|
|
}
|
|
}
|
|
if (this.isPublicKeyHashOut()) {
|
|
return new Buffer(this.chunks[2].buf);
|
|
}
|
|
throw new Error('Unrecognized script type to get data from');
|
|
};
|
|
|
|
/**
|
|
* @returns {boolean} if the script is only composed of data pushing
|
|
* opcodes or small int opcodes (OP_0, OP_1, ..., OP_16)
|
|
*/
|
|
Script.prototype.isPushOnly = function() {
|
|
return _.every(this.chunks, function(chunk) {
|
|
return chunk.opcodenum <= Opcode.OP_16;
|
|
});
|
|
};
|
|
|
|
|
|
Script.types = {};
|
|
Script.types.UNKNOWN = 'Unknown';
|
|
Script.types.PUBKEY_OUT = 'Pay to public key';
|
|
Script.types.PUBKEY_IN = 'Spend from public key';
|
|
Script.types.PUBKEYHASH_OUT = 'Pay to public key hash';
|
|
Script.types.PUBKEYHASH_IN = 'Spend from public key hash';
|
|
Script.types.SCRIPTHASH_OUT = 'Pay to script hash';
|
|
Script.types.SCRIPTHASH_IN = 'Spend from script hash';
|
|
Script.types.MULTISIG_OUT = 'Pay to multisig';
|
|
Script.types.MULTISIG_IN = 'Spend from multisig';
|
|
Script.types.DATA_OUT = 'Data push';
|
|
|
|
Script.OP_RETURN_STANDARD_SIZE = 80;
|
|
|
|
/**
|
|
* @returns {object} The Script type if it is a known form,
|
|
* or Script.UNKNOWN if it isn't
|
|
*/
|
|
Script.prototype.classify = function() {
|
|
if (this._isInput) {
|
|
return this.classifyInput();
|
|
} else if (this._isOutput) {
|
|
return this.classifyOutput();
|
|
} else {
|
|
var outputType = this.classifyOutput();
|
|
return outputType != Script.types.UNKNOWN ? outputType : this.classifyInput();
|
|
}
|
|
};
|
|
|
|
Script.outputIdentifiers = {};
|
|
Script.outputIdentifiers.PUBKEY_OUT = Script.prototype.isPublicKeyOut;
|
|
Script.outputIdentifiers.PUBKEYHASH_OUT = Script.prototype.isPublicKeyHashOut;
|
|
Script.outputIdentifiers.MULTISIG_OUT = Script.prototype.isMultisigOut;
|
|
Script.outputIdentifiers.SCRIPTHASH_OUT = Script.prototype.isScriptHashOut;
|
|
Script.outputIdentifiers.DATA_OUT = Script.prototype.isDataOut;
|
|
|
|
/**
|
|
* @returns {object} The Script type if it is a known form,
|
|
* or Script.UNKNOWN if it isn't
|
|
*/
|
|
Script.prototype.classifyOutput = function() {
|
|
for (var type in Script.outputIdentifiers) {
|
|
if (Script.outputIdentifiers[type].bind(this)()) {
|
|
return Script.types[type];
|
|
}
|
|
}
|
|
return Script.types.UNKNOWN;
|
|
};
|
|
|
|
Script.inputIdentifiers = {};
|
|
Script.inputIdentifiers.PUBKEY_IN = Script.prototype.isPublicKeyIn;
|
|
Script.inputIdentifiers.PUBKEYHASH_IN = Script.prototype.isPublicKeyHashIn;
|
|
Script.inputIdentifiers.MULTISIG_IN = Script.prototype.isMultisigIn;
|
|
Script.inputIdentifiers.SCRIPTHASH_IN = Script.prototype.isScriptHashIn;
|
|
|
|
/**
|
|
* @returns {object} The Script type if it is a known form,
|
|
* or Script.UNKNOWN if it isn't
|
|
*/
|
|
Script.prototype.classifyInput = function() {
|
|
for (var type in Script.inputIdentifiers) {
|
|
if (Script.inputIdentifiers[type].bind(this)()) {
|
|
return Script.types[type];
|
|
}
|
|
}
|
|
return Script.types.UNKNOWN;
|
|
};
|
|
|
|
|
|
/**
|
|
* @returns {boolean} if script is one of the known types
|
|
*/
|
|
Script.prototype.isStandard = function() {
|
|
// TODO: Add BIP62 compliance
|
|
return this.classify() !== Script.types.UNKNOWN;
|
|
};
|
|
|
|
|
|
// Script construction methods
|
|
|
|
/**
|
|
* Adds a script element at the start of the script.
|
|
* @param {*} obj a string, number, Opcode, Buffer, or object to add
|
|
* @returns {Script} this script instance
|
|
*/
|
|
Script.prototype.prepend = function(obj) {
|
|
this._addByType(obj, true);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Compares a script with another script
|
|
*/
|
|
Script.prototype.equals = function(script) {
|
|
$.checkState(script instanceof Script, 'Must provide another script');
|
|
if (this.chunks.length !== script.chunks.length) {
|
|
return false;
|
|
}
|
|
var i;
|
|
for (i = 0; i < this.chunks.length; i++) {
|
|
if (BufferUtil.isBuffer(this.chunks[i].buf) && !BufferUtil.isBuffer(script.chunks[i].buf)) {
|
|
return false;
|
|
}
|
|
if (BufferUtil.isBuffer(this.chunks[i].buf) && !BufferUtil.equals(this.chunks[i].buf, script.chunks[i].buf)) {
|
|
return false;
|
|
} else if (this.chunks[i].opcodenum !== script.chunks[i].opcodenum) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Adds a script element to the end of the script.
|
|
*
|
|
* @param {*} obj a string, number, Opcode, Buffer, or object to add
|
|
* @returns {Script} this script instance
|
|
*
|
|
*/
|
|
Script.prototype.add = function(obj) {
|
|
this._addByType(obj, false);
|
|
return this;
|
|
};
|
|
|
|
Script.prototype._addByType = function(obj, prepend) {
|
|
if (typeof obj === 'string') {
|
|
this._addOpcode(obj, prepend);
|
|
} else if (typeof obj === 'number') {
|
|
this._addOpcode(obj, prepend);
|
|
} else if (obj instanceof Opcode) {
|
|
this._addOpcode(obj, prepend);
|
|
} else if (BufferUtil.isBuffer(obj)) {
|
|
this._addBuffer(obj, prepend);
|
|
} else if (obj instanceof Script) {
|
|
this.chunks = this.chunks.concat(obj.chunks);
|
|
} else if (typeof obj === 'object') {
|
|
this._insertAtPosition(obj, prepend);
|
|
} else {
|
|
throw new Error('Invalid script chunk');
|
|
}
|
|
};
|
|
|
|
Script.prototype._insertAtPosition = function(op, prepend) {
|
|
if (prepend) {
|
|
this.chunks.unshift(op);
|
|
} else {
|
|
this.chunks.push(op);
|
|
}
|
|
};
|
|
|
|
Script.prototype._addOpcode = function(opcode, prepend) {
|
|
var op;
|
|
if (typeof opcode === 'number') {
|
|
op = opcode;
|
|
} else if (opcode instanceof Opcode) {
|
|
op = opcode.toNumber();
|
|
} else {
|
|
op = Opcode(opcode).toNumber();
|
|
}
|
|
this._insertAtPosition({
|
|
opcodenum: op
|
|
}, prepend);
|
|
return this;
|
|
};
|
|
|
|
Script.prototype._addBuffer = function(buf, prepend) {
|
|
var opcodenum;
|
|
var len = buf.length;
|
|
if (len >= 0 && len < Opcode.OP_PUSHDATA1) {
|
|
opcodenum = len;
|
|
} else if (len < Math.pow(2, 8)) {
|
|
opcodenum = Opcode.OP_PUSHDATA1;
|
|
} else if (len < Math.pow(2, 16)) {
|
|
opcodenum = Opcode.OP_PUSHDATA2;
|
|
} else if (len < Math.pow(2, 32)) {
|
|
opcodenum = Opcode.OP_PUSHDATA4;
|
|
} else {
|
|
throw new Error('You can\'t push that much data');
|
|
}
|
|
this._insertAtPosition({
|
|
buf: buf,
|
|
len: len,
|
|
opcodenum: opcodenum
|
|
}, prepend);
|
|
return this;
|
|
};
|
|
|
|
Script.prototype.removeCodeseparators = function() {
|
|
var chunks = [];
|
|
for (var i = 0; i < this.chunks.length; i++) {
|
|
if (this.chunks[i].opcodenum !== Opcode.OP_CODESEPARATOR) {
|
|
chunks.push(this.chunks[i]);
|
|
}
|
|
}
|
|
this.chunks = chunks;
|
|
return this;
|
|
};
|
|
|
|
// high level script builder methods
|
|
|
|
/**
|
|
* @returns {Script} a new Multisig output script for given public keys,
|
|
* requiring m of those public keys to spend
|
|
* @param {PublicKey[]} publicKeys - list of all public keys controlling the output
|
|
* @param {number} threshold - amount of required signatures to spend the output
|
|
* @param {Object=} opts - Several options:
|
|
* - noSorting: defaults to false, if true, don't sort the given
|
|
* public keys before creating the script
|
|
*/
|
|
Script.buildMultisigOut = function(publicKeys, threshold, opts) {
|
|
$.checkArgument(threshold <= publicKeys.length,
|
|
'Number of required signatures must be less than or equal to the number of public keys');
|
|
opts = opts || {};
|
|
var script = new Script();
|
|
script.add(Opcode.smallInt(threshold));
|
|
publicKeys = _.map(publicKeys, PublicKey);
|
|
var sorted = publicKeys;
|
|
if (!opts.noSorting) {
|
|
sorted = _.sortBy(publicKeys, function(publicKey) {
|
|
return publicKey.toString('hex');
|
|
});
|
|
}
|
|
for (var i = 0; i < sorted.length; i++) {
|
|
var publicKey = sorted[i];
|
|
script.add(publicKey.toBuffer());
|
|
}
|
|
script.add(Opcode.smallInt(publicKeys.length));
|
|
script.add(Opcode.OP_CHECKMULTISIG);
|
|
return script;
|
|
};
|
|
|
|
/**
|
|
* A new Multisig input script for the given public keys, requiring m of those public keys to spend
|
|
*
|
|
* @param {PublicKey[]} pubkeys list of all public keys controlling the output
|
|
* @param {number} threshold amount of required signatures to spend the output
|
|
* @param {Array} signatures and array of signature buffers to append to the script
|
|
* @param {Object=} opts
|
|
* @param {boolean=} opts.noSorting don't sort the given public keys before creating the script (false by default)
|
|
* @param {Script=} opts.cachedMultisig don't recalculate the redeemScript
|
|
*
|
|
* @returns {Script}
|
|
*/
|
|
Script.buildMultisigIn = function(pubkeys, threshold, signatures, opts) {
|
|
$.checkArgument(_.isArray(pubkeys));
|
|
$.checkArgument(_.isNumber(threshold));
|
|
$.checkArgument(_.isArray(signatures));
|
|
opts = opts || {};
|
|
var s = new Script();
|
|
s.add(Opcode.OP_0);
|
|
_.each(signatures, function(signature) {
|
|
$.checkArgument(BufferUtil.isBuffer(signature), 'Signatures must be an array of Buffers');
|
|
// TODO: allow signatures to be an array of Signature objects
|
|
s.add(signature);
|
|
});
|
|
return s;
|
|
};
|
|
|
|
/**
|
|
* A new P2SH Multisig input script for the given public keys, requiring m of those public keys to spend
|
|
*
|
|
* @param {PublicKey[]} pubkeys list of all public keys controlling the output
|
|
* @param {number} threshold amount of required signatures to spend the output
|
|
* @param {Array} signatures and array of signature buffers to append to the script
|
|
* @param {Object=} opts
|
|
* @param {boolean=} opts.noSorting don't sort the given public keys before creating the script (false by default)
|
|
* @param {Script=} opts.cachedMultisig don't recalculate the redeemScript
|
|
*
|
|
* @returns {Script}
|
|
*/
|
|
Script.buildP2SHMultisigIn = function(pubkeys, threshold, signatures, opts) {
|
|
$.checkArgument(_.isArray(pubkeys));
|
|
$.checkArgument(_.isNumber(threshold));
|
|
$.checkArgument(_.isArray(signatures));
|
|
opts = opts || {};
|
|
var s = new Script();
|
|
s.add(Opcode.OP_0);
|
|
_.each(signatures, function(signature) {
|
|
$.checkArgument(BufferUtil.isBuffer(signature), 'Signatures must be an array of Buffers');
|
|
// TODO: allow signatures to be an array of Signature objects
|
|
s.add(signature);
|
|
});
|
|
s.add((opts.cachedMultisig || Script.buildMultisigOut(pubkeys, threshold, opts)).toBuffer());
|
|
return s;
|
|
};
|
|
|
|
/**
|
|
* @returns {Script} a new pay to public key hash output for the given
|
|
* address or public key
|
|
* @param {(Address|PublicKey)} to - destination address or public key
|
|
*/
|
|
Script.buildPublicKeyHashOut = function(to) {
|
|
$.checkArgument(!_.isUndefined(to));
|
|
$.checkArgument(to instanceof PublicKey || to instanceof Address || _.isString(to));
|
|
if (to instanceof PublicKey) {
|
|
to = to.toAddress();
|
|
} else if (_.isString(to)) {
|
|
to = new Address(to);
|
|
}
|
|
var s = new Script();
|
|
s.add(Opcode.OP_DUP)
|
|
.add(Opcode.OP_HASH160)
|
|
.add(to.hashBuffer)
|
|
.add(Opcode.OP_EQUALVERIFY)
|
|
.add(Opcode.OP_CHECKSIG);
|
|
s._network = to.network;
|
|
return s;
|
|
};
|
|
|
|
/**
|
|
* @returns {Script} a new pay to public key output for the given
|
|
* public key
|
|
*/
|
|
Script.buildPublicKeyOut = function(pubkey) {
|
|
$.checkArgument(pubkey instanceof PublicKey);
|
|
var s = new Script();
|
|
s.add(pubkey.toBuffer())
|
|
.add(Opcode.OP_CHECKSIG);
|
|
return s;
|
|
};
|
|
|
|
/**
|
|
* @returns {Script} a new OP_RETURN script with data
|
|
* @param {(string|Buffer)} data - the data to embed in the output
|
|
* @param {(string)} encoding - the type of encoding of the string
|
|
*/
|
|
Script.buildDataOut = function(data, encoding) {
|
|
$.checkArgument(_.isUndefined(data) || _.isString(data) || BufferUtil.isBuffer(data));
|
|
if (_.isString(data)) {
|
|
data = new Buffer(data, encoding);
|
|
}
|
|
var s = new Script();
|
|
s.add(Opcode.OP_RETURN);
|
|
if (!_.isUndefined(data)) {
|
|
s.add(data);
|
|
}
|
|
return s;
|
|
};
|
|
|
|
/**
|
|
* @param {Script|Address} script - the redeemScript for the new p2sh output.
|
|
* It can also be a p2sh address
|
|
* @returns {Script} new pay to script hash script for given script
|
|
*/
|
|
Script.buildScriptHashOut = function(script) {
|
|
$.checkArgument(script instanceof Script ||
|
|
(script instanceof Address && script.isPayToScriptHash()));
|
|
var s = new Script();
|
|
s.add(Opcode.OP_HASH160)
|
|
.add(script instanceof Address ? script.hashBuffer : Hash.sha256ripemd160(script.toBuffer()))
|
|
.add(Opcode.OP_EQUAL);
|
|
|
|
s._network = script._network || script.network;
|
|
return s;
|
|
};
|
|
|
|
/**
|
|
* Builds a scriptSig (a script for an input) that signs a public key output script.
|
|
*
|
|
* @param {Signature|Buffer} signature - a Signature object, or the signature in DER canonical encoding
|
|
* @param {number=} sigtype - the type of the signature (defaults to SIGHASH_ALL)
|
|
*/
|
|
Script.buildPublicKeyIn = function(signature, sigtype) {
|
|
$.checkArgument(signature instanceof Signature || BufferUtil.isBuffer(signature));
|
|
$.checkArgument(_.isUndefined(sigtype) || _.isNumber(sigtype));
|
|
if (signature instanceof Signature) {
|
|
signature = signature.toBuffer();
|
|
}
|
|
var script = new Script();
|
|
script.add(BufferUtil.concat([
|
|
signature,
|
|
BufferUtil.integerAsSingleByteBuffer(sigtype || Signature.SIGHASH_ALL)
|
|
]));
|
|
return script;
|
|
};
|
|
|
|
/**
|
|
* Builds a scriptSig (a script for an input) that signs a public key hash
|
|
* output script.
|
|
*
|
|
* @param {Buffer|string|PublicKey} publicKey
|
|
* @param {Signature|Buffer} signature - a Signature object, or the signature in DER canonical encoding
|
|
* @param {number=} sigtype - the type of the signature (defaults to SIGHASH_ALL)
|
|
*/
|
|
Script.buildPublicKeyHashIn = function(publicKey, signature, sigtype) {
|
|
$.checkArgument(signature instanceof Signature || BufferUtil.isBuffer(signature));
|
|
$.checkArgument(_.isUndefined(sigtype) || _.isNumber(sigtype));
|
|
if (signature instanceof Signature) {
|
|
signature = signature.toBuffer();
|
|
}
|
|
var script = new Script()
|
|
.add(BufferUtil.concat([
|
|
signature,
|
|
BufferUtil.integerAsSingleByteBuffer(sigtype || Signature.SIGHASH_ALL)
|
|
]))
|
|
.add(new PublicKey(publicKey).toBuffer());
|
|
return script;
|
|
};
|
|
|
|
/**
|
|
* @returns {Script} an empty script
|
|
*/
|
|
Script.empty = function() {
|
|
return new Script();
|
|
};
|
|
|
|
/**
|
|
* @returns {Script} a new pay to script hash script that pays to this script
|
|
*/
|
|
Script.prototype.toScriptHashOut = function() {
|
|
return Script.buildScriptHashOut(this);
|
|
};
|
|
|
|
/**
|
|
* @return {Script} an output script built from the address
|
|
*/
|
|
Script.fromAddress = function(address) {
|
|
address = Address(address);
|
|
if (address.isPayToScriptHash()) {
|
|
return Script.buildScriptHashOut(address);
|
|
} else if (address.isPayToPublicKeyHash()) {
|
|
return Script.buildPublicKeyHashOut(address);
|
|
}
|
|
throw new errors.Script.UnrecognizedAddress(address);
|
|
};
|
|
|
|
/**
|
|
* Will return the associated address information object
|
|
* @return {Address|boolean}
|
|
*/
|
|
Script.prototype.getAddressInfo = function(opts) {
|
|
if (this._isInput) {
|
|
return this._getInputAddressInfo();
|
|
} else if (this._isOutput) {
|
|
return this._getOutputAddressInfo();
|
|
} else {
|
|
var info = this._getOutputAddressInfo();
|
|
if (!info) {
|
|
return this._getInputAddressInfo();
|
|
}
|
|
return info;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Will return the associated output scriptPubKey address information object
|
|
* @return {Address|boolean}
|
|
* @private
|
|
*/
|
|
Script.prototype._getOutputAddressInfo = function() {
|
|
var info = {};
|
|
if (this.isScriptHashOut()) {
|
|
info.hashBuffer = this.getData();
|
|
info.type = Address.PayToScriptHash;
|
|
} else if (this.isPublicKeyHashOut()) {
|
|
info.hashBuffer = this.getData();
|
|
info.type = Address.PayToPublicKeyHash;
|
|
} else {
|
|
return false;
|
|
}
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* Will return the associated input scriptSig address information object
|
|
* @return {Address|boolean}
|
|
* @private
|
|
*/
|
|
Script.prototype._getInputAddressInfo = function() {
|
|
var info = {};
|
|
if (this.isPublicKeyHashIn()) {
|
|
// hash the publickey found in the scriptSig
|
|
info.hashBuffer = Hash.sha256ripemd160(this.chunks[1].buf);
|
|
info.type = Address.PayToPublicKeyHash;
|
|
} else if (this.isScriptHashIn()) {
|
|
// hash the redeemscript found at the end of the scriptSig
|
|
info.hashBuffer = Hash.sha256ripemd160(this.chunks[this.chunks.length - 1].buf);
|
|
info.type = Address.PayToScriptHash;
|
|
} else {
|
|
return false;
|
|
}
|
|
return info;
|
|
};
|
|
|
|
/**
|
|
* @param {Network=} network
|
|
* @return {Address|boolean} the associated address for this script if possible, or false
|
|
*/
|
|
Script.prototype.toAddress = function(network) {
|
|
var info = this.getAddressInfo();
|
|
if (!info) {
|
|
return false;
|
|
}
|
|
info.network = Networks.get(network) || this._network || Networks.defaultNetwork;
|
|
return new Address(info);
|
|
};
|
|
|
|
/**
|
|
* Analogous to bitcoind's FindAndDelete. Find and delete equivalent chunks,
|
|
* typically used with push data chunks. Note that this will find and delete
|
|
* not just the same data, but the same data with the same push data op as
|
|
* produced by default. i.e., if a pushdata in a tx does not use the minimal
|
|
* pushdata op, then when you try to remove the data it is pushing, it will not
|
|
* be removed, because they do not use the same pushdata op.
|
|
*/
|
|
Script.prototype.findAndDelete = function(script) {
|
|
var buf = script.toBuffer();
|
|
var hex = buf.toString('hex');
|
|
for (var i = 0; i < this.chunks.length; i++) {
|
|
var script2 = Script({
|
|
chunks: [this.chunks[i]]
|
|
});
|
|
var buf2 = script2.toBuffer();
|
|
var hex2 = buf2.toString('hex');
|
|
if (hex === hex2) {
|
|
this.chunks.splice(i, 1);
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Comes from bitcoind's script interpreter CheckMinimalPush function
|
|
* @returns {boolean} if the chunk {i} is the smallest way to push that particular data.
|
|
*/
|
|
Script.prototype.checkMinimalPush = function(i) {
|
|
var chunk = this.chunks[i];
|
|
var buf = chunk.buf;
|
|
var opcodenum = chunk.opcodenum;
|
|
if (!buf) {
|
|
return true;
|
|
}
|
|
if (buf.length === 0) {
|
|
// Could have used OP_0.
|
|
return opcodenum === Opcode.OP_0;
|
|
} else if (buf.length === 1 && buf[0] >= 1 && buf[0] <= 16) {
|
|
// Could have used OP_1 .. OP_16.
|
|
return opcodenum === Opcode.OP_1 + (buf[0] - 1);
|
|
} else if (buf.length === 1 && buf[0] === 0x81) {
|
|
// Could have used OP_1NEGATE
|
|
return opcodenum === Opcode.OP_1NEGATE;
|
|
} else if (buf.length <= 75) {
|
|
// Could have used a direct push (opcode indicating number of bytes pushed + those bytes).
|
|
return opcodenum === buf.length;
|
|
} else if (buf.length <= 255) {
|
|
// Could have used OP_PUSHDATA.
|
|
return opcodenum === Opcode.OP_PUSHDATA1;
|
|
} else if (buf.length <= 65535) {
|
|
// Could have used OP_PUSHDATA2.
|
|
return opcodenum === Opcode.OP_PUSHDATA2;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Comes from bitcoind's script DecodeOP_N function
|
|
* @param {number} opcode
|
|
* @returns {number} numeric value in range of 0 to 16
|
|
*/
|
|
Script.prototype._decodeOP_N = function(opcode) {
|
|
if (opcode === Opcode.OP_0) {
|
|
return 0;
|
|
} else if (opcode >= Opcode.OP_1 && opcode <= Opcode.OP_16) {
|
|
return opcode - (Opcode.OP_1 - 1);
|
|
} else {
|
|
throw new Error('Invalid opcode: ' + JSON.stringify(opcode));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Comes from bitcoind's script GetSigOpCount(boolean) function
|
|
* @param {boolean} use current (true) or pre-version-0.6 (false) logic
|
|
* @returns {number} number of signature operations required by this script
|
|
*/
|
|
Script.prototype.getSignatureOperationsCount = function(accurate) {
|
|
accurate = (_.isUndefined(accurate) ? true : accurate);
|
|
var self = this;
|
|
var n = 0;
|
|
var lastOpcode = Opcode.OP_INVALIDOPCODE;
|
|
_.each(self.chunks, function getChunk(chunk) {
|
|
var opcode = chunk.opcodenum;
|
|
if (opcode == Opcode.OP_CHECKSIG || opcode == Opcode.OP_CHECKSIGVERIFY) {
|
|
n++;
|
|
} else if (opcode == Opcode.OP_CHECKMULTISIG || opcode == Opcode.OP_CHECKMULTISIGVERIFY) {
|
|
if (accurate && lastOpcode >= Opcode.OP_1 && lastOpcode <= Opcode.OP_16) {
|
|
n += self._decodeOP_N(lastOpcode);
|
|
} else {
|
|
n += 20;
|
|
}
|
|
}
|
|
lastOpcode = opcode;
|
|
});
|
|
return n;
|
|
};
|
|
|
|
module.exports = Script;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../address":1,"../crypto/hash":8,"../crypto/signature":11,"../encoding/bufferreader":14,"../encoding/bufferwriter":15,"../errors":17,"../networks":21,"../opcode":22,"../publickey":24,"../util/buffer":42,"../util/js":43,"../util/preconditions":44,"buffer":47,"lodash":319}],28:[function(require,module,exports){
|
|
module.exports = require('./transaction');
|
|
|
|
module.exports.Input = require('./input');
|
|
module.exports.Output = require('./output');
|
|
module.exports.UnspentOutput = require('./unspentoutput');
|
|
module.exports.Signature = require('./signature');
|
|
module.exports.Sighash = require('./sighash');
|
|
|
|
},{"./input":29,"./output":35,"./sighash":36,"./signature":37,"./transaction":38,"./unspentoutput":39}],29:[function(require,module,exports){
|
|
module.exports = require('./input');
|
|
|
|
module.exports.PublicKey = require('./publickey');
|
|
module.exports.PublicKeyHash = require('./publickeyhash');
|
|
module.exports.MultiSig = require('./multisig.js');
|
|
module.exports.MultiSigScriptHash = require('./multisigscripthash.js');
|
|
|
|
},{"./input":30,"./multisig.js":31,"./multisigscripthash.js":32,"./publickey":33,"./publickeyhash":34}],30:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var $ = require('../../util/preconditions');
|
|
var errors = require('../../errors');
|
|
var BufferWriter = require('../../encoding/bufferwriter');
|
|
var buffer = require('buffer');
|
|
var BufferUtil = require('../../util/buffer');
|
|
var JSUtil = require('../../util/js');
|
|
var Script = require('../../script');
|
|
var Sighash = require('../sighash');
|
|
var Output = require('../output');
|
|
|
|
var MAXINT = 0xffffffff; // Math.pow(2, 32) - 1;
|
|
var DEFAULT_RBF_SEQNUMBER = MAXINT - 2;
|
|
var DEFAULT_SEQNUMBER = MAXINT;
|
|
var DEFAULT_LOCKTIME_SEQNUMBER = MAXINT - 1;
|
|
|
|
function Input(params) {
|
|
if (!(this instanceof Input)) {
|
|
return new Input(params);
|
|
}
|
|
if (params) {
|
|
return this._fromObject(params);
|
|
}
|
|
}
|
|
|
|
Input.MAXINT = MAXINT;
|
|
Input.DEFAULT_SEQNUMBER = DEFAULT_SEQNUMBER;
|
|
Input.DEFAULT_LOCKTIME_SEQNUMBER = DEFAULT_LOCKTIME_SEQNUMBER;
|
|
Input.DEFAULT_RBF_SEQNUMBER = DEFAULT_RBF_SEQNUMBER;
|
|
|
|
Object.defineProperty(Input.prototype, 'script', {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
if (this.isNull()) {
|
|
return null;
|
|
}
|
|
if (!this._script) {
|
|
this._script = new Script(this._scriptBuffer);
|
|
this._script._isInput = true;
|
|
}
|
|
return this._script;
|
|
}
|
|
});
|
|
|
|
Input.fromObject = function(obj) {
|
|
$.checkArgument(_.isObject(obj));
|
|
var input = new Input();
|
|
return input._fromObject(obj);
|
|
};
|
|
|
|
Input.prototype._fromObject = function(params) {
|
|
var prevTxId;
|
|
if (_.isString(params.prevTxId) && JSUtil.isHexa(params.prevTxId)) {
|
|
prevTxId = new buffer.Buffer(params.prevTxId, 'hex');
|
|
} else {
|
|
prevTxId = params.prevTxId;
|
|
}
|
|
this.output = params.output ?
|
|
(params.output instanceof Output ? params.output : new Output(params.output)) : undefined;
|
|
this.prevTxId = prevTxId || params.txidbuf;
|
|
this.outputIndex = _.isUndefined(params.outputIndex) ? params.txoutnum : params.outputIndex;
|
|
this.sequenceNumber = _.isUndefined(params.sequenceNumber) ?
|
|
(_.isUndefined(params.seqnum) ? DEFAULT_SEQNUMBER : params.seqnum) : params.sequenceNumber;
|
|
if (_.isUndefined(params.script) && _.isUndefined(params.scriptBuffer)) {
|
|
throw new errors.Transaction.Input.MissingScript();
|
|
}
|
|
this.setScript(params.scriptBuffer || params.script);
|
|
return this;
|
|
};
|
|
|
|
Input.prototype.toObject = Input.prototype.toJSON = function toObject() {
|
|
var obj = {
|
|
prevTxId: this.prevTxId.toString('hex'),
|
|
outputIndex: this.outputIndex,
|
|
sequenceNumber: this.sequenceNumber,
|
|
script: this._scriptBuffer.toString('hex'),
|
|
};
|
|
// add human readable form if input contains valid script
|
|
if (this.script) {
|
|
obj.scriptString = this.script.toString();
|
|
}
|
|
if (this.output) {
|
|
obj.output = this.output.toObject();
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
Input.fromBufferReader = function(br) {
|
|
var input = new Input();
|
|
input.prevTxId = br.readReverse(32);
|
|
input.outputIndex = br.readUInt32LE();
|
|
input._scriptBuffer = br.readVarLengthBuffer();
|
|
input.sequenceNumber = br.readUInt32LE();
|
|
// TODO: return different classes according to which input it is
|
|
// e.g: CoinbaseInput, PublicKeyHashInput, MultiSigScriptHashInput, etc.
|
|
return input;
|
|
};
|
|
|
|
Input.prototype.toBufferWriter = function(writer) {
|
|
if (!writer) {
|
|
writer = new BufferWriter();
|
|
}
|
|
writer.writeReverse(this.prevTxId);
|
|
writer.writeUInt32LE(this.outputIndex);
|
|
var script = this._scriptBuffer;
|
|
writer.writeVarintNum(script.length);
|
|
writer.write(script);
|
|
writer.writeUInt32LE(this.sequenceNumber);
|
|
return writer;
|
|
};
|
|
|
|
Input.prototype.setScript = function(script) {
|
|
this._script = null;
|
|
if (script instanceof Script) {
|
|
this._script = script;
|
|
this._script._isInput = true;
|
|
this._scriptBuffer = script.toBuffer();
|
|
} else if (JSUtil.isHexa(script)) {
|
|
// hex string script
|
|
this._scriptBuffer = new buffer.Buffer(script, 'hex');
|
|
} else if (_.isString(script)) {
|
|
// human readable string script
|
|
this._script = new Script(script);
|
|
this._script._isInput = true;
|
|
this._scriptBuffer = this._script.toBuffer();
|
|
} else if (BufferUtil.isBuffer(script)) {
|
|
// buffer script
|
|
this._scriptBuffer = new buffer.Buffer(script);
|
|
} else {
|
|
throw new TypeError('Invalid argument type: script');
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Retrieve signatures for the provided PrivateKey.
|
|
*
|
|
* @param {Transaction} transaction - the transaction to be signed
|
|
* @param {PrivateKey} privateKey - the private key to use when signing
|
|
* @param {number} inputIndex - the index of this input in the provided transaction
|
|
* @param {number} sigType - defaults to Signature.SIGHASH_ALL
|
|
* @param {Buffer} addressHash - if provided, don't calculate the hash of the
|
|
* public key associated with the private key provided
|
|
* @abstract
|
|
*/
|
|
Input.prototype.getSignatures = function() {
|
|
throw new errors.AbstractMethodInvoked(
|
|
'Trying to sign unsupported output type (only P2PKH and P2SH multisig inputs are supported)' +
|
|
' for input: ' + JSON.stringify(this)
|
|
);
|
|
};
|
|
|
|
Input.prototype.isFullySigned = function() {
|
|
throw new errors.AbstractMethodInvoked('Input#isFullySigned');
|
|
};
|
|
|
|
Input.prototype.isFinal = function() {
|
|
return this.sequenceNumber !== 4294967295;
|
|
};
|
|
|
|
Input.prototype.addSignature = function() {
|
|
throw new errors.AbstractMethodInvoked('Input#addSignature');
|
|
};
|
|
|
|
Input.prototype.clearSignatures = function() {
|
|
throw new errors.AbstractMethodInvoked('Input#clearSignatures');
|
|
};
|
|
|
|
Input.prototype.isValidSignature = function(transaction, signature) {
|
|
// FIXME: Refactor signature so this is not necessary
|
|
signature.signature.nhashtype = signature.sigtype;
|
|
return Sighash.verify(
|
|
transaction,
|
|
signature.signature,
|
|
signature.publicKey,
|
|
signature.inputIndex,
|
|
this.output.script
|
|
);
|
|
};
|
|
|
|
/**
|
|
* @returns true if this is a coinbase input (represents no input)
|
|
*/
|
|
Input.prototype.isNull = function() {
|
|
return this.prevTxId.toString('hex') === '0000000000000000000000000000000000000000000000000000000000000000' &&
|
|
this.outputIndex === 0xffffffff;
|
|
};
|
|
|
|
Input.prototype._estimateSize = function() {
|
|
return this.toBufferWriter().toBuffer().length;
|
|
};
|
|
|
|
module.exports = Input;
|
|
|
|
},{"../../encoding/bufferwriter":15,"../../errors":17,"../../script":25,"../../util/buffer":42,"../../util/js":43,"../../util/preconditions":44,"../output":35,"../sighash":36,"buffer":47,"lodash":319}],31:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var inherits = require('inherits');
|
|
var Transaction = require('../transaction');
|
|
var Input = require('./input');
|
|
var Output = require('../output');
|
|
var $ = require('../../util/preconditions');
|
|
|
|
var Script = require('../../script');
|
|
var Signature = require('../../crypto/signature');
|
|
var Sighash = require('../sighash');
|
|
var PublicKey = require('../../publickey');
|
|
var BufferUtil = require('../../util/buffer');
|
|
var TransactionSignature = require('../signature');
|
|
|
|
/**
|
|
* @constructor
|
|
*/
|
|
function MultiSigInput(input, pubkeys, threshold, signatures) {
|
|
Input.apply(this, arguments);
|
|
var self = this;
|
|
pubkeys = pubkeys || input.publicKeys;
|
|
threshold = threshold || input.threshold;
|
|
signatures = signatures || input.signatures;
|
|
this.publicKeys = _.sortBy(pubkeys, function(publicKey) { return publicKey.toString('hex'); });
|
|
$.checkState(Script.buildMultisigOut(this.publicKeys, threshold).equals(this.output.script),
|
|
'Provided public keys don\'t match to the provided output script');
|
|
this.publicKeyIndex = {};
|
|
_.each(this.publicKeys, function(publicKey, index) {
|
|
self.publicKeyIndex[publicKey.toString()] = index;
|
|
});
|
|
this.threshold = threshold;
|
|
// Empty array of signatures
|
|
this.signatures = signatures ? this._deserializeSignatures(signatures) : new Array(this.publicKeys.length);
|
|
}
|
|
inherits(MultiSigInput, Input);
|
|
|
|
MultiSigInput.prototype.toObject = function() {
|
|
var obj = Input.prototype.toObject.apply(this, arguments);
|
|
obj.threshold = this.threshold;
|
|
obj.publicKeys = _.map(this.publicKeys, function(publicKey) { return publicKey.toString(); });
|
|
obj.signatures = this._serializeSignatures();
|
|
return obj;
|
|
};
|
|
|
|
MultiSigInput.prototype._deserializeSignatures = function(signatures) {
|
|
return _.map(signatures, function(signature) {
|
|
if (!signature) {
|
|
return undefined;
|
|
}
|
|
return new TransactionSignature(signature);
|
|
});
|
|
};
|
|
|
|
MultiSigInput.prototype._serializeSignatures = function() {
|
|
return _.map(this.signatures, function(signature) {
|
|
if (!signature) {
|
|
return undefined;
|
|
}
|
|
return signature.toObject();
|
|
});
|
|
};
|
|
|
|
MultiSigInput.prototype.getSignatures = function(transaction, privateKey, index, sigtype) {
|
|
$.checkState(this.output instanceof Output);
|
|
sigtype = sigtype || Signature.SIGHASH_ALL;
|
|
|
|
var self = this;
|
|
var results = [];
|
|
_.each(this.publicKeys, function(publicKey) {
|
|
if (publicKey.toString() === privateKey.publicKey.toString()) {
|
|
results.push(new TransactionSignature({
|
|
publicKey: privateKey.publicKey,
|
|
prevTxId: self.prevTxId,
|
|
outputIndex: self.outputIndex,
|
|
inputIndex: index,
|
|
signature: Sighash.sign(transaction, privateKey, sigtype, index, self.output.script),
|
|
sigtype: sigtype
|
|
}));
|
|
}
|
|
});
|
|
|
|
return results;
|
|
};
|
|
|
|
MultiSigInput.prototype.addSignature = function(transaction, signature) {
|
|
$.checkState(!this.isFullySigned(), 'All needed signatures have already been added');
|
|
$.checkArgument(!_.isUndefined(this.publicKeyIndex[signature.publicKey.toString()]),
|
|
'Signature has no matching public key');
|
|
$.checkState(this.isValidSignature(transaction, signature));
|
|
this.signatures[this.publicKeyIndex[signature.publicKey.toString()]] = signature;
|
|
this._updateScript();
|
|
return this;
|
|
};
|
|
|
|
MultiSigInput.prototype._updateScript = function() {
|
|
this.setScript(Script.buildMultisigIn(
|
|
this.publicKeys,
|
|
this.threshold,
|
|
this._createSignatures()
|
|
));
|
|
return this;
|
|
};
|
|
|
|
MultiSigInput.prototype._createSignatures = function() {
|
|
return _.map(
|
|
_.filter(this.signatures, function(signature) { return !_.isUndefined(signature); }),
|
|
function(signature) {
|
|
return BufferUtil.concat([
|
|
signature.signature.toDER(),
|
|
BufferUtil.integerAsSingleByteBuffer(signature.sigtype)
|
|
]);
|
|
}
|
|
);
|
|
};
|
|
|
|
MultiSigInput.prototype.clearSignatures = function() {
|
|
this.signatures = new Array(this.publicKeys.length);
|
|
this._updateScript();
|
|
};
|
|
|
|
MultiSigInput.prototype.isFullySigned = function() {
|
|
return this.countSignatures() === this.threshold;
|
|
};
|
|
|
|
MultiSigInput.prototype.countMissingSignatures = function() {
|
|
return this.threshold - this.countSignatures();
|
|
};
|
|
|
|
MultiSigInput.prototype.countSignatures = function() {
|
|
return _.reduce(this.signatures, function(sum, signature) {
|
|
return sum + (!!signature);
|
|
}, 0);
|
|
};
|
|
|
|
MultiSigInput.prototype.publicKeysWithoutSignature = function() {
|
|
var self = this;
|
|
return _.filter(this.publicKeys, function(publicKey) {
|
|
return !(self.signatures[self.publicKeyIndex[publicKey.toString()]]);
|
|
});
|
|
};
|
|
|
|
MultiSigInput.prototype.isValidSignature = function(transaction, signature) {
|
|
// FIXME: Refactor signature so this is not necessary
|
|
signature.signature.nhashtype = signature.sigtype;
|
|
return Sighash.verify(
|
|
transaction,
|
|
signature.signature,
|
|
signature.publicKey,
|
|
signature.inputIndex,
|
|
this.output.script
|
|
);
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param {Buffer[]} signatures
|
|
* @param {PublicKey[]} publicKeys
|
|
* @param {Transaction} transaction
|
|
* @param {Integer} inputIndex
|
|
* @param {Input} input
|
|
* @returns {TransactionSignature[]}
|
|
*/
|
|
MultiSigInput.normalizeSignatures = function(transaction, input, inputIndex, signatures, publicKeys) {
|
|
return publicKeys.map(function (pubKey) {
|
|
var signatureMatch = null;
|
|
signatures = signatures.filter(function (signatureBuffer) {
|
|
if (signatureMatch) {
|
|
return true;
|
|
}
|
|
|
|
var signature = new TransactionSignature({
|
|
signature: Signature.fromTxFormat(signatureBuffer),
|
|
publicKey: pubKey,
|
|
prevTxId: input.prevTxId,
|
|
outputIndex: input.outputIndex,
|
|
inputIndex: inputIndex,
|
|
sigtype: Signature.SIGHASH_ALL
|
|
});
|
|
|
|
signature.signature.nhashtype = signature.sigtype;
|
|
var isMatch = Sighash.verify(
|
|
transaction,
|
|
signature.signature,
|
|
signature.publicKey,
|
|
signature.inputIndex,
|
|
input.output.script
|
|
);
|
|
|
|
if (isMatch) {
|
|
signatureMatch = signature;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
return signatureMatch ? signatureMatch : null;
|
|
});
|
|
};
|
|
|
|
MultiSigInput.OPCODES_SIZE = 1; // 0
|
|
MultiSigInput.SIGNATURE_SIZE = 73; // size (1) + DER (<=72)
|
|
|
|
MultiSigInput.prototype._estimateSize = function() {
|
|
return MultiSigInput.OPCODES_SIZE +
|
|
this.threshold * MultiSigInput.SIGNATURE_SIZE;
|
|
};
|
|
|
|
module.exports = MultiSigInput;
|
|
|
|
},{"../../crypto/signature":11,"../../publickey":24,"../../script":25,"../../util/buffer":42,"../../util/preconditions":44,"../output":35,"../sighash":36,"../signature":37,"../transaction":38,"./input":30,"inherits":318,"lodash":319}],32:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var inherits = require('inherits');
|
|
var Input = require('./input');
|
|
var Output = require('../output');
|
|
var $ = require('../../util/preconditions');
|
|
|
|
var Script = require('../../script');
|
|
var Signature = require('../../crypto/signature');
|
|
var Sighash = require('../sighash');
|
|
var PublicKey = require('../../publickey');
|
|
var BufferUtil = require('../../util/buffer');
|
|
var TransactionSignature = require('../signature');
|
|
|
|
/**
|
|
* @constructor
|
|
*/
|
|
function MultiSigScriptHashInput(input, pubkeys, threshold, signatures) {
|
|
Input.apply(this, arguments);
|
|
var self = this;
|
|
pubkeys = pubkeys || input.publicKeys;
|
|
threshold = threshold || input.threshold;
|
|
signatures = signatures || input.signatures;
|
|
this.publicKeys = _.sortBy(pubkeys, function(publicKey) { return publicKey.toString('hex'); });
|
|
this.redeemScript = Script.buildMultisigOut(this.publicKeys, threshold);
|
|
$.checkState(Script.buildScriptHashOut(this.redeemScript).equals(this.output.script),
|
|
'Provided public keys don\'t hash to the provided output');
|
|
this.publicKeyIndex = {};
|
|
_.each(this.publicKeys, function(publicKey, index) {
|
|
self.publicKeyIndex[publicKey.toString()] = index;
|
|
});
|
|
this.threshold = threshold;
|
|
// Empty array of signatures
|
|
this.signatures = signatures ? this._deserializeSignatures(signatures) : new Array(this.publicKeys.length);
|
|
}
|
|
inherits(MultiSigScriptHashInput, Input);
|
|
|
|
MultiSigScriptHashInput.prototype.toObject = function() {
|
|
var obj = Input.prototype.toObject.apply(this, arguments);
|
|
obj.threshold = this.threshold;
|
|
obj.publicKeys = _.map(this.publicKeys, function(publicKey) { return publicKey.toString(); });
|
|
obj.signatures = this._serializeSignatures();
|
|
return obj;
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype._deserializeSignatures = function(signatures) {
|
|
return _.map(signatures, function(signature) {
|
|
if (!signature) {
|
|
return undefined;
|
|
}
|
|
return new TransactionSignature(signature);
|
|
});
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype._serializeSignatures = function() {
|
|
return _.map(this.signatures, function(signature) {
|
|
if (!signature) {
|
|
return undefined;
|
|
}
|
|
return signature.toObject();
|
|
});
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype.getSignatures = function(transaction, privateKey, index, sigtype) {
|
|
$.checkState(this.output instanceof Output);
|
|
sigtype = sigtype || Signature.SIGHASH_ALL;
|
|
|
|
var self = this;
|
|
var results = [];
|
|
_.each(this.publicKeys, function(publicKey) {
|
|
if (publicKey.toString() === privateKey.publicKey.toString()) {
|
|
results.push(new TransactionSignature({
|
|
publicKey: privateKey.publicKey,
|
|
prevTxId: self.prevTxId,
|
|
outputIndex: self.outputIndex,
|
|
inputIndex: index,
|
|
signature: Sighash.sign(transaction, privateKey, sigtype, index, self.redeemScript),
|
|
sigtype: sigtype
|
|
}));
|
|
}
|
|
});
|
|
return results;
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype.addSignature = function(transaction, signature) {
|
|
$.checkState(!this.isFullySigned(), 'All needed signatures have already been added');
|
|
$.checkArgument(!_.isUndefined(this.publicKeyIndex[signature.publicKey.toString()]),
|
|
'Signature has no matching public key');
|
|
$.checkState(this.isValidSignature(transaction, signature));
|
|
this.signatures[this.publicKeyIndex[signature.publicKey.toString()]] = signature;
|
|
this._updateScript();
|
|
return this;
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype._updateScript = function() {
|
|
this.setScript(Script.buildP2SHMultisigIn(
|
|
this.publicKeys,
|
|
this.threshold,
|
|
this._createSignatures(),
|
|
{ cachedMultisig: this.redeemScript }
|
|
));
|
|
return this;
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype._createSignatures = function() {
|
|
return _.map(
|
|
_.filter(this.signatures, function(signature) { return !_.isUndefined(signature); }),
|
|
function(signature) {
|
|
return BufferUtil.concat([
|
|
signature.signature.toDER(),
|
|
BufferUtil.integerAsSingleByteBuffer(signature.sigtype)
|
|
]);
|
|
}
|
|
);
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype.clearSignatures = function() {
|
|
this.signatures = new Array(this.publicKeys.length);
|
|
this._updateScript();
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype.isFullySigned = function() {
|
|
return this.countSignatures() === this.threshold;
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype.countMissingSignatures = function() {
|
|
return this.threshold - this.countSignatures();
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype.countSignatures = function() {
|
|
return _.reduce(this.signatures, function(sum, signature) {
|
|
return sum + (!!signature);
|
|
}, 0);
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype.publicKeysWithoutSignature = function() {
|
|
var self = this;
|
|
return _.filter(this.publicKeys, function(publicKey) {
|
|
return !(self.signatures[self.publicKeyIndex[publicKey.toString()]]);
|
|
});
|
|
};
|
|
|
|
MultiSigScriptHashInput.prototype.isValidSignature = function(transaction, signature) {
|
|
// FIXME: Refactor signature so this is not necessary
|
|
signature.signature.nhashtype = signature.sigtype;
|
|
return Sighash.verify(
|
|
transaction,
|
|
signature.signature,
|
|
signature.publicKey,
|
|
signature.inputIndex,
|
|
this.redeemScript
|
|
);
|
|
};
|
|
|
|
MultiSigScriptHashInput.OPCODES_SIZE = 7; // serialized size (<=3) + 0 .. N .. M OP_CHECKMULTISIG
|
|
MultiSigScriptHashInput.SIGNATURE_SIZE = 74; // size (1) + DER (<=72) + sighash (1)
|
|
MultiSigScriptHashInput.PUBKEY_SIZE = 34; // size (1) + DER (<=33)
|
|
|
|
MultiSigScriptHashInput.prototype._estimateSize = function() {
|
|
return MultiSigScriptHashInput.OPCODES_SIZE +
|
|
this.threshold * MultiSigScriptHashInput.SIGNATURE_SIZE +
|
|
this.publicKeys.length * MultiSigScriptHashInput.PUBKEY_SIZE;
|
|
};
|
|
|
|
module.exports = MultiSigScriptHashInput;
|
|
|
|
},{"../../crypto/signature":11,"../../publickey":24,"../../script":25,"../../util/buffer":42,"../../util/preconditions":44,"../output":35,"../sighash":36,"../signature":37,"./input":30,"inherits":318,"lodash":319}],33:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var inherits = require('inherits');
|
|
|
|
var $ = require('../../util/preconditions');
|
|
var BufferUtil = require('../../util/buffer');
|
|
|
|
var Input = require('./input');
|
|
var Output = require('../output');
|
|
var Sighash = require('../sighash');
|
|
var Script = require('../../script');
|
|
var Signature = require('../../crypto/signature');
|
|
var TransactionSignature = require('../signature');
|
|
|
|
/**
|
|
* Represents a special kind of input of PayToPublicKey kind.
|
|
* @constructor
|
|
*/
|
|
function PublicKeyInput() {
|
|
Input.apply(this, arguments);
|
|
}
|
|
inherits(PublicKeyInput, Input);
|
|
|
|
/**
|
|
* @param {Transaction} transaction - the transaction to be signed
|
|
* @param {PrivateKey} privateKey - the private key with which to sign the transaction
|
|
* @param {number} index - the index of the input in the transaction input vector
|
|
* @param {number=} sigtype - the type of signature, defaults to Signature.SIGHASH_ALL
|
|
* @return {Array} of objects that can be
|
|
*/
|
|
PublicKeyInput.prototype.getSignatures = function(transaction, privateKey, index, sigtype) {
|
|
$.checkState(this.output instanceof Output);
|
|
sigtype = sigtype || Signature.SIGHASH_ALL;
|
|
var publicKey = privateKey.toPublicKey();
|
|
if (publicKey.toString() === this.output.script.getPublicKey().toString('hex')) {
|
|
return [new TransactionSignature({
|
|
publicKey: publicKey,
|
|
prevTxId: this.prevTxId,
|
|
outputIndex: this.outputIndex,
|
|
inputIndex: index,
|
|
signature: Sighash.sign(transaction, privateKey, sigtype, index, this.output.script),
|
|
sigtype: sigtype
|
|
})];
|
|
}
|
|
return [];
|
|
};
|
|
|
|
/**
|
|
* Add the provided signature
|
|
*
|
|
* @param {Object} signature
|
|
* @param {PublicKey} signature.publicKey
|
|
* @param {Signature} signature.signature
|
|
* @param {number=} signature.sigtype
|
|
* @return {PublicKeyInput} this, for chaining
|
|
*/
|
|
PublicKeyInput.prototype.addSignature = function(transaction, signature) {
|
|
$.checkState(this.isValidSignature(transaction, signature), 'Signature is invalid');
|
|
this.setScript(Script.buildPublicKeyIn(
|
|
signature.signature.toDER(),
|
|
signature.sigtype
|
|
));
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Clear the input's signature
|
|
* @return {PublicKeyHashInput} this, for chaining
|
|
*/
|
|
PublicKeyInput.prototype.clearSignatures = function() {
|
|
this.setScript(Script.empty());
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Query whether the input is signed
|
|
* @return {boolean}
|
|
*/
|
|
PublicKeyInput.prototype.isFullySigned = function() {
|
|
return this.script.isPublicKeyIn();
|
|
};
|
|
|
|
PublicKeyInput.SCRIPT_MAX_SIZE = 73; // sigsize (1 + 72)
|
|
|
|
PublicKeyInput.prototype._estimateSize = function() {
|
|
return PublicKeyInput.SCRIPT_MAX_SIZE;
|
|
};
|
|
|
|
module.exports = PublicKeyInput;
|
|
|
|
},{"../../crypto/signature":11,"../../script":25,"../../util/buffer":42,"../../util/preconditions":44,"../output":35,"../sighash":36,"../signature":37,"./input":30,"inherits":318}],34:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var inherits = require('inherits');
|
|
|
|
var $ = require('../../util/preconditions');
|
|
var BufferUtil = require('../../util/buffer');
|
|
|
|
var Hash = require('../../crypto/hash');
|
|
var Input = require('./input');
|
|
var Output = require('../output');
|
|
var Sighash = require('../sighash');
|
|
var Script = require('../../script');
|
|
var Signature = require('../../crypto/signature');
|
|
var TransactionSignature = require('../signature');
|
|
|
|
/**
|
|
* Represents a special kind of input of PayToPublicKeyHash kind.
|
|
* @constructor
|
|
*/
|
|
function PublicKeyHashInput() {
|
|
Input.apply(this, arguments);
|
|
}
|
|
inherits(PublicKeyHashInput, Input);
|
|
|
|
/* jshint maxparams: 5 */
|
|
/**
|
|
* @param {Transaction} transaction - the transaction to be signed
|
|
* @param {PrivateKey} privateKey - the private key with which to sign the transaction
|
|
* @param {number} index - the index of the input in the transaction input vector
|
|
* @param {number=} sigtype - the type of signature, defaults to Signature.SIGHASH_ALL
|
|
* @param {Buffer=} hashData - the precalculated hash of the public key associated with the privateKey provided
|
|
* @return {Array} of objects that can be
|
|
*/
|
|
PublicKeyHashInput.prototype.getSignatures = function(transaction, privateKey, index, sigtype, hashData) {
|
|
$.checkState(this.output instanceof Output);
|
|
hashData = hashData || Hash.sha256ripemd160(privateKey.publicKey.toBuffer());
|
|
sigtype = sigtype || Signature.SIGHASH_ALL;
|
|
|
|
if (BufferUtil.equals(hashData, this.output.script.getPublicKeyHash())) {
|
|
return [new TransactionSignature({
|
|
publicKey: privateKey.publicKey,
|
|
prevTxId: this.prevTxId,
|
|
outputIndex: this.outputIndex,
|
|
inputIndex: index,
|
|
signature: Sighash.sign(transaction, privateKey, sigtype, index, this.output.script),
|
|
sigtype: sigtype
|
|
})];
|
|
}
|
|
return [];
|
|
};
|
|
/* jshint maxparams: 3 */
|
|
|
|
/**
|
|
* Add the provided signature
|
|
*
|
|
* @param {Object} signature
|
|
* @param {PublicKey} signature.publicKey
|
|
* @param {Signature} signature.signature
|
|
* @param {number=} signature.sigtype
|
|
* @return {PublicKeyHashInput} this, for chaining
|
|
*/
|
|
PublicKeyHashInput.prototype.addSignature = function(transaction, signature) {
|
|
$.checkState(this.isValidSignature(transaction, signature), 'Signature is invalid');
|
|
this.setScript(Script.buildPublicKeyHashIn(
|
|
signature.publicKey,
|
|
signature.signature.toDER(),
|
|
signature.sigtype
|
|
));
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Clear the input's signature
|
|
* @return {PublicKeyHashInput} this, for chaining
|
|
*/
|
|
PublicKeyHashInput.prototype.clearSignatures = function() {
|
|
this.setScript(Script.empty());
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Query whether the input is signed
|
|
* @return {boolean}
|
|
*/
|
|
PublicKeyHashInput.prototype.isFullySigned = function() {
|
|
return this.script.isPublicKeyHashIn();
|
|
};
|
|
|
|
PublicKeyHashInput.SCRIPT_MAX_SIZE = 73 + 34; // sigsize (1 + 72) + pubkey (1 + 33)
|
|
|
|
PublicKeyHashInput.prototype._estimateSize = function() {
|
|
return PublicKeyHashInput.SCRIPT_MAX_SIZE;
|
|
};
|
|
|
|
module.exports = PublicKeyHashInput;
|
|
|
|
},{"../../crypto/hash":8,"../../crypto/signature":11,"../../script":25,"../../util/buffer":42,"../../util/preconditions":44,"../output":35,"../sighash":36,"../signature":37,"./input":30,"inherits":318}],35:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var BN = require('../crypto/bn');
|
|
var buffer = require('buffer');
|
|
var bufferUtil = require('../util/buffer');
|
|
var JSUtil = require('../util/js');
|
|
var BufferWriter = require('../encoding/bufferwriter');
|
|
var Script = require('../script');
|
|
var $ = require('../util/preconditions');
|
|
var errors = require('../errors');
|
|
|
|
var MAX_SAFE_INTEGER = 0x1fffffffffffff;
|
|
|
|
function Output(args) {
|
|
if (!(this instanceof Output)) {
|
|
return new Output(args);
|
|
}
|
|
if (_.isObject(args)) {
|
|
this.satoshis = args.satoshis;
|
|
if (bufferUtil.isBuffer(args.script)) {
|
|
this._scriptBuffer = args.script;
|
|
} else {
|
|
var script;
|
|
if (_.isString(args.script) && JSUtil.isHexa(args.script)) {
|
|
script = new buffer.Buffer(args.script, 'hex');
|
|
} else {
|
|
script = args.script;
|
|
}
|
|
this.setScript(script);
|
|
}
|
|
} else {
|
|
throw new TypeError('Unrecognized argument for Output');
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(Output.prototype, 'script', {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
if (this._script) {
|
|
return this._script;
|
|
} else {
|
|
this.setScriptFromBuffer(this._scriptBuffer);
|
|
return this._script;
|
|
}
|
|
|
|
}
|
|
});
|
|
|
|
Object.defineProperty(Output.prototype, 'satoshis', {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
return this._satoshis;
|
|
},
|
|
set: function(num) {
|
|
if (num instanceof BN) {
|
|
this._satoshisBN = num;
|
|
this._satoshis = num.toNumber();
|
|
} else if (_.isString(num)) {
|
|
this._satoshis = parseInt(num);
|
|
this._satoshisBN = BN.fromNumber(this._satoshis);
|
|
} else {
|
|
$.checkArgument(
|
|
JSUtil.isNaturalNumber(num),
|
|
'Output satoshis is not a natural number'
|
|
);
|
|
this._satoshisBN = BN.fromNumber(num);
|
|
this._satoshis = num;
|
|
}
|
|
$.checkState(
|
|
JSUtil.isNaturalNumber(this._satoshis),
|
|
'Output satoshis is not a natural number'
|
|
);
|
|
}
|
|
});
|
|
|
|
Output.prototype.invalidSatoshis = function() {
|
|
if (this._satoshis > MAX_SAFE_INTEGER) {
|
|
return 'transaction txout satoshis greater than max safe integer';
|
|
}
|
|
if (this._satoshis !== this._satoshisBN.toNumber()) {
|
|
return 'transaction txout satoshis has corrupted value';
|
|
}
|
|
if (this._satoshis < 0) {
|
|
return 'transaction txout negative';
|
|
}
|
|
return false;
|
|
};
|
|
|
|
Output.prototype.toObject = Output.prototype.toJSON = function toObject() {
|
|
var obj = {
|
|
satoshis: this.satoshis
|
|
};
|
|
obj.script = this._scriptBuffer.toString('hex');
|
|
return obj;
|
|
};
|
|
|
|
Output.fromObject = function(data) {
|
|
return new Output(data);
|
|
};
|
|
|
|
Output.prototype.setScriptFromBuffer = function(buffer) {
|
|
this._scriptBuffer = buffer;
|
|
try {
|
|
this._script = Script.fromBuffer(this._scriptBuffer);
|
|
this._script._isOutput = true;
|
|
} catch(e) {
|
|
if (e instanceof errors.Script.InvalidBuffer) {
|
|
this._script = null;
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
};
|
|
|
|
Output.prototype.setScript = function(script) {
|
|
if (script instanceof Script) {
|
|
this._scriptBuffer = script.toBuffer();
|
|
this._script = script;
|
|
this._script._isOutput = true;
|
|
} else if (_.isString(script)) {
|
|
this._script = Script.fromString(script);
|
|
this._scriptBuffer = this._script.toBuffer();
|
|
this._script._isOutput = true;
|
|
} else if (bufferUtil.isBuffer(script)) {
|
|
this.setScriptFromBuffer(script);
|
|
} else {
|
|
throw new TypeError('Invalid argument type: script');
|
|
}
|
|
return this;
|
|
};
|
|
|
|
Output.prototype.inspect = function() {
|
|
var scriptStr;
|
|
if (this.script) {
|
|
scriptStr = this.script.inspect();
|
|
} else {
|
|
scriptStr = this._scriptBuffer.toString('hex');
|
|
}
|
|
return '<Output (' + this.satoshis + ' sats) ' + scriptStr + '>';
|
|
};
|
|
|
|
Output.fromBufferReader = function(br) {
|
|
var obj = {};
|
|
obj.satoshis = br.readUInt64LEBN();
|
|
var size = br.readVarintNum();
|
|
if (size !== 0) {
|
|
obj.script = br.read(size);
|
|
} else {
|
|
obj.script = new buffer.Buffer([]);
|
|
}
|
|
return new Output(obj);
|
|
};
|
|
|
|
Output.prototype.toBufferWriter = function(writer) {
|
|
if (!writer) {
|
|
writer = new BufferWriter();
|
|
}
|
|
writer.writeUInt64LEBN(this._satoshisBN);
|
|
var script = this._scriptBuffer;
|
|
writer.writeVarintNum(script.length);
|
|
writer.write(script);
|
|
return writer;
|
|
};
|
|
|
|
module.exports = Output;
|
|
|
|
},{"../crypto/bn":6,"../encoding/bufferwriter":15,"../errors":17,"../script":25,"../util/buffer":42,"../util/js":43,"../util/preconditions":44,"buffer":47,"lodash":319}],36:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var buffer = require('buffer');
|
|
|
|
var Signature = require('../crypto/signature');
|
|
var Script = require('../script');
|
|
var Output = require('./output');
|
|
var BufferReader = require('../encoding/bufferreader');
|
|
var BufferWriter = require('../encoding/bufferwriter');
|
|
var BN = require('../crypto/bn');
|
|
var Hash = require('../crypto/hash');
|
|
var ECDSA = require('../crypto/ecdsa');
|
|
var $ = require('../util/preconditions');
|
|
var _ = require('lodash');
|
|
|
|
var SIGHASH_SINGLE_BUG = '0000000000000000000000000000000000000000000000000000000000000001';
|
|
var BITS_64_ON = 'ffffffffffffffff';
|
|
|
|
/**
|
|
* Returns a buffer of length 32 bytes with the hash that needs to be signed
|
|
* for OP_CHECKSIG.
|
|
*
|
|
* @name Signing.sighash
|
|
* @param {Transaction} transaction the transaction to sign
|
|
* @param {number} sighashType the type of the hash
|
|
* @param {number} inputNumber the input index for the signature
|
|
* @param {Script} subscript the script that will be signed
|
|
*/
|
|
var sighash = function sighash(transaction, sighashType, inputNumber, subscript) {
|
|
var Transaction = require('./transaction');
|
|
var Input = require('./input');
|
|
|
|
var i;
|
|
// Copy transaction
|
|
var txcopy = Transaction.shallowCopy(transaction);
|
|
|
|
// Copy script
|
|
subscript = new Script(subscript);
|
|
subscript.removeCodeseparators();
|
|
|
|
for (i = 0; i < txcopy.inputs.length; i++) {
|
|
// Blank signatures for other inputs
|
|
txcopy.inputs[i] = new Input(txcopy.inputs[i]).setScript(Script.empty());
|
|
}
|
|
|
|
txcopy.inputs[inputNumber] = new Input(txcopy.inputs[inputNumber]).setScript(subscript);
|
|
|
|
if ((sighashType & 31) === Signature.SIGHASH_NONE ||
|
|
(sighashType & 31) === Signature.SIGHASH_SINGLE) {
|
|
|
|
// clear all sequenceNumbers
|
|
for (i = 0; i < txcopy.inputs.length; i++) {
|
|
if (i !== inputNumber) {
|
|
txcopy.inputs[i].sequenceNumber = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((sighashType & 31) === Signature.SIGHASH_NONE) {
|
|
txcopy.outputs = [];
|
|
|
|
} else if ((sighashType & 31) === Signature.SIGHASH_SINGLE) {
|
|
// The SIGHASH_SINGLE bug.
|
|
// https://bitcointalk.org/index.php?topic=260595.0
|
|
if (inputNumber >= txcopy.outputs.length) {
|
|
return new Buffer(SIGHASH_SINGLE_BUG, 'hex');
|
|
}
|
|
|
|
txcopy.outputs.length = inputNumber + 1;
|
|
|
|
for (i = 0; i < inputNumber; i++) {
|
|
txcopy.outputs[i] = new Output({
|
|
satoshis: BN.fromBuffer(new buffer.Buffer(BITS_64_ON, 'hex')),
|
|
script: Script.empty()
|
|
});
|
|
}
|
|
}
|
|
|
|
if (sighashType & Signature.SIGHASH_ANYONECANPAY) {
|
|
txcopy.inputs = [txcopy.inputs[inputNumber]];
|
|
}
|
|
|
|
var buf = new BufferWriter()
|
|
.write(txcopy.toBuffer())
|
|
.writeInt32LE(sighashType)
|
|
.toBuffer();
|
|
var ret = Hash.sha256sha256(buf);
|
|
ret = new BufferReader(ret).readReverse();
|
|
return ret;
|
|
};
|
|
|
|
/**
|
|
* Create a signature
|
|
*
|
|
* @name Signing.sign
|
|
* @param {Transaction} transaction
|
|
* @param {PrivateKey} privateKey
|
|
* @param {number} sighash
|
|
* @param {number} inputIndex
|
|
* @param {Script} subscript
|
|
* @return {Signature}
|
|
*/
|
|
function sign(transaction, privateKey, sighashType, inputIndex, subscript) {
|
|
var hashbuf = sighash(transaction, sighashType, inputIndex, subscript);
|
|
var sig = ECDSA.sign(hashbuf, privateKey, 'little').set({
|
|
nhashtype: sighashType
|
|
});
|
|
return sig;
|
|
}
|
|
|
|
/**
|
|
* Verify a signature
|
|
*
|
|
* @name Signing.verify
|
|
* @param {Transaction} transaction
|
|
* @param {Signature} signature
|
|
* @param {PublicKey} publicKey
|
|
* @param {number} inputIndex
|
|
* @param {Script} subscript
|
|
* @return {boolean}
|
|
*/
|
|
function verify(transaction, signature, publicKey, inputIndex, subscript) {
|
|
$.checkArgument(!_.isUndefined(transaction));
|
|
$.checkArgument(!_.isUndefined(signature) && !_.isUndefined(signature.nhashtype));
|
|
var hashbuf = sighash(transaction, signature.nhashtype, inputIndex, subscript);
|
|
return ECDSA.verify(hashbuf, signature, publicKey, 'little');
|
|
}
|
|
|
|
/**
|
|
* @namespace Signing
|
|
*/
|
|
module.exports = {
|
|
sighash: sighash,
|
|
sign: sign,
|
|
verify: verify
|
|
};
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../crypto/bn":6,"../crypto/ecdsa":7,"../crypto/hash":8,"../crypto/signature":11,"../encoding/bufferreader":14,"../encoding/bufferwriter":15,"../script":25,"../util/preconditions":44,"./input":29,"./output":35,"./transaction":38,"buffer":47,"lodash":319}],37:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var $ = require('../util/preconditions');
|
|
var inherits = require('inherits');
|
|
var BufferUtil = require('../util/buffer');
|
|
var JSUtil = require('../util/js');
|
|
|
|
var PublicKey = require('../publickey');
|
|
var errors = require('../errors');
|
|
var Signature = require('../crypto/signature');
|
|
|
|
/**
|
|
* @desc
|
|
* Wrapper around Signature with fields related to signing a transaction specifically
|
|
*
|
|
* @param {Object|string|TransactionSignature} arg
|
|
* @constructor
|
|
*/
|
|
function TransactionSignature(arg) {
|
|
if (!(this instanceof TransactionSignature)) {
|
|
return new TransactionSignature(arg);
|
|
}
|
|
if (arg instanceof TransactionSignature) {
|
|
return arg;
|
|
}
|
|
if (_.isObject(arg)) {
|
|
return this._fromObject(arg);
|
|
}
|
|
throw new errors.InvalidArgument('TransactionSignatures must be instantiated from an object');
|
|
}
|
|
inherits(TransactionSignature, Signature);
|
|
|
|
TransactionSignature.prototype._fromObject = function(arg) {
|
|
this._checkObjectArgs(arg);
|
|
this.publicKey = new PublicKey(arg.publicKey);
|
|
this.prevTxId = BufferUtil.isBuffer(arg.prevTxId) ? arg.prevTxId : new Buffer(arg.prevTxId, 'hex');
|
|
this.outputIndex = arg.outputIndex;
|
|
this.inputIndex = arg.inputIndex;
|
|
this.signature = (arg.signature instanceof Signature) ? arg.signature :
|
|
BufferUtil.isBuffer(arg.signature) ? Signature.fromBuffer(arg.signature) :
|
|
Signature.fromString(arg.signature);
|
|
this.sigtype = arg.sigtype;
|
|
return this;
|
|
};
|
|
|
|
TransactionSignature.prototype._checkObjectArgs = function(arg) {
|
|
$.checkArgument(PublicKey(arg.publicKey), 'publicKey');
|
|
$.checkArgument(!_.isUndefined(arg.inputIndex), 'inputIndex');
|
|
$.checkArgument(!_.isUndefined(arg.outputIndex), 'outputIndex');
|
|
$.checkState(_.isNumber(arg.inputIndex), 'inputIndex must be a number');
|
|
$.checkState(_.isNumber(arg.outputIndex), 'outputIndex must be a number');
|
|
$.checkArgument(arg.signature, 'signature');
|
|
$.checkArgument(arg.prevTxId, 'prevTxId');
|
|
$.checkState(arg.signature instanceof Signature ||
|
|
BufferUtil.isBuffer(arg.signature) ||
|
|
JSUtil.isHexa(arg.signature), 'signature must be a buffer or hexa value');
|
|
$.checkState(BufferUtil.isBuffer(arg.prevTxId) ||
|
|
JSUtil.isHexa(arg.prevTxId), 'prevTxId must be a buffer or hexa value');
|
|
$.checkArgument(arg.sigtype, 'sigtype');
|
|
$.checkState(_.isNumber(arg.sigtype), 'sigtype must be a number');
|
|
};
|
|
|
|
/**
|
|
* Serializes a transaction to a plain JS object
|
|
* @return {Object}
|
|
*/
|
|
TransactionSignature.prototype.toObject = TransactionSignature.prototype.toJSON = function toObject() {
|
|
return {
|
|
publicKey: this.publicKey.toString(),
|
|
prevTxId: this.prevTxId.toString('hex'),
|
|
outputIndex: this.outputIndex,
|
|
inputIndex: this.inputIndex,
|
|
signature: this.signature.toString(),
|
|
sigtype: this.sigtype
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Builds a TransactionSignature from an object
|
|
* @param {Object} object
|
|
* @return {TransactionSignature}
|
|
*/
|
|
TransactionSignature.fromObject = function(object) {
|
|
$.checkArgument(object);
|
|
return new TransactionSignature(object);
|
|
};
|
|
|
|
module.exports = TransactionSignature;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../crypto/signature":11,"../errors":17,"../publickey":24,"../util/buffer":42,"../util/js":43,"../util/preconditions":44,"buffer":47,"inherits":318,"lodash":319}],38:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var $ = require('../util/preconditions');
|
|
var buffer = require('buffer');
|
|
var compare = Buffer.compare || require('buffer-compare');
|
|
|
|
var errors = require('../errors');
|
|
var BufferUtil = require('../util/buffer');
|
|
var JSUtil = require('../util/js');
|
|
var BufferReader = require('../encoding/bufferreader');
|
|
var BufferWriter = require('../encoding/bufferwriter');
|
|
var Hash = require('../crypto/hash');
|
|
var Signature = require('../crypto/signature');
|
|
var Sighash = require('./sighash');
|
|
|
|
var Address = require('../address');
|
|
var UnspentOutput = require('./unspentoutput');
|
|
var Input = require('./input');
|
|
var PublicKeyHashInput = Input.PublicKeyHash;
|
|
var PublicKeyInput = Input.PublicKey;
|
|
var MultiSigScriptHashInput = Input.MultiSigScriptHash;
|
|
var MultiSigInput = Input.MultiSig;
|
|
var Output = require('./output');
|
|
var Script = require('../script');
|
|
var PrivateKey = require('../privatekey');
|
|
var BN = require('../crypto/bn');
|
|
|
|
/**
|
|
* Represents a transaction, a set of inputs and outputs to change ownership of tokens
|
|
*
|
|
* @param {*} serialized
|
|
* @constructor
|
|
*/
|
|
function Transaction(serialized) {
|
|
if (!(this instanceof Transaction)) {
|
|
return new Transaction(serialized);
|
|
}
|
|
this.inputs = [];
|
|
this.outputs = [];
|
|
this._inputAmount = undefined;
|
|
this._outputAmount = undefined;
|
|
|
|
if (serialized) {
|
|
if (serialized instanceof Transaction) {
|
|
return Transaction.shallowCopy(serialized);
|
|
} else if (JSUtil.isHexa(serialized)) {
|
|
this.fromString(serialized);
|
|
} else if (BufferUtil.isBuffer(serialized)) {
|
|
this.fromBuffer(serialized);
|
|
} else if (_.isObject(serialized)) {
|
|
this.fromObject(serialized);
|
|
} else {
|
|
throw new errors.InvalidArgument('Must provide an object or string to deserialize a transaction');
|
|
}
|
|
} else {
|
|
this._newTransaction();
|
|
}
|
|
}
|
|
|
|
var CURRENT_VERSION = 1;
|
|
var DEFAULT_NLOCKTIME = 0;
|
|
var MAX_BLOCK_SIZE = 1000000;
|
|
|
|
// Minimum amount for an output for it not to be considered a dust output
|
|
Transaction.DUST_AMOUNT = 546;
|
|
|
|
// Margin of error to allow fees in the vecinity of the expected value but doesn't allow a big difference
|
|
Transaction.FEE_SECURITY_MARGIN = 150;
|
|
|
|
// max amount of satoshis in circulation
|
|
Transaction.MAX_MONEY = 21000000 * 1e8;
|
|
|
|
// nlocktime limit to be considered block height rather than a timestamp
|
|
Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT = 5e8;
|
|
|
|
// Max value for an unsigned 32 bit value
|
|
Transaction.NLOCKTIME_MAX_VALUE = 4294967295;
|
|
|
|
// Value used for fee estimation (satoshis per kilobyte)
|
|
Transaction.FEE_PER_KB = 100000;
|
|
|
|
// Safe upper bound for change address script size in bytes
|
|
Transaction.CHANGE_OUTPUT_MAX_SIZE = 20 + 4 + 34 + 4;
|
|
Transaction.MAXIMUM_EXTRA_SIZE = 4 + 9 + 9 + 4;
|
|
|
|
/* Constructors and Serialization */
|
|
|
|
/**
|
|
* Create a 'shallow' copy of the transaction, by serializing and deserializing
|
|
* it dropping any additional information that inputs and outputs may have hold
|
|
*
|
|
* @param {Transaction} transaction
|
|
* @return {Transaction}
|
|
*/
|
|
Transaction.shallowCopy = function(transaction) {
|
|
var copy = new Transaction(transaction.toBuffer());
|
|
return copy;
|
|
};
|
|
|
|
var hashProperty = {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
return new BufferReader(this._getHash()).readReverse().toString('hex');
|
|
}
|
|
};
|
|
Object.defineProperty(Transaction.prototype, 'hash', hashProperty);
|
|
Object.defineProperty(Transaction.prototype, 'id', hashProperty);
|
|
|
|
var ioProperty = {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
return this._getInputAmount();
|
|
}
|
|
};
|
|
Object.defineProperty(Transaction.prototype, 'inputAmount', ioProperty);
|
|
ioProperty.get = function() {
|
|
return this._getOutputAmount();
|
|
};
|
|
Object.defineProperty(Transaction.prototype, 'outputAmount', ioProperty);
|
|
|
|
/**
|
|
* Retrieve the little endian hash of the transaction (used for serialization)
|
|
* @return {Buffer}
|
|
*/
|
|
Transaction.prototype._getHash = function() {
|
|
return Hash.sha256sha256(this.toBuffer());
|
|
};
|
|
|
|
/**
|
|
* Retrieve a hexa string that can be used with bitcoind's CLI interface
|
|
* (decoderawtransaction, sendrawtransaction)
|
|
*
|
|
* @param {Object|boolean=} unsafe if true, skip all tests. if it's an object,
|
|
* it's expected to contain a set of flags to skip certain tests:
|
|
* * `disableAll`: disable all checks
|
|
* * `disableSmallFees`: disable checking for fees that are too small
|
|
* * `disableLargeFees`: disable checking for fees that are too large
|
|
* * `disableIsFullySigned`: disable checking if all inputs are fully signed
|
|
* * `disableDustOutputs`: disable checking if there are no outputs that are dust amounts
|
|
* * `disableMoreOutputThanInput`: disable checking if the transaction spends more bitcoins than the sum of the input amounts
|
|
* @return {string}
|
|
*/
|
|
Transaction.prototype.serialize = function(unsafe) {
|
|
if (true === unsafe || unsafe && unsafe.disableAll) {
|
|
return this.uncheckedSerialize();
|
|
} else {
|
|
return this.checkedSerialize(unsafe);
|
|
}
|
|
};
|
|
|
|
Transaction.prototype.uncheckedSerialize = Transaction.prototype.toString = function() {
|
|
return this.toBuffer().toString('hex');
|
|
};
|
|
|
|
/**
|
|
* Retrieve a hexa string that can be used with bitcoind's CLI interface
|
|
* (decoderawtransaction, sendrawtransaction)
|
|
*
|
|
* @param {Object} opts allows to skip certain tests. {@see Transaction#serialize}
|
|
* @return {string}
|
|
*/
|
|
Transaction.prototype.checkedSerialize = function(opts) {
|
|
var serializationError = this.getSerializationError(opts);
|
|
if (serializationError) {
|
|
serializationError.message += ' - For more information please see: ' +
|
|
'https://bitcore.io/api/lib/transaction#serialization-checks';
|
|
throw serializationError;
|
|
}
|
|
return this.uncheckedSerialize();
|
|
};
|
|
|
|
Transaction.prototype.invalidSatoshis = function() {
|
|
var invalid = false;
|
|
for (var i = 0; i < this.outputs.length; i++) {
|
|
if (this.outputs[i].invalidSatoshis()) {
|
|
invalid = true;
|
|
}
|
|
}
|
|
return invalid;
|
|
};
|
|
|
|
/**
|
|
* Retrieve a possible error that could appear when trying to serialize and
|
|
* broadcast this transaction.
|
|
*
|
|
* @param {Object} opts allows to skip certain tests. {@see Transaction#serialize}
|
|
* @return {bitcore.Error}
|
|
*/
|
|
Transaction.prototype.getSerializationError = function(opts) {
|
|
opts = opts || {};
|
|
|
|
if (this.invalidSatoshis()) {
|
|
return new errors.Transaction.InvalidSatoshis();
|
|
}
|
|
|
|
var unspent = this._getUnspentValue();
|
|
var unspentError;
|
|
if (unspent < 0) {
|
|
if (!opts.disableMoreOutputThanInput) {
|
|
unspentError = new errors.Transaction.InvalidOutputAmountSum();
|
|
}
|
|
} else {
|
|
unspentError = this._hasFeeError(opts, unspent);
|
|
}
|
|
|
|
return unspentError ||
|
|
this._hasDustOutputs(opts) ||
|
|
this._isMissingSignatures(opts);
|
|
};
|
|
|
|
Transaction.prototype._hasFeeError = function(opts, unspent) {
|
|
|
|
if (!_.isUndefined(this._fee) && this._fee !== unspent) {
|
|
return new errors.Transaction.FeeError.Different(
|
|
'Unspent value is ' + unspent + ' but specified fee is ' + this._fee
|
|
);
|
|
}
|
|
|
|
if (!opts.disableLargeFees) {
|
|
var maximumFee = Math.floor(Transaction.FEE_SECURITY_MARGIN * this._estimateFee());
|
|
if (unspent > maximumFee) {
|
|
if (this._missingChange()) {
|
|
return new errors.Transaction.ChangeAddressMissing(
|
|
'Fee is too large and no change address was provided'
|
|
);
|
|
}
|
|
return new errors.Transaction.FeeError.TooLarge(
|
|
'expected less than ' + maximumFee + ' but got ' + unspent
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!opts.disableSmallFees) {
|
|
var minimumFee = Math.ceil(this._estimateFee() / Transaction.FEE_SECURITY_MARGIN);
|
|
if (unspent < minimumFee) {
|
|
return new errors.Transaction.FeeError.TooSmall(
|
|
'expected more than ' + minimumFee + ' but got ' + unspent
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
Transaction.prototype._missingChange = function() {
|
|
return !this._changeScript;
|
|
};
|
|
|
|
Transaction.prototype._hasDustOutputs = function(opts) {
|
|
if (opts.disableDustOutputs) {
|
|
return;
|
|
}
|
|
var index, output;
|
|
for (index in this.outputs) {
|
|
output = this.outputs[index];
|
|
if (output.satoshis < Transaction.DUST_AMOUNT && !output.script.isDataOut()) {
|
|
return new errors.Transaction.DustOutputs();
|
|
}
|
|
}
|
|
};
|
|
|
|
Transaction.prototype._isMissingSignatures = function(opts) {
|
|
if (opts.disableIsFullySigned) {
|
|
return;
|
|
}
|
|
if (!this.isFullySigned()) {
|
|
return new errors.Transaction.MissingSignatures();
|
|
}
|
|
};
|
|
|
|
Transaction.prototype.inspect = function() {
|
|
return '<Transaction: ' + this.uncheckedSerialize() + '>';
|
|
};
|
|
|
|
Transaction.prototype.toBuffer = function() {
|
|
var writer = new BufferWriter();
|
|
return this.toBufferWriter(writer).toBuffer();
|
|
};
|
|
|
|
Transaction.prototype.toBufferWriter = function(writer) {
|
|
writer.writeInt32LE(this.version);
|
|
writer.writeVarintNum(this.inputs.length);
|
|
_.each(this.inputs, function(input) {
|
|
input.toBufferWriter(writer);
|
|
});
|
|
writer.writeVarintNum(this.outputs.length);
|
|
_.each(this.outputs, function(output) {
|
|
output.toBufferWriter(writer);
|
|
});
|
|
writer.writeUInt32LE(this.nLockTime);
|
|
return writer;
|
|
};
|
|
|
|
Transaction.prototype.fromBuffer = function(buffer) {
|
|
var reader = new BufferReader(buffer);
|
|
return this.fromBufferReader(reader);
|
|
};
|
|
|
|
Transaction.prototype.fromBufferReader = function(reader) {
|
|
$.checkArgument(!reader.finished(), 'No transaction data received');
|
|
var i, sizeTxIns, sizeTxOuts;
|
|
|
|
this.version = reader.readInt32LE();
|
|
sizeTxIns = reader.readVarintNum();
|
|
for (i = 0; i < sizeTxIns; i++) {
|
|
var input = Input.fromBufferReader(reader);
|
|
this.inputs.push(input);
|
|
}
|
|
sizeTxOuts = reader.readVarintNum();
|
|
for (i = 0; i < sizeTxOuts; i++) {
|
|
this.outputs.push(Output.fromBufferReader(reader));
|
|
}
|
|
this.nLockTime = reader.readUInt32LE();
|
|
return this;
|
|
};
|
|
|
|
Transaction.prototype.toObject = Transaction.prototype.toJSON = function toObject() {
|
|
var inputs = [];
|
|
this.inputs.forEach(function(input) {
|
|
inputs.push(input.toObject());
|
|
});
|
|
var outputs = [];
|
|
this.outputs.forEach(function(output) {
|
|
outputs.push(output.toObject());
|
|
});
|
|
var obj = {
|
|
hash: this.hash,
|
|
version: this.version,
|
|
inputs: inputs,
|
|
outputs: outputs,
|
|
nLockTime: this.nLockTime
|
|
};
|
|
if (this._changeScript) {
|
|
obj.changeScript = this._changeScript.toString();
|
|
}
|
|
if (!_.isUndefined(this._changeIndex)) {
|
|
obj.changeIndex = this._changeIndex;
|
|
}
|
|
if (!_.isUndefined(this._fee)) {
|
|
obj.fee = this._fee;
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
Transaction.prototype.fromObject = function fromObject(arg) {
|
|
/* jshint maxstatements: 20 */
|
|
$.checkArgument(_.isObject(arg) || arg instanceof Transaction);
|
|
var self = this;
|
|
var transaction;
|
|
if (arg instanceof Transaction) {
|
|
transaction = transaction.toObject();
|
|
} else {
|
|
transaction = arg;
|
|
}
|
|
_.each(transaction.inputs, function(input) {
|
|
if (!input.output || !input.output.script) {
|
|
self.uncheckedAddInput(new Input(input));
|
|
return;
|
|
}
|
|
var script = new Script(input.output.script);
|
|
var txin;
|
|
if (script.isPublicKeyHashOut()) {
|
|
txin = new Input.PublicKeyHash(input);
|
|
} else if (script.isScriptHashOut() && input.publicKeys && input.threshold) {
|
|
txin = new Input.MultiSigScriptHash(
|
|
input, input.publicKeys, input.threshold, input.signatures
|
|
);
|
|
} else if (script.isPublicKeyOut()) {
|
|
txin = new Input.PublicKey(input);
|
|
} else {
|
|
throw new errors.Transaction.Input.UnsupportedScript(input.output.script);
|
|
}
|
|
self.addInput(txin);
|
|
});
|
|
_.each(transaction.outputs, function(output) {
|
|
self.addOutput(new Output(output));
|
|
});
|
|
if (transaction.changeIndex) {
|
|
this._changeIndex = transaction.changeIndex;
|
|
}
|
|
if (transaction.changeScript) {
|
|
this._changeScript = new Script(transaction.changeScript);
|
|
}
|
|
if (transaction.fee) {
|
|
this._fee = transaction.fee;
|
|
}
|
|
this.nLockTime = transaction.nLockTime;
|
|
this.version = transaction.version;
|
|
this._checkConsistency(arg);
|
|
return this;
|
|
};
|
|
|
|
Transaction.prototype._checkConsistency = function(arg) {
|
|
if (!_.isUndefined(this._changeIndex)) {
|
|
$.checkState(this._changeScript, 'Change script is expected.');
|
|
$.checkState(this.outputs[this._changeIndex], 'Change index points to undefined output.');
|
|
$.checkState(this.outputs[this._changeIndex].script.toString() ===
|
|
this._changeScript.toString(), 'Change output has an unexpected script.');
|
|
}
|
|
if (arg && arg.hash) {
|
|
$.checkState(arg.hash === this.hash, 'Hash in object does not match transaction hash.');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Sets nLockTime so that transaction is not valid until the desired date(a
|
|
* timestamp in seconds since UNIX epoch is also accepted)
|
|
*
|
|
* @param {Date | Number} time
|
|
* @return {Transaction} this
|
|
*/
|
|
Transaction.prototype.lockUntilDate = function(time) {
|
|
$.checkArgument(time);
|
|
if (_.isNumber(time) && time < Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT) {
|
|
throw new errors.Transaction.LockTimeTooEarly();
|
|
}
|
|
if (_.isDate(time)) {
|
|
time = time.getTime() / 1000;
|
|
}
|
|
|
|
for (var i = 0; i < this.inputs.length; i++) {
|
|
if (this.inputs[i].sequenceNumber === Input.DEFAULT_SEQNUMBER){
|
|
this.inputs[i].sequenceNumber = Input.DEFAULT_LOCKTIME_SEQNUMBER;
|
|
}
|
|
}
|
|
|
|
this.nLockTime = time;
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Sets nLockTime so that transaction is not valid until the desired block
|
|
* height.
|
|
*
|
|
* @param {Number} height
|
|
* @return {Transaction} this
|
|
*/
|
|
Transaction.prototype.lockUntilBlockHeight = function(height) {
|
|
$.checkArgument(_.isNumber(height));
|
|
if (height >= Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT) {
|
|
throw new errors.Transaction.BlockHeightTooHigh();
|
|
}
|
|
if (height < 0) {
|
|
throw new errors.Transaction.NLockTimeOutOfRange();
|
|
}
|
|
|
|
for (var i = 0; i < this.inputs.length; i++) {
|
|
if (this.inputs[i].sequenceNumber === Input.DEFAULT_SEQNUMBER){
|
|
this.inputs[i].sequenceNumber = Input.DEFAULT_LOCKTIME_SEQNUMBER;
|
|
}
|
|
}
|
|
|
|
|
|
this.nLockTime = height;
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Returns a semantic version of the transaction's nLockTime.
|
|
* @return {Number|Date}
|
|
* If nLockTime is 0, it returns null,
|
|
* if it is < 500000000, it returns a block height (number)
|
|
* else it returns a Date object.
|
|
*/
|
|
Transaction.prototype.getLockTime = function() {
|
|
if (!this.nLockTime) {
|
|
return null;
|
|
}
|
|
if (this.nLockTime < Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT) {
|
|
return this.nLockTime;
|
|
}
|
|
return new Date(1000 * this.nLockTime);
|
|
};
|
|
|
|
Transaction.prototype.fromString = function(string) {
|
|
this.fromBuffer(new buffer.Buffer(string, 'hex'));
|
|
};
|
|
|
|
Transaction.prototype._newTransaction = function() {
|
|
this.version = CURRENT_VERSION;
|
|
this.nLockTime = DEFAULT_NLOCKTIME;
|
|
};
|
|
|
|
/* Transaction creation interface */
|
|
|
|
/**
|
|
* @typedef {Object} Transaction~fromObject
|
|
* @property {string} prevTxId
|
|
* @property {number} outputIndex
|
|
* @property {(Buffer|string|Script)} script
|
|
* @property {number} satoshis
|
|
*/
|
|
|
|
/**
|
|
* Add an input to this transaction. This is a high level interface
|
|
* to add an input, for more control, use @{link Transaction#addInput}.
|
|
*
|
|
* Can receive, as output information, the output of bitcoind's `listunspent` command,
|
|
* and a slightly fancier format recognized by bitcore:
|
|
*
|
|
* ```
|
|
* {
|
|
* address: 'mszYqVnqKoQx4jcTdJXxwKAissE3Jbrrc1',
|
|
* txId: 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458',
|
|
* outputIndex: 0,
|
|
* script: Script.empty(),
|
|
* satoshis: 1020000
|
|
* }
|
|
* ```
|
|
* Where `address` can be either a string or a bitcore Address object. The
|
|
* same is true for `script`, which can be a string or a bitcore Script.
|
|
*
|
|
* Beware that this resets all the signatures for inputs (in further versions,
|
|
* SIGHASH_SINGLE or SIGHASH_NONE signatures will not be reset).
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* var transaction = new Transaction();
|
|
*
|
|
* // From a pay to public key hash output from bitcoind's listunspent
|
|
* transaction.from({'txid': '0000...', vout: 0, amount: 0.1, scriptPubKey: 'OP_DUP ...'});
|
|
*
|
|
* // From a pay to public key hash output
|
|
* transaction.from({'txId': '0000...', outputIndex: 0, satoshis: 1000, script: 'OP_DUP ...'});
|
|
*
|
|
* // From a multisig P2SH output
|
|
* transaction.from({'txId': '0000...', inputIndex: 0, satoshis: 1000, script: '... OP_HASH'},
|
|
* ['03000...', '02000...'], 2);
|
|
* ```
|
|
*
|
|
* @param {(Array.<Transaction~fromObject>|Transaction~fromObject)} utxo
|
|
* @param {Array=} pubkeys
|
|
* @param {number=} threshold
|
|
*/
|
|
Transaction.prototype.from = function(utxo, pubkeys, threshold) {
|
|
if (_.isArray(utxo)) {
|
|
var self = this;
|
|
_.each(utxo, function(utxo) {
|
|
self.from(utxo, pubkeys, threshold);
|
|
});
|
|
return this;
|
|
}
|
|
var exists = _.some(this.inputs, function(input) {
|
|
// TODO: Maybe prevTxId should be a string? Or defined as read only property?
|
|
return input.prevTxId.toString('hex') === utxo.txId && input.outputIndex === utxo.outputIndex;
|
|
});
|
|
if (exists) {
|
|
return this;
|
|
}
|
|
if (pubkeys && threshold) {
|
|
this._fromMultisigUtxo(utxo, pubkeys, threshold);
|
|
} else {
|
|
this._fromNonP2SH(utxo);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
Transaction.prototype._fromNonP2SH = function(utxo) {
|
|
var clazz;
|
|
utxo = new UnspentOutput(utxo);
|
|
if (utxo.script.isPublicKeyHashOut()) {
|
|
clazz = PublicKeyHashInput;
|
|
} else if (utxo.script.isPublicKeyOut()) {
|
|
clazz = PublicKeyInput;
|
|
} else {
|
|
clazz = Input;
|
|
}
|
|
this.addInput(new clazz({
|
|
output: new Output({
|
|
script: utxo.script,
|
|
satoshis: utxo.satoshis
|
|
}),
|
|
prevTxId: utxo.txId,
|
|
outputIndex: utxo.outputIndex,
|
|
script: Script.empty()
|
|
}));
|
|
};
|
|
|
|
Transaction.prototype._fromMultisigUtxo = function(utxo, pubkeys, threshold) {
|
|
$.checkArgument(threshold <= pubkeys.length,
|
|
'Number of required signatures must be greater than the number of public keys');
|
|
var clazz;
|
|
utxo = new UnspentOutput(utxo);
|
|
if (utxo.script.isMultisigOut()) {
|
|
clazz = MultiSigInput;
|
|
} else if (utxo.script.isScriptHashOut()) {
|
|
clazz = MultiSigScriptHashInput;
|
|
} else {
|
|
throw new Error("@TODO");
|
|
}
|
|
this.addInput(new clazz({
|
|
output: new Output({
|
|
script: utxo.script,
|
|
satoshis: utxo.satoshis
|
|
}),
|
|
prevTxId: utxo.txId,
|
|
outputIndex: utxo.outputIndex,
|
|
script: Script.empty()
|
|
}, pubkeys, threshold));
|
|
};
|
|
|
|
/**
|
|
* Add an input to this transaction. The input must be an instance of the `Input` class.
|
|
* It should have information about the Output that it's spending, but if it's not already
|
|
* set, two additional parameters, `outputScript` and `satoshis` can be provided.
|
|
*
|
|
* @param {Input} input
|
|
* @param {String|Script} outputScript
|
|
* @param {number} satoshis
|
|
* @return Transaction this, for chaining
|
|
*/
|
|
Transaction.prototype.addInput = function(input, outputScript, satoshis) {
|
|
$.checkArgumentType(input, Input, 'input');
|
|
if (!input.output && (_.isUndefined(outputScript) || _.isUndefined(satoshis))) {
|
|
throw new errors.Transaction.NeedMoreInfo('Need information about the UTXO script and satoshis');
|
|
}
|
|
if (!input.output && outputScript && !_.isUndefined(satoshis)) {
|
|
outputScript = outputScript instanceof Script ? outputScript : new Script(outputScript);
|
|
$.checkArgumentType(satoshis, 'number', 'satoshis');
|
|
input.output = new Output({
|
|
script: outputScript,
|
|
satoshis: satoshis
|
|
});
|
|
}
|
|
return this.uncheckedAddInput(input);
|
|
};
|
|
|
|
/**
|
|
* Add an input to this transaction, without checking that the input has information about
|
|
* the output that it's spending.
|
|
*
|
|
* @param {Input} input
|
|
* @return Transaction this, for chaining
|
|
*/
|
|
Transaction.prototype.uncheckedAddInput = function(input) {
|
|
$.checkArgumentType(input, Input, 'input');
|
|
this.inputs.push(input);
|
|
this._inputAmount = undefined;
|
|
this._updateChangeOutput();
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Returns true if the transaction has enough info on all inputs to be correctly validated
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
Transaction.prototype.hasAllUtxoInfo = function() {
|
|
return _.every(this.inputs.map(function(input) {
|
|
return !!input.output;
|
|
}));
|
|
};
|
|
|
|
/**
|
|
* Manually set the fee for this transaction. Beware that this resets all the signatures
|
|
* for inputs (in further versions, SIGHASH_SINGLE or SIGHASH_NONE signatures will not
|
|
* be reset).
|
|
*
|
|
* @param {number} amount satoshis to be sent
|
|
* @return {Transaction} this, for chaining
|
|
*/
|
|
Transaction.prototype.fee = function(amount) {
|
|
$.checkArgument(_.isNumber(amount), 'amount must be a number');
|
|
this._fee = amount;
|
|
this._updateChangeOutput();
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Manually set the fee per KB for this transaction. Beware that this resets all the signatures
|
|
* for inputs (in further versions, SIGHASH_SINGLE or SIGHASH_NONE signatures will not
|
|
* be reset).
|
|
*
|
|
* @param {number} amount satoshis per KB to be sent
|
|
* @return {Transaction} this, for chaining
|
|
*/
|
|
Transaction.prototype.feePerKb = function(amount) {
|
|
$.checkArgument(_.isNumber(amount), 'amount must be a number');
|
|
this._feePerKb = amount;
|
|
this._updateChangeOutput();
|
|
return this;
|
|
};
|
|
|
|
/* Output management */
|
|
|
|
/**
|
|
* Set the change address for this transaction
|
|
*
|
|
* Beware that this resets all the signatures for inputs (in further versions,
|
|
* SIGHASH_SINGLE or SIGHASH_NONE signatures will not be reset).
|
|
*
|
|
* @param {Address} address An address for change to be sent to.
|
|
* @return {Transaction} this, for chaining
|
|
*/
|
|
Transaction.prototype.change = function(address) {
|
|
$.checkArgument(address, 'address is required');
|
|
this._changeScript = Script.fromAddress(address);
|
|
this._updateChangeOutput();
|
|
return this;
|
|
};
|
|
|
|
|
|
/**
|
|
* @return {Output} change output, if it exists
|
|
*/
|
|
Transaction.prototype.getChangeOutput = function() {
|
|
if (!_.isUndefined(this._changeIndex)) {
|
|
return this.outputs[this._changeIndex];
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* @typedef {Object} Transaction~toObject
|
|
* @property {(string|Address)} address
|
|
* @property {number} satoshis
|
|
*/
|
|
|
|
/**
|
|
* Add an output to the transaction.
|
|
*
|
|
* Beware that this resets all the signatures for inputs (in further versions,
|
|
* SIGHASH_SINGLE or SIGHASH_NONE signatures will not be reset).
|
|
*
|
|
* @param {(string|Address|Array.<Transaction~toObject>)} address
|
|
* @param {number} amount in satoshis
|
|
* @return {Transaction} this, for chaining
|
|
*/
|
|
Transaction.prototype.to = function(address, amount) {
|
|
if (_.isArray(address)) {
|
|
var self = this;
|
|
_.each(address, function(to) {
|
|
self.to(to.address, to.satoshis);
|
|
});
|
|
return this;
|
|
}
|
|
|
|
$.checkArgument(
|
|
JSUtil.isNaturalNumber(amount),
|
|
'Amount is expected to be a positive integer'
|
|
);
|
|
this.addOutput(new Output({
|
|
script: Script(new Address(address)),
|
|
satoshis: amount
|
|
}));
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Add an OP_RETURN output to the transaction.
|
|
*
|
|
* Beware that this resets all the signatures for inputs (in further versions,
|
|
* SIGHASH_SINGLE or SIGHASH_NONE signatures will not be reset).
|
|
*
|
|
* @param {Buffer|string} value the data to be stored in the OP_RETURN output.
|
|
* In case of a string, the UTF-8 representation will be stored
|
|
* @return {Transaction} this, for chaining
|
|
*/
|
|
Transaction.prototype.addData = function(value) {
|
|
this.addOutput(new Output({
|
|
script: Script.buildDataOut(value),
|
|
satoshis: 0
|
|
}));
|
|
return this;
|
|
};
|
|
|
|
|
|
/**
|
|
* Add an output to the transaction.
|
|
*
|
|
* @param {Output} output the output to add.
|
|
* @return {Transaction} this, for chaining
|
|
*/
|
|
Transaction.prototype.addOutput = function(output) {
|
|
$.checkArgumentType(output, Output, 'output');
|
|
this._addOutput(output);
|
|
this._updateChangeOutput();
|
|
return this;
|
|
};
|
|
|
|
|
|
/**
|
|
* Remove all outputs from the transaction.
|
|
*
|
|
* @return {Transaction} this, for chaining
|
|
*/
|
|
Transaction.prototype.clearOutputs = function() {
|
|
this.outputs = [];
|
|
this._clearSignatures();
|
|
this._outputAmount = undefined;
|
|
this._changeIndex = undefined;
|
|
this._updateChangeOutput();
|
|
return this;
|
|
};
|
|
|
|
|
|
Transaction.prototype._addOutput = function(output) {
|
|
this.outputs.push(output);
|
|
this._outputAmount = undefined;
|
|
};
|
|
|
|
|
|
/**
|
|
* Calculates or gets the total output amount in satoshis
|
|
*
|
|
* @return {Number} the transaction total output amount
|
|
*/
|
|
Transaction.prototype._getOutputAmount = function() {
|
|
if (_.isUndefined(this._outputAmount)) {
|
|
var self = this;
|
|
this._outputAmount = 0;
|
|
_.each(this.outputs, function(output) {
|
|
self._outputAmount += output.satoshis;
|
|
});
|
|
}
|
|
return this._outputAmount;
|
|
};
|
|
|
|
|
|
/**
|
|
* Calculates or gets the total input amount in satoshis
|
|
*
|
|
* @return {Number} the transaction total input amount
|
|
*/
|
|
Transaction.prototype._getInputAmount = function() {
|
|
if (_.isUndefined(this._inputAmount)) {
|
|
var self = this;
|
|
this._inputAmount = 0;
|
|
_.each(this.inputs, function(input) {
|
|
if (_.isUndefined(input.output)) {
|
|
throw new errors.Transaction.Input.MissingPreviousOutput();
|
|
}
|
|
self._inputAmount += input.output.satoshis;
|
|
});
|
|
}
|
|
return this._inputAmount;
|
|
};
|
|
|
|
Transaction.prototype._updateChangeOutput = function() {
|
|
if (!this._changeScript) {
|
|
return;
|
|
}
|
|
this._clearSignatures();
|
|
if (!_.isUndefined(this._changeIndex)) {
|
|
this._removeOutput(this._changeIndex);
|
|
}
|
|
var available = this._getUnspentValue();
|
|
var fee = this.getFee();
|
|
var changeAmount = available - fee;
|
|
if (changeAmount > 0) {
|
|
this._changeIndex = this.outputs.length;
|
|
this._addOutput(new Output({
|
|
script: this._changeScript,
|
|
satoshis: changeAmount
|
|
}));
|
|
} else {
|
|
this._changeIndex = undefined;
|
|
}
|
|
};
|
|
/**
|
|
* Calculates the fee of the transaction.
|
|
*
|
|
* If there's a fixed fee set, return that.
|
|
*
|
|
* If there is no change output set, the fee is the
|
|
* total value of the outputs minus inputs. Note that
|
|
* a serialized transaction only specifies the value
|
|
* of its outputs. (The value of inputs are recorded
|
|
* in the previous transaction outputs being spent.)
|
|
* This method therefore raises a "MissingPreviousOutput"
|
|
* error when called on a serialized transaction.
|
|
*
|
|
* If there's no fee set and no change address,
|
|
* estimate the fee based on size.
|
|
*
|
|
* @return {Number} fee of this transaction in satoshis
|
|
*/
|
|
Transaction.prototype.getFee = function() {
|
|
if (this.isCoinbase()) {
|
|
return 0;
|
|
}
|
|
if (!_.isUndefined(this._fee)) {
|
|
return this._fee;
|
|
}
|
|
// if no change output is set, fees should equal all the unspent amount
|
|
if (!this._changeScript) {
|
|
return this._getUnspentValue();
|
|
}
|
|
return this._estimateFee();
|
|
};
|
|
|
|
/**
|
|
* Estimates fee from serialized transaction size in bytes.
|
|
*/
|
|
Transaction.prototype._estimateFee = function() {
|
|
var estimatedSize = this._estimateSize();
|
|
var available = this._getUnspentValue();
|
|
return Transaction._estimateFee(estimatedSize, available, this._feePerKb);
|
|
};
|
|
|
|
Transaction.prototype._getUnspentValue = function() {
|
|
return this._getInputAmount() - this._getOutputAmount();
|
|
};
|
|
|
|
Transaction.prototype._clearSignatures = function() {
|
|
_.each(this.inputs, function(input) {
|
|
input.clearSignatures();
|
|
});
|
|
};
|
|
|
|
Transaction._estimateFee = function(size, amountAvailable, feePerKb) {
|
|
var fee = Math.ceil(size / 1000) * (feePerKb || Transaction.FEE_PER_KB);
|
|
if (amountAvailable > fee) {
|
|
size += Transaction.CHANGE_OUTPUT_MAX_SIZE;
|
|
}
|
|
return Math.ceil(size / 1000) * (feePerKb || Transaction.FEE_PER_KB);
|
|
};
|
|
|
|
Transaction.prototype._estimateSize = function() {
|
|
var result = Transaction.MAXIMUM_EXTRA_SIZE;
|
|
_.each(this.inputs, function(input) {
|
|
result += input._estimateSize();
|
|
});
|
|
_.each(this.outputs, function(output) {
|
|
result += output.script.toBuffer().length + 9;
|
|
});
|
|
return result;
|
|
};
|
|
|
|
Transaction.prototype._removeOutput = function(index) {
|
|
var output = this.outputs[index];
|
|
this.outputs = _.without(this.outputs, output);
|
|
this._outputAmount = undefined;
|
|
};
|
|
|
|
Transaction.prototype.removeOutput = function(index) {
|
|
this._removeOutput(index);
|
|
this._updateChangeOutput();
|
|
};
|
|
|
|
/**
|
|
* Sort a transaction's inputs and outputs according to BIP69
|
|
*
|
|
* @see {https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki}
|
|
* @return {Transaction} this
|
|
*/
|
|
Transaction.prototype.sort = function() {
|
|
this.sortInputs(function(inputs) {
|
|
var copy = Array.prototype.concat.apply([], inputs);
|
|
copy.sort(function(first, second) {
|
|
return compare(first.prevTxId, second.prevTxId)
|
|
|| first.outputIndex - second.outputIndex;
|
|
});
|
|
return copy;
|
|
});
|
|
this.sortOutputs(function(outputs) {
|
|
var copy = Array.prototype.concat.apply([], outputs);
|
|
copy.sort(function(first, second) {
|
|
return first.satoshis - second.satoshis
|
|
|| compare(first.script.toBuffer(), second.script.toBuffer());
|
|
});
|
|
return copy;
|
|
});
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Randomize this transaction's outputs ordering. The shuffling algorithm is a
|
|
* version of the Fisher-Yates shuffle, provided by lodash's _.shuffle().
|
|
*
|
|
* @return {Transaction} this
|
|
*/
|
|
Transaction.prototype.shuffleOutputs = function() {
|
|
return this.sortOutputs(_.shuffle);
|
|
};
|
|
|
|
/**
|
|
* Sort this transaction's outputs, according to a given sorting function that
|
|
* takes an array as argument and returns a new array, with the same elements
|
|
* but with a different order. The argument function MUST NOT modify the order
|
|
* of the original array
|
|
*
|
|
* @param {Function} sortingFunction
|
|
* @return {Transaction} this
|
|
*/
|
|
Transaction.prototype.sortOutputs = function(sortingFunction) {
|
|
var outs = sortingFunction(this.outputs);
|
|
return this._newOutputOrder(outs);
|
|
};
|
|
|
|
/**
|
|
* Sort this transaction's inputs, according to a given sorting function that
|
|
* takes an array as argument and returns a new array, with the same elements
|
|
* but with a different order.
|
|
*
|
|
* @param {Function} sortingFunction
|
|
* @return {Transaction} this
|
|
*/
|
|
Transaction.prototype.sortInputs = function(sortingFunction) {
|
|
this.inputs = sortingFunction(this.inputs);
|
|
this._clearSignatures();
|
|
return this;
|
|
};
|
|
|
|
Transaction.prototype._newOutputOrder = function(newOutputs) {
|
|
var isInvalidSorting = (this.outputs.length !== newOutputs.length ||
|
|
_.difference(this.outputs, newOutputs).length !== 0);
|
|
if (isInvalidSorting) {
|
|
throw new errors.Transaction.InvalidSorting();
|
|
}
|
|
|
|
if (!_.isUndefined(this._changeIndex)) {
|
|
var changeOutput = this.outputs[this._changeIndex];
|
|
this._changeIndex = _.findIndex(newOutputs, changeOutput);
|
|
}
|
|
|
|
this.outputs = newOutputs;
|
|
return this;
|
|
};
|
|
|
|
Transaction.prototype.removeInput = function(txId, outputIndex) {
|
|
var index;
|
|
if (!outputIndex && _.isNumber(txId)) {
|
|
index = txId;
|
|
} else {
|
|
index = _.findIndex(this.inputs, function(input) {
|
|
return input.prevTxId.toString('hex') === txId && input.outputIndex === outputIndex;
|
|
});
|
|
}
|
|
if (index < 0 || index >= this.inputs.length) {
|
|
throw new errors.Transaction.InvalidIndex(index, this.inputs.length);
|
|
}
|
|
var input = this.inputs[index];
|
|
this.inputs = _.without(this.inputs, input);
|
|
this._inputAmount = undefined;
|
|
this._updateChangeOutput();
|
|
};
|
|
|
|
/* Signature handling */
|
|
|
|
/**
|
|
* Sign the transaction using one or more private keys.
|
|
*
|
|
* It tries to sign each input, verifying that the signature will be valid
|
|
* (matches a public key).
|
|
*
|
|
* @param {Array|String|PrivateKey} privateKey
|
|
* @param {number} sigtype
|
|
* @return {Transaction} this, for chaining
|
|
*/
|
|
Transaction.prototype.sign = function(privateKey, sigtype) {
|
|
$.checkState(this.hasAllUtxoInfo(), 'Not all utxo information is available to sign the transaction.');
|
|
var self = this;
|
|
if (_.isArray(privateKey)) {
|
|
_.each(privateKey, function(privateKey) {
|
|
self.sign(privateKey, sigtype);
|
|
});
|
|
return this;
|
|
}
|
|
_.each(this.getSignatures(privateKey, sigtype), function(signature) {
|
|
self.applySignature(signature);
|
|
});
|
|
return this;
|
|
};
|
|
|
|
Transaction.prototype.getSignatures = function(privKey, sigtype) {
|
|
privKey = new PrivateKey(privKey);
|
|
sigtype = sigtype || Signature.SIGHASH_ALL;
|
|
var transaction = this;
|
|
var results = [];
|
|
var hashData = Hash.sha256ripemd160(privKey.publicKey.toBuffer());
|
|
_.each(this.inputs, function forEachInput(input, index) {
|
|
_.each(input.getSignatures(transaction, privKey, index, sigtype, hashData), function(signature) {
|
|
results.push(signature);
|
|
});
|
|
});
|
|
return results;
|
|
};
|
|
|
|
/**
|
|
* Add a signature to the transaction
|
|
*
|
|
* @param {Object} signature
|
|
* @param {number} signature.inputIndex
|
|
* @param {number} signature.sigtype
|
|
* @param {PublicKey} signature.publicKey
|
|
* @param {Signature} signature.signature
|
|
* @return {Transaction} this, for chaining
|
|
*/
|
|
Transaction.prototype.applySignature = function(signature) {
|
|
this.inputs[signature.inputIndex].addSignature(this, signature);
|
|
return this;
|
|
};
|
|
|
|
Transaction.prototype.isFullySigned = function() {
|
|
_.each(this.inputs, function(input) {
|
|
if (input.isFullySigned === Input.prototype.isFullySigned) {
|
|
throw new errors.Transaction.UnableToVerifySignature(
|
|
'Unrecognized script kind, or not enough information to execute script.' +
|
|
'This usually happens when creating a transaction from a serialized transaction'
|
|
);
|
|
}
|
|
});
|
|
return _.every(_.map(this.inputs, function(input) {
|
|
return input.isFullySigned();
|
|
}));
|
|
};
|
|
|
|
Transaction.prototype.isValidSignature = function(signature) {
|
|
var self = this;
|
|
if (this.inputs[signature.inputIndex].isValidSignature === Input.prototype.isValidSignature) {
|
|
throw new errors.Transaction.UnableToVerifySignature(
|
|
'Unrecognized script kind, or not enough information to execute script.' +
|
|
'This usually happens when creating a transaction from a serialized transaction'
|
|
);
|
|
}
|
|
return this.inputs[signature.inputIndex].isValidSignature(self, signature);
|
|
};
|
|
|
|
/**
|
|
* @returns {bool} whether the signature is valid for this transaction input
|
|
*/
|
|
Transaction.prototype.verifySignature = function(sig, pubkey, nin, subscript) {
|
|
return Sighash.verify(this, sig, pubkey, nin, subscript);
|
|
};
|
|
|
|
/**
|
|
* Check that a transaction passes basic sanity tests. If not, return a string
|
|
* describing the error. This function contains the same logic as
|
|
* CheckTransaction in bitcoin core.
|
|
*/
|
|
Transaction.prototype.verify = function() {
|
|
// Basic checks that don't depend on any context
|
|
if (this.inputs.length === 0) {
|
|
return 'transaction txins empty';
|
|
}
|
|
|
|
if (this.outputs.length === 0) {
|
|
return 'transaction txouts empty';
|
|
}
|
|
|
|
// Check for negative or overflow output values
|
|
var valueoutbn = new BN(0);
|
|
for (var i = 0; i < this.outputs.length; i++) {
|
|
var txout = this.outputs[i];
|
|
|
|
if (txout.invalidSatoshis()) {
|
|
return 'transaction txout ' + i + ' satoshis is invalid';
|
|
}
|
|
if (txout._satoshisBN.gt(new BN(Transaction.MAX_MONEY, 10))) {
|
|
return 'transaction txout ' + i + ' greater than MAX_MONEY';
|
|
}
|
|
valueoutbn = valueoutbn.add(txout._satoshisBN);
|
|
if (valueoutbn.gt(new BN(Transaction.MAX_MONEY))) {
|
|
return 'transaction txout ' + i + ' total output greater than MAX_MONEY';
|
|
}
|
|
}
|
|
|
|
// Size limits
|
|
if (this.toBuffer().length > MAX_BLOCK_SIZE) {
|
|
return 'transaction over the maximum block size';
|
|
}
|
|
|
|
// Check for duplicate inputs
|
|
var txinmap = {};
|
|
for (i = 0; i < this.inputs.length; i++) {
|
|
var txin = this.inputs[i];
|
|
|
|
var inputid = txin.prevTxId + ':' + txin.outputIndex;
|
|
if (!_.isUndefined(txinmap[inputid])) {
|
|
return 'transaction input ' + i + ' duplicate input';
|
|
}
|
|
txinmap[inputid] = true;
|
|
}
|
|
|
|
var isCoinbase = this.isCoinbase();
|
|
if (isCoinbase) {
|
|
var buf = this.inputs[0]._scriptBuffer;
|
|
if (buf.length < 2 || buf.length > 100) {
|
|
return 'coinbase transaction script size invalid';
|
|
}
|
|
} else {
|
|
for (i = 0; i < this.inputs.length; i++) {
|
|
if (this.inputs[i].isNull()) {
|
|
return 'transaction input ' + i + ' has null input';
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Analogous to bitcoind's IsCoinBase function in transaction.h
|
|
*/
|
|
Transaction.prototype.isCoinbase = function() {
|
|
return (this.inputs.length === 1 && this.inputs[0].isNull());
|
|
};
|
|
|
|
/**
|
|
* Determines if this transaction can be replaced in the mempool with another
|
|
* transaction that provides a sufficiently higher fee (RBF).
|
|
*/
|
|
Transaction.prototype.isRBF = function() {
|
|
for (var i = 0; i < this.inputs.length; i++) {
|
|
var input = this.inputs[i];
|
|
if (input.sequenceNumber < Input.MAXINT - 1) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Enable this transaction to be replaced in the mempool (RBF) if a transaction
|
|
* includes a sufficiently higher fee. It will set the sequenceNumber to
|
|
* DEFAULT_RBF_SEQNUMBER for all inputs if the sequence number does not
|
|
* already enable RBF.
|
|
*/
|
|
Transaction.prototype.enableRBF = function() {
|
|
for (var i = 0; i < this.inputs.length; i++) {
|
|
var input = this.inputs[i];
|
|
if (input.sequenceNumber >= Input.MAXINT - 1) {
|
|
input.sequenceNumber = Input.DEFAULT_RBF_SEQNUMBER;
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
module.exports = Transaction;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"../address":1,"../crypto/bn":6,"../crypto/hash":8,"../crypto/signature":11,"../encoding/bufferreader":14,"../encoding/bufferwriter":15,"../errors":17,"../privatekey":23,"../script":25,"../util/buffer":42,"../util/js":43,"../util/preconditions":44,"./input":29,"./output":35,"./sighash":36,"./unspentoutput":39,"buffer":47,"buffer-compare":284,"lodash":319}],39:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var $ = require('../util/preconditions');
|
|
var JSUtil = require('../util/js');
|
|
|
|
var Script = require('../script');
|
|
var Address = require('../address');
|
|
var Unit = require('../unit');
|
|
|
|
/**
|
|
* Represents an unspent output information: its script, associated amount and address,
|
|
* transaction id and output index.
|
|
*
|
|
* @constructor
|
|
* @param {object} data
|
|
* @param {string} data.txid the previous transaction id
|
|
* @param {string=} data.txId alias for `txid`
|
|
* @param {number} data.vout the index in the transaction
|
|
* @param {number=} data.outputIndex alias for `vout`
|
|
* @param {string|Script} data.scriptPubKey the script that must be resolved to release the funds
|
|
* @param {string|Script=} data.script alias for `scriptPubKey`
|
|
* @param {number} data.amount amount of bitcoins associated
|
|
* @param {number=} data.satoshis alias for `amount`, but expressed in satoshis (1 BTC = 1e8 satoshis)
|
|
* @param {string|Address=} data.address the associated address to the script, if provided
|
|
*/
|
|
function UnspentOutput(data) {
|
|
/* jshint maxcomplexity: 20 */
|
|
/* jshint maxstatements: 20 */
|
|
if (!(this instanceof UnspentOutput)) {
|
|
return new UnspentOutput(data);
|
|
}
|
|
$.checkArgument(_.isObject(data), 'Must provide an object from where to extract data');
|
|
var address = data.address ? new Address(data.address) : undefined;
|
|
var txId = data.txid ? data.txid : data.txId;
|
|
if (!txId || !JSUtil.isHexaString(txId) || txId.length > 64) {
|
|
// TODO: Use the errors library
|
|
throw new Error('Invalid TXID in object', data);
|
|
}
|
|
var outputIndex = _.isUndefined(data.vout) ? data.outputIndex : data.vout;
|
|
if (!_.isNumber(outputIndex)) {
|
|
throw new Error('Invalid outputIndex, received ' + outputIndex);
|
|
}
|
|
$.checkArgument(!_.isUndefined(data.scriptPubKey) || !_.isUndefined(data.script),
|
|
'Must provide the scriptPubKey for that output!');
|
|
var script = new Script(data.scriptPubKey || data.script);
|
|
$.checkArgument(!_.isUndefined(data.amount) || !_.isUndefined(data.satoshis),
|
|
'Must provide an amount for the output');
|
|
var amount = !_.isUndefined(data.amount) ? new Unit.fromBTC(data.amount).toSatoshis() : data.satoshis;
|
|
$.checkArgument(_.isNumber(amount), 'Amount must be a number');
|
|
JSUtil.defineImmutable(this, {
|
|
address: address,
|
|
txId: txId,
|
|
outputIndex: outputIndex,
|
|
script: script,
|
|
satoshis: amount
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Provide an informative output when displaying this object in the console
|
|
* @returns string
|
|
*/
|
|
UnspentOutput.prototype.inspect = function() {
|
|
return '<UnspentOutput: ' + this.txId + ':' + this.outputIndex +
|
|
', satoshis: ' + this.satoshis + ', address: ' + this.address + '>';
|
|
};
|
|
|
|
/**
|
|
* String representation: just "txid:index"
|
|
* @returns string
|
|
*/
|
|
UnspentOutput.prototype.toString = function() {
|
|
return this.txId + ':' + this.outputIndex;
|
|
};
|
|
|
|
/**
|
|
* Deserialize an UnspentOutput from an object
|
|
* @param {object|string} data
|
|
* @return UnspentOutput
|
|
*/
|
|
UnspentOutput.fromObject = function(data) {
|
|
return new UnspentOutput(data);
|
|
};
|
|
|
|
/**
|
|
* Returns a plain object (no prototype or methods) with the associated info for this output
|
|
* @return {object}
|
|
*/
|
|
UnspentOutput.prototype.toObject = UnspentOutput.prototype.toJSON = function toObject() {
|
|
return {
|
|
address: this.address ? this.address.toString() : undefined,
|
|
txid: this.txId,
|
|
vout: this.outputIndex,
|
|
scriptPubKey: this.script.toBuffer().toString('hex'),
|
|
amount: Unit.fromSatoshis(this.satoshis).toBTC()
|
|
};
|
|
};
|
|
|
|
module.exports = UnspentOutput;
|
|
|
|
},{"../address":1,"../script":25,"../unit":40,"../util/js":43,"../util/preconditions":44,"lodash":319}],40:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
|
|
var errors = require('./errors');
|
|
var $ = require('./util/preconditions');
|
|
|
|
var UNITS = {
|
|
'BTC' : [1e8, 8],
|
|
'mBTC' : [1e5, 5],
|
|
'uBTC' : [1e2, 2],
|
|
'bits' : [1e2, 2],
|
|
'satoshis' : [1, 0]
|
|
};
|
|
|
|
/**
|
|
* Utility for handling and converting bitcoins units. The supported units are
|
|
* BTC, mBTC, bits (also named uBTC) and satoshis. A unit instance can be created with an
|
|
* amount and a unit code, or alternatively using static methods like {fromBTC}.
|
|
* It also allows to be created from a fiat amount and the exchange rate, or
|
|
* alternatively using the {fromFiat} static method.
|
|
* You can consult for different representation of a unit instance using it's
|
|
* {to} method, the fixed unit methods like {toSatoshis} or alternatively using
|
|
* the unit accessors. It also can be converted to a fiat amount by providing the
|
|
* corresponding BTC/fiat exchange rate.
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
* var sats = Unit.fromBTC(1.3).toSatoshis();
|
|
* var mili = Unit.fromBits(1.3).to(Unit.mBTC);
|
|
* var bits = Unit.fromFiat(1.3, 350).bits;
|
|
* var btc = new Unit(1.3, Unit.bits).BTC;
|
|
* ```
|
|
*
|
|
* @param {Number} amount - The amount to be represented
|
|
* @param {String|Number} code - The unit of the amount or the exchange rate
|
|
* @returns {Unit} A new instance of an Unit
|
|
* @constructor
|
|
*/
|
|
function Unit(amount, code) {
|
|
if (!(this instanceof Unit)) {
|
|
return new Unit(amount, code);
|
|
}
|
|
|
|
// convert fiat to BTC
|
|
if (_.isNumber(code)) {
|
|
if (code <= 0) {
|
|
throw new errors.Unit.InvalidRate(code);
|
|
}
|
|
amount = amount / code;
|
|
code = Unit.BTC;
|
|
}
|
|
|
|
this._value = this._from(amount, code);
|
|
|
|
var self = this;
|
|
var defineAccesor = function(key) {
|
|
Object.defineProperty(self, key, {
|
|
get: function() { return self.to(key); },
|
|
enumerable: true,
|
|
});
|
|
};
|
|
|
|
Object.keys(UNITS).forEach(defineAccesor);
|
|
}
|
|
|
|
Object.keys(UNITS).forEach(function(key) {
|
|
Unit[key] = key;
|
|
});
|
|
|
|
/**
|
|
* Returns a Unit instance created from JSON string or object
|
|
*
|
|
* @param {String|Object} json - JSON with keys: amount and code
|
|
* @returns {Unit} A Unit instance
|
|
*/
|
|
Unit.fromObject = function fromObject(data){
|
|
$.checkArgument(_.isObject(data), 'Argument is expected to be an object');
|
|
return new Unit(data.amount, data.code);
|
|
};
|
|
|
|
/**
|
|
* Returns a Unit instance created from an amount in BTC
|
|
*
|
|
* @param {Number} amount - The amount in BTC
|
|
* @returns {Unit} A Unit instance
|
|
*/
|
|
Unit.fromBTC = function(amount) {
|
|
return new Unit(amount, Unit.BTC);
|
|
};
|
|
|
|
/**
|
|
* Returns a Unit instance created from an amount in mBTC
|
|
*
|
|
* @param {Number} amount - The amount in mBTC
|
|
* @returns {Unit} A Unit instance
|
|
*/
|
|
Unit.fromMillis = Unit.fromMilis = function(amount) {
|
|
return new Unit(amount, Unit.mBTC);
|
|
};
|
|
|
|
/**
|
|
* Returns a Unit instance created from an amount in bits
|
|
*
|
|
* @param {Number} amount - The amount in bits
|
|
* @returns {Unit} A Unit instance
|
|
*/
|
|
Unit.fromMicros = Unit.fromBits = function(amount) {
|
|
return new Unit(amount, Unit.bits);
|
|
};
|
|
|
|
/**
|
|
* Returns a Unit instance created from an amount in satoshis
|
|
*
|
|
* @param {Number} amount - The amount in satoshis
|
|
* @returns {Unit} A Unit instance
|
|
*/
|
|
Unit.fromSatoshis = function(amount) {
|
|
return new Unit(amount, Unit.satoshis);
|
|
};
|
|
|
|
/**
|
|
* Returns a Unit instance created from a fiat amount and exchange rate.
|
|
*
|
|
* @param {Number} amount - The amount in fiat
|
|
* @param {Number} rate - The exchange rate BTC/fiat
|
|
* @returns {Unit} A Unit instance
|
|
*/
|
|
Unit.fromFiat = function(amount, rate) {
|
|
return new Unit(amount, rate);
|
|
};
|
|
|
|
Unit.prototype._from = function(amount, code) {
|
|
if (!UNITS[code]) {
|
|
throw new errors.Unit.UnknownCode(code);
|
|
}
|
|
return parseInt((amount * UNITS[code][0]).toFixed());
|
|
};
|
|
|
|
/**
|
|
* Returns the value represented in the specified unit
|
|
*
|
|
* @param {String|Number} code - The unit code or exchange rate
|
|
* @returns {Number} The converted value
|
|
*/
|
|
Unit.prototype.to = function(code) {
|
|
if (_.isNumber(code)) {
|
|
if (code <= 0) {
|
|
throw new errors.Unit.InvalidRate(code);
|
|
}
|
|
return parseFloat((this.BTC * code).toFixed(2));
|
|
}
|
|
|
|
if (!UNITS[code]) {
|
|
throw new errors.Unit.UnknownCode(code);
|
|
}
|
|
|
|
var value = this._value / UNITS[code][0];
|
|
return parseFloat(value.toFixed(UNITS[code][1]));
|
|
};
|
|
|
|
/**
|
|
* Returns the value represented in BTC
|
|
*
|
|
* @returns {Number} The value converted to BTC
|
|
*/
|
|
Unit.prototype.toBTC = function() {
|
|
return this.to(Unit.BTC);
|
|
};
|
|
|
|
/**
|
|
* Returns the value represented in mBTC
|
|
*
|
|
* @returns {Number} The value converted to mBTC
|
|
*/
|
|
Unit.prototype.toMillis = Unit.prototype.toMilis = function() {
|
|
return this.to(Unit.mBTC);
|
|
};
|
|
|
|
/**
|
|
* Returns the value represented in bits
|
|
*
|
|
* @returns {Number} The value converted to bits
|
|
*/
|
|
Unit.prototype.toMicros = Unit.prototype.toBits = function() {
|
|
return this.to(Unit.bits);
|
|
};
|
|
|
|
/**
|
|
* Returns the value represented in satoshis
|
|
*
|
|
* @returns {Number} The value converted to satoshis
|
|
*/
|
|
Unit.prototype.toSatoshis = function() {
|
|
return this.to(Unit.satoshis);
|
|
};
|
|
|
|
/**
|
|
* Returns the value represented in fiat
|
|
*
|
|
* @param {string} rate - The exchange rate between BTC/currency
|
|
* @returns {Number} The value converted to satoshis
|
|
*/
|
|
Unit.prototype.atRate = function(rate) {
|
|
return this.to(rate);
|
|
};
|
|
|
|
/**
|
|
* Returns a the string representation of the value in satoshis
|
|
*
|
|
* @returns {string} the value in satoshis
|
|
*/
|
|
Unit.prototype.toString = function() {
|
|
return this.satoshis + ' satoshis';
|
|
};
|
|
|
|
/**
|
|
* Returns a plain object representation of the Unit
|
|
*
|
|
* @returns {Object} An object with the keys: amount and code
|
|
*/
|
|
Unit.prototype.toObject = Unit.prototype.toJSON = function toObject() {
|
|
return {
|
|
amount: this.BTC,
|
|
code: Unit.BTC
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Returns a string formatted for the console
|
|
*
|
|
* @returns {string} the value in satoshis
|
|
*/
|
|
Unit.prototype.inspect = function() {
|
|
return '<Unit: ' + this.toString() + '>';
|
|
};
|
|
|
|
module.exports = Unit;
|
|
|
|
},{"./errors":17,"./util/preconditions":44,"lodash":319}],41:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var URL = require('url');
|
|
|
|
var Address = require('./address');
|
|
var Unit = require('./unit');
|
|
|
|
/**
|
|
* Bitcore URI
|
|
*
|
|
* Instantiate an URI from a bitcoin URI String or an Object. An URI instance
|
|
* can be created with a bitcoin uri string or an object. All instances of
|
|
* URI are valid, the static method isValid allows checking before instantiation.
|
|
*
|
|
* All standard parameters can be found as members of the class, the address
|
|
* is represented using an {Address} instance and the amount is represented in
|
|
* satoshis. Any other non-standard parameters can be found under the extra member.
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
*
|
|
* var uri = new URI('bitcoin:12A1MyfXbW6RhdRAZEqofac5jCQQjwEPBu?amount=1.2');
|
|
* console.log(uri.address, uri.amount);
|
|
* ```
|
|
*
|
|
* @param {string|Object} data - A bitcoin URI string or an Object
|
|
* @param {Array.<string>=} knownParams - Required non-standard params
|
|
* @throws {TypeError} Invalid bitcoin address
|
|
* @throws {TypeError} Invalid amount
|
|
* @throws {Error} Unknown required argument
|
|
* @returns {URI} A new valid and frozen instance of URI
|
|
* @constructor
|
|
*/
|
|
var URI = function(data, knownParams) {
|
|
if (!(this instanceof URI)) {
|
|
return new URI(data, knownParams);
|
|
}
|
|
|
|
this.extras = {};
|
|
this.knownParams = knownParams || [];
|
|
this.address = this.network = this.amount = this.message = null;
|
|
|
|
if (typeof(data) === 'string') {
|
|
var params = URI.parse(data);
|
|
if (params.amount) {
|
|
params.amount = this._parseAmount(params.amount);
|
|
}
|
|
this._fromObject(params);
|
|
} else if (typeof(data) === 'object') {
|
|
this._fromObject(data);
|
|
} else {
|
|
throw new TypeError('Unrecognized data format.');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Instantiate a URI from a String
|
|
*
|
|
* @param {string} str - JSON string or object of the URI
|
|
* @returns {URI} A new instance of a URI
|
|
*/
|
|
URI.fromString = function fromString(str) {
|
|
if (typeof(str) !== 'string') {
|
|
throw new TypeError('Expected a string');
|
|
}
|
|
return new URI(str);
|
|
};
|
|
|
|
/**
|
|
* Instantiate a URI from an Object
|
|
*
|
|
* @param {Object} data - object of the URI
|
|
* @returns {URI} A new instance of a URI
|
|
*/
|
|
URI.fromObject = function fromObject(json) {
|
|
return new URI(json);
|
|
};
|
|
|
|
/**
|
|
* Check if an bitcoin URI string is valid
|
|
*
|
|
* @example
|
|
* ```javascript
|
|
*
|
|
* var valid = URI.isValid('bitcoin:12A1MyfXbW6RhdRAZEqofac5jCQQjwEPBu');
|
|
* // true
|
|
* ```
|
|
*
|
|
* @param {string|Object} data - A bitcoin URI string or an Object
|
|
* @param {Array.<string>=} knownParams - Required non-standard params
|
|
* @returns {boolean} Result of uri validation
|
|
*/
|
|
URI.isValid = function(arg, knownParams) {
|
|
try {
|
|
new URI(arg, knownParams);
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Convert a bitcoin URI string into a simple object.
|
|
*
|
|
* @param {string} uri - A bitcoin URI string
|
|
* @throws {TypeError} Invalid bitcoin URI
|
|
* @returns {Object} An object with the parsed params
|
|
*/
|
|
URI.parse = function(uri) {
|
|
var info = URL.parse(uri, true);
|
|
|
|
if (info.protocol !== 'bitcoin:') {
|
|
throw new TypeError('Invalid bitcoin URI');
|
|
}
|
|
|
|
// workaround to host insensitiveness
|
|
var group = /[^:]*:\/?\/?([^?]*)/.exec(uri);
|
|
info.query.address = group && group[1] || undefined;
|
|
|
|
return info.query;
|
|
};
|
|
|
|
URI.Members = ['address', 'amount', 'message', 'label', 'r'];
|
|
|
|
/**
|
|
* Internal function to load the URI instance with an object.
|
|
*
|
|
* @param {Object} obj - Object with the information
|
|
* @throws {TypeError} Invalid bitcoin address
|
|
* @throws {TypeError} Invalid amount
|
|
* @throws {Error} Unknown required argument
|
|
*/
|
|
URI.prototype._fromObject = function(obj) {
|
|
/* jshint maxcomplexity: 10 */
|
|
|
|
if (!Address.isValid(obj.address)) {
|
|
throw new TypeError('Invalid bitcoin address');
|
|
}
|
|
|
|
this.address = new Address(obj.address);
|
|
this.network = this.address.network;
|
|
this.amount = obj.amount;
|
|
|
|
for (var key in obj) {
|
|
if (key === 'address' || key === 'amount') {
|
|
continue;
|
|
}
|
|
|
|
if (/^req-/.exec(key) && this.knownParams.indexOf(key) === -1) {
|
|
throw Error('Unknown required argument ' + key);
|
|
}
|
|
|
|
var destination = URI.Members.indexOf(key) > -1 ? this : this.extras;
|
|
destination[key] = obj[key];
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Internal function to transform a BTC string amount into satoshis
|
|
*
|
|
* @param {string} amount - Amount BTC string
|
|
* @throws {TypeError} Invalid amount
|
|
* @returns {Object} Amount represented in satoshis
|
|
*/
|
|
URI.prototype._parseAmount = function(amount) {
|
|
amount = Number(amount);
|
|
if (isNaN(amount)) {
|
|
throw new TypeError('Invalid amount');
|
|
}
|
|
return Unit.fromBTC(amount).toSatoshis();
|
|
};
|
|
|
|
URI.prototype.toObject = URI.prototype.toJSON = function toObject() {
|
|
var json = {};
|
|
for (var i = 0; i < URI.Members.length; i++) {
|
|
var m = URI.Members[i];
|
|
if (this.hasOwnProperty(m) && typeof(this[m]) !== 'undefined') {
|
|
json[m] = this[m].toString();
|
|
}
|
|
}
|
|
_.extend(json, this.extras);
|
|
return json;
|
|
};
|
|
|
|
/**
|
|
* Will return a the string representation of the URI
|
|
*
|
|
* @returns {string} Bitcoin URI string
|
|
*/
|
|
URI.prototype.toString = function() {
|
|
var query = {};
|
|
if (this.amount) {
|
|
query.amount = Unit.fromSatoshis(this.amount).toBTC();
|
|
}
|
|
if (this.message) {
|
|
query.message = this.message;
|
|
}
|
|
if (this.label) {
|
|
query.label = this.label;
|
|
}
|
|
if (this.r) {
|
|
query.r = this.r;
|
|
}
|
|
_.extend(query, this.extras);
|
|
|
|
return URL.format({
|
|
protocol: 'bitcoin:',
|
|
host: this.address,
|
|
query: query
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Will return a string formatted for the console
|
|
*
|
|
* @returns {string} Bitcoin URI
|
|
*/
|
|
URI.prototype.inspect = function() {
|
|
return '<URI: ' + this.toString() + '>';
|
|
};
|
|
|
|
module.exports = URI;
|
|
|
|
},{"./address":1,"./unit":40,"lodash":319,"url":274}],42:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var buffer = require('buffer');
|
|
var assert = require('assert');
|
|
|
|
var js = require('./js');
|
|
var $ = require('./preconditions');
|
|
|
|
function equals(a, b) {
|
|
if (a.length !== b.length) {
|
|
return false;
|
|
}
|
|
var length = a.length;
|
|
for (var i = 0; i < length; i++) {
|
|
if (a[i] !== b[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
module.exports = {
|
|
/**
|
|
* Fill a buffer with a value.
|
|
*
|
|
* @param {Buffer} buffer
|
|
* @param {number} value
|
|
* @return {Buffer}
|
|
*/
|
|
fill: function fill(buffer, value) {
|
|
$.checkArgumentType(buffer, 'Buffer', 'buffer');
|
|
$.checkArgumentType(value, 'number', 'value');
|
|
var length = buffer.length;
|
|
for (var i = 0; i < length; i++) {
|
|
buffer[i] = value;
|
|
}
|
|
return buffer;
|
|
},
|
|
|
|
/**
|
|
* Return a copy of a buffer
|
|
*
|
|
* @param {Buffer} original
|
|
* @return {Buffer}
|
|
*/
|
|
copy: function(original) {
|
|
var buffer = new Buffer(original.length);
|
|
original.copy(buffer);
|
|
return buffer;
|
|
},
|
|
|
|
/**
|
|
* Returns true if the given argument is an instance of a buffer. Tests for
|
|
* both node's Buffer and Uint8Array
|
|
*
|
|
* @param {*} arg
|
|
* @return {boolean}
|
|
*/
|
|
isBuffer: function isBuffer(arg) {
|
|
return buffer.Buffer.isBuffer(arg) || arg instanceof Uint8Array;
|
|
},
|
|
|
|
/**
|
|
* Returns a zero-filled byte array
|
|
*
|
|
* @param {number} bytes
|
|
* @return {Buffer}
|
|
*/
|
|
emptyBuffer: function emptyBuffer(bytes) {
|
|
$.checkArgumentType(bytes, 'number', 'bytes');
|
|
var result = new buffer.Buffer(bytes);
|
|
for (var i = 0; i < bytes; i++) {
|
|
result.write('\0', i);
|
|
}
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Concatenates a buffer
|
|
*
|
|
* Shortcut for <tt>buffer.Buffer.concat</tt>
|
|
*/
|
|
concat: buffer.Buffer.concat,
|
|
|
|
equals: equals,
|
|
equal: equals,
|
|
|
|
/**
|
|
* Transforms a number from 0 to 255 into a Buffer of size 1 with that value
|
|
*
|
|
* @param {number} integer
|
|
* @return {Buffer}
|
|
*/
|
|
integerAsSingleByteBuffer: function integerAsSingleByteBuffer(integer) {
|
|
$.checkArgumentType(integer, 'number', 'integer');
|
|
return new buffer.Buffer([integer & 0xff]);
|
|
},
|
|
|
|
/**
|
|
* Transform a 4-byte integer into a Buffer of length 4.
|
|
*
|
|
* @param {number} integer
|
|
* @return {Buffer}
|
|
*/
|
|
integerAsBuffer: function integerAsBuffer(integer) {
|
|
$.checkArgumentType(integer, 'number', 'integer');
|
|
var bytes = [];
|
|
bytes.push((integer >> 24) & 0xff);
|
|
bytes.push((integer >> 16) & 0xff);
|
|
bytes.push((integer >> 8) & 0xff);
|
|
bytes.push(integer & 0xff);
|
|
return new Buffer(bytes);
|
|
},
|
|
|
|
/**
|
|
* Transform the first 4 values of a Buffer into a number, in little endian encoding
|
|
*
|
|
* @param {Buffer} buffer
|
|
* @return {number}
|
|
*/
|
|
integerFromBuffer: function integerFromBuffer(buffer) {
|
|
$.checkArgumentType(buffer, 'Buffer', 'buffer');
|
|
return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
|
|
},
|
|
|
|
/**
|
|
* Transforms the first byte of an array into a number ranging from -128 to 127
|
|
* @param {Buffer} buffer
|
|
* @return {number}
|
|
*/
|
|
integerFromSingleByteBuffer: function integerFromBuffer(buffer) {
|
|
$.checkArgumentType(buffer, 'Buffer', 'buffer');
|
|
return buffer[0];
|
|
},
|
|
|
|
/**
|
|
* Transforms a buffer into a string with a number in hexa representation
|
|
*
|
|
* Shorthand for <tt>buffer.toString('hex')</tt>
|
|
*
|
|
* @param {Buffer} buffer
|
|
* @return {string}
|
|
*/
|
|
bufferToHex: function bufferToHex(buffer) {
|
|
$.checkArgumentType(buffer, 'Buffer', 'buffer');
|
|
return buffer.toString('hex');
|
|
},
|
|
|
|
/**
|
|
* Reverse a buffer
|
|
* @param {Buffer} param
|
|
* @return {Buffer}
|
|
*/
|
|
reverse: function reverse(param) {
|
|
var ret = new buffer.Buffer(param.length);
|
|
for (var i = 0; i < param.length; i++) {
|
|
ret[i] = param[param.length - i - 1];
|
|
}
|
|
return ret;
|
|
},
|
|
|
|
/**
|
|
* Transforms an hexa encoded string into a Buffer with binary values
|
|
*
|
|
* Shorthand for <tt>Buffer(string, 'hex')</tt>
|
|
*
|
|
* @param {string} string
|
|
* @return {Buffer}
|
|
*/
|
|
hexToBuffer: function hexToBuffer(string) {
|
|
assert(js.isHexa(string));
|
|
return new buffer.Buffer(string, 'hex');
|
|
}
|
|
};
|
|
|
|
module.exports.NULL_HASH = module.exports.fill(new Buffer(32), 0);
|
|
module.exports.EMPTY_BUFFER = new Buffer(0);
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./js":43,"./preconditions":44,"assert":45,"buffer":47}],43:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
|
|
/**
|
|
* Determines whether a string contains only hexadecimal values
|
|
*
|
|
* @name JSUtil.isHexa
|
|
* @param {string} value
|
|
* @return {boolean} true if the string is the hexa representation of a number
|
|
*/
|
|
var isHexa = function isHexa(value) {
|
|
if (!_.isString(value)) {
|
|
return false;
|
|
}
|
|
return /^[0-9a-fA-F]+$/.test(value);
|
|
};
|
|
|
|
/**
|
|
* @namespace JSUtil
|
|
*/
|
|
module.exports = {
|
|
/**
|
|
* Test if an argument is a valid JSON object. If it is, returns a truthy
|
|
* value (the json object decoded), so no double JSON.parse call is necessary
|
|
*
|
|
* @param {string} arg
|
|
* @return {Object|boolean} false if the argument is not a JSON string.
|
|
*/
|
|
isValidJSON: function isValidJSON(arg) {
|
|
var parsed;
|
|
if (!_.isString(arg)) {
|
|
return false;
|
|
}
|
|
try {
|
|
parsed = JSON.parse(arg);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
if (typeof(parsed) === 'object') {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
isHexa: isHexa,
|
|
isHexaString: isHexa,
|
|
|
|
/**
|
|
* Clone an array
|
|
*/
|
|
cloneArray: function(array) {
|
|
return [].concat(array);
|
|
},
|
|
|
|
/**
|
|
* Define immutable properties on a target object
|
|
*
|
|
* @param {Object} target - An object to be extended
|
|
* @param {Object} values - An object of properties
|
|
* @return {Object} The target object
|
|
*/
|
|
defineImmutable: function defineImmutable(target, values) {
|
|
Object.keys(values).forEach(function(key){
|
|
Object.defineProperty(target, key, {
|
|
configurable: false,
|
|
enumerable: true,
|
|
value: values[key]
|
|
});
|
|
});
|
|
return target;
|
|
},
|
|
/**
|
|
* Checks that a value is a natural number, a positive integer or zero.
|
|
*
|
|
* @param {*} value
|
|
* @return {Boolean}
|
|
*/
|
|
isNaturalNumber: function isNaturalNumber(value) {
|
|
return typeof value === 'number' &&
|
|
isFinite(value) &&
|
|
Math.floor(value) === value &&
|
|
value >= 0;
|
|
}
|
|
};
|
|
|
|
},{"lodash":319}],44:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var errors = require('../errors');
|
|
var _ = require('lodash');
|
|
|
|
module.exports = {
|
|
checkState: function(condition, message) {
|
|
if (!condition) {
|
|
throw new errors.InvalidState(message);
|
|
}
|
|
},
|
|
checkArgument: function(condition, argumentName, message, docsPath) {
|
|
if (!condition) {
|
|
throw new errors.InvalidArgument(argumentName, message, docsPath);
|
|
}
|
|
},
|
|
checkArgumentType: function(argument, type, argumentName) {
|
|
argumentName = argumentName || '(unknown name)';
|
|
if (_.isString(type)) {
|
|
if (type === 'Buffer') {
|
|
var buffer = require('buffer'); // './buffer' fails on cordova & RN
|
|
if (!buffer.Buffer.isBuffer(argument)) {
|
|
throw new errors.InvalidArgumentType(argument, type, argumentName);
|
|
}
|
|
} else if (typeof argument !== type) {
|
|
throw new errors.InvalidArgumentType(argument, type, argumentName);
|
|
}
|
|
} else {
|
|
if (!(argument instanceof type)) {
|
|
throw new errors.InvalidArgumentType(argument, type.name, argumentName);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
},{"../errors":17,"buffer":47,"lodash":319}],45:[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 <feross@feross.org> <http://feross.org>
|
|
* @license MIT
|
|
*/
|
|
function compare(a, b) {
|
|
if (a === b) {
|
|
return 0;
|
|
}
|
|
|
|
var x = a.length;
|
|
var y = b.length;
|
|
|
|
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
|
|
if (a[i] !== b[i]) {
|
|
x = a[i];
|
|
y = b[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (x < y) {
|
|
return -1;
|
|
}
|
|
if (y < x) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
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/":277}],46:[function(require,module,exports){
|
|
|
|
},{}],47:[function(require,module,exports){
|
|
(function (global){
|
|
/*!
|
|
* The buffer module from node.js, for the browser.
|
|
*
|
|
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
|
* @license MIT
|
|
*/
|
|
/* eslint-disable no-proto */
|
|
|
|
'use strict'
|
|
|
|
var base64 = require('base64-js')
|
|
var ieee754 = require('ieee754')
|
|
var isArray = require('isarray')
|
|
|
|
exports.Buffer = Buffer
|
|
exports.SlowBuffer = SlowBuffer
|
|
exports.INSPECT_MAX_BYTES = 50
|
|
|
|
/**
|
|
* If `Buffer.TYPED_ARRAY_SUPPORT`:
|
|
* === true Use Uint8Array implementation (fastest)
|
|
* === false Use 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+.
|
|
*
|
|
* Due to various browser bugs, sometimes the Object implementation will be used even
|
|
* when the browser supports typed arrays.
|
|
*
|
|
* Note:
|
|
*
|
|
* - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
|
|
* See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
|
|
*
|
|
* - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
|
|
*
|
|
* - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
|
|
* incorrect length in some situations.
|
|
|
|
* We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
|
|
* get the Object implementation, which is slower but behaves correctly.
|
|
*/
|
|
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
|
|
? global.TYPED_ARRAY_SUPPORT
|
|
: typedArraySupport()
|
|
|
|
/*
|
|
* Export kMaxLength after typed array support is determined.
|
|
*/
|
|
exports.kMaxLength = kMaxLength()
|
|
|
|
function typedArraySupport () {
|
|
try {
|
|
var arr = new Uint8Array(1)
|
|
arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
|
|
return arr.foo() === 42 && // typed array instances can be augmented
|
|
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
|
|
arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
|
|
} catch (e) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
function kMaxLength () {
|
|
return Buffer.TYPED_ARRAY_SUPPORT
|
|
? 0x7fffffff
|
|
: 0x3fffffff
|
|
}
|
|
|
|
function createBuffer (that, length) {
|
|
if (kMaxLength() < length) {
|
|
throw new RangeError('Invalid typed array length')
|
|
}
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
// Return an augmented `Uint8Array` instance, for best performance
|
|
that = new Uint8Array(length)
|
|
that.__proto__ = Buffer.prototype
|
|
} else {
|
|
// Fallback: Return an object instance of the Buffer class
|
|
if (that === null) {
|
|
that = new Buffer(length)
|
|
}
|
|
that.length = length
|
|
}
|
|
|
|
return that
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
|
|
return new 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(this, arg)
|
|
}
|
|
return from(this, arg, encodingOrOffset, length)
|
|
}
|
|
|
|
Buffer.poolSize = 8192 // not used by this implementation
|
|
|
|
// TODO: Legacy, not needed anymore. Remove in next major version.
|
|
Buffer._augment = function (arr) {
|
|
arr.__proto__ = Buffer.prototype
|
|
return arr
|
|
}
|
|
|
|
function from (that, value, encodingOrOffset, length) {
|
|
if (typeof value === 'number') {
|
|
throw new TypeError('"value" argument must not be a number')
|
|
}
|
|
|
|
if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
|
|
return fromArrayBuffer(that, value, encodingOrOffset, length)
|
|
}
|
|
|
|
if (typeof value === 'string') {
|
|
return fromString(that, value, encodingOrOffset)
|
|
}
|
|
|
|
return fromObject(that, 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(null, value, encodingOrOffset, length)
|
|
}
|
|
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
Buffer.prototype.__proto__ = Uint8Array.prototype
|
|
Buffer.__proto__ = Uint8Array
|
|
if (typeof Symbol !== 'undefined' && Symbol.species &&
|
|
Buffer[Symbol.species] === Buffer) {
|
|
// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
|
|
Object.defineProperty(Buffer, Symbol.species, {
|
|
value: null,
|
|
configurable: true
|
|
})
|
|
}
|
|
}
|
|
|
|
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 (that, size, fill, encoding) {
|
|
assertSize(size)
|
|
if (size <= 0) {
|
|
return createBuffer(that, 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(that, size).fill(fill, encoding)
|
|
: createBuffer(that, size).fill(fill)
|
|
}
|
|
return createBuffer(that, size)
|
|
}
|
|
|
|
/**
|
|
* Creates a new filled Buffer instance.
|
|
* alloc(size[, fill[, encoding]])
|
|
**/
|
|
Buffer.alloc = function (size, fill, encoding) {
|
|
return alloc(null, size, fill, encoding)
|
|
}
|
|
|
|
function allocUnsafe (that, size) {
|
|
assertSize(size)
|
|
that = createBuffer(that, size < 0 ? 0 : checked(size) | 0)
|
|
if (!Buffer.TYPED_ARRAY_SUPPORT) {
|
|
for (var i = 0; i < size; ++i) {
|
|
that[i] = 0
|
|
}
|
|
}
|
|
return that
|
|
}
|
|
|
|
/**
|
|
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
|
|
* */
|
|
Buffer.allocUnsafe = function (size) {
|
|
return allocUnsafe(null, size)
|
|
}
|
|
/**
|
|
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
|
|
*/
|
|
Buffer.allocUnsafeSlow = function (size) {
|
|
return allocUnsafe(null, size)
|
|
}
|
|
|
|
function fromString (that, 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
|
|
that = createBuffer(that, length)
|
|
|
|
var actual = that.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')
|
|
that = that.slice(0, actual)
|
|
}
|
|
|
|
return that
|
|
}
|
|
|
|
function fromArrayLike (that, array) {
|
|
var length = array.length < 0 ? 0 : checked(array.length) | 0
|
|
that = createBuffer(that, length)
|
|
for (var i = 0; i < length; i += 1) {
|
|
that[i] = array[i] & 255
|
|
}
|
|
return that
|
|
}
|
|
|
|
function fromArrayBuffer (that, array, byteOffset, length) {
|
|
array.byteLength // this throws if `array` is not a valid ArrayBuffer
|
|
|
|
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')
|
|
}
|
|
|
|
if (byteOffset === undefined && length === undefined) {
|
|
array = new Uint8Array(array)
|
|
} else if (length === undefined) {
|
|
array = new Uint8Array(array, byteOffset)
|
|
} else {
|
|
array = new Uint8Array(array, byteOffset, length)
|
|
}
|
|
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
// Return an augmented `Uint8Array` instance, for best performance
|
|
that = array
|
|
that.__proto__ = Buffer.prototype
|
|
} else {
|
|
// Fallback: Return an object instance of the Buffer class
|
|
that = fromArrayLike(that, array)
|
|
}
|
|
return that
|
|
}
|
|
|
|
function fromObject (that, obj) {
|
|
if (Buffer.isBuffer(obj)) {
|
|
var len = checked(obj.length) | 0
|
|
that = createBuffer(that, len)
|
|
|
|
if (that.length === 0) {
|
|
return that
|
|
}
|
|
|
|
obj.copy(that, 0, 0, len)
|
|
return that
|
|
}
|
|
|
|
if (obj) {
|
|
if ((typeof ArrayBuffer !== 'undefined' &&
|
|
obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
|
|
if (typeof obj.length !== 'number' || isnan(obj.length)) {
|
|
return createBuffer(that, 0)
|
|
}
|
|
return fromArrayLike(that, obj)
|
|
}
|
|
|
|
if (obj.type === 'Buffer' && isArray(obj.data)) {
|
|
return fromArrayLike(that, 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 < kMaxLength()` here because that fails when
|
|
// length is NaN (which is otherwise coerced to zero.)
|
|
if (length >= kMaxLength()) {
|
|
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
|
|
'size: 0x' + kMaxLength().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)
|
|
}
|
|
|
|
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 (!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 (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
|
|
(ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
|
|
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
|
|
}
|
|
}
|
|
}
|
|
|
|
// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
|
|
// Buffer instances.
|
|
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 | 0
|
|
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 ' + str + '>'
|
|
}
|
|
|
|
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 (isNaN(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 (Buffer.TYPED_ARRAY_SUPPORT &&
|
|
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 (isNaN(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
|
|
}
|
|
// legacy write(string, encoding, offset, length) - remove in v0.13
|
|
} 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
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
newBuf = this.subarray(start, end)
|
|
newBuf.__proto__ = Buffer.prototype
|
|
} else {
|
|
var sliceLen = end - start
|
|
newBuf = new Buffer(sliceLen, undefined)
|
|
for (var i = 0; i < sliceLen; ++i) {
|
|
newBuf[i] = this[i + start]
|
|
}
|
|
}
|
|
|
|
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) {
|
|
if (!noAssert) checkOffset(offset, 1, this.length)
|
|
return this[offset]
|
|
}
|
|
|
|
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
return this[offset] | (this[offset + 1] << 8)
|
|
}
|
|
|
|
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
return (this[offset] << 8) | this[offset + 1]
|
|
}
|
|
|
|
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
|
|
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) {
|
|
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) {
|
|
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) {
|
|
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) {
|
|
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) {
|
|
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) {
|
|
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) {
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
return ieee754.read(this, offset, true, 23, 4)
|
|
}
|
|
|
|
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
return ieee754.read(this, offset, false, 23, 4)
|
|
}
|
|
|
|
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 8, this.length)
|
|
return ieee754.read(this, offset, true, 52, 8)
|
|
}
|
|
|
|
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
|
|
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)
|
|
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
|
|
this[offset] = (value & 0xff)
|
|
return offset + 1
|
|
}
|
|
|
|
function objectWriteUInt16 (buf, value, offset, littleEndian) {
|
|
if (value < 0) value = 0xffff + value + 1
|
|
for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) {
|
|
buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
|
|
(littleEndian ? i : 1 - i) * 8
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
} else {
|
|
objectWriteUInt16(this, value, offset, true)
|
|
}
|
|
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)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value >>> 8)
|
|
this[offset + 1] = (value & 0xff)
|
|
} else {
|
|
objectWriteUInt16(this, value, offset, false)
|
|
}
|
|
return offset + 2
|
|
}
|
|
|
|
function objectWriteUInt32 (buf, value, offset, littleEndian) {
|
|
if (value < 0) value = 0xffffffff + value + 1
|
|
for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) {
|
|
buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset + 3] = (value >>> 24)
|
|
this[offset + 2] = (value >>> 16)
|
|
this[offset + 1] = (value >>> 8)
|
|
this[offset] = (value & 0xff)
|
|
} else {
|
|
objectWriteUInt32(this, value, offset, true)
|
|
}
|
|
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)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value >>> 24)
|
|
this[offset + 1] = (value >>> 16)
|
|
this[offset + 2] = (value >>> 8)
|
|
this[offset + 3] = (value & 0xff)
|
|
} else {
|
|
objectWriteUInt32(this, value, offset, false)
|
|
}
|
|
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 (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
|
|
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)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
} else {
|
|
objectWriteUInt16(this, value, offset, true)
|
|
}
|
|
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)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value >>> 8)
|
|
this[offset + 1] = (value & 0xff)
|
|
} else {
|
|
objectWriteUInt16(this, value, offset, false)
|
|
}
|
|
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)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
this[offset + 2] = (value >>> 16)
|
|
this[offset + 3] = (value >>> 24)
|
|
} else {
|
|
objectWriteUInt32(this, value, offset, true)
|
|
}
|
|
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
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value >>> 24)
|
|
this[offset + 1] = (value >>> 16)
|
|
this[offset + 2] = (value >>> 8)
|
|
this[offset + 3] = (value & 0xff)
|
|
} else {
|
|
objectWriteUInt32(this, value, offset, false)
|
|
}
|
|
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) {
|
|
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) {
|
|
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 || !Buffer.TYPED_ARRAY_SUPPORT) {
|
|
// 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
|
|
: utf8ToBytes(new Buffer(val, encoding).toString())
|
|
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 = stringtrim(str).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 stringtrim (str) {
|
|
if (str.trim) return str.trim()
|
|
return str.replace(/^\s+|\s+$/g, '')
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
function isnan (val) {
|
|
return val !== val // eslint-disable-line no-self-compare
|
|
}
|
|
|
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{"base64-js":48,"ieee754":49,"isarray":50}],48:[function(require,module,exports){
|
|
'use strict'
|
|
|
|
exports.byteLength = byteLength
|
|
exports.toByteArray = toByteArray
|
|
exports.fromByteArray = fromByteArray
|
|
|
|
var lookup = []
|
|
var revLookup = []
|
|
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
|
|
|
|
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
|
for (var i = 0, len = code.length; i < len; ++i) {
|
|
lookup[i] = code[i]
|
|
revLookup[code.charCodeAt(i)] = i
|
|
}
|
|
|
|
revLookup['-'.charCodeAt(0)] = 62
|
|
revLookup['_'.charCodeAt(0)] = 63
|
|
|
|
function placeHoldersCount (b64) {
|
|
var len = b64.length
|
|
if (len % 4 > 0) {
|
|
throw new Error('Invalid string. Length must be a multiple of 4')
|
|
}
|
|
|
|
// the number of equal signs (place holders)
|
|
// if there are two placeholders, than the two characters before it
|
|
// represent one byte
|
|
// if there is only one, then the three characters before it represent 2 bytes
|
|
// this is just a cheap hack to not do indexOf twice
|
|
return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
|
|
}
|
|
|
|
function byteLength (b64) {
|
|
// base64 is 4/3 + up to two characters of the original data
|
|
return (b64.length * 3 / 4) - placeHoldersCount(b64)
|
|
}
|
|
|
|
function toByteArray (b64) {
|
|
var i, l, tmp, placeHolders, arr
|
|
var len = b64.length
|
|
placeHolders = placeHoldersCount(b64)
|
|
|
|
arr = new Arr((len * 3 / 4) - placeHolders)
|
|
|
|
// if there are placeholders, only get up to the last complete 4 chars
|
|
l = placeHolders > 0 ? len - 4 : len
|
|
|
|
var L = 0
|
|
|
|
for (i = 0; i < l; i += 4) {
|
|
tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
|
|
arr[L++] = (tmp >> 16) & 0xFF
|
|
arr[L++] = (tmp >> 8) & 0xFF
|
|
arr[L++] = tmp & 0xFF
|
|
}
|
|
|
|
if (placeHolders === 2) {
|
|
tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
|
|
arr[L++] = tmp & 0xFF
|
|
} else if (placeHolders === 1) {
|
|
tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
|
|
arr[L++] = (tmp >> 8) & 0xFF
|
|
arr[L++] = tmp & 0xFF
|
|
}
|
|
|
|
return arr
|
|
}
|
|
|
|
function tripletToBase64 (num) {
|
|
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
|
|
}
|
|
|
|
function encodeChunk (uint8, start, end) {
|
|
var tmp
|
|
var output = []
|
|
for (var i = start; i < end; i += 3) {
|
|
tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
|
|
output.push(tripletToBase64(tmp))
|
|
}
|
|
return output.join('')
|
|
}
|
|
|
|
function fromByteArray (uint8) {
|
|
var tmp
|
|
var len = uint8.length
|
|
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
|
|
var output = ''
|
|
var parts = []
|
|
var maxChunkLength = 16383 // must be multiple of 3
|
|
|
|
// go through the array every three bytes, we'll deal with trailing stuff later
|
|
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
|
|
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
|
|
}
|
|
|
|
// pad the end with zeros, but make sure to not forget the extra bytes
|
|
if (extraBytes === 1) {
|
|
tmp = uint8[len - 1]
|
|
output += lookup[tmp >> 2]
|
|
output += lookup[(tmp << 4) & 0x3F]
|
|
output += '=='
|
|
} else if (extraBytes === 2) {
|
|
tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
|
|
output += lookup[tmp >> 10]
|
|
output += lookup[(tmp >> 4) & 0x3F]
|
|
output += lookup[(tmp << 2) & 0x3F]
|
|
output += '='
|
|
}
|
|
|
|
parts.push(output)
|
|
|
|
return parts.join('')
|
|
}
|
|
|
|
},{}],49:[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
|
|
}
|
|
|
|
},{}],50:[function(require,module,exports){
|
|
var toString = {}.toString;
|
|
|
|
module.exports = Array.isArray || function (arr) {
|
|
return toString.call(arr) == '[object Array]';
|
|
};
|
|
|
|
},{}],51:[function(require,module,exports){
|
|
'use strict'
|
|
|
|
exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = require('randombytes')
|
|
exports.createHash = exports.Hash = require('create-hash')
|
|
exports.createHmac = exports.Hmac = require('create-hmac')
|
|
|
|
var algos = require('browserify-sign/algos')
|
|
var algoKeys = Object.keys(algos)
|
|
var hashes = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'].concat(algoKeys)
|
|
exports.getHashes = function () {
|
|
return hashes
|
|
}
|
|
|
|
var p = require('pbkdf2')
|
|
exports.pbkdf2 = p.pbkdf2
|
|
exports.pbkdf2Sync = p.pbkdf2Sync
|
|
|
|
var aes = require('browserify-cipher')
|
|
|
|
exports.Cipher = aes.Cipher
|
|
exports.createCipher = aes.createCipher
|
|
exports.Cipheriv = aes.Cipheriv
|
|
exports.createCipheriv = aes.createCipheriv
|
|
exports.Decipher = aes.Decipher
|
|
exports.createDecipher = aes.createDecipher
|
|
exports.Decipheriv = aes.Decipheriv
|
|
exports.createDecipheriv = aes.createDecipheriv
|
|
exports.getCiphers = aes.getCiphers
|
|
exports.listCiphers = aes.listCiphers
|
|
|
|
var dh = require('diffie-hellman')
|
|
|
|
exports.DiffieHellmanGroup = dh.DiffieHellmanGroup
|
|
exports.createDiffieHellmanGroup = dh.createDiffieHellmanGroup
|
|
exports.getDiffieHellman = dh.getDiffieHellman
|
|
exports.createDiffieHellman = dh.createDiffieHellman
|
|
exports.DiffieHellman = dh.DiffieHellman
|
|
|
|
var sign = require('browserify-sign')
|
|
|
|
exports.createSign = sign.createSign
|
|
exports.Sign = sign.Sign
|
|
exports.createVerify = sign.createVerify
|
|
exports.Verify = sign.Verify
|
|
|
|
exports.createECDH = require('create-ecdh')
|
|
|
|
var publicEncrypt = require('public-encrypt')
|
|
|
|
exports.publicEncrypt = publicEncrypt.publicEncrypt
|
|
exports.privateEncrypt = publicEncrypt.privateEncrypt
|
|
exports.publicDecrypt = publicEncrypt.publicDecrypt
|
|
exports.privateDecrypt = publicEncrypt.privateDecrypt
|
|
|
|
// the least I can do is make error messages for the rest of the node.js/crypto api.
|
|
// ;[
|
|
// 'createCredentials'
|
|
// ].forEach(function (name) {
|
|
// exports[name] = function () {
|
|
// throw new Error([
|
|
// 'sorry, ' + name + ' is not implemented yet',
|
|
// 'we accept pull requests',
|
|
// 'https://github.com/crypto-browserify/crypto-browserify'
|
|
// ].join('\n'))
|
|
// }
|
|
// })
|
|
|
|
exports.createCredentials = function () {
|
|
throw new Error([
|
|
'sorry, createCredentials is not implemented yet',
|
|
'we accept pull requests',
|
|
'https://github.com/crypto-browserify/crypto-browserify'
|
|
].join('\n'))
|
|
}
|
|
|
|
exports.constants = {
|
|
'DH_CHECK_P_NOT_SAFE_PRIME': 2,
|
|
'DH_CHECK_P_NOT_PRIME': 1,
|
|
'DH_UNABLE_TO_CHECK_GENERATOR': 4,
|
|
'DH_NOT_SUITABLE_GENERATOR': 8,
|
|
'NPN_ENABLED': 1,
|
|
'ALPN_ENABLED': 1,
|
|
'RSA_PKCS1_PADDING': 1,
|
|
'RSA_SSLV23_PADDING': 2,
|
|
'RSA_NO_PADDING': 3,
|
|
'RSA_PKCS1_OAEP_PADDING': 4,
|
|
'RSA_X931_PADDING': 5,
|
|
'RSA_PKCS1_PSS_PADDING': 6,
|
|
'POINT_CONVERSION_COMPRESSED': 2,
|
|
'POINT_CONVERSION_UNCOMPRESSED': 4,
|
|
'POINT_CONVERSION_HYBRID': 6
|
|
}
|
|
|
|
},{"browserify-cipher":52,"browserify-sign":91,"browserify-sign/algos":88,"create-ecdh":139,"create-hash":140,"create-hmac":156,"diffie-hellman":170,"pbkdf2":176,"public-encrypt":192,"randombytes":243}],52:[function(require,module,exports){
|
|
var ebtk = require('evp_bytestokey')
|
|
var aes = require('browserify-aes/browser')
|
|
var DES = require('browserify-des')
|
|
var desModes = require('browserify-des/modes')
|
|
var aesModes = require('browserify-aes/modes')
|
|
function createCipher (suite, password) {
|
|
var keyLen, ivLen
|
|
suite = suite.toLowerCase()
|
|
if (aesModes[suite]) {
|
|
keyLen = aesModes[suite].key
|
|
ivLen = aesModes[suite].iv
|
|
} else if (desModes[suite]) {
|
|
keyLen = desModes[suite].key * 8
|
|
ivLen = desModes[suite].iv
|
|
} else {
|
|
throw new TypeError('invalid suite type')
|
|
}
|
|
var keys = ebtk(password, false, keyLen, ivLen)
|
|
return createCipheriv(suite, keys.key, keys.iv)
|
|
}
|
|
function createDecipher (suite, password) {
|
|
var keyLen, ivLen
|
|
suite = suite.toLowerCase()
|
|
if (aesModes[suite]) {
|
|
keyLen = aesModes[suite].key
|
|
ivLen = aesModes[suite].iv
|
|
} else if (desModes[suite]) {
|
|
keyLen = desModes[suite].key * 8
|
|
ivLen = desModes[suite].iv
|
|
} else {
|
|
throw new TypeError('invalid suite type')
|
|
}
|
|
var keys = ebtk(password, false, keyLen, ivLen)
|
|
return createDecipheriv(suite, keys.key, keys.iv)
|
|
}
|
|
|
|
function createCipheriv (suite, key, iv) {
|
|
suite = suite.toLowerCase()
|
|
if (aesModes[suite]) {
|
|
return aes.createCipheriv(suite, key, iv)
|
|
} else if (desModes[suite]) {
|
|
return new DES({
|
|
key: key,
|
|
iv: iv,
|
|
mode: suite
|
|
})
|
|
} else {
|
|
throw new TypeError('invalid suite type')
|
|
}
|
|
}
|
|
function createDecipheriv (suite, key, iv) {
|
|
suite = suite.toLowerCase()
|
|
if (aesModes[suite]) {
|
|
return aes.createDecipheriv(suite, key, iv)
|
|
} else if (desModes[suite]) {
|
|
return new DES({
|
|
key: key,
|
|
iv: iv,
|
|
mode: suite,
|
|
decrypt: true
|
|
})
|
|
} else {
|
|
throw new TypeError('invalid suite type')
|
|
}
|
|
}
|
|
exports.createCipher = exports.Cipher = createCipher
|
|
exports.createCipheriv = exports.Cipheriv = createCipheriv
|
|
exports.createDecipher = exports.Decipher = createDecipher
|
|
exports.createDecipheriv = exports.Decipheriv = createDecipheriv
|
|
function getCiphers () {
|
|
return Object.keys(desModes).concat(aes.getCiphers())
|
|
}
|
|
exports.listCiphers = exports.getCiphers = getCiphers
|
|
|
|
},{"browserify-aes/browser":55,"browserify-aes/modes":66,"browserify-des":73,"browserify-des/modes":74,"evp_bytestokey":84}],53:[function(require,module,exports){
|
|
// based on the aes implimentation in triple sec
|
|
// https://github.com/keybase/triplesec
|
|
// which is in turn based on the one from crypto-js
|
|
// https://code.google.com/p/crypto-js/
|
|
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
function asUInt32Array (buf) {
|
|
if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf)
|
|
|
|
var len = (buf.length / 4) | 0
|
|
var out = new Array(len)
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
out[i] = buf.readUInt32BE(i * 4)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
function scrubVec (v) {
|
|
for (var i = 0; i < v.length; v++) {
|
|
v[i] = 0
|
|
}
|
|
}
|
|
|
|
function cryptBlock (M, keySchedule, SUB_MIX, SBOX, nRounds) {
|
|
var SUB_MIX0 = SUB_MIX[0]
|
|
var SUB_MIX1 = SUB_MIX[1]
|
|
var SUB_MIX2 = SUB_MIX[2]
|
|
var SUB_MIX3 = SUB_MIX[3]
|
|
|
|
var s0 = M[0] ^ keySchedule[0]
|
|
var s1 = M[1] ^ keySchedule[1]
|
|
var s2 = M[2] ^ keySchedule[2]
|
|
var s3 = M[3] ^ keySchedule[3]
|
|
var t0, t1, t2, t3
|
|
var ksRow = 4
|
|
|
|
for (var round = 1; round < nRounds; round++) {
|
|
t0 = SUB_MIX0[s0 >>> 24] ^ SUB_MIX1[(s1 >>> 16) & 0xff] ^ SUB_MIX2[(s2 >>> 8) & 0xff] ^ SUB_MIX3[s3 & 0xff] ^ keySchedule[ksRow++]
|
|
t1 = SUB_MIX0[s1 >>> 24] ^ SUB_MIX1[(s2 >>> 16) & 0xff] ^ SUB_MIX2[(s3 >>> 8) & 0xff] ^ SUB_MIX3[s0 & 0xff] ^ keySchedule[ksRow++]
|
|
t2 = SUB_MIX0[s2 >>> 24] ^ SUB_MIX1[(s3 >>> 16) & 0xff] ^ SUB_MIX2[(s0 >>> 8) & 0xff] ^ SUB_MIX3[s1 & 0xff] ^ keySchedule[ksRow++]
|
|
t3 = SUB_MIX0[s3 >>> 24] ^ SUB_MIX1[(s0 >>> 16) & 0xff] ^ SUB_MIX2[(s1 >>> 8) & 0xff] ^ SUB_MIX3[s2 & 0xff] ^ keySchedule[ksRow++]
|
|
s0 = t0
|
|
s1 = t1
|
|
s2 = t2
|
|
s3 = t3
|
|
}
|
|
|
|
t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]
|
|
t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]
|
|
t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]
|
|
t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]
|
|
t0 = t0 >>> 0
|
|
t1 = t1 >>> 0
|
|
t2 = t2 >>> 0
|
|
t3 = t3 >>> 0
|
|
|
|
return [t0, t1, t2, t3]
|
|
}
|
|
|
|
// AES constants
|
|
var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]
|
|
var G = (function () {
|
|
// Compute double table
|
|
var d = new Array(256)
|
|
for (var j = 0; j < 256; j++) {
|
|
if (j < 128) {
|
|
d[j] = j << 1
|
|
} else {
|
|
d[j] = (j << 1) ^ 0x11b
|
|
}
|
|
}
|
|
|
|
var SBOX = []
|
|
var INV_SBOX = []
|
|
var SUB_MIX = [[], [], [], []]
|
|
var INV_SUB_MIX = [[], [], [], []]
|
|
|
|
// Walk GF(2^8)
|
|
var x = 0
|
|
var xi = 0
|
|
for (var i = 0; i < 256; ++i) {
|
|
// Compute sbox
|
|
var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4)
|
|
sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63
|
|
SBOX[x] = sx
|
|
INV_SBOX[sx] = x
|
|
|
|
// Compute multiplication
|
|
var x2 = d[x]
|
|
var x4 = d[x2]
|
|
var x8 = d[x4]
|
|
|
|
// Compute sub bytes, mix columns tables
|
|
var t = (d[sx] * 0x101) ^ (sx * 0x1010100)
|
|
SUB_MIX[0][x] = (t << 24) | (t >>> 8)
|
|
SUB_MIX[1][x] = (t << 16) | (t >>> 16)
|
|
SUB_MIX[2][x] = (t << 8) | (t >>> 24)
|
|
SUB_MIX[3][x] = t
|
|
|
|
// Compute inv sub bytes, inv mix columns tables
|
|
t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100)
|
|
INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8)
|
|
INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16)
|
|
INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24)
|
|
INV_SUB_MIX[3][sx] = t
|
|
|
|
if (x === 0) {
|
|
x = xi = 1
|
|
} else {
|
|
x = x2 ^ d[d[d[x8 ^ x2]]]
|
|
xi ^= d[d[xi]]
|
|
}
|
|
}
|
|
|
|
return {
|
|
SBOX: SBOX,
|
|
INV_SBOX: INV_SBOX,
|
|
SUB_MIX: SUB_MIX,
|
|
INV_SUB_MIX: INV_SUB_MIX
|
|
}
|
|
})()
|
|
|
|
function AES (key) {
|
|
this._key = asUInt32Array(key)
|
|
this._reset()
|
|
}
|
|
|
|
AES.blockSize = 4 * 4
|
|
AES.keySize = 256 / 8
|
|
AES.prototype.blockSize = AES.blockSize
|
|
AES.prototype.keySize = AES.keySize
|
|
AES.prototype._reset = function () {
|
|
var keyWords = this._key
|
|
var keySize = keyWords.length
|
|
var nRounds = keySize + 6
|
|
var ksRows = (nRounds + 1) * 4
|
|
|
|
var keySchedule = []
|
|
for (var k = 0; k < keySize; k++) {
|
|
keySchedule[k] = keyWords[k]
|
|
}
|
|
|
|
for (k = keySize; k < ksRows; k++) {
|
|
var t = keySchedule[k - 1]
|
|
|
|
if (k % keySize === 0) {
|
|
t = (t << 8) | (t >>> 24)
|
|
t =
|
|
(G.SBOX[t >>> 24] << 24) |
|
|
(G.SBOX[(t >>> 16) & 0xff] << 16) |
|
|
(G.SBOX[(t >>> 8) & 0xff] << 8) |
|
|
(G.SBOX[t & 0xff])
|
|
|
|
t ^= RCON[(k / keySize) | 0] << 24
|
|
} else if (keySize > 6 && k % keySize === 4) {
|
|
t =
|
|
(G.SBOX[t >>> 24] << 24) |
|
|
(G.SBOX[(t >>> 16) & 0xff] << 16) |
|
|
(G.SBOX[(t >>> 8) & 0xff] << 8) |
|
|
(G.SBOX[t & 0xff])
|
|
}
|
|
|
|
keySchedule[k] = keySchedule[k - keySize] ^ t
|
|
}
|
|
|
|
var invKeySchedule = []
|
|
for (var ik = 0; ik < ksRows; ik++) {
|
|
var ksR = ksRows - ik
|
|
var tt = keySchedule[ksR - (ik % 4 ? 0 : 4)]
|
|
|
|
if (ik < 4 || ksR <= 4) {
|
|
invKeySchedule[ik] = tt
|
|
} else {
|
|
invKeySchedule[ik] =
|
|
G.INV_SUB_MIX[0][G.SBOX[tt >>> 24]] ^
|
|
G.INV_SUB_MIX[1][G.SBOX[(tt >>> 16) & 0xff]] ^
|
|
G.INV_SUB_MIX[2][G.SBOX[(tt >>> 8) & 0xff]] ^
|
|
G.INV_SUB_MIX[3][G.SBOX[tt & 0xff]]
|
|
}
|
|
}
|
|
|
|
this._nRounds = nRounds
|
|
this._keySchedule = keySchedule
|
|
this._invKeySchedule = invKeySchedule
|
|
}
|
|
|
|
AES.prototype.encryptBlockRaw = function (M) {
|
|
M = asUInt32Array(M)
|
|
return cryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX, this._nRounds)
|
|
}
|
|
|
|
AES.prototype.encryptBlock = function (M) {
|
|
var out = this.encryptBlockRaw(M)
|
|
var buf = Buffer.allocUnsafe(16)
|
|
buf.writeUInt32BE(out[0], 0)
|
|
buf.writeUInt32BE(out[1], 4)
|
|
buf.writeUInt32BE(out[2], 8)
|
|
buf.writeUInt32BE(out[3], 12)
|
|
return buf
|
|
}
|
|
|
|
AES.prototype.decryptBlock = function (M) {
|
|
M = asUInt32Array(M)
|
|
|
|
// swap
|
|
var m1 = M[1]
|
|
M[1] = M[3]
|
|
M[3] = m1
|
|
|
|
var out = cryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX, this._nRounds)
|
|
var buf = Buffer.allocUnsafe(16)
|
|
buf.writeUInt32BE(out[0], 0)
|
|
buf.writeUInt32BE(out[3], 4)
|
|
buf.writeUInt32BE(out[2], 8)
|
|
buf.writeUInt32BE(out[1], 12)
|
|
return buf
|
|
}
|
|
|
|
AES.prototype.scrub = function () {
|
|
scrubVec(this._keySchedule)
|
|
scrubVec(this._invKeySchedule)
|
|
scrubVec(this._key)
|
|
}
|
|
|
|
module.exports.AES = AES
|
|
|
|
},{"safe-buffer":71}],54:[function(require,module,exports){
|
|
var aes = require('./aes')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var Transform = require('cipher-base')
|
|
var inherits = require('inherits')
|
|
var GHASH = require('./ghash')
|
|
var xor = require('buffer-xor')
|
|
var incr32 = require('./incr32')
|
|
|
|
function xorTest (a, b) {
|
|
var out = 0
|
|
if (a.length !== b.length) out++
|
|
|
|
var len = Math.min(a.length, b.length)
|
|
for (var i = 0; i < len; ++i) {
|
|
out += (a[i] ^ b[i])
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
function calcIv (self, iv, ck) {
|
|
if (iv.length === 12) {
|
|
self._finID = Buffer.concat([iv, Buffer.from([0, 0, 0, 1])])
|
|
return Buffer.concat([iv, Buffer.from([0, 0, 0, 2])])
|
|
}
|
|
var ghash = new GHASH(ck)
|
|
var len = iv.length
|
|
var toPad = len % 16
|
|
ghash.update(iv)
|
|
if (toPad) {
|
|
toPad = 16 - toPad
|
|
ghash.update(Buffer.alloc(toPad, 0))
|
|
}
|
|
ghash.update(Buffer.alloc(8, 0))
|
|
var ivBits = len * 8
|
|
var tail = Buffer.alloc(8)
|
|
tail.writeUIntBE(ivBits, 0, 8)
|
|
ghash.update(tail)
|
|
self._finID = ghash.state
|
|
var out = Buffer.from(self._finID)
|
|
incr32(out)
|
|
return out
|
|
}
|
|
function StreamCipher (mode, key, iv, decrypt) {
|
|
Transform.call(this)
|
|
|
|
var h = Buffer.alloc(4, 0)
|
|
|
|
this._cipher = new aes.AES(key)
|
|
var ck = this._cipher.encryptBlock(h)
|
|
this._ghash = new GHASH(ck)
|
|
iv = calcIv(this, iv, ck)
|
|
|
|
this._prev = Buffer.from(iv)
|
|
this._cache = Buffer.allocUnsafe(0)
|
|
this._secCache = Buffer.allocUnsafe(0)
|
|
this._decrypt = decrypt
|
|
this._alen = 0
|
|
this._len = 0
|
|
this._mode = mode
|
|
|
|
this._authTag = null
|
|
this._called = false
|
|
}
|
|
|
|
inherits(StreamCipher, Transform)
|
|
|
|
StreamCipher.prototype._update = function (chunk) {
|
|
if (!this._called && this._alen) {
|
|
var rump = 16 - (this._alen % 16)
|
|
if (rump < 16) {
|
|
rump = Buffer.alloc(rump, 0)
|
|
this._ghash.update(rump)
|
|
}
|
|
}
|
|
|
|
this._called = true
|
|
var out = this._mode.encrypt(this, chunk)
|
|
if (this._decrypt) {
|
|
this._ghash.update(chunk)
|
|
} else {
|
|
this._ghash.update(out)
|
|
}
|
|
this._len += chunk.length
|
|
return out
|
|
}
|
|
|
|
StreamCipher.prototype._final = function () {
|
|
if (this._decrypt && !this._authTag) throw new Error('Unsupported state or unable to authenticate data')
|
|
|
|
var tag = xor(this._ghash.final(this._alen * 8, this._len * 8), this._cipher.encryptBlock(this._finID))
|
|
if (this._decrypt && xorTest(tag, this._authTag)) throw new Error('Unsupported state or unable to authenticate data')
|
|
|
|
this._authTag = tag
|
|
this._cipher.scrub()
|
|
}
|
|
|
|
StreamCipher.prototype.getAuthTag = function getAuthTag () {
|
|
if (this._decrypt || !Buffer.isBuffer(this._authTag)) throw new Error('Attempting to get auth tag in unsupported state')
|
|
|
|
return this._authTag
|
|
}
|
|
|
|
StreamCipher.prototype.setAuthTag = function setAuthTag (tag) {
|
|
if (!this._decrypt) throw new Error('Attempting to set auth tag in unsupported state')
|
|
|
|
this._authTag = tag
|
|
}
|
|
|
|
StreamCipher.prototype.setAAD = function setAAD (buf) {
|
|
if (this._called) throw new Error('Attempting to set AAD in unsupported state')
|
|
|
|
this._ghash.update(buf)
|
|
this._alen += buf.length
|
|
}
|
|
|
|
module.exports = StreamCipher
|
|
|
|
},{"./aes":53,"./ghash":58,"./incr32":59,"buffer-xor":69,"cipher-base":70,"inherits":318,"safe-buffer":71}],55:[function(require,module,exports){
|
|
var ciphers = require('./encrypter')
|
|
var deciphers = require('./decrypter')
|
|
var modes = require('./modes/list.json')
|
|
|
|
function getCiphers () {
|
|
return Object.keys(modes)
|
|
}
|
|
|
|
exports.createCipher = exports.Cipher = ciphers.createCipher
|
|
exports.createCipheriv = exports.Cipheriv = ciphers.createCipheriv
|
|
exports.createDecipher = exports.Decipher = deciphers.createDecipher
|
|
exports.createDecipheriv = exports.Decipheriv = deciphers.createDecipheriv
|
|
exports.listCiphers = exports.getCiphers = getCiphers
|
|
|
|
},{"./decrypter":56,"./encrypter":57,"./modes/list.json":67}],56:[function(require,module,exports){
|
|
var AuthCipher = require('./authCipher')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var MODES = require('./modes')
|
|
var StreamCipher = require('./streamCipher')
|
|
var Transform = require('cipher-base')
|
|
var aes = require('./aes')
|
|
var ebtk = require('evp_bytestokey')
|
|
var inherits = require('inherits')
|
|
|
|
function Decipher (mode, key, iv) {
|
|
Transform.call(this)
|
|
|
|
this._cache = new Splitter()
|
|
this._last = void 0
|
|
this._cipher = new aes.AES(key)
|
|
this._prev = Buffer.from(iv)
|
|
this._mode = mode
|
|
this._autopadding = true
|
|
}
|
|
|
|
inherits(Decipher, Transform)
|
|
|
|
Decipher.prototype._update = function (data) {
|
|
this._cache.add(data)
|
|
var chunk
|
|
var thing
|
|
var out = []
|
|
while ((chunk = this._cache.get(this._autopadding))) {
|
|
thing = this._mode.decrypt(this, chunk)
|
|
out.push(thing)
|
|
}
|
|
return Buffer.concat(out)
|
|
}
|
|
|
|
Decipher.prototype._final = function () {
|
|
var chunk = this._cache.flush()
|
|
if (this._autopadding) {
|
|
return unpad(this._mode.decrypt(this, chunk))
|
|
} else if (chunk) {
|
|
throw new Error('data not multiple of block length')
|
|
}
|
|
}
|
|
|
|
Decipher.prototype.setAutoPadding = function (setTo) {
|
|
this._autopadding = !!setTo
|
|
return this
|
|
}
|
|
|
|
function Splitter () {
|
|
this.cache = Buffer.allocUnsafe(0)
|
|
}
|
|
|
|
Splitter.prototype.add = function (data) {
|
|
this.cache = Buffer.concat([this.cache, data])
|
|
}
|
|
|
|
Splitter.prototype.get = function (autoPadding) {
|
|
var out
|
|
if (autoPadding) {
|
|
if (this.cache.length > 16) {
|
|
out = this.cache.slice(0, 16)
|
|
this.cache = this.cache.slice(16)
|
|
return out
|
|
}
|
|
} else {
|
|
if (this.cache.length >= 16) {
|
|
out = this.cache.slice(0, 16)
|
|
this.cache = this.cache.slice(16)
|
|
return out
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
Splitter.prototype.flush = function () {
|
|
if (this.cache.length) return this.cache
|
|
}
|
|
|
|
function unpad (last) {
|
|
var padded = last[15]
|
|
var i = -1
|
|
while (++i < padded) {
|
|
if (last[(i + (16 - padded))] !== padded) {
|
|
throw new Error('unable to decrypt data')
|
|
}
|
|
}
|
|
if (padded === 16) return
|
|
|
|
return last.slice(0, 16 - padded)
|
|
}
|
|
|
|
function createDecipheriv (suite, password, iv) {
|
|
var config = MODES[suite.toLowerCase()]
|
|
if (!config) throw new TypeError('invalid suite type')
|
|
|
|
if (typeof iv === 'string') iv = Buffer.from(iv)
|
|
if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length)
|
|
|
|
if (typeof password === 'string') password = Buffer.from(password)
|
|
if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length)
|
|
|
|
if (config.type === 'stream') {
|
|
return new StreamCipher(config.module, password, iv, true)
|
|
} else if (config.type === 'auth') {
|
|
return new AuthCipher(config.module, password, iv, true)
|
|
}
|
|
|
|
return new Decipher(config.module, password, iv)
|
|
}
|
|
|
|
function createDecipher (suite, password) {
|
|
var config = MODES[suite.toLowerCase()]
|
|
if (!config) throw new TypeError('invalid suite type')
|
|
|
|
var keys = ebtk(password, false, config.key, config.iv)
|
|
return createDecipheriv(suite, keys.key, keys.iv)
|
|
}
|
|
|
|
exports.createDecipher = createDecipher
|
|
exports.createDecipheriv = createDecipheriv
|
|
|
|
},{"./aes":53,"./authCipher":54,"./modes":66,"./streamCipher":72,"cipher-base":70,"evp_bytestokey":84,"inherits":318,"safe-buffer":71}],57:[function(require,module,exports){
|
|
var MODES = require('./modes')
|
|
var AuthCipher = require('./authCipher')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var StreamCipher = require('./streamCipher')
|
|
var Transform = require('cipher-base')
|
|
var aes = require('./aes')
|
|
var ebtk = require('evp_bytestokey')
|
|
var inherits = require('inherits')
|
|
|
|
function Cipher (mode, key, iv) {
|
|
Transform.call(this)
|
|
|
|
this._cache = new Splitter()
|
|
this._cipher = new aes.AES(key)
|
|
this._prev = Buffer.from(iv)
|
|
this._mode = mode
|
|
this._autopadding = true
|
|
}
|
|
|
|
inherits(Cipher, Transform)
|
|
|
|
Cipher.prototype._update = function (data) {
|
|
this._cache.add(data)
|
|
var chunk
|
|
var thing
|
|
var out = []
|
|
|
|
while ((chunk = this._cache.get())) {
|
|
thing = this._mode.encrypt(this, chunk)
|
|
out.push(thing)
|
|
}
|
|
|
|
return Buffer.concat(out)
|
|
}
|
|
|
|
var PADDING = Buffer.alloc(16, 0x10)
|
|
|
|
Cipher.prototype._final = function () {
|
|
var chunk = this._cache.flush()
|
|
if (this._autopadding) {
|
|
chunk = this._mode.encrypt(this, chunk)
|
|
this._cipher.scrub()
|
|
return chunk
|
|
}
|
|
|
|
if (!chunk.equals(PADDING)) {
|
|
this._cipher.scrub()
|
|
throw new Error('data not multiple of block length')
|
|
}
|
|
}
|
|
|
|
Cipher.prototype.setAutoPadding = function (setTo) {
|
|
this._autopadding = !!setTo
|
|
return this
|
|
}
|
|
|
|
function Splitter () {
|
|
this.cache = Buffer.allocUnsafe(0)
|
|
}
|
|
|
|
Splitter.prototype.add = function (data) {
|
|
this.cache = Buffer.concat([this.cache, data])
|
|
}
|
|
|
|
Splitter.prototype.get = function () {
|
|
if (this.cache.length > 15) {
|
|
var out = this.cache.slice(0, 16)
|
|
this.cache = this.cache.slice(16)
|
|
return out
|
|
}
|
|
return null
|
|
}
|
|
|
|
Splitter.prototype.flush = function () {
|
|
var len = 16 - this.cache.length
|
|
var padBuff = Buffer.allocUnsafe(len)
|
|
|
|
var i = -1
|
|
while (++i < len) {
|
|
padBuff.writeUInt8(len, i)
|
|
}
|
|
|
|
return Buffer.concat([this.cache, padBuff])
|
|
}
|
|
|
|
function createCipheriv (suite, password, iv) {
|
|
var config = MODES[suite.toLowerCase()]
|
|
if (!config) throw new TypeError('invalid suite type')
|
|
|
|
if (typeof password === 'string') password = Buffer.from(password)
|
|
if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length)
|
|
|
|
if (typeof iv === 'string') iv = Buffer.from(iv)
|
|
if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length)
|
|
|
|
if (config.type === 'stream') {
|
|
return new StreamCipher(config.module, password, iv)
|
|
} else if (config.type === 'auth') {
|
|
return new AuthCipher(config.module, password, iv)
|
|
}
|
|
|
|
return new Cipher(config.module, password, iv)
|
|
}
|
|
|
|
function createCipher (suite, password) {
|
|
var config = MODES[suite.toLowerCase()]
|
|
if (!config) throw new TypeError('invalid suite type')
|
|
|
|
var keys = ebtk(password, false, config.key, config.iv)
|
|
return createCipheriv(suite, keys.key, keys.iv)
|
|
}
|
|
|
|
exports.createCipheriv = createCipheriv
|
|
exports.createCipher = createCipher
|
|
|
|
},{"./aes":53,"./authCipher":54,"./modes":66,"./streamCipher":72,"cipher-base":70,"evp_bytestokey":84,"inherits":318,"safe-buffer":71}],58:[function(require,module,exports){
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var ZEROES = Buffer.alloc(16, 0)
|
|
|
|
function toArray (buf) {
|
|
return [
|
|
buf.readUInt32BE(0),
|
|
buf.readUInt32BE(4),
|
|
buf.readUInt32BE(8),
|
|
buf.readUInt32BE(12)
|
|
]
|
|
}
|
|
|
|
function fromArray (out) {
|
|
var buf = Buffer.allocUnsafe(16)
|
|
buf.writeUInt32BE(out[0] >>> 0, 0)
|
|
buf.writeUInt32BE(out[1] >>> 0, 4)
|
|
buf.writeUInt32BE(out[2] >>> 0, 8)
|
|
buf.writeUInt32BE(out[3] >>> 0, 12)
|
|
return buf
|
|
}
|
|
|
|
function GHASH (key) {
|
|
this.h = key
|
|
this.state = Buffer.alloc(16, 0)
|
|
this.cache = Buffer.allocUnsafe(0)
|
|
}
|
|
|
|
// from http://bitwiseshiftleft.github.io/sjcl/doc/symbols/src/core_gcm.js.html
|
|
// by Juho Vähä-Herttua
|
|
GHASH.prototype.ghash = function (block) {
|
|
var i = -1
|
|
while (++i < block.length) {
|
|
this.state[i] ^= block[i]
|
|
}
|
|
this._multiply()
|
|
}
|
|
|
|
GHASH.prototype._multiply = function () {
|
|
var Vi = toArray(this.h)
|
|
var Zi = [0, 0, 0, 0]
|
|
var j, xi, lsbVi
|
|
var i = -1
|
|
while (++i < 128) {
|
|
xi = (this.state[~~(i / 8)] & (1 << (7 - (i % 8)))) !== 0
|
|
if (xi) {
|
|
// Z_i+1 = Z_i ^ V_i
|
|
Zi[0] ^= Vi[0]
|
|
Zi[1] ^= Vi[1]
|
|
Zi[2] ^= Vi[2]
|
|
Zi[3] ^= Vi[3]
|
|
}
|
|
|
|
// Store the value of LSB(V_i)
|
|
lsbVi = (Vi[3] & 1) !== 0
|
|
|
|
// V_i+1 = V_i >> 1
|
|
for (j = 3; j > 0; j--) {
|
|
Vi[j] = (Vi[j] >>> 1) | ((Vi[j - 1] & 1) << 31)
|
|
}
|
|
Vi[0] = Vi[0] >>> 1
|
|
|
|
// If LSB(V_i) is 1, V_i+1 = (V_i >> 1) ^ R
|
|
if (lsbVi) {
|
|
Vi[0] = Vi[0] ^ (0xe1 << 24)
|
|
}
|
|
}
|
|
this.state = fromArray(Zi)
|
|
}
|
|
|
|
GHASH.prototype.update = function (buf) {
|
|
this.cache = Buffer.concat([this.cache, buf])
|
|
var chunk
|
|
while (this.cache.length >= 16) {
|
|
chunk = this.cache.slice(0, 16)
|
|
this.cache = this.cache.slice(16)
|
|
this.ghash(chunk)
|
|
}
|
|
}
|
|
|
|
GHASH.prototype.final = function (abl, bl) {
|
|
if (this.cache.length) {
|
|
this.ghash(Buffer.concat([this.cache, ZEROES], 16))
|
|
}
|
|
|
|
this.ghash(fromArray([0, abl, 0, bl]))
|
|
return this.state
|
|
}
|
|
|
|
module.exports = GHASH
|
|
|
|
},{"safe-buffer":71}],59:[function(require,module,exports){
|
|
function incr32 (iv) {
|
|
var len = iv.length
|
|
var item
|
|
while (len--) {
|
|
item = iv.readUInt8(len)
|
|
if (item === 255) {
|
|
iv.writeUInt8(0, len)
|
|
} else {
|
|
item++
|
|
iv.writeUInt8(item, len)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
module.exports = incr32
|
|
|
|
},{}],60:[function(require,module,exports){
|
|
var xor = require('buffer-xor')
|
|
|
|
exports.encrypt = function (self, block) {
|
|
var data = xor(block, self._prev)
|
|
|
|
self._prev = self._cipher.encryptBlock(data)
|
|
return self._prev
|
|
}
|
|
|
|
exports.decrypt = function (self, block) {
|
|
var pad = self._prev
|
|
|
|
self._prev = block
|
|
var out = self._cipher.decryptBlock(block)
|
|
|
|
return xor(out, pad)
|
|
}
|
|
|
|
},{"buffer-xor":69}],61:[function(require,module,exports){
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var xor = require('buffer-xor')
|
|
|
|
function encryptStart (self, data, decrypt) {
|
|
var len = data.length
|
|
var out = xor(data, self._cache)
|
|
self._cache = self._cache.slice(len)
|
|
self._prev = Buffer.concat([self._prev, decrypt ? data : out])
|
|
return out
|
|
}
|
|
|
|
exports.encrypt = function (self, data, decrypt) {
|
|
var out = Buffer.allocUnsafe(0)
|
|
var len
|
|
|
|
while (data.length) {
|
|
if (self._cache.length === 0) {
|
|
self._cache = self._cipher.encryptBlock(self._prev)
|
|
self._prev = Buffer.allocUnsafe(0)
|
|
}
|
|
|
|
if (self._cache.length <= data.length) {
|
|
len = self._cache.length
|
|
out = Buffer.concat([out, encryptStart(self, data.slice(0, len), decrypt)])
|
|
data = data.slice(len)
|
|
} else {
|
|
out = Buffer.concat([out, encryptStart(self, data, decrypt)])
|
|
break
|
|
}
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
},{"buffer-xor":69,"safe-buffer":71}],62:[function(require,module,exports){
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
function encryptByte (self, byteParam, decrypt) {
|
|
var pad
|
|
var i = -1
|
|
var len = 8
|
|
var out = 0
|
|
var bit, value
|
|
while (++i < len) {
|
|
pad = self._cipher.encryptBlock(self._prev)
|
|
bit = (byteParam & (1 << (7 - i))) ? 0x80 : 0
|
|
value = pad[0] ^ bit
|
|
out += ((value & 0x80) >> (i % 8))
|
|
self._prev = shiftIn(self._prev, decrypt ? bit : value)
|
|
}
|
|
return out
|
|
}
|
|
|
|
function shiftIn (buffer, value) {
|
|
var len = buffer.length
|
|
var i = -1
|
|
var out = Buffer.allocUnsafe(buffer.length)
|
|
buffer = Buffer.concat([buffer, Buffer.from([value])])
|
|
|
|
while (++i < len) {
|
|
out[i] = buffer[i] << 1 | buffer[i + 1] >> (7)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
exports.encrypt = function (self, chunk, decrypt) {
|
|
var len = chunk.length
|
|
var out = Buffer.allocUnsafe(len)
|
|
var i = -1
|
|
|
|
while (++i < len) {
|
|
out[i] = encryptByte(self, chunk[i], decrypt)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
},{"safe-buffer":71}],63:[function(require,module,exports){
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
function encryptByte (self, byteParam, decrypt) {
|
|
var pad = self._cipher.encryptBlock(self._prev)
|
|
var out = pad[0] ^ byteParam
|
|
|
|
self._prev = Buffer.concat([
|
|
self._prev.slice(1),
|
|
Buffer.from([decrypt ? byteParam : out])
|
|
])
|
|
|
|
return out
|
|
}
|
|
|
|
exports.encrypt = function (self, chunk, decrypt) {
|
|
var len = chunk.length
|
|
var out = Buffer.allocUnsafe(len)
|
|
var i = -1
|
|
|
|
while (++i < len) {
|
|
out[i] = encryptByte(self, chunk[i], decrypt)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
},{"safe-buffer":71}],64:[function(require,module,exports){
|
|
var xor = require('buffer-xor')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var incr32 = require('../incr32')
|
|
|
|
function getBlock (self) {
|
|
var out = self._cipher.encryptBlockRaw(self._prev)
|
|
incr32(self._prev)
|
|
return out
|
|
}
|
|
|
|
var blockSize = 16
|
|
exports.encrypt = function (self, chunk) {
|
|
var chunkNum = Math.ceil(chunk.length / blockSize)
|
|
var start = self._cache.length
|
|
self._cache = Buffer.concat([
|
|
self._cache,
|
|
Buffer.allocUnsafe(chunkNum * blockSize)
|
|
])
|
|
for (var i = 0; i < chunkNum; i++) {
|
|
var out = getBlock(self)
|
|
var offset = start + i * blockSize
|
|
self._cache.writeUInt32BE(out[0], offset + 0)
|
|
self._cache.writeUInt32BE(out[1], offset + 4)
|
|
self._cache.writeUInt32BE(out[2], offset + 8)
|
|
self._cache.writeUInt32BE(out[3], offset + 12)
|
|
}
|
|
var pad = self._cache.slice(0, chunk.length)
|
|
self._cache = self._cache.slice(chunk.length)
|
|
return xor(chunk, pad)
|
|
}
|
|
|
|
},{"../incr32":59,"buffer-xor":69,"safe-buffer":71}],65:[function(require,module,exports){
|
|
exports.encrypt = function (self, block) {
|
|
return self._cipher.encryptBlock(block)
|
|
}
|
|
|
|
exports.decrypt = function (self, block) {
|
|
return self._cipher.decryptBlock(block)
|
|
}
|
|
|
|
},{}],66:[function(require,module,exports){
|
|
var modeModules = {
|
|
ECB: require('./ecb'),
|
|
CBC: require('./cbc'),
|
|
CFB: require('./cfb'),
|
|
CFB8: require('./cfb8'),
|
|
CFB1: require('./cfb1'),
|
|
OFB: require('./ofb'),
|
|
CTR: require('./ctr'),
|
|
GCM: require('./ctr')
|
|
}
|
|
|
|
var modes = require('./list.json')
|
|
|
|
for (var key in modes) {
|
|
modes[key].module = modeModules[modes[key].mode]
|
|
}
|
|
|
|
module.exports = modes
|
|
|
|
},{"./cbc":60,"./cfb":61,"./cfb1":62,"./cfb8":63,"./ctr":64,"./ecb":65,"./list.json":67,"./ofb":68}],67:[function(require,module,exports){
|
|
module.exports={
|
|
"aes-128-ecb": {
|
|
"cipher": "AES",
|
|
"key": 128,
|
|
"iv": 0,
|
|
"mode": "ECB",
|
|
"type": "block"
|
|
},
|
|
"aes-192-ecb": {
|
|
"cipher": "AES",
|
|
"key": 192,
|
|
"iv": 0,
|
|
"mode": "ECB",
|
|
"type": "block"
|
|
},
|
|
"aes-256-ecb": {
|
|
"cipher": "AES",
|
|
"key": 256,
|
|
"iv": 0,
|
|
"mode": "ECB",
|
|
"type": "block"
|
|
},
|
|
"aes-128-cbc": {
|
|
"cipher": "AES",
|
|
"key": 128,
|
|
"iv": 16,
|
|
"mode": "CBC",
|
|
"type": "block"
|
|
},
|
|
"aes-192-cbc": {
|
|
"cipher": "AES",
|
|
"key": 192,
|
|
"iv": 16,
|
|
"mode": "CBC",
|
|
"type": "block"
|
|
},
|
|
"aes-256-cbc": {
|
|
"cipher": "AES",
|
|
"key": 256,
|
|
"iv": 16,
|
|
"mode": "CBC",
|
|
"type": "block"
|
|
},
|
|
"aes128": {
|
|
"cipher": "AES",
|
|
"key": 128,
|
|
"iv": 16,
|
|
"mode": "CBC",
|
|
"type": "block"
|
|
},
|
|
"aes192": {
|
|
"cipher": "AES",
|
|
"key": 192,
|
|
"iv": 16,
|
|
"mode": "CBC",
|
|
"type": "block"
|
|
},
|
|
"aes256": {
|
|
"cipher": "AES",
|
|
"key": 256,
|
|
"iv": 16,
|
|
"mode": "CBC",
|
|
"type": "block"
|
|
},
|
|
"aes-128-cfb": {
|
|
"cipher": "AES",
|
|
"key": 128,
|
|
"iv": 16,
|
|
"mode": "CFB",
|
|
"type": "stream"
|
|
},
|
|
"aes-192-cfb": {
|
|
"cipher": "AES",
|
|
"key": 192,
|
|
"iv": 16,
|
|
"mode": "CFB",
|
|
"type": "stream"
|
|
},
|
|
"aes-256-cfb": {
|
|
"cipher": "AES",
|
|
"key": 256,
|
|
"iv": 16,
|
|
"mode": "CFB",
|
|
"type": "stream"
|
|
},
|
|
"aes-128-cfb8": {
|
|
"cipher": "AES",
|
|
"key": 128,
|
|
"iv": 16,
|
|
"mode": "CFB8",
|
|
"type": "stream"
|
|
},
|
|
"aes-192-cfb8": {
|
|
"cipher": "AES",
|
|
"key": 192,
|
|
"iv": 16,
|
|
"mode": "CFB8",
|
|
"type": "stream"
|
|
},
|
|
"aes-256-cfb8": {
|
|
"cipher": "AES",
|
|
"key": 256,
|
|
"iv": 16,
|
|
"mode": "CFB8",
|
|
"type": "stream"
|
|
},
|
|
"aes-128-cfb1": {
|
|
"cipher": "AES",
|
|
"key": 128,
|
|
"iv": 16,
|
|
"mode": "CFB1",
|
|
"type": "stream"
|
|
},
|
|
"aes-192-cfb1": {
|
|
"cipher": "AES",
|
|
"key": 192,
|
|
"iv": 16,
|
|
"mode": "CFB1",
|
|
"type": "stream"
|
|
},
|
|
"aes-256-cfb1": {
|
|
"cipher": "AES",
|
|
"key": 256,
|
|
"iv": 16,
|
|
"mode": "CFB1",
|
|
"type": "stream"
|
|
},
|
|
"aes-128-ofb": {
|
|
"cipher": "AES",
|
|
"key": 128,
|
|
"iv": 16,
|
|
"mode": "OFB",
|
|
"type": "stream"
|
|
},
|
|
"aes-192-ofb": {
|
|
"cipher": "AES",
|
|
"key": 192,
|
|
"iv": 16,
|
|
"mode": "OFB",
|
|
"type": "stream"
|
|
},
|
|
"aes-256-ofb": {
|
|
"cipher": "AES",
|
|
"key": 256,
|
|
"iv": 16,
|
|
"mode": "OFB",
|
|
"type": "stream"
|
|
},
|
|
"aes-128-ctr": {
|
|
"cipher": "AES",
|
|
"key": 128,
|
|
"iv": 16,
|
|
"mode": "CTR",
|
|
"type": "stream"
|
|
},
|
|
"aes-192-ctr": {
|
|
"cipher": "AES",
|
|
"key": 192,
|
|
"iv": 16,
|
|
"mode": "CTR",
|
|
"type": "stream"
|
|
},
|
|
"aes-256-ctr": {
|
|
"cipher": "AES",
|
|
"key": 256,
|
|
"iv": 16,
|
|
"mode": "CTR",
|
|
"type": "stream"
|
|
},
|
|
"aes-128-gcm": {
|
|
"cipher": "AES",
|
|
"key": 128,
|
|
"iv": 12,
|
|
"mode": "GCM",
|
|
"type": "auth"
|
|
},
|
|
"aes-192-gcm": {
|
|
"cipher": "AES",
|
|
"key": 192,
|
|
"iv": 12,
|
|
"mode": "GCM",
|
|
"type": "auth"
|
|
},
|
|
"aes-256-gcm": {
|
|
"cipher": "AES",
|
|
"key": 256,
|
|
"iv": 12,
|
|
"mode": "GCM",
|
|
"type": "auth"
|
|
}
|
|
}
|
|
|
|
},{}],68:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var xor = require('buffer-xor')
|
|
|
|
function getBlock (self) {
|
|
self._prev = self._cipher.encryptBlock(self._prev)
|
|
return self._prev
|
|
}
|
|
|
|
exports.encrypt = function (self, chunk) {
|
|
while (self._cache.length < chunk.length) {
|
|
self._cache = Buffer.concat([self._cache, getBlock(self)])
|
|
}
|
|
|
|
var pad = self._cache.slice(0, chunk.length)
|
|
self._cache = self._cache.slice(chunk.length)
|
|
return xor(chunk, pad)
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"buffer":47,"buffer-xor":69}],69:[function(require,module,exports){
|
|
(function (Buffer){
|
|
module.exports = function xor (a, b) {
|
|
var length = Math.min(a.length, b.length)
|
|
var buffer = new Buffer(length)
|
|
|
|
for (var i = 0; i < length; ++i) {
|
|
buffer[i] = a[i] ^ b[i]
|
|
}
|
|
|
|
return buffer
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"buffer":47}],70:[function(require,module,exports){
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var Transform = require('stream').Transform
|
|
var StringDecoder = require('string_decoder').StringDecoder
|
|
var inherits = require('inherits')
|
|
|
|
function CipherBase (hashMode) {
|
|
Transform.call(this)
|
|
this.hashMode = typeof hashMode === 'string'
|
|
if (this.hashMode) {
|
|
this[hashMode] = this._finalOrDigest
|
|
} else {
|
|
this.final = this._finalOrDigest
|
|
}
|
|
if (this._final) {
|
|
this.__final = this._final
|
|
this._final = null
|
|
}
|
|
this._decoder = null
|
|
this._encoding = null
|
|
}
|
|
inherits(CipherBase, Transform)
|
|
|
|
CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
|
|
if (typeof data === 'string') {
|
|
data = Buffer.from(data, inputEnc)
|
|
}
|
|
|
|
var outData = this._update(data)
|
|
if (this.hashMode) return this
|
|
|
|
if (outputEnc) {
|
|
outData = this._toString(outData, outputEnc)
|
|
}
|
|
|
|
return outData
|
|
}
|
|
|
|
CipherBase.prototype.setAutoPadding = function () {}
|
|
CipherBase.prototype.getAuthTag = function () {
|
|
throw new Error('trying to get auth tag in unsupported state')
|
|
}
|
|
|
|
CipherBase.prototype.setAuthTag = function () {
|
|
throw new Error('trying to set auth tag in unsupported state')
|
|
}
|
|
|
|
CipherBase.prototype.setAAD = function () {
|
|
throw new Error('trying to set aad in unsupported state')
|
|
}
|
|
|
|
CipherBase.prototype._transform = function (data, _, next) {
|
|
var err
|
|
try {
|
|
if (this.hashMode) {
|
|
this._update(data)
|
|
} else {
|
|
this.push(this._update(data))
|
|
}
|
|
} catch (e) {
|
|
err = e
|
|
} finally {
|
|
next(err)
|
|
}
|
|
}
|
|
CipherBase.prototype._flush = function (done) {
|
|
var err
|
|
try {
|
|
this.push(this.__final())
|
|
} catch (e) {
|
|
err = e
|
|
}
|
|
|
|
done(err)
|
|
}
|
|
CipherBase.prototype._finalOrDigest = function (outputEnc) {
|
|
var outData = this.__final() || Buffer.alloc(0)
|
|
if (outputEnc) {
|
|
outData = this._toString(outData, outputEnc, true)
|
|
}
|
|
return outData
|
|
}
|
|
|
|
CipherBase.prototype._toString = function (value, enc, fin) {
|
|
if (!this._decoder) {
|
|
this._decoder = new StringDecoder(enc)
|
|
this._encoding = enc
|
|
}
|
|
|
|
if (this._encoding !== enc) throw new Error('can\'t switch encodings')
|
|
|
|
var out = this._decoder.write(value)
|
|
if (fin) {
|
|
out += this._decoder.end()
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
module.exports = CipherBase
|
|
|
|
},{"inherits":318,"safe-buffer":71,"stream":272,"string_decoder":273}],71:[function(require,module,exports){
|
|
/* eslint-disable node/no-deprecated-api */
|
|
var buffer = require('buffer')
|
|
var Buffer = buffer.Buffer
|
|
|
|
// alternative to using Object.keys for old browsers
|
|
function copyProps (src, dst) {
|
|
for (var key in src) {
|
|
dst[key] = src[key]
|
|
}
|
|
}
|
|
if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) {
|
|
module.exports = buffer
|
|
} else {
|
|
// Copy properties from require('buffer')
|
|
copyProps(buffer, exports)
|
|
exports.Buffer = SafeBuffer
|
|
}
|
|
|
|
function SafeBuffer (arg, encodingOrOffset, length) {
|
|
return Buffer(arg, encodingOrOffset, length)
|
|
}
|
|
|
|
// Copy static methods from Buffer
|
|
copyProps(Buffer, SafeBuffer)
|
|
|
|
SafeBuffer.from = function (arg, encodingOrOffset, length) {
|
|
if (typeof arg === 'number') {
|
|
throw new TypeError('Argument must not be a number')
|
|
}
|
|
return Buffer(arg, encodingOrOffset, length)
|
|
}
|
|
|
|
SafeBuffer.alloc = function (size, fill, encoding) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('Argument must be a number')
|
|
}
|
|
var buf = Buffer(size)
|
|
if (fill !== undefined) {
|
|
if (typeof encoding === 'string') {
|
|
buf.fill(fill, encoding)
|
|
} else {
|
|
buf.fill(fill)
|
|
}
|
|
} else {
|
|
buf.fill(0)
|
|
}
|
|
return buf
|
|
}
|
|
|
|
SafeBuffer.allocUnsafe = function (size) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('Argument must be a number')
|
|
}
|
|
return Buffer(size)
|
|
}
|
|
|
|
SafeBuffer.allocUnsafeSlow = function (size) {
|
|
if (typeof size !== 'number') {
|
|
throw new TypeError('Argument must be a number')
|
|
}
|
|
return buffer.SlowBuffer(size)
|
|
}
|
|
|
|
},{"buffer":47}],72:[function(require,module,exports){
|
|
var aes = require('./aes')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var Transform = require('cipher-base')
|
|
var inherits = require('inherits')
|
|
|
|
function StreamCipher (mode, key, iv, decrypt) {
|
|
Transform.call(this)
|
|
|
|
this._cipher = new aes.AES(key)
|
|
this._prev = Buffer.from(iv)
|
|
this._cache = Buffer.allocUnsafe(0)
|
|
this._secCache = Buffer.allocUnsafe(0)
|
|
this._decrypt = decrypt
|
|
this._mode = mode
|
|
}
|
|
|
|
inherits(StreamCipher, Transform)
|
|
|
|
StreamCipher.prototype._update = function (chunk) {
|
|
return this._mode.encrypt(this, chunk, this._decrypt)
|
|
}
|
|
|
|
StreamCipher.prototype._final = function () {
|
|
this._cipher.scrub()
|
|
}
|
|
|
|
module.exports = StreamCipher
|
|
|
|
},{"./aes":53,"cipher-base":70,"inherits":318,"safe-buffer":71}],73:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var CipherBase = require('cipher-base')
|
|
var des = require('des.js')
|
|
var inherits = require('inherits')
|
|
|
|
var modes = {
|
|
'des-ede3-cbc': des.CBC.instantiate(des.EDE),
|
|
'des-ede3': des.EDE,
|
|
'des-ede-cbc': des.CBC.instantiate(des.EDE),
|
|
'des-ede': des.EDE,
|
|
'des-cbc': des.CBC.instantiate(des.DES),
|
|
'des-ecb': des.DES
|
|
}
|
|
modes.des = modes['des-cbc']
|
|
modes.des3 = modes['des-ede3-cbc']
|
|
module.exports = DES
|
|
inherits(DES, CipherBase)
|
|
function DES (opts) {
|
|
CipherBase.call(this)
|
|
var modeName = opts.mode.toLowerCase()
|
|
var mode = modes[modeName]
|
|
var type
|
|
if (opts.decrypt) {
|
|
type = 'decrypt'
|
|
} else {
|
|
type = 'encrypt'
|
|
}
|
|
var key = opts.key
|
|
if (modeName === 'des-ede' || modeName === 'des-ede-cbc') {
|
|
key = Buffer.concat([key, key.slice(0, 8)])
|
|
}
|
|
var iv = opts.iv
|
|
this._des = mode.create({
|
|
key: key,
|
|
iv: iv,
|
|
type: type
|
|
})
|
|
}
|
|
DES.prototype._update = function (data) {
|
|
return new Buffer(this._des.update(data))
|
|
}
|
|
DES.prototype._final = function () {
|
|
return new Buffer(this._des.final())
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"buffer":47,"cipher-base":75,"des.js":77,"inherits":318}],74:[function(require,module,exports){
|
|
exports['des-ecb'] = {
|
|
key: 8,
|
|
iv: 0
|
|
}
|
|
exports['des-cbc'] = exports.des = {
|
|
key: 8,
|
|
iv: 8
|
|
}
|
|
exports['des-ede3-cbc'] = exports.des3 = {
|
|
key: 24,
|
|
iv: 8
|
|
}
|
|
exports['des-ede3'] = {
|
|
key: 24,
|
|
iv: 0
|
|
}
|
|
exports['des-ede-cbc'] = {
|
|
key: 16,
|
|
iv: 8
|
|
}
|
|
exports['des-ede'] = {
|
|
key: 16,
|
|
iv: 0
|
|
}
|
|
|
|
},{}],75:[function(require,module,exports){
|
|
arguments[4][70][0].apply(exports,arguments)
|
|
},{"dup":70,"inherits":318,"safe-buffer":76,"stream":272,"string_decoder":273}],76:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],77:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
exports.utils = require('./des/utils');
|
|
exports.Cipher = require('./des/cipher');
|
|
exports.DES = require('./des/des');
|
|
exports.CBC = require('./des/cbc');
|
|
exports.EDE = require('./des/ede');
|
|
|
|
},{"./des/cbc":78,"./des/cipher":79,"./des/des":80,"./des/ede":81,"./des/utils":82}],78:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var assert = require('minimalistic-assert');
|
|
var inherits = require('inherits');
|
|
|
|
var proto = {};
|
|
|
|
function CBCState(iv) {
|
|
assert.equal(iv.length, 8, 'Invalid IV length');
|
|
|
|
this.iv = new Array(8);
|
|
for (var i = 0; i < this.iv.length; i++)
|
|
this.iv[i] = iv[i];
|
|
}
|
|
|
|
function instantiate(Base) {
|
|
function CBC(options) {
|
|
Base.call(this, options);
|
|
this._cbcInit();
|
|
}
|
|
inherits(CBC, Base);
|
|
|
|
var keys = Object.keys(proto);
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var key = keys[i];
|
|
CBC.prototype[key] = proto[key];
|
|
}
|
|
|
|
CBC.create = function create(options) {
|
|
return new CBC(options);
|
|
};
|
|
|
|
return CBC;
|
|
}
|
|
|
|
exports.instantiate = instantiate;
|
|
|
|
proto._cbcInit = function _cbcInit() {
|
|
var state = new CBCState(this.options.iv);
|
|
this._cbcState = state;
|
|
};
|
|
|
|
proto._update = function _update(inp, inOff, out, outOff) {
|
|
var state = this._cbcState;
|
|
var superProto = this.constructor.super_.prototype;
|
|
|
|
var iv = state.iv;
|
|
if (this.type === 'encrypt') {
|
|
for (var i = 0; i < this.blockSize; i++)
|
|
iv[i] ^= inp[inOff + i];
|
|
|
|
superProto._update.call(this, iv, 0, out, outOff);
|
|
|
|
for (var i = 0; i < this.blockSize; i++)
|
|
iv[i] = out[outOff + i];
|
|
} else {
|
|
superProto._update.call(this, inp, inOff, out, outOff);
|
|
|
|
for (var i = 0; i < this.blockSize; i++)
|
|
out[outOff + i] ^= iv[i];
|
|
|
|
for (var i = 0; i < this.blockSize; i++)
|
|
iv[i] = inp[inOff + i];
|
|
}
|
|
};
|
|
|
|
},{"inherits":318,"minimalistic-assert":83}],79:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var assert = require('minimalistic-assert');
|
|
|
|
function Cipher(options) {
|
|
this.options = options;
|
|
|
|
this.type = this.options.type;
|
|
this.blockSize = 8;
|
|
this._init();
|
|
|
|
this.buffer = new Array(this.blockSize);
|
|
this.bufferOff = 0;
|
|
}
|
|
module.exports = Cipher;
|
|
|
|
Cipher.prototype._init = function _init() {
|
|
// Might be overrided
|
|
};
|
|
|
|
Cipher.prototype.update = function update(data) {
|
|
if (data.length === 0)
|
|
return [];
|
|
|
|
if (this.type === 'decrypt')
|
|
return this._updateDecrypt(data);
|
|
else
|
|
return this._updateEncrypt(data);
|
|
};
|
|
|
|
Cipher.prototype._buffer = function _buffer(data, off) {
|
|
// Append data to buffer
|
|
var min = Math.min(this.buffer.length - this.bufferOff, data.length - off);
|
|
for (var i = 0; i < min; i++)
|
|
this.buffer[this.bufferOff + i] = data[off + i];
|
|
this.bufferOff += min;
|
|
|
|
// Shift next
|
|
return min;
|
|
};
|
|
|
|
Cipher.prototype._flushBuffer = function _flushBuffer(out, off) {
|
|
this._update(this.buffer, 0, out, off);
|
|
this.bufferOff = 0;
|
|
return this.blockSize;
|
|
};
|
|
|
|
Cipher.prototype._updateEncrypt = function _updateEncrypt(data) {
|
|
var inputOff = 0;
|
|
var outputOff = 0;
|
|
|
|
var count = ((this.bufferOff + data.length) / this.blockSize) | 0;
|
|
var out = new Array(count * this.blockSize);
|
|
|
|
if (this.bufferOff !== 0) {
|
|
inputOff += this._buffer(data, inputOff);
|
|
|
|
if (this.bufferOff === this.buffer.length)
|
|
outputOff += this._flushBuffer(out, outputOff);
|
|
}
|
|
|
|
// Write blocks
|
|
var max = data.length - ((data.length - inputOff) % this.blockSize);
|
|
for (; inputOff < max; inputOff += this.blockSize) {
|
|
this._update(data, inputOff, out, outputOff);
|
|
outputOff += this.blockSize;
|
|
}
|
|
|
|
// Queue rest
|
|
for (; inputOff < data.length; inputOff++, this.bufferOff++)
|
|
this.buffer[this.bufferOff] = data[inputOff];
|
|
|
|
return out;
|
|
};
|
|
|
|
Cipher.prototype._updateDecrypt = function _updateDecrypt(data) {
|
|
var inputOff = 0;
|
|
var outputOff = 0;
|
|
|
|
var count = Math.ceil((this.bufferOff + data.length) / this.blockSize) - 1;
|
|
var out = new Array(count * this.blockSize);
|
|
|
|
// TODO(indutny): optimize it, this is far from optimal
|
|
for (; count > 0; count--) {
|
|
inputOff += this._buffer(data, inputOff);
|
|
outputOff += this._flushBuffer(out, outputOff);
|
|
}
|
|
|
|
// Buffer rest of the input
|
|
inputOff += this._buffer(data, inputOff);
|
|
|
|
return out;
|
|
};
|
|
|
|
Cipher.prototype.final = function final(buffer) {
|
|
var first;
|
|
if (buffer)
|
|
first = this.update(buffer);
|
|
|
|
var last;
|
|
if (this.type === 'encrypt')
|
|
last = this._finalEncrypt();
|
|
else
|
|
last = this._finalDecrypt();
|
|
|
|
if (first)
|
|
return first.concat(last);
|
|
else
|
|
return last;
|
|
};
|
|
|
|
Cipher.prototype._pad = function _pad(buffer, off) {
|
|
if (off === 0)
|
|
return false;
|
|
|
|
while (off < buffer.length)
|
|
buffer[off++] = 0;
|
|
|
|
return true;
|
|
};
|
|
|
|
Cipher.prototype._finalEncrypt = function _finalEncrypt() {
|
|
if (!this._pad(this.buffer, this.bufferOff))
|
|
return [];
|
|
|
|
var out = new Array(this.blockSize);
|
|
this._update(this.buffer, 0, out, 0);
|
|
return out;
|
|
};
|
|
|
|
Cipher.prototype._unpad = function _unpad(buffer) {
|
|
return buffer;
|
|
};
|
|
|
|
Cipher.prototype._finalDecrypt = function _finalDecrypt() {
|
|
assert.equal(this.bufferOff, this.blockSize, 'Not enough data to decrypt');
|
|
var out = new Array(this.blockSize);
|
|
this._flushBuffer(out, 0);
|
|
|
|
return this._unpad(out);
|
|
};
|
|
|
|
},{"minimalistic-assert":83}],80:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var assert = require('minimalistic-assert');
|
|
var inherits = require('inherits');
|
|
|
|
var des = require('../des');
|
|
var utils = des.utils;
|
|
var Cipher = des.Cipher;
|
|
|
|
function DESState() {
|
|
this.tmp = new Array(2);
|
|
this.keys = null;
|
|
}
|
|
|
|
function DES(options) {
|
|
Cipher.call(this, options);
|
|
|
|
var state = new DESState();
|
|
this._desState = state;
|
|
|
|
this.deriveKeys(state, options.key);
|
|
}
|
|
inherits(DES, Cipher);
|
|
module.exports = DES;
|
|
|
|
DES.create = function create(options) {
|
|
return new DES(options);
|
|
};
|
|
|
|
var shiftTable = [
|
|
1, 1, 2, 2, 2, 2, 2, 2,
|
|
1, 2, 2, 2, 2, 2, 2, 1
|
|
];
|
|
|
|
DES.prototype.deriveKeys = function deriveKeys(state, key) {
|
|
state.keys = new Array(16 * 2);
|
|
|
|
assert.equal(key.length, this.blockSize, 'Invalid key length');
|
|
|
|
var kL = utils.readUInt32BE(key, 0);
|
|
var kR = utils.readUInt32BE(key, 4);
|
|
|
|
utils.pc1(kL, kR, state.tmp, 0);
|
|
kL = state.tmp[0];
|
|
kR = state.tmp[1];
|
|
for (var i = 0; i < state.keys.length; i += 2) {
|
|
var shift = shiftTable[i >>> 1];
|
|
kL = utils.r28shl(kL, shift);
|
|
kR = utils.r28shl(kR, shift);
|
|
utils.pc2(kL, kR, state.keys, i);
|
|
}
|
|
};
|
|
|
|
DES.prototype._update = function _update(inp, inOff, out, outOff) {
|
|
var state = this._desState;
|
|
|
|
var l = utils.readUInt32BE(inp, inOff);
|
|
var r = utils.readUInt32BE(inp, inOff + 4);
|
|
|
|
// Initial Permutation
|
|
utils.ip(l, r, state.tmp, 0);
|
|
l = state.tmp[0];
|
|
r = state.tmp[1];
|
|
|
|
if (this.type === 'encrypt')
|
|
this._encrypt(state, l, r, state.tmp, 0);
|
|
else
|
|
this._decrypt(state, l, r, state.tmp, 0);
|
|
|
|
l = state.tmp[0];
|
|
r = state.tmp[1];
|
|
|
|
utils.writeUInt32BE(out, l, outOff);
|
|
utils.writeUInt32BE(out, r, outOff + 4);
|
|
};
|
|
|
|
DES.prototype._pad = function _pad(buffer, off) {
|
|
var value = buffer.length - off;
|
|
for (var i = off; i < buffer.length; i++)
|
|
buffer[i] = value;
|
|
|
|
return true;
|
|
};
|
|
|
|
DES.prototype._unpad = function _unpad(buffer) {
|
|
var pad = buffer[buffer.length - 1];
|
|
for (var i = buffer.length - pad; i < buffer.length; i++)
|
|
assert.equal(buffer[i], pad);
|
|
|
|
return buffer.slice(0, buffer.length - pad);
|
|
};
|
|
|
|
DES.prototype._encrypt = function _encrypt(state, lStart, rStart, out, off) {
|
|
var l = lStart;
|
|
var r = rStart;
|
|
|
|
// Apply f() x16 times
|
|
for (var i = 0; i < state.keys.length; i += 2) {
|
|
var keyL = state.keys[i];
|
|
var keyR = state.keys[i + 1];
|
|
|
|
// f(r, k)
|
|
utils.expand(r, state.tmp, 0);
|
|
|
|
keyL ^= state.tmp[0];
|
|
keyR ^= state.tmp[1];
|
|
var s = utils.substitute(keyL, keyR);
|
|
var f = utils.permute(s);
|
|
|
|
var t = r;
|
|
r = (l ^ f) >>> 0;
|
|
l = t;
|
|
}
|
|
|
|
// Reverse Initial Permutation
|
|
utils.rip(r, l, out, off);
|
|
};
|
|
|
|
DES.prototype._decrypt = function _decrypt(state, lStart, rStart, out, off) {
|
|
var l = rStart;
|
|
var r = lStart;
|
|
|
|
// Apply f() x16 times
|
|
for (var i = state.keys.length - 2; i >= 0; i -= 2) {
|
|
var keyL = state.keys[i];
|
|
var keyR = state.keys[i + 1];
|
|
|
|
// f(r, k)
|
|
utils.expand(l, state.tmp, 0);
|
|
|
|
keyL ^= state.tmp[0];
|
|
keyR ^= state.tmp[1];
|
|
var s = utils.substitute(keyL, keyR);
|
|
var f = utils.permute(s);
|
|
|
|
var t = l;
|
|
l = (r ^ f) >>> 0;
|
|
r = t;
|
|
}
|
|
|
|
// Reverse Initial Permutation
|
|
utils.rip(l, r, out, off);
|
|
};
|
|
|
|
},{"../des":77,"inherits":318,"minimalistic-assert":83}],81:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var assert = require('minimalistic-assert');
|
|
var inherits = require('inherits');
|
|
|
|
var des = require('../des');
|
|
var Cipher = des.Cipher;
|
|
var DES = des.DES;
|
|
|
|
function EDEState(type, key) {
|
|
assert.equal(key.length, 24, 'Invalid key length');
|
|
|
|
var k1 = key.slice(0, 8);
|
|
var k2 = key.slice(8, 16);
|
|
var k3 = key.slice(16, 24);
|
|
|
|
if (type === 'encrypt') {
|
|
this.ciphers = [
|
|
DES.create({ type: 'encrypt', key: k1 }),
|
|
DES.create({ type: 'decrypt', key: k2 }),
|
|
DES.create({ type: 'encrypt', key: k3 })
|
|
];
|
|
} else {
|
|
this.ciphers = [
|
|
DES.create({ type: 'decrypt', key: k3 }),
|
|
DES.create({ type: 'encrypt', key: k2 }),
|
|
DES.create({ type: 'decrypt', key: k1 })
|
|
];
|
|
}
|
|
}
|
|
|
|
function EDE(options) {
|
|
Cipher.call(this, options);
|
|
|
|
var state = new EDEState(this.type, this.options.key);
|
|
this._edeState = state;
|
|
}
|
|
inherits(EDE, Cipher);
|
|
|
|
module.exports = EDE;
|
|
|
|
EDE.create = function create(options) {
|
|
return new EDE(options);
|
|
};
|
|
|
|
EDE.prototype._update = function _update(inp, inOff, out, outOff) {
|
|
var state = this._edeState;
|
|
|
|
state.ciphers[0]._update(inp, inOff, out, outOff);
|
|
state.ciphers[1]._update(out, outOff, out, outOff);
|
|
state.ciphers[2]._update(out, outOff, out, outOff);
|
|
};
|
|
|
|
EDE.prototype._pad = DES.prototype._pad;
|
|
EDE.prototype._unpad = DES.prototype._unpad;
|
|
|
|
},{"../des":77,"inherits":318,"minimalistic-assert":83}],82:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
exports.readUInt32BE = function readUInt32BE(bytes, off) {
|
|
var res = (bytes[0 + off] << 24) |
|
|
(bytes[1 + off] << 16) |
|
|
(bytes[2 + off] << 8) |
|
|
bytes[3 + off];
|
|
return res >>> 0;
|
|
};
|
|
|
|
exports.writeUInt32BE = function writeUInt32BE(bytes, value, off) {
|
|
bytes[0 + off] = value >>> 24;
|
|
bytes[1 + off] = (value >>> 16) & 0xff;
|
|
bytes[2 + off] = (value >>> 8) & 0xff;
|
|
bytes[3 + off] = value & 0xff;
|
|
};
|
|
|
|
exports.ip = function ip(inL, inR, out, off) {
|
|
var outL = 0;
|
|
var outR = 0;
|
|
|
|
for (var i = 6; i >= 0; i -= 2) {
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outL <<= 1;
|
|
outL |= (inR >>> (j + i)) & 1;
|
|
}
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outL <<= 1;
|
|
outL |= (inL >>> (j + i)) & 1;
|
|
}
|
|
}
|
|
|
|
for (var i = 6; i >= 0; i -= 2) {
|
|
for (var j = 1; j <= 25; j += 8) {
|
|
outR <<= 1;
|
|
outR |= (inR >>> (j + i)) & 1;
|
|
}
|
|
for (var j = 1; j <= 25; j += 8) {
|
|
outR <<= 1;
|
|
outR |= (inL >>> (j + i)) & 1;
|
|
}
|
|
}
|
|
|
|
out[off + 0] = outL >>> 0;
|
|
out[off + 1] = outR >>> 0;
|
|
};
|
|
|
|
exports.rip = function rip(inL, inR, out, off) {
|
|
var outL = 0;
|
|
var outR = 0;
|
|
|
|
for (var i = 0; i < 4; i++) {
|
|
for (var j = 24; j >= 0; j -= 8) {
|
|
outL <<= 1;
|
|
outL |= (inR >>> (j + i)) & 1;
|
|
outL <<= 1;
|
|
outL |= (inL >>> (j + i)) & 1;
|
|
}
|
|
}
|
|
for (var i = 4; i < 8; i++) {
|
|
for (var j = 24; j >= 0; j -= 8) {
|
|
outR <<= 1;
|
|
outR |= (inR >>> (j + i)) & 1;
|
|
outR <<= 1;
|
|
outR |= (inL >>> (j + i)) & 1;
|
|
}
|
|
}
|
|
|
|
out[off + 0] = outL >>> 0;
|
|
out[off + 1] = outR >>> 0;
|
|
};
|
|
|
|
exports.pc1 = function pc1(inL, inR, out, off) {
|
|
var outL = 0;
|
|
var outR = 0;
|
|
|
|
// 7, 15, 23, 31, 39, 47, 55, 63
|
|
// 6, 14, 22, 30, 39, 47, 55, 63
|
|
// 5, 13, 21, 29, 39, 47, 55, 63
|
|
// 4, 12, 20, 28
|
|
for (var i = 7; i >= 5; i--) {
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outL <<= 1;
|
|
outL |= (inR >> (j + i)) & 1;
|
|
}
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outL <<= 1;
|
|
outL |= (inL >> (j + i)) & 1;
|
|
}
|
|
}
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outL <<= 1;
|
|
outL |= (inR >> (j + i)) & 1;
|
|
}
|
|
|
|
// 1, 9, 17, 25, 33, 41, 49, 57
|
|
// 2, 10, 18, 26, 34, 42, 50, 58
|
|
// 3, 11, 19, 27, 35, 43, 51, 59
|
|
// 36, 44, 52, 60
|
|
for (var i = 1; i <= 3; i++) {
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outR <<= 1;
|
|
outR |= (inR >> (j + i)) & 1;
|
|
}
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outR <<= 1;
|
|
outR |= (inL >> (j + i)) & 1;
|
|
}
|
|
}
|
|
for (var j = 0; j <= 24; j += 8) {
|
|
outR <<= 1;
|
|
outR |= (inL >> (j + i)) & 1;
|
|
}
|
|
|
|
out[off + 0] = outL >>> 0;
|
|
out[off + 1] = outR >>> 0;
|
|
};
|
|
|
|
exports.r28shl = function r28shl(num, shift) {
|
|
return ((num << shift) & 0xfffffff) | (num >>> (28 - shift));
|
|
};
|
|
|
|
var pc2table = [
|
|
// inL => outL
|
|
14, 11, 17, 4, 27, 23, 25, 0,
|
|
13, 22, 7, 18, 5, 9, 16, 24,
|
|
2, 20, 12, 21, 1, 8, 15, 26,
|
|
|
|
// inR => outR
|
|
15, 4, 25, 19, 9, 1, 26, 16,
|
|
5, 11, 23, 8, 12, 7, 17, 0,
|
|
22, 3, 10, 14, 6, 20, 27, 24
|
|
];
|
|
|
|
exports.pc2 = function pc2(inL, inR, out, off) {
|
|
var outL = 0;
|
|
var outR = 0;
|
|
|
|
var len = pc2table.length >>> 1;
|
|
for (var i = 0; i < len; i++) {
|
|
outL <<= 1;
|
|
outL |= (inL >>> pc2table[i]) & 0x1;
|
|
}
|
|
for (var i = len; i < pc2table.length; i++) {
|
|
outR <<= 1;
|
|
outR |= (inR >>> pc2table[i]) & 0x1;
|
|
}
|
|
|
|
out[off + 0] = outL >>> 0;
|
|
out[off + 1] = outR >>> 0;
|
|
};
|
|
|
|
exports.expand = function expand(r, out, off) {
|
|
var outL = 0;
|
|
var outR = 0;
|
|
|
|
outL = ((r & 1) << 5) | (r >>> 27);
|
|
for (var i = 23; i >= 15; i -= 4) {
|
|
outL <<= 6;
|
|
outL |= (r >>> i) & 0x3f;
|
|
}
|
|
for (var i = 11; i >= 3; i -= 4) {
|
|
outR |= (r >>> i) & 0x3f;
|
|
outR <<= 6;
|
|
}
|
|
outR |= ((r & 0x1f) << 1) | (r >>> 31);
|
|
|
|
out[off + 0] = outL >>> 0;
|
|
out[off + 1] = outR >>> 0;
|
|
};
|
|
|
|
var sTable = [
|
|
14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
|
|
3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
|
|
4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
|
|
15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13,
|
|
|
|
15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
|
|
9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
|
|
0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
|
|
5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9,
|
|
|
|
10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
|
|
1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
|
|
13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
|
|
11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12,
|
|
|
|
7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
|
|
1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
|
|
10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
|
|
15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14,
|
|
|
|
2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
|
|
8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
|
|
4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
|
|
15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3,
|
|
|
|
12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
|
|
0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
|
|
9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
|
|
7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13,
|
|
|
|
4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
|
|
3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
|
|
1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
|
|
10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12,
|
|
|
|
13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
|
|
10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
|
|
7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
|
|
0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
|
|
];
|
|
|
|
exports.substitute = function substitute(inL, inR) {
|
|
var out = 0;
|
|
for (var i = 0; i < 4; i++) {
|
|
var b = (inL >>> (18 - i * 6)) & 0x3f;
|
|
var sb = sTable[i * 0x40 + b];
|
|
|
|
out <<= 4;
|
|
out |= sb;
|
|
}
|
|
for (var i = 0; i < 4; i++) {
|
|
var b = (inR >>> (18 - i * 6)) & 0x3f;
|
|
var sb = sTable[4 * 0x40 + i * 0x40 + b];
|
|
|
|
out <<= 4;
|
|
out |= sb;
|
|
}
|
|
return out >>> 0;
|
|
};
|
|
|
|
var permuteTable = [
|
|
16, 25, 12, 11, 3, 20, 4, 15, 31, 17, 9, 6, 27, 14, 1, 22,
|
|
30, 24, 8, 18, 0, 5, 29, 23, 13, 19, 2, 26, 10, 21, 28, 7
|
|
];
|
|
|
|
exports.permute = function permute(num) {
|
|
var out = 0;
|
|
for (var i = 0; i < permuteTable.length; i++) {
|
|
out <<= 1;
|
|
out |= (num >>> permuteTable[i]) & 0x1;
|
|
}
|
|
return out >>> 0;
|
|
};
|
|
|
|
exports.padSplit = function padSplit(num, size, group) {
|
|
var str = num.toString(2);
|
|
while (str.length < size)
|
|
str = '0' + str;
|
|
|
|
var out = [];
|
|
for (var i = 0; i < size; i += group)
|
|
out.push(str.slice(i, i + group));
|
|
return out.join(' ');
|
|
};
|
|
|
|
},{}],83:[function(require,module,exports){
|
|
module.exports = assert;
|
|
|
|
function assert(val, msg) {
|
|
if (!val)
|
|
throw new Error(msg || 'Assertion failed');
|
|
}
|
|
|
|
assert.equal = function assertEqual(l, r, msg) {
|
|
if (l != r)
|
|
throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r));
|
|
};
|
|
|
|
},{}],84:[function(require,module,exports){
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var MD5 = require('md5.js')
|
|
|
|
/* eslint-disable camelcase */
|
|
function EVP_BytesToKey (password, salt, keyBits, ivLen) {
|
|
if (!Buffer.isBuffer(password)) password = Buffer.from(password, 'binary')
|
|
if (salt) {
|
|
if (!Buffer.isBuffer(salt)) salt = Buffer.from(salt, 'binary')
|
|
if (salt.length !== 8) throw new RangeError('salt should be Buffer with 8 byte length')
|
|
}
|
|
|
|
var keyLen = keyBits / 8
|
|
var key = Buffer.alloc(keyLen)
|
|
var iv = Buffer.alloc(ivLen || 0)
|
|
var tmp = Buffer.alloc(0)
|
|
|
|
while (keyLen > 0 || ivLen > 0) {
|
|
var hash = new MD5()
|
|
hash.update(tmp)
|
|
hash.update(password)
|
|
if (salt) hash.update(salt)
|
|
tmp = hash.digest()
|
|
|
|
var used = 0
|
|
|
|
if (keyLen > 0) {
|
|
var keyStart = key.length - keyLen
|
|
used = Math.min(keyLen, tmp.length)
|
|
tmp.copy(key, keyStart, 0, used)
|
|
keyLen -= used
|
|
}
|
|
|
|
if (used < tmp.length && ivLen > 0) {
|
|
var ivStart = iv.length - ivLen
|
|
var length = Math.min(ivLen, tmp.length - used)
|
|
tmp.copy(iv, ivStart, used, used + length)
|
|
ivLen -= length
|
|
}
|
|
}
|
|
|
|
tmp.fill(0)
|
|
return { key: key, iv: iv }
|
|
}
|
|
|
|
module.exports = EVP_BytesToKey
|
|
|
|
},{"md5.js":85,"safe-buffer":87}],85:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict'
|
|
var inherits = require('inherits')
|
|
var HashBase = require('hash-base')
|
|
|
|
var ARRAY16 = new Array(16)
|
|
|
|
function MD5 () {
|
|
HashBase.call(this, 64)
|
|
|
|
// state
|
|
this._a = 0x67452301
|
|
this._b = 0xefcdab89
|
|
this._c = 0x98badcfe
|
|
this._d = 0x10325476
|
|
}
|
|
|
|
inherits(MD5, HashBase)
|
|
|
|
MD5.prototype._update = function () {
|
|
var M = ARRAY16
|
|
for (var i = 0; i < 16; ++i) M[i] = this._block.readInt32LE(i * 4)
|
|
|
|
var a = this._a
|
|
var b = this._b
|
|
var c = this._c
|
|
var d = this._d
|
|
|
|
a = fnF(a, b, c, d, M[0], 0xd76aa478, 7)
|
|
d = fnF(d, a, b, c, M[1], 0xe8c7b756, 12)
|
|
c = fnF(c, d, a, b, M[2], 0x242070db, 17)
|
|
b = fnF(b, c, d, a, M[3], 0xc1bdceee, 22)
|
|
a = fnF(a, b, c, d, M[4], 0xf57c0faf, 7)
|
|
d = fnF(d, a, b, c, M[5], 0x4787c62a, 12)
|
|
c = fnF(c, d, a, b, M[6], 0xa8304613, 17)
|
|
b = fnF(b, c, d, a, M[7], 0xfd469501, 22)
|
|
a = fnF(a, b, c, d, M[8], 0x698098d8, 7)
|
|
d = fnF(d, a, b, c, M[9], 0x8b44f7af, 12)
|
|
c = fnF(c, d, a, b, M[10], 0xffff5bb1, 17)
|
|
b = fnF(b, c, d, a, M[11], 0x895cd7be, 22)
|
|
a = fnF(a, b, c, d, M[12], 0x6b901122, 7)
|
|
d = fnF(d, a, b, c, M[13], 0xfd987193, 12)
|
|
c = fnF(c, d, a, b, M[14], 0xa679438e, 17)
|
|
b = fnF(b, c, d, a, M[15], 0x49b40821, 22)
|
|
|
|
a = fnG(a, b, c, d, M[1], 0xf61e2562, 5)
|
|
d = fnG(d, a, b, c, M[6], 0xc040b340, 9)
|
|
c = fnG(c, d, a, b, M[11], 0x265e5a51, 14)
|
|
b = fnG(b, c, d, a, M[0], 0xe9b6c7aa, 20)
|
|
a = fnG(a, b, c, d, M[5], 0xd62f105d, 5)
|
|
d = fnG(d, a, b, c, M[10], 0x02441453, 9)
|
|
c = fnG(c, d, a, b, M[15], 0xd8a1e681, 14)
|
|
b = fnG(b, c, d, a, M[4], 0xe7d3fbc8, 20)
|
|
a = fnG(a, b, c, d, M[9], 0x21e1cde6, 5)
|
|
d = fnG(d, a, b, c, M[14], 0xc33707d6, 9)
|
|
c = fnG(c, d, a, b, M[3], 0xf4d50d87, 14)
|
|
b = fnG(b, c, d, a, M[8], 0x455a14ed, 20)
|
|
a = fnG(a, b, c, d, M[13], 0xa9e3e905, 5)
|
|
d = fnG(d, a, b, c, M[2], 0xfcefa3f8, 9)
|
|
c = fnG(c, d, a, b, M[7], 0x676f02d9, 14)
|
|
b = fnG(b, c, d, a, M[12], 0x8d2a4c8a, 20)
|
|
|
|
a = fnH(a, b, c, d, M[5], 0xfffa3942, 4)
|
|
d = fnH(d, a, b, c, M[8], 0x8771f681, 11)
|
|
c = fnH(c, d, a, b, M[11], 0x6d9d6122, 16)
|
|
b = fnH(b, c, d, a, M[14], 0xfde5380c, 23)
|
|
a = fnH(a, b, c, d, M[1], 0xa4beea44, 4)
|
|
d = fnH(d, a, b, c, M[4], 0x4bdecfa9, 11)
|
|
c = fnH(c, d, a, b, M[7], 0xf6bb4b60, 16)
|
|
b = fnH(b, c, d, a, M[10], 0xbebfbc70, 23)
|
|
a = fnH(a, b, c, d, M[13], 0x289b7ec6, 4)
|
|
d = fnH(d, a, b, c, M[0], 0xeaa127fa, 11)
|
|
c = fnH(c, d, a, b, M[3], 0xd4ef3085, 16)
|
|
b = fnH(b, c, d, a, M[6], 0x04881d05, 23)
|
|
a = fnH(a, b, c, d, M[9], 0xd9d4d039, 4)
|
|
d = fnH(d, a, b, c, M[12], 0xe6db99e5, 11)
|
|
c = fnH(c, d, a, b, M[15], 0x1fa27cf8, 16)
|
|
b = fnH(b, c, d, a, M[2], 0xc4ac5665, 23)
|
|
|
|
a = fnI(a, b, c, d, M[0], 0xf4292244, 6)
|
|
d = fnI(d, a, b, c, M[7], 0x432aff97, 10)
|
|
c = fnI(c, d, a, b, M[14], 0xab9423a7, 15)
|
|
b = fnI(b, c, d, a, M[5], 0xfc93a039, 21)
|
|
a = fnI(a, b, c, d, M[12], 0x655b59c3, 6)
|
|
d = fnI(d, a, b, c, M[3], 0x8f0ccc92, 10)
|
|
c = fnI(c, d, a, b, M[10], 0xffeff47d, 15)
|
|
b = fnI(b, c, d, a, M[1], 0x85845dd1, 21)
|
|
a = fnI(a, b, c, d, M[8], 0x6fa87e4f, 6)
|
|
d = fnI(d, a, b, c, M[15], 0xfe2ce6e0, 10)
|
|
c = fnI(c, d, a, b, M[6], 0xa3014314, 15)
|
|
b = fnI(b, c, d, a, M[13], 0x4e0811a1, 21)
|
|
a = fnI(a, b, c, d, M[4], 0xf7537e82, 6)
|
|
d = fnI(d, a, b, c, M[11], 0xbd3af235, 10)
|
|
c = fnI(c, d, a, b, M[2], 0x2ad7d2bb, 15)
|
|
b = fnI(b, c, d, a, M[9], 0xeb86d391, 21)
|
|
|
|
this._a = (this._a + a) | 0
|
|
this._b = (this._b + b) | 0
|
|
this._c = (this._c + c) | 0
|
|
this._d = (this._d + d) | 0
|
|
}
|
|
|
|
MD5.prototype._digest = function () {
|
|
// create padding and handle blocks
|
|
this._block[this._blockOffset++] = 0x80
|
|
if (this._blockOffset > 56) {
|
|
this._block.fill(0, this._blockOffset, 64)
|
|
this._update()
|
|
this._blockOffset = 0
|
|
}
|
|
|
|
this._block.fill(0, this._blockOffset, 56)
|
|
this._block.writeUInt32LE(this._length[0], 56)
|
|
this._block.writeUInt32LE(this._length[1], 60)
|
|
this._update()
|
|
|
|
// produce result
|
|
var buffer = new Buffer(16)
|
|
buffer.writeInt32LE(this._a, 0)
|
|
buffer.writeInt32LE(this._b, 4)
|
|
buffer.writeInt32LE(this._c, 8)
|
|
buffer.writeInt32LE(this._d, 12)
|
|
return buffer
|
|
}
|
|
|
|
function rotl (x, n) {
|
|
return (x << n) | (x >>> (32 - n))
|
|
}
|
|
|
|
function fnF (a, b, c, d, m, k, s) {
|
|
return (rotl((a + ((b & c) | ((~b) & d)) + m + k) | 0, s) + b) | 0
|
|
}
|
|
|
|
function fnG (a, b, c, d, m, k, s) {
|
|
return (rotl((a + ((b & d) | (c & (~d))) + m + k) | 0, s) + b) | 0
|
|
}
|
|
|
|
function fnH (a, b, c, d, m, k, s) {
|
|
return (rotl((a + (b ^ c ^ d) + m + k) | 0, s) + b) | 0
|
|
}
|
|
|
|
function fnI (a, b, c, d, m, k, s) {
|
|
return (rotl((a + ((c ^ (b | (~d)))) + m + k) | 0, s) + b) | 0
|
|
}
|
|
|
|
module.exports = MD5
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"buffer":47,"hash-base":86,"inherits":318}],86:[function(require,module,exports){
|
|
'use strict'
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var Transform = require('stream').Transform
|
|
var inherits = require('inherits')
|
|
|
|
function throwIfNotStringOrBuffer (val, prefix) {
|
|
if (!Buffer.isBuffer(val) && typeof val !== 'string') {
|
|
throw new TypeError(prefix + ' must be a string or a buffer')
|
|
}
|
|
}
|
|
|
|
function HashBase (blockSize) {
|
|
Transform.call(this)
|
|
|
|
this._block = Buffer.allocUnsafe(blockSize)
|
|
this._blockSize = blockSize
|
|
this._blockOffset = 0
|
|
this._length = [0, 0, 0, 0]
|
|
|
|
this._finalized = false
|
|
}
|
|
|
|
inherits(HashBase, Transform)
|
|
|
|
HashBase.prototype._transform = function (chunk, encoding, callback) {
|
|
var error = null
|
|
try {
|
|
this.update(chunk, encoding)
|
|
} catch (err) {
|
|
error = err
|
|
}
|
|
|
|
callback(error)
|
|
}
|
|
|
|
HashBase.prototype._flush = function (callback) {
|
|
var error = null
|
|
try {
|
|
this.push(this.digest())
|
|
} catch (err) {
|
|
error = err
|
|
}
|
|
|
|
callback(error)
|
|
}
|
|
|
|
HashBase.prototype.update = function (data, encoding) {
|
|
throwIfNotStringOrBuffer(data, 'Data')
|
|
if (this._finalized) throw new Error('Digest already called')
|
|
if (!Buffer.isBuffer(data)) data = Buffer.from(data, encoding)
|
|
|
|
// consume data
|
|
var block = this._block
|
|
var offset = 0
|
|
while (this._blockOffset + data.length - offset >= this._blockSize) {
|
|
for (var i = this._blockOffset; i < this._blockSize;) block[i++] = data[offset++]
|
|
this._update()
|
|
this._blockOffset = 0
|
|
}
|
|
while (offset < data.length) block[this._blockOffset++] = data[offset++]
|
|
|
|
// update length
|
|
for (var j = 0, carry = data.length * 8; carry > 0; ++j) {
|
|
this._length[j] += carry
|
|
carry = (this._length[j] / 0x0100000000) | 0
|
|
if (carry > 0) this._length[j] -= 0x0100000000 * carry
|
|
}
|
|
|
|
return this
|
|
}
|
|
|
|
HashBase.prototype._update = function () {
|
|
throw new Error('_update is not implemented')
|
|
}
|
|
|
|
HashBase.prototype.digest = function (encoding) {
|
|
if (this._finalized) throw new Error('Digest already called')
|
|
this._finalized = true
|
|
|
|
var digest = this._digest()
|
|
if (encoding !== undefined) digest = digest.toString(encoding)
|
|
|
|
// reset state
|
|
this._block.fill(0)
|
|
this._blockOffset = 0
|
|
for (var i = 0; i < 4; ++i) this._length[i] = 0
|
|
|
|
return digest
|
|
}
|
|
|
|
HashBase.prototype._digest = function () {
|
|
throw new Error('_digest is not implemented')
|
|
}
|
|
|
|
module.exports = HashBase
|
|
|
|
},{"inherits":318,"safe-buffer":87,"stream":272}],87:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],88:[function(require,module,exports){
|
|
module.exports = require('./browser/algorithms.json')
|
|
|
|
},{"./browser/algorithms.json":89}],89:[function(require,module,exports){
|
|
module.exports={
|
|
"sha224WithRSAEncryption": {
|
|
"sign": "rsa",
|
|
"hash": "sha224",
|
|
"id": "302d300d06096086480165030402040500041c"
|
|
},
|
|
"RSA-SHA224": {
|
|
"sign": "ecdsa/rsa",
|
|
"hash": "sha224",
|
|
"id": "302d300d06096086480165030402040500041c"
|
|
},
|
|
"sha256WithRSAEncryption": {
|
|
"sign": "rsa",
|
|
"hash": "sha256",
|
|
"id": "3031300d060960864801650304020105000420"
|
|
},
|
|
"RSA-SHA256": {
|
|
"sign": "ecdsa/rsa",
|
|
"hash": "sha256",
|
|
"id": "3031300d060960864801650304020105000420"
|
|
},
|
|
"sha384WithRSAEncryption": {
|
|
"sign": "rsa",
|
|
"hash": "sha384",
|
|
"id": "3041300d060960864801650304020205000430"
|
|
},
|
|
"RSA-SHA384": {
|
|
"sign": "ecdsa/rsa",
|
|
"hash": "sha384",
|
|
"id": "3041300d060960864801650304020205000430"
|
|
},
|
|
"sha512WithRSAEncryption": {
|
|
"sign": "rsa",
|
|
"hash": "sha512",
|
|
"id": "3051300d060960864801650304020305000440"
|
|
},
|
|
"RSA-SHA512": {
|
|
"sign": "ecdsa/rsa",
|
|
"hash": "sha512",
|
|
"id": "3051300d060960864801650304020305000440"
|
|
},
|
|
"RSA-SHA1": {
|
|
"sign": "rsa",
|
|
"hash": "sha1",
|
|
"id": "3021300906052b0e03021a05000414"
|
|
},
|
|
"ecdsa-with-SHA1": {
|
|
"sign": "ecdsa",
|
|
"hash": "sha1",
|
|
"id": ""
|
|
},
|
|
"sha256": {
|
|
"sign": "ecdsa",
|
|
"hash": "sha256",
|
|
"id": ""
|
|
},
|
|
"sha224": {
|
|
"sign": "ecdsa",
|
|
"hash": "sha224",
|
|
"id": ""
|
|
},
|
|
"sha384": {
|
|
"sign": "ecdsa",
|
|
"hash": "sha384",
|
|
"id": ""
|
|
},
|
|
"sha512": {
|
|
"sign": "ecdsa",
|
|
"hash": "sha512",
|
|
"id": ""
|
|
},
|
|
"DSA-SHA": {
|
|
"sign": "dsa",
|
|
"hash": "sha1",
|
|
"id": ""
|
|
},
|
|
"DSA-SHA1": {
|
|
"sign": "dsa",
|
|
"hash": "sha1",
|
|
"id": ""
|
|
},
|
|
"DSA": {
|
|
"sign": "dsa",
|
|
"hash": "sha1",
|
|
"id": ""
|
|
},
|
|
"DSA-WITH-SHA224": {
|
|
"sign": "dsa",
|
|
"hash": "sha224",
|
|
"id": ""
|
|
},
|
|
"DSA-SHA224": {
|
|
"sign": "dsa",
|
|
"hash": "sha224",
|
|
"id": ""
|
|
},
|
|
"DSA-WITH-SHA256": {
|
|
"sign": "dsa",
|
|
"hash": "sha256",
|
|
"id": ""
|
|
},
|
|
"DSA-SHA256": {
|
|
"sign": "dsa",
|
|
"hash": "sha256",
|
|
"id": ""
|
|
},
|
|
"DSA-WITH-SHA384": {
|
|
"sign": "dsa",
|
|
"hash": "sha384",
|
|
"id": ""
|
|
},
|
|
"DSA-SHA384": {
|
|
"sign": "dsa",
|
|
"hash": "sha384",
|
|
"id": ""
|
|
},
|
|
"DSA-WITH-SHA512": {
|
|
"sign": "dsa",
|
|
"hash": "sha512",
|
|
"id": ""
|
|
},
|
|
"DSA-SHA512": {
|
|
"sign": "dsa",
|
|
"hash": "sha512",
|
|
"id": ""
|
|
},
|
|
"DSA-RIPEMD160": {
|
|
"sign": "dsa",
|
|
"hash": "rmd160",
|
|
"id": ""
|
|
},
|
|
"ripemd160WithRSA": {
|
|
"sign": "rsa",
|
|
"hash": "rmd160",
|
|
"id": "3021300906052b2403020105000414"
|
|
},
|
|
"RSA-RIPEMD160": {
|
|
"sign": "rsa",
|
|
"hash": "rmd160",
|
|
"id": "3021300906052b2403020105000414"
|
|
},
|
|
"md5WithRSAEncryption": {
|
|
"sign": "rsa",
|
|
"hash": "md5",
|
|
"id": "3020300c06082a864886f70d020505000410"
|
|
},
|
|
"RSA-MD5": {
|
|
"sign": "rsa",
|
|
"hash": "md5",
|
|
"id": "3020300c06082a864886f70d020505000410"
|
|
}
|
|
}
|
|
|
|
},{}],90:[function(require,module,exports){
|
|
module.exports={
|
|
"1.3.132.0.10": "secp256k1",
|
|
"1.3.132.0.33": "p224",
|
|
"1.2.840.10045.3.1.1": "p192",
|
|
"1.2.840.10045.3.1.7": "p256",
|
|
"1.3.132.0.34": "p384",
|
|
"1.3.132.0.35": "p521"
|
|
}
|
|
|
|
},{}],91:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var createHash = require('create-hash')
|
|
var stream = require('stream')
|
|
var inherits = require('inherits')
|
|
var sign = require('./sign')
|
|
var verify = require('./verify')
|
|
|
|
var algorithms = require('./algorithms.json')
|
|
Object.keys(algorithms).forEach(function (key) {
|
|
algorithms[key].id = new Buffer(algorithms[key].id, 'hex')
|
|
algorithms[key.toLowerCase()] = algorithms[key]
|
|
})
|
|
|
|
function Sign (algorithm) {
|
|
stream.Writable.call(this)
|
|
|
|
var data = algorithms[algorithm]
|
|
if (!data) throw new Error('Unknown message digest')
|
|
|
|
this._hashType = data.hash
|
|
this._hash = createHash(data.hash)
|
|
this._tag = data.id
|
|
this._signType = data.sign
|
|
}
|
|
inherits(Sign, stream.Writable)
|
|
|
|
Sign.prototype._write = function _write (data, _, done) {
|
|
this._hash.update(data)
|
|
done()
|
|
}
|
|
|
|
Sign.prototype.update = function update (data, enc) {
|
|
if (typeof data === 'string') data = new Buffer(data, enc)
|
|
|
|
this._hash.update(data)
|
|
return this
|
|
}
|
|
|
|
Sign.prototype.sign = function signMethod (key, enc) {
|
|
this.end()
|
|
var hash = this._hash.digest()
|
|
var sig = sign(hash, key, this._hashType, this._signType, this._tag)
|
|
|
|
return enc ? sig.toString(enc) : sig
|
|
}
|
|
|
|
function Verify (algorithm) {
|
|
stream.Writable.call(this)
|
|
|
|
var data = algorithms[algorithm]
|
|
if (!data) throw new Error('Unknown message digest')
|
|
|
|
this._hash = createHash(data.hash)
|
|
this._tag = data.id
|
|
this._signType = data.sign
|
|
}
|
|
inherits(Verify, stream.Writable)
|
|
|
|
Verify.prototype._write = function _write (data, _, done) {
|
|
this._hash.update(data)
|
|
done()
|
|
}
|
|
|
|
Verify.prototype.update = function update (data, enc) {
|
|
if (typeof data === 'string') data = new Buffer(data, enc)
|
|
|
|
this._hash.update(data)
|
|
return this
|
|
}
|
|
|
|
Verify.prototype.verify = function verifyMethod (key, sig, enc) {
|
|
if (typeof sig === 'string') sig = new Buffer(sig, enc)
|
|
|
|
this.end()
|
|
var hash = this._hash.digest()
|
|
return verify(sig, hash, key, this._signType, this._tag)
|
|
}
|
|
|
|
function createSign (algorithm) {
|
|
return new Sign(algorithm)
|
|
}
|
|
|
|
function createVerify (algorithm) {
|
|
return new Verify(algorithm)
|
|
}
|
|
|
|
module.exports = {
|
|
Sign: createSign,
|
|
Verify: createVerify,
|
|
createSign: createSign,
|
|
createVerify: createVerify
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./algorithms.json":89,"./sign":92,"./verify":93,"buffer":47,"create-hash":140,"inherits":318,"stream":272}],92:[function(require,module,exports){
|
|
(function (Buffer){
|
|
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
|
|
var createHmac = require('create-hmac')
|
|
var crt = require('browserify-rsa')
|
|
var EC = require('elliptic').ec
|
|
var BN = require('bn.js')
|
|
var parseKeys = require('parse-asn1')
|
|
var curves = require('./curves.json')
|
|
|
|
function sign (hash, key, hashType, signType, tag) {
|
|
var priv = parseKeys(key)
|
|
if (priv.curve) {
|
|
// rsa keys can be interpreted as ecdsa ones in openssl
|
|
if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type')
|
|
return ecSign(hash, priv)
|
|
} else if (priv.type === 'dsa') {
|
|
if (signType !== 'dsa') throw new Error('wrong private key type')
|
|
return dsaSign(hash, priv, hashType)
|
|
} else {
|
|
if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type')
|
|
}
|
|
hash = Buffer.concat([tag, hash])
|
|
var len = priv.modulus.byteLength()
|
|
var pad = [ 0, 1 ]
|
|
while (hash.length + pad.length + 1 < len) pad.push(0xff)
|
|
pad.push(0x00)
|
|
var i = -1
|
|
while (++i < hash.length) pad.push(hash[i])
|
|
|
|
var out = crt(pad, priv)
|
|
return out
|
|
}
|
|
|
|
function ecSign (hash, priv) {
|
|
var curveId = curves[priv.curve.join('.')]
|
|
if (!curveId) throw new Error('unknown curve ' + priv.curve.join('.'))
|
|
|
|
var curve = new EC(curveId)
|
|
var key = curve.keyFromPrivate(priv.privateKey)
|
|
var out = key.sign(hash)
|
|
|
|
return new Buffer(out.toDER())
|
|
}
|
|
|
|
function dsaSign (hash, priv, algo) {
|
|
var x = priv.params.priv_key
|
|
var p = priv.params.p
|
|
var q = priv.params.q
|
|
var g = priv.params.g
|
|
var r = new BN(0)
|
|
var k
|
|
var H = bits2int(hash, q).mod(q)
|
|
var s = false
|
|
var kv = getKey(x, q, hash, algo)
|
|
while (s === false) {
|
|
k = makeKey(q, kv, algo)
|
|
r = makeR(g, k, p, q)
|
|
s = k.invm(q).imul(H.add(x.mul(r))).mod(q)
|
|
if (s.cmpn(0) === 0) {
|
|
s = false
|
|
r = new BN(0)
|
|
}
|
|
}
|
|
return toDER(r, s)
|
|
}
|
|
|
|
function toDER (r, s) {
|
|
r = r.toArray()
|
|
s = s.toArray()
|
|
|
|
// Pad values
|
|
if (r[0] & 0x80) r = [ 0 ].concat(r)
|
|
if (s[0] & 0x80) s = [ 0 ].concat(s)
|
|
|
|
var total = r.length + s.length + 4
|
|
var res = [ 0x30, total, 0x02, r.length ]
|
|
res = res.concat(r, [ 0x02, s.length ], s)
|
|
return new Buffer(res)
|
|
}
|
|
|
|
function getKey (x, q, hash, algo) {
|
|
x = new Buffer(x.toArray())
|
|
if (x.length < q.byteLength()) {
|
|
var zeros = new Buffer(q.byteLength() - x.length)
|
|
zeros.fill(0)
|
|
x = Buffer.concat([ zeros, x ])
|
|
}
|
|
var hlen = hash.length
|
|
var hbits = bits2octets(hash, q)
|
|
var v = new Buffer(hlen)
|
|
v.fill(1)
|
|
var k = new Buffer(hlen)
|
|
k.fill(0)
|
|
k = createHmac(algo, k).update(v).update(new Buffer([ 0 ])).update(x).update(hbits).digest()
|
|
v = createHmac(algo, k).update(v).digest()
|
|
k = createHmac(algo, k).update(v).update(new Buffer([ 1 ])).update(x).update(hbits).digest()
|
|
v = createHmac(algo, k).update(v).digest()
|
|
return { k: k, v: v }
|
|
}
|
|
|
|
function bits2int (obits, q) {
|
|
var bits = new BN(obits)
|
|
var shift = (obits.length << 3) - q.bitLength()
|
|
if (shift > 0) bits.ishrn(shift)
|
|
return bits
|
|
}
|
|
|
|
function bits2octets (bits, q) {
|
|
bits = bits2int(bits, q)
|
|
bits = bits.mod(q)
|
|
var out = new Buffer(bits.toArray())
|
|
if (out.length < q.byteLength()) {
|
|
var zeros = new Buffer(q.byteLength() - out.length)
|
|
zeros.fill(0)
|
|
out = Buffer.concat([ zeros, out ])
|
|
}
|
|
return out
|
|
}
|
|
|
|
function makeKey (q, kv, algo) {
|
|
var t
|
|
var k
|
|
|
|
do {
|
|
t = new Buffer(0)
|
|
|
|
while (t.length * 8 < q.bitLength()) {
|
|
kv.v = createHmac(algo, kv.k).update(kv.v).digest()
|
|
t = Buffer.concat([ t, kv.v ])
|
|
}
|
|
|
|
k = bits2int(t, q)
|
|
kv.k = createHmac(algo, kv.k).update(kv.v).update(new Buffer([ 0 ])).digest()
|
|
kv.v = createHmac(algo, kv.k).update(kv.v).digest()
|
|
} while (k.cmp(q) !== -1)
|
|
|
|
return k
|
|
}
|
|
|
|
function makeR (g, k, p, q) {
|
|
return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q)
|
|
}
|
|
|
|
module.exports = sign
|
|
module.exports.getKey = getKey
|
|
module.exports.makeKey = makeKey
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./curves.json":90,"bn.js":280,"browserify-rsa":94,"buffer":47,"create-hmac":156,"elliptic":285,"parse-asn1":99}],93:[function(require,module,exports){
|
|
(function (Buffer){
|
|
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js
|
|
var BN = require('bn.js')
|
|
var EC = require('elliptic').ec
|
|
var parseKeys = require('parse-asn1')
|
|
var curves = require('./curves.json')
|
|
|
|
function verify (sig, hash, key, signType, tag) {
|
|
var pub = parseKeys(key)
|
|
if (pub.type === 'ec') {
|
|
// rsa keys can be interpreted as ecdsa ones in openssl
|
|
if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type')
|
|
return ecVerify(sig, hash, pub)
|
|
} else if (pub.type === 'dsa') {
|
|
if (signType !== 'dsa') throw new Error('wrong public key type')
|
|
return dsaVerify(sig, hash, pub)
|
|
} else {
|
|
if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type')
|
|
}
|
|
hash = Buffer.concat([tag, hash])
|
|
var len = pub.modulus.byteLength()
|
|
var pad = [ 1 ]
|
|
var padNum = 0
|
|
while (hash.length + pad.length + 2 < len) {
|
|
pad.push(0xff)
|
|
padNum++
|
|
}
|
|
pad.push(0x00)
|
|
var i = -1
|
|
while (++i < hash.length) {
|
|
pad.push(hash[i])
|
|
}
|
|
pad = new Buffer(pad)
|
|
var red = BN.mont(pub.modulus)
|
|
sig = new BN(sig).toRed(red)
|
|
|
|
sig = sig.redPow(new BN(pub.publicExponent))
|
|
sig = new Buffer(sig.fromRed().toArray())
|
|
var out = padNum < 8 ? 1 : 0
|
|
len = Math.min(sig.length, pad.length)
|
|
if (sig.length !== pad.length) out = 1
|
|
|
|
i = -1
|
|
while (++i < len) out |= sig[i] ^ pad[i]
|
|
return out === 0
|
|
}
|
|
|
|
function ecVerify (sig, hash, pub) {
|
|
var curveId = curves[pub.data.algorithm.curve.join('.')]
|
|
if (!curveId) throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.'))
|
|
|
|
var curve = new EC(curveId)
|
|
var pubkey = pub.data.subjectPrivateKey.data
|
|
|
|
return curve.verify(hash, sig, pubkey)
|
|
}
|
|
|
|
function dsaVerify (sig, hash, pub) {
|
|
var p = pub.data.p
|
|
var q = pub.data.q
|
|
var g = pub.data.g
|
|
var y = pub.data.pub_key
|
|
var unpacked = parseKeys.signature.decode(sig, 'der')
|
|
var s = unpacked.s
|
|
var r = unpacked.r
|
|
checkValue(s, q)
|
|
checkValue(r, q)
|
|
var montp = BN.mont(p)
|
|
var w = s.invm(q)
|
|
var v = g.toRed(montp)
|
|
.redPow(new BN(hash).mul(w).mod(q))
|
|
.fromRed()
|
|
.mul(y.toRed(montp).redPow(r.mul(w).mod(q)).fromRed())
|
|
.mod(p)
|
|
.mod(q)
|
|
return v.cmp(r) === 0
|
|
}
|
|
|
|
function checkValue (b, q) {
|
|
if (b.cmpn(0) <= 0) throw new Error('invalid sig')
|
|
if (b.cmp(q) >= q) throw new Error('invalid sig')
|
|
}
|
|
|
|
module.exports = verify
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./curves.json":90,"bn.js":280,"buffer":47,"elliptic":285,"parse-asn1":99}],94:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var bn = require('bn.js');
|
|
var randomBytes = require('randombytes');
|
|
module.exports = crt;
|
|
function blind(priv) {
|
|
var r = getr(priv);
|
|
var blinder = r.toRed(bn.mont(priv.modulus))
|
|
.redPow(new bn(priv.publicExponent)).fromRed();
|
|
return {
|
|
blinder: blinder,
|
|
unblinder:r.invm(priv.modulus)
|
|
};
|
|
}
|
|
function crt(msg, priv) {
|
|
var blinds = blind(priv);
|
|
var len = priv.modulus.byteLength();
|
|
var mod = bn.mont(priv.modulus);
|
|
var blinded = new bn(msg).mul(blinds.blinder).umod(priv.modulus);
|
|
var c1 = blinded.toRed(bn.mont(priv.prime1));
|
|
var c2 = blinded.toRed(bn.mont(priv.prime2));
|
|
var qinv = priv.coefficient;
|
|
var p = priv.prime1;
|
|
var q = priv.prime2;
|
|
var m1 = c1.redPow(priv.exponent1);
|
|
var m2 = c2.redPow(priv.exponent2);
|
|
m1 = m1.fromRed();
|
|
m2 = m2.fromRed();
|
|
var h = m1.isub(m2).imul(qinv).umod(p);
|
|
h.imul(q);
|
|
m2.iadd(h);
|
|
return new Buffer(m2.imul(blinds.unblinder).umod(priv.modulus).toArray(false, len));
|
|
}
|
|
crt.getr = getr;
|
|
function getr(priv) {
|
|
var len = priv.modulus.byteLength();
|
|
var r = new bn(randomBytes(len));
|
|
while (r.cmp(priv.modulus) >= 0 || !r.umod(priv.prime1) || !r.umod(priv.prime2)) {
|
|
r = new bn(randomBytes(len));
|
|
}
|
|
return r;
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"bn.js":280,"buffer":47,"randombytes":243}],95:[function(require,module,exports){
|
|
module.exports={"2.16.840.1.101.3.4.1.1": "aes-128-ecb",
|
|
"2.16.840.1.101.3.4.1.2": "aes-128-cbc",
|
|
"2.16.840.1.101.3.4.1.3": "aes-128-ofb",
|
|
"2.16.840.1.101.3.4.1.4": "aes-128-cfb",
|
|
"2.16.840.1.101.3.4.1.21": "aes-192-ecb",
|
|
"2.16.840.1.101.3.4.1.22": "aes-192-cbc",
|
|
"2.16.840.1.101.3.4.1.23": "aes-192-ofb",
|
|
"2.16.840.1.101.3.4.1.24": "aes-192-cfb",
|
|
"2.16.840.1.101.3.4.1.41": "aes-256-ecb",
|
|
"2.16.840.1.101.3.4.1.42": "aes-256-cbc",
|
|
"2.16.840.1.101.3.4.1.43": "aes-256-ofb",
|
|
"2.16.840.1.101.3.4.1.44": "aes-256-cfb"
|
|
}
|
|
},{}],96:[function(require,module,exports){
|
|
// from https://github.com/indutny/self-signed/blob/gh-pages/lib/asn1.js
|
|
// Fedor, you are amazing.
|
|
'use strict'
|
|
|
|
var asn1 = require('asn1.js')
|
|
|
|
exports.certificate = require('./certificate')
|
|
|
|
var RSAPrivateKey = asn1.define('RSAPrivateKey', function () {
|
|
this.seq().obj(
|
|
this.key('version').int(),
|
|
this.key('modulus').int(),
|
|
this.key('publicExponent').int(),
|
|
this.key('privateExponent').int(),
|
|
this.key('prime1').int(),
|
|
this.key('prime2').int(),
|
|
this.key('exponent1').int(),
|
|
this.key('exponent2').int(),
|
|
this.key('coefficient').int()
|
|
)
|
|
})
|
|
exports.RSAPrivateKey = RSAPrivateKey
|
|
|
|
var RSAPublicKey = asn1.define('RSAPublicKey', function () {
|
|
this.seq().obj(
|
|
this.key('modulus').int(),
|
|
this.key('publicExponent').int()
|
|
)
|
|
})
|
|
exports.RSAPublicKey = RSAPublicKey
|
|
|
|
var PublicKey = asn1.define('SubjectPublicKeyInfo', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').use(AlgorithmIdentifier),
|
|
this.key('subjectPublicKey').bitstr()
|
|
)
|
|
})
|
|
exports.PublicKey = PublicKey
|
|
|
|
var AlgorithmIdentifier = asn1.define('AlgorithmIdentifier', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').objid(),
|
|
this.key('none').null_().optional(),
|
|
this.key('curve').objid().optional(),
|
|
this.key('params').seq().obj(
|
|
this.key('p').int(),
|
|
this.key('q').int(),
|
|
this.key('g').int()
|
|
).optional()
|
|
)
|
|
})
|
|
|
|
var PrivateKeyInfo = asn1.define('PrivateKeyInfo', function () {
|
|
this.seq().obj(
|
|
this.key('version').int(),
|
|
this.key('algorithm').use(AlgorithmIdentifier),
|
|
this.key('subjectPrivateKey').octstr()
|
|
)
|
|
})
|
|
exports.PrivateKey = PrivateKeyInfo
|
|
var EncryptedPrivateKeyInfo = asn1.define('EncryptedPrivateKeyInfo', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').seq().obj(
|
|
this.key('id').objid(),
|
|
this.key('decrypt').seq().obj(
|
|
this.key('kde').seq().obj(
|
|
this.key('id').objid(),
|
|
this.key('kdeparams').seq().obj(
|
|
this.key('salt').octstr(),
|
|
this.key('iters').int()
|
|
)
|
|
),
|
|
this.key('cipher').seq().obj(
|
|
this.key('algo').objid(),
|
|
this.key('iv').octstr()
|
|
)
|
|
)
|
|
),
|
|
this.key('subjectPrivateKey').octstr()
|
|
)
|
|
})
|
|
|
|
exports.EncryptedPrivateKey = EncryptedPrivateKeyInfo
|
|
|
|
var DSAPrivateKey = asn1.define('DSAPrivateKey', function () {
|
|
this.seq().obj(
|
|
this.key('version').int(),
|
|
this.key('p').int(),
|
|
this.key('q').int(),
|
|
this.key('g').int(),
|
|
this.key('pub_key').int(),
|
|
this.key('priv_key').int()
|
|
)
|
|
})
|
|
exports.DSAPrivateKey = DSAPrivateKey
|
|
|
|
exports.DSAparam = asn1.define('DSAparam', function () {
|
|
this.int()
|
|
})
|
|
|
|
var ECPrivateKey = asn1.define('ECPrivateKey', function () {
|
|
this.seq().obj(
|
|
this.key('version').int(),
|
|
this.key('privateKey').octstr(),
|
|
this.key('parameters').optional().explicit(0).use(ECParameters),
|
|
this.key('publicKey').optional().explicit(1).bitstr()
|
|
)
|
|
})
|
|
exports.ECPrivateKey = ECPrivateKey
|
|
|
|
var ECParameters = asn1.define('ECParameters', function () {
|
|
this.choice({
|
|
namedCurve: this.objid()
|
|
})
|
|
})
|
|
|
|
exports.signature = asn1.define('signature', function () {
|
|
this.seq().obj(
|
|
this.key('r').int(),
|
|
this.key('s').int()
|
|
)
|
|
})
|
|
|
|
},{"./certificate":97,"asn1.js":100}],97:[function(require,module,exports){
|
|
// from https://github.com/Rantanen/node-dtls/blob/25a7dc861bda38cfeac93a723500eea4f0ac2e86/Certificate.js
|
|
// thanks to @Rantanen
|
|
|
|
'use strict'
|
|
|
|
var asn = require('asn1.js')
|
|
|
|
var Time = asn.define('Time', function () {
|
|
this.choice({
|
|
utcTime: this.utctime(),
|
|
generalTime: this.gentime()
|
|
})
|
|
})
|
|
|
|
var AttributeTypeValue = asn.define('AttributeTypeValue', function () {
|
|
this.seq().obj(
|
|
this.key('type').objid(),
|
|
this.key('value').any()
|
|
)
|
|
})
|
|
|
|
var AlgorithmIdentifier = asn.define('AlgorithmIdentifier', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').objid(),
|
|
this.key('parameters').optional()
|
|
)
|
|
})
|
|
|
|
var SubjectPublicKeyInfo = asn.define('SubjectPublicKeyInfo', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').use(AlgorithmIdentifier),
|
|
this.key('subjectPublicKey').bitstr()
|
|
)
|
|
})
|
|
|
|
var RelativeDistinguishedName = asn.define('RelativeDistinguishedName', function () {
|
|
this.setof(AttributeTypeValue)
|
|
})
|
|
|
|
var RDNSequence = asn.define('RDNSequence', function () {
|
|
this.seqof(RelativeDistinguishedName)
|
|
})
|
|
|
|
var Name = asn.define('Name', function () {
|
|
this.choice({
|
|
rdnSequence: this.use(RDNSequence)
|
|
})
|
|
})
|
|
|
|
var Validity = asn.define('Validity', function () {
|
|
this.seq().obj(
|
|
this.key('notBefore').use(Time),
|
|
this.key('notAfter').use(Time)
|
|
)
|
|
})
|
|
|
|
var Extension = asn.define('Extension', function () {
|
|
this.seq().obj(
|
|
this.key('extnID').objid(),
|
|
this.key('critical').bool().def(false),
|
|
this.key('extnValue').octstr()
|
|
)
|
|
})
|
|
|
|
var TBSCertificate = asn.define('TBSCertificate', function () {
|
|
this.seq().obj(
|
|
this.key('version').explicit(0).int(),
|
|
this.key('serialNumber').int(),
|
|
this.key('signature').use(AlgorithmIdentifier),
|
|
this.key('issuer').use(Name),
|
|
this.key('validity').use(Validity),
|
|
this.key('subject').use(Name),
|
|
this.key('subjectPublicKeyInfo').use(SubjectPublicKeyInfo),
|
|
this.key('issuerUniqueID').implicit(1).bitstr().optional(),
|
|
this.key('subjectUniqueID').implicit(2).bitstr().optional(),
|
|
this.key('extensions').explicit(3).seqof(Extension).optional()
|
|
)
|
|
})
|
|
|
|
var X509Certificate = asn.define('X509Certificate', function () {
|
|
this.seq().obj(
|
|
this.key('tbsCertificate').use(TBSCertificate),
|
|
this.key('signatureAlgorithm').use(AlgorithmIdentifier),
|
|
this.key('signatureValue').bitstr()
|
|
)
|
|
})
|
|
|
|
module.exports = X509Certificate
|
|
|
|
},{"asn1.js":100}],98:[function(require,module,exports){
|
|
(function (Buffer){
|
|
// adapted from https://github.com/apatil/pemstrip
|
|
var findProc = /Proc-Type: 4,ENCRYPTED\n\r?DEK-Info: AES-((?:128)|(?:192)|(?:256))-CBC,([0-9A-H]+)\n\r?\n\r?([0-9A-z\n\r\+\/\=]+)\n\r?/m
|
|
var startRegex = /^-----BEGIN ((?:.* KEY)|CERTIFICATE)-----\n/m
|
|
var fullRegex = /^-----BEGIN ((?:.* KEY)|CERTIFICATE)-----\n\r?([0-9A-z\n\r\+\/\=]+)\n\r?-----END \1-----$/m
|
|
var evp = require('evp_bytestokey')
|
|
var ciphers = require('browserify-aes')
|
|
module.exports = function (okey, password) {
|
|
var key = okey.toString()
|
|
var match = key.match(findProc)
|
|
var decrypted
|
|
if (!match) {
|
|
var match2 = key.match(fullRegex)
|
|
decrypted = new Buffer(match2[2].replace(/\r?\n/g, ''), 'base64')
|
|
} else {
|
|
var suite = 'aes' + match[1]
|
|
var iv = new Buffer(match[2], 'hex')
|
|
var cipherText = new Buffer(match[3].replace(/\r?\n/g, ''), 'base64')
|
|
var cipherKey = evp(password, iv.slice(0, 8), parseInt(match[1], 10)).key
|
|
var out = []
|
|
var cipher = ciphers.createDecipheriv(suite, cipherKey, iv)
|
|
out.push(cipher.update(cipherText))
|
|
out.push(cipher.final())
|
|
decrypted = Buffer.concat(out)
|
|
}
|
|
var tag = key.match(startRegex)[1]
|
|
return {
|
|
tag: tag,
|
|
data: decrypted
|
|
}
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"browserify-aes":117,"buffer":47,"evp_bytestokey":135}],99:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var asn1 = require('./asn1')
|
|
var aesid = require('./aesid.json')
|
|
var fixProc = require('./fixProc')
|
|
var ciphers = require('browserify-aes')
|
|
var compat = require('pbkdf2')
|
|
module.exports = parseKeys
|
|
|
|
function parseKeys (buffer) {
|
|
var password
|
|
if (typeof buffer === 'object' && !Buffer.isBuffer(buffer)) {
|
|
password = buffer.passphrase
|
|
buffer = buffer.key
|
|
}
|
|
if (typeof buffer === 'string') {
|
|
buffer = new Buffer(buffer)
|
|
}
|
|
|
|
var stripped = fixProc(buffer, password)
|
|
|
|
var type = stripped.tag
|
|
var data = stripped.data
|
|
var subtype, ndata
|
|
switch (type) {
|
|
case 'CERTIFICATE':
|
|
ndata = asn1.certificate.decode(data, 'der').tbsCertificate.subjectPublicKeyInfo
|
|
// falls through
|
|
case 'PUBLIC KEY':
|
|
if (!ndata) {
|
|
ndata = asn1.PublicKey.decode(data, 'der')
|
|
}
|
|
subtype = ndata.algorithm.algorithm.join('.')
|
|
switch (subtype) {
|
|
case '1.2.840.113549.1.1.1':
|
|
return asn1.RSAPublicKey.decode(ndata.subjectPublicKey.data, 'der')
|
|
case '1.2.840.10045.2.1':
|
|
ndata.subjectPrivateKey = ndata.subjectPublicKey
|
|
return {
|
|
type: 'ec',
|
|
data: ndata
|
|
}
|
|
case '1.2.840.10040.4.1':
|
|
ndata.algorithm.params.pub_key = asn1.DSAparam.decode(ndata.subjectPublicKey.data, 'der')
|
|
return {
|
|
type: 'dsa',
|
|
data: ndata.algorithm.params
|
|
}
|
|
default: throw new Error('unknown key id ' + subtype)
|
|
}
|
|
throw new Error('unknown key type ' + type)
|
|
case 'ENCRYPTED PRIVATE KEY':
|
|
data = asn1.EncryptedPrivateKey.decode(data, 'der')
|
|
data = decrypt(data, password)
|
|
// falls through
|
|
case 'PRIVATE KEY':
|
|
ndata = asn1.PrivateKey.decode(data, 'der')
|
|
subtype = ndata.algorithm.algorithm.join('.')
|
|
switch (subtype) {
|
|
case '1.2.840.113549.1.1.1':
|
|
return asn1.RSAPrivateKey.decode(ndata.subjectPrivateKey, 'der')
|
|
case '1.2.840.10045.2.1':
|
|
return {
|
|
curve: ndata.algorithm.curve,
|
|
privateKey: asn1.ECPrivateKey.decode(ndata.subjectPrivateKey, 'der').privateKey
|
|
}
|
|
case '1.2.840.10040.4.1':
|
|
ndata.algorithm.params.priv_key = asn1.DSAparam.decode(ndata.subjectPrivateKey, 'der')
|
|
return {
|
|
type: 'dsa',
|
|
params: ndata.algorithm.params
|
|
}
|
|
default: throw new Error('unknown key id ' + subtype)
|
|
}
|
|
throw new Error('unknown key type ' + type)
|
|
case 'RSA PUBLIC KEY':
|
|
return asn1.RSAPublicKey.decode(data, 'der')
|
|
case 'RSA PRIVATE KEY':
|
|
return asn1.RSAPrivateKey.decode(data, 'der')
|
|
case 'DSA PRIVATE KEY':
|
|
return {
|
|
type: 'dsa',
|
|
params: asn1.DSAPrivateKey.decode(data, 'der')
|
|
}
|
|
case 'EC PRIVATE KEY':
|
|
data = asn1.ECPrivateKey.decode(data, 'der')
|
|
return {
|
|
curve: data.parameters.value,
|
|
privateKey: data.privateKey
|
|
}
|
|
default: throw new Error('unknown key type ' + type)
|
|
}
|
|
}
|
|
parseKeys.signature = asn1.signature
|
|
function decrypt (data, password) {
|
|
var salt = data.algorithm.decrypt.kde.kdeparams.salt
|
|
var iters = parseInt(data.algorithm.decrypt.kde.kdeparams.iters.toString(), 10)
|
|
var algo = aesid[data.algorithm.decrypt.cipher.algo.join('.')]
|
|
var iv = data.algorithm.decrypt.cipher.iv
|
|
var cipherText = data.subjectPrivateKey
|
|
var keylen = parseInt(algo.split('-')[1], 10) / 8
|
|
var key = compat.pbkdf2Sync(password, salt, iters, keylen)
|
|
var cipher = ciphers.createDecipheriv(algo, key, iv)
|
|
var out = []
|
|
out.push(cipher.update(cipherText))
|
|
out.push(cipher.final())
|
|
return Buffer.concat(out)
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./aesid.json":95,"./asn1":96,"./fixProc":98,"browserify-aes":117,"buffer":47,"pbkdf2":176}],100:[function(require,module,exports){
|
|
var asn1 = exports;
|
|
|
|
asn1.bignum = require('bn.js');
|
|
|
|
asn1.define = require('./asn1/api').define;
|
|
asn1.base = require('./asn1/base');
|
|
asn1.constants = require('./asn1/constants');
|
|
asn1.decoders = require('./asn1/decoders');
|
|
asn1.encoders = require('./asn1/encoders');
|
|
|
|
},{"./asn1/api":101,"./asn1/base":103,"./asn1/constants":107,"./asn1/decoders":109,"./asn1/encoders":112,"bn.js":280}],101:[function(require,module,exports){
|
|
var asn1 = require('../asn1');
|
|
var inherits = require('inherits');
|
|
|
|
var api = exports;
|
|
|
|
api.define = function define(name, body) {
|
|
return new Entity(name, body);
|
|
};
|
|
|
|
function Entity(name, body) {
|
|
this.name = name;
|
|
this.body = body;
|
|
|
|
this.decoders = {};
|
|
this.encoders = {};
|
|
};
|
|
|
|
Entity.prototype._createNamed = function createNamed(base) {
|
|
var named;
|
|
try {
|
|
named = require('vm').runInThisContext(
|
|
'(function ' + this.name + '(entity) {\n' +
|
|
' this._initNamed(entity);\n' +
|
|
'})'
|
|
);
|
|
} catch (e) {
|
|
named = function (entity) {
|
|
this._initNamed(entity);
|
|
};
|
|
}
|
|
inherits(named, base);
|
|
named.prototype._initNamed = function initnamed(entity) {
|
|
base.call(this, entity);
|
|
};
|
|
|
|
return new named(this);
|
|
};
|
|
|
|
Entity.prototype._getDecoder = function _getDecoder(enc) {
|
|
enc = enc || 'der';
|
|
// Lazily create decoder
|
|
if (!this.decoders.hasOwnProperty(enc))
|
|
this.decoders[enc] = this._createNamed(asn1.decoders[enc]);
|
|
return this.decoders[enc];
|
|
};
|
|
|
|
Entity.prototype.decode = function decode(data, enc, options) {
|
|
return this._getDecoder(enc).decode(data, options);
|
|
};
|
|
|
|
Entity.prototype._getEncoder = function _getEncoder(enc) {
|
|
enc = enc || 'der';
|
|
// Lazily create encoder
|
|
if (!this.encoders.hasOwnProperty(enc))
|
|
this.encoders[enc] = this._createNamed(asn1.encoders[enc]);
|
|
return this.encoders[enc];
|
|
};
|
|
|
|
Entity.prototype.encode = function encode(data, enc, /* internal */ reporter) {
|
|
return this._getEncoder(enc).encode(data, reporter);
|
|
};
|
|
|
|
},{"../asn1":100,"inherits":318,"vm":278}],102:[function(require,module,exports){
|
|
var inherits = require('inherits');
|
|
var Reporter = require('../base').Reporter;
|
|
var Buffer = require('buffer').Buffer;
|
|
|
|
function DecoderBuffer(base, options) {
|
|
Reporter.call(this, options);
|
|
if (!Buffer.isBuffer(base)) {
|
|
this.error('Input not Buffer');
|
|
return;
|
|
}
|
|
|
|
this.base = base;
|
|
this.offset = 0;
|
|
this.length = base.length;
|
|
}
|
|
inherits(DecoderBuffer, Reporter);
|
|
exports.DecoderBuffer = DecoderBuffer;
|
|
|
|
DecoderBuffer.prototype.save = function save() {
|
|
return { offset: this.offset, reporter: Reporter.prototype.save.call(this) };
|
|
};
|
|
|
|
DecoderBuffer.prototype.restore = function restore(save) {
|
|
// Return skipped data
|
|
var res = new DecoderBuffer(this.base);
|
|
res.offset = save.offset;
|
|
res.length = this.offset;
|
|
|
|
this.offset = save.offset;
|
|
Reporter.prototype.restore.call(this, save.reporter);
|
|
|
|
return res;
|
|
};
|
|
|
|
DecoderBuffer.prototype.isEmpty = function isEmpty() {
|
|
return this.offset === this.length;
|
|
};
|
|
|
|
DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) {
|
|
if (this.offset + 1 <= this.length)
|
|
return this.base.readUInt8(this.offset++, true);
|
|
else
|
|
return this.error(fail || 'DecoderBuffer overrun');
|
|
}
|
|
|
|
DecoderBuffer.prototype.skip = function skip(bytes, fail) {
|
|
if (!(this.offset + bytes <= this.length))
|
|
return this.error(fail || 'DecoderBuffer overrun');
|
|
|
|
var res = new DecoderBuffer(this.base);
|
|
|
|
// Share reporter state
|
|
res._reporterState = this._reporterState;
|
|
|
|
res.offset = this.offset;
|
|
res.length = this.offset + bytes;
|
|
this.offset += bytes;
|
|
return res;
|
|
}
|
|
|
|
DecoderBuffer.prototype.raw = function raw(save) {
|
|
return this.base.slice(save ? save.offset : this.offset, this.length);
|
|
}
|
|
|
|
function EncoderBuffer(value, reporter) {
|
|
if (Array.isArray(value)) {
|
|
this.length = 0;
|
|
this.value = value.map(function(item) {
|
|
if (!(item instanceof EncoderBuffer))
|
|
item = new EncoderBuffer(item, reporter);
|
|
this.length += item.length;
|
|
return item;
|
|
}, this);
|
|
} else if (typeof value === 'number') {
|
|
if (!(0 <= value && value <= 0xff))
|
|
return reporter.error('non-byte EncoderBuffer value');
|
|
this.value = value;
|
|
this.length = 1;
|
|
} else if (typeof value === 'string') {
|
|
this.value = value;
|
|
this.length = Buffer.byteLength(value);
|
|
} else if (Buffer.isBuffer(value)) {
|
|
this.value = value;
|
|
this.length = value.length;
|
|
} else {
|
|
return reporter.error('Unsupported type: ' + typeof value);
|
|
}
|
|
}
|
|
exports.EncoderBuffer = EncoderBuffer;
|
|
|
|
EncoderBuffer.prototype.join = function join(out, offset) {
|
|
if (!out)
|
|
out = new Buffer(this.length);
|
|
if (!offset)
|
|
offset = 0;
|
|
|
|
if (this.length === 0)
|
|
return out;
|
|
|
|
if (Array.isArray(this.value)) {
|
|
this.value.forEach(function(item) {
|
|
item.join(out, offset);
|
|
offset += item.length;
|
|
});
|
|
} else {
|
|
if (typeof this.value === 'number')
|
|
out[offset] = this.value;
|
|
else if (typeof this.value === 'string')
|
|
out.write(this.value, offset);
|
|
else if (Buffer.isBuffer(this.value))
|
|
this.value.copy(out, offset);
|
|
offset += this.length;
|
|
}
|
|
|
|
return out;
|
|
};
|
|
|
|
},{"../base":103,"buffer":47,"inherits":318}],103:[function(require,module,exports){
|
|
var base = exports;
|
|
|
|
base.Reporter = require('./reporter').Reporter;
|
|
base.DecoderBuffer = require('./buffer').DecoderBuffer;
|
|
base.EncoderBuffer = require('./buffer').EncoderBuffer;
|
|
base.Node = require('./node');
|
|
|
|
},{"./buffer":102,"./node":104,"./reporter":105}],104:[function(require,module,exports){
|
|
var Reporter = require('../base').Reporter;
|
|
var EncoderBuffer = require('../base').EncoderBuffer;
|
|
var DecoderBuffer = require('../base').DecoderBuffer;
|
|
var assert = require('minimalistic-assert');
|
|
|
|
// Supported tags
|
|
var tags = [
|
|
'seq', 'seqof', 'set', 'setof', 'objid', 'bool',
|
|
'gentime', 'utctime', 'null_', 'enum', 'int', 'objDesc',
|
|
'bitstr', 'bmpstr', 'charstr', 'genstr', 'graphstr', 'ia5str', 'iso646str',
|
|
'numstr', 'octstr', 'printstr', 't61str', 'unistr', 'utf8str', 'videostr'
|
|
];
|
|
|
|
// Public methods list
|
|
var methods = [
|
|
'key', 'obj', 'use', 'optional', 'explicit', 'implicit', 'def', 'choice',
|
|
'any', 'contains'
|
|
].concat(tags);
|
|
|
|
// Overrided methods list
|
|
var overrided = [
|
|
'_peekTag', '_decodeTag', '_use',
|
|
'_decodeStr', '_decodeObjid', '_decodeTime',
|
|
'_decodeNull', '_decodeInt', '_decodeBool', '_decodeList',
|
|
|
|
'_encodeComposite', '_encodeStr', '_encodeObjid', '_encodeTime',
|
|
'_encodeNull', '_encodeInt', '_encodeBool'
|
|
];
|
|
|
|
function Node(enc, parent) {
|
|
var state = {};
|
|
this._baseState = state;
|
|
|
|
state.enc = enc;
|
|
|
|
state.parent = parent || null;
|
|
state.children = null;
|
|
|
|
// State
|
|
state.tag = null;
|
|
state.args = null;
|
|
state.reverseArgs = null;
|
|
state.choice = null;
|
|
state.optional = false;
|
|
state.any = false;
|
|
state.obj = false;
|
|
state.use = null;
|
|
state.useDecoder = null;
|
|
state.key = null;
|
|
state['default'] = null;
|
|
state.explicit = null;
|
|
state.implicit = null;
|
|
state.contains = null;
|
|
|
|
// Should create new instance on each method
|
|
if (!state.parent) {
|
|
state.children = [];
|
|
this._wrap();
|
|
}
|
|
}
|
|
module.exports = Node;
|
|
|
|
var stateProps = [
|
|
'enc', 'parent', 'children', 'tag', 'args', 'reverseArgs', 'choice',
|
|
'optional', 'any', 'obj', 'use', 'alteredUse', 'key', 'default', 'explicit',
|
|
'implicit', 'contains'
|
|
];
|
|
|
|
Node.prototype.clone = function clone() {
|
|
var state = this._baseState;
|
|
var cstate = {};
|
|
stateProps.forEach(function(prop) {
|
|
cstate[prop] = state[prop];
|
|
});
|
|
var res = new this.constructor(cstate.parent);
|
|
res._baseState = cstate;
|
|
return res;
|
|
};
|
|
|
|
Node.prototype._wrap = function wrap() {
|
|
var state = this._baseState;
|
|
methods.forEach(function(method) {
|
|
this[method] = function _wrappedMethod() {
|
|
var clone = new this.constructor(this);
|
|
state.children.push(clone);
|
|
return clone[method].apply(clone, arguments);
|
|
};
|
|
}, this);
|
|
};
|
|
|
|
Node.prototype._init = function init(body) {
|
|
var state = this._baseState;
|
|
|
|
assert(state.parent === null);
|
|
body.call(this);
|
|
|
|
// Filter children
|
|
state.children = state.children.filter(function(child) {
|
|
return child._baseState.parent === this;
|
|
}, this);
|
|
assert.equal(state.children.length, 1, 'Root node can have only one child');
|
|
};
|
|
|
|
Node.prototype._useArgs = function useArgs(args) {
|
|
var state = this._baseState;
|
|
|
|
// Filter children and args
|
|
var children = args.filter(function(arg) {
|
|
return arg instanceof this.constructor;
|
|
}, this);
|
|
args = args.filter(function(arg) {
|
|
return !(arg instanceof this.constructor);
|
|
}, this);
|
|
|
|
if (children.length !== 0) {
|
|
assert(state.children === null);
|
|
state.children = children;
|
|
|
|
// Replace parent to maintain backward link
|
|
children.forEach(function(child) {
|
|
child._baseState.parent = this;
|
|
}, this);
|
|
}
|
|
if (args.length !== 0) {
|
|
assert(state.args === null);
|
|
state.args = args;
|
|
state.reverseArgs = args.map(function(arg) {
|
|
if (typeof arg !== 'object' || arg.constructor !== Object)
|
|
return arg;
|
|
|
|
var res = {};
|
|
Object.keys(arg).forEach(function(key) {
|
|
if (key == (key | 0))
|
|
key |= 0;
|
|
var value = arg[key];
|
|
res[value] = key;
|
|
});
|
|
return res;
|
|
});
|
|
}
|
|
};
|
|
|
|
//
|
|
// Overrided methods
|
|
//
|
|
|
|
overrided.forEach(function(method) {
|
|
Node.prototype[method] = function _overrided() {
|
|
var state = this._baseState;
|
|
throw new Error(method + ' not implemented for encoding: ' + state.enc);
|
|
};
|
|
});
|
|
|
|
//
|
|
// Public methods
|
|
//
|
|
|
|
tags.forEach(function(tag) {
|
|
Node.prototype[tag] = function _tagMethod() {
|
|
var state = this._baseState;
|
|
var args = Array.prototype.slice.call(arguments);
|
|
|
|
assert(state.tag === null);
|
|
state.tag = tag;
|
|
|
|
this._useArgs(args);
|
|
|
|
return this;
|
|
};
|
|
});
|
|
|
|
Node.prototype.use = function use(item) {
|
|
assert(item);
|
|
var state = this._baseState;
|
|
|
|
assert(state.use === null);
|
|
state.use = item;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.optional = function optional() {
|
|
var state = this._baseState;
|
|
|
|
state.optional = true;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.def = function def(val) {
|
|
var state = this._baseState;
|
|
|
|
assert(state['default'] === null);
|
|
state['default'] = val;
|
|
state.optional = true;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.explicit = function explicit(num) {
|
|
var state = this._baseState;
|
|
|
|
assert(state.explicit === null && state.implicit === null);
|
|
state.explicit = num;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.implicit = function implicit(num) {
|
|
var state = this._baseState;
|
|
|
|
assert(state.explicit === null && state.implicit === null);
|
|
state.implicit = num;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.obj = function obj() {
|
|
var state = this._baseState;
|
|
var args = Array.prototype.slice.call(arguments);
|
|
|
|
state.obj = true;
|
|
|
|
if (args.length !== 0)
|
|
this._useArgs(args);
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.key = function key(newKey) {
|
|
var state = this._baseState;
|
|
|
|
assert(state.key === null);
|
|
state.key = newKey;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.any = function any() {
|
|
var state = this._baseState;
|
|
|
|
state.any = true;
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.choice = function choice(obj) {
|
|
var state = this._baseState;
|
|
|
|
assert(state.choice === null);
|
|
state.choice = obj;
|
|
this._useArgs(Object.keys(obj).map(function(key) {
|
|
return obj[key];
|
|
}));
|
|
|
|
return this;
|
|
};
|
|
|
|
Node.prototype.contains = function contains(item) {
|
|
var state = this._baseState;
|
|
|
|
assert(state.use === null);
|
|
state.contains = item;
|
|
|
|
return this;
|
|
};
|
|
|
|
//
|
|
// Decoding
|
|
//
|
|
|
|
Node.prototype._decode = function decode(input, options) {
|
|
var state = this._baseState;
|
|
|
|
// Decode root node
|
|
if (state.parent === null)
|
|
return input.wrapResult(state.children[0]._decode(input, options));
|
|
|
|
var result = state['default'];
|
|
var present = true;
|
|
|
|
var prevKey = null;
|
|
if (state.key !== null)
|
|
prevKey = input.enterKey(state.key);
|
|
|
|
// Check if tag is there
|
|
if (state.optional) {
|
|
var tag = null;
|
|
if (state.explicit !== null)
|
|
tag = state.explicit;
|
|
else if (state.implicit !== null)
|
|
tag = state.implicit;
|
|
else if (state.tag !== null)
|
|
tag = state.tag;
|
|
|
|
if (tag === null && !state.any) {
|
|
// Trial and Error
|
|
var save = input.save();
|
|
try {
|
|
if (state.choice === null)
|
|
this._decodeGeneric(state.tag, input, options);
|
|
else
|
|
this._decodeChoice(input, options);
|
|
present = true;
|
|
} catch (e) {
|
|
present = false;
|
|
}
|
|
input.restore(save);
|
|
} else {
|
|
present = this._peekTag(input, tag, state.any);
|
|
|
|
if (input.isError(present))
|
|
return present;
|
|
}
|
|
}
|
|
|
|
// Push object on stack
|
|
var prevObj;
|
|
if (state.obj && present)
|
|
prevObj = input.enterObject();
|
|
|
|
if (present) {
|
|
// Unwrap explicit values
|
|
if (state.explicit !== null) {
|
|
var explicit = this._decodeTag(input, state.explicit);
|
|
if (input.isError(explicit))
|
|
return explicit;
|
|
input = explicit;
|
|
}
|
|
|
|
var start = input.offset;
|
|
|
|
// Unwrap implicit and normal values
|
|
if (state.use === null && state.choice === null) {
|
|
if (state.any)
|
|
var save = input.save();
|
|
var body = this._decodeTag(
|
|
input,
|
|
state.implicit !== null ? state.implicit : state.tag,
|
|
state.any
|
|
);
|
|
if (input.isError(body))
|
|
return body;
|
|
|
|
if (state.any)
|
|
result = input.raw(save);
|
|
else
|
|
input = body;
|
|
}
|
|
|
|
if (options && options.track && state.tag !== null)
|
|
options.track(input.path(), start, input.length, 'tagged');
|
|
|
|
if (options && options.track && state.tag !== null)
|
|
options.track(input.path(), input.offset, input.length, 'content');
|
|
|
|
// Select proper method for tag
|
|
if (state.any)
|
|
result = result;
|
|
else if (state.choice === null)
|
|
result = this._decodeGeneric(state.tag, input, options);
|
|
else
|
|
result = this._decodeChoice(input, options);
|
|
|
|
if (input.isError(result))
|
|
return result;
|
|
|
|
// Decode children
|
|
if (!state.any && state.choice === null && state.children !== null) {
|
|
state.children.forEach(function decodeChildren(child) {
|
|
// NOTE: We are ignoring errors here, to let parser continue with other
|
|
// parts of encoded data
|
|
child._decode(input, options);
|
|
});
|
|
}
|
|
|
|
// Decode contained/encoded by schema, only in bit or octet strings
|
|
if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) {
|
|
var data = new DecoderBuffer(result);
|
|
result = this._getUse(state.contains, input._reporterState.obj)
|
|
._decode(data, options);
|
|
}
|
|
}
|
|
|
|
// Pop object
|
|
if (state.obj && present)
|
|
result = input.leaveObject(prevObj);
|
|
|
|
// Set key
|
|
if (state.key !== null && (result !== null || present === true))
|
|
input.leaveKey(prevKey, state.key, result);
|
|
else if (prevKey !== null)
|
|
input.exitKey(prevKey);
|
|
|
|
return result;
|
|
};
|
|
|
|
Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) {
|
|
var state = this._baseState;
|
|
|
|
if (tag === 'seq' || tag === 'set')
|
|
return null;
|
|
if (tag === 'seqof' || tag === 'setof')
|
|
return this._decodeList(input, tag, state.args[0], options);
|
|
else if (/str$/.test(tag))
|
|
return this._decodeStr(input, tag, options);
|
|
else if (tag === 'objid' && state.args)
|
|
return this._decodeObjid(input, state.args[0], state.args[1], options);
|
|
else if (tag === 'objid')
|
|
return this._decodeObjid(input, null, null, options);
|
|
else if (tag === 'gentime' || tag === 'utctime')
|
|
return this._decodeTime(input, tag, options);
|
|
else if (tag === 'null_')
|
|
return this._decodeNull(input, options);
|
|
else if (tag === 'bool')
|
|
return this._decodeBool(input, options);
|
|
else if (tag === 'objDesc')
|
|
return this._decodeStr(input, tag, options);
|
|
else if (tag === 'int' || tag === 'enum')
|
|
return this._decodeInt(input, state.args && state.args[0], options);
|
|
|
|
if (state.use !== null) {
|
|
return this._getUse(state.use, input._reporterState.obj)
|
|
._decode(input, options);
|
|
} else {
|
|
return input.error('unknown tag: ' + tag);
|
|
}
|
|
};
|
|
|
|
Node.prototype._getUse = function _getUse(entity, obj) {
|
|
|
|
var state = this._baseState;
|
|
// Create altered use decoder if implicit is set
|
|
state.useDecoder = this._use(entity, obj);
|
|
assert(state.useDecoder._baseState.parent === null);
|
|
state.useDecoder = state.useDecoder._baseState.children[0];
|
|
if (state.implicit !== state.useDecoder._baseState.implicit) {
|
|
state.useDecoder = state.useDecoder.clone();
|
|
state.useDecoder._baseState.implicit = state.implicit;
|
|
}
|
|
return state.useDecoder;
|
|
};
|
|
|
|
Node.prototype._decodeChoice = function decodeChoice(input, options) {
|
|
var state = this._baseState;
|
|
var result = null;
|
|
var match = false;
|
|
|
|
Object.keys(state.choice).some(function(key) {
|
|
var save = input.save();
|
|
var node = state.choice[key];
|
|
try {
|
|
var value = node._decode(input, options);
|
|
if (input.isError(value))
|
|
return false;
|
|
|
|
result = { type: key, value: value };
|
|
match = true;
|
|
} catch (e) {
|
|
input.restore(save);
|
|
return false;
|
|
}
|
|
return true;
|
|
}, this);
|
|
|
|
if (!match)
|
|
return input.error('Choice not matched');
|
|
|
|
return result;
|
|
};
|
|
|
|
//
|
|
// Encoding
|
|
//
|
|
|
|
Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) {
|
|
return new EncoderBuffer(data, this.reporter);
|
|
};
|
|
|
|
Node.prototype._encode = function encode(data, reporter, parent) {
|
|
var state = this._baseState;
|
|
if (state['default'] !== null && state['default'] === data)
|
|
return;
|
|
|
|
var result = this._encodeValue(data, reporter, parent);
|
|
if (result === undefined)
|
|
return;
|
|
|
|
if (this._skipDefault(result, reporter, parent))
|
|
return;
|
|
|
|
return result;
|
|
};
|
|
|
|
Node.prototype._encodeValue = function encode(data, reporter, parent) {
|
|
var state = this._baseState;
|
|
|
|
// Decode root node
|
|
if (state.parent === null)
|
|
return state.children[0]._encode(data, reporter || new Reporter());
|
|
|
|
var result = null;
|
|
|
|
// Set reporter to share it with a child class
|
|
this.reporter = reporter;
|
|
|
|
// Check if data is there
|
|
if (state.optional && data === undefined) {
|
|
if (state['default'] !== null)
|
|
data = state['default']
|
|
else
|
|
return;
|
|
}
|
|
|
|
// Encode children first
|
|
var content = null;
|
|
var primitive = false;
|
|
if (state.any) {
|
|
// Anything that was given is translated to buffer
|
|
result = this._createEncoderBuffer(data);
|
|
} else if (state.choice) {
|
|
result = this._encodeChoice(data, reporter);
|
|
} else if (state.contains) {
|
|
content = this._getUse(state.contains, parent)._encode(data, reporter);
|
|
primitive = true;
|
|
} else if (state.children) {
|
|
content = state.children.map(function(child) {
|
|
if (child._baseState.tag === 'null_')
|
|
return child._encode(null, reporter, data);
|
|
|
|
if (child._baseState.key === null)
|
|
return reporter.error('Child should have a key');
|
|
var prevKey = reporter.enterKey(child._baseState.key);
|
|
|
|
if (typeof data !== 'object')
|
|
return reporter.error('Child expected, but input is not object');
|
|
|
|
var res = child._encode(data[child._baseState.key], reporter, data);
|
|
reporter.leaveKey(prevKey);
|
|
|
|
return res;
|
|
}, this).filter(function(child) {
|
|
return child;
|
|
});
|
|
content = this._createEncoderBuffer(content);
|
|
} else {
|
|
if (state.tag === 'seqof' || state.tag === 'setof') {
|
|
// TODO(indutny): this should be thrown on DSL level
|
|
if (!(state.args && state.args.length === 1))
|
|
return reporter.error('Too many args for : ' + state.tag);
|
|
|
|
if (!Array.isArray(data))
|
|
return reporter.error('seqof/setof, but data is not Array');
|
|
|
|
var child = this.clone();
|
|
child._baseState.implicit = null;
|
|
content = this._createEncoderBuffer(data.map(function(item) {
|
|
var state = this._baseState;
|
|
|
|
return this._getUse(state.args[0], data)._encode(item, reporter);
|
|
}, child));
|
|
} else if (state.use !== null) {
|
|
result = this._getUse(state.use, parent)._encode(data, reporter);
|
|
} else {
|
|
content = this._encodePrimitive(state.tag, data);
|
|
primitive = true;
|
|
}
|
|
}
|
|
|
|
// Encode data itself
|
|
var result;
|
|
if (!state.any && state.choice === null) {
|
|
var tag = state.implicit !== null ? state.implicit : state.tag;
|
|
var cls = state.implicit === null ? 'universal' : 'context';
|
|
|
|
if (tag === null) {
|
|
if (state.use === null)
|
|
reporter.error('Tag could be ommited only for .use()');
|
|
} else {
|
|
if (state.use === null)
|
|
result = this._encodeComposite(tag, primitive, cls, content);
|
|
}
|
|
}
|
|
|
|
// Wrap in explicit
|
|
if (state.explicit !== null)
|
|
result = this._encodeComposite(state.explicit, false, 'context', result);
|
|
|
|
return result;
|
|
};
|
|
|
|
Node.prototype._encodeChoice = function encodeChoice(data, reporter) {
|
|
var state = this._baseState;
|
|
|
|
var node = state.choice[data.type];
|
|
if (!node) {
|
|
assert(
|
|
false,
|
|
data.type + ' not found in ' +
|
|
JSON.stringify(Object.keys(state.choice)));
|
|
}
|
|
return node._encode(data.value, reporter);
|
|
};
|
|
|
|
Node.prototype._encodePrimitive = function encodePrimitive(tag, data) {
|
|
var state = this._baseState;
|
|
|
|
if (/str$/.test(tag))
|
|
return this._encodeStr(data, tag);
|
|
else if (tag === 'objid' && state.args)
|
|
return this._encodeObjid(data, state.reverseArgs[0], state.args[1]);
|
|
else if (tag === 'objid')
|
|
return this._encodeObjid(data, null, null);
|
|
else if (tag === 'gentime' || tag === 'utctime')
|
|
return this._encodeTime(data, tag);
|
|
else if (tag === 'null_')
|
|
return this._encodeNull();
|
|
else if (tag === 'int' || tag === 'enum')
|
|
return this._encodeInt(data, state.args && state.reverseArgs[0]);
|
|
else if (tag === 'bool')
|
|
return this._encodeBool(data);
|
|
else if (tag === 'objDesc')
|
|
return this._encodeStr(data, tag);
|
|
else
|
|
throw new Error('Unsupported tag: ' + tag);
|
|
};
|
|
|
|
Node.prototype._isNumstr = function isNumstr(str) {
|
|
return /^[0-9 ]*$/.test(str);
|
|
};
|
|
|
|
Node.prototype._isPrintstr = function isPrintstr(str) {
|
|
return /^[A-Za-z0-9 '\(\)\+,\-\.\/:=\?]*$/.test(str);
|
|
};
|
|
|
|
},{"../base":103,"minimalistic-assert":114}],105:[function(require,module,exports){
|
|
var inherits = require('inherits');
|
|
|
|
function Reporter(options) {
|
|
this._reporterState = {
|
|
obj: null,
|
|
path: [],
|
|
options: options || {},
|
|
errors: []
|
|
};
|
|
}
|
|
exports.Reporter = Reporter;
|
|
|
|
Reporter.prototype.isError = function isError(obj) {
|
|
return obj instanceof ReporterError;
|
|
};
|
|
|
|
Reporter.prototype.save = function save() {
|
|
var state = this._reporterState;
|
|
|
|
return { obj: state.obj, pathLen: state.path.length };
|
|
};
|
|
|
|
Reporter.prototype.restore = function restore(data) {
|
|
var state = this._reporterState;
|
|
|
|
state.obj = data.obj;
|
|
state.path = state.path.slice(0, data.pathLen);
|
|
};
|
|
|
|
Reporter.prototype.enterKey = function enterKey(key) {
|
|
return this._reporterState.path.push(key);
|
|
};
|
|
|
|
Reporter.prototype.exitKey = function exitKey(index) {
|
|
var state = this._reporterState;
|
|
|
|
state.path = state.path.slice(0, index - 1);
|
|
};
|
|
|
|
Reporter.prototype.leaveKey = function leaveKey(index, key, value) {
|
|
var state = this._reporterState;
|
|
|
|
this.exitKey(index);
|
|
if (state.obj !== null)
|
|
state.obj[key] = value;
|
|
};
|
|
|
|
Reporter.prototype.path = function path() {
|
|
return this._reporterState.path.join('/');
|
|
};
|
|
|
|
Reporter.prototype.enterObject = function enterObject() {
|
|
var state = this._reporterState;
|
|
|
|
var prev = state.obj;
|
|
state.obj = {};
|
|
return prev;
|
|
};
|
|
|
|
Reporter.prototype.leaveObject = function leaveObject(prev) {
|
|
var state = this._reporterState;
|
|
|
|
var now = state.obj;
|
|
state.obj = prev;
|
|
return now;
|
|
};
|
|
|
|
Reporter.prototype.error = function error(msg) {
|
|
var err;
|
|
var state = this._reporterState;
|
|
|
|
var inherited = msg instanceof ReporterError;
|
|
if (inherited) {
|
|
err = msg;
|
|
} else {
|
|
err = new ReporterError(state.path.map(function(elem) {
|
|
return '[' + JSON.stringify(elem) + ']';
|
|
}).join(''), msg.message || msg, msg.stack);
|
|
}
|
|
|
|
if (!state.options.partial)
|
|
throw err;
|
|
|
|
if (!inherited)
|
|
state.errors.push(err);
|
|
|
|
return err;
|
|
};
|
|
|
|
Reporter.prototype.wrapResult = function wrapResult(result) {
|
|
var state = this._reporterState;
|
|
if (!state.options.partial)
|
|
return result;
|
|
|
|
return {
|
|
result: this.isError(result) ? null : result,
|
|
errors: state.errors
|
|
};
|
|
};
|
|
|
|
function ReporterError(path, msg) {
|
|
this.path = path;
|
|
this.rethrow(msg);
|
|
};
|
|
inherits(ReporterError, Error);
|
|
|
|
ReporterError.prototype.rethrow = function rethrow(msg) {
|
|
this.message = msg + ' at: ' + (this.path || '(shallow)');
|
|
if (Error.captureStackTrace)
|
|
Error.captureStackTrace(this, ReporterError);
|
|
|
|
if (!this.stack) {
|
|
try {
|
|
// IE only adds stack when thrown
|
|
throw new Error(this.message);
|
|
} catch (e) {
|
|
this.stack = e.stack;
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
},{"inherits":318}],106:[function(require,module,exports){
|
|
var constants = require('../constants');
|
|
|
|
exports.tagClass = {
|
|
0: 'universal',
|
|
1: 'application',
|
|
2: 'context',
|
|
3: 'private'
|
|
};
|
|
exports.tagClassByName = constants._reverse(exports.tagClass);
|
|
|
|
exports.tag = {
|
|
0x00: 'end',
|
|
0x01: 'bool',
|
|
0x02: 'int',
|
|
0x03: 'bitstr',
|
|
0x04: 'octstr',
|
|
0x05: 'null_',
|
|
0x06: 'objid',
|
|
0x07: 'objDesc',
|
|
0x08: 'external',
|
|
0x09: 'real',
|
|
0x0a: 'enum',
|
|
0x0b: 'embed',
|
|
0x0c: 'utf8str',
|
|
0x0d: 'relativeOid',
|
|
0x10: 'seq',
|
|
0x11: 'set',
|
|
0x12: 'numstr',
|
|
0x13: 'printstr',
|
|
0x14: 't61str',
|
|
0x15: 'videostr',
|
|
0x16: 'ia5str',
|
|
0x17: 'utctime',
|
|
0x18: 'gentime',
|
|
0x19: 'graphstr',
|
|
0x1a: 'iso646str',
|
|
0x1b: 'genstr',
|
|
0x1c: 'unistr',
|
|
0x1d: 'charstr',
|
|
0x1e: 'bmpstr'
|
|
};
|
|
exports.tagByName = constants._reverse(exports.tag);
|
|
|
|
},{"../constants":107}],107:[function(require,module,exports){
|
|
var constants = exports;
|
|
|
|
// Helper
|
|
constants._reverse = function reverse(map) {
|
|
var res = {};
|
|
|
|
Object.keys(map).forEach(function(key) {
|
|
// Convert key to integer if it is stringified
|
|
if ((key | 0) == key)
|
|
key = key | 0;
|
|
|
|
var value = map[key];
|
|
res[value] = key;
|
|
});
|
|
|
|
return res;
|
|
};
|
|
|
|
constants.der = require('./der');
|
|
|
|
},{"./der":106}],108:[function(require,module,exports){
|
|
var inherits = require('inherits');
|
|
|
|
var asn1 = require('../../asn1');
|
|
var base = asn1.base;
|
|
var bignum = asn1.bignum;
|
|
|
|
// Import DER constants
|
|
var der = asn1.constants.der;
|
|
|
|
function DERDecoder(entity) {
|
|
this.enc = 'der';
|
|
this.name = entity.name;
|
|
this.entity = entity;
|
|
|
|
// Construct base tree
|
|
this.tree = new DERNode();
|
|
this.tree._init(entity.body);
|
|
};
|
|
module.exports = DERDecoder;
|
|
|
|
DERDecoder.prototype.decode = function decode(data, options) {
|
|
if (!(data instanceof base.DecoderBuffer))
|
|
data = new base.DecoderBuffer(data, options);
|
|
|
|
return this.tree._decode(data, options);
|
|
};
|
|
|
|
// Tree methods
|
|
|
|
function DERNode(parent) {
|
|
base.Node.call(this, 'der', parent);
|
|
}
|
|
inherits(DERNode, base.Node);
|
|
|
|
DERNode.prototype._peekTag = function peekTag(buffer, tag, any) {
|
|
if (buffer.isEmpty())
|
|
return false;
|
|
|
|
var state = buffer.save();
|
|
var decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"');
|
|
if (buffer.isError(decodedTag))
|
|
return decodedTag;
|
|
|
|
buffer.restore(state);
|
|
|
|
return decodedTag.tag === tag || decodedTag.tagStr === tag ||
|
|
(decodedTag.tagStr + 'of') === tag || any;
|
|
};
|
|
|
|
DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) {
|
|
var decodedTag = derDecodeTag(buffer,
|
|
'Failed to decode tag of "' + tag + '"');
|
|
if (buffer.isError(decodedTag))
|
|
return decodedTag;
|
|
|
|
var len = derDecodeLen(buffer,
|
|
decodedTag.primitive,
|
|
'Failed to get length of "' + tag + '"');
|
|
|
|
// Failure
|
|
if (buffer.isError(len))
|
|
return len;
|
|
|
|
if (!any &&
|
|
decodedTag.tag !== tag &&
|
|
decodedTag.tagStr !== tag &&
|
|
decodedTag.tagStr + 'of' !== tag) {
|
|
return buffer.error('Failed to match tag: "' + tag + '"');
|
|
}
|
|
|
|
if (decodedTag.primitive || len !== null)
|
|
return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
|
|
|
|
// Indefinite length... find END tag
|
|
var state = buffer.save();
|
|
var res = this._skipUntilEnd(
|
|
buffer,
|
|
'Failed to skip indefinite length body: "' + this.tag + '"');
|
|
if (buffer.isError(res))
|
|
return res;
|
|
|
|
len = buffer.offset - state.offset;
|
|
buffer.restore(state);
|
|
return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
|
|
};
|
|
|
|
DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) {
|
|
while (true) {
|
|
var tag = derDecodeTag(buffer, fail);
|
|
if (buffer.isError(tag))
|
|
return tag;
|
|
var len = derDecodeLen(buffer, tag.primitive, fail);
|
|
if (buffer.isError(len))
|
|
return len;
|
|
|
|
var res;
|
|
if (tag.primitive || len !== null)
|
|
res = buffer.skip(len)
|
|
else
|
|
res = this._skipUntilEnd(buffer, fail);
|
|
|
|
// Failure
|
|
if (buffer.isError(res))
|
|
return res;
|
|
|
|
if (tag.tagStr === 'end')
|
|
break;
|
|
}
|
|
};
|
|
|
|
DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder,
|
|
options) {
|
|
var result = [];
|
|
while (!buffer.isEmpty()) {
|
|
var possibleEnd = this._peekTag(buffer, 'end');
|
|
if (buffer.isError(possibleEnd))
|
|
return possibleEnd;
|
|
|
|
var res = decoder.decode(buffer, 'der', options);
|
|
if (buffer.isError(res) && possibleEnd)
|
|
break;
|
|
result.push(res);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
DERNode.prototype._decodeStr = function decodeStr(buffer, tag) {
|
|
if (tag === 'bitstr') {
|
|
var unused = buffer.readUInt8();
|
|
if (buffer.isError(unused))
|
|
return unused;
|
|
return { unused: unused, data: buffer.raw() };
|
|
} else if (tag === 'bmpstr') {
|
|
var raw = buffer.raw();
|
|
if (raw.length % 2 === 1)
|
|
return buffer.error('Decoding of string type: bmpstr length mismatch');
|
|
|
|
var str = '';
|
|
for (var i = 0; i < raw.length / 2; i++) {
|
|
str += String.fromCharCode(raw.readUInt16BE(i * 2));
|
|
}
|
|
return str;
|
|
} else if (tag === 'numstr') {
|
|
var numstr = buffer.raw().toString('ascii');
|
|
if (!this._isNumstr(numstr)) {
|
|
return buffer.error('Decoding of string type: ' +
|
|
'numstr unsupported characters');
|
|
}
|
|
return numstr;
|
|
} else if (tag === 'octstr') {
|
|
return buffer.raw();
|
|
} else if (tag === 'objDesc') {
|
|
return buffer.raw();
|
|
} else if (tag === 'printstr') {
|
|
var printstr = buffer.raw().toString('ascii');
|
|
if (!this._isPrintstr(printstr)) {
|
|
return buffer.error('Decoding of string type: ' +
|
|
'printstr unsupported characters');
|
|
}
|
|
return printstr;
|
|
} else if (/str$/.test(tag)) {
|
|
return buffer.raw().toString();
|
|
} else {
|
|
return buffer.error('Decoding of string type: ' + tag + ' unsupported');
|
|
}
|
|
};
|
|
|
|
DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) {
|
|
var result;
|
|
var identifiers = [];
|
|
var ident = 0;
|
|
while (!buffer.isEmpty()) {
|
|
var subident = buffer.readUInt8();
|
|
ident <<= 7;
|
|
ident |= subident & 0x7f;
|
|
if ((subident & 0x80) === 0) {
|
|
identifiers.push(ident);
|
|
ident = 0;
|
|
}
|
|
}
|
|
if (subident & 0x80)
|
|
identifiers.push(ident);
|
|
|
|
var first = (identifiers[0] / 40) | 0;
|
|
var second = identifiers[0] % 40;
|
|
|
|
if (relative)
|
|
result = identifiers;
|
|
else
|
|
result = [first, second].concat(identifiers.slice(1));
|
|
|
|
if (values) {
|
|
var tmp = values[result.join(' ')];
|
|
if (tmp === undefined)
|
|
tmp = values[result.join('.')];
|
|
if (tmp !== undefined)
|
|
result = tmp;
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
DERNode.prototype._decodeTime = function decodeTime(buffer, tag) {
|
|
var str = buffer.raw().toString();
|
|
if (tag === 'gentime') {
|
|
var year = str.slice(0, 4) | 0;
|
|
var mon = str.slice(4, 6) | 0;
|
|
var day = str.slice(6, 8) | 0;
|
|
var hour = str.slice(8, 10) | 0;
|
|
var min = str.slice(10, 12) | 0;
|
|
var sec = str.slice(12, 14) | 0;
|
|
} else if (tag === 'utctime') {
|
|
var year = str.slice(0, 2) | 0;
|
|
var mon = str.slice(2, 4) | 0;
|
|
var day = str.slice(4, 6) | 0;
|
|
var hour = str.slice(6, 8) | 0;
|
|
var min = str.slice(8, 10) | 0;
|
|
var sec = str.slice(10, 12) | 0;
|
|
if (year < 70)
|
|
year = 2000 + year;
|
|
else
|
|
year = 1900 + year;
|
|
} else {
|
|
return buffer.error('Decoding ' + tag + ' time is not supported yet');
|
|
}
|
|
|
|
return Date.UTC(year, mon - 1, day, hour, min, sec, 0);
|
|
};
|
|
|
|
DERNode.prototype._decodeNull = function decodeNull(buffer) {
|
|
return null;
|
|
};
|
|
|
|
DERNode.prototype._decodeBool = function decodeBool(buffer) {
|
|
var res = buffer.readUInt8();
|
|
if (buffer.isError(res))
|
|
return res;
|
|
else
|
|
return res !== 0;
|
|
};
|
|
|
|
DERNode.prototype._decodeInt = function decodeInt(buffer, values) {
|
|
// Bigint, return as it is (assume big endian)
|
|
var raw = buffer.raw();
|
|
var res = new bignum(raw);
|
|
|
|
if (values)
|
|
res = values[res.toString(10)] || res;
|
|
|
|
return res;
|
|
};
|
|
|
|
DERNode.prototype._use = function use(entity, obj) {
|
|
if (typeof entity === 'function')
|
|
entity = entity(obj);
|
|
return entity._getDecoder('der').tree;
|
|
};
|
|
|
|
// Utility methods
|
|
|
|
function derDecodeTag(buf, fail) {
|
|
var tag = buf.readUInt8(fail);
|
|
if (buf.isError(tag))
|
|
return tag;
|
|
|
|
var cls = der.tagClass[tag >> 6];
|
|
var primitive = (tag & 0x20) === 0;
|
|
|
|
// Multi-octet tag - load
|
|
if ((tag & 0x1f) === 0x1f) {
|
|
var oct = tag;
|
|
tag = 0;
|
|
while ((oct & 0x80) === 0x80) {
|
|
oct = buf.readUInt8(fail);
|
|
if (buf.isError(oct))
|
|
return oct;
|
|
|
|
tag <<= 7;
|
|
tag |= oct & 0x7f;
|
|
}
|
|
} else {
|
|
tag &= 0x1f;
|
|
}
|
|
var tagStr = der.tag[tag];
|
|
|
|
return {
|
|
cls: cls,
|
|
primitive: primitive,
|
|
tag: tag,
|
|
tagStr: tagStr
|
|
};
|
|
}
|
|
|
|
function derDecodeLen(buf, primitive, fail) {
|
|
var len = buf.readUInt8(fail);
|
|
if (buf.isError(len))
|
|
return len;
|
|
|
|
// Indefinite form
|
|
if (!primitive && len === 0x80)
|
|
return null;
|
|
|
|
// Definite form
|
|
if ((len & 0x80) === 0) {
|
|
// Short form
|
|
return len;
|
|
}
|
|
|
|
// Long form
|
|
var num = len & 0x7f;
|
|
if (num > 4)
|
|
return buf.error('length octect is too long');
|
|
|
|
len = 0;
|
|
for (var i = 0; i < num; i++) {
|
|
len <<= 8;
|
|
var j = buf.readUInt8(fail);
|
|
if (buf.isError(j))
|
|
return j;
|
|
len |= j;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
},{"../../asn1":100,"inherits":318}],109:[function(require,module,exports){
|
|
var decoders = exports;
|
|
|
|
decoders.der = require('./der');
|
|
decoders.pem = require('./pem');
|
|
|
|
},{"./der":108,"./pem":110}],110:[function(require,module,exports){
|
|
var inherits = require('inherits');
|
|
var Buffer = require('buffer').Buffer;
|
|
|
|
var DERDecoder = require('./der');
|
|
|
|
function PEMDecoder(entity) {
|
|
DERDecoder.call(this, entity);
|
|
this.enc = 'pem';
|
|
};
|
|
inherits(PEMDecoder, DERDecoder);
|
|
module.exports = PEMDecoder;
|
|
|
|
PEMDecoder.prototype.decode = function decode(data, options) {
|
|
var lines = data.toString().split(/[\r\n]+/g);
|
|
|
|
var label = options.label.toUpperCase();
|
|
|
|
var re = /^-----(BEGIN|END) ([^-]+)-----$/;
|
|
var start = -1;
|
|
var end = -1;
|
|
for (var i = 0; i < lines.length; i++) {
|
|
var match = lines[i].match(re);
|
|
if (match === null)
|
|
continue;
|
|
|
|
if (match[2] !== label)
|
|
continue;
|
|
|
|
if (start === -1) {
|
|
if (match[1] !== 'BEGIN')
|
|
break;
|
|
start = i;
|
|
} else {
|
|
if (match[1] !== 'END')
|
|
break;
|
|
end = i;
|
|
break;
|
|
}
|
|
}
|
|
if (start === -1 || end === -1)
|
|
throw new Error('PEM section not found for: ' + label);
|
|
|
|
var base64 = lines.slice(start + 1, end).join('');
|
|
// Remove excessive symbols
|
|
base64.replace(/[^a-z0-9\+\/=]+/gi, '');
|
|
|
|
var input = new Buffer(base64, 'base64');
|
|
return DERDecoder.prototype.decode.call(this, input, options);
|
|
};
|
|
|
|
},{"./der":108,"buffer":47,"inherits":318}],111:[function(require,module,exports){
|
|
var inherits = require('inherits');
|
|
var Buffer = require('buffer').Buffer;
|
|
|
|
var asn1 = require('../../asn1');
|
|
var base = asn1.base;
|
|
|
|
// Import DER constants
|
|
var der = asn1.constants.der;
|
|
|
|
function DEREncoder(entity) {
|
|
this.enc = 'der';
|
|
this.name = entity.name;
|
|
this.entity = entity;
|
|
|
|
// Construct base tree
|
|
this.tree = new DERNode();
|
|
this.tree._init(entity.body);
|
|
};
|
|
module.exports = DEREncoder;
|
|
|
|
DEREncoder.prototype.encode = function encode(data, reporter) {
|
|
return this.tree._encode(data, reporter).join();
|
|
};
|
|
|
|
// Tree methods
|
|
|
|
function DERNode(parent) {
|
|
base.Node.call(this, 'der', parent);
|
|
}
|
|
inherits(DERNode, base.Node);
|
|
|
|
DERNode.prototype._encodeComposite = function encodeComposite(tag,
|
|
primitive,
|
|
cls,
|
|
content) {
|
|
var encodedTag = encodeTag(tag, primitive, cls, this.reporter);
|
|
|
|
// Short form
|
|
if (content.length < 0x80) {
|
|
var header = new Buffer(2);
|
|
header[0] = encodedTag;
|
|
header[1] = content.length;
|
|
return this._createEncoderBuffer([ header, content ]);
|
|
}
|
|
|
|
// Long form
|
|
// Count octets required to store length
|
|
var lenOctets = 1;
|
|
for (var i = content.length; i >= 0x100; i >>= 8)
|
|
lenOctets++;
|
|
|
|
var header = new Buffer(1 + 1 + lenOctets);
|
|
header[0] = encodedTag;
|
|
header[1] = 0x80 | lenOctets;
|
|
|
|
for (var i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8)
|
|
header[i] = j & 0xff;
|
|
|
|
return this._createEncoderBuffer([ header, content ]);
|
|
};
|
|
|
|
DERNode.prototype._encodeStr = function encodeStr(str, tag) {
|
|
if (tag === 'bitstr') {
|
|
return this._createEncoderBuffer([ str.unused | 0, str.data ]);
|
|
} else if (tag === 'bmpstr') {
|
|
var buf = new Buffer(str.length * 2);
|
|
for (var i = 0; i < str.length; i++) {
|
|
buf.writeUInt16BE(str.charCodeAt(i), i * 2);
|
|
}
|
|
return this._createEncoderBuffer(buf);
|
|
} else if (tag === 'numstr') {
|
|
if (!this._isNumstr(str)) {
|
|
return this.reporter.error('Encoding of string type: numstr supports ' +
|
|
'only digits and space');
|
|
}
|
|
return this._createEncoderBuffer(str);
|
|
} else if (tag === 'printstr') {
|
|
if (!this._isPrintstr(str)) {
|
|
return this.reporter.error('Encoding of string type: printstr supports ' +
|
|
'only latin upper and lower case letters, ' +
|
|
'digits, space, apostrophe, left and rigth ' +
|
|
'parenthesis, plus sign, comma, hyphen, ' +
|
|
'dot, slash, colon, equal sign, ' +
|
|
'question mark');
|
|
}
|
|
return this._createEncoderBuffer(str);
|
|
} else if (/str$/.test(tag)) {
|
|
return this._createEncoderBuffer(str);
|
|
} else if (tag === 'objDesc') {
|
|
return this._createEncoderBuffer(str);
|
|
} else {
|
|
return this.reporter.error('Encoding of string type: ' + tag +
|
|
' unsupported');
|
|
}
|
|
};
|
|
|
|
DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) {
|
|
if (typeof id === 'string') {
|
|
if (!values)
|
|
return this.reporter.error('string objid given, but no values map found');
|
|
if (!values.hasOwnProperty(id))
|
|
return this.reporter.error('objid not found in values map');
|
|
id = values[id].split(/[\s\.]+/g);
|
|
for (var i = 0; i < id.length; i++)
|
|
id[i] |= 0;
|
|
} else if (Array.isArray(id)) {
|
|
id = id.slice();
|
|
for (var i = 0; i < id.length; i++)
|
|
id[i] |= 0;
|
|
}
|
|
|
|
if (!Array.isArray(id)) {
|
|
return this.reporter.error('objid() should be either array or string, ' +
|
|
'got: ' + JSON.stringify(id));
|
|
}
|
|
|
|
if (!relative) {
|
|
if (id[1] >= 40)
|
|
return this.reporter.error('Second objid identifier OOB');
|
|
id.splice(0, 2, id[0] * 40 + id[1]);
|
|
}
|
|
|
|
// Count number of octets
|
|
var size = 0;
|
|
for (var i = 0; i < id.length; i++) {
|
|
var ident = id[i];
|
|
for (size++; ident >= 0x80; ident >>= 7)
|
|
size++;
|
|
}
|
|
|
|
var objid = new Buffer(size);
|
|
var offset = objid.length - 1;
|
|
for (var i = id.length - 1; i >= 0; i--) {
|
|
var ident = id[i];
|
|
objid[offset--] = ident & 0x7f;
|
|
while ((ident >>= 7) > 0)
|
|
objid[offset--] = 0x80 | (ident & 0x7f);
|
|
}
|
|
|
|
return this._createEncoderBuffer(objid);
|
|
};
|
|
|
|
function two(num) {
|
|
if (num < 10)
|
|
return '0' + num;
|
|
else
|
|
return num;
|
|
}
|
|
|
|
DERNode.prototype._encodeTime = function encodeTime(time, tag) {
|
|
var str;
|
|
var date = new Date(time);
|
|
|
|
if (tag === 'gentime') {
|
|
str = [
|
|
two(date.getFullYear()),
|
|
two(date.getUTCMonth() + 1),
|
|
two(date.getUTCDate()),
|
|
two(date.getUTCHours()),
|
|
two(date.getUTCMinutes()),
|
|
two(date.getUTCSeconds()),
|
|
'Z'
|
|
].join('');
|
|
} else if (tag === 'utctime') {
|
|
str = [
|
|
two(date.getFullYear() % 100),
|
|
two(date.getUTCMonth() + 1),
|
|
two(date.getUTCDate()),
|
|
two(date.getUTCHours()),
|
|
two(date.getUTCMinutes()),
|
|
two(date.getUTCSeconds()),
|
|
'Z'
|
|
].join('');
|
|
} else {
|
|
this.reporter.error('Encoding ' + tag + ' time is not supported yet');
|
|
}
|
|
|
|
return this._encodeStr(str, 'octstr');
|
|
};
|
|
|
|
DERNode.prototype._encodeNull = function encodeNull() {
|
|
return this._createEncoderBuffer('');
|
|
};
|
|
|
|
DERNode.prototype._encodeInt = function encodeInt(num, values) {
|
|
if (typeof num === 'string') {
|
|
if (!values)
|
|
return this.reporter.error('String int or enum given, but no values map');
|
|
if (!values.hasOwnProperty(num)) {
|
|
return this.reporter.error('Values map doesn\'t contain: ' +
|
|
JSON.stringify(num));
|
|
}
|
|
num = values[num];
|
|
}
|
|
|
|
// Bignum, assume big endian
|
|
if (typeof num !== 'number' && !Buffer.isBuffer(num)) {
|
|
var numArray = num.toArray();
|
|
if (!num.sign && numArray[0] & 0x80) {
|
|
numArray.unshift(0);
|
|
}
|
|
num = new Buffer(numArray);
|
|
}
|
|
|
|
if (Buffer.isBuffer(num)) {
|
|
var size = num.length;
|
|
if (num.length === 0)
|
|
size++;
|
|
|
|
var out = new Buffer(size);
|
|
num.copy(out);
|
|
if (num.length === 0)
|
|
out[0] = 0
|
|
return this._createEncoderBuffer(out);
|
|
}
|
|
|
|
if (num < 0x80)
|
|
return this._createEncoderBuffer(num);
|
|
|
|
if (num < 0x100)
|
|
return this._createEncoderBuffer([0, num]);
|
|
|
|
var size = 1;
|
|
for (var i = num; i >= 0x100; i >>= 8)
|
|
size++;
|
|
|
|
var out = new Array(size);
|
|
for (var i = out.length - 1; i >= 0; i--) {
|
|
out[i] = num & 0xff;
|
|
num >>= 8;
|
|
}
|
|
if(out[0] & 0x80) {
|
|
out.unshift(0);
|
|
}
|
|
|
|
return this._createEncoderBuffer(new Buffer(out));
|
|
};
|
|
|
|
DERNode.prototype._encodeBool = function encodeBool(value) {
|
|
return this._createEncoderBuffer(value ? 0xff : 0);
|
|
};
|
|
|
|
DERNode.prototype._use = function use(entity, obj) {
|
|
if (typeof entity === 'function')
|
|
entity = entity(obj);
|
|
return entity._getEncoder('der').tree;
|
|
};
|
|
|
|
DERNode.prototype._skipDefault = function skipDefault(dataBuffer, reporter, parent) {
|
|
var state = this._baseState;
|
|
var i;
|
|
if (state['default'] === null)
|
|
return false;
|
|
|
|
var data = dataBuffer.join();
|
|
if (state.defaultBuffer === undefined)
|
|
state.defaultBuffer = this._encodeValue(state['default'], reporter, parent).join();
|
|
|
|
if (data.length !== state.defaultBuffer.length)
|
|
return false;
|
|
|
|
for (i=0; i < data.length; i++)
|
|
if (data[i] !== state.defaultBuffer[i])
|
|
return false;
|
|
|
|
return true;
|
|
};
|
|
|
|
// Utility methods
|
|
|
|
function encodeTag(tag, primitive, cls, reporter) {
|
|
var res;
|
|
|
|
if (tag === 'seqof')
|
|
tag = 'seq';
|
|
else if (tag === 'setof')
|
|
tag = 'set';
|
|
|
|
if (der.tagByName.hasOwnProperty(tag))
|
|
res = der.tagByName[tag];
|
|
else if (typeof tag === 'number' && (tag | 0) === tag)
|
|
res = tag;
|
|
else
|
|
return reporter.error('Unknown tag: ' + tag);
|
|
|
|
if (res >= 0x1f)
|
|
return reporter.error('Multi-octet tag encoding unsupported');
|
|
|
|
if (!primitive)
|
|
res |= 0x20;
|
|
|
|
res |= (der.tagClassByName[cls || 'universal'] << 6);
|
|
|
|
return res;
|
|
}
|
|
|
|
},{"../../asn1":100,"buffer":47,"inherits":318}],112:[function(require,module,exports){
|
|
var encoders = exports;
|
|
|
|
encoders.der = require('./der');
|
|
encoders.pem = require('./pem');
|
|
|
|
},{"./der":111,"./pem":113}],113:[function(require,module,exports){
|
|
var inherits = require('inherits');
|
|
|
|
var DEREncoder = require('./der');
|
|
|
|
function PEMEncoder(entity) {
|
|
DEREncoder.call(this, entity);
|
|
this.enc = 'pem';
|
|
};
|
|
inherits(PEMEncoder, DEREncoder);
|
|
module.exports = PEMEncoder;
|
|
|
|
PEMEncoder.prototype.encode = function encode(data, options) {
|
|
var buf = DEREncoder.prototype.encode.call(this, data);
|
|
|
|
var p = buf.toString('base64');
|
|
var out = [ '-----BEGIN ' + options.label + '-----' ];
|
|
for (var i = 0; i < p.length; i += 64)
|
|
out.push(p.slice(i, i + 64));
|
|
out.push('-----END ' + options.label + '-----');
|
|
return out.join('\n');
|
|
};
|
|
|
|
},{"./der":111,"inherits":318}],114:[function(require,module,exports){
|
|
arguments[4][83][0].apply(exports,arguments)
|
|
},{"dup":83}],115:[function(require,module,exports){
|
|
arguments[4][53][0].apply(exports,arguments)
|
|
},{"dup":53,"safe-buffer":133}],116:[function(require,module,exports){
|
|
arguments[4][54][0].apply(exports,arguments)
|
|
},{"./aes":115,"./ghash":120,"./incr32":121,"buffer-xor":131,"cipher-base":132,"dup":54,"inherits":318,"safe-buffer":133}],117:[function(require,module,exports){
|
|
arguments[4][55][0].apply(exports,arguments)
|
|
},{"./decrypter":118,"./encrypter":119,"./modes/list.json":129,"dup":55}],118:[function(require,module,exports){
|
|
arguments[4][56][0].apply(exports,arguments)
|
|
},{"./aes":115,"./authCipher":116,"./modes":128,"./streamCipher":134,"cipher-base":132,"dup":56,"evp_bytestokey":135,"inherits":318,"safe-buffer":133}],119:[function(require,module,exports){
|
|
arguments[4][57][0].apply(exports,arguments)
|
|
},{"./aes":115,"./authCipher":116,"./modes":128,"./streamCipher":134,"cipher-base":132,"dup":57,"evp_bytestokey":135,"inherits":318,"safe-buffer":133}],120:[function(require,module,exports){
|
|
arguments[4][58][0].apply(exports,arguments)
|
|
},{"dup":58,"safe-buffer":133}],121:[function(require,module,exports){
|
|
arguments[4][59][0].apply(exports,arguments)
|
|
},{"dup":59}],122:[function(require,module,exports){
|
|
arguments[4][60][0].apply(exports,arguments)
|
|
},{"buffer-xor":131,"dup":60}],123:[function(require,module,exports){
|
|
arguments[4][61][0].apply(exports,arguments)
|
|
},{"buffer-xor":131,"dup":61,"safe-buffer":133}],124:[function(require,module,exports){
|
|
arguments[4][62][0].apply(exports,arguments)
|
|
},{"dup":62,"safe-buffer":133}],125:[function(require,module,exports){
|
|
arguments[4][63][0].apply(exports,arguments)
|
|
},{"dup":63,"safe-buffer":133}],126:[function(require,module,exports){
|
|
arguments[4][64][0].apply(exports,arguments)
|
|
},{"../incr32":121,"buffer-xor":131,"dup":64,"safe-buffer":133}],127:[function(require,module,exports){
|
|
arguments[4][65][0].apply(exports,arguments)
|
|
},{"dup":65}],128:[function(require,module,exports){
|
|
arguments[4][66][0].apply(exports,arguments)
|
|
},{"./cbc":122,"./cfb":123,"./cfb1":124,"./cfb8":125,"./ctr":126,"./ecb":127,"./list.json":129,"./ofb":130,"dup":66}],129:[function(require,module,exports){
|
|
arguments[4][67][0].apply(exports,arguments)
|
|
},{"dup":67}],130:[function(require,module,exports){
|
|
arguments[4][68][0].apply(exports,arguments)
|
|
},{"buffer":47,"buffer-xor":131,"dup":68}],131:[function(require,module,exports){
|
|
arguments[4][69][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":69}],132:[function(require,module,exports){
|
|
arguments[4][70][0].apply(exports,arguments)
|
|
},{"dup":70,"inherits":318,"safe-buffer":133,"stream":272,"string_decoder":273}],133:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],134:[function(require,module,exports){
|
|
arguments[4][72][0].apply(exports,arguments)
|
|
},{"./aes":115,"cipher-base":132,"dup":72,"inherits":318,"safe-buffer":133}],135:[function(require,module,exports){
|
|
arguments[4][84][0].apply(exports,arguments)
|
|
},{"dup":84,"md5.js":136,"safe-buffer":138}],136:[function(require,module,exports){
|
|
arguments[4][85][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":85,"hash-base":137,"inherits":318}],137:[function(require,module,exports){
|
|
arguments[4][86][0].apply(exports,arguments)
|
|
},{"dup":86,"inherits":318,"safe-buffer":138,"stream":272}],138:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],139:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var elliptic = require('elliptic');
|
|
var BN = require('bn.js');
|
|
|
|
module.exports = function createECDH(curve) {
|
|
return new ECDH(curve);
|
|
};
|
|
|
|
var aliases = {
|
|
secp256k1: {
|
|
name: 'secp256k1',
|
|
byteLength: 32
|
|
},
|
|
secp224r1: {
|
|
name: 'p224',
|
|
byteLength: 28
|
|
},
|
|
prime256v1: {
|
|
name: 'p256',
|
|
byteLength: 32
|
|
},
|
|
prime192v1: {
|
|
name: 'p192',
|
|
byteLength: 24
|
|
},
|
|
ed25519: {
|
|
name: 'ed25519',
|
|
byteLength: 32
|
|
},
|
|
secp384r1: {
|
|
name: 'p384',
|
|
byteLength: 48
|
|
},
|
|
secp521r1: {
|
|
name: 'p521',
|
|
byteLength: 66
|
|
}
|
|
};
|
|
|
|
aliases.p224 = aliases.secp224r1;
|
|
aliases.p256 = aliases.secp256r1 = aliases.prime256v1;
|
|
aliases.p192 = aliases.secp192r1 = aliases.prime192v1;
|
|
aliases.p384 = aliases.secp384r1;
|
|
aliases.p521 = aliases.secp521r1;
|
|
|
|
function ECDH(curve) {
|
|
this.curveType = aliases[curve];
|
|
if (!this.curveType ) {
|
|
this.curveType = {
|
|
name: curve
|
|
};
|
|
}
|
|
this.curve = new elliptic.ec(this.curveType.name);
|
|
this.keys = void 0;
|
|
}
|
|
|
|
ECDH.prototype.generateKeys = function (enc, format) {
|
|
this.keys = this.curve.genKeyPair();
|
|
return this.getPublicKey(enc, format);
|
|
};
|
|
|
|
ECDH.prototype.computeSecret = function (other, inenc, enc) {
|
|
inenc = inenc || 'utf8';
|
|
if (!Buffer.isBuffer(other)) {
|
|
other = new Buffer(other, inenc);
|
|
}
|
|
var otherPub = this.curve.keyFromPublic(other).getPublic();
|
|
var out = otherPub.mul(this.keys.getPrivate()).getX();
|
|
return formatReturnValue(out, enc, this.curveType.byteLength);
|
|
};
|
|
|
|
ECDH.prototype.getPublicKey = function (enc, format) {
|
|
var key = this.keys.getPublic(format === 'compressed', true);
|
|
if (format === 'hybrid') {
|
|
if (key[key.length - 1] % 2) {
|
|
key[0] = 7;
|
|
} else {
|
|
key [0] = 6;
|
|
}
|
|
}
|
|
return formatReturnValue(key, enc);
|
|
};
|
|
|
|
ECDH.prototype.getPrivateKey = function (enc) {
|
|
return formatReturnValue(this.keys.getPrivate(), enc);
|
|
};
|
|
|
|
ECDH.prototype.setPublicKey = function (pub, enc) {
|
|
enc = enc || 'utf8';
|
|
if (!Buffer.isBuffer(pub)) {
|
|
pub = new Buffer(pub, enc);
|
|
}
|
|
this.keys._importPublic(pub);
|
|
return this;
|
|
};
|
|
|
|
ECDH.prototype.setPrivateKey = function (priv, enc) {
|
|
enc = enc || 'utf8';
|
|
if (!Buffer.isBuffer(priv)) {
|
|
priv = new Buffer(priv, enc);
|
|
}
|
|
var _priv = new BN(priv);
|
|
_priv = _priv.toString(16);
|
|
this.keys._importPrivate(_priv);
|
|
return this;
|
|
};
|
|
|
|
function formatReturnValue(bn, enc, len) {
|
|
if (!Array.isArray(bn)) {
|
|
bn = bn.toArray();
|
|
}
|
|
var buf = new Buffer(bn);
|
|
if (len && buf.length < len) {
|
|
var zeros = new Buffer(len - buf.length);
|
|
zeros.fill(0);
|
|
buf = Buffer.concat([zeros, buf]);
|
|
}
|
|
if (!enc) {
|
|
return buf;
|
|
} else {
|
|
return buf.toString(enc);
|
|
}
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"bn.js":280,"buffer":47,"elliptic":285}],140:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict'
|
|
var inherits = require('inherits')
|
|
var md5 = require('./md5')
|
|
var RIPEMD160 = require('ripemd160')
|
|
var sha = require('sha.js')
|
|
|
|
var Base = require('cipher-base')
|
|
|
|
function HashNoConstructor (hash) {
|
|
Base.call(this, 'digest')
|
|
|
|
this._hash = hash
|
|
this.buffers = []
|
|
}
|
|
|
|
inherits(HashNoConstructor, Base)
|
|
|
|
HashNoConstructor.prototype._update = function (data) {
|
|
this.buffers.push(data)
|
|
}
|
|
|
|
HashNoConstructor.prototype._final = function () {
|
|
var buf = Buffer.concat(this.buffers)
|
|
var r = this._hash(buf)
|
|
this.buffers = null
|
|
|
|
return r
|
|
}
|
|
|
|
function Hash (hash) {
|
|
Base.call(this, 'digest')
|
|
|
|
this._hash = hash
|
|
}
|
|
|
|
inherits(Hash, Base)
|
|
|
|
Hash.prototype._update = function (data) {
|
|
this._hash.update(data)
|
|
}
|
|
|
|
Hash.prototype._final = function () {
|
|
return this._hash.digest()
|
|
}
|
|
|
|
module.exports = function createHash (alg) {
|
|
alg = alg.toLowerCase()
|
|
if (alg === 'md5') return new HashNoConstructor(md5)
|
|
if (alg === 'rmd160' || alg === 'ripemd160') return new Hash(new RIPEMD160())
|
|
|
|
return new Hash(sha(alg))
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./md5":142,"buffer":47,"cipher-base":143,"inherits":318,"ripemd160":145,"sha.js":148}],141:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict'
|
|
var intSize = 4
|
|
var zeroBuffer = new Buffer(intSize)
|
|
zeroBuffer.fill(0)
|
|
|
|
var charSize = 8
|
|
var hashSize = 16
|
|
|
|
function toArray (buf) {
|
|
if ((buf.length % intSize) !== 0) {
|
|
var len = buf.length + (intSize - (buf.length % intSize))
|
|
buf = Buffer.concat([buf, zeroBuffer], len)
|
|
}
|
|
|
|
var arr = new Array(buf.length >>> 2)
|
|
for (var i = 0, j = 0; i < buf.length; i += intSize, j++) {
|
|
arr[j] = buf.readInt32LE(i)
|
|
}
|
|
|
|
return arr
|
|
}
|
|
|
|
module.exports = function hash (buf, fn) {
|
|
var arr = fn(toArray(buf), buf.length * charSize)
|
|
buf = new Buffer(hashSize)
|
|
for (var i = 0; i < arr.length; i++) {
|
|
buf.writeInt32LE(arr[i], i << 2, true)
|
|
}
|
|
return buf
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"buffer":47}],142:[function(require,module,exports){
|
|
'use strict'
|
|
/*
|
|
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
|
* Digest Algorithm, as defined in RFC 1321.
|
|
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
* Distributed under the BSD License
|
|
* See http://pajhome.org.uk/crypt/md5 for more info.
|
|
*/
|
|
|
|
var makeHash = require('./make-hash')
|
|
|
|
/*
|
|
* Calculate the MD5 of an array of little-endian words, and a bit length
|
|
*/
|
|
function core_md5 (x, len) {
|
|
/* append padding */
|
|
x[len >> 5] |= 0x80 << ((len) % 32)
|
|
x[(((len + 64) >>> 9) << 4) + 14] = len
|
|
|
|
var a = 1732584193
|
|
var b = -271733879
|
|
var c = -1732584194
|
|
var d = 271733878
|
|
|
|
for (var i = 0; i < x.length; i += 16) {
|
|
var olda = a
|
|
var oldb = b
|
|
var oldc = c
|
|
var oldd = d
|
|
|
|
a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936)
|
|
d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586)
|
|
c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819)
|
|
b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330)
|
|
a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897)
|
|
d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426)
|
|
c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341)
|
|
b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983)
|
|
a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416)
|
|
d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417)
|
|
c = md5_ff(c, d, a, b, x[i + 10], 17, -42063)
|
|
b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162)
|
|
a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682)
|
|
d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101)
|
|
c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290)
|
|
b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329)
|
|
|
|
a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510)
|
|
d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632)
|
|
c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713)
|
|
b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302)
|
|
a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691)
|
|
d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083)
|
|
c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335)
|
|
b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848)
|
|
a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438)
|
|
d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690)
|
|
c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961)
|
|
b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501)
|
|
a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467)
|
|
d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784)
|
|
c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473)
|
|
b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734)
|
|
|
|
a = md5_hh(a, b, c, d, x[i + 5], 4, -378558)
|
|
d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463)
|
|
c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562)
|
|
b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556)
|
|
a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060)
|
|
d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353)
|
|
c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632)
|
|
b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640)
|
|
a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174)
|
|
d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222)
|
|
c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979)
|
|
b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189)
|
|
a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487)
|
|
d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835)
|
|
c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520)
|
|
b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651)
|
|
|
|
a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844)
|
|
d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415)
|
|
c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905)
|
|
b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055)
|
|
a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571)
|
|
d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606)
|
|
c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523)
|
|
b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799)
|
|
a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359)
|
|
d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744)
|
|
c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380)
|
|
b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649)
|
|
a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070)
|
|
d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379)
|
|
c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259)
|
|
b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551)
|
|
|
|
a = safe_add(a, olda)
|
|
b = safe_add(b, oldb)
|
|
c = safe_add(c, oldc)
|
|
d = safe_add(d, oldd)
|
|
}
|
|
|
|
return [a, b, c, d]
|
|
}
|
|
|
|
/*
|
|
* These functions implement the four basic operations the algorithm uses.
|
|
*/
|
|
function md5_cmn (q, a, b, x, s, t) {
|
|
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b)
|
|
}
|
|
|
|
function md5_ff (a, b, c, d, x, s, t) {
|
|
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t)
|
|
}
|
|
|
|
function md5_gg (a, b, c, d, x, s, t) {
|
|
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t)
|
|
}
|
|
|
|
function md5_hh (a, b, c, d, x, s, t) {
|
|
return md5_cmn(b ^ c ^ d, a, b, x, s, t)
|
|
}
|
|
|
|
function md5_ii (a, b, c, d, x, s, t) {
|
|
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t)
|
|
}
|
|
|
|
/*
|
|
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
|
* to work around bugs in some JS interpreters.
|
|
*/
|
|
function safe_add (x, y) {
|
|
var lsw = (x & 0xFFFF) + (y & 0xFFFF)
|
|
var msw = (x >> 16) + (y >> 16) + (lsw >> 16)
|
|
return (msw << 16) | (lsw & 0xFFFF)
|
|
}
|
|
|
|
/*
|
|
* Bitwise rotate a 32-bit number to the left.
|
|
*/
|
|
function bit_rol (num, cnt) {
|
|
return (num << cnt) | (num >>> (32 - cnt))
|
|
}
|
|
|
|
module.exports = function md5 (buf) {
|
|
return makeHash(buf, core_md5)
|
|
}
|
|
|
|
},{"./make-hash":141}],143:[function(require,module,exports){
|
|
arguments[4][70][0].apply(exports,arguments)
|
|
},{"dup":70,"inherits":318,"safe-buffer":144,"stream":272,"string_decoder":273}],144:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],145:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict'
|
|
var inherits = require('inherits')
|
|
var HashBase = require('hash-base')
|
|
|
|
function RIPEMD160 () {
|
|
HashBase.call(this, 64)
|
|
|
|
// state
|
|
this._a = 0x67452301
|
|
this._b = 0xefcdab89
|
|
this._c = 0x98badcfe
|
|
this._d = 0x10325476
|
|
this._e = 0xc3d2e1f0
|
|
}
|
|
|
|
inherits(RIPEMD160, HashBase)
|
|
|
|
RIPEMD160.prototype._update = function () {
|
|
var m = new Array(16)
|
|
for (var i = 0; i < 16; ++i) m[i] = this._block.readInt32LE(i * 4)
|
|
|
|
var al = this._a
|
|
var bl = this._b
|
|
var cl = this._c
|
|
var dl = this._d
|
|
var el = this._e
|
|
|
|
// Mj = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
|
// K = 0x00000000
|
|
// Sj = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8
|
|
al = fn1(al, bl, cl, dl, el, m[0], 0x00000000, 11); cl = rotl(cl, 10)
|
|
el = fn1(el, al, bl, cl, dl, m[1], 0x00000000, 14); bl = rotl(bl, 10)
|
|
dl = fn1(dl, el, al, bl, cl, m[2], 0x00000000, 15); al = rotl(al, 10)
|
|
cl = fn1(cl, dl, el, al, bl, m[3], 0x00000000, 12); el = rotl(el, 10)
|
|
bl = fn1(bl, cl, dl, el, al, m[4], 0x00000000, 5); dl = rotl(dl, 10)
|
|
al = fn1(al, bl, cl, dl, el, m[5], 0x00000000, 8); cl = rotl(cl, 10)
|
|
el = fn1(el, al, bl, cl, dl, m[6], 0x00000000, 7); bl = rotl(bl, 10)
|
|
dl = fn1(dl, el, al, bl, cl, m[7], 0x00000000, 9); al = rotl(al, 10)
|
|
cl = fn1(cl, dl, el, al, bl, m[8], 0x00000000, 11); el = rotl(el, 10)
|
|
bl = fn1(bl, cl, dl, el, al, m[9], 0x00000000, 13); dl = rotl(dl, 10)
|
|
al = fn1(al, bl, cl, dl, el, m[10], 0x00000000, 14); cl = rotl(cl, 10)
|
|
el = fn1(el, al, bl, cl, dl, m[11], 0x00000000, 15); bl = rotl(bl, 10)
|
|
dl = fn1(dl, el, al, bl, cl, m[12], 0x00000000, 6); al = rotl(al, 10)
|
|
cl = fn1(cl, dl, el, al, bl, m[13], 0x00000000, 7); el = rotl(el, 10)
|
|
bl = fn1(bl, cl, dl, el, al, m[14], 0x00000000, 9); dl = rotl(dl, 10)
|
|
al = fn1(al, bl, cl, dl, el, m[15], 0x00000000, 8); cl = rotl(cl, 10)
|
|
|
|
// Mj = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8
|
|
// K = 0x5a827999
|
|
// Sj = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12
|
|
el = fn2(el, al, bl, cl, dl, m[7], 0x5a827999, 7); bl = rotl(bl, 10)
|
|
dl = fn2(dl, el, al, bl, cl, m[4], 0x5a827999, 6); al = rotl(al, 10)
|
|
cl = fn2(cl, dl, el, al, bl, m[13], 0x5a827999, 8); el = rotl(el, 10)
|
|
bl = fn2(bl, cl, dl, el, al, m[1], 0x5a827999, 13); dl = rotl(dl, 10)
|
|
al = fn2(al, bl, cl, dl, el, m[10], 0x5a827999, 11); cl = rotl(cl, 10)
|
|
el = fn2(el, al, bl, cl, dl, m[6], 0x5a827999, 9); bl = rotl(bl, 10)
|
|
dl = fn2(dl, el, al, bl, cl, m[15], 0x5a827999, 7); al = rotl(al, 10)
|
|
cl = fn2(cl, dl, el, al, bl, m[3], 0x5a827999, 15); el = rotl(el, 10)
|
|
bl = fn2(bl, cl, dl, el, al, m[12], 0x5a827999, 7); dl = rotl(dl, 10)
|
|
al = fn2(al, bl, cl, dl, el, m[0], 0x5a827999, 12); cl = rotl(cl, 10)
|
|
el = fn2(el, al, bl, cl, dl, m[9], 0x5a827999, 15); bl = rotl(bl, 10)
|
|
dl = fn2(dl, el, al, bl, cl, m[5], 0x5a827999, 9); al = rotl(al, 10)
|
|
cl = fn2(cl, dl, el, al, bl, m[2], 0x5a827999, 11); el = rotl(el, 10)
|
|
bl = fn2(bl, cl, dl, el, al, m[14], 0x5a827999, 7); dl = rotl(dl, 10)
|
|
al = fn2(al, bl, cl, dl, el, m[11], 0x5a827999, 13); cl = rotl(cl, 10)
|
|
el = fn2(el, al, bl, cl, dl, m[8], 0x5a827999, 12); bl = rotl(bl, 10)
|
|
|
|
// Mj = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12
|
|
// K = 0x6ed9eba1
|
|
// Sj = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5
|
|
dl = fn3(dl, el, al, bl, cl, m[3], 0x6ed9eba1, 11); al = rotl(al, 10)
|
|
cl = fn3(cl, dl, el, al, bl, m[10], 0x6ed9eba1, 13); el = rotl(el, 10)
|
|
bl = fn3(bl, cl, dl, el, al, m[14], 0x6ed9eba1, 6); dl = rotl(dl, 10)
|
|
al = fn3(al, bl, cl, dl, el, m[4], 0x6ed9eba1, 7); cl = rotl(cl, 10)
|
|
el = fn3(el, al, bl, cl, dl, m[9], 0x6ed9eba1, 14); bl = rotl(bl, 10)
|
|
dl = fn3(dl, el, al, bl, cl, m[15], 0x6ed9eba1, 9); al = rotl(al, 10)
|
|
cl = fn3(cl, dl, el, al, bl, m[8], 0x6ed9eba1, 13); el = rotl(el, 10)
|
|
bl = fn3(bl, cl, dl, el, al, m[1], 0x6ed9eba1, 15); dl = rotl(dl, 10)
|
|
al = fn3(al, bl, cl, dl, el, m[2], 0x6ed9eba1, 14); cl = rotl(cl, 10)
|
|
el = fn3(el, al, bl, cl, dl, m[7], 0x6ed9eba1, 8); bl = rotl(bl, 10)
|
|
dl = fn3(dl, el, al, bl, cl, m[0], 0x6ed9eba1, 13); al = rotl(al, 10)
|
|
cl = fn3(cl, dl, el, al, bl, m[6], 0x6ed9eba1, 6); el = rotl(el, 10)
|
|
bl = fn3(bl, cl, dl, el, al, m[13], 0x6ed9eba1, 5); dl = rotl(dl, 10)
|
|
al = fn3(al, bl, cl, dl, el, m[11], 0x6ed9eba1, 12); cl = rotl(cl, 10)
|
|
el = fn3(el, al, bl, cl, dl, m[5], 0x6ed9eba1, 7); bl = rotl(bl, 10)
|
|
dl = fn3(dl, el, al, bl, cl, m[12], 0x6ed9eba1, 5); al = rotl(al, 10)
|
|
|
|
// Mj = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2
|
|
// K = 0x8f1bbcdc
|
|
// Sj = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12
|
|
cl = fn4(cl, dl, el, al, bl, m[1], 0x8f1bbcdc, 11); el = rotl(el, 10)
|
|
bl = fn4(bl, cl, dl, el, al, m[9], 0x8f1bbcdc, 12); dl = rotl(dl, 10)
|
|
al = fn4(al, bl, cl, dl, el, m[11], 0x8f1bbcdc, 14); cl = rotl(cl, 10)
|
|
el = fn4(el, al, bl, cl, dl, m[10], 0x8f1bbcdc, 15); bl = rotl(bl, 10)
|
|
dl = fn4(dl, el, al, bl, cl, m[0], 0x8f1bbcdc, 14); al = rotl(al, 10)
|
|
cl = fn4(cl, dl, el, al, bl, m[8], 0x8f1bbcdc, 15); el = rotl(el, 10)
|
|
bl = fn4(bl, cl, dl, el, al, m[12], 0x8f1bbcdc, 9); dl = rotl(dl, 10)
|
|
al = fn4(al, bl, cl, dl, el, m[4], 0x8f1bbcdc, 8); cl = rotl(cl, 10)
|
|
el = fn4(el, al, bl, cl, dl, m[13], 0x8f1bbcdc, 9); bl = rotl(bl, 10)
|
|
dl = fn4(dl, el, al, bl, cl, m[3], 0x8f1bbcdc, 14); al = rotl(al, 10)
|
|
cl = fn4(cl, dl, el, al, bl, m[7], 0x8f1bbcdc, 5); el = rotl(el, 10)
|
|
bl = fn4(bl, cl, dl, el, al, m[15], 0x8f1bbcdc, 6); dl = rotl(dl, 10)
|
|
al = fn4(al, bl, cl, dl, el, m[14], 0x8f1bbcdc, 8); cl = rotl(cl, 10)
|
|
el = fn4(el, al, bl, cl, dl, m[5], 0x8f1bbcdc, 6); bl = rotl(bl, 10)
|
|
dl = fn4(dl, el, al, bl, cl, m[6], 0x8f1bbcdc, 5); al = rotl(al, 10)
|
|
cl = fn4(cl, dl, el, al, bl, m[2], 0x8f1bbcdc, 12); el = rotl(el, 10)
|
|
|
|
// Mj = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
|
|
// K = 0xa953fd4e
|
|
// Sj = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
|
|
bl = fn5(bl, cl, dl, el, al, m[4], 0xa953fd4e, 9); dl = rotl(dl, 10)
|
|
al = fn5(al, bl, cl, dl, el, m[0], 0xa953fd4e, 15); cl = rotl(cl, 10)
|
|
el = fn5(el, al, bl, cl, dl, m[5], 0xa953fd4e, 5); bl = rotl(bl, 10)
|
|
dl = fn5(dl, el, al, bl, cl, m[9], 0xa953fd4e, 11); al = rotl(al, 10)
|
|
cl = fn5(cl, dl, el, al, bl, m[7], 0xa953fd4e, 6); el = rotl(el, 10)
|
|
bl = fn5(bl, cl, dl, el, al, m[12], 0xa953fd4e, 8); dl = rotl(dl, 10)
|
|
al = fn5(al, bl, cl, dl, el, m[2], 0xa953fd4e, 13); cl = rotl(cl, 10)
|
|
el = fn5(el, al, bl, cl, dl, m[10], 0xa953fd4e, 12); bl = rotl(bl, 10)
|
|
dl = fn5(dl, el, al, bl, cl, m[14], 0xa953fd4e, 5); al = rotl(al, 10)
|
|
cl = fn5(cl, dl, el, al, bl, m[1], 0xa953fd4e, 12); el = rotl(el, 10)
|
|
bl = fn5(bl, cl, dl, el, al, m[3], 0xa953fd4e, 13); dl = rotl(dl, 10)
|
|
al = fn5(al, bl, cl, dl, el, m[8], 0xa953fd4e, 14); cl = rotl(cl, 10)
|
|
el = fn5(el, al, bl, cl, dl, m[11], 0xa953fd4e, 11); bl = rotl(bl, 10)
|
|
dl = fn5(dl, el, al, bl, cl, m[6], 0xa953fd4e, 8); al = rotl(al, 10)
|
|
cl = fn5(cl, dl, el, al, bl, m[15], 0xa953fd4e, 5); el = rotl(el, 10)
|
|
bl = fn5(bl, cl, dl, el, al, m[13], 0xa953fd4e, 6); dl = rotl(dl, 10)
|
|
|
|
var ar = this._a
|
|
var br = this._b
|
|
var cr = this._c
|
|
var dr = this._d
|
|
var er = this._e
|
|
|
|
// M'j = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12
|
|
// K' = 0x50a28be6
|
|
// S'j = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6
|
|
ar = fn5(ar, br, cr, dr, er, m[5], 0x50a28be6, 8); cr = rotl(cr, 10)
|
|
er = fn5(er, ar, br, cr, dr, m[14], 0x50a28be6, 9); br = rotl(br, 10)
|
|
dr = fn5(dr, er, ar, br, cr, m[7], 0x50a28be6, 9); ar = rotl(ar, 10)
|
|
cr = fn5(cr, dr, er, ar, br, m[0], 0x50a28be6, 11); er = rotl(er, 10)
|
|
br = fn5(br, cr, dr, er, ar, m[9], 0x50a28be6, 13); dr = rotl(dr, 10)
|
|
ar = fn5(ar, br, cr, dr, er, m[2], 0x50a28be6, 15); cr = rotl(cr, 10)
|
|
er = fn5(er, ar, br, cr, dr, m[11], 0x50a28be6, 15); br = rotl(br, 10)
|
|
dr = fn5(dr, er, ar, br, cr, m[4], 0x50a28be6, 5); ar = rotl(ar, 10)
|
|
cr = fn5(cr, dr, er, ar, br, m[13], 0x50a28be6, 7); er = rotl(er, 10)
|
|
br = fn5(br, cr, dr, er, ar, m[6], 0x50a28be6, 7); dr = rotl(dr, 10)
|
|
ar = fn5(ar, br, cr, dr, er, m[15], 0x50a28be6, 8); cr = rotl(cr, 10)
|
|
er = fn5(er, ar, br, cr, dr, m[8], 0x50a28be6, 11); br = rotl(br, 10)
|
|
dr = fn5(dr, er, ar, br, cr, m[1], 0x50a28be6, 14); ar = rotl(ar, 10)
|
|
cr = fn5(cr, dr, er, ar, br, m[10], 0x50a28be6, 14); er = rotl(er, 10)
|
|
br = fn5(br, cr, dr, er, ar, m[3], 0x50a28be6, 12); dr = rotl(dr, 10)
|
|
ar = fn5(ar, br, cr, dr, er, m[12], 0x50a28be6, 6); cr = rotl(cr, 10)
|
|
|
|
// M'j = 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2
|
|
// K' = 0x5c4dd124
|
|
// S'j = 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11
|
|
er = fn4(er, ar, br, cr, dr, m[6], 0x5c4dd124, 9); br = rotl(br, 10)
|
|
dr = fn4(dr, er, ar, br, cr, m[11], 0x5c4dd124, 13); ar = rotl(ar, 10)
|
|
cr = fn4(cr, dr, er, ar, br, m[3], 0x5c4dd124, 15); er = rotl(er, 10)
|
|
br = fn4(br, cr, dr, er, ar, m[7], 0x5c4dd124, 7); dr = rotl(dr, 10)
|
|
ar = fn4(ar, br, cr, dr, er, m[0], 0x5c4dd124, 12); cr = rotl(cr, 10)
|
|
er = fn4(er, ar, br, cr, dr, m[13], 0x5c4dd124, 8); br = rotl(br, 10)
|
|
dr = fn4(dr, er, ar, br, cr, m[5], 0x5c4dd124, 9); ar = rotl(ar, 10)
|
|
cr = fn4(cr, dr, er, ar, br, m[10], 0x5c4dd124, 11); er = rotl(er, 10)
|
|
br = fn4(br, cr, dr, er, ar, m[14], 0x5c4dd124, 7); dr = rotl(dr, 10)
|
|
ar = fn4(ar, br, cr, dr, er, m[15], 0x5c4dd124, 7); cr = rotl(cr, 10)
|
|
er = fn4(er, ar, br, cr, dr, m[8], 0x5c4dd124, 12); br = rotl(br, 10)
|
|
dr = fn4(dr, er, ar, br, cr, m[12], 0x5c4dd124, 7); ar = rotl(ar, 10)
|
|
cr = fn4(cr, dr, er, ar, br, m[4], 0x5c4dd124, 6); er = rotl(er, 10)
|
|
br = fn4(br, cr, dr, er, ar, m[9], 0x5c4dd124, 15); dr = rotl(dr, 10)
|
|
ar = fn4(ar, br, cr, dr, er, m[1], 0x5c4dd124, 13); cr = rotl(cr, 10)
|
|
er = fn4(er, ar, br, cr, dr, m[2], 0x5c4dd124, 11); br = rotl(br, 10)
|
|
|
|
// M'j = 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13
|
|
// K' = 0x6d703ef3
|
|
// S'j = 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5
|
|
dr = fn3(dr, er, ar, br, cr, m[15], 0x6d703ef3, 9); ar = rotl(ar, 10)
|
|
cr = fn3(cr, dr, er, ar, br, m[5], 0x6d703ef3, 7); er = rotl(er, 10)
|
|
br = fn3(br, cr, dr, er, ar, m[1], 0x6d703ef3, 15); dr = rotl(dr, 10)
|
|
ar = fn3(ar, br, cr, dr, er, m[3], 0x6d703ef3, 11); cr = rotl(cr, 10)
|
|
er = fn3(er, ar, br, cr, dr, m[7], 0x6d703ef3, 8); br = rotl(br, 10)
|
|
dr = fn3(dr, er, ar, br, cr, m[14], 0x6d703ef3, 6); ar = rotl(ar, 10)
|
|
cr = fn3(cr, dr, er, ar, br, m[6], 0x6d703ef3, 6); er = rotl(er, 10)
|
|
br = fn3(br, cr, dr, er, ar, m[9], 0x6d703ef3, 14); dr = rotl(dr, 10)
|
|
ar = fn3(ar, br, cr, dr, er, m[11], 0x6d703ef3, 12); cr = rotl(cr, 10)
|
|
er = fn3(er, ar, br, cr, dr, m[8], 0x6d703ef3, 13); br = rotl(br, 10)
|
|
dr = fn3(dr, er, ar, br, cr, m[12], 0x6d703ef3, 5); ar = rotl(ar, 10)
|
|
cr = fn3(cr, dr, er, ar, br, m[2], 0x6d703ef3, 14); er = rotl(er, 10)
|
|
br = fn3(br, cr, dr, er, ar, m[10], 0x6d703ef3, 13); dr = rotl(dr, 10)
|
|
ar = fn3(ar, br, cr, dr, er, m[0], 0x6d703ef3, 13); cr = rotl(cr, 10)
|
|
er = fn3(er, ar, br, cr, dr, m[4], 0x6d703ef3, 7); br = rotl(br, 10)
|
|
dr = fn3(dr, er, ar, br, cr, m[13], 0x6d703ef3, 5); ar = rotl(ar, 10)
|
|
|
|
// M'j = 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14
|
|
// K' = 0x7a6d76e9
|
|
// S'j = 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8
|
|
cr = fn2(cr, dr, er, ar, br, m[8], 0x7a6d76e9, 15); er = rotl(er, 10)
|
|
br = fn2(br, cr, dr, er, ar, m[6], 0x7a6d76e9, 5); dr = rotl(dr, 10)
|
|
ar = fn2(ar, br, cr, dr, er, m[4], 0x7a6d76e9, 8); cr = rotl(cr, 10)
|
|
er = fn2(er, ar, br, cr, dr, m[1], 0x7a6d76e9, 11); br = rotl(br, 10)
|
|
dr = fn2(dr, er, ar, br, cr, m[3], 0x7a6d76e9, 14); ar = rotl(ar, 10)
|
|
cr = fn2(cr, dr, er, ar, br, m[11], 0x7a6d76e9, 14); er = rotl(er, 10)
|
|
br = fn2(br, cr, dr, er, ar, m[15], 0x7a6d76e9, 6); dr = rotl(dr, 10)
|
|
ar = fn2(ar, br, cr, dr, er, m[0], 0x7a6d76e9, 14); cr = rotl(cr, 10)
|
|
er = fn2(er, ar, br, cr, dr, m[5], 0x7a6d76e9, 6); br = rotl(br, 10)
|
|
dr = fn2(dr, er, ar, br, cr, m[12], 0x7a6d76e9, 9); ar = rotl(ar, 10)
|
|
cr = fn2(cr, dr, er, ar, br, m[2], 0x7a6d76e9, 12); er = rotl(er, 10)
|
|
br = fn2(br, cr, dr, er, ar, m[13], 0x7a6d76e9, 9); dr = rotl(dr, 10)
|
|
ar = fn2(ar, br, cr, dr, er, m[9], 0x7a6d76e9, 12); cr = rotl(cr, 10)
|
|
er = fn2(er, ar, br, cr, dr, m[7], 0x7a6d76e9, 5); br = rotl(br, 10)
|
|
dr = fn2(dr, er, ar, br, cr, m[10], 0x7a6d76e9, 15); ar = rotl(ar, 10)
|
|
cr = fn2(cr, dr, er, ar, br, m[14], 0x7a6d76e9, 8); er = rotl(er, 10)
|
|
|
|
// M'j = 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
|
|
// K' = 0x00000000
|
|
// S'j = 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
|
|
br = fn1(br, cr, dr, er, ar, m[12], 0x00000000, 8); dr = rotl(dr, 10)
|
|
ar = fn1(ar, br, cr, dr, er, m[15], 0x00000000, 5); cr = rotl(cr, 10)
|
|
er = fn1(er, ar, br, cr, dr, m[10], 0x00000000, 12); br = rotl(br, 10)
|
|
dr = fn1(dr, er, ar, br, cr, m[4], 0x00000000, 9); ar = rotl(ar, 10)
|
|
cr = fn1(cr, dr, er, ar, br, m[1], 0x00000000, 12); er = rotl(er, 10)
|
|
br = fn1(br, cr, dr, er, ar, m[5], 0x00000000, 5); dr = rotl(dr, 10)
|
|
ar = fn1(ar, br, cr, dr, er, m[8], 0x00000000, 14); cr = rotl(cr, 10)
|
|
er = fn1(er, ar, br, cr, dr, m[7], 0x00000000, 6); br = rotl(br, 10)
|
|
dr = fn1(dr, er, ar, br, cr, m[6], 0x00000000, 8); ar = rotl(ar, 10)
|
|
cr = fn1(cr, dr, er, ar, br, m[2], 0x00000000, 13); er = rotl(er, 10)
|
|
br = fn1(br, cr, dr, er, ar, m[13], 0x00000000, 6); dr = rotl(dr, 10)
|
|
ar = fn1(ar, br, cr, dr, er, m[14], 0x00000000, 5); cr = rotl(cr, 10)
|
|
er = fn1(er, ar, br, cr, dr, m[0], 0x00000000, 15); br = rotl(br, 10)
|
|
dr = fn1(dr, er, ar, br, cr, m[3], 0x00000000, 13); ar = rotl(ar, 10)
|
|
cr = fn1(cr, dr, er, ar, br, m[9], 0x00000000, 11); er = rotl(er, 10)
|
|
br = fn1(br, cr, dr, er, ar, m[11], 0x00000000, 11); dr = rotl(dr, 10)
|
|
|
|
// change state
|
|
var t = (this._b + cl + dr) | 0
|
|
this._b = (this._c + dl + er) | 0
|
|
this._c = (this._d + el + ar) | 0
|
|
this._d = (this._e + al + br) | 0
|
|
this._e = (this._a + bl + cr) | 0
|
|
this._a = t
|
|
}
|
|
|
|
RIPEMD160.prototype._digest = function () {
|
|
// create padding and handle blocks
|
|
this._block[this._blockOffset++] = 0x80
|
|
if (this._blockOffset > 56) {
|
|
this._block.fill(0, this._blockOffset, 64)
|
|
this._update()
|
|
this._blockOffset = 0
|
|
}
|
|
|
|
this._block.fill(0, this._blockOffset, 56)
|
|
this._block.writeUInt32LE(this._length[0], 56)
|
|
this._block.writeUInt32LE(this._length[1], 60)
|
|
this._update()
|
|
|
|
// produce result
|
|
var buffer = new Buffer(20)
|
|
buffer.writeInt32LE(this._a, 0)
|
|
buffer.writeInt32LE(this._b, 4)
|
|
buffer.writeInt32LE(this._c, 8)
|
|
buffer.writeInt32LE(this._d, 12)
|
|
buffer.writeInt32LE(this._e, 16)
|
|
return buffer
|
|
}
|
|
|
|
function rotl (x, n) {
|
|
return (x << n) | (x >>> (32 - n))
|
|
}
|
|
|
|
function fn1 (a, b, c, d, e, m, k, s) {
|
|
return (rotl((a + (b ^ c ^ d) + m + k) | 0, s) + e) | 0
|
|
}
|
|
|
|
function fn2 (a, b, c, d, e, m, k, s) {
|
|
return (rotl((a + ((b & c) | ((~b) & d)) + m + k) | 0, s) + e) | 0
|
|
}
|
|
|
|
function fn3 (a, b, c, d, e, m, k, s) {
|
|
return (rotl((a + ((b | (~c)) ^ d) + m + k) | 0, s) + e) | 0
|
|
}
|
|
|
|
function fn4 (a, b, c, d, e, m, k, s) {
|
|
return (rotl((a + ((b & d) | (c & (~d))) + m + k) | 0, s) + e) | 0
|
|
}
|
|
|
|
function fn5 (a, b, c, d, e, m, k, s) {
|
|
return (rotl((a + (b ^ (c | (~d))) + m + k) | 0, s) + e) | 0
|
|
}
|
|
|
|
module.exports = RIPEMD160
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"buffer":47,"hash-base":146,"inherits":318}],146:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict'
|
|
var Transform = require('stream').Transform
|
|
var inherits = require('inherits')
|
|
|
|
function HashBase (blockSize) {
|
|
Transform.call(this)
|
|
|
|
this._block = new Buffer(blockSize)
|
|
this._blockSize = blockSize
|
|
this._blockOffset = 0
|
|
this._length = [0, 0, 0, 0]
|
|
|
|
this._finalized = false
|
|
}
|
|
|
|
inherits(HashBase, Transform)
|
|
|
|
HashBase.prototype._transform = function (chunk, encoding, callback) {
|
|
var error = null
|
|
try {
|
|
if (encoding !== 'buffer') chunk = new Buffer(chunk, encoding)
|
|
this.update(chunk)
|
|
} catch (err) {
|
|
error = err
|
|
}
|
|
|
|
callback(error)
|
|
}
|
|
|
|
HashBase.prototype._flush = function (callback) {
|
|
var error = null
|
|
try {
|
|
this.push(this._digest())
|
|
} catch (err) {
|
|
error = err
|
|
}
|
|
|
|
callback(error)
|
|
}
|
|
|
|
HashBase.prototype.update = function (data, encoding) {
|
|
if (!Buffer.isBuffer(data) && typeof data !== 'string') throw new TypeError('Data must be a string or a buffer')
|
|
if (this._finalized) throw new Error('Digest already called')
|
|
if (!Buffer.isBuffer(data)) data = new Buffer(data, encoding || 'binary')
|
|
|
|
// consume data
|
|
var block = this._block
|
|
var offset = 0
|
|
while (this._blockOffset + data.length - offset >= this._blockSize) {
|
|
for (var i = this._blockOffset; i < this._blockSize;) block[i++] = data[offset++]
|
|
this._update()
|
|
this._blockOffset = 0
|
|
}
|
|
while (offset < data.length) block[this._blockOffset++] = data[offset++]
|
|
|
|
// update length
|
|
for (var j = 0, carry = data.length * 8; carry > 0; ++j) {
|
|
this._length[j] += carry
|
|
carry = (this._length[j] / 0x0100000000) | 0
|
|
if (carry > 0) this._length[j] -= 0x0100000000 * carry
|
|
}
|
|
|
|
return this
|
|
}
|
|
|
|
HashBase.prototype._update = function (data) {
|
|
throw new Error('_update is not implemented')
|
|
}
|
|
|
|
HashBase.prototype.digest = function (encoding) {
|
|
if (this._finalized) throw new Error('Digest already called')
|
|
this._finalized = true
|
|
|
|
var digest = this._digest()
|
|
if (encoding !== undefined) digest = digest.toString(encoding)
|
|
return digest
|
|
}
|
|
|
|
HashBase.prototype._digest = function () {
|
|
throw new Error('_digest is not implemented')
|
|
}
|
|
|
|
module.exports = HashBase
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"buffer":47,"inherits":318,"stream":272}],147:[function(require,module,exports){
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
// prototype class for hash functions
|
|
function Hash (blockSize, finalSize) {
|
|
this._block = Buffer.alloc(blockSize)
|
|
this._finalSize = finalSize
|
|
this._blockSize = blockSize
|
|
this._len = 0
|
|
}
|
|
|
|
Hash.prototype.update = function (data, enc) {
|
|
if (typeof data === 'string') {
|
|
enc = enc || 'utf8'
|
|
data = Buffer.from(data, enc)
|
|
}
|
|
|
|
var block = this._block
|
|
var blockSize = this._blockSize
|
|
var length = data.length
|
|
var accum = this._len
|
|
|
|
for (var offset = 0; offset < length;) {
|
|
var assigned = accum % blockSize
|
|
var remainder = Math.min(length - offset, blockSize - assigned)
|
|
|
|
for (var i = 0; i < remainder; i++) {
|
|
block[assigned + i] = data[offset + i]
|
|
}
|
|
|
|
accum += remainder
|
|
offset += remainder
|
|
|
|
if ((accum % blockSize) === 0) {
|
|
this._update(block)
|
|
}
|
|
}
|
|
|
|
this._len += length
|
|
return this
|
|
}
|
|
|
|
Hash.prototype.digest = function (enc) {
|
|
var rem = this._len % this._blockSize
|
|
|
|
this._block[rem] = 0x80
|
|
|
|
// zero (rem + 1) trailing bits, where (rem + 1) is the smallest
|
|
// non-negative solution to the equation (length + 1 + (rem + 1)) === finalSize mod blockSize
|
|
this._block.fill(0, rem + 1)
|
|
|
|
if (rem >= this._finalSize) {
|
|
this._update(this._block)
|
|
this._block.fill(0)
|
|
}
|
|
|
|
var bits = this._len * 8
|
|
|
|
// uint32
|
|
if (bits <= 0xffffffff) {
|
|
this._block.writeUInt32BE(bits, this._blockSize - 4)
|
|
|
|
// uint64
|
|
} else {
|
|
var lowBits = bits & 0xffffffff
|
|
var highBits = (bits - lowBits) / 0x100000000
|
|
|
|
this._block.writeUInt32BE(highBits, this._blockSize - 8)
|
|
this._block.writeUInt32BE(lowBits, this._blockSize - 4)
|
|
}
|
|
|
|
this._update(this._block)
|
|
var hash = this._hash()
|
|
|
|
return enc ? hash.toString(enc) : hash
|
|
}
|
|
|
|
Hash.prototype._update = function () {
|
|
throw new Error('_update must be implemented by subclass')
|
|
}
|
|
|
|
module.exports = Hash
|
|
|
|
},{"safe-buffer":149}],148:[function(require,module,exports){
|
|
var exports = module.exports = function SHA (algorithm) {
|
|
algorithm = algorithm.toLowerCase()
|
|
|
|
var Algorithm = exports[algorithm]
|
|
if (!Algorithm) throw new Error(algorithm + ' is not supported (we accept pull requests)')
|
|
|
|
return new Algorithm()
|
|
}
|
|
|
|
exports.sha = require('./sha')
|
|
exports.sha1 = require('./sha1')
|
|
exports.sha224 = require('./sha224')
|
|
exports.sha256 = require('./sha256')
|
|
exports.sha384 = require('./sha384')
|
|
exports.sha512 = require('./sha512')
|
|
|
|
},{"./sha":150,"./sha1":151,"./sha224":152,"./sha256":153,"./sha384":154,"./sha512":155}],149:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],150:[function(require,module,exports){
|
|
/*
|
|
* A JavaScript implementation of the Secure Hash Algorithm, SHA-0, as defined
|
|
* in FIPS PUB 180-1
|
|
* This source code is derived from sha1.js of the same repository.
|
|
* The difference between SHA-0 and SHA-1 is just a bitwise rotate left
|
|
* operation was added.
|
|
*/
|
|
|
|
var inherits = require('inherits')
|
|
var Hash = require('./hash')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
var K = [
|
|
0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0
|
|
]
|
|
|
|
var W = new Array(80)
|
|
|
|
function Sha () {
|
|
this.init()
|
|
this._w = W
|
|
|
|
Hash.call(this, 64, 56)
|
|
}
|
|
|
|
inherits(Sha, Hash)
|
|
|
|
Sha.prototype.init = function () {
|
|
this._a = 0x67452301
|
|
this._b = 0xefcdab89
|
|
this._c = 0x98badcfe
|
|
this._d = 0x10325476
|
|
this._e = 0xc3d2e1f0
|
|
|
|
return this
|
|
}
|
|
|
|
function rotl5 (num) {
|
|
return (num << 5) | (num >>> 27)
|
|
}
|
|
|
|
function rotl30 (num) {
|
|
return (num << 30) | (num >>> 2)
|
|
}
|
|
|
|
function ft (s, b, c, d) {
|
|
if (s === 0) return (b & c) | ((~b) & d)
|
|
if (s === 2) return (b & c) | (b & d) | (c & d)
|
|
return b ^ c ^ d
|
|
}
|
|
|
|
Sha.prototype._update = function (M) {
|
|
var W = this._w
|
|
|
|
var a = this._a | 0
|
|
var b = this._b | 0
|
|
var c = this._c | 0
|
|
var d = this._d | 0
|
|
var e = this._e | 0
|
|
|
|
for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4)
|
|
for (; i < 80; ++i) W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]
|
|
|
|
for (var j = 0; j < 80; ++j) {
|
|
var s = ~~(j / 20)
|
|
var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0
|
|
|
|
e = d
|
|
d = c
|
|
c = rotl30(b)
|
|
b = a
|
|
a = t
|
|
}
|
|
|
|
this._a = (a + this._a) | 0
|
|
this._b = (b + this._b) | 0
|
|
this._c = (c + this._c) | 0
|
|
this._d = (d + this._d) | 0
|
|
this._e = (e + this._e) | 0
|
|
}
|
|
|
|
Sha.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(20)
|
|
|
|
H.writeInt32BE(this._a | 0, 0)
|
|
H.writeInt32BE(this._b | 0, 4)
|
|
H.writeInt32BE(this._c | 0, 8)
|
|
H.writeInt32BE(this._d | 0, 12)
|
|
H.writeInt32BE(this._e | 0, 16)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha
|
|
|
|
},{"./hash":147,"inherits":318,"safe-buffer":149}],151:[function(require,module,exports){
|
|
/*
|
|
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
|
|
* in FIPS PUB 180-1
|
|
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
* Distributed under the BSD License
|
|
* See http://pajhome.org.uk/crypt/md5 for details.
|
|
*/
|
|
|
|
var inherits = require('inherits')
|
|
var Hash = require('./hash')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
var K = [
|
|
0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0
|
|
]
|
|
|
|
var W = new Array(80)
|
|
|
|
function Sha1 () {
|
|
this.init()
|
|
this._w = W
|
|
|
|
Hash.call(this, 64, 56)
|
|
}
|
|
|
|
inherits(Sha1, Hash)
|
|
|
|
Sha1.prototype.init = function () {
|
|
this._a = 0x67452301
|
|
this._b = 0xefcdab89
|
|
this._c = 0x98badcfe
|
|
this._d = 0x10325476
|
|
this._e = 0xc3d2e1f0
|
|
|
|
return this
|
|
}
|
|
|
|
function rotl1 (num) {
|
|
return (num << 1) | (num >>> 31)
|
|
}
|
|
|
|
function rotl5 (num) {
|
|
return (num << 5) | (num >>> 27)
|
|
}
|
|
|
|
function rotl30 (num) {
|
|
return (num << 30) | (num >>> 2)
|
|
}
|
|
|
|
function ft (s, b, c, d) {
|
|
if (s === 0) return (b & c) | ((~b) & d)
|
|
if (s === 2) return (b & c) | (b & d) | (c & d)
|
|
return b ^ c ^ d
|
|
}
|
|
|
|
Sha1.prototype._update = function (M) {
|
|
var W = this._w
|
|
|
|
var a = this._a | 0
|
|
var b = this._b | 0
|
|
var c = this._c | 0
|
|
var d = this._d | 0
|
|
var e = this._e | 0
|
|
|
|
for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4)
|
|
for (; i < 80; ++i) W[i] = rotl1(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16])
|
|
|
|
for (var j = 0; j < 80; ++j) {
|
|
var s = ~~(j / 20)
|
|
var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0
|
|
|
|
e = d
|
|
d = c
|
|
c = rotl30(b)
|
|
b = a
|
|
a = t
|
|
}
|
|
|
|
this._a = (a + this._a) | 0
|
|
this._b = (b + this._b) | 0
|
|
this._c = (c + this._c) | 0
|
|
this._d = (d + this._d) | 0
|
|
this._e = (e + this._e) | 0
|
|
}
|
|
|
|
Sha1.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(20)
|
|
|
|
H.writeInt32BE(this._a | 0, 0)
|
|
H.writeInt32BE(this._b | 0, 4)
|
|
H.writeInt32BE(this._c | 0, 8)
|
|
H.writeInt32BE(this._d | 0, 12)
|
|
H.writeInt32BE(this._e | 0, 16)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha1
|
|
|
|
},{"./hash":147,"inherits":318,"safe-buffer":149}],152:[function(require,module,exports){
|
|
/**
|
|
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
|
|
* in FIPS 180-2
|
|
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
*
|
|
*/
|
|
|
|
var inherits = require('inherits')
|
|
var Sha256 = require('./sha256')
|
|
var Hash = require('./hash')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
var W = new Array(64)
|
|
|
|
function Sha224 () {
|
|
this.init()
|
|
|
|
this._w = W // new Array(64)
|
|
|
|
Hash.call(this, 64, 56)
|
|
}
|
|
|
|
inherits(Sha224, Sha256)
|
|
|
|
Sha224.prototype.init = function () {
|
|
this._a = 0xc1059ed8
|
|
this._b = 0x367cd507
|
|
this._c = 0x3070dd17
|
|
this._d = 0xf70e5939
|
|
this._e = 0xffc00b31
|
|
this._f = 0x68581511
|
|
this._g = 0x64f98fa7
|
|
this._h = 0xbefa4fa4
|
|
|
|
return this
|
|
}
|
|
|
|
Sha224.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(28)
|
|
|
|
H.writeInt32BE(this._a, 0)
|
|
H.writeInt32BE(this._b, 4)
|
|
H.writeInt32BE(this._c, 8)
|
|
H.writeInt32BE(this._d, 12)
|
|
H.writeInt32BE(this._e, 16)
|
|
H.writeInt32BE(this._f, 20)
|
|
H.writeInt32BE(this._g, 24)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha224
|
|
|
|
},{"./hash":147,"./sha256":153,"inherits":318,"safe-buffer":149}],153:[function(require,module,exports){
|
|
/**
|
|
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
|
|
* in FIPS 180-2
|
|
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
*
|
|
*/
|
|
|
|
var inherits = require('inherits')
|
|
var Hash = require('./hash')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
var K = [
|
|
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
|
|
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
|
|
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
|
|
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
|
|
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
|
|
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
|
|
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
|
|
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
|
|
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
|
|
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
|
|
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
|
|
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
|
|
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
|
|
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
|
|
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
|
|
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
|
|
]
|
|
|
|
var W = new Array(64)
|
|
|
|
function Sha256 () {
|
|
this.init()
|
|
|
|
this._w = W // new Array(64)
|
|
|
|
Hash.call(this, 64, 56)
|
|
}
|
|
|
|
inherits(Sha256, Hash)
|
|
|
|
Sha256.prototype.init = function () {
|
|
this._a = 0x6a09e667
|
|
this._b = 0xbb67ae85
|
|
this._c = 0x3c6ef372
|
|
this._d = 0xa54ff53a
|
|
this._e = 0x510e527f
|
|
this._f = 0x9b05688c
|
|
this._g = 0x1f83d9ab
|
|
this._h = 0x5be0cd19
|
|
|
|
return this
|
|
}
|
|
|
|
function ch (x, y, z) {
|
|
return z ^ (x & (y ^ z))
|
|
}
|
|
|
|
function maj (x, y, z) {
|
|
return (x & y) | (z & (x | y))
|
|
}
|
|
|
|
function sigma0 (x) {
|
|
return (x >>> 2 | x << 30) ^ (x >>> 13 | x << 19) ^ (x >>> 22 | x << 10)
|
|
}
|
|
|
|
function sigma1 (x) {
|
|
return (x >>> 6 | x << 26) ^ (x >>> 11 | x << 21) ^ (x >>> 25 | x << 7)
|
|
}
|
|
|
|
function gamma0 (x) {
|
|
return (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ (x >>> 3)
|
|
}
|
|
|
|
function gamma1 (x) {
|
|
return (x >>> 17 | x << 15) ^ (x >>> 19 | x << 13) ^ (x >>> 10)
|
|
}
|
|
|
|
Sha256.prototype._update = function (M) {
|
|
var W = this._w
|
|
|
|
var a = this._a | 0
|
|
var b = this._b | 0
|
|
var c = this._c | 0
|
|
var d = this._d | 0
|
|
var e = this._e | 0
|
|
var f = this._f | 0
|
|
var g = this._g | 0
|
|
var h = this._h | 0
|
|
|
|
for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4)
|
|
for (; i < 64; ++i) W[i] = (gamma1(W[i - 2]) + W[i - 7] + gamma0(W[i - 15]) + W[i - 16]) | 0
|
|
|
|
for (var j = 0; j < 64; ++j) {
|
|
var T1 = (h + sigma1(e) + ch(e, f, g) + K[j] + W[j]) | 0
|
|
var T2 = (sigma0(a) + maj(a, b, c)) | 0
|
|
|
|
h = g
|
|
g = f
|
|
f = e
|
|
e = (d + T1) | 0
|
|
d = c
|
|
c = b
|
|
b = a
|
|
a = (T1 + T2) | 0
|
|
}
|
|
|
|
this._a = (a + this._a) | 0
|
|
this._b = (b + this._b) | 0
|
|
this._c = (c + this._c) | 0
|
|
this._d = (d + this._d) | 0
|
|
this._e = (e + this._e) | 0
|
|
this._f = (f + this._f) | 0
|
|
this._g = (g + this._g) | 0
|
|
this._h = (h + this._h) | 0
|
|
}
|
|
|
|
Sha256.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(32)
|
|
|
|
H.writeInt32BE(this._a, 0)
|
|
H.writeInt32BE(this._b, 4)
|
|
H.writeInt32BE(this._c, 8)
|
|
H.writeInt32BE(this._d, 12)
|
|
H.writeInt32BE(this._e, 16)
|
|
H.writeInt32BE(this._f, 20)
|
|
H.writeInt32BE(this._g, 24)
|
|
H.writeInt32BE(this._h, 28)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha256
|
|
|
|
},{"./hash":147,"inherits":318,"safe-buffer":149}],154:[function(require,module,exports){
|
|
var inherits = require('inherits')
|
|
var SHA512 = require('./sha512')
|
|
var Hash = require('./hash')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
var W = new Array(160)
|
|
|
|
function Sha384 () {
|
|
this.init()
|
|
this._w = W
|
|
|
|
Hash.call(this, 128, 112)
|
|
}
|
|
|
|
inherits(Sha384, SHA512)
|
|
|
|
Sha384.prototype.init = function () {
|
|
this._ah = 0xcbbb9d5d
|
|
this._bh = 0x629a292a
|
|
this._ch = 0x9159015a
|
|
this._dh = 0x152fecd8
|
|
this._eh = 0x67332667
|
|
this._fh = 0x8eb44a87
|
|
this._gh = 0xdb0c2e0d
|
|
this._hh = 0x47b5481d
|
|
|
|
this._al = 0xc1059ed8
|
|
this._bl = 0x367cd507
|
|
this._cl = 0x3070dd17
|
|
this._dl = 0xf70e5939
|
|
this._el = 0xffc00b31
|
|
this._fl = 0x68581511
|
|
this._gl = 0x64f98fa7
|
|
this._hl = 0xbefa4fa4
|
|
|
|
return this
|
|
}
|
|
|
|
Sha384.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(48)
|
|
|
|
function writeInt64BE (h, l, offset) {
|
|
H.writeInt32BE(h, offset)
|
|
H.writeInt32BE(l, offset + 4)
|
|
}
|
|
|
|
writeInt64BE(this._ah, this._al, 0)
|
|
writeInt64BE(this._bh, this._bl, 8)
|
|
writeInt64BE(this._ch, this._cl, 16)
|
|
writeInt64BE(this._dh, this._dl, 24)
|
|
writeInt64BE(this._eh, this._el, 32)
|
|
writeInt64BE(this._fh, this._fl, 40)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha384
|
|
|
|
},{"./hash":147,"./sha512":155,"inherits":318,"safe-buffer":149}],155:[function(require,module,exports){
|
|
var inherits = require('inherits')
|
|
var Hash = require('./hash')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
var K = [
|
|
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
|
|
0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
|
|
0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
|
|
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
|
|
0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
|
|
0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
|
|
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
|
|
0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
|
|
0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
|
|
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
|
|
0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
|
|
0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
|
|
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
|
|
0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
|
|
0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
|
|
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
|
|
0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
|
|
0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
|
|
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
|
|
0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
|
|
0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
|
|
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
|
|
0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
|
|
0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
|
|
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
|
|
0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
|
|
0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
|
|
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
|
|
0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
|
|
0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
|
|
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
|
|
0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
|
|
0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
|
|
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
|
|
0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
|
|
0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
|
|
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
|
|
0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
|
|
0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
|
|
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
|
|
]
|
|
|
|
var W = new Array(160)
|
|
|
|
function Sha512 () {
|
|
this.init()
|
|
this._w = W
|
|
|
|
Hash.call(this, 128, 112)
|
|
}
|
|
|
|
inherits(Sha512, Hash)
|
|
|
|
Sha512.prototype.init = function () {
|
|
this._ah = 0x6a09e667
|
|
this._bh = 0xbb67ae85
|
|
this._ch = 0x3c6ef372
|
|
this._dh = 0xa54ff53a
|
|
this._eh = 0x510e527f
|
|
this._fh = 0x9b05688c
|
|
this._gh = 0x1f83d9ab
|
|
this._hh = 0x5be0cd19
|
|
|
|
this._al = 0xf3bcc908
|
|
this._bl = 0x84caa73b
|
|
this._cl = 0xfe94f82b
|
|
this._dl = 0x5f1d36f1
|
|
this._el = 0xade682d1
|
|
this._fl = 0x2b3e6c1f
|
|
this._gl = 0xfb41bd6b
|
|
this._hl = 0x137e2179
|
|
|
|
return this
|
|
}
|
|
|
|
function Ch (x, y, z) {
|
|
return z ^ (x & (y ^ z))
|
|
}
|
|
|
|
function maj (x, y, z) {
|
|
return (x & y) | (z & (x | y))
|
|
}
|
|
|
|
function sigma0 (x, xl) {
|
|
return (x >>> 28 | xl << 4) ^ (xl >>> 2 | x << 30) ^ (xl >>> 7 | x << 25)
|
|
}
|
|
|
|
function sigma1 (x, xl) {
|
|
return (x >>> 14 | xl << 18) ^ (x >>> 18 | xl << 14) ^ (xl >>> 9 | x << 23)
|
|
}
|
|
|
|
function Gamma0 (x, xl) {
|
|
return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7)
|
|
}
|
|
|
|
function Gamma0l (x, xl) {
|
|
return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7 | xl << 25)
|
|
}
|
|
|
|
function Gamma1 (x, xl) {
|
|
return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6)
|
|
}
|
|
|
|
function Gamma1l (x, xl) {
|
|
return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6 | xl << 26)
|
|
}
|
|
|
|
function getCarry (a, b) {
|
|
return (a >>> 0) < (b >>> 0) ? 1 : 0
|
|
}
|
|
|
|
Sha512.prototype._update = function (M) {
|
|
var W = this._w
|
|
|
|
var ah = this._ah | 0
|
|
var bh = this._bh | 0
|
|
var ch = this._ch | 0
|
|
var dh = this._dh | 0
|
|
var eh = this._eh | 0
|
|
var fh = this._fh | 0
|
|
var gh = this._gh | 0
|
|
var hh = this._hh | 0
|
|
|
|
var al = this._al | 0
|
|
var bl = this._bl | 0
|
|
var cl = this._cl | 0
|
|
var dl = this._dl | 0
|
|
var el = this._el | 0
|
|
var fl = this._fl | 0
|
|
var gl = this._gl | 0
|
|
var hl = this._hl | 0
|
|
|
|
for (var i = 0; i < 32; i += 2) {
|
|
W[i] = M.readInt32BE(i * 4)
|
|
W[i + 1] = M.readInt32BE(i * 4 + 4)
|
|
}
|
|
for (; i < 160; i += 2) {
|
|
var xh = W[i - 15 * 2]
|
|
var xl = W[i - 15 * 2 + 1]
|
|
var gamma0 = Gamma0(xh, xl)
|
|
var gamma0l = Gamma0l(xl, xh)
|
|
|
|
xh = W[i - 2 * 2]
|
|
xl = W[i - 2 * 2 + 1]
|
|
var gamma1 = Gamma1(xh, xl)
|
|
var gamma1l = Gamma1l(xl, xh)
|
|
|
|
// W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]
|
|
var Wi7h = W[i - 7 * 2]
|
|
var Wi7l = W[i - 7 * 2 + 1]
|
|
|
|
var Wi16h = W[i - 16 * 2]
|
|
var Wi16l = W[i - 16 * 2 + 1]
|
|
|
|
var Wil = (gamma0l + Wi7l) | 0
|
|
var Wih = (gamma0 + Wi7h + getCarry(Wil, gamma0l)) | 0
|
|
Wil = (Wil + gamma1l) | 0
|
|
Wih = (Wih + gamma1 + getCarry(Wil, gamma1l)) | 0
|
|
Wil = (Wil + Wi16l) | 0
|
|
Wih = (Wih + Wi16h + getCarry(Wil, Wi16l)) | 0
|
|
|
|
W[i] = Wih
|
|
W[i + 1] = Wil
|
|
}
|
|
|
|
for (var j = 0; j < 160; j += 2) {
|
|
Wih = W[j]
|
|
Wil = W[j + 1]
|
|
|
|
var majh = maj(ah, bh, ch)
|
|
var majl = maj(al, bl, cl)
|
|
|
|
var sigma0h = sigma0(ah, al)
|
|
var sigma0l = sigma0(al, ah)
|
|
var sigma1h = sigma1(eh, el)
|
|
var sigma1l = sigma1(el, eh)
|
|
|
|
// t1 = h + sigma1 + ch + K[j] + W[j]
|
|
var Kih = K[j]
|
|
var Kil = K[j + 1]
|
|
|
|
var chh = Ch(eh, fh, gh)
|
|
var chl = Ch(el, fl, gl)
|
|
|
|
var t1l = (hl + sigma1l) | 0
|
|
var t1h = (hh + sigma1h + getCarry(t1l, hl)) | 0
|
|
t1l = (t1l + chl) | 0
|
|
t1h = (t1h + chh + getCarry(t1l, chl)) | 0
|
|
t1l = (t1l + Kil) | 0
|
|
t1h = (t1h + Kih + getCarry(t1l, Kil)) | 0
|
|
t1l = (t1l + Wil) | 0
|
|
t1h = (t1h + Wih + getCarry(t1l, Wil)) | 0
|
|
|
|
// t2 = sigma0 + maj
|
|
var t2l = (sigma0l + majl) | 0
|
|
var t2h = (sigma0h + majh + getCarry(t2l, sigma0l)) | 0
|
|
|
|
hh = gh
|
|
hl = gl
|
|
gh = fh
|
|
gl = fl
|
|
fh = eh
|
|
fl = el
|
|
el = (dl + t1l) | 0
|
|
eh = (dh + t1h + getCarry(el, dl)) | 0
|
|
dh = ch
|
|
dl = cl
|
|
ch = bh
|
|
cl = bl
|
|
bh = ah
|
|
bl = al
|
|
al = (t1l + t2l) | 0
|
|
ah = (t1h + t2h + getCarry(al, t1l)) | 0
|
|
}
|
|
|
|
this._al = (this._al + al) | 0
|
|
this._bl = (this._bl + bl) | 0
|
|
this._cl = (this._cl + cl) | 0
|
|
this._dl = (this._dl + dl) | 0
|
|
this._el = (this._el + el) | 0
|
|
this._fl = (this._fl + fl) | 0
|
|
this._gl = (this._gl + gl) | 0
|
|
this._hl = (this._hl + hl) | 0
|
|
|
|
this._ah = (this._ah + ah + getCarry(this._al, al)) | 0
|
|
this._bh = (this._bh + bh + getCarry(this._bl, bl)) | 0
|
|
this._ch = (this._ch + ch + getCarry(this._cl, cl)) | 0
|
|
this._dh = (this._dh + dh + getCarry(this._dl, dl)) | 0
|
|
this._eh = (this._eh + eh + getCarry(this._el, el)) | 0
|
|
this._fh = (this._fh + fh + getCarry(this._fl, fl)) | 0
|
|
this._gh = (this._gh + gh + getCarry(this._gl, gl)) | 0
|
|
this._hh = (this._hh + hh + getCarry(this._hl, hl)) | 0
|
|
}
|
|
|
|
Sha512.prototype._hash = function () {
|
|
var H = Buffer.allocUnsafe(64)
|
|
|
|
function writeInt64BE (h, l, offset) {
|
|
H.writeInt32BE(h, offset)
|
|
H.writeInt32BE(l, offset + 4)
|
|
}
|
|
|
|
writeInt64BE(this._ah, this._al, 0)
|
|
writeInt64BE(this._bh, this._bl, 8)
|
|
writeInt64BE(this._ch, this._cl, 16)
|
|
writeInt64BE(this._dh, this._dl, 24)
|
|
writeInt64BE(this._eh, this._el, 32)
|
|
writeInt64BE(this._fh, this._fl, 40)
|
|
writeInt64BE(this._gh, this._gl, 48)
|
|
writeInt64BE(this._hh, this._hl, 56)
|
|
|
|
return H
|
|
}
|
|
|
|
module.exports = Sha512
|
|
|
|
},{"./hash":147,"inherits":318,"safe-buffer":149}],156:[function(require,module,exports){
|
|
'use strict'
|
|
var inherits = require('inherits')
|
|
var Legacy = require('./legacy')
|
|
var Base = require('cipher-base')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var md5 = require('create-hash/md5')
|
|
var RIPEMD160 = require('ripemd160')
|
|
|
|
var sha = require('sha.js')
|
|
|
|
var ZEROS = Buffer.alloc(128)
|
|
|
|
function Hmac (alg, key) {
|
|
Base.call(this, 'digest')
|
|
if (typeof key === 'string') {
|
|
key = Buffer.from(key)
|
|
}
|
|
|
|
var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64
|
|
|
|
this._alg = alg
|
|
this._key = key
|
|
if (key.length > blocksize) {
|
|
var hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg)
|
|
key = hash.update(key).digest()
|
|
} else if (key.length < blocksize) {
|
|
key = Buffer.concat([key, ZEROS], blocksize)
|
|
}
|
|
|
|
var ipad = this._ipad = Buffer.allocUnsafe(blocksize)
|
|
var opad = this._opad = Buffer.allocUnsafe(blocksize)
|
|
|
|
for (var i = 0; i < blocksize; i++) {
|
|
ipad[i] = key[i] ^ 0x36
|
|
opad[i] = key[i] ^ 0x5C
|
|
}
|
|
this._hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg)
|
|
this._hash.update(ipad)
|
|
}
|
|
|
|
inherits(Hmac, Base)
|
|
|
|
Hmac.prototype._update = function (data) {
|
|
this._hash.update(data)
|
|
}
|
|
|
|
Hmac.prototype._final = function () {
|
|
var h = this._hash.digest()
|
|
var hash = this._alg === 'rmd160' ? new RIPEMD160() : sha(this._alg)
|
|
return hash.update(this._opad).update(h).digest()
|
|
}
|
|
|
|
module.exports = function createHmac (alg, key) {
|
|
alg = alg.toLowerCase()
|
|
if (alg === 'rmd160' || alg === 'ripemd160') {
|
|
return new Hmac('rmd160', key)
|
|
}
|
|
if (alg === 'md5') {
|
|
return new Legacy(md5, key)
|
|
}
|
|
return new Hmac(alg, key)
|
|
}
|
|
|
|
},{"./legacy":157,"cipher-base":158,"create-hash/md5":142,"inherits":318,"ripemd160":159,"safe-buffer":161,"sha.js":163}],157:[function(require,module,exports){
|
|
'use strict'
|
|
var inherits = require('inherits')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
var Base = require('cipher-base')
|
|
|
|
var ZEROS = Buffer.alloc(128)
|
|
var blocksize = 64
|
|
|
|
function Hmac (alg, key) {
|
|
Base.call(this, 'digest')
|
|
if (typeof key === 'string') {
|
|
key = Buffer.from(key)
|
|
}
|
|
|
|
this._alg = alg
|
|
this._key = key
|
|
|
|
if (key.length > blocksize) {
|
|
key = alg(key)
|
|
} else if (key.length < blocksize) {
|
|
key = Buffer.concat([key, ZEROS], blocksize)
|
|
}
|
|
|
|
var ipad = this._ipad = Buffer.allocUnsafe(blocksize)
|
|
var opad = this._opad = Buffer.allocUnsafe(blocksize)
|
|
|
|
for (var i = 0; i < blocksize; i++) {
|
|
ipad[i] = key[i] ^ 0x36
|
|
opad[i] = key[i] ^ 0x5C
|
|
}
|
|
|
|
this._hash = [ipad]
|
|
}
|
|
|
|
inherits(Hmac, Base)
|
|
|
|
Hmac.prototype._update = function (data) {
|
|
this._hash.push(data)
|
|
}
|
|
|
|
Hmac.prototype._final = function () {
|
|
var h = this._alg(Buffer.concat(this._hash))
|
|
return this._alg(Buffer.concat([this._opad, h]))
|
|
}
|
|
module.exports = Hmac
|
|
|
|
},{"cipher-base":158,"inherits":318,"safe-buffer":161}],158:[function(require,module,exports){
|
|
arguments[4][70][0].apply(exports,arguments)
|
|
},{"dup":70,"inherits":318,"safe-buffer":161,"stream":272,"string_decoder":273}],159:[function(require,module,exports){
|
|
arguments[4][145][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":145,"hash-base":160,"inherits":318}],160:[function(require,module,exports){
|
|
arguments[4][146][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":146,"inherits":318,"stream":272}],161:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],162:[function(require,module,exports){
|
|
arguments[4][147][0].apply(exports,arguments)
|
|
},{"dup":147,"safe-buffer":161}],163:[function(require,module,exports){
|
|
arguments[4][148][0].apply(exports,arguments)
|
|
},{"./sha":164,"./sha1":165,"./sha224":166,"./sha256":167,"./sha384":168,"./sha512":169,"dup":148}],164:[function(require,module,exports){
|
|
arguments[4][150][0].apply(exports,arguments)
|
|
},{"./hash":162,"dup":150,"inherits":318,"safe-buffer":161}],165:[function(require,module,exports){
|
|
arguments[4][151][0].apply(exports,arguments)
|
|
},{"./hash":162,"dup":151,"inherits":318,"safe-buffer":161}],166:[function(require,module,exports){
|
|
arguments[4][152][0].apply(exports,arguments)
|
|
},{"./hash":162,"./sha256":167,"dup":152,"inherits":318,"safe-buffer":161}],167:[function(require,module,exports){
|
|
arguments[4][153][0].apply(exports,arguments)
|
|
},{"./hash":162,"dup":153,"inherits":318,"safe-buffer":161}],168:[function(require,module,exports){
|
|
arguments[4][154][0].apply(exports,arguments)
|
|
},{"./hash":162,"./sha512":169,"dup":154,"inherits":318,"safe-buffer":161}],169:[function(require,module,exports){
|
|
arguments[4][155][0].apply(exports,arguments)
|
|
},{"./hash":162,"dup":155,"inherits":318,"safe-buffer":161}],170:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var generatePrime = require('./lib/generatePrime')
|
|
var primes = require('./lib/primes.json')
|
|
|
|
var DH = require('./lib/dh')
|
|
|
|
function getDiffieHellman (mod) {
|
|
var prime = new Buffer(primes[mod].prime, 'hex')
|
|
var gen = new Buffer(primes[mod].gen, 'hex')
|
|
|
|
return new DH(prime, gen)
|
|
}
|
|
|
|
var ENCODINGS = {
|
|
'binary': true, 'hex': true, 'base64': true
|
|
}
|
|
|
|
function createDiffieHellman (prime, enc, generator, genc) {
|
|
if (Buffer.isBuffer(enc) || ENCODINGS[enc] === undefined) {
|
|
return createDiffieHellman(prime, 'binary', enc, generator)
|
|
}
|
|
|
|
enc = enc || 'binary'
|
|
genc = genc || 'binary'
|
|
generator = generator || new Buffer([2])
|
|
|
|
if (!Buffer.isBuffer(generator)) {
|
|
generator = new Buffer(generator, genc)
|
|
}
|
|
|
|
if (typeof prime === 'number') {
|
|
return new DH(generatePrime(prime, generator), generator, true)
|
|
}
|
|
|
|
if (!Buffer.isBuffer(prime)) {
|
|
prime = new Buffer(prime, enc)
|
|
}
|
|
|
|
return new DH(prime, generator, true)
|
|
}
|
|
|
|
exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = getDiffieHellman
|
|
exports.createDiffieHellman = exports.DiffieHellman = createDiffieHellman
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./lib/dh":171,"./lib/generatePrime":172,"./lib/primes.json":173,"buffer":47}],171:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var BN = require('bn.js');
|
|
var MillerRabin = require('miller-rabin');
|
|
var millerRabin = new MillerRabin();
|
|
var TWENTYFOUR = new BN(24);
|
|
var ELEVEN = new BN(11);
|
|
var TEN = new BN(10);
|
|
var THREE = new BN(3);
|
|
var SEVEN = new BN(7);
|
|
var primes = require('./generatePrime');
|
|
var randomBytes = require('randombytes');
|
|
module.exports = DH;
|
|
|
|
function setPublicKey(pub, enc) {
|
|
enc = enc || 'utf8';
|
|
if (!Buffer.isBuffer(pub)) {
|
|
pub = new Buffer(pub, enc);
|
|
}
|
|
this._pub = new BN(pub);
|
|
return this;
|
|
}
|
|
|
|
function setPrivateKey(priv, enc) {
|
|
enc = enc || 'utf8';
|
|
if (!Buffer.isBuffer(priv)) {
|
|
priv = new Buffer(priv, enc);
|
|
}
|
|
this._priv = new BN(priv);
|
|
return this;
|
|
}
|
|
|
|
var primeCache = {};
|
|
function checkPrime(prime, generator) {
|
|
var gen = generator.toString('hex');
|
|
var hex = [gen, prime.toString(16)].join('_');
|
|
if (hex in primeCache) {
|
|
return primeCache[hex];
|
|
}
|
|
var error = 0;
|
|
|
|
if (prime.isEven() ||
|
|
!primes.simpleSieve ||
|
|
!primes.fermatTest(prime) ||
|
|
!millerRabin.test(prime)) {
|
|
//not a prime so +1
|
|
error += 1;
|
|
|
|
if (gen === '02' || gen === '05') {
|
|
// we'd be able to check the generator
|
|
// it would fail so +8
|
|
error += 8;
|
|
} else {
|
|
//we wouldn't be able to test the generator
|
|
// so +4
|
|
error += 4;
|
|
}
|
|
primeCache[hex] = error;
|
|
return error;
|
|
}
|
|
if (!millerRabin.test(prime.shrn(1))) {
|
|
//not a safe prime
|
|
error += 2;
|
|
}
|
|
var rem;
|
|
switch (gen) {
|
|
case '02':
|
|
if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) {
|
|
// unsuidable generator
|
|
error += 8;
|
|
}
|
|
break;
|
|
case '05':
|
|
rem = prime.mod(TEN);
|
|
if (rem.cmp(THREE) && rem.cmp(SEVEN)) {
|
|
// prime mod 10 needs to equal 3 or 7
|
|
error += 8;
|
|
}
|
|
break;
|
|
default:
|
|
error += 4;
|
|
}
|
|
primeCache[hex] = error;
|
|
return error;
|
|
}
|
|
|
|
function DH(prime, generator, malleable) {
|
|
this.setGenerator(generator);
|
|
this.__prime = new BN(prime);
|
|
this._prime = BN.mont(this.__prime);
|
|
this._primeLen = prime.length;
|
|
this._pub = undefined;
|
|
this._priv = undefined;
|
|
this._primeCode = undefined;
|
|
if (malleable) {
|
|
this.setPublicKey = setPublicKey;
|
|
this.setPrivateKey = setPrivateKey;
|
|
} else {
|
|
this._primeCode = 8;
|
|
}
|
|
}
|
|
Object.defineProperty(DH.prototype, 'verifyError', {
|
|
enumerable: true,
|
|
get: function () {
|
|
if (typeof this._primeCode !== 'number') {
|
|
this._primeCode = checkPrime(this.__prime, this.__gen);
|
|
}
|
|
return this._primeCode;
|
|
}
|
|
});
|
|
DH.prototype.generateKeys = function () {
|
|
if (!this._priv) {
|
|
this._priv = new BN(randomBytes(this._primeLen));
|
|
}
|
|
this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed();
|
|
return this.getPublicKey();
|
|
};
|
|
|
|
DH.prototype.computeSecret = function (other) {
|
|
other = new BN(other);
|
|
other = other.toRed(this._prime);
|
|
var secret = other.redPow(this._priv).fromRed();
|
|
var out = new Buffer(secret.toArray());
|
|
var prime = this.getPrime();
|
|
if (out.length < prime.length) {
|
|
var front = new Buffer(prime.length - out.length);
|
|
front.fill(0);
|
|
out = Buffer.concat([front, out]);
|
|
}
|
|
return out;
|
|
};
|
|
|
|
DH.prototype.getPublicKey = function getPublicKey(enc) {
|
|
return formatReturnValue(this._pub, enc);
|
|
};
|
|
|
|
DH.prototype.getPrivateKey = function getPrivateKey(enc) {
|
|
return formatReturnValue(this._priv, enc);
|
|
};
|
|
|
|
DH.prototype.getPrime = function (enc) {
|
|
return formatReturnValue(this.__prime, enc);
|
|
};
|
|
|
|
DH.prototype.getGenerator = function (enc) {
|
|
return formatReturnValue(this._gen, enc);
|
|
};
|
|
|
|
DH.prototype.setGenerator = function (gen, enc) {
|
|
enc = enc || 'utf8';
|
|
if (!Buffer.isBuffer(gen)) {
|
|
gen = new Buffer(gen, enc);
|
|
}
|
|
this.__gen = gen;
|
|
this._gen = new BN(gen);
|
|
return this;
|
|
};
|
|
|
|
function formatReturnValue(bn, enc) {
|
|
var buf = new Buffer(bn.toArray());
|
|
if (!enc) {
|
|
return buf;
|
|
} else {
|
|
return buf.toString(enc);
|
|
}
|
|
}
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./generatePrime":172,"bn.js":280,"buffer":47,"miller-rabin":174,"randombytes":243}],172:[function(require,module,exports){
|
|
var randomBytes = require('randombytes');
|
|
module.exports = findPrime;
|
|
findPrime.simpleSieve = simpleSieve;
|
|
findPrime.fermatTest = fermatTest;
|
|
var BN = require('bn.js');
|
|
var TWENTYFOUR = new BN(24);
|
|
var MillerRabin = require('miller-rabin');
|
|
var millerRabin = new MillerRabin();
|
|
var ONE = new BN(1);
|
|
var TWO = new BN(2);
|
|
var FIVE = new BN(5);
|
|
var SIXTEEN = new BN(16);
|
|
var EIGHT = new BN(8);
|
|
var TEN = new BN(10);
|
|
var THREE = new BN(3);
|
|
var SEVEN = new BN(7);
|
|
var ELEVEN = new BN(11);
|
|
var FOUR = new BN(4);
|
|
var TWELVE = new BN(12);
|
|
var primes = null;
|
|
|
|
function _getPrimes() {
|
|
if (primes !== null)
|
|
return primes;
|
|
|
|
var limit = 0x100000;
|
|
var res = [];
|
|
res[0] = 2;
|
|
for (var i = 1, k = 3; k < limit; k += 2) {
|
|
var sqrt = Math.ceil(Math.sqrt(k));
|
|
for (var j = 0; j < i && res[j] <= sqrt; j++)
|
|
if (k % res[j] === 0)
|
|
break;
|
|
|
|
if (i !== j && res[j] <= sqrt)
|
|
continue;
|
|
|
|
res[i++] = k;
|
|
}
|
|
primes = res;
|
|
return res;
|
|
}
|
|
|
|
function simpleSieve(p) {
|
|
var primes = _getPrimes();
|
|
|
|
for (var i = 0; i < primes.length; i++)
|
|
if (p.modn(primes[i]) === 0) {
|
|
if (p.cmpn(primes[i]) === 0) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function fermatTest(p) {
|
|
var red = BN.mont(p);
|
|
return TWO.toRed(red).redPow(p.subn(1)).fromRed().cmpn(1) === 0;
|
|
}
|
|
|
|
function findPrime(bits, gen) {
|
|
if (bits < 16) {
|
|
// this is what openssl does
|
|
if (gen === 2 || gen === 5) {
|
|
return new BN([0x8c, 0x7b]);
|
|
} else {
|
|
return new BN([0x8c, 0x27]);
|
|
}
|
|
}
|
|
gen = new BN(gen);
|
|
|
|
var num, n2;
|
|
|
|
while (true) {
|
|
num = new BN(randomBytes(Math.ceil(bits / 8)));
|
|
while (num.bitLength() > bits) {
|
|
num.ishrn(1);
|
|
}
|
|
if (num.isEven()) {
|
|
num.iadd(ONE);
|
|
}
|
|
if (!num.testn(1)) {
|
|
num.iadd(TWO);
|
|
}
|
|
if (!gen.cmp(TWO)) {
|
|
while (num.mod(TWENTYFOUR).cmp(ELEVEN)) {
|
|
num.iadd(FOUR);
|
|
}
|
|
} else if (!gen.cmp(FIVE)) {
|
|
while (num.mod(TEN).cmp(THREE)) {
|
|
num.iadd(FOUR);
|
|
}
|
|
}
|
|
n2 = num.shrn(1);
|
|
if (simpleSieve(n2) && simpleSieve(num) &&
|
|
fermatTest(n2) && fermatTest(num) &&
|
|
millerRabin.test(n2) && millerRabin.test(num)) {
|
|
return num;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
},{"bn.js":280,"miller-rabin":174,"randombytes":243}],173:[function(require,module,exports){
|
|
module.exports={
|
|
"modp1": {
|
|
"gen": "02",
|
|
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"
|
|
},
|
|
"modp2": {
|
|
"gen": "02",
|
|
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff"
|
|
},
|
|
"modp5": {
|
|
"gen": "02",
|
|
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff"
|
|
},
|
|
"modp14": {
|
|
"gen": "02",
|
|
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff"
|
|
},
|
|
"modp15": {
|
|
"gen": "02",
|
|
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff"
|
|
},
|
|
"modp16": {
|
|
"gen": "02",
|
|
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff"
|
|
},
|
|
"modp17": {
|
|
"gen": "02",
|
|
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff"
|
|
},
|
|
"modp18": {
|
|
"gen": "02",
|
|
"prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff"
|
|
}
|
|
}
|
|
},{}],174:[function(require,module,exports){
|
|
var bn = require('bn.js');
|
|
var brorand = require('brorand');
|
|
|
|
function MillerRabin(rand) {
|
|
this.rand = rand || new brorand.Rand();
|
|
}
|
|
module.exports = MillerRabin;
|
|
|
|
MillerRabin.create = function create(rand) {
|
|
return new MillerRabin(rand);
|
|
};
|
|
|
|
MillerRabin.prototype._randbelow = function _randbelow(n) {
|
|
var len = n.bitLength();
|
|
var min_bytes = Math.ceil(len / 8);
|
|
|
|
// Generage random bytes until a number less than n is found.
|
|
// This ensures that 0..n-1 have an equal probability of being selected.
|
|
do
|
|
var a = new bn(this.rand.generate(min_bytes));
|
|
while (a.cmp(n) >= 0);
|
|
|
|
return a;
|
|
};
|
|
|
|
MillerRabin.prototype._randrange = function _randrange(start, stop) {
|
|
// Generate a random number greater than or equal to start and less than stop.
|
|
var size = stop.sub(start);
|
|
return start.add(this._randbelow(size));
|
|
};
|
|
|
|
MillerRabin.prototype.test = function test(n, k, cb) {
|
|
var len = n.bitLength();
|
|
var red = bn.mont(n);
|
|
var rone = new bn(1).toRed(red);
|
|
|
|
if (!k)
|
|
k = Math.max(1, (len / 48) | 0);
|
|
|
|
// Find d and s, (n - 1) = (2 ^ s) * d;
|
|
var n1 = n.subn(1);
|
|
for (var s = 0; !n1.testn(s); s++) {}
|
|
var d = n.shrn(s);
|
|
|
|
var rn1 = n1.toRed(red);
|
|
|
|
var prime = true;
|
|
for (; k > 0; k--) {
|
|
var a = this._randrange(new bn(2), n1);
|
|
if (cb)
|
|
cb(a);
|
|
|
|
var x = a.toRed(red).redPow(d);
|
|
if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
|
|
continue;
|
|
|
|
for (var i = 1; i < s; i++) {
|
|
x = x.redSqr();
|
|
|
|
if (x.cmp(rone) === 0)
|
|
return false;
|
|
if (x.cmp(rn1) === 0)
|
|
break;
|
|
}
|
|
|
|
if (i === s)
|
|
return false;
|
|
}
|
|
|
|
return prime;
|
|
};
|
|
|
|
MillerRabin.prototype.getDivisor = function getDivisor(n, k) {
|
|
var len = n.bitLength();
|
|
var red = bn.mont(n);
|
|
var rone = new bn(1).toRed(red);
|
|
|
|
if (!k)
|
|
k = Math.max(1, (len / 48) | 0);
|
|
|
|
// Find d and s, (n - 1) = (2 ^ s) * d;
|
|
var n1 = n.subn(1);
|
|
for (var s = 0; !n1.testn(s); s++) {}
|
|
var d = n.shrn(s);
|
|
|
|
var rn1 = n1.toRed(red);
|
|
|
|
for (; k > 0; k--) {
|
|
var a = this._randrange(new bn(2), n1);
|
|
|
|
var g = n.gcd(a);
|
|
if (g.cmpn(1) !== 0)
|
|
return g;
|
|
|
|
var x = a.toRed(red).redPow(d);
|
|
if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
|
|
continue;
|
|
|
|
for (var i = 1; i < s; i++) {
|
|
x = x.redSqr();
|
|
|
|
if (x.cmp(rone) === 0)
|
|
return x.fromRed().subn(1).gcd(n);
|
|
if (x.cmp(rn1) === 0)
|
|
break;
|
|
}
|
|
|
|
if (i === s) {
|
|
x = x.redSqr();
|
|
return x.fromRed().subn(1).gcd(n);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
},{"bn.js":280,"brorand":175}],175:[function(require,module,exports){
|
|
var r;
|
|
|
|
module.exports = function rand(len) {
|
|
if (!r)
|
|
r = new Rand(null);
|
|
|
|
return r.generate(len);
|
|
};
|
|
|
|
function Rand(rand) {
|
|
this.rand = rand;
|
|
}
|
|
module.exports.Rand = Rand;
|
|
|
|
Rand.prototype.generate = function generate(len) {
|
|
return this._rand(len);
|
|
};
|
|
|
|
// Emulate crypto API using randy
|
|
Rand.prototype._rand = function _rand(n) {
|
|
if (this.rand.getBytes)
|
|
return this.rand.getBytes(n);
|
|
|
|
var res = new Uint8Array(n);
|
|
for (var i = 0; i < res.length; i++)
|
|
res[i] = this.rand.getByte();
|
|
return res;
|
|
};
|
|
|
|
if (typeof self === 'object') {
|
|
if (self.crypto && self.crypto.getRandomValues) {
|
|
// Modern browsers
|
|
Rand.prototype._rand = function _rand(n) {
|
|
var arr = new Uint8Array(n);
|
|
self.crypto.getRandomValues(arr);
|
|
return arr;
|
|
};
|
|
} else if (self.msCrypto && self.msCrypto.getRandomValues) {
|
|
// IE
|
|
Rand.prototype._rand = function _rand(n) {
|
|
var arr = new Uint8Array(n);
|
|
self.msCrypto.getRandomValues(arr);
|
|
return arr;
|
|
};
|
|
|
|
// Safari's WebWorkers do not have `crypto`
|
|
} else if (typeof window === 'object') {
|
|
// Old junk
|
|
Rand.prototype._rand = function() {
|
|
throw new Error('Not implemented yet');
|
|
};
|
|
}
|
|
} else {
|
|
// Node.js or Web worker with no crypto support
|
|
try {
|
|
var crypto = require('crypto');
|
|
if (typeof crypto.randomBytes !== 'function')
|
|
throw new Error('Not supported');
|
|
|
|
Rand.prototype._rand = function _rand(n) {
|
|
return crypto.randomBytes(n);
|
|
};
|
|
} catch (e) {
|
|
}
|
|
}
|
|
|
|
},{"crypto":46}],176:[function(require,module,exports){
|
|
|
|
exports.pbkdf2 = require('./lib/async')
|
|
|
|
exports.pbkdf2Sync = require('./lib/sync')
|
|
|
|
},{"./lib/async":177,"./lib/sync":180}],177:[function(require,module,exports){
|
|
(function (process,global){
|
|
var checkParameters = require('./precondition')
|
|
var defaultEncoding = require('./default-encoding')
|
|
var sync = require('./sync')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
var ZERO_BUF
|
|
var subtle = global.crypto && global.crypto.subtle
|
|
var toBrowser = {
|
|
'sha': 'SHA-1',
|
|
'sha-1': 'SHA-1',
|
|
'sha1': 'SHA-1',
|
|
'sha256': 'SHA-256',
|
|
'sha-256': 'SHA-256',
|
|
'sha384': 'SHA-384',
|
|
'sha-384': 'SHA-384',
|
|
'sha-512': 'SHA-512',
|
|
'sha512': 'SHA-512'
|
|
}
|
|
var checks = []
|
|
function checkNative (algo) {
|
|
if (global.process && !global.process.browser) {
|
|
return Promise.resolve(false)
|
|
}
|
|
if (!subtle || !subtle.importKey || !subtle.deriveBits) {
|
|
return Promise.resolve(false)
|
|
}
|
|
if (checks[algo] !== undefined) {
|
|
return checks[algo]
|
|
}
|
|
ZERO_BUF = ZERO_BUF || Buffer.alloc(8)
|
|
var prom = browserPbkdf2(ZERO_BUF, ZERO_BUF, 10, 128, algo)
|
|
.then(function () {
|
|
return true
|
|
}).catch(function () {
|
|
return false
|
|
})
|
|
checks[algo] = prom
|
|
return prom
|
|
}
|
|
function browserPbkdf2 (password, salt, iterations, length, algo) {
|
|
return subtle.importKey(
|
|
'raw', password, {name: 'PBKDF2'}, false, ['deriveBits']
|
|
).then(function (key) {
|
|
return subtle.deriveBits({
|
|
name: 'PBKDF2',
|
|
salt: salt,
|
|
iterations: iterations,
|
|
hash: {
|
|
name: algo
|
|
}
|
|
}, key, length << 3)
|
|
}).then(function (res) {
|
|
return Buffer.from(res)
|
|
})
|
|
}
|
|
function resolvePromise (promise, callback) {
|
|
promise.then(function (out) {
|
|
process.nextTick(function () {
|
|
callback(null, out)
|
|
})
|
|
}, function (e) {
|
|
process.nextTick(function () {
|
|
callback(e)
|
|
})
|
|
})
|
|
}
|
|
module.exports = function (password, salt, iterations, keylen, digest, callback) {
|
|
if (!Buffer.isBuffer(password)) password = Buffer.from(password, defaultEncoding)
|
|
if (!Buffer.isBuffer(salt)) salt = Buffer.from(salt, defaultEncoding)
|
|
|
|
checkParameters(iterations, keylen)
|
|
if (typeof digest === 'function') {
|
|
callback = digest
|
|
digest = undefined
|
|
}
|
|
if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2')
|
|
|
|
digest = digest || 'sha1'
|
|
var algo = toBrowser[digest.toLowerCase()]
|
|
if (!algo || typeof global.Promise !== 'function') {
|
|
return process.nextTick(function () {
|
|
var out
|
|
try {
|
|
out = sync(password, salt, iterations, keylen, digest)
|
|
} catch (e) {
|
|
return callback(e)
|
|
}
|
|
callback(null, out)
|
|
})
|
|
}
|
|
resolvePromise(checkNative(algo).then(function (resp) {
|
|
if (resp) {
|
|
return browserPbkdf2(password, salt, iterations, keylen, algo)
|
|
} else {
|
|
return sync(password, salt, iterations, keylen, digest)
|
|
}
|
|
}), callback)
|
|
}
|
|
|
|
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{"./default-encoding":178,"./precondition":179,"./sync":180,"_process":247,"safe-buffer":183}],178:[function(require,module,exports){
|
|
(function (process){
|
|
var defaultEncoding
|
|
/* istanbul ignore next */
|
|
if (process.browser) {
|
|
defaultEncoding = 'utf-8'
|
|
} else {
|
|
var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10)
|
|
|
|
defaultEncoding = pVersionMajor >= 6 ? 'utf-8' : 'binary'
|
|
}
|
|
module.exports = defaultEncoding
|
|
|
|
}).call(this,require('_process'))
|
|
},{"_process":247}],179:[function(require,module,exports){
|
|
var MAX_ALLOC = Math.pow(2, 30) - 1 // default in iojs
|
|
module.exports = function (iterations, keylen) {
|
|
if (typeof iterations !== 'number') {
|
|
throw new TypeError('Iterations not a number')
|
|
}
|
|
|
|
if (iterations < 0) {
|
|
throw new TypeError('Bad iterations')
|
|
}
|
|
|
|
if (typeof keylen !== 'number') {
|
|
throw new TypeError('Key length not a number')
|
|
}
|
|
|
|
if (keylen < 0 || keylen > MAX_ALLOC || keylen !== keylen) { /* eslint no-self-compare: 0 */
|
|
throw new TypeError('Bad key length')
|
|
}
|
|
}
|
|
|
|
},{}],180:[function(require,module,exports){
|
|
var md5 = require('create-hash/md5')
|
|
var rmd160 = require('ripemd160')
|
|
var sha = require('sha.js')
|
|
|
|
var checkParameters = require('./precondition')
|
|
var defaultEncoding = require('./default-encoding')
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var ZEROS = Buffer.alloc(128)
|
|
var sizes = {
|
|
md5: 16,
|
|
sha1: 20,
|
|
sha224: 28,
|
|
sha256: 32,
|
|
sha384: 48,
|
|
sha512: 64,
|
|
rmd160: 20,
|
|
ripemd160: 20
|
|
}
|
|
|
|
function Hmac (alg, key, saltLen) {
|
|
var hash = getDigest(alg)
|
|
var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64
|
|
|
|
if (key.length > blocksize) {
|
|
key = hash(key)
|
|
} else if (key.length < blocksize) {
|
|
key = Buffer.concat([key, ZEROS], blocksize)
|
|
}
|
|
|
|
var ipad = Buffer.allocUnsafe(blocksize + sizes[alg])
|
|
var opad = Buffer.allocUnsafe(blocksize + sizes[alg])
|
|
for (var i = 0; i < blocksize; i++) {
|
|
ipad[i] = key[i] ^ 0x36
|
|
opad[i] = key[i] ^ 0x5C
|
|
}
|
|
|
|
var ipad1 = Buffer.allocUnsafe(blocksize + saltLen + 4)
|
|
ipad.copy(ipad1, 0, 0, blocksize)
|
|
this.ipad1 = ipad1
|
|
this.ipad2 = ipad
|
|
this.opad = opad
|
|
this.alg = alg
|
|
this.blocksize = blocksize
|
|
this.hash = hash
|
|
this.size = sizes[alg]
|
|
}
|
|
|
|
Hmac.prototype.run = function (data, ipad) {
|
|
data.copy(ipad, this.blocksize)
|
|
var h = this.hash(ipad)
|
|
h.copy(this.opad, this.blocksize)
|
|
return this.hash(this.opad)
|
|
}
|
|
|
|
function getDigest (alg) {
|
|
function shaFunc (data) {
|
|
return sha(alg).update(data).digest()
|
|
}
|
|
|
|
if (alg === 'rmd160' || alg === 'ripemd160') return rmd160
|
|
if (alg === 'md5') return md5
|
|
return shaFunc
|
|
}
|
|
|
|
function pbkdf2 (password, salt, iterations, keylen, digest) {
|
|
if (!Buffer.isBuffer(password)) password = Buffer.from(password, defaultEncoding)
|
|
if (!Buffer.isBuffer(salt)) salt = Buffer.from(salt, defaultEncoding)
|
|
|
|
checkParameters(iterations, keylen)
|
|
|
|
digest = digest || 'sha1'
|
|
|
|
var hmac = new Hmac(digest, password, salt.length)
|
|
|
|
var DK = Buffer.allocUnsafe(keylen)
|
|
var block1 = Buffer.allocUnsafe(salt.length + 4)
|
|
salt.copy(block1, 0, 0, salt.length)
|
|
|
|
var destPos = 0
|
|
var hLen = sizes[digest]
|
|
var l = Math.ceil(keylen / hLen)
|
|
|
|
for (var i = 1; i <= l; i++) {
|
|
block1.writeUInt32BE(i, salt.length)
|
|
|
|
var T = hmac.run(block1, hmac.ipad1)
|
|
var U = T
|
|
|
|
for (var j = 1; j < iterations; j++) {
|
|
U = hmac.run(U, hmac.ipad2)
|
|
for (var k = 0; k < hLen; k++) T[k] ^= U[k]
|
|
}
|
|
|
|
T.copy(DK, destPos)
|
|
destPos += hLen
|
|
}
|
|
|
|
return DK
|
|
}
|
|
|
|
module.exports = pbkdf2
|
|
|
|
},{"./default-encoding":178,"./precondition":179,"create-hash/md5":142,"ripemd160":181,"safe-buffer":183,"sha.js":185}],181:[function(require,module,exports){
|
|
arguments[4][145][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":145,"hash-base":182,"inherits":318}],182:[function(require,module,exports){
|
|
arguments[4][146][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":146,"inherits":318,"stream":272}],183:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],184:[function(require,module,exports){
|
|
arguments[4][147][0].apply(exports,arguments)
|
|
},{"dup":147,"safe-buffer":183}],185:[function(require,module,exports){
|
|
arguments[4][148][0].apply(exports,arguments)
|
|
},{"./sha":186,"./sha1":187,"./sha224":188,"./sha256":189,"./sha384":190,"./sha512":191,"dup":148}],186:[function(require,module,exports){
|
|
arguments[4][150][0].apply(exports,arguments)
|
|
},{"./hash":184,"dup":150,"inherits":318,"safe-buffer":183}],187:[function(require,module,exports){
|
|
arguments[4][151][0].apply(exports,arguments)
|
|
},{"./hash":184,"dup":151,"inherits":318,"safe-buffer":183}],188:[function(require,module,exports){
|
|
arguments[4][152][0].apply(exports,arguments)
|
|
},{"./hash":184,"./sha256":189,"dup":152,"inherits":318,"safe-buffer":183}],189:[function(require,module,exports){
|
|
arguments[4][153][0].apply(exports,arguments)
|
|
},{"./hash":184,"dup":153,"inherits":318,"safe-buffer":183}],190:[function(require,module,exports){
|
|
arguments[4][154][0].apply(exports,arguments)
|
|
},{"./hash":184,"./sha512":191,"dup":154,"inherits":318,"safe-buffer":183}],191:[function(require,module,exports){
|
|
arguments[4][155][0].apply(exports,arguments)
|
|
},{"./hash":184,"dup":155,"inherits":318,"safe-buffer":183}],192:[function(require,module,exports){
|
|
exports.publicEncrypt = require('./publicEncrypt');
|
|
exports.privateDecrypt = require('./privateDecrypt');
|
|
|
|
exports.privateEncrypt = function privateEncrypt(key, buf) {
|
|
return exports.publicEncrypt(key, buf, true);
|
|
};
|
|
|
|
exports.publicDecrypt = function publicDecrypt(key, buf) {
|
|
return exports.privateDecrypt(key, buf, true);
|
|
};
|
|
},{"./privateDecrypt":239,"./publicEncrypt":240}],193:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var createHash = require('create-hash');
|
|
module.exports = function (seed, len) {
|
|
var t = new Buffer('');
|
|
var i = 0, c;
|
|
while (t.length < len) {
|
|
c = i2ops(i++);
|
|
t = Buffer.concat([t, createHash('sha1').update(seed).update(c).digest()]);
|
|
}
|
|
return t.slice(0, len);
|
|
};
|
|
|
|
function i2ops(c) {
|
|
var out = new Buffer(4);
|
|
out.writeUInt32BE(c,0);
|
|
return out;
|
|
}
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"buffer":47,"create-hash":140}],194:[function(require,module,exports){
|
|
arguments[4][94][0].apply(exports,arguments)
|
|
},{"bn.js":280,"buffer":47,"dup":94,"randombytes":243}],195:[function(require,module,exports){
|
|
arguments[4][95][0].apply(exports,arguments)
|
|
},{"dup":95}],196:[function(require,module,exports){
|
|
arguments[4][96][0].apply(exports,arguments)
|
|
},{"./certificate":197,"asn1.js":200,"dup":96}],197:[function(require,module,exports){
|
|
arguments[4][97][0].apply(exports,arguments)
|
|
},{"asn1.js":200,"dup":97}],198:[function(require,module,exports){
|
|
arguments[4][98][0].apply(exports,arguments)
|
|
},{"browserify-aes":217,"buffer":47,"dup":98,"evp_bytestokey":235}],199:[function(require,module,exports){
|
|
arguments[4][99][0].apply(exports,arguments)
|
|
},{"./aesid.json":195,"./asn1":196,"./fixProc":198,"browserify-aes":217,"buffer":47,"dup":99,"pbkdf2":176}],200:[function(require,module,exports){
|
|
arguments[4][100][0].apply(exports,arguments)
|
|
},{"./asn1/api":201,"./asn1/base":203,"./asn1/constants":207,"./asn1/decoders":209,"./asn1/encoders":212,"bn.js":280,"dup":100}],201:[function(require,module,exports){
|
|
arguments[4][101][0].apply(exports,arguments)
|
|
},{"../asn1":200,"dup":101,"inherits":318,"vm":278}],202:[function(require,module,exports){
|
|
arguments[4][102][0].apply(exports,arguments)
|
|
},{"../base":203,"buffer":47,"dup":102,"inherits":318}],203:[function(require,module,exports){
|
|
arguments[4][103][0].apply(exports,arguments)
|
|
},{"./buffer":202,"./node":204,"./reporter":205,"dup":103}],204:[function(require,module,exports){
|
|
arguments[4][104][0].apply(exports,arguments)
|
|
},{"../base":203,"dup":104,"minimalistic-assert":214}],205:[function(require,module,exports){
|
|
arguments[4][105][0].apply(exports,arguments)
|
|
},{"dup":105,"inherits":318}],206:[function(require,module,exports){
|
|
arguments[4][106][0].apply(exports,arguments)
|
|
},{"../constants":207,"dup":106}],207:[function(require,module,exports){
|
|
arguments[4][107][0].apply(exports,arguments)
|
|
},{"./der":206,"dup":107}],208:[function(require,module,exports){
|
|
arguments[4][108][0].apply(exports,arguments)
|
|
},{"../../asn1":200,"dup":108,"inherits":318}],209:[function(require,module,exports){
|
|
arguments[4][109][0].apply(exports,arguments)
|
|
},{"./der":208,"./pem":210,"dup":109}],210:[function(require,module,exports){
|
|
arguments[4][110][0].apply(exports,arguments)
|
|
},{"./der":208,"buffer":47,"dup":110,"inherits":318}],211:[function(require,module,exports){
|
|
arguments[4][111][0].apply(exports,arguments)
|
|
},{"../../asn1":200,"buffer":47,"dup":111,"inherits":318}],212:[function(require,module,exports){
|
|
arguments[4][112][0].apply(exports,arguments)
|
|
},{"./der":211,"./pem":213,"dup":112}],213:[function(require,module,exports){
|
|
arguments[4][113][0].apply(exports,arguments)
|
|
},{"./der":211,"dup":113,"inherits":318}],214:[function(require,module,exports){
|
|
arguments[4][83][0].apply(exports,arguments)
|
|
},{"dup":83}],215:[function(require,module,exports){
|
|
arguments[4][53][0].apply(exports,arguments)
|
|
},{"dup":53,"safe-buffer":233}],216:[function(require,module,exports){
|
|
arguments[4][54][0].apply(exports,arguments)
|
|
},{"./aes":215,"./ghash":220,"./incr32":221,"buffer-xor":231,"cipher-base":232,"dup":54,"inherits":318,"safe-buffer":233}],217:[function(require,module,exports){
|
|
arguments[4][55][0].apply(exports,arguments)
|
|
},{"./decrypter":218,"./encrypter":219,"./modes/list.json":229,"dup":55}],218:[function(require,module,exports){
|
|
arguments[4][56][0].apply(exports,arguments)
|
|
},{"./aes":215,"./authCipher":216,"./modes":228,"./streamCipher":234,"cipher-base":232,"dup":56,"evp_bytestokey":235,"inherits":318,"safe-buffer":233}],219:[function(require,module,exports){
|
|
arguments[4][57][0].apply(exports,arguments)
|
|
},{"./aes":215,"./authCipher":216,"./modes":228,"./streamCipher":234,"cipher-base":232,"dup":57,"evp_bytestokey":235,"inherits":318,"safe-buffer":233}],220:[function(require,module,exports){
|
|
arguments[4][58][0].apply(exports,arguments)
|
|
},{"dup":58,"safe-buffer":233}],221:[function(require,module,exports){
|
|
arguments[4][59][0].apply(exports,arguments)
|
|
},{"dup":59}],222:[function(require,module,exports){
|
|
arguments[4][60][0].apply(exports,arguments)
|
|
},{"buffer-xor":231,"dup":60}],223:[function(require,module,exports){
|
|
arguments[4][61][0].apply(exports,arguments)
|
|
},{"buffer-xor":231,"dup":61,"safe-buffer":233}],224:[function(require,module,exports){
|
|
arguments[4][62][0].apply(exports,arguments)
|
|
},{"dup":62,"safe-buffer":233}],225:[function(require,module,exports){
|
|
arguments[4][63][0].apply(exports,arguments)
|
|
},{"dup":63,"safe-buffer":233}],226:[function(require,module,exports){
|
|
arguments[4][64][0].apply(exports,arguments)
|
|
},{"../incr32":221,"buffer-xor":231,"dup":64,"safe-buffer":233}],227:[function(require,module,exports){
|
|
arguments[4][65][0].apply(exports,arguments)
|
|
},{"dup":65}],228:[function(require,module,exports){
|
|
arguments[4][66][0].apply(exports,arguments)
|
|
},{"./cbc":222,"./cfb":223,"./cfb1":224,"./cfb8":225,"./ctr":226,"./ecb":227,"./list.json":229,"./ofb":230,"dup":66}],229:[function(require,module,exports){
|
|
arguments[4][67][0].apply(exports,arguments)
|
|
},{"dup":67}],230:[function(require,module,exports){
|
|
arguments[4][68][0].apply(exports,arguments)
|
|
},{"buffer":47,"buffer-xor":231,"dup":68}],231:[function(require,module,exports){
|
|
arguments[4][69][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":69}],232:[function(require,module,exports){
|
|
arguments[4][70][0].apply(exports,arguments)
|
|
},{"dup":70,"inherits":318,"safe-buffer":233,"stream":272,"string_decoder":273}],233:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],234:[function(require,module,exports){
|
|
arguments[4][72][0].apply(exports,arguments)
|
|
},{"./aes":215,"cipher-base":232,"dup":72,"inherits":318,"safe-buffer":233}],235:[function(require,module,exports){
|
|
arguments[4][84][0].apply(exports,arguments)
|
|
},{"dup":84,"md5.js":236,"safe-buffer":238}],236:[function(require,module,exports){
|
|
arguments[4][85][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":85,"hash-base":237,"inherits":318}],237:[function(require,module,exports){
|
|
arguments[4][86][0].apply(exports,arguments)
|
|
},{"dup":86,"inherits":318,"safe-buffer":238,"stream":272}],238:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],239:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var parseKeys = require('parse-asn1');
|
|
var mgf = require('./mgf');
|
|
var xor = require('./xor');
|
|
var bn = require('bn.js');
|
|
var crt = require('browserify-rsa');
|
|
var createHash = require('create-hash');
|
|
var withPublic = require('./withPublic');
|
|
module.exports = function privateDecrypt(private_key, enc, reverse) {
|
|
var padding;
|
|
if (private_key.padding) {
|
|
padding = private_key.padding;
|
|
} else if (reverse) {
|
|
padding = 1;
|
|
} else {
|
|
padding = 4;
|
|
}
|
|
|
|
var key = parseKeys(private_key);
|
|
var k = key.modulus.byteLength();
|
|
if (enc.length > k || new bn(enc).cmp(key.modulus) >= 0) {
|
|
throw new Error('decryption error');
|
|
}
|
|
var msg;
|
|
if (reverse) {
|
|
msg = withPublic(new bn(enc), key);
|
|
} else {
|
|
msg = crt(enc, key);
|
|
}
|
|
var zBuffer = new Buffer(k - msg.length);
|
|
zBuffer.fill(0);
|
|
msg = Buffer.concat([zBuffer, msg], k);
|
|
if (padding === 4) {
|
|
return oaep(key, msg);
|
|
} else if (padding === 1) {
|
|
return pkcs1(key, msg, reverse);
|
|
} else if (padding === 3) {
|
|
return msg;
|
|
} else {
|
|
throw new Error('unknown padding');
|
|
}
|
|
};
|
|
|
|
function oaep(key, msg){
|
|
var n = key.modulus;
|
|
var k = key.modulus.byteLength();
|
|
var mLen = msg.length;
|
|
var iHash = createHash('sha1').update(new Buffer('')).digest();
|
|
var hLen = iHash.length;
|
|
var hLen2 = 2 * hLen;
|
|
if (msg[0] !== 0) {
|
|
throw new Error('decryption error');
|
|
}
|
|
var maskedSeed = msg.slice(1, hLen + 1);
|
|
var maskedDb = msg.slice(hLen + 1);
|
|
var seed = xor(maskedSeed, mgf(maskedDb, hLen));
|
|
var db = xor(maskedDb, mgf(seed, k - hLen - 1));
|
|
if (compare(iHash, db.slice(0, hLen))) {
|
|
throw new Error('decryption error');
|
|
}
|
|
var i = hLen;
|
|
while (db[i] === 0) {
|
|
i++;
|
|
}
|
|
if (db[i++] !== 1) {
|
|
throw new Error('decryption error');
|
|
}
|
|
return db.slice(i);
|
|
}
|
|
|
|
function pkcs1(key, msg, reverse){
|
|
var p1 = msg.slice(0, 2);
|
|
var i = 2;
|
|
var status = 0;
|
|
while (msg[i++] !== 0) {
|
|
if (i >= msg.length) {
|
|
status++;
|
|
break;
|
|
}
|
|
}
|
|
var ps = msg.slice(2, i - 1);
|
|
var p2 = msg.slice(i - 1, i);
|
|
|
|
if ((p1.toString('hex') !== '0002' && !reverse) || (p1.toString('hex') !== '0001' && reverse)){
|
|
status++;
|
|
}
|
|
if (ps.length < 8) {
|
|
status++;
|
|
}
|
|
if (status) {
|
|
throw new Error('decryption error');
|
|
}
|
|
return msg.slice(i);
|
|
}
|
|
function compare(a, b){
|
|
a = new Buffer(a);
|
|
b = new Buffer(b);
|
|
var dif = 0;
|
|
var len = a.length;
|
|
if (a.length !== b.length) {
|
|
dif++;
|
|
len = Math.min(a.length, b.length);
|
|
}
|
|
var i = -1;
|
|
while (++i < len) {
|
|
dif += (a[i] ^ b[i]);
|
|
}
|
|
return dif;
|
|
}
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./mgf":193,"./withPublic":241,"./xor":242,"bn.js":280,"browserify-rsa":194,"buffer":47,"create-hash":140,"parse-asn1":199}],240:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var parseKeys = require('parse-asn1');
|
|
var randomBytes = require('randombytes');
|
|
var createHash = require('create-hash');
|
|
var mgf = require('./mgf');
|
|
var xor = require('./xor');
|
|
var bn = require('bn.js');
|
|
var withPublic = require('./withPublic');
|
|
var crt = require('browserify-rsa');
|
|
|
|
var constants = {
|
|
RSA_PKCS1_OAEP_PADDING: 4,
|
|
RSA_PKCS1_PADDIN: 1,
|
|
RSA_NO_PADDING: 3
|
|
};
|
|
|
|
module.exports = function publicEncrypt(public_key, msg, reverse) {
|
|
var padding;
|
|
if (public_key.padding) {
|
|
padding = public_key.padding;
|
|
} else if (reverse) {
|
|
padding = 1;
|
|
} else {
|
|
padding = 4;
|
|
}
|
|
var key = parseKeys(public_key);
|
|
var paddedMsg;
|
|
if (padding === 4) {
|
|
paddedMsg = oaep(key, msg);
|
|
} else if (padding === 1) {
|
|
paddedMsg = pkcs1(key, msg, reverse);
|
|
} else if (padding === 3) {
|
|
paddedMsg = new bn(msg);
|
|
if (paddedMsg.cmp(key.modulus) >= 0) {
|
|
throw new Error('data too long for modulus');
|
|
}
|
|
} else {
|
|
throw new Error('unknown padding');
|
|
}
|
|
if (reverse) {
|
|
return crt(paddedMsg, key);
|
|
} else {
|
|
return withPublic(paddedMsg, key);
|
|
}
|
|
};
|
|
|
|
function oaep(key, msg){
|
|
var k = key.modulus.byteLength();
|
|
var mLen = msg.length;
|
|
var iHash = createHash('sha1').update(new Buffer('')).digest();
|
|
var hLen = iHash.length;
|
|
var hLen2 = 2 * hLen;
|
|
if (mLen > k - hLen2 - 2) {
|
|
throw new Error('message too long');
|
|
}
|
|
var ps = new Buffer(k - mLen - hLen2 - 2);
|
|
ps.fill(0);
|
|
var dblen = k - hLen - 1;
|
|
var seed = randomBytes(hLen);
|
|
var maskedDb = xor(Buffer.concat([iHash, ps, new Buffer([1]), msg], dblen), mgf(seed, dblen));
|
|
var maskedSeed = xor(seed, mgf(maskedDb, hLen));
|
|
return new bn(Buffer.concat([new Buffer([0]), maskedSeed, maskedDb], k));
|
|
}
|
|
function pkcs1(key, msg, reverse){
|
|
var mLen = msg.length;
|
|
var k = key.modulus.byteLength();
|
|
if (mLen > k - 11) {
|
|
throw new Error('message too long');
|
|
}
|
|
var ps;
|
|
if (reverse) {
|
|
ps = new Buffer(k - mLen - 3);
|
|
ps.fill(0xff);
|
|
} else {
|
|
ps = nonZero(k - mLen - 3);
|
|
}
|
|
return new bn(Buffer.concat([new Buffer([0, reverse?1:2]), ps, new Buffer([0]), msg], k));
|
|
}
|
|
function nonZero(len, crypto) {
|
|
var out = new Buffer(len);
|
|
var i = 0;
|
|
var cache = randomBytes(len*2);
|
|
var cur = 0;
|
|
var num;
|
|
while (i < len) {
|
|
if (cur === cache.length) {
|
|
cache = randomBytes(len*2);
|
|
cur = 0;
|
|
}
|
|
num = cache[cur++];
|
|
if (num) {
|
|
out[i++] = num;
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"./mgf":193,"./withPublic":241,"./xor":242,"bn.js":280,"browserify-rsa":194,"buffer":47,"create-hash":140,"parse-asn1":199,"randombytes":243}],241:[function(require,module,exports){
|
|
(function (Buffer){
|
|
var bn = require('bn.js');
|
|
function withPublic(paddedMsg, key) {
|
|
return new Buffer(paddedMsg
|
|
.toRed(bn.mont(key.modulus))
|
|
.redPow(new bn(key.publicExponent))
|
|
.fromRed()
|
|
.toArray());
|
|
}
|
|
|
|
module.exports = withPublic;
|
|
}).call(this,require("buffer").Buffer)
|
|
},{"bn.js":280,"buffer":47}],242:[function(require,module,exports){
|
|
module.exports = function xor(a, b) {
|
|
var len = a.length;
|
|
var i = -1;
|
|
while (++i < len) {
|
|
a[i] ^= b[i];
|
|
}
|
|
return a
|
|
};
|
|
},{}],243:[function(require,module,exports){
|
|
(function (process,global){
|
|
'use strict'
|
|
|
|
function oldBrowser () {
|
|
throw new Error('secure random number generation not supported by this browser\nuse chrome, FireFox or Internet Explorer 11')
|
|
}
|
|
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var crypto = global.crypto || global.msCrypto
|
|
|
|
if (crypto && crypto.getRandomValues) {
|
|
module.exports = randomBytes
|
|
} else {
|
|
module.exports = oldBrowser
|
|
}
|
|
|
|
function randomBytes (size, cb) {
|
|
// phantomjs needs to throw
|
|
if (size > 65536) throw new Error('requested too many random bytes')
|
|
// in case browserify isn't using the Uint8Array version
|
|
var rawBytes = new global.Uint8Array(size)
|
|
|
|
// This will not work in older browsers.
|
|
// See https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
|
|
if (size > 0) { // getRandomValues fails on IE if size == 0
|
|
crypto.getRandomValues(rawBytes)
|
|
}
|
|
|
|
// XXX: phantomjs doesn't like a buffer being passed here
|
|
var bytes = Buffer.from(rawBytes.buffer)
|
|
|
|
if (typeof cb === 'function') {
|
|
return process.nextTick(function () {
|
|
cb(null, bytes)
|
|
})
|
|
}
|
|
|
|
return bytes
|
|
}
|
|
|
|
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{"_process":247,"safe-buffer":244}],244:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],245:[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.
|
|
|
|
function EventEmitter() {
|
|
this._events = this._events || {};
|
|
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.
|
|
EventEmitter.defaultMaxListeners = 10;
|
|
|
|
// 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(n) {
|
|
if (!isNumber(n) || n < 0 || isNaN(n))
|
|
throw TypeError('n must be a positive number');
|
|
this._maxListeners = n;
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.emit = function(type) {
|
|
var er, handler, len, args, i, listeners;
|
|
|
|
if (!this._events)
|
|
this._events = {};
|
|
|
|
// If there is no 'error' event listener then throw.
|
|
if (type === 'error') {
|
|
if (!this._events.error ||
|
|
(isObject(this._events.error) && !this._events.error.length)) {
|
|
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('Uncaught, unspecified "error" event. (' + er + ')');
|
|
err.context = er;
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
|
|
handler = this._events[type];
|
|
|
|
if (isUndefined(handler))
|
|
return false;
|
|
|
|
if (isFunction(handler)) {
|
|
switch (arguments.length) {
|
|
// fast cases
|
|
case 1:
|
|
handler.call(this);
|
|
break;
|
|
case 2:
|
|
handler.call(this, arguments[1]);
|
|
break;
|
|
case 3:
|
|
handler.call(this, arguments[1], arguments[2]);
|
|
break;
|
|
// slower
|
|
default:
|
|
args = Array.prototype.slice.call(arguments, 1);
|
|
handler.apply(this, args);
|
|
}
|
|
} else if (isObject(handler)) {
|
|
args = Array.prototype.slice.call(arguments, 1);
|
|
listeners = handler.slice();
|
|
len = listeners.length;
|
|
for (i = 0; i < len; i++)
|
|
listeners[i].apply(this, args);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
EventEmitter.prototype.addListener = function(type, listener) {
|
|
var m;
|
|
|
|
if (!isFunction(listener))
|
|
throw TypeError('listener must be a function');
|
|
|
|
if (!this._events)
|
|
this._events = {};
|
|
|
|
// To avoid recursion in the case that type === "newListener"! Before
|
|
// adding it to the listeners, first emit "newListener".
|
|
if (this._events.newListener)
|
|
this.emit('newListener', type,
|
|
isFunction(listener.listener) ?
|
|
listener.listener : listener);
|
|
|
|
if (!this._events[type])
|
|
// Optimize the case of one listener. Don't need the extra array object.
|
|
this._events[type] = listener;
|
|
else if (isObject(this._events[type]))
|
|
// If we've already got an array, just append.
|
|
this._events[type].push(listener);
|
|
else
|
|
// Adding the second element, need to change to array.
|
|
this._events[type] = [this._events[type], listener];
|
|
|
|
// Check for listener leak
|
|
if (isObject(this._events[type]) && !this._events[type].warned) {
|
|
if (!isUndefined(this._maxListeners)) {
|
|
m = this._maxListeners;
|
|
} else {
|
|
m = EventEmitter.defaultMaxListeners;
|
|
}
|
|
|
|
if (m && m > 0 && this._events[type].length > m) {
|
|
this._events[type].warned = true;
|
|
console.error('(node) warning: possible EventEmitter memory ' +
|
|
'leak detected. %d listeners added. ' +
|
|
'Use emitter.setMaxListeners() to increase limit.',
|
|
this._events[type].length);
|
|
if (typeof console.trace === 'function') {
|
|
// not supported in IE 10
|
|
console.trace();
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|
|
|
EventEmitter.prototype.once = function(type, listener) {
|
|
if (!isFunction(listener))
|
|
throw TypeError('listener must be a function');
|
|
|
|
var fired = false;
|
|
|
|
function g() {
|
|
this.removeListener(type, g);
|
|
|
|
if (!fired) {
|
|
fired = true;
|
|
listener.apply(this, arguments);
|
|
}
|
|
}
|
|
|
|
g.listener = listener;
|
|
this.on(type, g);
|
|
|
|
return this;
|
|
};
|
|
|
|
// emits a 'removeListener' event iff the listener was removed
|
|
EventEmitter.prototype.removeListener = function(type, listener) {
|
|
var list, position, length, i;
|
|
|
|
if (!isFunction(listener))
|
|
throw TypeError('listener must be a function');
|
|
|
|
if (!this._events || !this._events[type])
|
|
return this;
|
|
|
|
list = this._events[type];
|
|
length = list.length;
|
|
position = -1;
|
|
|
|
if (list === listener ||
|
|
(isFunction(list.listener) && list.listener === listener)) {
|
|
delete this._events[type];
|
|
if (this._events.removeListener)
|
|
this.emit('removeListener', type, listener);
|
|
|
|
} else if (isObject(list)) {
|
|
for (i = length; i-- > 0;) {
|
|
if (list[i] === listener ||
|
|
(list[i].listener && list[i].listener === listener)) {
|
|
position = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (position < 0)
|
|
return this;
|
|
|
|
if (list.length === 1) {
|
|
list.length = 0;
|
|
delete this._events[type];
|
|
} else {
|
|
list.splice(position, 1);
|
|
}
|
|
|
|
if (this._events.removeListener)
|
|
this.emit('removeListener', type, listener);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.removeAllListeners = function(type) {
|
|
var key, listeners;
|
|
|
|
if (!this._events)
|
|
return this;
|
|
|
|
// not listening for removeListener, no need to emit
|
|
if (!this._events.removeListener) {
|
|
if (arguments.length === 0)
|
|
this._events = {};
|
|
else if (this._events[type])
|
|
delete this._events[type];
|
|
return this;
|
|
}
|
|
|
|
// emit removeListener for all listeners on all events
|
|
if (arguments.length === 0) {
|
|
for (key in this._events) {
|
|
if (key === 'removeListener') continue;
|
|
this.removeAllListeners(key);
|
|
}
|
|
this.removeAllListeners('removeListener');
|
|
this._events = {};
|
|
return this;
|
|
}
|
|
|
|
listeners = this._events[type];
|
|
|
|
if (isFunction(listeners)) {
|
|
this.removeListener(type, listeners);
|
|
} else if (listeners) {
|
|
// LIFO order
|
|
while (listeners.length)
|
|
this.removeListener(type, listeners[listeners.length - 1]);
|
|
}
|
|
delete this._events[type];
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.listeners = function(type) {
|
|
var ret;
|
|
if (!this._events || !this._events[type])
|
|
ret = [];
|
|
else if (isFunction(this._events[type]))
|
|
ret = [this._events[type]];
|
|
else
|
|
ret = this._events[type].slice();
|
|
return ret;
|
|
};
|
|
|
|
EventEmitter.prototype.listenerCount = function(type) {
|
|
if (this._events) {
|
|
var evlistener = this._events[type];
|
|
|
|
if (isFunction(evlistener))
|
|
return 1;
|
|
else if (evlistener)
|
|
return evlistener.length;
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
EventEmitter.listenerCount = function(emitter, type) {
|
|
return emitter.listenerCount(type);
|
|
};
|
|
|
|
function isFunction(arg) {
|
|
return typeof arg === 'function';
|
|
}
|
|
|
|
function isNumber(arg) {
|
|
return typeof arg === 'number';
|
|
}
|
|
|
|
function isObject(arg) {
|
|
return typeof arg === 'object' && arg !== null;
|
|
}
|
|
|
|
function isUndefined(arg) {
|
|
return arg === void 0;
|
|
}
|
|
|
|
},{}],246:[function(require,module,exports){
|
|
/*!
|
|
* Determine if an object is a Buffer
|
|
*
|
|
* @author Feross Aboukhadijeh <https://feross.org>
|
|
* @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))
|
|
}
|
|
|
|
},{}],247:[function(require,module,exports){
|
|
// shim for using process in browser
|
|
var process = module.exports = {};
|
|
|
|
// cached from whatever global is present so that test runners that stub it
|
|
// don't break things. But we need to wrap it in a try catch in case it is
|
|
// wrapped in strict mode code which doesn't define any globals. It's inside a
|
|
// function because try/catches deoptimize in certain engines.
|
|
|
|
var cachedSetTimeout;
|
|
var cachedClearTimeout;
|
|
|
|
function defaultSetTimout() {
|
|
throw new Error('setTimeout has not been defined');
|
|
}
|
|
function defaultClearTimeout () {
|
|
throw new Error('clearTimeout has not been defined');
|
|
}
|
|
(function () {
|
|
try {
|
|
if (typeof setTimeout === 'function') {
|
|
cachedSetTimeout = setTimeout;
|
|
} else {
|
|
cachedSetTimeout = defaultSetTimout;
|
|
}
|
|
} catch (e) {
|
|
cachedSetTimeout = defaultSetTimout;
|
|
}
|
|
try {
|
|
if (typeof clearTimeout === 'function') {
|
|
cachedClearTimeout = clearTimeout;
|
|
} else {
|
|
cachedClearTimeout = defaultClearTimeout;
|
|
}
|
|
} catch (e) {
|
|
cachedClearTimeout = defaultClearTimeout;
|
|
}
|
|
} ())
|
|
function runTimeout(fun) {
|
|
if (cachedSetTimeout === setTimeout) {
|
|
//normal enviroments in sane situations
|
|
return setTimeout(fun, 0);
|
|
}
|
|
// if setTimeout wasn't available but was latter defined
|
|
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
|
|
cachedSetTimeout = setTimeout;
|
|
return setTimeout(fun, 0);
|
|
}
|
|
try {
|
|
// when when somebody has screwed with setTimeout but no I.E. maddness
|
|
return cachedSetTimeout(fun, 0);
|
|
} catch(e){
|
|
try {
|
|
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
|
return cachedSetTimeout.call(null, fun, 0);
|
|
} catch(e){
|
|
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
|
|
return cachedSetTimeout.call(this, fun, 0);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
function runClearTimeout(marker) {
|
|
if (cachedClearTimeout === clearTimeout) {
|
|
//normal enviroments in sane situations
|
|
return clearTimeout(marker);
|
|
}
|
|
// if clearTimeout wasn't available but was latter defined
|
|
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
|
|
cachedClearTimeout = clearTimeout;
|
|
return clearTimeout(marker);
|
|
}
|
|
try {
|
|
// when when somebody has screwed with setTimeout but no I.E. maddness
|
|
return cachedClearTimeout(marker);
|
|
} catch (e){
|
|
try {
|
|
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
|
return cachedClearTimeout.call(null, marker);
|
|
} catch (e){
|
|
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
|
|
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
|
|
return cachedClearTimeout.call(this, marker);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
var queue = [];
|
|
var draining = false;
|
|
var currentQueue;
|
|
var queueIndex = -1;
|
|
|
|
function cleanUpNextTick() {
|
|
if (!draining || !currentQueue) {
|
|
return;
|
|
}
|
|
draining = false;
|
|
if (currentQueue.length) {
|
|
queue = currentQueue.concat(queue);
|
|
} else {
|
|
queueIndex = -1;
|
|
}
|
|
if (queue.length) {
|
|
drainQueue();
|
|
}
|
|
}
|
|
|
|
function drainQueue() {
|
|
if (draining) {
|
|
return;
|
|
}
|
|
var timeout = runTimeout(cleanUpNextTick);
|
|
draining = true;
|
|
|
|
var len = queue.length;
|
|
while(len) {
|
|
currentQueue = queue;
|
|
queue = [];
|
|
while (++queueIndex < len) {
|
|
if (currentQueue) {
|
|
currentQueue[queueIndex].run();
|
|
}
|
|
}
|
|
queueIndex = -1;
|
|
len = queue.length;
|
|
}
|
|
currentQueue = null;
|
|
draining = false;
|
|
runClearTimeout(timeout);
|
|
}
|
|
|
|
process.nextTick = function (fun) {
|
|
var args = new Array(arguments.length - 1);
|
|
if (arguments.length > 1) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
args[i - 1] = arguments[i];
|
|
}
|
|
}
|
|
queue.push(new Item(fun, args));
|
|
if (queue.length === 1 && !draining) {
|
|
runTimeout(drainQueue);
|
|
}
|
|
};
|
|
|
|
// v8 likes predictible objects
|
|
function Item(fun, array) {
|
|
this.fun = fun;
|
|
this.array = array;
|
|
}
|
|
Item.prototype.run = function () {
|
|
this.fun.apply(null, this.array);
|
|
};
|
|
process.title = 'browser';
|
|
process.browser = true;
|
|
process.env = {};
|
|
process.argv = [];
|
|
process.version = ''; // empty string to avoid regexp issues
|
|
process.versions = {};
|
|
|
|
function noop() {}
|
|
|
|
process.on = noop;
|
|
process.addListener = noop;
|
|
process.once = noop;
|
|
process.off = noop;
|
|
process.removeListener = noop;
|
|
process.removeAllListeners = noop;
|
|
process.emit = noop;
|
|
process.prependListener = noop;
|
|
process.prependOnceListener = noop;
|
|
|
|
process.listeners = function (name) { return [] }
|
|
|
|
process.binding = function (name) {
|
|
throw new Error('process.binding is not supported');
|
|
};
|
|
|
|
process.cwd = function () { return '/' };
|
|
process.chdir = function (dir) {
|
|
throw new Error('process.chdir is not supported');
|
|
};
|
|
process.umask = function() { return 0; };
|
|
|
|
},{}],248:[function(require,module,exports){
|
|
(function (global){
|
|
/*! https://mths.be/punycode v1.4.1 by @mathias */
|
|
;(function(root) {
|
|
|
|
/** Detect free variables */
|
|
var freeExports = typeof exports == 'object' && exports &&
|
|
!exports.nodeType && exports;
|
|
var freeModule = typeof module == 'object' && module &&
|
|
!module.nodeType && module;
|
|
var freeGlobal = typeof global == 'object' && global;
|
|
if (
|
|
freeGlobal.global === freeGlobal ||
|
|
freeGlobal.window === freeGlobal ||
|
|
freeGlobal.self === freeGlobal
|
|
) {
|
|
root = freeGlobal;
|
|
}
|
|
|
|
/**
|
|
* The `punycode` object.
|
|
* @name punycode
|
|
* @type Object
|
|
*/
|
|
var punycode,
|
|
|
|
/** Highest positive signed 32-bit float value */
|
|
maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
|
|
|
|
/** Bootstring parameters */
|
|
base = 36,
|
|
tMin = 1,
|
|
tMax = 26,
|
|
skew = 38,
|
|
damp = 700,
|
|
initialBias = 72,
|
|
initialN = 128, // 0x80
|
|
delimiter = '-', // '\x2D'
|
|
|
|
/** Regular expressions */
|
|
regexPunycode = /^xn--/,
|
|
regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
|
|
regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
|
|
|
|
/** Error messages */
|
|
errors = {
|
|
'overflow': 'Overflow: input needs wider integers to process',
|
|
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
|
|
'invalid-input': 'Invalid input'
|
|
},
|
|
|
|
/** Convenience shortcuts */
|
|
baseMinusTMin = base - tMin,
|
|
floor = Math.floor,
|
|
stringFromCharCode = String.fromCharCode,
|
|
|
|
/** Temporary variable */
|
|
key;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* A generic error utility function.
|
|
* @private
|
|
* @param {String} type The error type.
|
|
* @returns {Error} Throws a `RangeError` with the applicable error message.
|
|
*/
|
|
function error(type) {
|
|
throw new RangeError(errors[type]);
|
|
}
|
|
|
|
/**
|
|
* A generic `Array#map` utility function.
|
|
* @private
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} callback The function that gets called for every array
|
|
* item.
|
|
* @returns {Array} A new array of values returned by the callback function.
|
|
*/
|
|
function map(array, fn) {
|
|
var length = array.length;
|
|
var result = [];
|
|
while (length--) {
|
|
result[length] = fn(array[length]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A simple `Array#map`-like wrapper to work with domain name strings or email
|
|
* addresses.
|
|
* @private
|
|
* @param {String} domain The domain name or email address.
|
|
* @param {Function} callback The function that gets called for every
|
|
* character.
|
|
* @returns {Array} A new string of characters returned by the callback
|
|
* function.
|
|
*/
|
|
function mapDomain(string, fn) {
|
|
var parts = string.split('@');
|
|
var result = '';
|
|
if (parts.length > 1) {
|
|
// In email addresses, only the domain name should be punycoded. Leave
|
|
// the local part (i.e. everything up to `@`) intact.
|
|
result = parts[0] + '@';
|
|
string = parts[1];
|
|
}
|
|
// Avoid `split(regex)` for IE8 compatibility. See #17.
|
|
string = string.replace(regexSeparators, '\x2E');
|
|
var labels = string.split('.');
|
|
var encoded = map(labels, fn).join('.');
|
|
return result + encoded;
|
|
}
|
|
|
|
/**
|
|
* Creates an array containing the numeric code points of each Unicode
|
|
* character in the string. While JavaScript uses UCS-2 internally,
|
|
* this function will convert a pair of surrogate halves (each of which
|
|
* UCS-2 exposes as separate characters) into a single code point,
|
|
* matching UTF-16.
|
|
* @see `punycode.ucs2.encode`
|
|
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
|
* @memberOf punycode.ucs2
|
|
* @name decode
|
|
* @param {String} string The Unicode input string (UCS-2).
|
|
* @returns {Array} The new array of code points.
|
|
*/
|
|
function ucs2decode(string) {
|
|
var output = [],
|
|
counter = 0,
|
|
length = string.length,
|
|
value,
|
|
extra;
|
|
while (counter < length) {
|
|
value = string.charCodeAt(counter++);
|
|
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
|
|
// high surrogate, and there is a next character
|
|
extra = string.charCodeAt(counter++);
|
|
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
|
|
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
|
|
} else {
|
|
// unmatched surrogate; only append this code unit, in case the next
|
|
// code unit is the high surrogate of a surrogate pair
|
|
output.push(value);
|
|
counter--;
|
|
}
|
|
} else {
|
|
output.push(value);
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
/**
|
|
* Creates a string based on an array of numeric code points.
|
|
* @see `punycode.ucs2.decode`
|
|
* @memberOf punycode.ucs2
|
|
* @name encode
|
|
* @param {Array} codePoints The array of numeric code points.
|
|
* @returns {String} The new Unicode string (UCS-2).
|
|
*/
|
|
function ucs2encode(array) {
|
|
return map(array, function(value) {
|
|
var output = '';
|
|
if (value > 0xFFFF) {
|
|
value -= 0x10000;
|
|
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
|
|
value = 0xDC00 | value & 0x3FF;
|
|
}
|
|
output += stringFromCharCode(value);
|
|
return output;
|
|
}).join('');
|
|
}
|
|
|
|
/**
|
|
* Converts a basic code point into a digit/integer.
|
|
* @see `digitToBasic()`
|
|
* @private
|
|
* @param {Number} codePoint The basic numeric code point value.
|
|
* @returns {Number} The numeric value of a basic code point (for use in
|
|
* representing integers) in the range `0` to `base - 1`, or `base` if
|
|
* the code point does not represent a value.
|
|
*/
|
|
function basicToDigit(codePoint) {
|
|
if (codePoint - 48 < 10) {
|
|
return codePoint - 22;
|
|
}
|
|
if (codePoint - 65 < 26) {
|
|
return codePoint - 65;
|
|
}
|
|
if (codePoint - 97 < 26) {
|
|
return codePoint - 97;
|
|
}
|
|
return base;
|
|
}
|
|
|
|
/**
|
|
* Converts a digit/integer into a basic code point.
|
|
* @see `basicToDigit()`
|
|
* @private
|
|
* @param {Number} digit The numeric value of a basic code point.
|
|
* @returns {Number} The basic code point whose value (when used for
|
|
* representing integers) is `digit`, which needs to be in the range
|
|
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
|
|
* used; else, the lowercase form is used. The behavior is undefined
|
|
* if `flag` is non-zero and `digit` has no uppercase form.
|
|
*/
|
|
function digitToBasic(digit, flag) {
|
|
// 0..25 map to ASCII a..z or A..Z
|
|
// 26..35 map to ASCII 0..9
|
|
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
|
|
}
|
|
|
|
/**
|
|
* Bias adaptation function as per section 3.4 of RFC 3492.
|
|
* https://tools.ietf.org/html/rfc3492#section-3.4
|
|
* @private
|
|
*/
|
|
function adapt(delta, numPoints, firstTime) {
|
|
var k = 0;
|
|
delta = firstTime ? floor(delta / damp) : delta >> 1;
|
|
delta += floor(delta / numPoints);
|
|
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
|
|
delta = floor(delta / baseMinusTMin);
|
|
}
|
|
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
|
|
}
|
|
|
|
/**
|
|
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
|
|
* symbols.
|
|
* @memberOf punycode
|
|
* @param {String} input The Punycode string of ASCII-only symbols.
|
|
* @returns {String} The resulting string of Unicode symbols.
|
|
*/
|
|
function decode(input) {
|
|
// Don't use UCS-2
|
|
var output = [],
|
|
inputLength = input.length,
|
|
out,
|
|
i = 0,
|
|
n = initialN,
|
|
bias = initialBias,
|
|
basic,
|
|
j,
|
|
index,
|
|
oldi,
|
|
w,
|
|
k,
|
|
digit,
|
|
t,
|
|
/** Cached calculation results */
|
|
baseMinusT;
|
|
|
|
// Handle the basic code points: let `basic` be the number of input code
|
|
// points before the last delimiter, or `0` if there is none, then copy
|
|
// the first basic code points to the output.
|
|
|
|
basic = input.lastIndexOf(delimiter);
|
|
if (basic < 0) {
|
|
basic = 0;
|
|
}
|
|
|
|
for (j = 0; j < basic; ++j) {
|
|
// if it's not a basic code point
|
|
if (input.charCodeAt(j) >= 0x80) {
|
|
error('not-basic');
|
|
}
|
|
output.push(input.charCodeAt(j));
|
|
}
|
|
|
|
// Main decoding loop: start just after the last delimiter if any basic code
|
|
// points were copied; start at the beginning otherwise.
|
|
|
|
for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
|
|
|
|
// `index` is the index of the next character to be consumed.
|
|
// Decode a generalized variable-length integer into `delta`,
|
|
// which gets added to `i`. The overflow checking is easier
|
|
// if we increase `i` as we go, then subtract off its starting
|
|
// value at the end to obtain `delta`.
|
|
for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
|
|
|
|
if (index >= inputLength) {
|
|
error('invalid-input');
|
|
}
|
|
|
|
digit = basicToDigit(input.charCodeAt(index++));
|
|
|
|
if (digit >= base || digit > floor((maxInt - i) / w)) {
|
|
error('overflow');
|
|
}
|
|
|
|
i += digit * w;
|
|
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
|
|
|
|
if (digit < t) {
|
|
break;
|
|
}
|
|
|
|
baseMinusT = base - t;
|
|
if (w > floor(maxInt / baseMinusT)) {
|
|
error('overflow');
|
|
}
|
|
|
|
w *= baseMinusT;
|
|
|
|
}
|
|
|
|
out = output.length + 1;
|
|
bias = adapt(i - oldi, out, oldi == 0);
|
|
|
|
// `i` was supposed to wrap around from `out` to `0`,
|
|
// incrementing `n` each time, so we'll fix that now:
|
|
if (floor(i / out) > maxInt - n) {
|
|
error('overflow');
|
|
}
|
|
|
|
n += floor(i / out);
|
|
i %= out;
|
|
|
|
// Insert `n` at position `i` of the output
|
|
output.splice(i++, 0, n);
|
|
|
|
}
|
|
|
|
return ucs2encode(output);
|
|
}
|
|
|
|
/**
|
|
* Converts a string of Unicode symbols (e.g. a domain name label) to a
|
|
* Punycode string of ASCII-only symbols.
|
|
* @memberOf punycode
|
|
* @param {String} input The string of Unicode symbols.
|
|
* @returns {String} The resulting Punycode string of ASCII-only symbols.
|
|
*/
|
|
function encode(input) {
|
|
var n,
|
|
delta,
|
|
handledCPCount,
|
|
basicLength,
|
|
bias,
|
|
j,
|
|
m,
|
|
q,
|
|
k,
|
|
t,
|
|
currentValue,
|
|
output = [],
|
|
/** `inputLength` will hold the number of code points in `input`. */
|
|
inputLength,
|
|
/** Cached calculation results */
|
|
handledCPCountPlusOne,
|
|
baseMinusT,
|
|
qMinusT;
|
|
|
|
// Convert the input in UCS-2 to Unicode
|
|
input = ucs2decode(input);
|
|
|
|
// Cache the length
|
|
inputLength = input.length;
|
|
|
|
// Initialize the state
|
|
n = initialN;
|
|
delta = 0;
|
|
bias = initialBias;
|
|
|
|
// Handle the basic code points
|
|
for (j = 0; j < inputLength; ++j) {
|
|
currentValue = input[j];
|
|
if (currentValue < 0x80) {
|
|
output.push(stringFromCharCode(currentValue));
|
|
}
|
|
}
|
|
|
|
handledCPCount = basicLength = output.length;
|
|
|
|
// `handledCPCount` is the number of code points that have been handled;
|
|
// `basicLength` is the number of basic code points.
|
|
|
|
// Finish the basic string - if it is not empty - with a delimiter
|
|
if (basicLength) {
|
|
output.push(delimiter);
|
|
}
|
|
|
|
// Main encoding loop:
|
|
while (handledCPCount < inputLength) {
|
|
|
|
// All non-basic code points < n have been handled already. Find the next
|
|
// larger one:
|
|
for (m = maxInt, j = 0; j < inputLength; ++j) {
|
|
currentValue = input[j];
|
|
if (currentValue >= n && currentValue < m) {
|
|
m = currentValue;
|
|
}
|
|
}
|
|
|
|
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
|
|
// but guard against overflow
|
|
handledCPCountPlusOne = handledCPCount + 1;
|
|
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
|
|
error('overflow');
|
|
}
|
|
|
|
delta += (m - n) * handledCPCountPlusOne;
|
|
n = m;
|
|
|
|
for (j = 0; j < inputLength; ++j) {
|
|
currentValue = input[j];
|
|
|
|
if (currentValue < n && ++delta > maxInt) {
|
|
error('overflow');
|
|
}
|
|
|
|
if (currentValue == n) {
|
|
// Represent delta as a generalized variable-length integer
|
|
for (q = delta, k = base; /* no condition */; k += base) {
|
|
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
|
|
if (q < t) {
|
|
break;
|
|
}
|
|
qMinusT = q - t;
|
|
baseMinusT = base - t;
|
|
output.push(
|
|
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
|
|
);
|
|
q = floor(qMinusT / baseMinusT);
|
|
}
|
|
|
|
output.push(stringFromCharCode(digitToBasic(q, 0)));
|
|
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
|
|
delta = 0;
|
|
++handledCPCount;
|
|
}
|
|
}
|
|
|
|
++delta;
|
|
++n;
|
|
|
|
}
|
|
return output.join('');
|
|
}
|
|
|
|
/**
|
|
* Converts a Punycode string representing a domain name or an email address
|
|
* to Unicode. Only the Punycoded parts of the input will be converted, i.e.
|
|
* it doesn't matter if you call it on a string that has already been
|
|
* converted to Unicode.
|
|
* @memberOf punycode
|
|
* @param {String} input The Punycoded domain name or email address to
|
|
* convert to Unicode.
|
|
* @returns {String} The Unicode representation of the given Punycode
|
|
* string.
|
|
*/
|
|
function toUnicode(input) {
|
|
return mapDomain(input, function(string) {
|
|
return regexPunycode.test(string)
|
|
? decode(string.slice(4).toLowerCase())
|
|
: string;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Converts a Unicode string representing a domain name or an email address to
|
|
* Punycode. Only the non-ASCII parts of the domain name will be converted,
|
|
* i.e. it doesn't matter if you call it with a domain that's already in
|
|
* ASCII.
|
|
* @memberOf punycode
|
|
* @param {String} input The domain name or email address to convert, as a
|
|
* Unicode string.
|
|
* @returns {String} The Punycode representation of the given domain name or
|
|
* email address.
|
|
*/
|
|
function toASCII(input) {
|
|
return mapDomain(input, function(string) {
|
|
return regexNonASCII.test(string)
|
|
? 'xn--' + encode(string)
|
|
: string;
|
|
});
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/** Define the public API */
|
|
punycode = {
|
|
/**
|
|
* A string representing the current Punycode.js version number.
|
|
* @memberOf punycode
|
|
* @type String
|
|
*/
|
|
'version': '1.4.1',
|
|
/**
|
|
* An object of methods to convert from JavaScript's internal character
|
|
* representation (UCS-2) to Unicode code points, and back.
|
|
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
|
* @memberOf punycode
|
|
* @type Object
|
|
*/
|
|
'ucs2': {
|
|
'decode': ucs2decode,
|
|
'encode': ucs2encode
|
|
},
|
|
'decode': decode,
|
|
'encode': encode,
|
|
'toASCII': toASCII,
|
|
'toUnicode': toUnicode
|
|
};
|
|
|
|
/** Expose `punycode` */
|
|
// Some AMD build optimizers, like r.js, check for specific condition patterns
|
|
// like the following:
|
|
if (
|
|
typeof define == 'function' &&
|
|
typeof define.amd == 'object' &&
|
|
define.amd
|
|
) {
|
|
define('punycode', function() {
|
|
return punycode;
|
|
});
|
|
} else if (freeExports && freeModule) {
|
|
if (module.exports == freeExports) {
|
|
// in Node.js, io.js, or RingoJS v0.8.0+
|
|
freeModule.exports = punycode;
|
|
} else {
|
|
// in Narwhal or RingoJS v0.7.0-
|
|
for (key in punycode) {
|
|
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
|
|
}
|
|
}
|
|
} else {
|
|
// in Rhino or a web browser
|
|
root.punycode = punycode;
|
|
}
|
|
|
|
}(this));
|
|
|
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{}],249:[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.
|
|
|
|
'use strict';
|
|
|
|
// If obj.hasOwnProperty has been overridden, then calling
|
|
// obj.hasOwnProperty(prop) will break.
|
|
// See: https://github.com/joyent/node/issues/1707
|
|
function hasOwnProperty(obj, prop) {
|
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
}
|
|
|
|
module.exports = function(qs, sep, eq, options) {
|
|
sep = sep || '&';
|
|
eq = eq || '=';
|
|
var obj = {};
|
|
|
|
if (typeof qs !== 'string' || qs.length === 0) {
|
|
return obj;
|
|
}
|
|
|
|
var regexp = /\+/g;
|
|
qs = qs.split(sep);
|
|
|
|
var maxKeys = 1000;
|
|
if (options && typeof options.maxKeys === 'number') {
|
|
maxKeys = options.maxKeys;
|
|
}
|
|
|
|
var len = qs.length;
|
|
// maxKeys <= 0 means that we should not limit keys count
|
|
if (maxKeys > 0 && len > maxKeys) {
|
|
len = maxKeys;
|
|
}
|
|
|
|
for (var i = 0; i < len; ++i) {
|
|
var x = qs[i].replace(regexp, '%20'),
|
|
idx = x.indexOf(eq),
|
|
kstr, vstr, k, v;
|
|
|
|
if (idx >= 0) {
|
|
kstr = x.substr(0, idx);
|
|
vstr = x.substr(idx + 1);
|
|
} else {
|
|
kstr = x;
|
|
vstr = '';
|
|
}
|
|
|
|
k = decodeURIComponent(kstr);
|
|
v = decodeURIComponent(vstr);
|
|
|
|
if (!hasOwnProperty(obj, k)) {
|
|
obj[k] = v;
|
|
} else if (isArray(obj[k])) {
|
|
obj[k].push(v);
|
|
} else {
|
|
obj[k] = [obj[k], v];
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
};
|
|
|
|
var isArray = Array.isArray || function (xs) {
|
|
return Object.prototype.toString.call(xs) === '[object Array]';
|
|
};
|
|
|
|
},{}],250:[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.
|
|
|
|
'use strict';
|
|
|
|
var stringifyPrimitive = function(v) {
|
|
switch (typeof v) {
|
|
case 'string':
|
|
return v;
|
|
|
|
case 'boolean':
|
|
return v ? 'true' : 'false';
|
|
|
|
case 'number':
|
|
return isFinite(v) ? v : '';
|
|
|
|
default:
|
|
return '';
|
|
}
|
|
};
|
|
|
|
module.exports = function(obj, sep, eq, name) {
|
|
sep = sep || '&';
|
|
eq = eq || '=';
|
|
if (obj === null) {
|
|
obj = undefined;
|
|
}
|
|
|
|
if (typeof obj === 'object') {
|
|
return map(objectKeys(obj), function(k) {
|
|
var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
|
|
if (isArray(obj[k])) {
|
|
return map(obj[k], function(v) {
|
|
return ks + encodeURIComponent(stringifyPrimitive(v));
|
|
}).join(sep);
|
|
} else {
|
|
return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
|
|
}
|
|
}).join(sep);
|
|
|
|
}
|
|
|
|
if (!name) return '';
|
|
return encodeURIComponent(stringifyPrimitive(name)) + eq +
|
|
encodeURIComponent(stringifyPrimitive(obj));
|
|
};
|
|
|
|
var isArray = Array.isArray || function (xs) {
|
|
return Object.prototype.toString.call(xs) === '[object Array]';
|
|
};
|
|
|
|
function map (xs, f) {
|
|
if (xs.map) return xs.map(f);
|
|
var res = [];
|
|
for (var i = 0; i < xs.length; i++) {
|
|
res.push(f(xs[i], i));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
var objectKeys = Object.keys || function (obj) {
|
|
var res = [];
|
|
for (var key in obj) {
|
|
if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
},{}],251:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
exports.decode = exports.parse = require('./decode');
|
|
exports.encode = exports.stringify = require('./encode');
|
|
|
|
},{"./decode":249,"./encode":250}],252:[function(require,module,exports){
|
|
module.exports = require('./lib/_stream_duplex.js');
|
|
|
|
},{"./lib/_stream_duplex.js":253}],253:[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 duplex stream is just a stream that is both readable and writable.
|
|
// Since JS doesn't have multiple prototypal inheritance, this class
|
|
// prototypally inherits from Readable, and then parasitically from
|
|
// Writable.
|
|
|
|
'use strict';
|
|
|
|
/*<replacement>*/
|
|
|
|
var processNextTick = require('process-nextick-args');
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
var objectKeys = Object.keys || function (obj) {
|
|
var keys = [];
|
|
for (var key in obj) {
|
|
keys.push(key);
|
|
}return keys;
|
|
};
|
|
/*</replacement>*/
|
|
|
|
module.exports = Duplex;
|
|
|
|
/*<replacement>*/
|
|
var util = require('core-util-is');
|
|
util.inherits = require('inherits');
|
|
/*</replacement>*/
|
|
|
|
var Readable = require('./_stream_readable');
|
|
var Writable = require('./_stream_writable');
|
|
|
|
util.inherits(Duplex, Readable);
|
|
|
|
var keys = objectKeys(Writable.prototype);
|
|
for (var v = 0; v < keys.length; v++) {
|
|
var method = keys[v];
|
|
if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
|
|
}
|
|
|
|
function Duplex(options) {
|
|
if (!(this instanceof Duplex)) return new Duplex(options);
|
|
|
|
Readable.call(this, options);
|
|
Writable.call(this, options);
|
|
|
|
if (options && options.readable === false) this.readable = false;
|
|
|
|
if (options && options.writable === false) this.writable = false;
|
|
|
|
this.allowHalfOpen = true;
|
|
if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
|
|
|
|
this.once('end', onend);
|
|
}
|
|
|
|
// the no-half-open enforcer
|
|
function onend() {
|
|
// if we allow half-open state, or if the writable side ended,
|
|
// then we're ok.
|
|
if (this.allowHalfOpen || this._writableState.ended) return;
|
|
|
|
// no more data can be written.
|
|
// But allow more writes to happen in this tick.
|
|
processNextTick(onEndNT, this);
|
|
}
|
|
|
|
function onEndNT(self) {
|
|
self.end();
|
|
}
|
|
|
|
Object.defineProperty(Duplex.prototype, 'destroyed', {
|
|
get: function () {
|
|
if (this._readableState === undefined || this._writableState === undefined) {
|
|
return false;
|
|
}
|
|
return this._readableState.destroyed && this._writableState.destroyed;
|
|
},
|
|
set: function (value) {
|
|
// we ignore the value if the stream
|
|
// has not been initialized yet
|
|
if (this._readableState === undefined || this._writableState === undefined) {
|
|
return;
|
|
}
|
|
|
|
// backward compatibility, the user is explicitly
|
|
// managing destroyed
|
|
this._readableState.destroyed = value;
|
|
this._writableState.destroyed = value;
|
|
}
|
|
});
|
|
|
|
Duplex.prototype._destroy = function (err, cb) {
|
|
this.push(null);
|
|
this.end();
|
|
|
|
processNextTick(cb, err);
|
|
};
|
|
|
|
function forEach(xs, f) {
|
|
for (var i = 0, l = xs.length; i < l; i++) {
|
|
f(xs[i], i);
|
|
}
|
|
}
|
|
},{"./_stream_readable":255,"./_stream_writable":257,"core-util-is":261,"inherits":262,"process-nextick-args":264}],254:[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 passthrough stream.
|
|
// basically just the most minimal sort of Transform stream.
|
|
// Every written chunk gets output as-is.
|
|
|
|
'use strict';
|
|
|
|
module.exports = PassThrough;
|
|
|
|
var Transform = require('./_stream_transform');
|
|
|
|
/*<replacement>*/
|
|
var util = require('core-util-is');
|
|
util.inherits = require('inherits');
|
|
/*</replacement>*/
|
|
|
|
util.inherits(PassThrough, Transform);
|
|
|
|
function PassThrough(options) {
|
|
if (!(this instanceof PassThrough)) return new PassThrough(options);
|
|
|
|
Transform.call(this, options);
|
|
}
|
|
|
|
PassThrough.prototype._transform = function (chunk, encoding, cb) {
|
|
cb(null, chunk);
|
|
};
|
|
},{"./_stream_transform":256,"core-util-is":261,"inherits":262}],255:[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.
|
|
|
|
'use strict';
|
|
|
|
/*<replacement>*/
|
|
|
|
var processNextTick = require('process-nextick-args');
|
|
/*</replacement>*/
|
|
|
|
module.exports = Readable;
|
|
|
|
/*<replacement>*/
|
|
var isArray = require('isarray');
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
var Duplex;
|
|
/*</replacement>*/
|
|
|
|
Readable.ReadableState = ReadableState;
|
|
|
|
/*<replacement>*/
|
|
var EE = require('events').EventEmitter;
|
|
|
|
var EElistenerCount = function (emitter, type) {
|
|
return emitter.listeners(type).length;
|
|
};
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
var Stream = require('./internal/streams/stream');
|
|
/*</replacement>*/
|
|
|
|
// TODO(bmeurer): Change this back to const once hole checks are
|
|
// properly optimized away early in Ignition+TurboFan.
|
|
/*<replacement>*/
|
|
var Buffer = require('safe-buffer').Buffer;
|
|
var OurUint8Array = global.Uint8Array || function () {};
|
|
function _uint8ArrayToBuffer(chunk) {
|
|
return Buffer.from(chunk);
|
|
}
|
|
function _isUint8Array(obj) {
|
|
return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
|
|
}
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
var util = require('core-util-is');
|
|
util.inherits = require('inherits');
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
var debugUtil = require('util');
|
|
var debug = void 0;
|
|
if (debugUtil && debugUtil.debuglog) {
|
|
debug = debugUtil.debuglog('stream');
|
|
} else {
|
|
debug = function () {};
|
|
}
|
|
/*</replacement>*/
|
|
|
|
var BufferList = require('./internal/streams/BufferList');
|
|
var destroyImpl = require('./internal/streams/destroy');
|
|
var StringDecoder;
|
|
|
|
util.inherits(Readable, Stream);
|
|
|
|
var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume'];
|
|
|
|
function prependListener(emitter, event, fn) {
|
|
// Sadly this is not cacheable as some libraries bundle their own
|
|
// event emitter implementation with them.
|
|
if (typeof emitter.prependListener === 'function') {
|
|
return emitter.prependListener(event, fn);
|
|
} else {
|
|
// This is a hack to make sure that our error handler is attached before any
|
|
// userland ones. NEVER DO THIS. This is here only because this code needs
|
|
// to continue to work with older versions of Node.js that do not include
|
|
// the prependListener() method. The goal is to eventually remove this hack.
|
|
if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]];
|
|
}
|
|
}
|
|
|
|
function ReadableState(options, stream) {
|
|
Duplex = Duplex || require('./_stream_duplex');
|
|
|
|
options = options || {};
|
|
|
|
// 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;
|
|
|
|
// 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 = this.objectMode ? 16 : 16 * 1024;
|
|
this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
|
|
|
|
// cast to ints.
|
|
this.highWaterMark = Math.floor(this.highWaterMark);
|
|
|
|
// A linked list is used to store data chunks instead of an array because the
|
|
// linked list can remove elements from the beginning faster than
|
|
// array.shift()
|
|
this.buffer = new BufferList();
|
|
this.length = 0;
|
|
this.pipes = null;
|
|
this.pipesCount = 0;
|
|
this.flowing = null;
|
|
this.ended = false;
|
|
this.endEmitted = false;
|
|
this.reading = false;
|
|
|
|
// a flag to be able to tell if the event 'readable'/'data' is emitted
|
|
// immediately, or on a later tick. We set this to true at first, because
|
|
// any actions that shouldn't happen until "later" should generally also
|
|
// not happen before the first read call.
|
|
this.sync = true;
|
|
|
|
// whenever we return null, then we set a flag to say
|
|
// that we're awaiting a 'readable' event emission.
|
|
this.needReadable = false;
|
|
this.emittedReadable = false;
|
|
this.readableListening = false;
|
|
this.resumeScheduled = false;
|
|
|
|
// has it been destroyed
|
|
this.destroyed = false;
|
|
|
|
// Crypto is kind of old and crusty. Historically, its default string
|
|
// encoding is 'binary' so we have to make this configurable.
|
|
// Everything else in the universe uses 'utf8', though.
|
|
this.defaultEncoding = options.defaultEncoding || 'utf8';
|
|
|
|
// the number of writers that are awaiting a drain event in .pipe()s
|
|
this.awaitDrain = 0;
|
|
|
|
// if true, a maybeReadMore has been scheduled
|
|
this.readingMore = false;
|
|
|
|
this.decoder = null;
|
|
this.encoding = null;
|
|
if (options.encoding) {
|
|
if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
|
|
this.decoder = new StringDecoder(options.encoding);
|
|
this.encoding = options.encoding;
|
|
}
|
|
}
|
|
|
|
function Readable(options) {
|
|
Duplex = Duplex || require('./_stream_duplex');
|
|
|
|
if (!(this instanceof Readable)) return new Readable(options);
|
|
|
|
this._readableState = new ReadableState(options, this);
|
|
|
|
// legacy
|
|
this.readable = true;
|
|
|
|
if (options) {
|
|
if (typeof options.read === 'function') this._read = options.read;
|
|
|
|
if (typeof options.destroy === 'function') this._destroy = options.destroy;
|
|
}
|
|
|
|
Stream.call(this);
|
|
}
|
|
|
|
Object.defineProperty(Readable.prototype, 'destroyed', {
|
|
get: function () {
|
|
if (this._readableState === undefined) {
|
|
return false;
|
|
}
|
|
return this._readableState.destroyed;
|
|
},
|
|
set: function (value) {
|
|
// we ignore the value if the stream
|
|
// has not been initialized yet
|
|
if (!this._readableState) {
|
|
return;
|
|
}
|
|
|
|
// backward compatibility, the user is explicitly
|
|
// managing destroyed
|
|
this._readableState.destroyed = value;
|
|
}
|
|
});
|
|
|
|
Readable.prototype.destroy = destroyImpl.destroy;
|
|
Readable.prototype._undestroy = destroyImpl.undestroy;
|
|
Readable.prototype._destroy = function (err, cb) {
|
|
this.push(null);
|
|
cb(err);
|
|
};
|
|
|
|
// Manually shove something into the read() buffer.
|
|
// This returns true if the highWaterMark has not been hit yet,
|
|
// similar to how Writable.write() returns true if you should
|
|
// write() some more.
|
|
Readable.prototype.push = function (chunk, encoding) {
|
|
var state = this._readableState;
|
|
var skipChunkCheck;
|
|
|
|
if (!state.objectMode) {
|
|
if (typeof chunk === 'string') {
|
|
encoding = encoding || state.defaultEncoding;
|
|
if (encoding !== state.encoding) {
|
|
chunk = Buffer.from(chunk, encoding);
|
|
encoding = '';
|
|
}
|
|
skipChunkCheck = true;
|
|
}
|
|
} else {
|
|
skipChunkCheck = true;
|
|
}
|
|
|
|
return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
|
|
};
|
|
|
|
// Unshift should *always* be something directly out of read()
|
|
Readable.prototype.unshift = function (chunk) {
|
|
return readableAddChunk(this, chunk, null, true, false);
|
|
};
|
|
|
|
function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
|
|
var state = stream._readableState;
|
|
if (chunk === null) {
|
|
state.reading = false;
|
|
onEofChunk(stream, state);
|
|
} else {
|
|
var er;
|
|
if (!skipChunkCheck) er = chunkInvalid(state, chunk);
|
|
if (er) {
|
|
stream.emit('error', er);
|
|
} else if (state.objectMode || chunk && chunk.length > 0) {
|
|
if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) {
|
|
chunk = _uint8ArrayToBuffer(chunk);
|
|
}
|
|
|
|
if (addToFront) {
|
|
if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true);
|
|
} else if (state.ended) {
|
|
stream.emit('error', new Error('stream.push() after EOF'));
|
|
} else {
|
|
state.reading = false;
|
|
if (state.decoder && !encoding) {
|
|
chunk = state.decoder.write(chunk);
|
|
if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state);
|
|
} else {
|
|
addChunk(stream, state, chunk, false);
|
|
}
|
|
}
|
|
} else if (!addToFront) {
|
|
state.reading = false;
|
|
}
|
|
}
|
|
|
|
return needMoreData(state);
|
|
}
|
|
|
|
function addChunk(stream, state, chunk, addToFront) {
|
|
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);
|
|
}
|
|
|
|
function chunkInvalid(state, chunk) {
|
|
var er;
|
|
if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
|
|
er = new TypeError('Invalid non-string/buffer chunk');
|
|
}
|
|
return er;
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
|
|
Readable.prototype.isPaused = function () {
|
|
return this._readableState.flowing === false;
|
|
};
|
|
|
|
// 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 > 8MB
|
|
var MAX_HWM = 0x800000;
|
|
function computeNewHighWaterMark(n) {
|
|
if (n >= MAX_HWM) {
|
|
n = MAX_HWM;
|
|
} else {
|
|
// Get the next highest power of 2 to prevent increasing hwm excessively in
|
|
// tiny amounts
|
|
n--;
|
|
n |= n >>> 1;
|
|
n |= n >>> 2;
|
|
n |= n >>> 4;
|
|
n |= n >>> 8;
|
|
n |= n >>> 16;
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
// This function is designed to be inlinable, so please take care when making
|
|
// changes to the function body.
|
|
function howMuchToRead(n, state) {
|
|
if (n <= 0 || state.length === 0 && state.ended) return 0;
|
|
if (state.objectMode) return 1;
|
|
if (n !== n) {
|
|
// Only flow one buffer at a time
|
|
if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length;
|
|
}
|
|
// If we're asking for more than the current hwm, then raise the hwm.
|
|
if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
|
|
if (n <= state.length) return n;
|
|
// Don't have enough
|
|
if (!state.ended) {
|
|
state.needReadable = true;
|
|
return 0;
|
|
}
|
|
return state.length;
|
|
}
|
|
|
|
// you can override either this method, or the async _read(n) below.
|
|
Readable.prototype.read = function (n) {
|
|
debug('read', n);
|
|
n = parseInt(n, 10);
|
|
var state = this._readableState;
|
|
var nOrig = n;
|
|
|
|
if (n !== 0) state.emittedReadable = false;
|
|
|
|
// if we're doing read(0) to trigger a readable event, but we
|
|
// already have a bunch of data in the buffer, then just trigger
|
|
// the 'readable' event and move on.
|
|
if (n === 0 && state.needReadable && (state.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);
|
|
} else if (doRead) {
|
|
debug('do read');
|
|
state.reading = true;
|
|
state.sync = true;
|
|
// if the length is currently zero, then we *need* a readable event.
|
|
if (state.length === 0) state.needReadable = true;
|
|
// call internal read method
|
|
this._read(state.highWaterMark);
|
|
state.sync = false;
|
|
// If _read pushed data synchronously, then `reading` will be false,
|
|
// and we need to re-evaluate how much data we can return to the user.
|
|
if (!state.reading) n = howMuchToRead(nOrig, state);
|
|
}
|
|
|
|
var ret;
|
|
if (n > 0) ret = fromList(n, state);else ret = null;
|
|
|
|
if (ret === null) {
|
|
state.needReadable = true;
|
|
n = 0;
|
|
} else {
|
|
state.length -= n;
|
|
}
|
|
|
|
if (state.length === 0) {
|
|
// If we have nothing in the buffer, then we want to know
|
|
// as soon as we *do* get something into the buffer.
|
|
if (!state.ended) state.needReadable = true;
|
|
|
|
// If we tried to read() past the EOF, then emit end on the next tick.
|
|
if (nOrig !== n && state.ended) endReadable(this);
|
|
}
|
|
|
|
if (ret !== null) this.emit('data', ret);
|
|
|
|
return ret;
|
|
};
|
|
|
|
function onEofChunk(stream, state) {
|
|
if (state.ended) return;
|
|
if (state.decoder) {
|
|
var chunk = state.decoder.end();
|
|
if (chunk && chunk.length) {
|
|
state.buffer.push(chunk);
|
|
state.length += state.objectMode ? 1 : chunk.length;
|
|
}
|
|
}
|
|
state.ended = true;
|
|
|
|
// 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) processNextTick(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;
|
|
processNextTick(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('_read() is 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 : unpipe;
|
|
if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn);
|
|
|
|
dest.on('unpipe', onunpipe);
|
|
function onunpipe(readable, unpipeInfo) {
|
|
debug('onunpipe');
|
|
if (readable === src) {
|
|
if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
|
|
unpipeInfo.hasUnpiped = true;
|
|
cleanup();
|
|
}
|
|
}
|
|
}
|
|
|
|
function onend() {
|
|
debug('onend');
|
|
dest.end();
|
|
}
|
|
|
|
// when the dest drains, it reduces the awaitDrain counter
|
|
// on the source. This would be more elegant with a .once()
|
|
// handler in flow(), but adding and removing repeatedly is
|
|
// too slow.
|
|
var ondrain = pipeOnDrain(src);
|
|
dest.on('drain', ondrain);
|
|
|
|
var cleanedUp = false;
|
|
function cleanup() {
|
|
debug('cleanup');
|
|
// cleanup event handlers once the pipe is broken
|
|
dest.removeListener('close', onclose);
|
|
dest.removeListener('finish', onfinish);
|
|
dest.removeListener('drain', ondrain);
|
|
dest.removeListener('error', onerror);
|
|
dest.removeListener('unpipe', onunpipe);
|
|
src.removeListener('end', onend);
|
|
src.removeListener('end', unpipe);
|
|
src.removeListener('data', ondata);
|
|
|
|
cleanedUp = true;
|
|
|
|
// if the reader is waiting for a drain event from this
|
|
// specific writer, then it would cause it to never start
|
|
// flowing again.
|
|
// So, if this is awaiting a drain, then we just call it now.
|
|
// If we don't know, then assume that we are waiting for one.
|
|
if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
|
|
}
|
|
|
|
// If the user pushes more data while we're writing to dest then we'll end up
|
|
// in ondata again. However, we only want to increase awaitDrain once because
|
|
// dest will only emit one 'drain' event for the multiple writes.
|
|
// => Introduce a guard on increasing awaitDrain.
|
|
var increasedAwaitDrain = false;
|
|
src.on('data', ondata);
|
|
function ondata(chunk) {
|
|
debug('ondata');
|
|
increasedAwaitDrain = false;
|
|
var ret = dest.write(chunk);
|
|
if (false === ret && !increasedAwaitDrain) {
|
|
// If the user unpiped during `dest.write()`, it is possible
|
|
// to get stuck in a permanently paused state if that write
|
|
// also returned false.
|
|
// => Check whether `dest` is still a piping destination.
|
|
if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
|
|
debug('false write response, pause', src._readableState.awaitDrain);
|
|
src._readableState.awaitDrain++;
|
|
increasedAwaitDrain = true;
|
|
}
|
|
src.pause();
|
|
}
|
|
}
|
|
|
|
// if the dest has an error, then stop piping into it.
|
|
// however, don't suppress the throwing behavior for this.
|
|
function onerror(er) {
|
|
debug('onerror', er);
|
|
unpipe();
|
|
dest.removeListener('error', onerror);
|
|
if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er);
|
|
}
|
|
|
|
// Make sure our error handler is attached before userland ones.
|
|
prependListener(dest, 'error', onerror);
|
|
|
|
// Both close and finish should trigger unpipe, but only once.
|
|
function onclose() {
|
|
dest.removeListener('finish', onfinish);
|
|
unpipe();
|
|
}
|
|
dest.once('close', onclose);
|
|
function onfinish() {
|
|
debug('onfinish');
|
|
dest.removeListener('close', onclose);
|
|
unpipe();
|
|
}
|
|
dest.once('finish', onfinish);
|
|
|
|
function unpipe() {
|
|
debug('unpipe');
|
|
src.unpipe(dest);
|
|
}
|
|
|
|
// tell the dest that it's being piped to
|
|
dest.emit('pipe', src);
|
|
|
|
// start the flow if it hasn't been started already.
|
|
if (!state.flowing) {
|
|
debug('pipe resume');
|
|
src.resume();
|
|
}
|
|
|
|
return dest;
|
|
};
|
|
|
|
function pipeOnDrain(src) {
|
|
return function () {
|
|
var state = src._readableState;
|
|
debug('pipeOnDrain', state.awaitDrain);
|
|
if (state.awaitDrain) state.awaitDrain--;
|
|
if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
|
|
state.flowing = true;
|
|
flow(src);
|
|
}
|
|
};
|
|
}
|
|
|
|
Readable.prototype.unpipe = function (dest) {
|
|
var state = this._readableState;
|
|
var unpipeInfo = { hasUnpiped: false };
|
|
|
|
// if we're not piping anywhere, then do nothing.
|
|
if (state.pipesCount === 0) return this;
|
|
|
|
// just one destination. most common case.
|
|
if (state.pipesCount === 1) {
|
|
// passed in one, but it's not the right one.
|
|
if (dest && dest !== state.pipes) return this;
|
|
|
|
if (!dest) dest = state.pipes;
|
|
|
|
// got a match.
|
|
state.pipes = null;
|
|
state.pipesCount = 0;
|
|
state.flowing = false;
|
|
if (dest) dest.emit('unpipe', this, unpipeInfo);
|
|
return this;
|
|
}
|
|
|
|
// slow case. multiple pipe destinations.
|
|
|
|
if (!dest) {
|
|
// remove all.
|
|
var dests = state.pipes;
|
|
var len = state.pipesCount;
|
|
state.pipes = null;
|
|
state.pipesCount = 0;
|
|
state.flowing = false;
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
dests[i].emit('unpipe', this, unpipeInfo);
|
|
}return this;
|
|
}
|
|
|
|
// try to find the right one.
|
|
var index = indexOf(state.pipes, dest);
|
|
if (index === -1) return this;
|
|
|
|
state.pipes.splice(index, 1);
|
|
state.pipesCount -= 1;
|
|
if (state.pipesCount === 1) state.pipes = state.pipes[0];
|
|
|
|
dest.emit('unpipe', this, unpipeInfo);
|
|
|
|
return this;
|
|
};
|
|
|
|
// set up data events if they are asked for
|
|
// Ensure readable listeners eventually get something
|
|
Readable.prototype.on = function (ev, fn) {
|
|
var res = Stream.prototype.on.call(this, ev, fn);
|
|
|
|
if (ev === 'data') {
|
|
// Start flowing on next tick if stream isn't explicitly paused
|
|
if (this._readableState.flowing !== false) this.resume();
|
|
} else if (ev === 'readable') {
|
|
var state = this._readableState;
|
|
if (!state.endEmitted && !state.readableListening) {
|
|
state.readableListening = state.needReadable = true;
|
|
state.emittedReadable = false;
|
|
if (!state.reading) {
|
|
processNextTick(nReadingNextTick, this);
|
|
} else if (state.length) {
|
|
emitReadable(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
Readable.prototype.addListener = Readable.prototype.on;
|
|
|
|
function nReadingNextTick(self) {
|
|
debug('readable nexttick read 0');
|
|
self.read(0);
|
|
}
|
|
|
|
// pause() and resume() are remnants of the legacy readable stream API
|
|
// If the user uses them, then switch into old mode.
|
|
Readable.prototype.resume = function () {
|
|
var state = this._readableState;
|
|
if (!state.flowing) {
|
|
debug('resume');
|
|
state.flowing = true;
|
|
resume(this, state);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
function resume(stream, state) {
|
|
if (!state.resumeScheduled) {
|
|
state.resumeScheduled = true;
|
|
processNextTick(resume_, stream, state);
|
|
}
|
|
}
|
|
|
|
function resume_(stream, state) {
|
|
if (!state.reading) {
|
|
debug('resume read 0');
|
|
stream.read(0);
|
|
}
|
|
|
|
state.resumeScheduled = false;
|
|
state.awaitDrain = 0;
|
|
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);
|
|
while (state.flowing && stream.read() !== null) {}
|
|
}
|
|
|
|
// wrap an old-style stream as the async data source.
|
|
// This is *not* part of the readable stream interface.
|
|
// It is an ugly unfortunate mess of history.
|
|
Readable.prototype.wrap = function (stream) {
|
|
var 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);
|
|
|
|
// don't skip over falsy values in objectMode
|
|
if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return;
|
|
|
|
var ret = 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 (this[i] === undefined && typeof stream[i] === 'function') {
|
|
this[i] = function (method) {
|
|
return function () {
|
|
return stream[method].apply(stream, arguments);
|
|
};
|
|
}(i);
|
|
}
|
|
}
|
|
|
|
// proxy certain important events.
|
|
for (var n = 0; n < kProxyEvents.length; n++) {
|
|
stream.on(kProxyEvents[n], self.emit.bind(self, kProxyEvents[n]));
|
|
}
|
|
|
|
// 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.
|
|
// This function is designed to be inlinable, so please take care when making
|
|
// changes to the function body.
|
|
function fromList(n, state) {
|
|
// nothing buffered
|
|
if (state.length === 0) return null;
|
|
|
|
var ret;
|
|
if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) {
|
|
// read it all, truncate the list
|
|
if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length);
|
|
state.buffer.clear();
|
|
} else {
|
|
// read part of list
|
|
ret = fromListPartial(n, state.buffer, state.decoder);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Extracts only enough buffered data to satisfy the amount requested.
|
|
// This function is designed to be inlinable, so please take care when making
|
|
// changes to the function body.
|
|
function fromListPartial(n, list, hasStrings) {
|
|
var ret;
|
|
if (n < list.head.data.length) {
|
|
// slice is the same for buffers and strings
|
|
ret = list.head.data.slice(0, n);
|
|
list.head.data = list.head.data.slice(n);
|
|
} else if (n === list.head.data.length) {
|
|
// first chunk is a perfect match
|
|
ret = list.shift();
|
|
} else {
|
|
// result spans more than one buffer
|
|
ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Copies a specified amount of characters from the list of buffered data
|
|
// chunks.
|
|
// This function is designed to be inlinable, so please take care when making
|
|
// changes to the function body.
|
|
function copyFromBufferString(n, list) {
|
|
var p = list.head;
|
|
var c = 1;
|
|
var ret = p.data;
|
|
n -= ret.length;
|
|
while (p = p.next) {
|
|
var str = p.data;
|
|
var nb = n > str.length ? str.length : n;
|
|
if (nb === str.length) ret += str;else ret += str.slice(0, n);
|
|
n -= nb;
|
|
if (n === 0) {
|
|
if (nb === str.length) {
|
|
++c;
|
|
if (p.next) list.head = p.next;else list.head = list.tail = null;
|
|
} else {
|
|
list.head = p;
|
|
p.data = str.slice(nb);
|
|
}
|
|
break;
|
|
}
|
|
++c;
|
|
}
|
|
list.length -= c;
|
|
return ret;
|
|
}
|
|
|
|
// Copies a specified amount of bytes from the list of buffered data chunks.
|
|
// This function is designed to be inlinable, so please take care when making
|
|
// changes to the function body.
|
|
function copyFromBuffer(n, list) {
|
|
var ret = Buffer.allocUnsafe(n);
|
|
var p = list.head;
|
|
var c = 1;
|
|
p.data.copy(ret);
|
|
n -= p.data.length;
|
|
while (p = p.next) {
|
|
var buf = p.data;
|
|
var nb = n > buf.length ? buf.length : n;
|
|
buf.copy(ret, ret.length - n, 0, nb);
|
|
n -= nb;
|
|
if (n === 0) {
|
|
if (nb === buf.length) {
|
|
++c;
|
|
if (p.next) list.head = p.next;else list.head = list.tail = null;
|
|
} else {
|
|
list.head = p;
|
|
p.data = buf.slice(nb);
|
|
}
|
|
break;
|
|
}
|
|
++c;
|
|
}
|
|
list.length -= c;
|
|
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;
|
|
processNextTick(endReadableNT, state, stream);
|
|
}
|
|
}
|
|
|
|
function endReadableNT(state, stream) {
|
|
// 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'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{"./_stream_duplex":253,"./internal/streams/BufferList":258,"./internal/streams/destroy":259,"./internal/streams/stream":260,"_process":247,"core-util-is":261,"events":245,"inherits":262,"isarray":263,"process-nextick-args":264,"safe-buffer":265,"string_decoder/":266,"util":46}],256:[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.
|
|
|
|
'use strict';
|
|
|
|
module.exports = Transform;
|
|
|
|
var Duplex = require('./_stream_duplex');
|
|
|
|
/*<replacement>*/
|
|
var util = require('core-util-is');
|
|
util.inherits = require('inherits');
|
|
/*</replacement>*/
|
|
|
|
util.inherits(Transform, Duplex);
|
|
|
|
function TransformState(stream) {
|
|
this.afterTransform = function (er, data) {
|
|
return afterTransform(stream, er, data);
|
|
};
|
|
|
|
this.needTransform = false;
|
|
this.transforming = false;
|
|
this.writecb = null;
|
|
this.writechunk = null;
|
|
this.writeencoding = 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('write callback called multiple times'));
|
|
}
|
|
|
|
ts.writechunk = null;
|
|
ts.writecb = null;
|
|
|
|
if (data !== null && data !== undefined) stream.push(data);
|
|
|
|
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(this);
|
|
|
|
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;
|
|
|
|
if (options) {
|
|
if (typeof options.transform === 'function') this._transform = options.transform;
|
|
|
|
if (typeof options.flush === 'function') this._flush = options.flush;
|
|
}
|
|
|
|
// When the writable side finishes, then flush out anything remaining.
|
|
this.once('prefinish', function () {
|
|
if (typeof this._flush === 'function') this._flush(function (er, data) {
|
|
done(stream, er, data);
|
|
});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('_transform() is 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 (ts.writechunk !== null && 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;
|
|
}
|
|
};
|
|
|
|
Transform.prototype._destroy = function (err, cb) {
|
|
var _this = this;
|
|
|
|
Duplex.prototype._destroy.call(this, err, function (err2) {
|
|
cb(err2);
|
|
_this.emit('close');
|
|
});
|
|
};
|
|
|
|
function done(stream, er, data) {
|
|
if (er) return stream.emit('error', er);
|
|
|
|
if (data !== null && data !== undefined) stream.push(data);
|
|
|
|
// 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":253,"core-util-is":261,"inherits":262}],257:[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.
|
|
|
|
// A bit simpler than readable streams.
|
|
// Implement an async ._write(chunk, encoding, cb), and it'll handle all
|
|
// the drain event emission and buffering.
|
|
|
|
'use strict';
|
|
|
|
/*<replacement>*/
|
|
|
|
var processNextTick = require('process-nextick-args');
|
|
/*</replacement>*/
|
|
|
|
module.exports = Writable;
|
|
|
|
/* <replacement> */
|
|
function WriteReq(chunk, encoding, cb) {
|
|
this.chunk = chunk;
|
|
this.encoding = encoding;
|
|
this.callback = cb;
|
|
this.next = null;
|
|
}
|
|
|
|
// It seems a linked list but it is not
|
|
// there will be only 2 of these for each stream
|
|
function CorkedRequest(state) {
|
|
var _this = this;
|
|
|
|
this.next = null;
|
|
this.entry = null;
|
|
this.finish = function () {
|
|
onCorkedFinish(_this, state);
|
|
};
|
|
}
|
|
/* </replacement> */
|
|
|
|
/*<replacement>*/
|
|
var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick;
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
var Duplex;
|
|
/*</replacement>*/
|
|
|
|
Writable.WritableState = WritableState;
|
|
|
|
/*<replacement>*/
|
|
var util = require('core-util-is');
|
|
util.inherits = require('inherits');
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
var internalUtil = {
|
|
deprecate: require('util-deprecate')
|
|
};
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
var Stream = require('./internal/streams/stream');
|
|
/*</replacement>*/
|
|
|
|
/*<replacement>*/
|
|
var Buffer = require('safe-buffer').Buffer;
|
|
var OurUint8Array = global.Uint8Array || function () {};
|
|
function _uint8ArrayToBuffer(chunk) {
|
|
return Buffer.from(chunk);
|
|
}
|
|
function _isUint8Array(obj) {
|
|
return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
|
|
}
|
|
/*</replacement>*/
|
|
|
|
var destroyImpl = require('./internal/streams/destroy');
|
|
|
|
util.inherits(Writable, Stream);
|
|
|
|
function nop() {}
|
|
|
|
function WritableState(options, stream) {
|
|
Duplex = Duplex || require('./_stream_duplex');
|
|
|
|
options = options || {};
|
|
|
|
// 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;
|
|
|
|
// 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 = this.objectMode ? 16 : 16 * 1024;
|
|
this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
|
|
|
|
// cast to ints.
|
|
this.highWaterMark = Math.floor(this.highWaterMark);
|
|
|
|
// if _final has been called
|
|
this.finalCalled = false;
|
|
|
|
// drain event flag.
|
|
this.needDrain = false;
|
|
// at the start of calling end()
|
|
this.ending = false;
|
|
// when end() has been called, and returned
|
|
this.ended = false;
|
|
// when 'finish' is emitted
|
|
this.finished = false;
|
|
|
|
// has it been destroyed
|
|
this.destroyed = false;
|
|
|
|
// should we decode strings into buffers before passing to _write?
|
|
// this is here so that some node-core streams can optimize string
|
|
// handling at a lower level.
|
|
var noDecode = options.decodeStrings === false;
|
|
this.decodeStrings = !noDecode;
|
|
|
|
// Crypto is kind of old and crusty. Historically, its default string
|
|
// encoding is 'binary' so we have to make this configurable.
|
|
// Everything else in the universe uses 'utf8', though.
|
|
this.defaultEncoding = options.defaultEncoding || 'utf8';
|
|
|
|
// not an actual buffer we keep track of, but a measurement
|
|
// of how much we're waiting to get pushed to some underlying
|
|
// socket or file.
|
|
this.length = 0;
|
|
|
|
// a flag to see when we're in the middle of a write.
|
|
this.writing = false;
|
|
|
|
// when true all writes will be buffered until .uncork() call
|
|
this.corked = 0;
|
|
|
|
// a flag to be able to tell if the onwrite cb is called immediately,
|
|
// or on a later tick. We set this to true at first, because any
|
|
// actions that shouldn't happen until "later" should generally also
|
|
// not happen before the first write call.
|
|
this.sync = true;
|
|
|
|
// a flag to know if we're processing previously buffered items, which
|
|
// may call the _write() callback in the same tick, so that we don't
|
|
// end up in an overlapped onwrite situation.
|
|
this.bufferProcessing = false;
|
|
|
|
// the callback that's passed to _write(chunk,cb)
|
|
this.onwrite = function (er) {
|
|
onwrite(stream, er);
|
|
};
|
|
|
|
// the callback that the user supplies to write(chunk,encoding,cb)
|
|
this.writecb = null;
|
|
|
|
// the amount that is being written when _write is called.
|
|
this.writelen = 0;
|
|
|
|
this.bufferedRequest = null;
|
|
this.lastBufferedRequest = null;
|
|
|
|
// number of pending user-supplied write callbacks
|
|
// this must be 0 before 'finish' can be emitted
|
|
this.pendingcb = 0;
|
|
|
|
// emit prefinish if the only thing we're waiting for is _write cbs
|
|
// This is relevant for synchronous Transform streams
|
|
this.prefinished = false;
|
|
|
|
// True if the error was already emitted and should not be thrown again
|
|
this.errorEmitted = false;
|
|
|
|
// count buffered requests
|
|
this.bufferedRequestCount = 0;
|
|
|
|
// allocate the first CorkedRequest, there is always
|
|
// one allocated and free to use, and we maintain at most two
|
|
this.corkedRequestsFree = new CorkedRequest(this);
|
|
}
|
|
|
|
WritableState.prototype.getBuffer = function getBuffer() {
|
|
var current = this.bufferedRequest;
|
|
var out = [];
|
|
while (current) {
|
|
out.push(current);
|
|
current = current.next;
|
|
}
|
|
return out;
|
|
};
|
|
|
|
(function () {
|
|
try {
|
|
Object.defineProperty(WritableState.prototype, 'buffer', {
|
|
get: internalUtil.deprecate(function () {
|
|
return this.getBuffer();
|
|
}, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003')
|
|
});
|
|
} catch (_) {}
|
|
})();
|
|
|
|
// Test _writableState for inheritance to account for Duplex streams,
|
|
// whose prototype chain only points to Readable.
|
|
var realHasInstance;
|
|
if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
|
|
realHasInstance = Function.prototype[Symbol.hasInstance];
|
|
Object.defineProperty(Writable, Symbol.hasInstance, {
|
|
value: function (object) {
|
|
if (realHasInstance.call(this, object)) return true;
|
|
|
|
return object && object._writableState instanceof WritableState;
|
|
}
|
|
});
|
|
} else {
|
|
realHasInstance = function (object) {
|
|
return object instanceof this;
|
|
};
|
|
}
|
|
|
|
function Writable(options) {
|
|
Duplex = Duplex || require('./_stream_duplex');
|
|
|
|
// Writable ctor is applied to Duplexes, too.
|
|
// `realHasInstance` is necessary because using plain `instanceof`
|
|
// would return false, as no `_writableState` property is attached.
|
|
|
|
// Trying to use the custom `instanceof` for Writable here will also break the
|
|
// Node.js LazyTransform implementation, which has a non-trivial getter for
|
|
// `_writableState` that would lead to infinite recursion.
|
|
if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) {
|
|
return new Writable(options);
|
|
}
|
|
|
|
this._writableState = new WritableState(options, this);
|
|
|
|
// legacy.
|
|
this.writable = true;
|
|
|
|
if (options) {
|
|
if (typeof options.write === 'function') this._write = options.write;
|
|
|
|
if (typeof options.writev === 'function') this._writev = options.writev;
|
|
|
|
if (typeof options.destroy === 'function') this._destroy = options.destroy;
|
|
|
|
if (typeof options.final === 'function') this._final = options.final;
|
|
}
|
|
|
|
Stream.call(this);
|
|
}
|
|
|
|
// Otherwise people can pipe Writable streams, which is just wrong.
|
|
Writable.prototype.pipe = function () {
|
|
this.emit('error', new Error('Cannot pipe, not readable'));
|
|
};
|
|
|
|
function writeAfterEnd(stream, cb) {
|
|
var er = new Error('write after end');
|
|
// TODO: defer error events consistently everywhere, not just the cb
|
|
stream.emit('error', er);
|
|
processNextTick(cb, er);
|
|
}
|
|
|
|
// Checks that a user-supplied chunk is valid, especially for the particular
|
|
// mode the stream is in. Currently this means that `null` is never accepted
|
|
// and undefined/non-string values are only allowed in object mode.
|
|
function validChunk(stream, state, chunk, cb) {
|
|
var valid = true;
|
|
var er = false;
|
|
|
|
if (chunk === null) {
|
|
er = new TypeError('May not write null values to stream');
|
|
} else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
|
|
er = new TypeError('Invalid non-string/buffer chunk');
|
|
}
|
|
if (er) {
|
|
stream.emit('error', er);
|
|
processNextTick(cb, er);
|
|
valid = false;
|
|
}
|
|
return valid;
|
|
}
|
|
|
|
Writable.prototype.write = function (chunk, encoding, cb) {
|
|
var state = this._writableState;
|
|
var ret = false;
|
|
var isBuf = _isUint8Array(chunk) && !state.objectMode;
|
|
|
|
if (isBuf && !Buffer.isBuffer(chunk)) {
|
|
chunk = _uint8ArrayToBuffer(chunk);
|
|
}
|
|
|
|
if (typeof encoding === 'function') {
|
|
cb = encoding;
|
|
encoding = null;
|
|
}
|
|
|
|
if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;
|
|
|
|
if (typeof cb !== 'function') cb = nop;
|
|
|
|
if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) {
|
|
state.pendingcb++;
|
|
ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
Writable.prototype.cork = function () {
|
|
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.bufferedRequest) clearBuffer(this, state);
|
|
}
|
|
};
|
|
|
|
Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
|
|
// node::ParseEncoding() requires lower case.
|
|
if (typeof encoding === 'string') encoding = encoding.toLowerCase();
|
|
if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding);
|
|
this._writableState.defaultEncoding = encoding;
|
|
return this;
|
|
};
|
|
|
|
function decodeChunk(state, chunk, encoding) {
|
|
if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
|
|
chunk = Buffer.from(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, isBuf, chunk, encoding, cb) {
|
|
if (!isBuf) {
|
|
var newChunk = decodeChunk(state, chunk, encoding);
|
|
if (chunk !== newChunk) {
|
|
isBuf = true;
|
|
encoding = 'buffer';
|
|
chunk = newChunk;
|
|
}
|
|
}
|
|
var len = state.objectMode ? 1 : chunk.length;
|
|
|
|
state.length += len;
|
|
|
|
var ret = state.length < state.highWaterMark;
|
|
// we must ensure that previous needDrain will not be reset to false.
|
|
if (!ret) state.needDrain = true;
|
|
|
|
if (state.writing || state.corked) {
|
|
var last = state.lastBufferedRequest;
|
|
state.lastBufferedRequest = {
|
|
chunk: chunk,
|
|
encoding: encoding,
|
|
isBuf: isBuf,
|
|
callback: cb,
|
|
next: null
|
|
};
|
|
if (last) {
|
|
last.next = state.lastBufferedRequest;
|
|
} else {
|
|
state.bufferedRequest = state.lastBufferedRequest;
|
|
}
|
|
state.bufferedRequestCount += 1;
|
|
} else {
|
|
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
function doWrite(stream, state, writev, len, chunk, encoding, cb) {
|
|
state.writelen = len;
|
|
state.writecb = cb;
|
|
state.writing = true;
|
|
state.sync = true;
|
|
if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
|
|
state.sync = false;
|
|
}
|
|
|
|
function onwriteError(stream, state, sync, er, cb) {
|
|
--state.pendingcb;
|
|
|
|
if (sync) {
|
|
// defer the callback if we are being called synchronously
|
|
// to avoid piling up things on the stack
|
|
processNextTick(cb, er);
|
|
// this can emit finish, and it will always happen
|
|
// after error
|
|
processNextTick(finishMaybe, stream, state);
|
|
stream._writableState.errorEmitted = true;
|
|
stream.emit('error', er);
|
|
} else {
|
|
// the caller expect this to happen before if
|
|
// it is async
|
|
cb(er);
|
|
stream._writableState.errorEmitted = true;
|
|
stream.emit('error', er);
|
|
// this can emit finish, but finish must
|
|
// always follow error
|
|
finishMaybe(stream, state);
|
|
}
|
|
}
|
|
|
|
function onwriteStateUpdate(state) {
|
|
state.writing = false;
|
|
state.writecb = null;
|
|
state.length -= state.writelen;
|
|
state.writelen = 0;
|
|
}
|
|
|
|
function onwrite(stream, er) {
|
|
var state = stream._writableState;
|
|
var sync = state.sync;
|
|
var cb = state.writecb;
|
|
|
|
onwriteStateUpdate(state);
|
|
|
|
if (er) onwriteError(stream, state, sync, er, cb);else {
|
|
// Check if we're actually ready to finish, but don't emit yet
|
|
var finished = needFinish(state);
|
|
|
|
if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
|
|
clearBuffer(stream, state);
|
|
}
|
|
|
|
if (sync) {
|
|
/*<replacement>*/
|
|
asyncWrite(afterWrite, stream, state, finished, cb);
|
|
/*</replacement>*/
|
|
} else {
|
|
afterWrite(stream, state, finished, cb);
|
|
}
|
|
}
|
|
}
|
|
|
|
function afterWrite(stream, state, finished, cb) {
|
|
if (!finished) onwriteDrain(stream, state);
|
|
state.pendingcb--;
|
|
cb();
|
|
finishMaybe(stream, state);
|
|
}
|
|
|
|
// Must force callback to be called on nextTick, so that we don't
|
|
// emit 'drain' before the write() consumer gets the 'false' return
|
|
// value, and has a chance to attach a 'drain' listener.
|
|
function onwriteDrain(stream, state) {
|
|
if (state.length === 0 && state.needDrain) {
|
|
state.needDrain = false;
|
|
stream.emit('drain');
|
|
}
|
|
}
|
|
|
|
// if there's something in the buffer waiting, then process it
|
|
function clearBuffer(stream, state) {
|
|
state.bufferProcessing = true;
|
|
var entry = state.bufferedRequest;
|
|
|
|
if (stream._writev && entry && entry.next) {
|
|
// Fast case, write everything using _writev()
|
|
var l = state.bufferedRequestCount;
|
|
var buffer = new Array(l);
|
|
var holder = state.corkedRequestsFree;
|
|
holder.entry = entry;
|
|
|
|
var count = 0;
|
|
var allBuffers = true;
|
|
while (entry) {
|
|
buffer[count] = entry;
|
|
if (!entry.isBuf) allBuffers = false;
|
|
entry = entry.next;
|
|
count += 1;
|
|
}
|
|
buffer.allBuffers = allBuffers;
|
|
|
|
doWrite(stream, state, true, state.length, buffer, '', holder.finish);
|
|
|
|
// doWrite is almost always async, defer these to save a bit of time
|
|
// as the hot path ends with doWrite
|
|
state.pendingcb++;
|
|
state.lastBufferedRequest = null;
|
|
if (holder.next) {
|
|
state.corkedRequestsFree = holder.next;
|
|
holder.next = null;
|
|
} else {
|
|
state.corkedRequestsFree = new CorkedRequest(state);
|
|
}
|
|
} else {
|
|
// Slow case, write chunks one-by-one
|
|
while (entry) {
|
|
var chunk = entry.chunk;
|
|
var encoding = entry.encoding;
|
|
var cb = entry.callback;
|
|
var len = state.objectMode ? 1 : chunk.length;
|
|
|
|
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
entry = entry.next;
|
|
// if we didn't call the onwrite immediately, then
|
|
// it means that we need to wait until it does.
|
|
// also, that means that the chunk and cb are currently
|
|
// being processed, so move the buffer counter past them.
|
|
if (state.writing) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (entry === null) state.lastBufferedRequest = null;
|
|
}
|
|
|
|
state.bufferedRequestCount = 0;
|
|
state.bufferedRequest = entry;
|
|
state.bufferProcessing = false;
|
|
}
|
|
|
|
Writable.prototype._write = function (chunk, encoding, cb) {
|
|
cb(new Error('_write() is not implemented'));
|
|
};
|
|
|
|
Writable.prototype._writev = null;
|
|
|
|
Writable.prototype.end = function (chunk, encoding, cb) {
|
|
var state = this._writableState;
|
|
|
|
if (typeof chunk === 'function') {
|
|
cb = chunk;
|
|
chunk = null;
|
|
encoding = null;
|
|
} else if (typeof encoding === 'function') {
|
|
cb = encoding;
|
|
encoding = null;
|
|
}
|
|
|
|
if (chunk !== null && chunk !== undefined) this.write(chunk, encoding);
|
|
|
|
// .end() fully uncorks
|
|
if (state.corked) {
|
|
state.corked = 1;
|
|
this.uncork();
|
|
}
|
|
|
|
// ignore unnecessary end() calls.
|
|
if (!state.ending && !state.finished) endWritable(this, state, cb);
|
|
};
|
|
|
|
function needFinish(state) {
|
|
return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
|
|
}
|
|
function callFinal(stream, state) {
|
|
stream._final(function (err) {
|
|
state.pendingcb--;
|
|
if (err) {
|
|
stream.emit('error', err);
|
|
}
|
|
state.prefinished = true;
|
|
stream.emit('prefinish');
|
|
finishMaybe(stream, state);
|
|
});
|
|
}
|
|
function prefinish(stream, state) {
|
|
if (!state.prefinished && !state.finalCalled) {
|
|
if (typeof stream._final === 'function') {
|
|
state.pendingcb++;
|
|
state.finalCalled = true;
|
|
processNextTick(callFinal, stream, state);
|
|
} else {
|
|
state.prefinished = true;
|
|
stream.emit('prefinish');
|
|
}
|
|
}
|
|
}
|
|
|
|
function finishMaybe(stream, state) {
|
|
var need = needFinish(state);
|
|
if (need) {
|
|
prefinish(stream, state);
|
|
if (state.pendingcb === 0) {
|
|
state.finished = true;
|
|
stream.emit('finish');
|
|
}
|
|
}
|
|
return need;
|
|
}
|
|
|
|
function endWritable(stream, state, cb) {
|
|
state.ending = true;
|
|
finishMaybe(stream, state);
|
|
if (cb) {
|
|
if (state.finished) processNextTick(cb);else stream.once('finish', cb);
|
|
}
|
|
state.ended = true;
|
|
stream.writable = false;
|
|
}
|
|
|
|
function onCorkedFinish(corkReq, state, err) {
|
|
var entry = corkReq.entry;
|
|
corkReq.entry = null;
|
|
while (entry) {
|
|
var cb = entry.callback;
|
|
state.pendingcb--;
|
|
cb(err);
|
|
entry = entry.next;
|
|
}
|
|
if (state.corkedRequestsFree) {
|
|
state.corkedRequestsFree.next = corkReq;
|
|
} else {
|
|
state.corkedRequestsFree = corkReq;
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(Writable.prototype, 'destroyed', {
|
|
get: function () {
|
|
if (this._writableState === undefined) {
|
|
return false;
|
|
}
|
|
return this._writableState.destroyed;
|
|
},
|
|
set: function (value) {
|
|
// we ignore the value if the stream
|
|
// has not been initialized yet
|
|
if (!this._writableState) {
|
|
return;
|
|
}
|
|
|
|
// backward compatibility, the user is explicitly
|
|
// managing destroyed
|
|
this._writableState.destroyed = value;
|
|
}
|
|
});
|
|
|
|
Writable.prototype.destroy = destroyImpl.destroy;
|
|
Writable.prototype._undestroy = destroyImpl.undestroy;
|
|
Writable.prototype._destroy = function (err, cb) {
|
|
this.end();
|
|
cb(err);
|
|
};
|
|
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{"./_stream_duplex":253,"./internal/streams/destroy":259,"./internal/streams/stream":260,"_process":247,"core-util-is":261,"inherits":262,"process-nextick-args":264,"safe-buffer":265,"util-deprecate":267}],258:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
/*<replacement>*/
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
var Buffer = require('safe-buffer').Buffer;
|
|
/*</replacement>*/
|
|
|
|
function copyBuffer(src, target, offset) {
|
|
src.copy(target, offset);
|
|
}
|
|
|
|
module.exports = function () {
|
|
function BufferList() {
|
|
_classCallCheck(this, BufferList);
|
|
|
|
this.head = null;
|
|
this.tail = null;
|
|
this.length = 0;
|
|
}
|
|
|
|
BufferList.prototype.push = function push(v) {
|
|
var entry = { data: v, next: null };
|
|
if (this.length > 0) this.tail.next = entry;else this.head = entry;
|
|
this.tail = entry;
|
|
++this.length;
|
|
};
|
|
|
|
BufferList.prototype.unshift = function unshift(v) {
|
|
var entry = { data: v, next: this.head };
|
|
if (this.length === 0) this.tail = entry;
|
|
this.head = entry;
|
|
++this.length;
|
|
};
|
|
|
|
BufferList.prototype.shift = function shift() {
|
|
if (this.length === 0) return;
|
|
var ret = this.head.data;
|
|
if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
|
|
--this.length;
|
|
return ret;
|
|
};
|
|
|
|
BufferList.prototype.clear = function clear() {
|
|
this.head = this.tail = null;
|
|
this.length = 0;
|
|
};
|
|
|
|
BufferList.prototype.join = function join(s) {
|
|
if (this.length === 0) return '';
|
|
var p = this.head;
|
|
var ret = '' + p.data;
|
|
while (p = p.next) {
|
|
ret += s + p.data;
|
|
}return ret;
|
|
};
|
|
|
|
BufferList.prototype.concat = function concat(n) {
|
|
if (this.length === 0) return Buffer.alloc(0);
|
|
if (this.length === 1) return this.head.data;
|
|
var ret = Buffer.allocUnsafe(n >>> 0);
|
|
var p = this.head;
|
|
var i = 0;
|
|
while (p) {
|
|
copyBuffer(p.data, ret, i);
|
|
i += p.data.length;
|
|
p = p.next;
|
|
}
|
|
return ret;
|
|
};
|
|
|
|
return BufferList;
|
|
}();
|
|
},{"safe-buffer":265}],259:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
/*<replacement>*/
|
|
|
|
var processNextTick = require('process-nextick-args');
|
|
/*</replacement>*/
|
|
|
|
// undocumented cb() API, needed for core, not for public API
|
|
function destroy(err, cb) {
|
|
var _this = this;
|
|
|
|
var readableDestroyed = this._readableState && this._readableState.destroyed;
|
|
var writableDestroyed = this._writableState && this._writableState.destroyed;
|
|
|
|
if (readableDestroyed || writableDestroyed) {
|
|
if (cb) {
|
|
cb(err);
|
|
} else if (err && (!this._writableState || !this._writableState.errorEmitted)) {
|
|
processNextTick(emitErrorNT, this, err);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// we set destroyed to true before firing error callbacks in order
|
|
// to make it re-entrance safe in case destroy() is called within callbacks
|
|
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = true;
|
|
}
|
|
|
|
// if this is a duplex stream mark the writable part as destroyed as well
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = true;
|
|
}
|
|
|
|
this._destroy(err || null, function (err) {
|
|
if (!cb && err) {
|
|
processNextTick(emitErrorNT, _this, err);
|
|
if (_this._writableState) {
|
|
_this._writableState.errorEmitted = true;
|
|
}
|
|
} else if (cb) {
|
|
cb(err);
|
|
}
|
|
});
|
|
}
|
|
|
|
function undestroy() {
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = false;
|
|
this._readableState.reading = false;
|
|
this._readableState.ended = false;
|
|
this._readableState.endEmitted = false;
|
|
}
|
|
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = false;
|
|
this._writableState.ended = false;
|
|
this._writableState.ending = false;
|
|
this._writableState.finished = false;
|
|
this._writableState.errorEmitted = false;
|
|
}
|
|
}
|
|
|
|
function emitErrorNT(self, err) {
|
|
self.emit('error', err);
|
|
}
|
|
|
|
module.exports = {
|
|
destroy: destroy,
|
|
undestroy: undestroy
|
|
};
|
|
},{"process-nextick-args":264}],260:[function(require,module,exports){
|
|
module.exports = require('events').EventEmitter;
|
|
|
|
},{"events":245}],261:[function(require,module,exports){
|
|
(function (Buffer){
|
|
// 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.
|
|
|
|
// NOTE: These type checking functions intentionally don't use `instanceof`
|
|
// because it is fragile and can be easily faked with `Object.create()`.
|
|
|
|
function isArray(arg) {
|
|
if (Array.isArray) {
|
|
return Array.isArray(arg);
|
|
}
|
|
return objectToString(arg) === '[object Array]';
|
|
}
|
|
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 objectToString(re) === '[object RegExp]';
|
|
}
|
|
exports.isRegExp = isRegExp;
|
|
|
|
function isObject(arg) {
|
|
return typeof arg === 'object' && arg !== null;
|
|
}
|
|
exports.isObject = isObject;
|
|
|
|
function isDate(d) {
|
|
return objectToString(d) === '[object Date]';
|
|
}
|
|
exports.isDate = isDate;
|
|
|
|
function isError(e) {
|
|
return (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 = Buffer.isBuffer;
|
|
|
|
function objectToString(o) {
|
|
return Object.prototype.toString.call(o);
|
|
}
|
|
|
|
}).call(this,{"isBuffer":require("../../../../insert-module-globals/node_modules/is-buffer/index.js")})
|
|
},{"../../../../insert-module-globals/node_modules/is-buffer/index.js":246}],262:[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
|
|
}
|
|
}
|
|
|
|
},{}],263:[function(require,module,exports){
|
|
arguments[4][50][0].apply(exports,arguments)
|
|
},{"dup":50}],264:[function(require,module,exports){
|
|
(function (process){
|
|
'use strict';
|
|
|
|
if (!process.version ||
|
|
process.version.indexOf('v0.') === 0 ||
|
|
process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) {
|
|
module.exports = nextTick;
|
|
} else {
|
|
module.exports = process.nextTick;
|
|
}
|
|
|
|
function nextTick(fn, arg1, arg2, arg3) {
|
|
if (typeof fn !== 'function') {
|
|
throw new TypeError('"callback" argument must be a function');
|
|
}
|
|
var len = arguments.length;
|
|
var args, i;
|
|
switch (len) {
|
|
case 0:
|
|
case 1:
|
|
return process.nextTick(fn);
|
|
case 2:
|
|
return process.nextTick(function afterTickOne() {
|
|
fn.call(null, arg1);
|
|
});
|
|
case 3:
|
|
return process.nextTick(function afterTickTwo() {
|
|
fn.call(null, arg1, arg2);
|
|
});
|
|
case 4:
|
|
return process.nextTick(function afterTickThree() {
|
|
fn.call(null, arg1, arg2, arg3);
|
|
});
|
|
default:
|
|
args = new Array(len - 1);
|
|
i = 0;
|
|
while (i < args.length) {
|
|
args[i++] = arguments[i];
|
|
}
|
|
return process.nextTick(function afterTick() {
|
|
fn.apply(null, args);
|
|
});
|
|
}
|
|
}
|
|
|
|
}).call(this,require('_process'))
|
|
},{"_process":247}],265:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],266:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var Buffer = require('safe-buffer').Buffer;
|
|
|
|
var isEncoding = Buffer.isEncoding || function (encoding) {
|
|
encoding = '' + encoding;
|
|
switch (encoding && encoding.toLowerCase()) {
|
|
case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw':
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
};
|
|
|
|
function _normalizeEncoding(enc) {
|
|
if (!enc) return 'utf8';
|
|
var retried;
|
|
while (true) {
|
|
switch (enc) {
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return 'utf8';
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
case 'utf16le':
|
|
case 'utf-16le':
|
|
return 'utf16le';
|
|
case 'latin1':
|
|
case 'binary':
|
|
return 'latin1';
|
|
case 'base64':
|
|
case 'ascii':
|
|
case 'hex':
|
|
return enc;
|
|
default:
|
|
if (retried) return; // undefined
|
|
enc = ('' + enc).toLowerCase();
|
|
retried = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
// Do not cache `Buffer.isEncoding` when checking encoding names as some
|
|
// modules monkey-patch it to support additional encodings
|
|
function normalizeEncoding(enc) {
|
|
var nenc = _normalizeEncoding(enc);
|
|
if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc);
|
|
return nenc || enc;
|
|
}
|
|
|
|
// StringDecoder provides an interface for efficiently splitting a series of
|
|
// buffers into a series of JS strings without breaking apart multi-byte
|
|
// characters.
|
|
exports.StringDecoder = StringDecoder;
|
|
function StringDecoder(encoding) {
|
|
this.encoding = normalizeEncoding(encoding);
|
|
var nb;
|
|
switch (this.encoding) {
|
|
case 'utf16le':
|
|
this.text = utf16Text;
|
|
this.end = utf16End;
|
|
nb = 4;
|
|
break;
|
|
case 'utf8':
|
|
this.fillLast = utf8FillLast;
|
|
nb = 4;
|
|
break;
|
|
case 'base64':
|
|
this.text = base64Text;
|
|
this.end = base64End;
|
|
nb = 3;
|
|
break;
|
|
default:
|
|
this.write = simpleWrite;
|
|
this.end = simpleEnd;
|
|
return;
|
|
}
|
|
this.lastNeed = 0;
|
|
this.lastTotal = 0;
|
|
this.lastChar = Buffer.allocUnsafe(nb);
|
|
}
|
|
|
|
StringDecoder.prototype.write = function (buf) {
|
|
if (buf.length === 0) return '';
|
|
var r;
|
|
var i;
|
|
if (this.lastNeed) {
|
|
r = this.fillLast(buf);
|
|
if (r === undefined) return '';
|
|
i = this.lastNeed;
|
|
this.lastNeed = 0;
|
|
} else {
|
|
i = 0;
|
|
}
|
|
if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i);
|
|
return r || '';
|
|
};
|
|
|
|
StringDecoder.prototype.end = utf8End;
|
|
|
|
// Returns only complete characters in a Buffer
|
|
StringDecoder.prototype.text = utf8Text;
|
|
|
|
// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer
|
|
StringDecoder.prototype.fillLast = function (buf) {
|
|
if (this.lastNeed <= buf.length) {
|
|
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed);
|
|
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
|
}
|
|
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length);
|
|
this.lastNeed -= buf.length;
|
|
};
|
|
|
|
// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a
|
|
// continuation byte.
|
|
function utf8CheckByte(byte) {
|
|
if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4;
|
|
return -1;
|
|
}
|
|
|
|
// Checks at most 3 bytes at the end of a Buffer in order to detect an
|
|
// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4)
|
|
// needed to complete the UTF-8 character (if applicable) are returned.
|
|
function utf8CheckIncomplete(self, buf, i) {
|
|
var j = buf.length - 1;
|
|
if (j < i) return 0;
|
|
var nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) self.lastNeed = nb - 1;
|
|
return nb;
|
|
}
|
|
if (--j < i) return 0;
|
|
nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) self.lastNeed = nb - 2;
|
|
return nb;
|
|
}
|
|
if (--j < i) return 0;
|
|
nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) {
|
|
if (nb === 2) nb = 0;else self.lastNeed = nb - 3;
|
|
}
|
|
return nb;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Validates as many continuation bytes for a multi-byte UTF-8 character as
|
|
// needed or are available. If we see a non-continuation byte where we expect
|
|
// one, we "replace" the validated continuation bytes we've seen so far with
|
|
// UTF-8 replacement characters ('\ufffd'), to match v8's UTF-8 decoding
|
|
// behavior. The continuation byte check is included three times in the case
|
|
// where all of the continuation bytes for a character exist in the same buffer.
|
|
// It is also done this way as a slight performance increase instead of using a
|
|
// loop.
|
|
function utf8CheckExtraBytes(self, buf, p) {
|
|
if ((buf[0] & 0xC0) !== 0x80) {
|
|
self.lastNeed = 0;
|
|
return '\ufffd'.repeat(p);
|
|
}
|
|
if (self.lastNeed > 1 && buf.length > 1) {
|
|
if ((buf[1] & 0xC0) !== 0x80) {
|
|
self.lastNeed = 1;
|
|
return '\ufffd'.repeat(p + 1);
|
|
}
|
|
if (self.lastNeed > 2 && buf.length > 2) {
|
|
if ((buf[2] & 0xC0) !== 0x80) {
|
|
self.lastNeed = 2;
|
|
return '\ufffd'.repeat(p + 2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer.
|
|
function utf8FillLast(buf) {
|
|
var p = this.lastTotal - this.lastNeed;
|
|
var r = utf8CheckExtraBytes(this, buf, p);
|
|
if (r !== undefined) return r;
|
|
if (this.lastNeed <= buf.length) {
|
|
buf.copy(this.lastChar, p, 0, this.lastNeed);
|
|
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
|
}
|
|
buf.copy(this.lastChar, p, 0, buf.length);
|
|
this.lastNeed -= buf.length;
|
|
}
|
|
|
|
// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a
|
|
// partial character, the character's bytes are buffered until the required
|
|
// number of bytes are available.
|
|
function utf8Text(buf, i) {
|
|
var total = utf8CheckIncomplete(this, buf, i);
|
|
if (!this.lastNeed) return buf.toString('utf8', i);
|
|
this.lastTotal = total;
|
|
var end = buf.length - (total - this.lastNeed);
|
|
buf.copy(this.lastChar, 0, end);
|
|
return buf.toString('utf8', i, end);
|
|
}
|
|
|
|
// For UTF-8, a replacement character for each buffered byte of a (partial)
|
|
// character needs to be added to the output.
|
|
function utf8End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : '';
|
|
if (this.lastNeed) return r + '\ufffd'.repeat(this.lastTotal - this.lastNeed);
|
|
return r;
|
|
}
|
|
|
|
// UTF-16LE typically needs two bytes per character, but even if we have an even
|
|
// number of bytes available, we need to check if we end on a leading/high
|
|
// surrogate. In that case, we need to wait for the next two bytes in order to
|
|
// decode the last character properly.
|
|
function utf16Text(buf, i) {
|
|
if ((buf.length - i) % 2 === 0) {
|
|
var r = buf.toString('utf16le', i);
|
|
if (r) {
|
|
var c = r.charCodeAt(r.length - 1);
|
|
if (c >= 0xD800 && c <= 0xDBFF) {
|
|
this.lastNeed = 2;
|
|
this.lastTotal = 4;
|
|
this.lastChar[0] = buf[buf.length - 2];
|
|
this.lastChar[1] = buf[buf.length - 1];
|
|
return r.slice(0, -1);
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
this.lastNeed = 1;
|
|
this.lastTotal = 2;
|
|
this.lastChar[0] = buf[buf.length - 1];
|
|
return buf.toString('utf16le', i, buf.length - 1);
|
|
}
|
|
|
|
// For UTF-16LE we do not explicitly append special replacement characters if we
|
|
// end on a partial character, we simply let v8 handle that.
|
|
function utf16End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : '';
|
|
if (this.lastNeed) {
|
|
var end = this.lastTotal - this.lastNeed;
|
|
return r + this.lastChar.toString('utf16le', 0, end);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
function base64Text(buf, i) {
|
|
var n = (buf.length - i) % 3;
|
|
if (n === 0) return buf.toString('base64', i);
|
|
this.lastNeed = 3 - n;
|
|
this.lastTotal = 3;
|
|
if (n === 1) {
|
|
this.lastChar[0] = buf[buf.length - 1];
|
|
} else {
|
|
this.lastChar[0] = buf[buf.length - 2];
|
|
this.lastChar[1] = buf[buf.length - 1];
|
|
}
|
|
return buf.toString('base64', i, buf.length - n);
|
|
}
|
|
|
|
function base64End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : '';
|
|
if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed);
|
|
return r;
|
|
}
|
|
|
|
// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex)
|
|
function simpleWrite(buf) {
|
|
return buf.toString(this.encoding);
|
|
}
|
|
|
|
function simpleEnd(buf) {
|
|
return buf && buf.length ? this.write(buf) : '';
|
|
}
|
|
},{"safe-buffer":265}],267:[function(require,module,exports){
|
|
(function (global){
|
|
|
|
/**
|
|
* Module exports.
|
|
*/
|
|
|
|
module.exports = deprecate;
|
|
|
|
/**
|
|
* Mark that a method should not be used.
|
|
* Returns a modified function which warns once by default.
|
|
*
|
|
* If `localStorage.noDeprecation = true` is set, then it is a no-op.
|
|
*
|
|
* If `localStorage.throwDeprecation = true` is set, then deprecated functions
|
|
* will throw an Error when invoked.
|
|
*
|
|
* If `localStorage.traceDeprecation = true` is set, then deprecated functions
|
|
* will invoke `console.trace()` instead of `console.error()`.
|
|
*
|
|
* @param {Function} fn - the function to deprecate
|
|
* @param {String} msg - the string to print to the console when `fn` is invoked
|
|
* @returns {Function} a new "deprecated" version of `fn`
|
|
* @api public
|
|
*/
|
|
|
|
function deprecate (fn, msg) {
|
|
if (config('noDeprecation')) {
|
|
return fn;
|
|
}
|
|
|
|
var warned = false;
|
|
function deprecated() {
|
|
if (!warned) {
|
|
if (config('throwDeprecation')) {
|
|
throw new Error(msg);
|
|
} else if (config('traceDeprecation')) {
|
|
console.trace(msg);
|
|
} else {
|
|
console.warn(msg);
|
|
}
|
|
warned = true;
|
|
}
|
|
return fn.apply(this, arguments);
|
|
}
|
|
|
|
return deprecated;
|
|
}
|
|
|
|
/**
|
|
* Checks `localStorage` for boolean values for the given `name`.
|
|
*
|
|
* @param {String} name
|
|
* @returns {Boolean}
|
|
* @api private
|
|
*/
|
|
|
|
function config (name) {
|
|
// accessing global.localStorage can trigger a DOMException in sandboxed iframes
|
|
try {
|
|
if (!global.localStorage) return false;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
var val = global.localStorage[name];
|
|
if (null == val) return false;
|
|
return String(val).toLowerCase() === 'true';
|
|
}
|
|
|
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{}],268:[function(require,module,exports){
|
|
module.exports = require('./readable').PassThrough
|
|
|
|
},{"./readable":269}],269:[function(require,module,exports){
|
|
exports = module.exports = require('./lib/_stream_readable.js');
|
|
exports.Stream = exports;
|
|
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');
|
|
|
|
},{"./lib/_stream_duplex.js":253,"./lib/_stream_passthrough.js":254,"./lib/_stream_readable.js":255,"./lib/_stream_transform.js":256,"./lib/_stream_writable.js":257}],270:[function(require,module,exports){
|
|
module.exports = require('./readable').Transform
|
|
|
|
},{"./readable":269}],271:[function(require,module,exports){
|
|
module.exports = require('./lib/_stream_writable.js');
|
|
|
|
},{"./lib/_stream_writable.js":257}],272:[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.
|
|
|
|
module.exports = Stream;
|
|
|
|
var EE = require('events').EventEmitter;
|
|
var inherits = require('inherits');
|
|
|
|
inherits(Stream, EE);
|
|
Stream.Readable = require('readable-stream/readable.js');
|
|
Stream.Writable = require('readable-stream/writable.js');
|
|
Stream.Duplex = require('readable-stream/duplex.js');
|
|
Stream.Transform = require('readable-stream/transform.js');
|
|
Stream.PassThrough = require('readable-stream/passthrough.js');
|
|
|
|
// Backwards-compat with node 0.4.x
|
|
Stream.Stream = Stream;
|
|
|
|
|
|
|
|
// old-style streams. Note that the pipe method (the only relevant
|
|
// part of this class) is overridden in the Readable class.
|
|
|
|
function Stream() {
|
|
EE.call(this);
|
|
}
|
|
|
|
Stream.prototype.pipe = function(dest, options) {
|
|
var source = this;
|
|
|
|
function ondata(chunk) {
|
|
if (dest.writable) {
|
|
if (false === dest.write(chunk) && source.pause) {
|
|
source.pause();
|
|
}
|
|
}
|
|
}
|
|
|
|
source.on('data', ondata);
|
|
|
|
function ondrain() {
|
|
if (source.readable && source.resume) {
|
|
source.resume();
|
|
}
|
|
}
|
|
|
|
dest.on('drain', ondrain);
|
|
|
|
// If the 'end' option is not supplied, dest.end() will be called when
|
|
// source gets the 'end' or 'close' events. Only dest.end() once.
|
|
if (!dest._isStdio && (!options || options.end !== false)) {
|
|
source.on('end', onend);
|
|
source.on('close', onclose);
|
|
}
|
|
|
|
var didOnEnd = false;
|
|
function onend() {
|
|
if (didOnEnd) return;
|
|
didOnEnd = true;
|
|
|
|
dest.end();
|
|
}
|
|
|
|
|
|
function onclose() {
|
|
if (didOnEnd) return;
|
|
didOnEnd = true;
|
|
|
|
if (typeof dest.destroy === 'function') dest.destroy();
|
|
}
|
|
|
|
// don't leave dangling pipes when there are errors.
|
|
function onerror(er) {
|
|
cleanup();
|
|
if (EE.listenerCount(this, 'error') === 0) {
|
|
throw er; // Unhandled stream error in pipe.
|
|
}
|
|
}
|
|
|
|
source.on('error', onerror);
|
|
dest.on('error', onerror);
|
|
|
|
// remove all the event listeners that were added.
|
|
function cleanup() {
|
|
source.removeListener('data', ondata);
|
|
dest.removeListener('drain', ondrain);
|
|
|
|
source.removeListener('end', onend);
|
|
source.removeListener('close', onclose);
|
|
|
|
source.removeListener('error', onerror);
|
|
dest.removeListener('error', onerror);
|
|
|
|
source.removeListener('end', cleanup);
|
|
source.removeListener('close', cleanup);
|
|
|
|
dest.removeListener('close', cleanup);
|
|
}
|
|
|
|
source.on('end', cleanup);
|
|
source.on('close', cleanup);
|
|
|
|
dest.on('close', cleanup);
|
|
|
|
dest.emit('pipe', source);
|
|
|
|
// Allow for unix-like usage: A.pipe(B).pipe(C)
|
|
return dest;
|
|
};
|
|
|
|
},{"events":245,"inherits":318,"readable-stream/duplex.js":252,"readable-stream/passthrough.js":268,"readable-stream/readable.js":269,"readable-stream/transform.js":270,"readable-stream/writable.js":271}],273:[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 Buffer = require('buffer').Buffer;
|
|
|
|
var isBufferEncoding = Buffer.isEncoding
|
|
|| function(encoding) {
|
|
switch (encoding && encoding.toLowerCase()) {
|
|
case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
|
|
function assertEncoding(encoding) {
|
|
if (encoding && !isBufferEncoding(encoding)) {
|
|
throw new Error('Unknown encoding: ' + encoding);
|
|
}
|
|
}
|
|
|
|
// StringDecoder provides an interface for efficiently splitting a series of
|
|
// buffers into a series of JS strings without breaking apart multi-byte
|
|
// characters. CESU-8 is handled as part of the UTF-8 encoding.
|
|
//
|
|
// @TODO Handling all encodings inside a single object makes it very difficult
|
|
// to reason about this code, so it should be split up in the future.
|
|
// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
|
|
// points as used by CESU-8.
|
|
var StringDecoder = exports.StringDecoder = function(encoding) {
|
|
this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
|
|
assertEncoding(encoding);
|
|
switch (this.encoding) {
|
|
case 'utf8':
|
|
// CESU-8 represents each of Surrogate Pair by 3-bytes
|
|
this.surrogateSize = 3;
|
|
break;
|
|
case 'ucs2':
|
|
case 'utf16le':
|
|
// UTF-16 represents each of Surrogate Pair by 2-bytes
|
|
this.surrogateSize = 2;
|
|
this.detectIncompleteChar = utf16DetectIncompleteChar;
|
|
break;
|
|
case 'base64':
|
|
// Base-64 stores 3 bytes in 4 chars, and pads the remainder.
|
|
this.surrogateSize = 3;
|
|
this.detectIncompleteChar = base64DetectIncompleteChar;
|
|
break;
|
|
default:
|
|
this.write = passThroughWrite;
|
|
return;
|
|
}
|
|
|
|
// Enough space to store all bytes of a single character. UTF-8 needs 4
|
|
// bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
|
|
this.charBuffer = new Buffer(6);
|
|
// Number of bytes received for the current incomplete multi-byte character.
|
|
this.charReceived = 0;
|
|
// Number of bytes expected for the current incomplete multi-byte character.
|
|
this.charLength = 0;
|
|
};
|
|
|
|
|
|
// write decodes the given buffer and returns it as JS string that is
|
|
// guaranteed to not contain any partial multi-byte characters. Any partial
|
|
// character found at the end of the buffer is buffered up, and will be
|
|
// returned when calling write again with the remaining bytes.
|
|
//
|
|
// Note: Converting a Buffer containing an orphan surrogate to a String
|
|
// currently works, but converting a String to a Buffer (via `new Buffer`, or
|
|
// Buffer#write) will replace incomplete surrogates with the unicode
|
|
// replacement character. See https://codereview.chromium.org/121173009/ .
|
|
StringDecoder.prototype.write = function(buffer) {
|
|
var charStr = '';
|
|
// if our last write ended with an incomplete multibyte character
|
|
while (this.charLength) {
|
|
// determine how many remaining bytes this buffer has to offer for this char
|
|
var available = (buffer.length >= this.charLength - this.charReceived) ?
|
|
this.charLength - this.charReceived :
|
|
buffer.length;
|
|
|
|
// add the new bytes to the char buffer
|
|
buffer.copy(this.charBuffer, this.charReceived, 0, available);
|
|
this.charReceived += available;
|
|
|
|
if (this.charReceived < this.charLength) {
|
|
// still not enough chars in this buffer? wait for more ...
|
|
return '';
|
|
}
|
|
|
|
// remove bytes belonging to the current character from the buffer
|
|
buffer = buffer.slice(available, buffer.length);
|
|
|
|
// get the character that was split
|
|
charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
|
|
|
|
// CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
|
|
var charCode = charStr.charCodeAt(charStr.length - 1);
|
|
if (charCode >= 0xD800 && charCode <= 0xDBFF) {
|
|
this.charLength += this.surrogateSize;
|
|
charStr = '';
|
|
continue;
|
|
}
|
|
this.charReceived = this.charLength = 0;
|
|
|
|
// if there are no more bytes in this buffer, just emit our char
|
|
if (buffer.length === 0) {
|
|
return charStr;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// determine and set charLength / charReceived
|
|
this.detectIncompleteChar(buffer);
|
|
|
|
var end = buffer.length;
|
|
if (this.charLength) {
|
|
// buffer the incomplete character bytes we got
|
|
buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
|
|
end -= this.charReceived;
|
|
}
|
|
|
|
charStr += buffer.toString(this.encoding, 0, end);
|
|
|
|
var end = charStr.length - 1;
|
|
var charCode = charStr.charCodeAt(end);
|
|
// CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
|
|
if (charCode >= 0xD800 && charCode <= 0xDBFF) {
|
|
var size = this.surrogateSize;
|
|
this.charLength += size;
|
|
this.charReceived += size;
|
|
this.charBuffer.copy(this.charBuffer, size, 0, size);
|
|
buffer.copy(this.charBuffer, 0, 0, size);
|
|
return charStr.substring(0, end);
|
|
}
|
|
|
|
// or just emit the charStr
|
|
return charStr;
|
|
};
|
|
|
|
// detectIncompleteChar determines if there is an incomplete UTF-8 character at
|
|
// the end of the given buffer. If so, it sets this.charLength to the byte
|
|
// length that character, and sets this.charReceived to the number of bytes
|
|
// that are available for this character.
|
|
StringDecoder.prototype.detectIncompleteChar = function(buffer) {
|
|
// determine how many bytes we have to check at the end of this buffer
|
|
var i = (buffer.length >= 3) ? 3 : buffer.length;
|
|
|
|
// Figure out if one of the last i bytes of our buffer announces an
|
|
// incomplete char.
|
|
for (; i > 0; i--) {
|
|
var c = buffer[buffer.length - i];
|
|
|
|
// See http://en.wikipedia.org/wiki/UTF-8#Description
|
|
|
|
// 110XXXXX
|
|
if (i == 1 && c >> 5 == 0x06) {
|
|
this.charLength = 2;
|
|
break;
|
|
}
|
|
|
|
// 1110XXXX
|
|
if (i <= 2 && c >> 4 == 0x0E) {
|
|
this.charLength = 3;
|
|
break;
|
|
}
|
|
|
|
// 11110XXX
|
|
if (i <= 3 && c >> 3 == 0x1E) {
|
|
this.charLength = 4;
|
|
break;
|
|
}
|
|
}
|
|
this.charReceived = i;
|
|
};
|
|
|
|
StringDecoder.prototype.end = function(buffer) {
|
|
var res = '';
|
|
if (buffer && buffer.length)
|
|
res = this.write(buffer);
|
|
|
|
if (this.charReceived) {
|
|
var cr = this.charReceived;
|
|
var buf = this.charBuffer;
|
|
var enc = this.encoding;
|
|
res += buf.slice(0, cr).toString(enc);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
function passThroughWrite(buffer) {
|
|
return buffer.toString(this.encoding);
|
|
}
|
|
|
|
function utf16DetectIncompleteChar(buffer) {
|
|
this.charReceived = buffer.length % 2;
|
|
this.charLength = this.charReceived ? 2 : 0;
|
|
}
|
|
|
|
function base64DetectIncompleteChar(buffer) {
|
|
this.charReceived = buffer.length % 3;
|
|
this.charLength = this.charReceived ? 3 : 0;
|
|
}
|
|
|
|
},{"buffer":47}],274:[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.
|
|
|
|
'use strict';
|
|
|
|
var punycode = require('punycode');
|
|
var util = require('./util');
|
|
|
|
exports.parse = urlParse;
|
|
exports.resolve = urlResolve;
|
|
exports.resolveObject = urlResolveObject;
|
|
exports.format = urlFormat;
|
|
|
|
exports.Url = Url;
|
|
|
|
function Url() {
|
|
this.protocol = null;
|
|
this.slashes = null;
|
|
this.auth = null;
|
|
this.host = null;
|
|
this.port = null;
|
|
this.hostname = null;
|
|
this.hash = null;
|
|
this.search = null;
|
|
this.query = null;
|
|
this.pathname = null;
|
|
this.path = null;
|
|
this.href = null;
|
|
}
|
|
|
|
// Reference: RFC 3986, RFC 1808, RFC 2396
|
|
|
|
// define these here so at least they only have to be
|
|
// compiled once on the first module load.
|
|
var protocolPattern = /^([a-z0-9.+-]+:)/i,
|
|
portPattern = /:[0-9]*$/,
|
|
|
|
// Special case for a simple path URL
|
|
simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
|
|
|
|
// RFC 2396: characters reserved for delimiting URLs.
|
|
// We actually just auto-escape these.
|
|
delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
|
|
|
|
// RFC 2396: characters not allowed for various reasons.
|
|
unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
|
|
|
|
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
|
|
autoEscape = ['\''].concat(unwise),
|
|
// Characters that are never ever allowed in a hostname.
|
|
// Note that any invalid chars are also handled, but these
|
|
// are the ones that are *expected* to be seen, so we fast-path
|
|
// them.
|
|
nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
|
|
hostEndingChars = ['/', '?', '#'],
|
|
hostnameMaxLen = 255,
|
|
hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
|
|
hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
|
|
// protocols that can allow "unsafe" and "unwise" chars.
|
|
unsafeProtocol = {
|
|
'javascript': true,
|
|
'javascript:': true
|
|
},
|
|
// protocols that never have a hostname.
|
|
hostlessProtocol = {
|
|
'javascript': true,
|
|
'javascript:': true
|
|
},
|
|
// protocols that always contain a // bit.
|
|
slashedProtocol = {
|
|
'http': true,
|
|
'https': true,
|
|
'ftp': true,
|
|
'gopher': true,
|
|
'file': true,
|
|
'http:': true,
|
|
'https:': true,
|
|
'ftp:': true,
|
|
'gopher:': true,
|
|
'file:': true
|
|
},
|
|
querystring = require('querystring');
|
|
|
|
function urlParse(url, parseQueryString, slashesDenoteHost) {
|
|
if (url && util.isObject(url) && url instanceof Url) return url;
|
|
|
|
var u = new Url;
|
|
u.parse(url, parseQueryString, slashesDenoteHost);
|
|
return u;
|
|
}
|
|
|
|
Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
|
|
if (!util.isString(url)) {
|
|
throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
|
|
}
|
|
|
|
// Copy chrome, IE, opera backslash-handling behavior.
|
|
// Back slashes before the query string get converted to forward slashes
|
|
// See: https://code.google.com/p/chromium/issues/detail?id=25916
|
|
var queryIndex = url.indexOf('?'),
|
|
splitter =
|
|
(queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
|
|
uSplit = url.split(splitter),
|
|
slashRegex = /\\/g;
|
|
uSplit[0] = uSplit[0].replace(slashRegex, '/');
|
|
url = uSplit.join(splitter);
|
|
|
|
var rest = url;
|
|
|
|
// trim before proceeding.
|
|
// This is to support parse stuff like " http://foo.com \n"
|
|
rest = rest.trim();
|
|
|
|
if (!slashesDenoteHost && url.split('#').length === 1) {
|
|
// Try fast path regexp
|
|
var simplePath = simplePathPattern.exec(rest);
|
|
if (simplePath) {
|
|
this.path = rest;
|
|
this.href = rest;
|
|
this.pathname = simplePath[1];
|
|
if (simplePath[2]) {
|
|
this.search = simplePath[2];
|
|
if (parseQueryString) {
|
|
this.query = querystring.parse(this.search.substr(1));
|
|
} else {
|
|
this.query = this.search.substr(1);
|
|
}
|
|
} else if (parseQueryString) {
|
|
this.search = '';
|
|
this.query = {};
|
|
}
|
|
return this;
|
|
}
|
|
}
|
|
|
|
var proto = protocolPattern.exec(rest);
|
|
if (proto) {
|
|
proto = proto[0];
|
|
var lowerProto = proto.toLowerCase();
|
|
this.protocol = lowerProto;
|
|
rest = rest.substr(proto.length);
|
|
}
|
|
|
|
// figure out if it's got a host
|
|
// user@server is *always* interpreted as a hostname, and url
|
|
// resolution will treat //foo/bar as host=foo,path=bar because that's
|
|
// how the browser resolves relative URLs.
|
|
if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
|
|
var slashes = rest.substr(0, 2) === '//';
|
|
if (slashes && !(proto && hostlessProtocol[proto])) {
|
|
rest = rest.substr(2);
|
|
this.slashes = true;
|
|
}
|
|
}
|
|
|
|
if (!hostlessProtocol[proto] &&
|
|
(slashes || (proto && !slashedProtocol[proto]))) {
|
|
|
|
// there's a hostname.
|
|
// the first instance of /, ?, ;, or # ends the host.
|
|
//
|
|
// If there is an @ in the hostname, then non-host chars *are* allowed
|
|
// to the left of the last @ sign, unless some host-ending character
|
|
// comes *before* the @-sign.
|
|
// URLs are obnoxious.
|
|
//
|
|
// ex:
|
|
// http://a@b@c/ => user:a@b host:c
|
|
// http://a@b?@c => user:a host:c path:/?@c
|
|
|
|
// v0.12 TODO(isaacs): This is not quite how Chrome does things.
|
|
// Review our test case against browsers more comprehensively.
|
|
|
|
// find the first instance of any hostEndingChars
|
|
var hostEnd = -1;
|
|
for (var i = 0; i < hostEndingChars.length; i++) {
|
|
var hec = rest.indexOf(hostEndingChars[i]);
|
|
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
|
|
hostEnd = hec;
|
|
}
|
|
|
|
// at this point, either we have an explicit point where the
|
|
// auth portion cannot go past, or the last @ char is the decider.
|
|
var auth, atSign;
|
|
if (hostEnd === -1) {
|
|
// atSign can be anywhere.
|
|
atSign = rest.lastIndexOf('@');
|
|
} else {
|
|
// atSign must be in auth portion.
|
|
// http://a@b/c@d => host:b auth:a path:/c@d
|
|
atSign = rest.lastIndexOf('@', hostEnd);
|
|
}
|
|
|
|
// Now we have a portion which is definitely the auth.
|
|
// Pull that off.
|
|
if (atSign !== -1) {
|
|
auth = rest.slice(0, atSign);
|
|
rest = rest.slice(atSign + 1);
|
|
this.auth = decodeURIComponent(auth);
|
|
}
|
|
|
|
// the host is the remaining to the left of the first non-host char
|
|
hostEnd = -1;
|
|
for (var i = 0; i < nonHostChars.length; i++) {
|
|
var hec = rest.indexOf(nonHostChars[i]);
|
|
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
|
|
hostEnd = hec;
|
|
}
|
|
// if we still have not hit it, then the entire thing is a host.
|
|
if (hostEnd === -1)
|
|
hostEnd = rest.length;
|
|
|
|
this.host = rest.slice(0, hostEnd);
|
|
rest = rest.slice(hostEnd);
|
|
|
|
// pull out port.
|
|
this.parseHost();
|
|
|
|
// we've indicated that there is a hostname,
|
|
// so even if it's empty, it has to be present.
|
|
this.hostname = this.hostname || '';
|
|
|
|
// if hostname begins with [ and ends with ]
|
|
// assume that it's an IPv6 address.
|
|
var ipv6Hostname = this.hostname[0] === '[' &&
|
|
this.hostname[this.hostname.length - 1] === ']';
|
|
|
|
// validate a little.
|
|
if (!ipv6Hostname) {
|
|
var hostparts = this.hostname.split(/\./);
|
|
for (var i = 0, l = hostparts.length; i < l; i++) {
|
|
var part = hostparts[i];
|
|
if (!part) continue;
|
|
if (!part.match(hostnamePartPattern)) {
|
|
var newpart = '';
|
|
for (var j = 0, k = part.length; j < k; j++) {
|
|
if (part.charCodeAt(j) > 127) {
|
|
// we replace non-ASCII char with a temporary placeholder
|
|
// we need this to make sure size of hostname is not
|
|
// broken by replacing non-ASCII by nothing
|
|
newpart += 'x';
|
|
} else {
|
|
newpart += part[j];
|
|
}
|
|
}
|
|
// we test again with ASCII char only
|
|
if (!newpart.match(hostnamePartPattern)) {
|
|
var validParts = hostparts.slice(0, i);
|
|
var notHost = hostparts.slice(i + 1);
|
|
var bit = part.match(hostnamePartStart);
|
|
if (bit) {
|
|
validParts.push(bit[1]);
|
|
notHost.unshift(bit[2]);
|
|
}
|
|
if (notHost.length) {
|
|
rest = '/' + notHost.join('.') + rest;
|
|
}
|
|
this.hostname = validParts.join('.');
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.hostname.length > hostnameMaxLen) {
|
|
this.hostname = '';
|
|
} else {
|
|
// hostnames are always lower case.
|
|
this.hostname = this.hostname.toLowerCase();
|
|
}
|
|
|
|
if (!ipv6Hostname) {
|
|
// IDNA Support: Returns a punycoded representation of "domain".
|
|
// It only converts parts of the domain name that
|
|
// have non-ASCII characters, i.e. it doesn't matter if
|
|
// you call it with a domain that already is ASCII-only.
|
|
this.hostname = punycode.toASCII(this.hostname);
|
|
}
|
|
|
|
var p = this.port ? ':' + this.port : '';
|
|
var h = this.hostname || '';
|
|
this.host = h + p;
|
|
this.href += this.host;
|
|
|
|
// strip [ and ] from the hostname
|
|
// the host field still retains them, though
|
|
if (ipv6Hostname) {
|
|
this.hostname = this.hostname.substr(1, this.hostname.length - 2);
|
|
if (rest[0] !== '/') {
|
|
rest = '/' + rest;
|
|
}
|
|
}
|
|
}
|
|
|
|
// now rest is set to the post-host stuff.
|
|
// chop off any delim chars.
|
|
if (!unsafeProtocol[lowerProto]) {
|
|
|
|
// First, make 100% sure that any "autoEscape" chars get
|
|
// escaped, even if encodeURIComponent doesn't think they
|
|
// need to be.
|
|
for (var i = 0, l = autoEscape.length; i < l; i++) {
|
|
var ae = autoEscape[i];
|
|
if (rest.indexOf(ae) === -1)
|
|
continue;
|
|
var esc = encodeURIComponent(ae);
|
|
if (esc === ae) {
|
|
esc = escape(ae);
|
|
}
|
|
rest = rest.split(ae).join(esc);
|
|
}
|
|
}
|
|
|
|
|
|
// chop off from the tail first.
|
|
var hash = rest.indexOf('#');
|
|
if (hash !== -1) {
|
|
// got a fragment string.
|
|
this.hash = rest.substr(hash);
|
|
rest = rest.slice(0, hash);
|
|
}
|
|
var qm = rest.indexOf('?');
|
|
if (qm !== -1) {
|
|
this.search = rest.substr(qm);
|
|
this.query = rest.substr(qm + 1);
|
|
if (parseQueryString) {
|
|
this.query = querystring.parse(this.query);
|
|
}
|
|
rest = rest.slice(0, qm);
|
|
} else if (parseQueryString) {
|
|
// no query string, but parseQueryString still requested
|
|
this.search = '';
|
|
this.query = {};
|
|
}
|
|
if (rest) this.pathname = rest;
|
|
if (slashedProtocol[lowerProto] &&
|
|
this.hostname && !this.pathname) {
|
|
this.pathname = '/';
|
|
}
|
|
|
|
//to support http.request
|
|
if (this.pathname || this.search) {
|
|
var p = this.pathname || '';
|
|
var s = this.search || '';
|
|
this.path = p + s;
|
|
}
|
|
|
|
// finally, reconstruct the href based on what has been validated.
|
|
this.href = this.format();
|
|
return this;
|
|
};
|
|
|
|
// format a parsed object into a url string
|
|
function urlFormat(obj) {
|
|
// ensure it's an object, and not a string url.
|
|
// If it's an obj, this is a no-op.
|
|
// this way, you can call url_format() on strings
|
|
// to clean up potentially wonky urls.
|
|
if (util.isString(obj)) obj = urlParse(obj);
|
|
if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
|
|
return obj.format();
|
|
}
|
|
|
|
Url.prototype.format = function() {
|
|
var auth = this.auth || '';
|
|
if (auth) {
|
|
auth = encodeURIComponent(auth);
|
|
auth = auth.replace(/%3A/i, ':');
|
|
auth += '@';
|
|
}
|
|
|
|
var protocol = this.protocol || '',
|
|
pathname = this.pathname || '',
|
|
hash = this.hash || '',
|
|
host = false,
|
|
query = '';
|
|
|
|
if (this.host) {
|
|
host = auth + this.host;
|
|
} else if (this.hostname) {
|
|
host = auth + (this.hostname.indexOf(':') === -1 ?
|
|
this.hostname :
|
|
'[' + this.hostname + ']');
|
|
if (this.port) {
|
|
host += ':' + this.port;
|
|
}
|
|
}
|
|
|
|
if (this.query &&
|
|
util.isObject(this.query) &&
|
|
Object.keys(this.query).length) {
|
|
query = querystring.stringify(this.query);
|
|
}
|
|
|
|
var search = this.search || (query && ('?' + query)) || '';
|
|
|
|
if (protocol && protocol.substr(-1) !== ':') protocol += ':';
|
|
|
|
// only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
|
|
// unless they had them to begin with.
|
|
if (this.slashes ||
|
|
(!protocol || slashedProtocol[protocol]) && host !== false) {
|
|
host = '//' + (host || '');
|
|
if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
|
|
} else if (!host) {
|
|
host = '';
|
|
}
|
|
|
|
if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
|
|
if (search && search.charAt(0) !== '?') search = '?' + search;
|
|
|
|
pathname = pathname.replace(/[?#]/g, function(match) {
|
|
return encodeURIComponent(match);
|
|
});
|
|
search = search.replace('#', '%23');
|
|
|
|
return protocol + host + pathname + search + hash;
|
|
};
|
|
|
|
function urlResolve(source, relative) {
|
|
return urlParse(source, false, true).resolve(relative);
|
|
}
|
|
|
|
Url.prototype.resolve = function(relative) {
|
|
return this.resolveObject(urlParse(relative, false, true)).format();
|
|
};
|
|
|
|
function urlResolveObject(source, relative) {
|
|
if (!source) return relative;
|
|
return urlParse(source, false, true).resolveObject(relative);
|
|
}
|
|
|
|
Url.prototype.resolveObject = function(relative) {
|
|
if (util.isString(relative)) {
|
|
var rel = new Url();
|
|
rel.parse(relative, false, true);
|
|
relative = rel;
|
|
}
|
|
|
|
var result = new Url();
|
|
var tkeys = Object.keys(this);
|
|
for (var tk = 0; tk < tkeys.length; tk++) {
|
|
var tkey = tkeys[tk];
|
|
result[tkey] = this[tkey];
|
|
}
|
|
|
|
// hash is always overridden, no matter what.
|
|
// even href="" will remove it.
|
|
result.hash = relative.hash;
|
|
|
|
// if the relative url is empty, then there's nothing left to do here.
|
|
if (relative.href === '') {
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
// hrefs like //foo/bar always cut to the protocol.
|
|
if (relative.slashes && !relative.protocol) {
|
|
// take everything except the protocol from relative
|
|
var rkeys = Object.keys(relative);
|
|
for (var rk = 0; rk < rkeys.length; rk++) {
|
|
var rkey = rkeys[rk];
|
|
if (rkey !== 'protocol')
|
|
result[rkey] = relative[rkey];
|
|
}
|
|
|
|
//urlParse appends trailing / to urls like http://www.example.com
|
|
if (slashedProtocol[result.protocol] &&
|
|
result.hostname && !result.pathname) {
|
|
result.path = result.pathname = '/';
|
|
}
|
|
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
if (relative.protocol && relative.protocol !== result.protocol) {
|
|
// if it's a known url protocol, then changing
|
|
// the protocol does weird things
|
|
// first, if it's not file:, then we MUST have a host,
|
|
// and if there was a path
|
|
// to begin with, then we MUST have a path.
|
|
// if it is file:, then the host is dropped,
|
|
// because that's known to be hostless.
|
|
// anything else is assumed to be absolute.
|
|
if (!slashedProtocol[relative.protocol]) {
|
|
var keys = Object.keys(relative);
|
|
for (var v = 0; v < keys.length; v++) {
|
|
var k = keys[v];
|
|
result[k] = relative[k];
|
|
}
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
result.protocol = relative.protocol;
|
|
if (!relative.host && !hostlessProtocol[relative.protocol]) {
|
|
var relPath = (relative.pathname || '').split('/');
|
|
while (relPath.length && !(relative.host = relPath.shift()));
|
|
if (!relative.host) relative.host = '';
|
|
if (!relative.hostname) relative.hostname = '';
|
|
if (relPath[0] !== '') relPath.unshift('');
|
|
if (relPath.length < 2) relPath.unshift('');
|
|
result.pathname = relPath.join('/');
|
|
} else {
|
|
result.pathname = relative.pathname;
|
|
}
|
|
result.search = relative.search;
|
|
result.query = relative.query;
|
|
result.host = relative.host || '';
|
|
result.auth = relative.auth;
|
|
result.hostname = relative.hostname || relative.host;
|
|
result.port = relative.port;
|
|
// to support http.request
|
|
if (result.pathname || result.search) {
|
|
var p = result.pathname || '';
|
|
var s = result.search || '';
|
|
result.path = p + s;
|
|
}
|
|
result.slashes = result.slashes || relative.slashes;
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
|
|
isRelAbs = (
|
|
relative.host ||
|
|
relative.pathname && relative.pathname.charAt(0) === '/'
|
|
),
|
|
mustEndAbs = (isRelAbs || isSourceAbs ||
|
|
(result.host && relative.pathname)),
|
|
removeAllDots = mustEndAbs,
|
|
srcPath = result.pathname && result.pathname.split('/') || [],
|
|
relPath = relative.pathname && relative.pathname.split('/') || [],
|
|
psychotic = result.protocol && !slashedProtocol[result.protocol];
|
|
|
|
// if the url is a non-slashed url, then relative
|
|
// links like ../.. should be able
|
|
// to crawl up to the hostname, as well. This is strange.
|
|
// result.protocol has already been set by now.
|
|
// Later on, put the first path part into the host field.
|
|
if (psychotic) {
|
|
result.hostname = '';
|
|
result.port = null;
|
|
if (result.host) {
|
|
if (srcPath[0] === '') srcPath[0] = result.host;
|
|
else srcPath.unshift(result.host);
|
|
}
|
|
result.host = '';
|
|
if (relative.protocol) {
|
|
relative.hostname = null;
|
|
relative.port = null;
|
|
if (relative.host) {
|
|
if (relPath[0] === '') relPath[0] = relative.host;
|
|
else relPath.unshift(relative.host);
|
|
}
|
|
relative.host = null;
|
|
}
|
|
mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
|
|
}
|
|
|
|
if (isRelAbs) {
|
|
// it's absolute.
|
|
result.host = (relative.host || relative.host === '') ?
|
|
relative.host : result.host;
|
|
result.hostname = (relative.hostname || relative.hostname === '') ?
|
|
relative.hostname : result.hostname;
|
|
result.search = relative.search;
|
|
result.query = relative.query;
|
|
srcPath = relPath;
|
|
// fall through to the dot-handling below.
|
|
} else if (relPath.length) {
|
|
// it's relative
|
|
// throw away the existing file, and take the new path instead.
|
|
if (!srcPath) srcPath = [];
|
|
srcPath.pop();
|
|
srcPath = srcPath.concat(relPath);
|
|
result.search = relative.search;
|
|
result.query = relative.query;
|
|
} else if (!util.isNullOrUndefined(relative.search)) {
|
|
// just pull out the search.
|
|
// like href='?foo'.
|
|
// Put this after the other two cases because it simplifies the booleans
|
|
if (psychotic) {
|
|
result.hostname = result.host = srcPath.shift();
|
|
//occationaly the auth can get stuck only in host
|
|
//this especially happens in cases like
|
|
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
|
|
var authInHost = result.host && result.host.indexOf('@') > 0 ?
|
|
result.host.split('@') : false;
|
|
if (authInHost) {
|
|
result.auth = authInHost.shift();
|
|
result.host = result.hostname = authInHost.shift();
|
|
}
|
|
}
|
|
result.search = relative.search;
|
|
result.query = relative.query;
|
|
//to support http.request
|
|
if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
|
|
result.path = (result.pathname ? result.pathname : '') +
|
|
(result.search ? result.search : '');
|
|
}
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
if (!srcPath.length) {
|
|
// no path at all. easy.
|
|
// we've already handled the other stuff above.
|
|
result.pathname = null;
|
|
//to support http.request
|
|
if (result.search) {
|
|
result.path = '/' + result.search;
|
|
} else {
|
|
result.path = null;
|
|
}
|
|
result.href = result.format();
|
|
return result;
|
|
}
|
|
|
|
// if a url ENDs in . or .., then it must get a trailing slash.
|
|
// however, if it ends in anything else non-slashy,
|
|
// then it must NOT get a trailing slash.
|
|
var last = srcPath.slice(-1)[0];
|
|
var hasTrailingSlash = (
|
|
(result.host || relative.host || srcPath.length > 1) &&
|
|
(last === '.' || last === '..') || last === '');
|
|
|
|
// strip single dots, resolve double dots to parent dir
|
|
// if the path tries to go above the root, `up` ends up > 0
|
|
var up = 0;
|
|
for (var i = srcPath.length; i >= 0; i--) {
|
|
last = srcPath[i];
|
|
if (last === '.') {
|
|
srcPath.splice(i, 1);
|
|
} else if (last === '..') {
|
|
srcPath.splice(i, 1);
|
|
up++;
|
|
} else if (up) {
|
|
srcPath.splice(i, 1);
|
|
up--;
|
|
}
|
|
}
|
|
|
|
// if the path is allowed to go above the root, restore leading ..s
|
|
if (!mustEndAbs && !removeAllDots) {
|
|
for (; up--; up) {
|
|
srcPath.unshift('..');
|
|
}
|
|
}
|
|
|
|
if (mustEndAbs && srcPath[0] !== '' &&
|
|
(!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
|
|
srcPath.unshift('');
|
|
}
|
|
|
|
if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
|
|
srcPath.push('');
|
|
}
|
|
|
|
var isAbsolute = srcPath[0] === '' ||
|
|
(srcPath[0] && srcPath[0].charAt(0) === '/');
|
|
|
|
// put the host back
|
|
if (psychotic) {
|
|
result.hostname = result.host = isAbsolute ? '' :
|
|
srcPath.length ? srcPath.shift() : '';
|
|
//occationaly the auth can get stuck only in host
|
|
//this especially happens in cases like
|
|
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
|
|
var authInHost = result.host && result.host.indexOf('@') > 0 ?
|
|
result.host.split('@') : false;
|
|
if (authInHost) {
|
|
result.auth = authInHost.shift();
|
|
result.host = result.hostname = authInHost.shift();
|
|
}
|
|
}
|
|
|
|
mustEndAbs = mustEndAbs || (result.host && srcPath.length);
|
|
|
|
if (mustEndAbs && !isAbsolute) {
|
|
srcPath.unshift('');
|
|
}
|
|
|
|
if (!srcPath.length) {
|
|
result.pathname = null;
|
|
result.path = null;
|
|
} else {
|
|
result.pathname = srcPath.join('/');
|
|
}
|
|
|
|
//to support request.http
|
|
if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
|
|
result.path = (result.pathname ? result.pathname : '') +
|
|
(result.search ? result.search : '');
|
|
}
|
|
result.auth = relative.auth || result.auth;
|
|
result.slashes = result.slashes || relative.slashes;
|
|
result.href = result.format();
|
|
return result;
|
|
};
|
|
|
|
Url.prototype.parseHost = function() {
|
|
var host = this.host;
|
|
var port = portPattern.exec(host);
|
|
if (port) {
|
|
port = port[0];
|
|
if (port !== ':') {
|
|
this.port = port.substr(1);
|
|
}
|
|
host = host.substr(0, host.length - port.length);
|
|
}
|
|
if (host) this.hostname = host;
|
|
};
|
|
|
|
},{"./util":275,"punycode":248,"querystring":251}],275:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
module.exports = {
|
|
isString: function(arg) {
|
|
return typeof(arg) === 'string';
|
|
},
|
|
isObject: function(arg) {
|
|
return typeof(arg) === 'object' && arg !== null;
|
|
},
|
|
isNull: function(arg) {
|
|
return arg === null;
|
|
},
|
|
isNullOrUndefined: function(arg) {
|
|
return arg == null;
|
|
}
|
|
};
|
|
|
|
},{}],276:[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';
|
|
}
|
|
},{}],277:[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":276,"_process":247,"inherits":318}],278:[function(require,module,exports){
|
|
var indexOf = require('indexof');
|
|
|
|
var Object_keys = function (obj) {
|
|
if (Object.keys) return Object.keys(obj)
|
|
else {
|
|
var res = [];
|
|
for (var key in obj) res.push(key)
|
|
return res;
|
|
}
|
|
};
|
|
|
|
var forEach = function (xs, fn) {
|
|
if (xs.forEach) return xs.forEach(fn)
|
|
else for (var i = 0; i < xs.length; i++) {
|
|
fn(xs[i], i, xs);
|
|
}
|
|
};
|
|
|
|
var defineProp = (function() {
|
|
try {
|
|
Object.defineProperty({}, '_', {});
|
|
return function(obj, name, value) {
|
|
Object.defineProperty(obj, name, {
|
|
writable: true,
|
|
enumerable: false,
|
|
configurable: true,
|
|
value: value
|
|
})
|
|
};
|
|
} catch(e) {
|
|
return function(obj, name, value) {
|
|
obj[name] = value;
|
|
};
|
|
}
|
|
}());
|
|
|
|
var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function',
|
|
'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError',
|
|
'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError',
|
|
'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape',
|
|
'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined', 'unescape'];
|
|
|
|
function Context() {}
|
|
Context.prototype = {};
|
|
|
|
var Script = exports.Script = function NodeScript (code) {
|
|
if (!(this instanceof Script)) return new Script(code);
|
|
this.code = code;
|
|
};
|
|
|
|
Script.prototype.runInContext = function (context) {
|
|
if (!(context instanceof Context)) {
|
|
throw new TypeError("needs a 'context' argument.");
|
|
}
|
|
|
|
var iframe = document.createElement('iframe');
|
|
if (!iframe.style) iframe.style = {};
|
|
iframe.style.display = 'none';
|
|
|
|
document.body.appendChild(iframe);
|
|
|
|
var win = iframe.contentWindow;
|
|
var wEval = win.eval, wExecScript = win.execScript;
|
|
|
|
if (!wEval && wExecScript) {
|
|
// win.eval() magically appears when this is called in IE:
|
|
wExecScript.call(win, 'null');
|
|
wEval = win.eval;
|
|
}
|
|
|
|
forEach(Object_keys(context), function (key) {
|
|
win[key] = context[key];
|
|
});
|
|
forEach(globals, function (key) {
|
|
if (context[key]) {
|
|
win[key] = context[key];
|
|
}
|
|
});
|
|
|
|
var winKeys = Object_keys(win);
|
|
|
|
var res = wEval.call(win, this.code);
|
|
|
|
forEach(Object_keys(win), function (key) {
|
|
// Avoid copying circular objects like `top` and `window` by only
|
|
// updating existing context properties or new properties in the `win`
|
|
// that was only introduced after the eval.
|
|
if (key in context || indexOf(winKeys, key) === -1) {
|
|
context[key] = win[key];
|
|
}
|
|
});
|
|
|
|
forEach(globals, function (key) {
|
|
if (!(key in context)) {
|
|
defineProp(context, key, win[key]);
|
|
}
|
|
});
|
|
|
|
document.body.removeChild(iframe);
|
|
|
|
return res;
|
|
};
|
|
|
|
Script.prototype.runInThisContext = function () {
|
|
return eval(this.code); // maybe...
|
|
};
|
|
|
|
Script.prototype.runInNewContext = function (context) {
|
|
var ctx = Script.createContext(context);
|
|
var res = this.runInContext(ctx);
|
|
|
|
forEach(Object_keys(ctx), function (key) {
|
|
context[key] = ctx[key];
|
|
});
|
|
|
|
return res;
|
|
};
|
|
|
|
forEach(Object_keys(Script.prototype), function (name) {
|
|
exports[name] = Script[name] = function (code) {
|
|
var s = Script(code);
|
|
return s[name].apply(s, [].slice.call(arguments, 1));
|
|
};
|
|
});
|
|
|
|
exports.createScript = function (code) {
|
|
return exports.Script(code);
|
|
};
|
|
|
|
exports.createContext = Script.createContext = function (context) {
|
|
var copy = new Context();
|
|
if(typeof context === 'object') {
|
|
forEach(Object_keys(context), function (key) {
|
|
copy[key] = context[key];
|
|
});
|
|
}
|
|
return copy;
|
|
};
|
|
|
|
},{"indexof":279}],279:[function(require,module,exports){
|
|
|
|
var indexOf = [].indexOf;
|
|
|
|
module.exports = function(arr, obj){
|
|
if (indexOf) return arr.indexOf(obj);
|
|
for (var i = 0; i < arr.length; ++i) {
|
|
if (arr[i] === obj) return i;
|
|
}
|
|
return -1;
|
|
};
|
|
},{}],280:[function(require,module,exports){
|
|
(function (module, exports) {
|
|
'use strict';
|
|
|
|
// Utils
|
|
function assert (val, msg) {
|
|
if (!val) throw new Error(msg || 'Assertion failed');
|
|
}
|
|
|
|
// Could use `inherits` module, but don't want to move from single file
|
|
// architecture yet.
|
|
function inherits (ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
var TempCtor = function () {};
|
|
TempCtor.prototype = superCtor.prototype;
|
|
ctor.prototype = new TempCtor();
|
|
ctor.prototype.constructor = ctor;
|
|
}
|
|
|
|
// BN
|
|
|
|
function BN (number, base, endian) {
|
|
if (BN.isBN(number)) {
|
|
return number;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.words = null;
|
|
this.length = 0;
|
|
|
|
// Reduction context
|
|
this.red = null;
|
|
|
|
if (number !== null) {
|
|
if (base === 'le' || base === 'be') {
|
|
endian = base;
|
|
base = 10;
|
|
}
|
|
|
|
this._init(number || 0, base || 10, endian || 'be');
|
|
}
|
|
}
|
|
if (typeof module === 'object') {
|
|
module.exports = BN;
|
|
} else {
|
|
exports.BN = BN;
|
|
}
|
|
|
|
BN.BN = BN;
|
|
BN.wordSize = 26;
|
|
|
|
var Buffer;
|
|
try {
|
|
Buffer = require('buffer').Buffer;
|
|
} catch (e) {
|
|
}
|
|
|
|
BN.isBN = function isBN (num) {
|
|
if (num instanceof BN) {
|
|
return true;
|
|
}
|
|
|
|
return num !== null && typeof num === 'object' &&
|
|
num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
|
|
};
|
|
|
|
BN.max = function max (left, right) {
|
|
if (left.cmp(right) > 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.min = function min (left, right) {
|
|
if (left.cmp(right) < 0) return left;
|
|
return right;
|
|
};
|
|
|
|
BN.prototype._init = function init (number, base, endian) {
|
|
if (typeof number === 'number') {
|
|
return this._initNumber(number, base, endian);
|
|
}
|
|
|
|
if (typeof number === 'object') {
|
|
return this._initArray(number, base, endian);
|
|
}
|
|
|
|
if (base === 'hex') {
|
|
base = 16;
|
|
}
|
|
assert(base === (base | 0) && base >= 2 && base <= 36);
|
|
|
|
number = number.toString().replace(/\s+/g, '');
|
|
var start = 0;
|
|
if (number[0] === '-') {
|
|
start++;
|
|
}
|
|
|
|
if (base === 16) {
|
|
this._parseHex(number, start);
|
|
} else {
|
|
this._parseBase(number, base, start);
|
|
}
|
|
|
|
if (number[0] === '-') {
|
|
this.negative = 1;
|
|
}
|
|
|
|
this.strip();
|
|
|
|
if (endian !== 'le') return;
|
|
|
|
this._initArray(this.toArray(), base, endian);
|
|
};
|
|
|
|
BN.prototype._initNumber = function _initNumber (number, base, endian) {
|
|
if (number < 0) {
|
|
this.negative = 1;
|
|
number = -number;
|
|
}
|
|
if (number < 0x4000000) {
|
|
this.words = [ number & 0x3ffffff ];
|
|
this.length = 1;
|
|
} else if (number < 0x10000000000000) {
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff
|
|
];
|
|
this.length = 2;
|
|
} else {
|
|
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
|
|
this.words = [
|
|
number & 0x3ffffff,
|
|
(number / 0x4000000) & 0x3ffffff,
|
|
1
|
|
];
|
|
this.length = 3;
|
|
}
|
|
|
|
if (endian !== 'le') return;
|
|
|
|
// Reverse the bytes
|
|
this._initArray(this.toArray(), base, endian);
|
|
};
|
|
|
|
BN.prototype._initArray = function _initArray (number, base, endian) {
|
|
// Perhaps a Uint8Array
|
|
assert(typeof number.length === 'number');
|
|
if (number.length <= 0) {
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
return this;
|
|
}
|
|
|
|
this.length = Math.ceil(number.length / 3);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
var j, w;
|
|
var off = 0;
|
|
if (endian === 'be') {
|
|
for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
|
|
w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
} else if (endian === 'le') {
|
|
for (i = 0, j = 0; i < number.length; i += 3) {
|
|
w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
return this.strip();
|
|
};
|
|
|
|
function parseHex (str, start, end) {
|
|
var r = 0;
|
|
var len = Math.min(str.length, end);
|
|
for (var i = start; i < len; i++) {
|
|
var c = str.charCodeAt(i) - 48;
|
|
|
|
r <<= 4;
|
|
|
|
// 'a' - 'f'
|
|
if (c >= 49 && c <= 54) {
|
|
r |= c - 49 + 0xa;
|
|
|
|
// 'A' - 'F'
|
|
} else if (c >= 17 && c <= 22) {
|
|
r |= c - 17 + 0xa;
|
|
|
|
// '0' - '9'
|
|
} else {
|
|
r |= c & 0xf;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseHex = function _parseHex (number, start) {
|
|
// Create possibly bigger array to ensure that it fits the number
|
|
this.length = Math.ceil((number.length - start) / 6);
|
|
this.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
var j, w;
|
|
// Scan 24-bit chunks and add them to the number
|
|
var off = 0;
|
|
for (i = number.length - 6, j = 0; i >= start; i -= 6) {
|
|
w = parseHex(number, i, i + 6);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
// NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb
|
|
this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
|
|
off += 24;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
j++;
|
|
}
|
|
}
|
|
if (i + 6 !== start) {
|
|
w = parseHex(number, start, i + 6);
|
|
this.words[j] |= (w << off) & 0x3ffffff;
|
|
this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
|
|
}
|
|
this.strip();
|
|
};
|
|
|
|
function parseBase (str, start, end, mul) {
|
|
var r = 0;
|
|
var len = Math.min(str.length, end);
|
|
for (var i = start; i < len; i++) {
|
|
var c = str.charCodeAt(i) - 48;
|
|
|
|
r *= mul;
|
|
|
|
// 'a'
|
|
if (c >= 49) {
|
|
r += c - 49 + 0xa;
|
|
|
|
// 'A'
|
|
} else if (c >= 17) {
|
|
r += c - 17 + 0xa;
|
|
|
|
// '0' - '9'
|
|
} else {
|
|
r += c;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
BN.prototype._parseBase = function _parseBase (number, base, start) {
|
|
// Initialize as zero
|
|
this.words = [ 0 ];
|
|
this.length = 1;
|
|
|
|
// Find length of limb in base
|
|
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
|
|
limbLen++;
|
|
}
|
|
limbLen--;
|
|
limbPow = (limbPow / base) | 0;
|
|
|
|
var total = number.length - start;
|
|
var mod = total % limbLen;
|
|
var end = Math.min(total, total - mod) + start;
|
|
|
|
var word = 0;
|
|
for (var i = start; i < end; i += limbLen) {
|
|
word = parseBase(number, i, i + limbLen, base);
|
|
|
|
this.imuln(limbPow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
|
|
if (mod !== 0) {
|
|
var pow = 1;
|
|
word = parseBase(number, i, number.length, base);
|
|
|
|
for (i = 0; i < mod; i++) {
|
|
pow *= base;
|
|
}
|
|
|
|
this.imuln(pow);
|
|
if (this.words[0] + word < 0x4000000) {
|
|
this.words[0] += word;
|
|
} else {
|
|
this._iaddn(word);
|
|
}
|
|
}
|
|
};
|
|
|
|
BN.prototype.copy = function copy (dest) {
|
|
dest.words = new Array(this.length);
|
|
for (var i = 0; i < this.length; i++) {
|
|
dest.words[i] = this.words[i];
|
|
}
|
|
dest.length = this.length;
|
|
dest.negative = this.negative;
|
|
dest.red = this.red;
|
|
};
|
|
|
|
BN.prototype.clone = function clone () {
|
|
var r = new BN(null);
|
|
this.copy(r);
|
|
return r;
|
|
};
|
|
|
|
BN.prototype._expand = function _expand (size) {
|
|
while (this.length < size) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
// Remove leading `0` from `this`
|
|
BN.prototype.strip = function strip () {
|
|
while (this.length > 1 && this.words[this.length - 1] === 0) {
|
|
this.length--;
|
|
}
|
|
return this._normSign();
|
|
};
|
|
|
|
BN.prototype._normSign = function _normSign () {
|
|
// -0 = 0
|
|
if (this.length === 1 && this.words[0] === 0) {
|
|
this.negative = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.inspect = function inspect () {
|
|
return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
|
|
};
|
|
|
|
/*
|
|
|
|
var zeros = [];
|
|
var groupSizes = [];
|
|
var groupBases = [];
|
|
|
|
var s = '';
|
|
var i = -1;
|
|
while (++i < BN.wordSize) {
|
|
zeros[i] = s;
|
|
s += '0';
|
|
}
|
|
groupSizes[0] = 0;
|
|
groupSizes[1] = 0;
|
|
groupBases[0] = 0;
|
|
groupBases[1] = 0;
|
|
var base = 2 - 1;
|
|
while (++base < 36 + 1) {
|
|
var groupSize = 0;
|
|
var groupBase = 1;
|
|
while (groupBase < (1 << BN.wordSize) / base) {
|
|
groupBase *= base;
|
|
groupSize += 1;
|
|
}
|
|
groupSizes[base] = groupSize;
|
|
groupBases[base] = groupBase;
|
|
}
|
|
|
|
*/
|
|
|
|
var zeros = [
|
|
'',
|
|
'0',
|
|
'00',
|
|
'000',
|
|
'0000',
|
|
'00000',
|
|
'000000',
|
|
'0000000',
|
|
'00000000',
|
|
'000000000',
|
|
'0000000000',
|
|
'00000000000',
|
|
'000000000000',
|
|
'0000000000000',
|
|
'00000000000000',
|
|
'000000000000000',
|
|
'0000000000000000',
|
|
'00000000000000000',
|
|
'000000000000000000',
|
|
'0000000000000000000',
|
|
'00000000000000000000',
|
|
'000000000000000000000',
|
|
'0000000000000000000000',
|
|
'00000000000000000000000',
|
|
'000000000000000000000000',
|
|
'0000000000000000000000000'
|
|
];
|
|
|
|
var groupSizes = [
|
|
0, 0,
|
|
25, 16, 12, 11, 10, 9, 8,
|
|
8, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5
|
|
];
|
|
|
|
var groupBases = [
|
|
0, 0,
|
|
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
|
|
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
|
|
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
|
|
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
|
|
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
|
|
];
|
|
|
|
BN.prototype.toString = function toString (base, padding) {
|
|
base = base || 10;
|
|
padding = padding | 0 || 1;
|
|
|
|
var out;
|
|
if (base === 16 || base === 'hex') {
|
|
out = '';
|
|
var off = 0;
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = this.words[i];
|
|
var word = (((w << off) | carry) & 0xffffff).toString(16);
|
|
carry = (w >>> (24 - off)) & 0xffffff;
|
|
if (carry !== 0 || i !== this.length - 1) {
|
|
out = zeros[6 - word.length] + word + out;
|
|
} else {
|
|
out = word + out;
|
|
}
|
|
off += 2;
|
|
if (off >= 26) {
|
|
off -= 26;
|
|
i--;
|
|
}
|
|
}
|
|
if (carry !== 0) {
|
|
out = carry.toString(16) + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
if (base === (base | 0) && base >= 2 && base <= 36) {
|
|
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
|
|
var groupSize = groupSizes[base];
|
|
// var groupBase = Math.pow(base, groupSize);
|
|
var groupBase = groupBases[base];
|
|
out = '';
|
|
var c = this.clone();
|
|
c.negative = 0;
|
|
while (!c.isZero()) {
|
|
var r = c.modn(groupBase).toString(base);
|
|
c = c.idivn(groupBase);
|
|
|
|
if (!c.isZero()) {
|
|
out = zeros[groupSize - r.length] + r + out;
|
|
} else {
|
|
out = r + out;
|
|
}
|
|
}
|
|
if (this.isZero()) {
|
|
out = '0' + out;
|
|
}
|
|
while (out.length % padding !== 0) {
|
|
out = '0' + out;
|
|
}
|
|
if (this.negative !== 0) {
|
|
out = '-' + out;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
assert(false, 'Base should be between 2 and 36');
|
|
};
|
|
|
|
BN.prototype.toNumber = function toNumber () {
|
|
var ret = this.words[0];
|
|
if (this.length === 2) {
|
|
ret += this.words[1] * 0x4000000;
|
|
} else if (this.length === 3 && this.words[2] === 0x01) {
|
|
// NOTE: at this stage it is known that the top bit is set
|
|
ret += 0x10000000000000 + (this.words[1] * 0x4000000);
|
|
} else if (this.length > 2) {
|
|
assert(false, 'Number can only safely store up to 53 bits');
|
|
}
|
|
return (this.negative !== 0) ? -ret : ret;
|
|
};
|
|
|
|
BN.prototype.toJSON = function toJSON () {
|
|
return this.toString(16);
|
|
};
|
|
|
|
BN.prototype.toBuffer = function toBuffer (endian, length) {
|
|
assert(typeof Buffer !== 'undefined');
|
|
return this.toArrayLike(Buffer, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArray = function toArray (endian, length) {
|
|
return this.toArrayLike(Array, endian, length);
|
|
};
|
|
|
|
BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
|
|
var byteLength = this.byteLength();
|
|
var reqLength = length || Math.max(1, byteLength);
|
|
assert(byteLength <= reqLength, 'byte array longer than desired length');
|
|
assert(reqLength > 0, 'Requested array length <= 0');
|
|
|
|
this.strip();
|
|
var littleEndian = endian === 'le';
|
|
var res = new ArrayType(reqLength);
|
|
|
|
var b, i;
|
|
var q = this.clone();
|
|
if (!littleEndian) {
|
|
// Assume big-endian
|
|
for (i = 0; i < reqLength - byteLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[reqLength - i - 1] = b;
|
|
}
|
|
} else {
|
|
for (i = 0; !q.isZero(); i++) {
|
|
b = q.andln(0xff);
|
|
q.iushrn(8);
|
|
|
|
res[i] = b;
|
|
}
|
|
|
|
for (; i < reqLength; i++) {
|
|
res[i] = 0;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
if (Math.clz32) {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
return 32 - Math.clz32(w);
|
|
};
|
|
} else {
|
|
BN.prototype._countBits = function _countBits (w) {
|
|
var t = w;
|
|
var r = 0;
|
|
if (t >= 0x1000) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if (t >= 0x40) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if (t >= 0x8) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if (t >= 0x02) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
return r + t;
|
|
};
|
|
}
|
|
|
|
BN.prototype._zeroBits = function _zeroBits (w) {
|
|
// Short-cut
|
|
if (w === 0) return 26;
|
|
|
|
var t = w;
|
|
var r = 0;
|
|
if ((t & 0x1fff) === 0) {
|
|
r += 13;
|
|
t >>>= 13;
|
|
}
|
|
if ((t & 0x7f) === 0) {
|
|
r += 7;
|
|
t >>>= 7;
|
|
}
|
|
if ((t & 0xf) === 0) {
|
|
r += 4;
|
|
t >>>= 4;
|
|
}
|
|
if ((t & 0x3) === 0) {
|
|
r += 2;
|
|
t >>>= 2;
|
|
}
|
|
if ((t & 0x1) === 0) {
|
|
r++;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
// Return number of used bits in a BN
|
|
BN.prototype.bitLength = function bitLength () {
|
|
var w = this.words[this.length - 1];
|
|
var hi = this._countBits(w);
|
|
return (this.length - 1) * 26 + hi;
|
|
};
|
|
|
|
function toBitArray (num) {
|
|
var w = new Array(num.bitLength());
|
|
|
|
for (var bit = 0; bit < w.length; bit++) {
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
// Number of trailing zero bits
|
|
BN.prototype.zeroBits = function zeroBits () {
|
|
if (this.isZero()) return 0;
|
|
|
|
var r = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var b = this._zeroBits(this.words[i]);
|
|
r += b;
|
|
if (b !== 26) break;
|
|
}
|
|
return r;
|
|
};
|
|
|
|
BN.prototype.byteLength = function byteLength () {
|
|
return Math.ceil(this.bitLength() / 8);
|
|
};
|
|
|
|
BN.prototype.toTwos = function toTwos (width) {
|
|
if (this.negative !== 0) {
|
|
return this.abs().inotn(width).iaddn(1);
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.fromTwos = function fromTwos (width) {
|
|
if (this.testn(width - 1)) {
|
|
return this.notn(width).iaddn(1).ineg();
|
|
}
|
|
return this.clone();
|
|
};
|
|
|
|
BN.prototype.isNeg = function isNeg () {
|
|
return this.negative !== 0;
|
|
};
|
|
|
|
// Return negative clone of `this`
|
|
BN.prototype.neg = function neg () {
|
|
return this.clone().ineg();
|
|
};
|
|
|
|
BN.prototype.ineg = function ineg () {
|
|
if (!this.isZero()) {
|
|
this.negative ^= 1;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Or `num` with `this` in-place
|
|
BN.prototype.iuor = function iuor (num) {
|
|
while (this.length < num.length) {
|
|
this.words[this.length++] = 0;
|
|
}
|
|
|
|
for (var i = 0; i < num.length; i++) {
|
|
this.words[i] = this.words[i] | num.words[i];
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ior = function ior (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuor(num);
|
|
};
|
|
|
|
// Or `num` with `this`
|
|
BN.prototype.or = function or (num) {
|
|
if (this.length > num.length) return this.clone().ior(num);
|
|
return num.clone().ior(this);
|
|
};
|
|
|
|
BN.prototype.uor = function uor (num) {
|
|
if (this.length > num.length) return this.clone().iuor(num);
|
|
return num.clone().iuor(this);
|
|
};
|
|
|
|
// And `num` with `this` in-place
|
|
BN.prototype.iuand = function iuand (num) {
|
|
// b = min-length(num, this)
|
|
var b;
|
|
if (this.length > num.length) {
|
|
b = num;
|
|
} else {
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = this.words[i] & num.words[i];
|
|
}
|
|
|
|
this.length = b.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.iand = function iand (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuand(num);
|
|
};
|
|
|
|
// And `num` with `this`
|
|
BN.prototype.and = function and (num) {
|
|
if (this.length > num.length) return this.clone().iand(num);
|
|
return num.clone().iand(this);
|
|
};
|
|
|
|
BN.prototype.uand = function uand (num) {
|
|
if (this.length > num.length) return this.clone().iuand(num);
|
|
return num.clone().iuand(this);
|
|
};
|
|
|
|
// Xor `num` with `this` in-place
|
|
BN.prototype.iuxor = function iuxor (num) {
|
|
// a.length > b.length
|
|
var a;
|
|
var b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
for (var i = 0; i < b.length; i++) {
|
|
this.words[i] = a.words[i] ^ b.words[i];
|
|
}
|
|
|
|
if (this !== a) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = a.length;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ixor = function ixor (num) {
|
|
assert((this.negative | num.negative) === 0);
|
|
return this.iuxor(num);
|
|
};
|
|
|
|
// Xor `num` with `this`
|
|
BN.prototype.xor = function xor (num) {
|
|
if (this.length > num.length) return this.clone().ixor(num);
|
|
return num.clone().ixor(this);
|
|
};
|
|
|
|
BN.prototype.uxor = function uxor (num) {
|
|
if (this.length > num.length) return this.clone().iuxor(num);
|
|
return num.clone().iuxor(this);
|
|
};
|
|
|
|
// Not ``this`` with ``width`` bitwidth
|
|
BN.prototype.inotn = function inotn (width) {
|
|
assert(typeof width === 'number' && width >= 0);
|
|
|
|
var bytesNeeded = Math.ceil(width / 26) | 0;
|
|
var bitsLeft = width % 26;
|
|
|
|
// Extend the buffer with leading zeroes
|
|
this._expand(bytesNeeded);
|
|
|
|
if (bitsLeft > 0) {
|
|
bytesNeeded--;
|
|
}
|
|
|
|
// Handle complete words
|
|
for (var i = 0; i < bytesNeeded; i++) {
|
|
this.words[i] = ~this.words[i] & 0x3ffffff;
|
|
}
|
|
|
|
// Handle the residue
|
|
if (bitsLeft > 0) {
|
|
this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
|
|
}
|
|
|
|
// And remove leading zeroes
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.notn = function notn (width) {
|
|
return this.clone().inotn(width);
|
|
};
|
|
|
|
// Set `bit` of `this`
|
|
BN.prototype.setn = function setn (bit, val) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
|
|
var off = (bit / 26) | 0;
|
|
var wbit = bit % 26;
|
|
|
|
this._expand(off + 1);
|
|
|
|
if (val) {
|
|
this.words[off] = this.words[off] | (1 << wbit);
|
|
} else {
|
|
this.words[off] = this.words[off] & ~(1 << wbit);
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Add `num` to `this` in-place
|
|
BN.prototype.iadd = function iadd (num) {
|
|
var r;
|
|
|
|
// negative + positive
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
this.negative = 0;
|
|
r = this.isub(num);
|
|
this.negative ^= 1;
|
|
return this._normSign();
|
|
|
|
// positive + negative
|
|
} else if (this.negative === 0 && num.negative !== 0) {
|
|
num.negative = 0;
|
|
r = this.isub(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
}
|
|
|
|
// a.length > b.length
|
|
var a, b;
|
|
if (this.length > num.length) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
this.words[i] = r & 0x3ffffff;
|
|
carry = r >>> 26;
|
|
}
|
|
|
|
this.length = a.length;
|
|
if (carry !== 0) {
|
|
this.words[this.length] = carry;
|
|
this.length++;
|
|
// Copy the rest of the words
|
|
} else if (a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
// Add `num` to `this`
|
|
BN.prototype.add = function add (num) {
|
|
var res;
|
|
if (num.negative !== 0 && this.negative === 0) {
|
|
num.negative = 0;
|
|
res = this.sub(num);
|
|
num.negative ^= 1;
|
|
return res;
|
|
} else if (num.negative === 0 && this.negative !== 0) {
|
|
this.negative = 0;
|
|
res = num.sub(this);
|
|
this.negative = 1;
|
|
return res;
|
|
}
|
|
|
|
if (this.length > num.length) return this.clone().iadd(num);
|
|
|
|
return num.clone().iadd(this);
|
|
};
|
|
|
|
// Subtract `num` from `this` in-place
|
|
BN.prototype.isub = function isub (num) {
|
|
// this - (-num) = this + num
|
|
if (num.negative !== 0) {
|
|
num.negative = 0;
|
|
var r = this.iadd(num);
|
|
num.negative = 1;
|
|
return r._normSign();
|
|
|
|
// -this - num = -(this + num)
|
|
} else if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iadd(num);
|
|
this.negative = 1;
|
|
return this._normSign();
|
|
}
|
|
|
|
// At this point both numbers are positive
|
|
var cmp = this.cmp(num);
|
|
|
|
// Optimization - zeroify
|
|
if (cmp === 0) {
|
|
this.negative = 0;
|
|
this.length = 1;
|
|
this.words[0] = 0;
|
|
return this;
|
|
}
|
|
|
|
// a > b
|
|
var a, b;
|
|
if (cmp > 0) {
|
|
a = this;
|
|
b = num;
|
|
} else {
|
|
a = num;
|
|
b = this;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (var i = 0; i < b.length; i++) {
|
|
r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
for (; carry !== 0 && i < a.length; i++) {
|
|
r = (a.words[i] | 0) + carry;
|
|
carry = r >> 26;
|
|
this.words[i] = r & 0x3ffffff;
|
|
}
|
|
|
|
// Copy rest of the words
|
|
if (carry === 0 && i < a.length && a !== this) {
|
|
for (; i < a.length; i++) {
|
|
this.words[i] = a.words[i];
|
|
}
|
|
}
|
|
|
|
this.length = Math.max(this.length, i);
|
|
|
|
if (a !== this) {
|
|
this.negative = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Subtract `num` from `this`
|
|
BN.prototype.sub = function sub (num) {
|
|
return this.clone().isub(num);
|
|
};
|
|
|
|
function smallMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
var len = (self.length + num.length) | 0;
|
|
out.length = len;
|
|
len = (len - 1) | 0;
|
|
|
|
// Peel one iteration (compiler can't do it, because of code complexity)
|
|
var a = self.words[0] | 0;
|
|
var b = num.words[0] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
var carry = (r / 0x4000000) | 0;
|
|
out.words[0] = lo;
|
|
|
|
for (var k = 1; k < len; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = carry >>> 26;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = (k - j) | 0;
|
|
a = self.words[i] | 0;
|
|
b = num.words[j] | 0;
|
|
r = a * b + rword;
|
|
ncarry += (r / 0x4000000) | 0;
|
|
rword = r & 0x3ffffff;
|
|
}
|
|
out.words[k] = rword | 0;
|
|
carry = ncarry | 0;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry | 0;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
// TODO(indutny): it may be reasonable to omit it for users who don't need
|
|
// to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
|
|
// multiplication (like elliptic secp256k1).
|
|
var comb10MulTo = function comb10MulTo (self, num, out) {
|
|
var a = self.words;
|
|
var b = num.words;
|
|
var o = out.words;
|
|
var c = 0;
|
|
var lo;
|
|
var mid;
|
|
var hi;
|
|
var a0 = a[0] | 0;
|
|
var al0 = a0 & 0x1fff;
|
|
var ah0 = a0 >>> 13;
|
|
var a1 = a[1] | 0;
|
|
var al1 = a1 & 0x1fff;
|
|
var ah1 = a1 >>> 13;
|
|
var a2 = a[2] | 0;
|
|
var al2 = a2 & 0x1fff;
|
|
var ah2 = a2 >>> 13;
|
|
var a3 = a[3] | 0;
|
|
var al3 = a3 & 0x1fff;
|
|
var ah3 = a3 >>> 13;
|
|
var a4 = a[4] | 0;
|
|
var al4 = a4 & 0x1fff;
|
|
var ah4 = a4 >>> 13;
|
|
var a5 = a[5] | 0;
|
|
var al5 = a5 & 0x1fff;
|
|
var ah5 = a5 >>> 13;
|
|
var a6 = a[6] | 0;
|
|
var al6 = a6 & 0x1fff;
|
|
var ah6 = a6 >>> 13;
|
|
var a7 = a[7] | 0;
|
|
var al7 = a7 & 0x1fff;
|
|
var ah7 = a7 >>> 13;
|
|
var a8 = a[8] | 0;
|
|
var al8 = a8 & 0x1fff;
|
|
var ah8 = a8 >>> 13;
|
|
var a9 = a[9] | 0;
|
|
var al9 = a9 & 0x1fff;
|
|
var ah9 = a9 >>> 13;
|
|
var b0 = b[0] | 0;
|
|
var bl0 = b0 & 0x1fff;
|
|
var bh0 = b0 >>> 13;
|
|
var b1 = b[1] | 0;
|
|
var bl1 = b1 & 0x1fff;
|
|
var bh1 = b1 >>> 13;
|
|
var b2 = b[2] | 0;
|
|
var bl2 = b2 & 0x1fff;
|
|
var bh2 = b2 >>> 13;
|
|
var b3 = b[3] | 0;
|
|
var bl3 = b3 & 0x1fff;
|
|
var bh3 = b3 >>> 13;
|
|
var b4 = b[4] | 0;
|
|
var bl4 = b4 & 0x1fff;
|
|
var bh4 = b4 >>> 13;
|
|
var b5 = b[5] | 0;
|
|
var bl5 = b5 & 0x1fff;
|
|
var bh5 = b5 >>> 13;
|
|
var b6 = b[6] | 0;
|
|
var bl6 = b6 & 0x1fff;
|
|
var bh6 = b6 >>> 13;
|
|
var b7 = b[7] | 0;
|
|
var bl7 = b7 & 0x1fff;
|
|
var bh7 = b7 >>> 13;
|
|
var b8 = b[8] | 0;
|
|
var bl8 = b8 & 0x1fff;
|
|
var bh8 = b8 >>> 13;
|
|
var b9 = b[9] | 0;
|
|
var bl9 = b9 & 0x1fff;
|
|
var bh9 = b9 >>> 13;
|
|
|
|
out.negative = self.negative ^ num.negative;
|
|
out.length = 19;
|
|
/* k = 0 */
|
|
lo = Math.imul(al0, bl0);
|
|
mid = Math.imul(al0, bh0);
|
|
mid = (mid + Math.imul(ah0, bl0)) | 0;
|
|
hi = Math.imul(ah0, bh0);
|
|
var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
|
|
w0 &= 0x3ffffff;
|
|
/* k = 1 */
|
|
lo = Math.imul(al1, bl0);
|
|
mid = Math.imul(al1, bh0);
|
|
mid = (mid + Math.imul(ah1, bl0)) | 0;
|
|
hi = Math.imul(ah1, bh0);
|
|
lo = (lo + Math.imul(al0, bl1)) | 0;
|
|
mid = (mid + Math.imul(al0, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh1)) | 0;
|
|
var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
|
|
w1 &= 0x3ffffff;
|
|
/* k = 2 */
|
|
lo = Math.imul(al2, bl0);
|
|
mid = Math.imul(al2, bh0);
|
|
mid = (mid + Math.imul(ah2, bl0)) | 0;
|
|
hi = Math.imul(ah2, bh0);
|
|
lo = (lo + Math.imul(al1, bl1)) | 0;
|
|
mid = (mid + Math.imul(al1, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh1)) | 0;
|
|
lo = (lo + Math.imul(al0, bl2)) | 0;
|
|
mid = (mid + Math.imul(al0, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh2)) | 0;
|
|
var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
|
|
w2 &= 0x3ffffff;
|
|
/* k = 3 */
|
|
lo = Math.imul(al3, bl0);
|
|
mid = Math.imul(al3, bh0);
|
|
mid = (mid + Math.imul(ah3, bl0)) | 0;
|
|
hi = Math.imul(ah3, bh0);
|
|
lo = (lo + Math.imul(al2, bl1)) | 0;
|
|
mid = (mid + Math.imul(al2, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh1)) | 0;
|
|
lo = (lo + Math.imul(al1, bl2)) | 0;
|
|
mid = (mid + Math.imul(al1, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh2)) | 0;
|
|
lo = (lo + Math.imul(al0, bl3)) | 0;
|
|
mid = (mid + Math.imul(al0, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh3)) | 0;
|
|
var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
|
|
w3 &= 0x3ffffff;
|
|
/* k = 4 */
|
|
lo = Math.imul(al4, bl0);
|
|
mid = Math.imul(al4, bh0);
|
|
mid = (mid + Math.imul(ah4, bl0)) | 0;
|
|
hi = Math.imul(ah4, bh0);
|
|
lo = (lo + Math.imul(al3, bl1)) | 0;
|
|
mid = (mid + Math.imul(al3, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh1)) | 0;
|
|
lo = (lo + Math.imul(al2, bl2)) | 0;
|
|
mid = (mid + Math.imul(al2, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh2)) | 0;
|
|
lo = (lo + Math.imul(al1, bl3)) | 0;
|
|
mid = (mid + Math.imul(al1, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh3)) | 0;
|
|
lo = (lo + Math.imul(al0, bl4)) | 0;
|
|
mid = (mid + Math.imul(al0, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh4)) | 0;
|
|
var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
|
|
w4 &= 0x3ffffff;
|
|
/* k = 5 */
|
|
lo = Math.imul(al5, bl0);
|
|
mid = Math.imul(al5, bh0);
|
|
mid = (mid + Math.imul(ah5, bl0)) | 0;
|
|
hi = Math.imul(ah5, bh0);
|
|
lo = (lo + Math.imul(al4, bl1)) | 0;
|
|
mid = (mid + Math.imul(al4, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh1)) | 0;
|
|
lo = (lo + Math.imul(al3, bl2)) | 0;
|
|
mid = (mid + Math.imul(al3, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh2)) | 0;
|
|
lo = (lo + Math.imul(al2, bl3)) | 0;
|
|
mid = (mid + Math.imul(al2, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh3)) | 0;
|
|
lo = (lo + Math.imul(al1, bl4)) | 0;
|
|
mid = (mid + Math.imul(al1, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh4)) | 0;
|
|
lo = (lo + Math.imul(al0, bl5)) | 0;
|
|
mid = (mid + Math.imul(al0, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh5)) | 0;
|
|
var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
|
|
w5 &= 0x3ffffff;
|
|
/* k = 6 */
|
|
lo = Math.imul(al6, bl0);
|
|
mid = Math.imul(al6, bh0);
|
|
mid = (mid + Math.imul(ah6, bl0)) | 0;
|
|
hi = Math.imul(ah6, bh0);
|
|
lo = (lo + Math.imul(al5, bl1)) | 0;
|
|
mid = (mid + Math.imul(al5, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh1)) | 0;
|
|
lo = (lo + Math.imul(al4, bl2)) | 0;
|
|
mid = (mid + Math.imul(al4, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh2)) | 0;
|
|
lo = (lo + Math.imul(al3, bl3)) | 0;
|
|
mid = (mid + Math.imul(al3, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh3)) | 0;
|
|
lo = (lo + Math.imul(al2, bl4)) | 0;
|
|
mid = (mid + Math.imul(al2, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh4)) | 0;
|
|
lo = (lo + Math.imul(al1, bl5)) | 0;
|
|
mid = (mid + Math.imul(al1, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh5)) | 0;
|
|
lo = (lo + Math.imul(al0, bl6)) | 0;
|
|
mid = (mid + Math.imul(al0, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh6)) | 0;
|
|
var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
|
|
w6 &= 0x3ffffff;
|
|
/* k = 7 */
|
|
lo = Math.imul(al7, bl0);
|
|
mid = Math.imul(al7, bh0);
|
|
mid = (mid + Math.imul(ah7, bl0)) | 0;
|
|
hi = Math.imul(ah7, bh0);
|
|
lo = (lo + Math.imul(al6, bl1)) | 0;
|
|
mid = (mid + Math.imul(al6, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh1)) | 0;
|
|
lo = (lo + Math.imul(al5, bl2)) | 0;
|
|
mid = (mid + Math.imul(al5, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh2)) | 0;
|
|
lo = (lo + Math.imul(al4, bl3)) | 0;
|
|
mid = (mid + Math.imul(al4, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh3)) | 0;
|
|
lo = (lo + Math.imul(al3, bl4)) | 0;
|
|
mid = (mid + Math.imul(al3, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh4)) | 0;
|
|
lo = (lo + Math.imul(al2, bl5)) | 0;
|
|
mid = (mid + Math.imul(al2, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh5)) | 0;
|
|
lo = (lo + Math.imul(al1, bl6)) | 0;
|
|
mid = (mid + Math.imul(al1, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh6)) | 0;
|
|
lo = (lo + Math.imul(al0, bl7)) | 0;
|
|
mid = (mid + Math.imul(al0, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh7)) | 0;
|
|
var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
|
|
w7 &= 0x3ffffff;
|
|
/* k = 8 */
|
|
lo = Math.imul(al8, bl0);
|
|
mid = Math.imul(al8, bh0);
|
|
mid = (mid + Math.imul(ah8, bl0)) | 0;
|
|
hi = Math.imul(ah8, bh0);
|
|
lo = (lo + Math.imul(al7, bl1)) | 0;
|
|
mid = (mid + Math.imul(al7, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh1)) | 0;
|
|
lo = (lo + Math.imul(al6, bl2)) | 0;
|
|
mid = (mid + Math.imul(al6, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh2)) | 0;
|
|
lo = (lo + Math.imul(al5, bl3)) | 0;
|
|
mid = (mid + Math.imul(al5, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh3)) | 0;
|
|
lo = (lo + Math.imul(al4, bl4)) | 0;
|
|
mid = (mid + Math.imul(al4, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh4)) | 0;
|
|
lo = (lo + Math.imul(al3, bl5)) | 0;
|
|
mid = (mid + Math.imul(al3, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh5)) | 0;
|
|
lo = (lo + Math.imul(al2, bl6)) | 0;
|
|
mid = (mid + Math.imul(al2, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh6)) | 0;
|
|
lo = (lo + Math.imul(al1, bl7)) | 0;
|
|
mid = (mid + Math.imul(al1, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh7)) | 0;
|
|
lo = (lo + Math.imul(al0, bl8)) | 0;
|
|
mid = (mid + Math.imul(al0, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh8)) | 0;
|
|
var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
|
|
w8 &= 0x3ffffff;
|
|
/* k = 9 */
|
|
lo = Math.imul(al9, bl0);
|
|
mid = Math.imul(al9, bh0);
|
|
mid = (mid + Math.imul(ah9, bl0)) | 0;
|
|
hi = Math.imul(ah9, bh0);
|
|
lo = (lo + Math.imul(al8, bl1)) | 0;
|
|
mid = (mid + Math.imul(al8, bh1)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl1)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh1)) | 0;
|
|
lo = (lo + Math.imul(al7, bl2)) | 0;
|
|
mid = (mid + Math.imul(al7, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh2)) | 0;
|
|
lo = (lo + Math.imul(al6, bl3)) | 0;
|
|
mid = (mid + Math.imul(al6, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh3)) | 0;
|
|
lo = (lo + Math.imul(al5, bl4)) | 0;
|
|
mid = (mid + Math.imul(al5, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh4)) | 0;
|
|
lo = (lo + Math.imul(al4, bl5)) | 0;
|
|
mid = (mid + Math.imul(al4, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh5)) | 0;
|
|
lo = (lo + Math.imul(al3, bl6)) | 0;
|
|
mid = (mid + Math.imul(al3, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh6)) | 0;
|
|
lo = (lo + Math.imul(al2, bl7)) | 0;
|
|
mid = (mid + Math.imul(al2, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh7)) | 0;
|
|
lo = (lo + Math.imul(al1, bl8)) | 0;
|
|
mid = (mid + Math.imul(al1, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh8)) | 0;
|
|
lo = (lo + Math.imul(al0, bl9)) | 0;
|
|
mid = (mid + Math.imul(al0, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah0, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah0, bh9)) | 0;
|
|
var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
|
|
w9 &= 0x3ffffff;
|
|
/* k = 10 */
|
|
lo = Math.imul(al9, bl1);
|
|
mid = Math.imul(al9, bh1);
|
|
mid = (mid + Math.imul(ah9, bl1)) | 0;
|
|
hi = Math.imul(ah9, bh1);
|
|
lo = (lo + Math.imul(al8, bl2)) | 0;
|
|
mid = (mid + Math.imul(al8, bh2)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl2)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh2)) | 0;
|
|
lo = (lo + Math.imul(al7, bl3)) | 0;
|
|
mid = (mid + Math.imul(al7, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh3)) | 0;
|
|
lo = (lo + Math.imul(al6, bl4)) | 0;
|
|
mid = (mid + Math.imul(al6, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh4)) | 0;
|
|
lo = (lo + Math.imul(al5, bl5)) | 0;
|
|
mid = (mid + Math.imul(al5, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh5)) | 0;
|
|
lo = (lo + Math.imul(al4, bl6)) | 0;
|
|
mid = (mid + Math.imul(al4, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh6)) | 0;
|
|
lo = (lo + Math.imul(al3, bl7)) | 0;
|
|
mid = (mid + Math.imul(al3, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh7)) | 0;
|
|
lo = (lo + Math.imul(al2, bl8)) | 0;
|
|
mid = (mid + Math.imul(al2, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh8)) | 0;
|
|
lo = (lo + Math.imul(al1, bl9)) | 0;
|
|
mid = (mid + Math.imul(al1, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah1, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah1, bh9)) | 0;
|
|
var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
|
|
w10 &= 0x3ffffff;
|
|
/* k = 11 */
|
|
lo = Math.imul(al9, bl2);
|
|
mid = Math.imul(al9, bh2);
|
|
mid = (mid + Math.imul(ah9, bl2)) | 0;
|
|
hi = Math.imul(ah9, bh2);
|
|
lo = (lo + Math.imul(al8, bl3)) | 0;
|
|
mid = (mid + Math.imul(al8, bh3)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl3)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh3)) | 0;
|
|
lo = (lo + Math.imul(al7, bl4)) | 0;
|
|
mid = (mid + Math.imul(al7, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh4)) | 0;
|
|
lo = (lo + Math.imul(al6, bl5)) | 0;
|
|
mid = (mid + Math.imul(al6, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh5)) | 0;
|
|
lo = (lo + Math.imul(al5, bl6)) | 0;
|
|
mid = (mid + Math.imul(al5, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh6)) | 0;
|
|
lo = (lo + Math.imul(al4, bl7)) | 0;
|
|
mid = (mid + Math.imul(al4, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh7)) | 0;
|
|
lo = (lo + Math.imul(al3, bl8)) | 0;
|
|
mid = (mid + Math.imul(al3, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh8)) | 0;
|
|
lo = (lo + Math.imul(al2, bl9)) | 0;
|
|
mid = (mid + Math.imul(al2, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah2, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah2, bh9)) | 0;
|
|
var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
|
|
w11 &= 0x3ffffff;
|
|
/* k = 12 */
|
|
lo = Math.imul(al9, bl3);
|
|
mid = Math.imul(al9, bh3);
|
|
mid = (mid + Math.imul(ah9, bl3)) | 0;
|
|
hi = Math.imul(ah9, bh3);
|
|
lo = (lo + Math.imul(al8, bl4)) | 0;
|
|
mid = (mid + Math.imul(al8, bh4)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl4)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh4)) | 0;
|
|
lo = (lo + Math.imul(al7, bl5)) | 0;
|
|
mid = (mid + Math.imul(al7, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh5)) | 0;
|
|
lo = (lo + Math.imul(al6, bl6)) | 0;
|
|
mid = (mid + Math.imul(al6, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh6)) | 0;
|
|
lo = (lo + Math.imul(al5, bl7)) | 0;
|
|
mid = (mid + Math.imul(al5, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh7)) | 0;
|
|
lo = (lo + Math.imul(al4, bl8)) | 0;
|
|
mid = (mid + Math.imul(al4, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh8)) | 0;
|
|
lo = (lo + Math.imul(al3, bl9)) | 0;
|
|
mid = (mid + Math.imul(al3, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah3, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah3, bh9)) | 0;
|
|
var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
|
|
w12 &= 0x3ffffff;
|
|
/* k = 13 */
|
|
lo = Math.imul(al9, bl4);
|
|
mid = Math.imul(al9, bh4);
|
|
mid = (mid + Math.imul(ah9, bl4)) | 0;
|
|
hi = Math.imul(ah9, bh4);
|
|
lo = (lo + Math.imul(al8, bl5)) | 0;
|
|
mid = (mid + Math.imul(al8, bh5)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl5)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh5)) | 0;
|
|
lo = (lo + Math.imul(al7, bl6)) | 0;
|
|
mid = (mid + Math.imul(al7, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh6)) | 0;
|
|
lo = (lo + Math.imul(al6, bl7)) | 0;
|
|
mid = (mid + Math.imul(al6, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh7)) | 0;
|
|
lo = (lo + Math.imul(al5, bl8)) | 0;
|
|
mid = (mid + Math.imul(al5, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh8)) | 0;
|
|
lo = (lo + Math.imul(al4, bl9)) | 0;
|
|
mid = (mid + Math.imul(al4, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah4, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah4, bh9)) | 0;
|
|
var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
|
|
w13 &= 0x3ffffff;
|
|
/* k = 14 */
|
|
lo = Math.imul(al9, bl5);
|
|
mid = Math.imul(al9, bh5);
|
|
mid = (mid + Math.imul(ah9, bl5)) | 0;
|
|
hi = Math.imul(ah9, bh5);
|
|
lo = (lo + Math.imul(al8, bl6)) | 0;
|
|
mid = (mid + Math.imul(al8, bh6)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl6)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh6)) | 0;
|
|
lo = (lo + Math.imul(al7, bl7)) | 0;
|
|
mid = (mid + Math.imul(al7, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh7)) | 0;
|
|
lo = (lo + Math.imul(al6, bl8)) | 0;
|
|
mid = (mid + Math.imul(al6, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh8)) | 0;
|
|
lo = (lo + Math.imul(al5, bl9)) | 0;
|
|
mid = (mid + Math.imul(al5, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah5, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah5, bh9)) | 0;
|
|
var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
|
|
w14 &= 0x3ffffff;
|
|
/* k = 15 */
|
|
lo = Math.imul(al9, bl6);
|
|
mid = Math.imul(al9, bh6);
|
|
mid = (mid + Math.imul(ah9, bl6)) | 0;
|
|
hi = Math.imul(ah9, bh6);
|
|
lo = (lo + Math.imul(al8, bl7)) | 0;
|
|
mid = (mid + Math.imul(al8, bh7)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl7)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh7)) | 0;
|
|
lo = (lo + Math.imul(al7, bl8)) | 0;
|
|
mid = (mid + Math.imul(al7, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh8)) | 0;
|
|
lo = (lo + Math.imul(al6, bl9)) | 0;
|
|
mid = (mid + Math.imul(al6, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah6, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah6, bh9)) | 0;
|
|
var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
|
|
w15 &= 0x3ffffff;
|
|
/* k = 16 */
|
|
lo = Math.imul(al9, bl7);
|
|
mid = Math.imul(al9, bh7);
|
|
mid = (mid + Math.imul(ah9, bl7)) | 0;
|
|
hi = Math.imul(ah9, bh7);
|
|
lo = (lo + Math.imul(al8, bl8)) | 0;
|
|
mid = (mid + Math.imul(al8, bh8)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl8)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh8)) | 0;
|
|
lo = (lo + Math.imul(al7, bl9)) | 0;
|
|
mid = (mid + Math.imul(al7, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah7, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah7, bh9)) | 0;
|
|
var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
|
|
w16 &= 0x3ffffff;
|
|
/* k = 17 */
|
|
lo = Math.imul(al9, bl8);
|
|
mid = Math.imul(al9, bh8);
|
|
mid = (mid + Math.imul(ah9, bl8)) | 0;
|
|
hi = Math.imul(ah9, bh8);
|
|
lo = (lo + Math.imul(al8, bl9)) | 0;
|
|
mid = (mid + Math.imul(al8, bh9)) | 0;
|
|
mid = (mid + Math.imul(ah8, bl9)) | 0;
|
|
hi = (hi + Math.imul(ah8, bh9)) | 0;
|
|
var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
|
|
w17 &= 0x3ffffff;
|
|
/* k = 18 */
|
|
lo = Math.imul(al9, bl9);
|
|
mid = Math.imul(al9, bh9);
|
|
mid = (mid + Math.imul(ah9, bl9)) | 0;
|
|
hi = Math.imul(ah9, bh9);
|
|
var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
|
c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
|
|
w18 &= 0x3ffffff;
|
|
o[0] = w0;
|
|
o[1] = w1;
|
|
o[2] = w2;
|
|
o[3] = w3;
|
|
o[4] = w4;
|
|
o[5] = w5;
|
|
o[6] = w6;
|
|
o[7] = w7;
|
|
o[8] = w8;
|
|
o[9] = w9;
|
|
o[10] = w10;
|
|
o[11] = w11;
|
|
o[12] = w12;
|
|
o[13] = w13;
|
|
o[14] = w14;
|
|
o[15] = w15;
|
|
o[16] = w16;
|
|
o[17] = w17;
|
|
o[18] = w18;
|
|
if (c !== 0) {
|
|
o[19] = c;
|
|
out.length++;
|
|
}
|
|
return out;
|
|
};
|
|
|
|
// Polyfill comb
|
|
if (!Math.imul) {
|
|
comb10MulTo = smallMulTo;
|
|
}
|
|
|
|
function bigMulTo (self, num, out) {
|
|
out.negative = num.negative ^ self.negative;
|
|
out.length = self.length + num.length;
|
|
|
|
var carry = 0;
|
|
var hncarry = 0;
|
|
for (var k = 0; k < out.length - 1; k++) {
|
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
|
// note that ncarry could be >= 0x3ffffff
|
|
var ncarry = hncarry;
|
|
hncarry = 0;
|
|
var rword = carry & 0x3ffffff;
|
|
var maxJ = Math.min(k, num.length - 1);
|
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
|
var i = k - j;
|
|
var a = self.words[i] | 0;
|
|
var b = num.words[j] | 0;
|
|
var r = a * b;
|
|
|
|
var lo = r & 0x3ffffff;
|
|
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
|
|
lo = (lo + rword) | 0;
|
|
rword = lo & 0x3ffffff;
|
|
ncarry = (ncarry + (lo >>> 26)) | 0;
|
|
|
|
hncarry += ncarry >>> 26;
|
|
ncarry &= 0x3ffffff;
|
|
}
|
|
out.words[k] = rword;
|
|
carry = ncarry;
|
|
ncarry = hncarry;
|
|
}
|
|
if (carry !== 0) {
|
|
out.words[k] = carry;
|
|
} else {
|
|
out.length--;
|
|
}
|
|
|
|
return out.strip();
|
|
}
|
|
|
|
function jumboMulTo (self, num, out) {
|
|
var fftm = new FFTM();
|
|
return fftm.mulp(self, num, out);
|
|
}
|
|
|
|
BN.prototype.mulTo = function mulTo (num, out) {
|
|
var res;
|
|
var len = this.length + num.length;
|
|
if (this.length === 10 && num.length === 10) {
|
|
res = comb10MulTo(this, num, out);
|
|
} else if (len < 63) {
|
|
res = smallMulTo(this, num, out);
|
|
} else if (len < 1024) {
|
|
res = bigMulTo(this, num, out);
|
|
} else {
|
|
res = jumboMulTo(this, num, out);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Cooley-Tukey algorithm for FFT
|
|
// slightly revisited to rely on looping instead of recursion
|
|
|
|
function FFTM (x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
FFTM.prototype.makeRBT = function makeRBT (N) {
|
|
var t = new Array(N);
|
|
var l = BN.prototype._countBits(N) - 1;
|
|
for (var i = 0; i < N; i++) {
|
|
t[i] = this.revBin(i, l, N);
|
|
}
|
|
|
|
return t;
|
|
};
|
|
|
|
// Returns binary-reversed representation of `x`
|
|
FFTM.prototype.revBin = function revBin (x, l, N) {
|
|
if (x === 0 || x === N - 1) return x;
|
|
|
|
var rb = 0;
|
|
for (var i = 0; i < l; i++) {
|
|
rb |= (x & 1) << (l - i - 1);
|
|
x >>= 1;
|
|
}
|
|
|
|
return rb;
|
|
};
|
|
|
|
// Performs "tweedling" phase, therefore 'emulating'
|
|
// behaviour of the recursive algorithm
|
|
FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
|
|
for (var i = 0; i < N; i++) {
|
|
rtws[i] = rws[rbt[i]];
|
|
itws[i] = iws[rbt[i]];
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
|
|
this.permute(rbt, rws, iws, rtws, itws, N);
|
|
|
|
for (var s = 1; s < N; s <<= 1) {
|
|
var l = s << 1;
|
|
|
|
var rtwdf = Math.cos(2 * Math.PI / l);
|
|
var itwdf = Math.sin(2 * Math.PI / l);
|
|
|
|
for (var p = 0; p < N; p += l) {
|
|
var rtwdf_ = rtwdf;
|
|
var itwdf_ = itwdf;
|
|
|
|
for (var j = 0; j < s; j++) {
|
|
var re = rtws[p + j];
|
|
var ie = itws[p + j];
|
|
|
|
var ro = rtws[p + j + s];
|
|
var io = itws[p + j + s];
|
|
|
|
var rx = rtwdf_ * ro - itwdf_ * io;
|
|
|
|
io = rtwdf_ * io + itwdf_ * ro;
|
|
ro = rx;
|
|
|
|
rtws[p + j] = re + ro;
|
|
itws[p + j] = ie + io;
|
|
|
|
rtws[p + j + s] = re - ro;
|
|
itws[p + j + s] = ie - io;
|
|
|
|
/* jshint maxdepth : false */
|
|
if (j !== l) {
|
|
rx = rtwdf * rtwdf_ - itwdf * itwdf_;
|
|
|
|
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
|
|
rtwdf_ = rx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
|
|
var N = Math.max(m, n) | 1;
|
|
var odd = N & 1;
|
|
var i = 0;
|
|
for (N = N / 2 | 0; N; N = N >>> 1) {
|
|
i++;
|
|
}
|
|
|
|
return 1 << i + 1 + odd;
|
|
};
|
|
|
|
FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
|
|
if (N <= 1) return;
|
|
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var t = rws[i];
|
|
|
|
rws[i] = rws[N - i - 1];
|
|
rws[N - i - 1] = t;
|
|
|
|
t = iws[i];
|
|
|
|
iws[i] = -iws[N - i - 1];
|
|
iws[N - i - 1] = -t;
|
|
}
|
|
};
|
|
|
|
FFTM.prototype.normalize13b = function normalize13b (ws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < N / 2; i++) {
|
|
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
|
|
Math.round(ws[2 * i] / N) +
|
|
carry;
|
|
|
|
ws[i] = w & 0x3ffffff;
|
|
|
|
if (w < 0x4000000) {
|
|
carry = 0;
|
|
} else {
|
|
carry = w / 0x4000000 | 0;
|
|
}
|
|
}
|
|
|
|
return ws;
|
|
};
|
|
|
|
FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
|
|
var carry = 0;
|
|
for (var i = 0; i < len; i++) {
|
|
carry = carry + (ws[i] | 0);
|
|
|
|
rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
|
|
rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
|
|
}
|
|
|
|
// Pad with zeroes
|
|
for (i = 2 * len; i < N; ++i) {
|
|
rws[i] = 0;
|
|
}
|
|
|
|
assert(carry === 0);
|
|
assert((carry & ~0x1fff) === 0);
|
|
};
|
|
|
|
FFTM.prototype.stub = function stub (N) {
|
|
var ph = new Array(N);
|
|
for (var i = 0; i < N; i++) {
|
|
ph[i] = 0;
|
|
}
|
|
|
|
return ph;
|
|
};
|
|
|
|
FFTM.prototype.mulp = function mulp (x, y, out) {
|
|
var N = 2 * this.guessLen13b(x.length, y.length);
|
|
|
|
var rbt = this.makeRBT(N);
|
|
|
|
var _ = this.stub(N);
|
|
|
|
var rws = new Array(N);
|
|
var rwst = new Array(N);
|
|
var iwst = new Array(N);
|
|
|
|
var nrws = new Array(N);
|
|
var nrwst = new Array(N);
|
|
var niwst = new Array(N);
|
|
|
|
var rmws = out.words;
|
|
rmws.length = N;
|
|
|
|
this.convert13b(x.words, x.length, rws, N);
|
|
this.convert13b(y.words, y.length, nrws, N);
|
|
|
|
this.transform(rws, _, rwst, iwst, N, rbt);
|
|
this.transform(nrws, _, nrwst, niwst, N, rbt);
|
|
|
|
for (var i = 0; i < N; i++) {
|
|
var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
|
|
iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
|
|
rwst[i] = rx;
|
|
}
|
|
|
|
this.conjugate(rwst, iwst, N);
|
|
this.transform(rwst, iwst, rmws, _, N, rbt);
|
|
this.conjugate(rmws, _, N);
|
|
this.normalize13b(rmws, N);
|
|
|
|
out.negative = x.negative ^ y.negative;
|
|
out.length = x.length + y.length;
|
|
return out.strip();
|
|
};
|
|
|
|
// Multiply `this` by `num`
|
|
BN.prototype.mul = function mul (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return this.mulTo(num, out);
|
|
};
|
|
|
|
// Multiply employing FFT
|
|
BN.prototype.mulf = function mulf (num) {
|
|
var out = new BN(null);
|
|
out.words = new Array(this.length + num.length);
|
|
return jumboMulTo(this, num, out);
|
|
};
|
|
|
|
// In-place Multiplication
|
|
BN.prototype.imul = function imul (num) {
|
|
return this.clone().mulTo(num, this);
|
|
};
|
|
|
|
BN.prototype.imuln = function imuln (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
|
|
// Carry
|
|
var carry = 0;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var w = (this.words[i] | 0) * num;
|
|
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
|
|
carry >>= 26;
|
|
carry += (w / 0x4000000) | 0;
|
|
// NOTE: lo is 27bit maximum
|
|
carry += lo >>> 26;
|
|
this.words[i] = lo & 0x3ffffff;
|
|
}
|
|
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.muln = function muln (num) {
|
|
return this.clone().imuln(num);
|
|
};
|
|
|
|
// `this` * `this`
|
|
BN.prototype.sqr = function sqr () {
|
|
return this.mul(this);
|
|
};
|
|
|
|
// `this` * `this` in-place
|
|
BN.prototype.isqr = function isqr () {
|
|
return this.imul(this.clone());
|
|
};
|
|
|
|
// Math.pow(`this`, `num`)
|
|
BN.prototype.pow = function pow (num) {
|
|
var w = toBitArray(num);
|
|
if (w.length === 0) return new BN(1);
|
|
|
|
// Skip leading zeroes
|
|
var res = this;
|
|
for (var i = 0; i < w.length; i++, res = res.sqr()) {
|
|
if (w[i] !== 0) break;
|
|
}
|
|
|
|
if (++i < w.length) {
|
|
for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
|
|
if (w[i] === 0) continue;
|
|
|
|
res = res.mul(q);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
// Shift-left in-place
|
|
BN.prototype.iushln = function iushln (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
|
|
var i;
|
|
|
|
if (r !== 0) {
|
|
var carry = 0;
|
|
|
|
for (i = 0; i < this.length; i++) {
|
|
var newCarry = this.words[i] & carryMask;
|
|
var c = ((this.words[i] | 0) - newCarry) << r;
|
|
this.words[i] = c | carry;
|
|
carry = newCarry >>> (26 - r);
|
|
}
|
|
|
|
if (carry) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
}
|
|
|
|
if (s !== 0) {
|
|
for (i = this.length - 1; i >= 0; i--) {
|
|
this.words[i + s] = this.words[i];
|
|
}
|
|
|
|
for (i = 0; i < s; i++) {
|
|
this.words[i] = 0;
|
|
}
|
|
|
|
this.length += s;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishln = function ishln (bits) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushln(bits);
|
|
};
|
|
|
|
// Shift-right in-place
|
|
// NOTE: `hint` is a lowest bit before trailing zeroes
|
|
// NOTE: if `extended` is present - it will be filled with destroyed bits
|
|
BN.prototype.iushrn = function iushrn (bits, hint, extended) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var h;
|
|
if (hint) {
|
|
h = (hint - (hint % 26)) / 26;
|
|
} else {
|
|
h = 0;
|
|
}
|
|
|
|
var r = bits % 26;
|
|
var s = Math.min((bits - r) / 26, this.length);
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
var maskedWords = extended;
|
|
|
|
h -= s;
|
|
h = Math.max(0, h);
|
|
|
|
// Extended mode, copy masked part
|
|
if (maskedWords) {
|
|
for (var i = 0; i < s; i++) {
|
|
maskedWords.words[i] = this.words[i];
|
|
}
|
|
maskedWords.length = s;
|
|
}
|
|
|
|
if (s === 0) {
|
|
// No-op, we should not move anything at all
|
|
} else if (this.length > s) {
|
|
this.length -= s;
|
|
for (i = 0; i < this.length; i++) {
|
|
this.words[i] = this.words[i + s];
|
|
}
|
|
} else {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
var carry = 0;
|
|
for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
|
|
var word = this.words[i] | 0;
|
|
this.words[i] = (carry << (26 - r)) | (word >>> r);
|
|
carry = word & mask;
|
|
}
|
|
|
|
// Push carried bits as a mask
|
|
if (maskedWords && carry !== 0) {
|
|
maskedWords.words[maskedWords.length++] = carry;
|
|
}
|
|
|
|
if (this.length === 0) {
|
|
this.words[0] = 0;
|
|
this.length = 1;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.ishrn = function ishrn (bits, hint, extended) {
|
|
// TODO(indutny): implement me
|
|
assert(this.negative === 0);
|
|
return this.iushrn(bits, hint, extended);
|
|
};
|
|
|
|
// Shift-left
|
|
BN.prototype.shln = function shln (bits) {
|
|
return this.clone().ishln(bits);
|
|
};
|
|
|
|
BN.prototype.ushln = function ushln (bits) {
|
|
return this.clone().iushln(bits);
|
|
};
|
|
|
|
// Shift-right
|
|
BN.prototype.shrn = function shrn (bits) {
|
|
return this.clone().ishrn(bits);
|
|
};
|
|
|
|
BN.prototype.ushrn = function ushrn (bits) {
|
|
return this.clone().iushrn(bits);
|
|
};
|
|
|
|
// Test if n bit is set
|
|
BN.prototype.testn = function testn (bit) {
|
|
assert(typeof bit === 'number' && bit >= 0);
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) return false;
|
|
|
|
// Check bit and return
|
|
var w = this.words[s];
|
|
|
|
return !!(w & q);
|
|
};
|
|
|
|
// Return only lowers bits of number (in-place)
|
|
BN.prototype.imaskn = function imaskn (bits) {
|
|
assert(typeof bits === 'number' && bits >= 0);
|
|
var r = bits % 26;
|
|
var s = (bits - r) / 26;
|
|
|
|
assert(this.negative === 0, 'imaskn works only with positive numbers');
|
|
|
|
if (this.length <= s) {
|
|
return this;
|
|
}
|
|
|
|
if (r !== 0) {
|
|
s++;
|
|
}
|
|
this.length = Math.min(s, this.length);
|
|
|
|
if (r !== 0) {
|
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
|
this.words[this.length - 1] &= mask;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
// Return only lowers bits of number
|
|
BN.prototype.maskn = function maskn (bits) {
|
|
return this.clone().imaskn(bits);
|
|
};
|
|
|
|
// Add plain number `num` to `this`
|
|
BN.prototype.iaddn = function iaddn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.isubn(-num);
|
|
|
|
// Possible sign change
|
|
if (this.negative !== 0) {
|
|
if (this.length === 1 && (this.words[0] | 0) < num) {
|
|
this.words[0] = num - (this.words[0] | 0);
|
|
this.negative = 0;
|
|
return this;
|
|
}
|
|
|
|
this.negative = 0;
|
|
this.isubn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
// Add without checks
|
|
return this._iaddn(num);
|
|
};
|
|
|
|
BN.prototype._iaddn = function _iaddn (num) {
|
|
this.words[0] += num;
|
|
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
|
|
this.words[i] -= 0x4000000;
|
|
if (i === this.length - 1) {
|
|
this.words[i + 1] = 1;
|
|
} else {
|
|
this.words[i + 1]++;
|
|
}
|
|
}
|
|
this.length = Math.max(this.length, i + 1);
|
|
|
|
return this;
|
|
};
|
|
|
|
// Subtract plain number `num` from `this`
|
|
BN.prototype.isubn = function isubn (num) {
|
|
assert(typeof num === 'number');
|
|
assert(num < 0x4000000);
|
|
if (num < 0) return this.iaddn(-num);
|
|
|
|
if (this.negative !== 0) {
|
|
this.negative = 0;
|
|
this.iaddn(num);
|
|
this.negative = 1;
|
|
return this;
|
|
}
|
|
|
|
this.words[0] -= num;
|
|
|
|
if (this.length === 1 && this.words[0] < 0) {
|
|
this.words[0] = -this.words[0];
|
|
this.negative = 1;
|
|
} else {
|
|
// Carry
|
|
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
|
|
this.words[i] += 0x4000000;
|
|
this.words[i + 1] -= 1;
|
|
}
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.addn = function addn (num) {
|
|
return this.clone().iaddn(num);
|
|
};
|
|
|
|
BN.prototype.subn = function subn (num) {
|
|
return this.clone().isubn(num);
|
|
};
|
|
|
|
BN.prototype.iabs = function iabs () {
|
|
this.negative = 0;
|
|
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.abs = function abs () {
|
|
return this.clone().iabs();
|
|
};
|
|
|
|
BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
|
|
var len = num.length + shift;
|
|
var i;
|
|
|
|
this._expand(len);
|
|
|
|
var w;
|
|
var carry = 0;
|
|
for (i = 0; i < num.length; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
var right = (num.words[i] | 0) * mul;
|
|
w -= right & 0x3ffffff;
|
|
carry = (w >> 26) - ((right / 0x4000000) | 0);
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
for (; i < this.length - shift; i++) {
|
|
w = (this.words[i + shift] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i + shift] = w & 0x3ffffff;
|
|
}
|
|
|
|
if (carry === 0) return this.strip();
|
|
|
|
// Subtraction overflow
|
|
assert(carry === -1);
|
|
carry = 0;
|
|
for (i = 0; i < this.length; i++) {
|
|
w = -(this.words[i] | 0) + carry;
|
|
carry = w >> 26;
|
|
this.words[i] = w & 0x3ffffff;
|
|
}
|
|
this.negative = 1;
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype._wordDiv = function _wordDiv (num, mode) {
|
|
var shift = this.length - num.length;
|
|
|
|
var a = this.clone();
|
|
var b = num;
|
|
|
|
// Normalize
|
|
var bhi = b.words[b.length - 1] | 0;
|
|
var bhiBits = this._countBits(bhi);
|
|
shift = 26 - bhiBits;
|
|
if (shift !== 0) {
|
|
b = b.ushln(shift);
|
|
a.iushln(shift);
|
|
bhi = b.words[b.length - 1] | 0;
|
|
}
|
|
|
|
// Initialize quotient
|
|
var m = a.length - b.length;
|
|
var q;
|
|
|
|
if (mode !== 'mod') {
|
|
q = new BN(null);
|
|
q.length = m + 1;
|
|
q.words = new Array(q.length);
|
|
for (var i = 0; i < q.length; i++) {
|
|
q.words[i] = 0;
|
|
}
|
|
}
|
|
|
|
var diff = a.clone()._ishlnsubmul(b, 1, m);
|
|
if (diff.negative === 0) {
|
|
a = diff;
|
|
if (q) {
|
|
q.words[m] = 1;
|
|
}
|
|
}
|
|
|
|
for (var j = m - 1; j >= 0; j--) {
|
|
var qj = (a.words[b.length + j] | 0) * 0x4000000 +
|
|
(a.words[b.length + j - 1] | 0);
|
|
|
|
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
|
|
// (0x7ffffff)
|
|
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
|
|
|
|
a._ishlnsubmul(b, qj, j);
|
|
while (a.negative !== 0) {
|
|
qj--;
|
|
a.negative = 0;
|
|
a._ishlnsubmul(b, 1, j);
|
|
if (!a.isZero()) {
|
|
a.negative ^= 1;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.words[j] = qj;
|
|
}
|
|
}
|
|
if (q) {
|
|
q.strip();
|
|
}
|
|
a.strip();
|
|
|
|
// Denormalize
|
|
if (mode !== 'div' && shift !== 0) {
|
|
a.iushrn(shift);
|
|
}
|
|
|
|
return {
|
|
div: q || null,
|
|
mod: a
|
|
};
|
|
};
|
|
|
|
// NOTE: 1) `mode` can be set to `mod` to request mod only,
|
|
// to `div` to request div only, or be absent to
|
|
// request both div & mod
|
|
// 2) `positive` is true if unsigned mod is requested
|
|
BN.prototype.divmod = function divmod (num, mode, positive) {
|
|
assert(!num.isZero());
|
|
|
|
if (this.isZero()) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: new BN(0)
|
|
};
|
|
}
|
|
|
|
var div, mod, res;
|
|
if (this.negative !== 0 && num.negative === 0) {
|
|
res = this.neg().divmod(num, mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.iadd(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
if (this.negative === 0 && num.negative !== 0) {
|
|
res = this.divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'mod') {
|
|
div = res.div.neg();
|
|
}
|
|
|
|
return {
|
|
div: div,
|
|
mod: res.mod
|
|
};
|
|
}
|
|
|
|
if ((this.negative & num.negative) !== 0) {
|
|
res = this.neg().divmod(num.neg(), mode);
|
|
|
|
if (mode !== 'div') {
|
|
mod = res.mod.neg();
|
|
if (positive && mod.negative !== 0) {
|
|
mod.isub(num);
|
|
}
|
|
}
|
|
|
|
return {
|
|
div: res.div,
|
|
mod: mod
|
|
};
|
|
}
|
|
|
|
// Both numbers are positive at this point
|
|
|
|
// Strip both numbers to approximate shift value
|
|
if (num.length > this.length || this.cmp(num) < 0) {
|
|
return {
|
|
div: new BN(0),
|
|
mod: this
|
|
};
|
|
}
|
|
|
|
// Very short reduction
|
|
if (num.length === 1) {
|
|
if (mode === 'div') {
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: null
|
|
};
|
|
}
|
|
|
|
if (mode === 'mod') {
|
|
return {
|
|
div: null,
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return {
|
|
div: this.divn(num.words[0]),
|
|
mod: new BN(this.modn(num.words[0]))
|
|
};
|
|
}
|
|
|
|
return this._wordDiv(num, mode);
|
|
};
|
|
|
|
// Find `this` / `num`
|
|
BN.prototype.div = function div (num) {
|
|
return this.divmod(num, 'div', false).div;
|
|
};
|
|
|
|
// Find `this` % `num`
|
|
BN.prototype.mod = function mod (num) {
|
|
return this.divmod(num, 'mod', false).mod;
|
|
};
|
|
|
|
BN.prototype.umod = function umod (num) {
|
|
return this.divmod(num, 'mod', true).mod;
|
|
};
|
|
|
|
// Find Round(`this` / `num`)
|
|
BN.prototype.divRound = function divRound (num) {
|
|
var dm = this.divmod(num);
|
|
|
|
// Fast case - exact division
|
|
if (dm.mod.isZero()) return dm.div;
|
|
|
|
var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
|
|
|
|
var half = num.ushrn(1);
|
|
var r2 = num.andln(1);
|
|
var cmp = mod.cmp(half);
|
|
|
|
// Round down
|
|
if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
|
|
|
|
// Round up
|
|
return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
|
|
};
|
|
|
|
BN.prototype.modn = function modn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
var p = (1 << 26) % num;
|
|
|
|
var acc = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
acc = (p * acc + (this.words[i] | 0)) % num;
|
|
}
|
|
|
|
return acc;
|
|
};
|
|
|
|
// In-place division by number
|
|
BN.prototype.idivn = function idivn (num) {
|
|
assert(num <= 0x3ffffff);
|
|
|
|
var carry = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var w = (this.words[i] | 0) + carry * 0x4000000;
|
|
this.words[i] = (w / num) | 0;
|
|
carry = w % num;
|
|
}
|
|
|
|
return this.strip();
|
|
};
|
|
|
|
BN.prototype.divn = function divn (num) {
|
|
return this.clone().idivn(num);
|
|
};
|
|
|
|
BN.prototype.egcd = function egcd (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var x = this;
|
|
var y = p.clone();
|
|
|
|
if (x.negative !== 0) {
|
|
x = x.umod(p);
|
|
} else {
|
|
x = x.clone();
|
|
}
|
|
|
|
// A * x + B * y = x
|
|
var A = new BN(1);
|
|
var B = new BN(0);
|
|
|
|
// C * x + D * y = y
|
|
var C = new BN(0);
|
|
var D = new BN(1);
|
|
|
|
var g = 0;
|
|
|
|
while (x.isEven() && y.isEven()) {
|
|
x.iushrn(1);
|
|
y.iushrn(1);
|
|
++g;
|
|
}
|
|
|
|
var yp = y.clone();
|
|
var xp = x.clone();
|
|
|
|
while (!x.isZero()) {
|
|
for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
x.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (A.isOdd() || B.isOdd()) {
|
|
A.iadd(yp);
|
|
B.isub(xp);
|
|
}
|
|
|
|
A.iushrn(1);
|
|
B.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
y.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (C.isOdd() || D.isOdd()) {
|
|
C.iadd(yp);
|
|
D.isub(xp);
|
|
}
|
|
|
|
C.iushrn(1);
|
|
D.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (x.cmp(y) >= 0) {
|
|
x.isub(y);
|
|
A.isub(C);
|
|
B.isub(D);
|
|
} else {
|
|
y.isub(x);
|
|
C.isub(A);
|
|
D.isub(B);
|
|
}
|
|
}
|
|
|
|
return {
|
|
a: C,
|
|
b: D,
|
|
gcd: y.iushln(g)
|
|
};
|
|
};
|
|
|
|
// This is reduced incarnation of the binary EEA
|
|
// above, designated to invert members of the
|
|
// _prime_ fields F(p) at a maximal speed
|
|
BN.prototype._invmp = function _invmp (p) {
|
|
assert(p.negative === 0);
|
|
assert(!p.isZero());
|
|
|
|
var a = this;
|
|
var b = p.clone();
|
|
|
|
if (a.negative !== 0) {
|
|
a = a.umod(p);
|
|
} else {
|
|
a = a.clone();
|
|
}
|
|
|
|
var x1 = new BN(1);
|
|
var x2 = new BN(0);
|
|
|
|
var delta = b.clone();
|
|
|
|
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
|
|
for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
|
if (i > 0) {
|
|
a.iushrn(i);
|
|
while (i-- > 0) {
|
|
if (x1.isOdd()) {
|
|
x1.iadd(delta);
|
|
}
|
|
|
|
x1.iushrn(1);
|
|
}
|
|
}
|
|
|
|
for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
|
if (j > 0) {
|
|
b.iushrn(j);
|
|
while (j-- > 0) {
|
|
if (x2.isOdd()) {
|
|
x2.iadd(delta);
|
|
}
|
|
|
|
x2.iushrn(1);
|
|
}
|
|
}
|
|
|
|
if (a.cmp(b) >= 0) {
|
|
a.isub(b);
|
|
x1.isub(x2);
|
|
} else {
|
|
b.isub(a);
|
|
x2.isub(x1);
|
|
}
|
|
}
|
|
|
|
var res;
|
|
if (a.cmpn(1) === 0) {
|
|
res = x1;
|
|
} else {
|
|
res = x2;
|
|
}
|
|
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(p);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gcd = function gcd (num) {
|
|
if (this.isZero()) return num.abs();
|
|
if (num.isZero()) return this.abs();
|
|
|
|
var a = this.clone();
|
|
var b = num.clone();
|
|
a.negative = 0;
|
|
b.negative = 0;
|
|
|
|
// Remove common factor of two
|
|
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
|
|
a.iushrn(1);
|
|
b.iushrn(1);
|
|
}
|
|
|
|
do {
|
|
while (a.isEven()) {
|
|
a.iushrn(1);
|
|
}
|
|
while (b.isEven()) {
|
|
b.iushrn(1);
|
|
}
|
|
|
|
var r = a.cmp(b);
|
|
if (r < 0) {
|
|
// Swap `a` and `b` to make `a` always bigger than `b`
|
|
var t = a;
|
|
a = b;
|
|
b = t;
|
|
} else if (r === 0 || b.cmpn(1) === 0) {
|
|
break;
|
|
}
|
|
|
|
a.isub(b);
|
|
} while (true);
|
|
|
|
return b.iushln(shift);
|
|
};
|
|
|
|
// Invert number in the field F(num)
|
|
BN.prototype.invm = function invm (num) {
|
|
return this.egcd(num).a.umod(num);
|
|
};
|
|
|
|
BN.prototype.isEven = function isEven () {
|
|
return (this.words[0] & 1) === 0;
|
|
};
|
|
|
|
BN.prototype.isOdd = function isOdd () {
|
|
return (this.words[0] & 1) === 1;
|
|
};
|
|
|
|
// And first word and num
|
|
BN.prototype.andln = function andln (num) {
|
|
return this.words[0] & num;
|
|
};
|
|
|
|
// Increment at the bit position in-line
|
|
BN.prototype.bincn = function bincn (bit) {
|
|
assert(typeof bit === 'number');
|
|
var r = bit % 26;
|
|
var s = (bit - r) / 26;
|
|
var q = 1 << r;
|
|
|
|
// Fast case: bit is much higher than all existing words
|
|
if (this.length <= s) {
|
|
this._expand(s + 1);
|
|
this.words[s] |= q;
|
|
return this;
|
|
}
|
|
|
|
// Add bit and propagate, if needed
|
|
var carry = q;
|
|
for (var i = s; carry !== 0 && i < this.length; i++) {
|
|
var w = this.words[i] | 0;
|
|
w += carry;
|
|
carry = w >>> 26;
|
|
w &= 0x3ffffff;
|
|
this.words[i] = w;
|
|
}
|
|
if (carry !== 0) {
|
|
this.words[i] = carry;
|
|
this.length++;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.isZero = function isZero () {
|
|
return this.length === 1 && this.words[0] === 0;
|
|
};
|
|
|
|
BN.prototype.cmpn = function cmpn (num) {
|
|
var negative = num < 0;
|
|
|
|
if (this.negative !== 0 && !negative) return -1;
|
|
if (this.negative === 0 && negative) return 1;
|
|
|
|
this.strip();
|
|
|
|
var res;
|
|
if (this.length > 1) {
|
|
res = 1;
|
|
} else {
|
|
if (negative) {
|
|
num = -num;
|
|
}
|
|
|
|
assert(num <= 0x3ffffff, 'Number is too big');
|
|
|
|
var w = this.words[0] | 0;
|
|
res = w === num ? 0 : w < num ? -1 : 1;
|
|
}
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Compare two numbers and return:
|
|
// 1 - if `this` > `num`
|
|
// 0 - if `this` == `num`
|
|
// -1 - if `this` < `num`
|
|
BN.prototype.cmp = function cmp (num) {
|
|
if (this.negative !== 0 && num.negative === 0) return -1;
|
|
if (this.negative === 0 && num.negative !== 0) return 1;
|
|
|
|
var res = this.ucmp(num);
|
|
if (this.negative !== 0) return -res | 0;
|
|
return res;
|
|
};
|
|
|
|
// Unsigned comparison
|
|
BN.prototype.ucmp = function ucmp (num) {
|
|
// At this point both numbers have the same sign
|
|
if (this.length > num.length) return 1;
|
|
if (this.length < num.length) return -1;
|
|
|
|
var res = 0;
|
|
for (var i = this.length - 1; i >= 0; i--) {
|
|
var a = this.words[i] | 0;
|
|
var b = num.words[i] | 0;
|
|
|
|
if (a === b) continue;
|
|
if (a < b) {
|
|
res = -1;
|
|
} else if (a > b) {
|
|
res = 1;
|
|
}
|
|
break;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
BN.prototype.gtn = function gtn (num) {
|
|
return this.cmpn(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gt = function gt (num) {
|
|
return this.cmp(num) === 1;
|
|
};
|
|
|
|
BN.prototype.gten = function gten (num) {
|
|
return this.cmpn(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.gte = function gte (num) {
|
|
return this.cmp(num) >= 0;
|
|
};
|
|
|
|
BN.prototype.ltn = function ltn (num) {
|
|
return this.cmpn(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lt = function lt (num) {
|
|
return this.cmp(num) === -1;
|
|
};
|
|
|
|
BN.prototype.lten = function lten (num) {
|
|
return this.cmpn(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.lte = function lte (num) {
|
|
return this.cmp(num) <= 0;
|
|
};
|
|
|
|
BN.prototype.eqn = function eqn (num) {
|
|
return this.cmpn(num) === 0;
|
|
};
|
|
|
|
BN.prototype.eq = function eq (num) {
|
|
return this.cmp(num) === 0;
|
|
};
|
|
|
|
//
|
|
// A reduce context, could be using montgomery or something better, depending
|
|
// on the `m` itself.
|
|
//
|
|
BN.red = function red (num) {
|
|
return new Red(num);
|
|
};
|
|
|
|
BN.prototype.toRed = function toRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
assert(this.negative === 0, 'red works only with positives');
|
|
return ctx.convertTo(this)._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.fromRed = function fromRed () {
|
|
assert(this.red, 'fromRed works only with numbers in reduction context');
|
|
return this.red.convertFrom(this);
|
|
};
|
|
|
|
BN.prototype._forceRed = function _forceRed (ctx) {
|
|
this.red = ctx;
|
|
return this;
|
|
};
|
|
|
|
BN.prototype.forceRed = function forceRed (ctx) {
|
|
assert(!this.red, 'Already a number in reduction context');
|
|
return this._forceRed(ctx);
|
|
};
|
|
|
|
BN.prototype.redAdd = function redAdd (num) {
|
|
assert(this.red, 'redAdd works only with red numbers');
|
|
return this.red.add(this, num);
|
|
};
|
|
|
|
BN.prototype.redIAdd = function redIAdd (num) {
|
|
assert(this.red, 'redIAdd works only with red numbers');
|
|
return this.red.iadd(this, num);
|
|
};
|
|
|
|
BN.prototype.redSub = function redSub (num) {
|
|
assert(this.red, 'redSub works only with red numbers');
|
|
return this.red.sub(this, num);
|
|
};
|
|
|
|
BN.prototype.redISub = function redISub (num) {
|
|
assert(this.red, 'redISub works only with red numbers');
|
|
return this.red.isub(this, num);
|
|
};
|
|
|
|
BN.prototype.redShl = function redShl (num) {
|
|
assert(this.red, 'redShl works only with red numbers');
|
|
return this.red.shl(this, num);
|
|
};
|
|
|
|
BN.prototype.redMul = function redMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.mul(this, num);
|
|
};
|
|
|
|
BN.prototype.redIMul = function redIMul (num) {
|
|
assert(this.red, 'redMul works only with red numbers');
|
|
this.red._verify2(this, num);
|
|
return this.red.imul(this, num);
|
|
};
|
|
|
|
BN.prototype.redSqr = function redSqr () {
|
|
assert(this.red, 'redSqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqr(this);
|
|
};
|
|
|
|
BN.prototype.redISqr = function redISqr () {
|
|
assert(this.red, 'redISqr works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.isqr(this);
|
|
};
|
|
|
|
// Square root over p
|
|
BN.prototype.redSqrt = function redSqrt () {
|
|
assert(this.red, 'redSqrt works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.sqrt(this);
|
|
};
|
|
|
|
BN.prototype.redInvm = function redInvm () {
|
|
assert(this.red, 'redInvm works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.invm(this);
|
|
};
|
|
|
|
// Return negative clone of `this` % `red modulo`
|
|
BN.prototype.redNeg = function redNeg () {
|
|
assert(this.red, 'redNeg works only with red numbers');
|
|
this.red._verify1(this);
|
|
return this.red.neg(this);
|
|
};
|
|
|
|
BN.prototype.redPow = function redPow (num) {
|
|
assert(this.red && !num.red, 'redPow(normalNum)');
|
|
this.red._verify1(this);
|
|
return this.red.pow(this, num);
|
|
};
|
|
|
|
// Prime numbers with efficient reduction
|
|
var primes = {
|
|
k256: null,
|
|
p224: null,
|
|
p192: null,
|
|
p25519: null
|
|
};
|
|
|
|
// Pseudo-Mersenne prime
|
|
function MPrime (name, p) {
|
|
// P = 2 ^ N - K
|
|
this.name = name;
|
|
this.p = new BN(p, 16);
|
|
this.n = this.p.bitLength();
|
|
this.k = new BN(1).iushln(this.n).isub(this.p);
|
|
|
|
this.tmp = this._tmp();
|
|
}
|
|
|
|
MPrime.prototype._tmp = function _tmp () {
|
|
var tmp = new BN(null);
|
|
tmp.words = new Array(Math.ceil(this.n / 13));
|
|
return tmp;
|
|
};
|
|
|
|
MPrime.prototype.ireduce = function ireduce (num) {
|
|
// Assumes that `num` is less than `P^2`
|
|
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
|
|
var r = num;
|
|
var rlen;
|
|
|
|
do {
|
|
this.split(r, this.tmp);
|
|
r = this.imulK(r);
|
|
r = r.iadd(this.tmp);
|
|
rlen = r.bitLength();
|
|
} while (rlen > this.n);
|
|
|
|
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
|
|
if (cmp === 0) {
|
|
r.words[0] = 0;
|
|
r.length = 1;
|
|
} else if (cmp > 0) {
|
|
r.isub(this.p);
|
|
} else {
|
|
r.strip();
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
MPrime.prototype.split = function split (input, out) {
|
|
input.iushrn(this.n, 0, out);
|
|
};
|
|
|
|
MPrime.prototype.imulK = function imulK (num) {
|
|
return num.imul(this.k);
|
|
};
|
|
|
|
function K256 () {
|
|
MPrime.call(
|
|
this,
|
|
'k256',
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
|
|
}
|
|
inherits(K256, MPrime);
|
|
|
|
K256.prototype.split = function split (input, output) {
|
|
// 256 = 9 * 26 + 22
|
|
var mask = 0x3fffff;
|
|
|
|
var outLen = Math.min(input.length, 9);
|
|
for (var i = 0; i < outLen; i++) {
|
|
output.words[i] = input.words[i];
|
|
}
|
|
output.length = outLen;
|
|
|
|
if (input.length <= 9) {
|
|
input.words[0] = 0;
|
|
input.length = 1;
|
|
return;
|
|
}
|
|
|
|
// Shift by 9 limbs
|
|
var prev = input.words[9];
|
|
output.words[output.length++] = prev & mask;
|
|
|
|
for (i = 10; i < input.length; i++) {
|
|
var next = input.words[i] | 0;
|
|
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
|
|
prev = next;
|
|
}
|
|
prev >>>= 22;
|
|
input.words[i - 10] = prev;
|
|
if (prev === 0 && input.length > 10) {
|
|
input.length -= 10;
|
|
} else {
|
|
input.length -= 9;
|
|
}
|
|
};
|
|
|
|
K256.prototype.imulK = function imulK (num) {
|
|
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
|
|
num.words[num.length] = 0;
|
|
num.words[num.length + 1] = 0;
|
|
num.length += 2;
|
|
|
|
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
|
|
var lo = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var w = num.words[i] | 0;
|
|
lo += w * 0x3d1;
|
|
num.words[i] = lo & 0x3ffffff;
|
|
lo = w * 0x40 + ((lo / 0x4000000) | 0);
|
|
}
|
|
|
|
// Fast length reduction
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
if (num.words[num.length - 1] === 0) {
|
|
num.length--;
|
|
}
|
|
}
|
|
return num;
|
|
};
|
|
|
|
function P224 () {
|
|
MPrime.call(
|
|
this,
|
|
'p224',
|
|
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
|
|
}
|
|
inherits(P224, MPrime);
|
|
|
|
function P192 () {
|
|
MPrime.call(
|
|
this,
|
|
'p192',
|
|
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
|
|
}
|
|
inherits(P192, MPrime);
|
|
|
|
function P25519 () {
|
|
// 2 ^ 255 - 19
|
|
MPrime.call(
|
|
this,
|
|
'25519',
|
|
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
|
|
}
|
|
inherits(P25519, MPrime);
|
|
|
|
P25519.prototype.imulK = function imulK (num) {
|
|
// K = 0x13
|
|
var carry = 0;
|
|
for (var i = 0; i < num.length; i++) {
|
|
var hi = (num.words[i] | 0) * 0x13 + carry;
|
|
var lo = hi & 0x3ffffff;
|
|
hi >>>= 26;
|
|
|
|
num.words[i] = lo;
|
|
carry = hi;
|
|
}
|
|
if (carry !== 0) {
|
|
num.words[num.length++] = carry;
|
|
}
|
|
return num;
|
|
};
|
|
|
|
// Exported mostly for testing purposes, use plain name instead
|
|
BN._prime = function prime (name) {
|
|
// Cached version of prime
|
|
if (primes[name]) return primes[name];
|
|
|
|
var prime;
|
|
if (name === 'k256') {
|
|
prime = new K256();
|
|
} else if (name === 'p224') {
|
|
prime = new P224();
|
|
} else if (name === 'p192') {
|
|
prime = new P192();
|
|
} else if (name === 'p25519') {
|
|
prime = new P25519();
|
|
} else {
|
|
throw new Error('Unknown prime ' + name);
|
|
}
|
|
primes[name] = prime;
|
|
|
|
return prime;
|
|
};
|
|
|
|
//
|
|
// Base reduction engine
|
|
//
|
|
function Red (m) {
|
|
if (typeof m === 'string') {
|
|
var prime = BN._prime(m);
|
|
this.m = prime.p;
|
|
this.prime = prime;
|
|
} else {
|
|
assert(m.gtn(1), 'modulus must be greater than 1');
|
|
this.m = m;
|
|
this.prime = null;
|
|
}
|
|
}
|
|
|
|
Red.prototype._verify1 = function _verify1 (a) {
|
|
assert(a.negative === 0, 'red works only with positives');
|
|
assert(a.red, 'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype._verify2 = function _verify2 (a, b) {
|
|
assert((a.negative | b.negative) === 0, 'red works only with positives');
|
|
assert(a.red && a.red === b.red,
|
|
'red works only with red numbers');
|
|
};
|
|
|
|
Red.prototype.imod = function imod (a) {
|
|
if (this.prime) return this.prime.ireduce(a)._forceRed(this);
|
|
return a.umod(this.m)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.neg = function neg (a) {
|
|
if (a.isZero()) {
|
|
return a.clone();
|
|
}
|
|
|
|
return this.m.sub(a)._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.add = function add (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.add(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.iadd = function iadd (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.iadd(b);
|
|
if (res.cmp(this.m) >= 0) {
|
|
res.isub(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.sub = function sub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.sub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Red.prototype.isub = function isub (a, b) {
|
|
this._verify2(a, b);
|
|
|
|
var res = a.isub(b);
|
|
if (res.cmpn(0) < 0) {
|
|
res.iadd(this.m);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.shl = function shl (a, num) {
|
|
this._verify1(a);
|
|
return this.imod(a.ushln(num));
|
|
};
|
|
|
|
Red.prototype.imul = function imul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.imul(b));
|
|
};
|
|
|
|
Red.prototype.mul = function mul (a, b) {
|
|
this._verify2(a, b);
|
|
return this.imod(a.mul(b));
|
|
};
|
|
|
|
Red.prototype.isqr = function isqr (a) {
|
|
return this.imul(a, a.clone());
|
|
};
|
|
|
|
Red.prototype.sqr = function sqr (a) {
|
|
return this.mul(a, a);
|
|
};
|
|
|
|
Red.prototype.sqrt = function sqrt (a) {
|
|
if (a.isZero()) return a.clone();
|
|
|
|
var mod3 = this.m.andln(3);
|
|
assert(mod3 % 2 === 1);
|
|
|
|
// Fast case
|
|
if (mod3 === 3) {
|
|
var pow = this.m.add(new BN(1)).iushrn(2);
|
|
return this.pow(a, pow);
|
|
}
|
|
|
|
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
|
|
//
|
|
// Find Q and S, that Q * 2 ^ S = (P - 1)
|
|
var q = this.m.subn(1);
|
|
var s = 0;
|
|
while (!q.isZero() && q.andln(1) === 0) {
|
|
s++;
|
|
q.iushrn(1);
|
|
}
|
|
assert(!q.isZero());
|
|
|
|
var one = new BN(1).toRed(this);
|
|
var nOne = one.redNeg();
|
|
|
|
// Find quadratic non-residue
|
|
// NOTE: Max is such because of generalized Riemann hypothesis.
|
|
var lpow = this.m.subn(1).iushrn(1);
|
|
var z = this.m.bitLength();
|
|
z = new BN(2 * z * z).toRed(this);
|
|
|
|
while (this.pow(z, lpow).cmp(nOne) !== 0) {
|
|
z.redIAdd(nOne);
|
|
}
|
|
|
|
var c = this.pow(z, q);
|
|
var r = this.pow(a, q.addn(1).iushrn(1));
|
|
var t = this.pow(a, q);
|
|
var m = s;
|
|
while (t.cmp(one) !== 0) {
|
|
var tmp = t;
|
|
for (var i = 0; tmp.cmp(one) !== 0; i++) {
|
|
tmp = tmp.redSqr();
|
|
}
|
|
assert(i < m);
|
|
var b = this.pow(c, new BN(1).iushln(m - i - 1));
|
|
|
|
r = r.redMul(b);
|
|
c = b.redSqr();
|
|
t = t.redMul(c);
|
|
m = i;
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
Red.prototype.invm = function invm (a) {
|
|
var inv = a._invmp(this.m);
|
|
if (inv.negative !== 0) {
|
|
inv.negative = 0;
|
|
return this.imod(inv).redNeg();
|
|
} else {
|
|
return this.imod(inv);
|
|
}
|
|
};
|
|
|
|
Red.prototype.pow = function pow (a, num) {
|
|
if (num.isZero()) return new BN(1).toRed(this);
|
|
if (num.cmpn(1) === 0) return a.clone();
|
|
|
|
var windowSize = 4;
|
|
var wnd = new Array(1 << windowSize);
|
|
wnd[0] = new BN(1).toRed(this);
|
|
wnd[1] = a;
|
|
for (var i = 2; i < wnd.length; i++) {
|
|
wnd[i] = this.mul(wnd[i - 1], a);
|
|
}
|
|
|
|
var res = wnd[0];
|
|
var current = 0;
|
|
var currentLen = 0;
|
|
var start = num.bitLength() % 26;
|
|
if (start === 0) {
|
|
start = 26;
|
|
}
|
|
|
|
for (i = num.length - 1; i >= 0; i--) {
|
|
var word = num.words[i];
|
|
for (var j = start - 1; j >= 0; j--) {
|
|
var bit = (word >> j) & 1;
|
|
if (res !== wnd[0]) {
|
|
res = this.sqr(res);
|
|
}
|
|
|
|
if (bit === 0 && current === 0) {
|
|
currentLen = 0;
|
|
continue;
|
|
}
|
|
|
|
current <<= 1;
|
|
current |= bit;
|
|
currentLen++;
|
|
if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
|
|
|
|
res = this.mul(res, wnd[current]);
|
|
currentLen = 0;
|
|
current = 0;
|
|
}
|
|
start = 26;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Red.prototype.convertTo = function convertTo (num) {
|
|
var r = num.umod(this.m);
|
|
|
|
return r === num ? r.clone() : r;
|
|
};
|
|
|
|
Red.prototype.convertFrom = function convertFrom (num) {
|
|
var res = num.clone();
|
|
res.red = null;
|
|
return res;
|
|
};
|
|
|
|
//
|
|
// Montgomery method engine
|
|
//
|
|
|
|
BN.mont = function mont (num) {
|
|
return new Mont(num);
|
|
};
|
|
|
|
function Mont (m) {
|
|
Red.call(this, m);
|
|
|
|
this.shift = this.m.bitLength();
|
|
if (this.shift % 26 !== 0) {
|
|
this.shift += 26 - (this.shift % 26);
|
|
}
|
|
|
|
this.r = new BN(1).iushln(this.shift);
|
|
this.r2 = this.imod(this.r.sqr());
|
|
this.rinv = this.r._invmp(this.m);
|
|
|
|
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
|
|
this.minv = this.minv.umod(this.r);
|
|
this.minv = this.r.sub(this.minv);
|
|
}
|
|
inherits(Mont, Red);
|
|
|
|
Mont.prototype.convertTo = function convertTo (num) {
|
|
return this.imod(num.ushln(this.shift));
|
|
};
|
|
|
|
Mont.prototype.convertFrom = function convertFrom (num) {
|
|
var r = this.imod(num.mul(this.rinv));
|
|
r.red = null;
|
|
return r;
|
|
};
|
|
|
|
Mont.prototype.imul = function imul (a, b) {
|
|
if (a.isZero() || b.isZero()) {
|
|
a.words[0] = 0;
|
|
a.length = 1;
|
|
return a;
|
|
}
|
|
|
|
var t = a.imul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.mul = function mul (a, b) {
|
|
if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
|
|
|
|
var t = a.mul(b);
|
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
|
var u = t.isub(c).iushrn(this.shift);
|
|
var res = u;
|
|
if (u.cmp(this.m) >= 0) {
|
|
res = u.isub(this.m);
|
|
} else if (u.cmpn(0) < 0) {
|
|
res = u.iadd(this.m);
|
|
}
|
|
|
|
return res._forceRed(this);
|
|
};
|
|
|
|
Mont.prototype.invm = function invm (a) {
|
|
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
|
|
var res = this.imod(a._invmp(this.m).mul(this.r2));
|
|
return res._forceRed(this);
|
|
};
|
|
})(typeof module === 'undefined' || module, this);
|
|
|
|
},{"buffer":46}],281:[function(require,module,exports){
|
|
var basex = require('base-x')
|
|
var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
|
|
|
module.exports = basex(ALPHABET)
|
|
|
|
},{"base-x":282}],282:[function(require,module,exports){
|
|
// base-x encoding
|
|
// Forked from https://github.com/cryptocoinjs/bs58
|
|
// Originally written by Mike Hearn for BitcoinJ
|
|
// Copyright (c) 2011 Google Inc
|
|
// Ported to JavaScript by Stefan Thomas
|
|
// Merged Buffer refactorings from base58-native by Stephen Pair
|
|
// Copyright (c) 2013 BitPay Inc
|
|
|
|
var Buffer = require('safe-buffer').Buffer
|
|
|
|
module.exports = function base (ALPHABET) {
|
|
var ALPHABET_MAP = {}
|
|
var BASE = ALPHABET.length
|
|
var LEADER = ALPHABET.charAt(0)
|
|
|
|
// pre-compute lookup table
|
|
for (var z = 0; z < ALPHABET.length; z++) {
|
|
var x = ALPHABET.charAt(z)
|
|
|
|
if (ALPHABET_MAP[x] !== undefined) throw new TypeError(x + ' is ambiguous')
|
|
ALPHABET_MAP[x] = z
|
|
}
|
|
|
|
function encode (source) {
|
|
if (source.length === 0) return ''
|
|
|
|
var digits = [0]
|
|
for (var i = 0; i < source.length; ++i) {
|
|
for (var j = 0, carry = source[i]; j < digits.length; ++j) {
|
|
carry += digits[j] << 8
|
|
digits[j] = carry % BASE
|
|
carry = (carry / BASE) | 0
|
|
}
|
|
|
|
while (carry > 0) {
|
|
digits.push(carry % BASE)
|
|
carry = (carry / BASE) | 0
|
|
}
|
|
}
|
|
|
|
var string = ''
|
|
|
|
// deal with leading zeros
|
|
for (var k = 0; source[k] === 0 && k < source.length - 1; ++k) string += ALPHABET[0]
|
|
// convert digits to a string
|
|
for (var q = digits.length - 1; q >= 0; --q) string += ALPHABET[digits[q]]
|
|
|
|
return string
|
|
}
|
|
|
|
function decodeUnsafe (string) {
|
|
if (string.length === 0) return Buffer.allocUnsafe(0)
|
|
|
|
var bytes = [0]
|
|
for (var i = 0; i < string.length; i++) {
|
|
var value = ALPHABET_MAP[string[i]]
|
|
if (value === undefined) return
|
|
|
|
for (var j = 0, carry = value; j < bytes.length; ++j) {
|
|
carry += bytes[j] * BASE
|
|
bytes[j] = carry & 0xff
|
|
carry >>= 8
|
|
}
|
|
|
|
while (carry > 0) {
|
|
bytes.push(carry & 0xff)
|
|
carry >>= 8
|
|
}
|
|
}
|
|
|
|
// deal with leading zeros
|
|
for (var k = 0; string[k] === LEADER && k < string.length - 1; ++k) {
|
|
bytes.push(0)
|
|
}
|
|
|
|
return Buffer.from(bytes.reverse())
|
|
}
|
|
|
|
function decode (string) {
|
|
var buffer = decodeUnsafe(string)
|
|
if (buffer) return buffer
|
|
|
|
throw new Error('Non-base' + BASE + ' character')
|
|
}
|
|
|
|
return {
|
|
encode: encode,
|
|
decodeUnsafe: decodeUnsafe,
|
|
decode: decode
|
|
}
|
|
}
|
|
|
|
},{"safe-buffer":283}],283:[function(require,module,exports){
|
|
arguments[4][71][0].apply(exports,arguments)
|
|
},{"buffer":47,"dup":71}],284:[function(require,module,exports){
|
|
module.exports = function(a, b) {
|
|
if (typeof a.compare === 'function') return a.compare(b)
|
|
if (a === b) return 0
|
|
|
|
var x = a.length
|
|
var y = b.length
|
|
|
|
var i = 0
|
|
var len = Math.min(x, y)
|
|
while (i < len) {
|
|
if (a[i] !== b[i]) break
|
|
|
|
++i
|
|
}
|
|
|
|
if (i !== len) {
|
|
x = a[i]
|
|
y = b[i]
|
|
}
|
|
|
|
if (x < y) return -1
|
|
if (y < x) return 1
|
|
return 0
|
|
}
|
|
|
|
|
|
},{}],285:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var elliptic = exports;
|
|
|
|
elliptic.version = require('../package.json').version;
|
|
elliptic.utils = require('./elliptic/utils');
|
|
elliptic.rand = require('brorand');
|
|
elliptic.curve = require('./elliptic/curve');
|
|
elliptic.curves = require('./elliptic/curves');
|
|
|
|
// Protocols
|
|
elliptic.ec = require('./elliptic/ec');
|
|
elliptic.eddsa = require('./elliptic/eddsa');
|
|
|
|
},{"../package.json":317,"./elliptic/curve":288,"./elliptic/curves":291,"./elliptic/ec":292,"./elliptic/eddsa":295,"./elliptic/utils":299,"brorand":300}],286:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var BN = require('bn.js');
|
|
var elliptic = require('../../elliptic');
|
|
var utils = elliptic.utils;
|
|
var getNAF = utils.getNAF;
|
|
var getJSF = utils.getJSF;
|
|
var assert = utils.assert;
|
|
|
|
function BaseCurve(type, conf) {
|
|
this.type = type;
|
|
this.p = new BN(conf.p, 16);
|
|
|
|
// Use Montgomery, when there is no fast reduction for the prime
|
|
this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p);
|
|
|
|
// Useful for many curves
|
|
this.zero = new BN(0).toRed(this.red);
|
|
this.one = new BN(1).toRed(this.red);
|
|
this.two = new BN(2).toRed(this.red);
|
|
|
|
// Curve configuration, optional
|
|
this.n = conf.n && new BN(conf.n, 16);
|
|
this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed);
|
|
|
|
// Temporary arrays
|
|
this._wnafT1 = new Array(4);
|
|
this._wnafT2 = new Array(4);
|
|
this._wnafT3 = new Array(4);
|
|
this._wnafT4 = new Array(4);
|
|
|
|
// Generalized Greg Maxwell's trick
|
|
var adjustCount = this.n && this.p.div(this.n);
|
|
if (!adjustCount || adjustCount.cmpn(100) > 0) {
|
|
this.redN = null;
|
|
} else {
|
|
this._maxwellTrick = true;
|
|
this.redN = this.n.toRed(this.red);
|
|
}
|
|
}
|
|
module.exports = BaseCurve;
|
|
|
|
BaseCurve.prototype.point = function point() {
|
|
throw new Error('Not implemented');
|
|
};
|
|
|
|
BaseCurve.prototype.validate = function validate() {
|
|
throw new Error('Not implemented');
|
|
};
|
|
|
|
BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) {
|
|
assert(p.precomputed);
|
|
var doubles = p._getDoubles();
|
|
|
|
var naf = getNAF(k, 1);
|
|
var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1);
|
|
I /= 3;
|
|
|
|
// Translate into more windowed form
|
|
var repr = [];
|
|
for (var j = 0; j < naf.length; j += doubles.step) {
|
|
var nafW = 0;
|
|
for (var k = j + doubles.step - 1; k >= j; k--)
|
|
nafW = (nafW << 1) + naf[k];
|
|
repr.push(nafW);
|
|
}
|
|
|
|
var a = this.jpoint(null, null, null);
|
|
var b = this.jpoint(null, null, null);
|
|
for (var i = I; i > 0; i--) {
|
|
for (var j = 0; j < repr.length; j++) {
|
|
var nafW = repr[j];
|
|
if (nafW === i)
|
|
b = b.mixedAdd(doubles.points[j]);
|
|
else if (nafW === -i)
|
|
b = b.mixedAdd(doubles.points[j].neg());
|
|
}
|
|
a = a.add(b);
|
|
}
|
|
return a.toP();
|
|
};
|
|
|
|
BaseCurve.prototype._wnafMul = function _wnafMul(p, k) {
|
|
var w = 4;
|
|
|
|
// Precompute window
|
|
var nafPoints = p._getNAFPoints(w);
|
|
w = nafPoints.wnd;
|
|
var wnd = nafPoints.points;
|
|
|
|
// Get NAF form
|
|
var naf = getNAF(k, w);
|
|
|
|
// Add `this`*(N+1) for every w-NAF index
|
|
var acc = this.jpoint(null, null, null);
|
|
for (var i = naf.length - 1; i >= 0; i--) {
|
|
// Count zeroes
|
|
for (var k = 0; i >= 0 && naf[i] === 0; i--)
|
|
k++;
|
|
if (i >= 0)
|
|
k++;
|
|
acc = acc.dblp(k);
|
|
|
|
if (i < 0)
|
|
break;
|
|
var z = naf[i];
|
|
assert(z !== 0);
|
|
if (p.type === 'affine') {
|
|
// J +- P
|
|
if (z > 0)
|
|
acc = acc.mixedAdd(wnd[(z - 1) >> 1]);
|
|
else
|
|
acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg());
|
|
} else {
|
|
// J +- J
|
|
if (z > 0)
|
|
acc = acc.add(wnd[(z - 1) >> 1]);
|
|
else
|
|
acc = acc.add(wnd[(-z - 1) >> 1].neg());
|
|
}
|
|
}
|
|
return p.type === 'affine' ? acc.toP() : acc;
|
|
};
|
|
|
|
BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW,
|
|
points,
|
|
coeffs,
|
|
len,
|
|
jacobianResult) {
|
|
var wndWidth = this._wnafT1;
|
|
var wnd = this._wnafT2;
|
|
var naf = this._wnafT3;
|
|
|
|
// Fill all arrays
|
|
var max = 0;
|
|
for (var i = 0; i < len; i++) {
|
|
var p = points[i];
|
|
var nafPoints = p._getNAFPoints(defW);
|
|
wndWidth[i] = nafPoints.wnd;
|
|
wnd[i] = nafPoints.points;
|
|
}
|
|
|
|
// Comb small window NAFs
|
|
for (var i = len - 1; i >= 1; i -= 2) {
|
|
var a = i - 1;
|
|
var b = i;
|
|
if (wndWidth[a] !== 1 || wndWidth[b] !== 1) {
|
|
naf[a] = getNAF(coeffs[a], wndWidth[a]);
|
|
naf[b] = getNAF(coeffs[b], wndWidth[b]);
|
|
max = Math.max(naf[a].length, max);
|
|
max = Math.max(naf[b].length, max);
|
|
continue;
|
|
}
|
|
|
|
var comb = [
|
|
points[a], /* 1 */
|
|
null, /* 3 */
|
|
null, /* 5 */
|
|
points[b] /* 7 */
|
|
];
|
|
|
|
// Try to avoid Projective points, if possible
|
|
if (points[a].y.cmp(points[b].y) === 0) {
|
|
comb[1] = points[a].add(points[b]);
|
|
comb[2] = points[a].toJ().mixedAdd(points[b].neg());
|
|
} else if (points[a].y.cmp(points[b].y.redNeg()) === 0) {
|
|
comb[1] = points[a].toJ().mixedAdd(points[b]);
|
|
comb[2] = points[a].add(points[b].neg());
|
|
} else {
|
|
comb[1] = points[a].toJ().mixedAdd(points[b]);
|
|
comb[2] = points[a].toJ().mixedAdd(points[b].neg());
|
|
}
|
|
|
|
var index = [
|
|
-3, /* -1 -1 */
|
|
-1, /* -1 0 */
|
|
-5, /* -1 1 */
|
|
-7, /* 0 -1 */
|
|
0, /* 0 0 */
|
|
7, /* 0 1 */
|
|
5, /* 1 -1 */
|
|
1, /* 1 0 */
|
|
3 /* 1 1 */
|
|
];
|
|
|
|
var jsf = getJSF(coeffs[a], coeffs[b]);
|
|
max = Math.max(jsf[0].length, max);
|
|
naf[a] = new Array(max);
|
|
naf[b] = new Array(max);
|
|
for (var j = 0; j < max; j++) {
|
|
var ja = jsf[0][j] | 0;
|
|
var jb = jsf[1][j] | 0;
|
|
|
|
naf[a][j] = index[(ja + 1) * 3 + (jb + 1)];
|
|
naf[b][j] = 0;
|
|
wnd[a] = comb;
|
|
}
|
|
}
|
|
|
|
var acc = this.jpoint(null, null, null);
|
|
var tmp = this._wnafT4;
|
|
for (var i = max; i >= 0; i--) {
|
|
var k = 0;
|
|
|
|
while (i >= 0) {
|
|
var zero = true;
|
|
for (var j = 0; j < len; j++) {
|
|
tmp[j] = naf[j][i] | 0;
|
|
if (tmp[j] !== 0)
|
|
zero = false;
|
|
}
|
|
if (!zero)
|
|
break;
|
|
k++;
|
|
i--;
|
|
}
|
|
if (i >= 0)
|
|
k++;
|
|
acc = acc.dblp(k);
|
|
if (i < 0)
|
|
break;
|
|
|
|
for (var j = 0; j < len; j++) {
|
|
var z = tmp[j];
|
|
var p;
|
|
if (z === 0)
|
|
continue;
|
|
else if (z > 0)
|
|
p = wnd[j][(z - 1) >> 1];
|
|
else if (z < 0)
|
|
p = wnd[j][(-z - 1) >> 1].neg();
|
|
|
|
if (p.type === 'affine')
|
|
acc = acc.mixedAdd(p);
|
|
else
|
|
acc = acc.add(p);
|
|
}
|
|
}
|
|
// Zeroify references
|
|
for (var i = 0; i < len; i++)
|
|
wnd[i] = null;
|
|
|
|
if (jacobianResult)
|
|
return acc;
|
|
else
|
|
return acc.toP();
|
|
};
|
|
|
|
function BasePoint(curve, type) {
|
|
this.curve = curve;
|
|
this.type = type;
|
|
this.precomputed = null;
|
|
}
|
|
BaseCurve.BasePoint = BasePoint;
|
|
|
|
BasePoint.prototype.eq = function eq(/*other*/) {
|
|
throw new Error('Not implemented');
|
|
};
|
|
|
|
BasePoint.prototype.validate = function validate() {
|
|
return this.curve.validate(this);
|
|
};
|
|
|
|
BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) {
|
|
bytes = utils.toArray(bytes, enc);
|
|
|
|
var len = this.p.byteLength();
|
|
|
|
// uncompressed, hybrid-odd, hybrid-even
|
|
if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) &&
|
|
bytes.length - 1 === 2 * len) {
|
|
if (bytes[0] === 0x06)
|
|
assert(bytes[bytes.length - 1] % 2 === 0);
|
|
else if (bytes[0] === 0x07)
|
|
assert(bytes[bytes.length - 1] % 2 === 1);
|
|
|
|
var res = this.point(bytes.slice(1, 1 + len),
|
|
bytes.slice(1 + len, 1 + 2 * len));
|
|
|
|
return res;
|
|
} else if ((bytes[0] === 0x02 || bytes[0] === 0x03) &&
|
|
bytes.length - 1 === len) {
|
|
return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03);
|
|
}
|
|
throw new Error('Unknown point format');
|
|
};
|
|
|
|
BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) {
|
|
return this.encode(enc, true);
|
|
};
|
|
|
|
BasePoint.prototype._encode = function _encode(compact) {
|
|
var len = this.curve.p.byteLength();
|
|
var x = this.getX().toArray('be', len);
|
|
|
|
if (compact)
|
|
return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x);
|
|
|
|
return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ;
|
|
};
|
|
|
|
BasePoint.prototype.encode = function encode(enc, compact) {
|
|
return utils.encode(this._encode(compact), enc);
|
|
};
|
|
|
|
BasePoint.prototype.precompute = function precompute(power) {
|
|
if (this.precomputed)
|
|
return this;
|
|
|
|
var precomputed = {
|
|
doubles: null,
|
|
naf: null,
|
|
beta: null
|
|
};
|
|
precomputed.naf = this._getNAFPoints(8);
|
|
precomputed.doubles = this._getDoubles(4, power);
|
|
precomputed.beta = this._getBeta();
|
|
this.precomputed = precomputed;
|
|
|
|
return this;
|
|
};
|
|
|
|
BasePoint.prototype._hasDoubles = function _hasDoubles(k) {
|
|
if (!this.precomputed)
|
|
return false;
|
|
|
|
var doubles = this.precomputed.doubles;
|
|
if (!doubles)
|
|
return false;
|
|
|
|
return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step);
|
|
};
|
|
|
|
BasePoint.prototype._getDoubles = function _getDoubles(step, power) {
|
|
if (this.precomputed && this.precomputed.doubles)
|
|
return this.precomputed.doubles;
|
|
|
|
var doubles = [ this ];
|
|
var acc = this;
|
|
for (var i = 0; i < power; i += step) {
|
|
for (var j = 0; j < step; j++)
|
|
acc = acc.dbl();
|
|
doubles.push(acc);
|
|
}
|
|
return {
|
|
step: step,
|
|
points: doubles
|
|
};
|
|
};
|
|
|
|
BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) {
|
|
if (this.precomputed && this.precomputed.naf)
|
|
return this.precomputed.naf;
|
|
|
|
var res = [ this ];
|
|
var max = (1 << wnd) - 1;
|
|
var dbl = max === 1 ? null : this.dbl();
|
|
for (var i = 1; i < max; i++)
|
|
res[i] = res[i - 1].add(dbl);
|
|
return {
|
|
wnd: wnd,
|
|
points: res
|
|
};
|
|
};
|
|
|
|
BasePoint.prototype._getBeta = function _getBeta() {
|
|
return null;
|
|
};
|
|
|
|
BasePoint.prototype.dblp = function dblp(k) {
|
|
var r = this;
|
|
for (var i = 0; i < k; i++)
|
|
r = r.dbl();
|
|
return r;
|
|
};
|
|
|
|
},{"../../elliptic":285,"bn.js":280}],287:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var curve = require('../curve');
|
|
var elliptic = require('../../elliptic');
|
|
var BN = require('bn.js');
|
|
var inherits = require('inherits');
|
|
var Base = curve.base;
|
|
|
|
var assert = elliptic.utils.assert;
|
|
|
|
function EdwardsCurve(conf) {
|
|
// NOTE: Important as we are creating point in Base.call()
|
|
this.twisted = (conf.a | 0) !== 1;
|
|
this.mOneA = this.twisted && (conf.a | 0) === -1;
|
|
this.extended = this.mOneA;
|
|
|
|
Base.call(this, 'edwards', conf);
|
|
|
|
this.a = new BN(conf.a, 16).umod(this.red.m);
|
|
this.a = this.a.toRed(this.red);
|
|
this.c = new BN(conf.c, 16).toRed(this.red);
|
|
this.c2 = this.c.redSqr();
|
|
this.d = new BN(conf.d, 16).toRed(this.red);
|
|
this.dd = this.d.redAdd(this.d);
|
|
|
|
assert(!this.twisted || this.c.fromRed().cmpn(1) === 0);
|
|
this.oneC = (conf.c | 0) === 1;
|
|
}
|
|
inherits(EdwardsCurve, Base);
|
|
module.exports = EdwardsCurve;
|
|
|
|
EdwardsCurve.prototype._mulA = function _mulA(num) {
|
|
if (this.mOneA)
|
|
return num.redNeg();
|
|
else
|
|
return this.a.redMul(num);
|
|
};
|
|
|
|
EdwardsCurve.prototype._mulC = function _mulC(num) {
|
|
if (this.oneC)
|
|
return num;
|
|
else
|
|
return this.c.redMul(num);
|
|
};
|
|
|
|
// Just for compatibility with Short curve
|
|
EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) {
|
|
return this.point(x, y, z, t);
|
|
};
|
|
|
|
EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) {
|
|
x = new BN(x, 16);
|
|
if (!x.red)
|
|
x = x.toRed(this.red);
|
|
|
|
var x2 = x.redSqr();
|
|
var rhs = this.c2.redSub(this.a.redMul(x2));
|
|
var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2));
|
|
|
|
var y2 = rhs.redMul(lhs.redInvm());
|
|
var y = y2.redSqrt();
|
|
if (y.redSqr().redSub(y2).cmp(this.zero) !== 0)
|
|
throw new Error('invalid point');
|
|
|
|
var isOdd = y.fromRed().isOdd();
|
|
if (odd && !isOdd || !odd && isOdd)
|
|
y = y.redNeg();
|
|
|
|
return this.point(x, y);
|
|
};
|
|
|
|
EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) {
|
|
y = new BN(y, 16);
|
|
if (!y.red)
|
|
y = y.toRed(this.red);
|
|
|
|
// x^2 = (y^2 - 1) / (d y^2 + 1)
|
|
var y2 = y.redSqr();
|
|
var lhs = y2.redSub(this.one);
|
|
var rhs = y2.redMul(this.d).redAdd(this.one);
|
|
var x2 = lhs.redMul(rhs.redInvm());
|
|
|
|
if (x2.cmp(this.zero) === 0) {
|
|
if (odd)
|
|
throw new Error('invalid point');
|
|
else
|
|
return this.point(this.zero, y);
|
|
}
|
|
|
|
var x = x2.redSqrt();
|
|
if (x.redSqr().redSub(x2).cmp(this.zero) !== 0)
|
|
throw new Error('invalid point');
|
|
|
|
if (x.isOdd() !== odd)
|
|
x = x.redNeg();
|
|
|
|
return this.point(x, y);
|
|
};
|
|
|
|
EdwardsCurve.prototype.validate = function validate(point) {
|
|
if (point.isInfinity())
|
|
return true;
|
|
|
|
// Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2)
|
|
point.normalize();
|
|
|
|
var x2 = point.x.redSqr();
|
|
var y2 = point.y.redSqr();
|
|
var lhs = x2.redMul(this.a).redAdd(y2);
|
|
var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2)));
|
|
|
|
return lhs.cmp(rhs) === 0;
|
|
};
|
|
|
|
function Point(curve, x, y, z, t) {
|
|
Base.BasePoint.call(this, curve, 'projective');
|
|
if (x === null && y === null && z === null) {
|
|
this.x = this.curve.zero;
|
|
this.y = this.curve.one;
|
|
this.z = this.curve.one;
|
|
this.t = this.curve.zero;
|
|
this.zOne = true;
|
|
} else {
|
|
this.x = new BN(x, 16);
|
|
this.y = new BN(y, 16);
|
|
this.z = z ? new BN(z, 16) : this.curve.one;
|
|
this.t = t && new BN(t, 16);
|
|
if (!this.x.red)
|
|
this.x = this.x.toRed(this.curve.red);
|
|
if (!this.y.red)
|
|
this.y = this.y.toRed(this.curve.red);
|
|
if (!this.z.red)
|
|
this.z = this.z.toRed(this.curve.red);
|
|
if (this.t && !this.t.red)
|
|
this.t = this.t.toRed(this.curve.red);
|
|
this.zOne = this.z === this.curve.one;
|
|
|
|
// Use extended coordinates
|
|
if (this.curve.extended && !this.t) {
|
|
this.t = this.x.redMul(this.y);
|
|
if (!this.zOne)
|
|
this.t = this.t.redMul(this.z.redInvm());
|
|
}
|
|
}
|
|
}
|
|
inherits(Point, Base.BasePoint);
|
|
|
|
EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) {
|
|
return Point.fromJSON(this, obj);
|
|
};
|
|
|
|
EdwardsCurve.prototype.point = function point(x, y, z, t) {
|
|
return new Point(this, x, y, z, t);
|
|
};
|
|
|
|
Point.fromJSON = function fromJSON(curve, obj) {
|
|
return new Point(curve, obj[0], obj[1], obj[2]);
|
|
};
|
|
|
|
Point.prototype.inspect = function inspect() {
|
|
if (this.isInfinity())
|
|
return '<EC Point Infinity>';
|
|
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
|
|
' y: ' + this.y.fromRed().toString(16, 2) +
|
|
' z: ' + this.z.fromRed().toString(16, 2) + '>';
|
|
};
|
|
|
|
Point.prototype.isInfinity = function isInfinity() {
|
|
// XXX This code assumes that zero is always zero in red
|
|
return this.x.cmpn(0) === 0 &&
|
|
this.y.cmp(this.z) === 0;
|
|
};
|
|
|
|
Point.prototype._extDbl = function _extDbl() {
|
|
// hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
|
|
// #doubling-dbl-2008-hwcd
|
|
// 4M + 4S
|
|
|
|
// A = X1^2
|
|
var a = this.x.redSqr();
|
|
// B = Y1^2
|
|
var b = this.y.redSqr();
|
|
// C = 2 * Z1^2
|
|
var c = this.z.redSqr();
|
|
c = c.redIAdd(c);
|
|
// D = a * A
|
|
var d = this.curve._mulA(a);
|
|
// E = (X1 + Y1)^2 - A - B
|
|
var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b);
|
|
// G = D + B
|
|
var g = d.redAdd(b);
|
|
// F = G - C
|
|
var f = g.redSub(c);
|
|
// H = D - B
|
|
var h = d.redSub(b);
|
|
// X3 = E * F
|
|
var nx = e.redMul(f);
|
|
// Y3 = G * H
|
|
var ny = g.redMul(h);
|
|
// T3 = E * H
|
|
var nt = e.redMul(h);
|
|
// Z3 = F * G
|
|
var nz = f.redMul(g);
|
|
return this.curve.point(nx, ny, nz, nt);
|
|
};
|
|
|
|
Point.prototype._projDbl = function _projDbl() {
|
|
// hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
|
|
// #doubling-dbl-2008-bbjlp
|
|
// #doubling-dbl-2007-bl
|
|
// and others
|
|
// Generally 3M + 4S or 2M + 4S
|
|
|
|
// B = (X1 + Y1)^2
|
|
var b = this.x.redAdd(this.y).redSqr();
|
|
// C = X1^2
|
|
var c = this.x.redSqr();
|
|
// D = Y1^2
|
|
var d = this.y.redSqr();
|
|
|
|
var nx;
|
|
var ny;
|
|
var nz;
|
|
if (this.curve.twisted) {
|
|
// E = a * C
|
|
var e = this.curve._mulA(c);
|
|
// F = E + D
|
|
var f = e.redAdd(d);
|
|
if (this.zOne) {
|
|
// X3 = (B - C - D) * (F - 2)
|
|
nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two));
|
|
// Y3 = F * (E - D)
|
|
ny = f.redMul(e.redSub(d));
|
|
// Z3 = F^2 - 2 * F
|
|
nz = f.redSqr().redSub(f).redSub(f);
|
|
} else {
|
|
// H = Z1^2
|
|
var h = this.z.redSqr();
|
|
// J = F - 2 * H
|
|
var j = f.redSub(h).redISub(h);
|
|
// X3 = (B-C-D)*J
|
|
nx = b.redSub(c).redISub(d).redMul(j);
|
|
// Y3 = F * (E - D)
|
|
ny = f.redMul(e.redSub(d));
|
|
// Z3 = F * J
|
|
nz = f.redMul(j);
|
|
}
|
|
} else {
|
|
// E = C + D
|
|
var e = c.redAdd(d);
|
|
// H = (c * Z1)^2
|
|
var h = this.curve._mulC(this.c.redMul(this.z)).redSqr();
|
|
// J = E - 2 * H
|
|
var j = e.redSub(h).redSub(h);
|
|
// X3 = c * (B - E) * J
|
|
nx = this.curve._mulC(b.redISub(e)).redMul(j);
|
|
// Y3 = c * E * (C - D)
|
|
ny = this.curve._mulC(e).redMul(c.redISub(d));
|
|
// Z3 = E * J
|
|
nz = e.redMul(j);
|
|
}
|
|
return this.curve.point(nx, ny, nz);
|
|
};
|
|
|
|
Point.prototype.dbl = function dbl() {
|
|
if (this.isInfinity())
|
|
return this;
|
|
|
|
// Double in extended coordinates
|
|
if (this.curve.extended)
|
|
return this._extDbl();
|
|
else
|
|
return this._projDbl();
|
|
};
|
|
|
|
Point.prototype._extAdd = function _extAdd(p) {
|
|
// hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
|
|
// #addition-add-2008-hwcd-3
|
|
// 8M
|
|
|
|
// A = (Y1 - X1) * (Y2 - X2)
|
|
var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x));
|
|
// B = (Y1 + X1) * (Y2 + X2)
|
|
var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x));
|
|
// C = T1 * k * T2
|
|
var c = this.t.redMul(this.curve.dd).redMul(p.t);
|
|
// D = Z1 * 2 * Z2
|
|
var d = this.z.redMul(p.z.redAdd(p.z));
|
|
// E = B - A
|
|
var e = b.redSub(a);
|
|
// F = D - C
|
|
var f = d.redSub(c);
|
|
// G = D + C
|
|
var g = d.redAdd(c);
|
|
// H = B + A
|
|
var h = b.redAdd(a);
|
|
// X3 = E * F
|
|
var nx = e.redMul(f);
|
|
// Y3 = G * H
|
|
var ny = g.redMul(h);
|
|
// T3 = E * H
|
|
var nt = e.redMul(h);
|
|
// Z3 = F * G
|
|
var nz = f.redMul(g);
|
|
return this.curve.point(nx, ny, nz, nt);
|
|
};
|
|
|
|
Point.prototype._projAdd = function _projAdd(p) {
|
|
// hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
|
|
// #addition-add-2008-bbjlp
|
|
// #addition-add-2007-bl
|
|
// 10M + 1S
|
|
|
|
// A = Z1 * Z2
|
|
var a = this.z.redMul(p.z);
|
|
// B = A^2
|
|
var b = a.redSqr();
|
|
// C = X1 * X2
|
|
var c = this.x.redMul(p.x);
|
|
// D = Y1 * Y2
|
|
var d = this.y.redMul(p.y);
|
|
// E = d * C * D
|
|
var e = this.curve.d.redMul(c).redMul(d);
|
|
// F = B - E
|
|
var f = b.redSub(e);
|
|
// G = B + E
|
|
var g = b.redAdd(e);
|
|
// X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D)
|
|
var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d);
|
|
var nx = a.redMul(f).redMul(tmp);
|
|
var ny;
|
|
var nz;
|
|
if (this.curve.twisted) {
|
|
// Y3 = A * G * (D - a * C)
|
|
ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c)));
|
|
// Z3 = F * G
|
|
nz = f.redMul(g);
|
|
} else {
|
|
// Y3 = A * G * (D - C)
|
|
ny = a.redMul(g).redMul(d.redSub(c));
|
|
// Z3 = c * F * G
|
|
nz = this.curve._mulC(f).redMul(g);
|
|
}
|
|
return this.curve.point(nx, ny, nz);
|
|
};
|
|
|
|
Point.prototype.add = function add(p) {
|
|
if (this.isInfinity())
|
|
return p;
|
|
if (p.isInfinity())
|
|
return this;
|
|
|
|
if (this.curve.extended)
|
|
return this._extAdd(p);
|
|
else
|
|
return this._projAdd(p);
|
|
};
|
|
|
|
Point.prototype.mul = function mul(k) {
|
|
if (this._hasDoubles(k))
|
|
return this.curve._fixedNafMul(this, k);
|
|
else
|
|
return this.curve._wnafMul(this, k);
|
|
};
|
|
|
|
Point.prototype.mulAdd = function mulAdd(k1, p, k2) {
|
|
return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false);
|
|
};
|
|
|
|
Point.prototype.jmulAdd = function jmulAdd(k1, p, k2) {
|
|
return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true);
|
|
};
|
|
|
|
Point.prototype.normalize = function normalize() {
|
|
if (this.zOne)
|
|
return this;
|
|
|
|
// Normalize coordinates
|
|
var zi = this.z.redInvm();
|
|
this.x = this.x.redMul(zi);
|
|
this.y = this.y.redMul(zi);
|
|
if (this.t)
|
|
this.t = this.t.redMul(zi);
|
|
this.z = this.curve.one;
|
|
this.zOne = true;
|
|
return this;
|
|
};
|
|
|
|
Point.prototype.neg = function neg() {
|
|
return this.curve.point(this.x.redNeg(),
|
|
this.y,
|
|
this.z,
|
|
this.t && this.t.redNeg());
|
|
};
|
|
|
|
Point.prototype.getX = function getX() {
|
|
this.normalize();
|
|
return this.x.fromRed();
|
|
};
|
|
|
|
Point.prototype.getY = function getY() {
|
|
this.normalize();
|
|
return this.y.fromRed();
|
|
};
|
|
|
|
Point.prototype.eq = function eq(other) {
|
|
return this === other ||
|
|
this.getX().cmp(other.getX()) === 0 &&
|
|
this.getY().cmp(other.getY()) === 0;
|
|
};
|
|
|
|
Point.prototype.eqXToP = function eqXToP(x) {
|
|
var rx = x.toRed(this.curve.red).redMul(this.z);
|
|
if (this.x.cmp(rx) === 0)
|
|
return true;
|
|
|
|
var xc = x.clone();
|
|
var t = this.curve.redN.redMul(this.z);
|
|
for (;;) {
|
|
xc.iadd(this.curve.n);
|
|
if (xc.cmp(this.curve.p) >= 0)
|
|
return false;
|
|
|
|
rx.redIAdd(t);
|
|
if (this.x.cmp(rx) === 0)
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
// Compatibility with BaseCurve
|
|
Point.prototype.toP = Point.prototype.normalize;
|
|
Point.prototype.mixedAdd = Point.prototype.add;
|
|
|
|
},{"../../elliptic":285,"../curve":288,"bn.js":280,"inherits":318}],288:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var curve = exports;
|
|
|
|
curve.base = require('./base');
|
|
curve.short = require('./short');
|
|
curve.mont = require('./mont');
|
|
curve.edwards = require('./edwards');
|
|
|
|
},{"./base":286,"./edwards":287,"./mont":289,"./short":290}],289:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var curve = require('../curve');
|
|
var BN = require('bn.js');
|
|
var inherits = require('inherits');
|
|
var Base = curve.base;
|
|
|
|
var elliptic = require('../../elliptic');
|
|
var utils = elliptic.utils;
|
|
|
|
function MontCurve(conf) {
|
|
Base.call(this, 'mont', conf);
|
|
|
|
this.a = new BN(conf.a, 16).toRed(this.red);
|
|
this.b = new BN(conf.b, 16).toRed(this.red);
|
|
this.i4 = new BN(4).toRed(this.red).redInvm();
|
|
this.two = new BN(2).toRed(this.red);
|
|
this.a24 = this.i4.redMul(this.a.redAdd(this.two));
|
|
}
|
|
inherits(MontCurve, Base);
|
|
module.exports = MontCurve;
|
|
|
|
MontCurve.prototype.validate = function validate(point) {
|
|
var x = point.normalize().x;
|
|
var x2 = x.redSqr();
|
|
var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x);
|
|
var y = rhs.redSqrt();
|
|
|
|
return y.redSqr().cmp(rhs) === 0;
|
|
};
|
|
|
|
function Point(curve, x, z) {
|
|
Base.BasePoint.call(this, curve, 'projective');
|
|
if (x === null && z === null) {
|
|
this.x = this.curve.one;
|
|
this.z = this.curve.zero;
|
|
} else {
|
|
this.x = new BN(x, 16);
|
|
this.z = new BN(z, 16);
|
|
if (!this.x.red)
|
|
this.x = this.x.toRed(this.curve.red);
|
|
if (!this.z.red)
|
|
this.z = this.z.toRed(this.curve.red);
|
|
}
|
|
}
|
|
inherits(Point, Base.BasePoint);
|
|
|
|
MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) {
|
|
return this.point(utils.toArray(bytes, enc), 1);
|
|
};
|
|
|
|
MontCurve.prototype.point = function point(x, z) {
|
|
return new Point(this, x, z);
|
|
};
|
|
|
|
MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) {
|
|
return Point.fromJSON(this, obj);
|
|
};
|
|
|
|
Point.prototype.precompute = function precompute() {
|
|
// No-op
|
|
};
|
|
|
|
Point.prototype._encode = function _encode() {
|
|
return this.getX().toArray('be', this.curve.p.byteLength());
|
|
};
|
|
|
|
Point.fromJSON = function fromJSON(curve, obj) {
|
|
return new Point(curve, obj[0], obj[1] || curve.one);
|
|
};
|
|
|
|
Point.prototype.inspect = function inspect() {
|
|
if (this.isInfinity())
|
|
return '<EC Point Infinity>';
|
|
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
|
|
' z: ' + this.z.fromRed().toString(16, 2) + '>';
|
|
};
|
|
|
|
Point.prototype.isInfinity = function isInfinity() {
|
|
// XXX This code assumes that zero is always zero in red
|
|
return this.z.cmpn(0) === 0;
|
|
};
|
|
|
|
Point.prototype.dbl = function dbl() {
|
|
// http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3
|
|
// 2M + 2S + 4A
|
|
|
|
// A = X1 + Z1
|
|
var a = this.x.redAdd(this.z);
|
|
// AA = A^2
|
|
var aa = a.redSqr();
|
|
// B = X1 - Z1
|
|
var b = this.x.redSub(this.z);
|
|
// BB = B^2
|
|
var bb = b.redSqr();
|
|
// C = AA - BB
|
|
var c = aa.redSub(bb);
|
|
// X3 = AA * BB
|
|
var nx = aa.redMul(bb);
|
|
// Z3 = C * (BB + A24 * C)
|
|
var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c)));
|
|
return this.curve.point(nx, nz);
|
|
};
|
|
|
|
Point.prototype.add = function add() {
|
|
throw new Error('Not supported on Montgomery curve');
|
|
};
|
|
|
|
Point.prototype.diffAdd = function diffAdd(p, diff) {
|
|
// http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3
|
|
// 4M + 2S + 6A
|
|
|
|
// A = X2 + Z2
|
|
var a = this.x.redAdd(this.z);
|
|
// B = X2 - Z2
|
|
var b = this.x.redSub(this.z);
|
|
// C = X3 + Z3
|
|
var c = p.x.redAdd(p.z);
|
|
// D = X3 - Z3
|
|
var d = p.x.redSub(p.z);
|
|
// DA = D * A
|
|
var da = d.redMul(a);
|
|
// CB = C * B
|
|
var cb = c.redMul(b);
|
|
// X5 = Z1 * (DA + CB)^2
|
|
var nx = diff.z.redMul(da.redAdd(cb).redSqr());
|
|
// Z5 = X1 * (DA - CB)^2
|
|
var nz = diff.x.redMul(da.redISub(cb).redSqr());
|
|
return this.curve.point(nx, nz);
|
|
};
|
|
|
|
Point.prototype.mul = function mul(k) {
|
|
var t = k.clone();
|
|
var a = this; // (N / 2) * Q + Q
|
|
var b = this.curve.point(null, null); // (N / 2) * Q
|
|
var c = this; // Q
|
|
|
|
for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1))
|
|
bits.push(t.andln(1));
|
|
|
|
for (var i = bits.length - 1; i >= 0; i--) {
|
|
if (bits[i] === 0) {
|
|
// N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q
|
|
a = a.diffAdd(b, c);
|
|
// N * Q = 2 * ((N / 2) * Q + Q))
|
|
b = b.dbl();
|
|
} else {
|
|
// N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q)
|
|
b = a.diffAdd(b, c);
|
|
// N * Q + Q = 2 * ((N / 2) * Q + Q)
|
|
a = a.dbl();
|
|
}
|
|
}
|
|
return b;
|
|
};
|
|
|
|
Point.prototype.mulAdd = function mulAdd() {
|
|
throw new Error('Not supported on Montgomery curve');
|
|
};
|
|
|
|
Point.prototype.jumlAdd = function jumlAdd() {
|
|
throw new Error('Not supported on Montgomery curve');
|
|
};
|
|
|
|
Point.prototype.eq = function eq(other) {
|
|
return this.getX().cmp(other.getX()) === 0;
|
|
};
|
|
|
|
Point.prototype.normalize = function normalize() {
|
|
this.x = this.x.redMul(this.z.redInvm());
|
|
this.z = this.curve.one;
|
|
return this;
|
|
};
|
|
|
|
Point.prototype.getX = function getX() {
|
|
// Normalize coordinates
|
|
this.normalize();
|
|
|
|
return this.x.fromRed();
|
|
};
|
|
|
|
},{"../../elliptic":285,"../curve":288,"bn.js":280,"inherits":318}],290:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var curve = require('../curve');
|
|
var elliptic = require('../../elliptic');
|
|
var BN = require('bn.js');
|
|
var inherits = require('inherits');
|
|
var Base = curve.base;
|
|
|
|
var assert = elliptic.utils.assert;
|
|
|
|
function ShortCurve(conf) {
|
|
Base.call(this, 'short', conf);
|
|
|
|
this.a = new BN(conf.a, 16).toRed(this.red);
|
|
this.b = new BN(conf.b, 16).toRed(this.red);
|
|
this.tinv = this.two.redInvm();
|
|
|
|
this.zeroA = this.a.fromRed().cmpn(0) === 0;
|
|
this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0;
|
|
|
|
// If the curve is endomorphic, precalculate beta and lambda
|
|
this.endo = this._getEndomorphism(conf);
|
|
this._endoWnafT1 = new Array(4);
|
|
this._endoWnafT2 = new Array(4);
|
|
}
|
|
inherits(ShortCurve, Base);
|
|
module.exports = ShortCurve;
|
|
|
|
ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) {
|
|
// No efficient endomorphism
|
|
if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1)
|
|
return;
|
|
|
|
// Compute beta and lambda, that lambda * P = (beta * Px; Py)
|
|
var beta;
|
|
var lambda;
|
|
if (conf.beta) {
|
|
beta = new BN(conf.beta, 16).toRed(this.red);
|
|
} else {
|
|
var betas = this._getEndoRoots(this.p);
|
|
// Choose the smallest beta
|
|
beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1];
|
|
beta = beta.toRed(this.red);
|
|
}
|
|
if (conf.lambda) {
|
|
lambda = new BN(conf.lambda, 16);
|
|
} else {
|
|
// Choose the lambda that is matching selected beta
|
|
var lambdas = this._getEndoRoots(this.n);
|
|
if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) {
|
|
lambda = lambdas[0];
|
|
} else {
|
|
lambda = lambdas[1];
|
|
assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0);
|
|
}
|
|
}
|
|
|
|
// Get basis vectors, used for balanced length-two representation
|
|
var basis;
|
|
if (conf.basis) {
|
|
basis = conf.basis.map(function(vec) {
|
|
return {
|
|
a: new BN(vec.a, 16),
|
|
b: new BN(vec.b, 16)
|
|
};
|
|
});
|
|
} else {
|
|
basis = this._getEndoBasis(lambda);
|
|
}
|
|
|
|
return {
|
|
beta: beta,
|
|
lambda: lambda,
|
|
basis: basis
|
|
};
|
|
};
|
|
|
|
ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) {
|
|
// Find roots of for x^2 + x + 1 in F
|
|
// Root = (-1 +- Sqrt(-3)) / 2
|
|
//
|
|
var red = num === this.p ? this.red : BN.mont(num);
|
|
var tinv = new BN(2).toRed(red).redInvm();
|
|
var ntinv = tinv.redNeg();
|
|
|
|
var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv);
|
|
|
|
var l1 = ntinv.redAdd(s).fromRed();
|
|
var l2 = ntinv.redSub(s).fromRed();
|
|
return [ l1, l2 ];
|
|
};
|
|
|
|
ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) {
|
|
// aprxSqrt >= sqrt(this.n)
|
|
var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2));
|
|
|
|
// 3.74
|
|
// Run EGCD, until r(L + 1) < aprxSqrt
|
|
var u = lambda;
|
|
var v = this.n.clone();
|
|
var x1 = new BN(1);
|
|
var y1 = new BN(0);
|
|
var x2 = new BN(0);
|
|
var y2 = new BN(1);
|
|
|
|
// NOTE: all vectors are roots of: a + b * lambda = 0 (mod n)
|
|
var a0;
|
|
var b0;
|
|
// First vector
|
|
var a1;
|
|
var b1;
|
|
// Second vector
|
|
var a2;
|
|
var b2;
|
|
|
|
var prevR;
|
|
var i = 0;
|
|
var r;
|
|
var x;
|
|
while (u.cmpn(0) !== 0) {
|
|
var q = v.div(u);
|
|
r = v.sub(q.mul(u));
|
|
x = x2.sub(q.mul(x1));
|
|
var y = y2.sub(q.mul(y1));
|
|
|
|
if (!a1 && r.cmp(aprxSqrt) < 0) {
|
|
a0 = prevR.neg();
|
|
b0 = x1;
|
|
a1 = r.neg();
|
|
b1 = x;
|
|
} else if (a1 && ++i === 2) {
|
|
break;
|
|
}
|
|
prevR = r;
|
|
|
|
v = u;
|
|
u = r;
|
|
x2 = x1;
|
|
x1 = x;
|
|
y2 = y1;
|
|
y1 = y;
|
|
}
|
|
a2 = r.neg();
|
|
b2 = x;
|
|
|
|
var len1 = a1.sqr().add(b1.sqr());
|
|
var len2 = a2.sqr().add(b2.sqr());
|
|
if (len2.cmp(len1) >= 0) {
|
|
a2 = a0;
|
|
b2 = b0;
|
|
}
|
|
|
|
// Normalize signs
|
|
if (a1.negative) {
|
|
a1 = a1.neg();
|
|
b1 = b1.neg();
|
|
}
|
|
if (a2.negative) {
|
|
a2 = a2.neg();
|
|
b2 = b2.neg();
|
|
}
|
|
|
|
return [
|
|
{ a: a1, b: b1 },
|
|
{ a: a2, b: b2 }
|
|
];
|
|
};
|
|
|
|
ShortCurve.prototype._endoSplit = function _endoSplit(k) {
|
|
var basis = this.endo.basis;
|
|
var v1 = basis[0];
|
|
var v2 = basis[1];
|
|
|
|
var c1 = v2.b.mul(k).divRound(this.n);
|
|
var c2 = v1.b.neg().mul(k).divRound(this.n);
|
|
|
|
var p1 = c1.mul(v1.a);
|
|
var p2 = c2.mul(v2.a);
|
|
var q1 = c1.mul(v1.b);
|
|
var q2 = c2.mul(v2.b);
|
|
|
|
// Calculate answer
|
|
var k1 = k.sub(p1).sub(p2);
|
|
var k2 = q1.add(q2).neg();
|
|
return { k1: k1, k2: k2 };
|
|
};
|
|
|
|
ShortCurve.prototype.pointFromX = function pointFromX(x, odd) {
|
|
x = new BN(x, 16);
|
|
if (!x.red)
|
|
x = x.toRed(this.red);
|
|
|
|
var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b);
|
|
var y = y2.redSqrt();
|
|
if (y.redSqr().redSub(y2).cmp(this.zero) !== 0)
|
|
throw new Error('invalid point');
|
|
|
|
// XXX Is there any way to tell if the number is odd without converting it
|
|
// to non-red form?
|
|
var isOdd = y.fromRed().isOdd();
|
|
if (odd && !isOdd || !odd && isOdd)
|
|
y = y.redNeg();
|
|
|
|
return this.point(x, y);
|
|
};
|
|
|
|
ShortCurve.prototype.validate = function validate(point) {
|
|
if (point.inf)
|
|
return true;
|
|
|
|
var x = point.x;
|
|
var y = point.y;
|
|
|
|
var ax = this.a.redMul(x);
|
|
var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b);
|
|
return y.redSqr().redISub(rhs).cmpn(0) === 0;
|
|
};
|
|
|
|
ShortCurve.prototype._endoWnafMulAdd =
|
|
function _endoWnafMulAdd(points, coeffs, jacobianResult) {
|
|
var npoints = this._endoWnafT1;
|
|
var ncoeffs = this._endoWnafT2;
|
|
for (var i = 0; i < points.length; i++) {
|
|
var split = this._endoSplit(coeffs[i]);
|
|
var p = points[i];
|
|
var beta = p._getBeta();
|
|
|
|
if (split.k1.negative) {
|
|
split.k1.ineg();
|
|
p = p.neg(true);
|
|
}
|
|
if (split.k2.negative) {
|
|
split.k2.ineg();
|
|
beta = beta.neg(true);
|
|
}
|
|
|
|
npoints[i * 2] = p;
|
|
npoints[i * 2 + 1] = beta;
|
|
ncoeffs[i * 2] = split.k1;
|
|
ncoeffs[i * 2 + 1] = split.k2;
|
|
}
|
|
var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult);
|
|
|
|
// Clean-up references to points and coefficients
|
|
for (var j = 0; j < i * 2; j++) {
|
|
npoints[j] = null;
|
|
ncoeffs[j] = null;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
function Point(curve, x, y, isRed) {
|
|
Base.BasePoint.call(this, curve, 'affine');
|
|
if (x === null && y === null) {
|
|
this.x = null;
|
|
this.y = null;
|
|
this.inf = true;
|
|
} else {
|
|
this.x = new BN(x, 16);
|
|
this.y = new BN(y, 16);
|
|
// Force redgomery representation when loading from JSON
|
|
if (isRed) {
|
|
this.x.forceRed(this.curve.red);
|
|
this.y.forceRed(this.curve.red);
|
|
}
|
|
if (!this.x.red)
|
|
this.x = this.x.toRed(this.curve.red);
|
|
if (!this.y.red)
|
|
this.y = this.y.toRed(this.curve.red);
|
|
this.inf = false;
|
|
}
|
|
}
|
|
inherits(Point, Base.BasePoint);
|
|
|
|
ShortCurve.prototype.point = function point(x, y, isRed) {
|
|
return new Point(this, x, y, isRed);
|
|
};
|
|
|
|
ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) {
|
|
return Point.fromJSON(this, obj, red);
|
|
};
|
|
|
|
Point.prototype._getBeta = function _getBeta() {
|
|
if (!this.curve.endo)
|
|
return;
|
|
|
|
var pre = this.precomputed;
|
|
if (pre && pre.beta)
|
|
return pre.beta;
|
|
|
|
var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y);
|
|
if (pre) {
|
|
var curve = this.curve;
|
|
var endoMul = function(p) {
|
|
return curve.point(p.x.redMul(curve.endo.beta), p.y);
|
|
};
|
|
pre.beta = beta;
|
|
beta.precomputed = {
|
|
beta: null,
|
|
naf: pre.naf && {
|
|
wnd: pre.naf.wnd,
|
|
points: pre.naf.points.map(endoMul)
|
|
},
|
|
doubles: pre.doubles && {
|
|
step: pre.doubles.step,
|
|
points: pre.doubles.points.map(endoMul)
|
|
}
|
|
};
|
|
}
|
|
return beta;
|
|
};
|
|
|
|
Point.prototype.toJSON = function toJSON() {
|
|
if (!this.precomputed)
|
|
return [ this.x, this.y ];
|
|
|
|
return [ this.x, this.y, this.precomputed && {
|
|
doubles: this.precomputed.doubles && {
|
|
step: this.precomputed.doubles.step,
|
|
points: this.precomputed.doubles.points.slice(1)
|
|
},
|
|
naf: this.precomputed.naf && {
|
|
wnd: this.precomputed.naf.wnd,
|
|
points: this.precomputed.naf.points.slice(1)
|
|
}
|
|
} ];
|
|
};
|
|
|
|
Point.fromJSON = function fromJSON(curve, obj, red) {
|
|
if (typeof obj === 'string')
|
|
obj = JSON.parse(obj);
|
|
var res = curve.point(obj[0], obj[1], red);
|
|
if (!obj[2])
|
|
return res;
|
|
|
|
function obj2point(obj) {
|
|
return curve.point(obj[0], obj[1], red);
|
|
}
|
|
|
|
var pre = obj[2];
|
|
res.precomputed = {
|
|
beta: null,
|
|
doubles: pre.doubles && {
|
|
step: pre.doubles.step,
|
|
points: [ res ].concat(pre.doubles.points.map(obj2point))
|
|
},
|
|
naf: pre.naf && {
|
|
wnd: pre.naf.wnd,
|
|
points: [ res ].concat(pre.naf.points.map(obj2point))
|
|
}
|
|
};
|
|
return res;
|
|
};
|
|
|
|
Point.prototype.inspect = function inspect() {
|
|
if (this.isInfinity())
|
|
return '<EC Point Infinity>';
|
|
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
|
|
' y: ' + this.y.fromRed().toString(16, 2) + '>';
|
|
};
|
|
|
|
Point.prototype.isInfinity = function isInfinity() {
|
|
return this.inf;
|
|
};
|
|
|
|
Point.prototype.add = function add(p) {
|
|
// O + P = P
|
|
if (this.inf)
|
|
return p;
|
|
|
|
// P + O = P
|
|
if (p.inf)
|
|
return this;
|
|
|
|
// P + P = 2P
|
|
if (this.eq(p))
|
|
return this.dbl();
|
|
|
|
// P + (-P) = O
|
|
if (this.neg().eq(p))
|
|
return this.curve.point(null, null);
|
|
|
|
// P + Q = O
|
|
if (this.x.cmp(p.x) === 0)
|
|
return this.curve.point(null, null);
|
|
|
|
var c = this.y.redSub(p.y);
|
|
if (c.cmpn(0) !== 0)
|
|
c = c.redMul(this.x.redSub(p.x).redInvm());
|
|
var nx = c.redSqr().redISub(this.x).redISub(p.x);
|
|
var ny = c.redMul(this.x.redSub(nx)).redISub(this.y);
|
|
return this.curve.point(nx, ny);
|
|
};
|
|
|
|
Point.prototype.dbl = function dbl() {
|
|
if (this.inf)
|
|
return this;
|
|
|
|
// 2P = O
|
|
var ys1 = this.y.redAdd(this.y);
|
|
if (ys1.cmpn(0) === 0)
|
|
return this.curve.point(null, null);
|
|
|
|
var a = this.curve.a;
|
|
|
|
var x2 = this.x.redSqr();
|
|
var dyinv = ys1.redInvm();
|
|
var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv);
|
|
|
|
var nx = c.redSqr().redISub(this.x.redAdd(this.x));
|
|
var ny = c.redMul(this.x.redSub(nx)).redISub(this.y);
|
|
return this.curve.point(nx, ny);
|
|
};
|
|
|
|
Point.prototype.getX = function getX() {
|
|
return this.x.fromRed();
|
|
};
|
|
|
|
Point.prototype.getY = function getY() {
|
|
return this.y.fromRed();
|
|
};
|
|
|
|
Point.prototype.mul = function mul(k) {
|
|
k = new BN(k, 16);
|
|
|
|
if (this._hasDoubles(k))
|
|
return this.curve._fixedNafMul(this, k);
|
|
else if (this.curve.endo)
|
|
return this.curve._endoWnafMulAdd([ this ], [ k ]);
|
|
else
|
|
return this.curve._wnafMul(this, k);
|
|
};
|
|
|
|
Point.prototype.mulAdd = function mulAdd(k1, p2, k2) {
|
|
var points = [ this, p2 ];
|
|
var coeffs = [ k1, k2 ];
|
|
if (this.curve.endo)
|
|
return this.curve._endoWnafMulAdd(points, coeffs);
|
|
else
|
|
return this.curve._wnafMulAdd(1, points, coeffs, 2);
|
|
};
|
|
|
|
Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) {
|
|
var points = [ this, p2 ];
|
|
var coeffs = [ k1, k2 ];
|
|
if (this.curve.endo)
|
|
return this.curve._endoWnafMulAdd(points, coeffs, true);
|
|
else
|
|
return this.curve._wnafMulAdd(1, points, coeffs, 2, true);
|
|
};
|
|
|
|
Point.prototype.eq = function eq(p) {
|
|
return this === p ||
|
|
this.inf === p.inf &&
|
|
(this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0);
|
|
};
|
|
|
|
Point.prototype.neg = function neg(_precompute) {
|
|
if (this.inf)
|
|
return this;
|
|
|
|
var res = this.curve.point(this.x, this.y.redNeg());
|
|
if (_precompute && this.precomputed) {
|
|
var pre = this.precomputed;
|
|
var negate = function(p) {
|
|
return p.neg();
|
|
};
|
|
res.precomputed = {
|
|
naf: pre.naf && {
|
|
wnd: pre.naf.wnd,
|
|
points: pre.naf.points.map(negate)
|
|
},
|
|
doubles: pre.doubles && {
|
|
step: pre.doubles.step,
|
|
points: pre.doubles.points.map(negate)
|
|
}
|
|
};
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Point.prototype.toJ = function toJ() {
|
|
if (this.inf)
|
|
return this.curve.jpoint(null, null, null);
|
|
|
|
var res = this.curve.jpoint(this.x, this.y, this.curve.one);
|
|
return res;
|
|
};
|
|
|
|
function JPoint(curve, x, y, z) {
|
|
Base.BasePoint.call(this, curve, 'jacobian');
|
|
if (x === null && y === null && z === null) {
|
|
this.x = this.curve.one;
|
|
this.y = this.curve.one;
|
|
this.z = new BN(0);
|
|
} else {
|
|
this.x = new BN(x, 16);
|
|
this.y = new BN(y, 16);
|
|
this.z = new BN(z, 16);
|
|
}
|
|
if (!this.x.red)
|
|
this.x = this.x.toRed(this.curve.red);
|
|
if (!this.y.red)
|
|
this.y = this.y.toRed(this.curve.red);
|
|
if (!this.z.red)
|
|
this.z = this.z.toRed(this.curve.red);
|
|
|
|
this.zOne = this.z === this.curve.one;
|
|
}
|
|
inherits(JPoint, Base.BasePoint);
|
|
|
|
ShortCurve.prototype.jpoint = function jpoint(x, y, z) {
|
|
return new JPoint(this, x, y, z);
|
|
};
|
|
|
|
JPoint.prototype.toP = function toP() {
|
|
if (this.isInfinity())
|
|
return this.curve.point(null, null);
|
|
|
|
var zinv = this.z.redInvm();
|
|
var zinv2 = zinv.redSqr();
|
|
var ax = this.x.redMul(zinv2);
|
|
var ay = this.y.redMul(zinv2).redMul(zinv);
|
|
|
|
return this.curve.point(ax, ay);
|
|
};
|
|
|
|
JPoint.prototype.neg = function neg() {
|
|
return this.curve.jpoint(this.x, this.y.redNeg(), this.z);
|
|
};
|
|
|
|
JPoint.prototype.add = function add(p) {
|
|
// O + P = P
|
|
if (this.isInfinity())
|
|
return p;
|
|
|
|
// P + O = P
|
|
if (p.isInfinity())
|
|
return this;
|
|
|
|
// 12M + 4S + 7A
|
|
var pz2 = p.z.redSqr();
|
|
var z2 = this.z.redSqr();
|
|
var u1 = this.x.redMul(pz2);
|
|
var u2 = p.x.redMul(z2);
|
|
var s1 = this.y.redMul(pz2.redMul(p.z));
|
|
var s2 = p.y.redMul(z2.redMul(this.z));
|
|
|
|
var h = u1.redSub(u2);
|
|
var r = s1.redSub(s2);
|
|
if (h.cmpn(0) === 0) {
|
|
if (r.cmpn(0) !== 0)
|
|
return this.curve.jpoint(null, null, null);
|
|
else
|
|
return this.dbl();
|
|
}
|
|
|
|
var h2 = h.redSqr();
|
|
var h3 = h2.redMul(h);
|
|
var v = u1.redMul(h2);
|
|
|
|
var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v);
|
|
var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3));
|
|
var nz = this.z.redMul(p.z).redMul(h);
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype.mixedAdd = function mixedAdd(p) {
|
|
// O + P = P
|
|
if (this.isInfinity())
|
|
return p.toJ();
|
|
|
|
// P + O = P
|
|
if (p.isInfinity())
|
|
return this;
|
|
|
|
// 8M + 3S + 7A
|
|
var z2 = this.z.redSqr();
|
|
var u1 = this.x;
|
|
var u2 = p.x.redMul(z2);
|
|
var s1 = this.y;
|
|
var s2 = p.y.redMul(z2).redMul(this.z);
|
|
|
|
var h = u1.redSub(u2);
|
|
var r = s1.redSub(s2);
|
|
if (h.cmpn(0) === 0) {
|
|
if (r.cmpn(0) !== 0)
|
|
return this.curve.jpoint(null, null, null);
|
|
else
|
|
return this.dbl();
|
|
}
|
|
|
|
var h2 = h.redSqr();
|
|
var h3 = h2.redMul(h);
|
|
var v = u1.redMul(h2);
|
|
|
|
var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v);
|
|
var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3));
|
|
var nz = this.z.redMul(h);
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype.dblp = function dblp(pow) {
|
|
if (pow === 0)
|
|
return this;
|
|
if (this.isInfinity())
|
|
return this;
|
|
if (!pow)
|
|
return this.dbl();
|
|
|
|
if (this.curve.zeroA || this.curve.threeA) {
|
|
var r = this;
|
|
for (var i = 0; i < pow; i++)
|
|
r = r.dbl();
|
|
return r;
|
|
}
|
|
|
|
// 1M + 2S + 1A + N * (4S + 5M + 8A)
|
|
// N = 1 => 6M + 6S + 9A
|
|
var a = this.curve.a;
|
|
var tinv = this.curve.tinv;
|
|
|
|
var jx = this.x;
|
|
var jy = this.y;
|
|
var jz = this.z;
|
|
var jz4 = jz.redSqr().redSqr();
|
|
|
|
// Reuse results
|
|
var jyd = jy.redAdd(jy);
|
|
for (var i = 0; i < pow; i++) {
|
|
var jx2 = jx.redSqr();
|
|
var jyd2 = jyd.redSqr();
|
|
var jyd4 = jyd2.redSqr();
|
|
var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4));
|
|
|
|
var t1 = jx.redMul(jyd2);
|
|
var nx = c.redSqr().redISub(t1.redAdd(t1));
|
|
var t2 = t1.redISub(nx);
|
|
var dny = c.redMul(t2);
|
|
dny = dny.redIAdd(dny).redISub(jyd4);
|
|
var nz = jyd.redMul(jz);
|
|
if (i + 1 < pow)
|
|
jz4 = jz4.redMul(jyd4);
|
|
|
|
jx = nx;
|
|
jz = nz;
|
|
jyd = dny;
|
|
}
|
|
|
|
return this.curve.jpoint(jx, jyd.redMul(tinv), jz);
|
|
};
|
|
|
|
JPoint.prototype.dbl = function dbl() {
|
|
if (this.isInfinity())
|
|
return this;
|
|
|
|
if (this.curve.zeroA)
|
|
return this._zeroDbl();
|
|
else if (this.curve.threeA)
|
|
return this._threeDbl();
|
|
else
|
|
return this._dbl();
|
|
};
|
|
|
|
JPoint.prototype._zeroDbl = function _zeroDbl() {
|
|
var nx;
|
|
var ny;
|
|
var nz;
|
|
// Z = 1
|
|
if (this.zOne) {
|
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
|
|
// #doubling-mdbl-2007-bl
|
|
// 1M + 5S + 14A
|
|
|
|
// XX = X1^2
|
|
var xx = this.x.redSqr();
|
|
// YY = Y1^2
|
|
var yy = this.y.redSqr();
|
|
// YYYY = YY^2
|
|
var yyyy = yy.redSqr();
|
|
// S = 2 * ((X1 + YY)^2 - XX - YYYY)
|
|
var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
|
|
s = s.redIAdd(s);
|
|
// M = 3 * XX + a; a = 0
|
|
var m = xx.redAdd(xx).redIAdd(xx);
|
|
// T = M ^ 2 - 2*S
|
|
var t = m.redSqr().redISub(s).redISub(s);
|
|
|
|
// 8 * YYYY
|
|
var yyyy8 = yyyy.redIAdd(yyyy);
|
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
|
|
|
// X3 = T
|
|
nx = t;
|
|
// Y3 = M * (S - T) - 8 * YYYY
|
|
ny = m.redMul(s.redISub(t)).redISub(yyyy8);
|
|
// Z3 = 2*Y1
|
|
nz = this.y.redAdd(this.y);
|
|
} else {
|
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
|
|
// #doubling-dbl-2009-l
|
|
// 2M + 5S + 13A
|
|
|
|
// A = X1^2
|
|
var a = this.x.redSqr();
|
|
// B = Y1^2
|
|
var b = this.y.redSqr();
|
|
// C = B^2
|
|
var c = b.redSqr();
|
|
// D = 2 * ((X1 + B)^2 - A - C)
|
|
var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c);
|
|
d = d.redIAdd(d);
|
|
// E = 3 * A
|
|
var e = a.redAdd(a).redIAdd(a);
|
|
// F = E^2
|
|
var f = e.redSqr();
|
|
|
|
// 8 * C
|
|
var c8 = c.redIAdd(c);
|
|
c8 = c8.redIAdd(c8);
|
|
c8 = c8.redIAdd(c8);
|
|
|
|
// X3 = F - 2 * D
|
|
nx = f.redISub(d).redISub(d);
|
|
// Y3 = E * (D - X3) - 8 * C
|
|
ny = e.redMul(d.redISub(nx)).redISub(c8);
|
|
// Z3 = 2 * Y1 * Z1
|
|
nz = this.y.redMul(this.z);
|
|
nz = nz.redIAdd(nz);
|
|
}
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype._threeDbl = function _threeDbl() {
|
|
var nx;
|
|
var ny;
|
|
var nz;
|
|
// Z = 1
|
|
if (this.zOne) {
|
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html
|
|
// #doubling-mdbl-2007-bl
|
|
// 1M + 5S + 15A
|
|
|
|
// XX = X1^2
|
|
var xx = this.x.redSqr();
|
|
// YY = Y1^2
|
|
var yy = this.y.redSqr();
|
|
// YYYY = YY^2
|
|
var yyyy = yy.redSqr();
|
|
// S = 2 * ((X1 + YY)^2 - XX - YYYY)
|
|
var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
|
|
s = s.redIAdd(s);
|
|
// M = 3 * XX + a
|
|
var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a);
|
|
// T = M^2 - 2 * S
|
|
var t = m.redSqr().redISub(s).redISub(s);
|
|
// X3 = T
|
|
nx = t;
|
|
// Y3 = M * (S - T) - 8 * YYYY
|
|
var yyyy8 = yyyy.redIAdd(yyyy);
|
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
|
ny = m.redMul(s.redISub(t)).redISub(yyyy8);
|
|
// Z3 = 2 * Y1
|
|
nz = this.y.redAdd(this.y);
|
|
} else {
|
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
|
|
// 3M + 5S
|
|
|
|
// delta = Z1^2
|
|
var delta = this.z.redSqr();
|
|
// gamma = Y1^2
|
|
var gamma = this.y.redSqr();
|
|
// beta = X1 * gamma
|
|
var beta = this.x.redMul(gamma);
|
|
// alpha = 3 * (X1 - delta) * (X1 + delta)
|
|
var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta));
|
|
alpha = alpha.redAdd(alpha).redIAdd(alpha);
|
|
// X3 = alpha^2 - 8 * beta
|
|
var beta4 = beta.redIAdd(beta);
|
|
beta4 = beta4.redIAdd(beta4);
|
|
var beta8 = beta4.redAdd(beta4);
|
|
nx = alpha.redSqr().redISub(beta8);
|
|
// Z3 = (Y1 + Z1)^2 - gamma - delta
|
|
nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta);
|
|
// Y3 = alpha * (4 * beta - X3) - 8 * gamma^2
|
|
var ggamma8 = gamma.redSqr();
|
|
ggamma8 = ggamma8.redIAdd(ggamma8);
|
|
ggamma8 = ggamma8.redIAdd(ggamma8);
|
|
ggamma8 = ggamma8.redIAdd(ggamma8);
|
|
ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8);
|
|
}
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype._dbl = function _dbl() {
|
|
var a = this.curve.a;
|
|
|
|
// 4M + 6S + 10A
|
|
var jx = this.x;
|
|
var jy = this.y;
|
|
var jz = this.z;
|
|
var jz4 = jz.redSqr().redSqr();
|
|
|
|
var jx2 = jx.redSqr();
|
|
var jy2 = jy.redSqr();
|
|
|
|
var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4));
|
|
|
|
var jxd4 = jx.redAdd(jx);
|
|
jxd4 = jxd4.redIAdd(jxd4);
|
|
var t1 = jxd4.redMul(jy2);
|
|
var nx = c.redSqr().redISub(t1.redAdd(t1));
|
|
var t2 = t1.redISub(nx);
|
|
|
|
var jyd8 = jy2.redSqr();
|
|
jyd8 = jyd8.redIAdd(jyd8);
|
|
jyd8 = jyd8.redIAdd(jyd8);
|
|
jyd8 = jyd8.redIAdd(jyd8);
|
|
var ny = c.redMul(t2).redISub(jyd8);
|
|
var nz = jy.redAdd(jy).redMul(jz);
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype.trpl = function trpl() {
|
|
if (!this.curve.zeroA)
|
|
return this.dbl().add(this);
|
|
|
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl
|
|
// 5M + 10S + ...
|
|
|
|
// XX = X1^2
|
|
var xx = this.x.redSqr();
|
|
// YY = Y1^2
|
|
var yy = this.y.redSqr();
|
|
// ZZ = Z1^2
|
|
var zz = this.z.redSqr();
|
|
// YYYY = YY^2
|
|
var yyyy = yy.redSqr();
|
|
// M = 3 * XX + a * ZZ2; a = 0
|
|
var m = xx.redAdd(xx).redIAdd(xx);
|
|
// MM = M^2
|
|
var mm = m.redSqr();
|
|
// E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM
|
|
var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
|
|
e = e.redIAdd(e);
|
|
e = e.redAdd(e).redIAdd(e);
|
|
e = e.redISub(mm);
|
|
// EE = E^2
|
|
var ee = e.redSqr();
|
|
// T = 16*YYYY
|
|
var t = yyyy.redIAdd(yyyy);
|
|
t = t.redIAdd(t);
|
|
t = t.redIAdd(t);
|
|
t = t.redIAdd(t);
|
|
// U = (M + E)^2 - MM - EE - T
|
|
var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t);
|
|
// X3 = 4 * (X1 * EE - 4 * YY * U)
|
|
var yyu4 = yy.redMul(u);
|
|
yyu4 = yyu4.redIAdd(yyu4);
|
|
yyu4 = yyu4.redIAdd(yyu4);
|
|
var nx = this.x.redMul(ee).redISub(yyu4);
|
|
nx = nx.redIAdd(nx);
|
|
nx = nx.redIAdd(nx);
|
|
// Y3 = 8 * Y1 * (U * (T - U) - E * EE)
|
|
var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee)));
|
|
ny = ny.redIAdd(ny);
|
|
ny = ny.redIAdd(ny);
|
|
ny = ny.redIAdd(ny);
|
|
// Z3 = (Z1 + E)^2 - ZZ - EE
|
|
var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee);
|
|
|
|
return this.curve.jpoint(nx, ny, nz);
|
|
};
|
|
|
|
JPoint.prototype.mul = function mul(k, kbase) {
|
|
k = new BN(k, kbase);
|
|
|
|
return this.curve._wnafMul(this, k);
|
|
};
|
|
|
|
JPoint.prototype.eq = function eq(p) {
|
|
if (p.type === 'affine')
|
|
return this.eq(p.toJ());
|
|
|
|
if (this === p)
|
|
return true;
|
|
|
|
// x1 * z2^2 == x2 * z1^2
|
|
var z2 = this.z.redSqr();
|
|
var pz2 = p.z.redSqr();
|
|
if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0)
|
|
return false;
|
|
|
|
// y1 * z2^3 == y2 * z1^3
|
|
var z3 = z2.redMul(this.z);
|
|
var pz3 = pz2.redMul(p.z);
|
|
return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0;
|
|
};
|
|
|
|
JPoint.prototype.eqXToP = function eqXToP(x) {
|
|
var zs = this.z.redSqr();
|
|
var rx = x.toRed(this.curve.red).redMul(zs);
|
|
if (this.x.cmp(rx) === 0)
|
|
return true;
|
|
|
|
var xc = x.clone();
|
|
var t = this.curve.redN.redMul(zs);
|
|
for (;;) {
|
|
xc.iadd(this.curve.n);
|
|
if (xc.cmp(this.curve.p) >= 0)
|
|
return false;
|
|
|
|
rx.redIAdd(t);
|
|
if (this.x.cmp(rx) === 0)
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
JPoint.prototype.inspect = function inspect() {
|
|
if (this.isInfinity())
|
|
return '<EC JPoint Infinity>';
|
|
return '<EC JPoint x: ' + this.x.toString(16, 2) +
|
|
' y: ' + this.y.toString(16, 2) +
|
|
' z: ' + this.z.toString(16, 2) + '>';
|
|
};
|
|
|
|
JPoint.prototype.isInfinity = function isInfinity() {
|
|
// XXX This code assumes that zero is always zero in red
|
|
return this.z.cmpn(0) === 0;
|
|
};
|
|
|
|
},{"../../elliptic":285,"../curve":288,"bn.js":280,"inherits":318}],291:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var curves = exports;
|
|
|
|
var hash = require('hash.js');
|
|
var elliptic = require('../elliptic');
|
|
|
|
var assert = elliptic.utils.assert;
|
|
|
|
function PresetCurve(options) {
|
|
if (options.type === 'short')
|
|
this.curve = new elliptic.curve.short(options);
|
|
else if (options.type === 'edwards')
|
|
this.curve = new elliptic.curve.edwards(options);
|
|
else
|
|
this.curve = new elliptic.curve.mont(options);
|
|
this.g = this.curve.g;
|
|
this.n = this.curve.n;
|
|
this.hash = options.hash;
|
|
|
|
assert(this.g.validate(), 'Invalid curve');
|
|
assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, G*N != O');
|
|
}
|
|
curves.PresetCurve = PresetCurve;
|
|
|
|
function defineCurve(name, options) {
|
|
Object.defineProperty(curves, name, {
|
|
configurable: true,
|
|
enumerable: true,
|
|
get: function() {
|
|
var curve = new PresetCurve(options);
|
|
Object.defineProperty(curves, name, {
|
|
configurable: true,
|
|
enumerable: true,
|
|
value: curve
|
|
});
|
|
return curve;
|
|
}
|
|
});
|
|
}
|
|
|
|
defineCurve('p192', {
|
|
type: 'short',
|
|
prime: 'p192',
|
|
p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff',
|
|
a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc',
|
|
b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1',
|
|
n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831',
|
|
hash: hash.sha256,
|
|
gRed: false,
|
|
g: [
|
|
'188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012',
|
|
'07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811'
|
|
]
|
|
});
|
|
|
|
defineCurve('p224', {
|
|
type: 'short',
|
|
prime: 'p224',
|
|
p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001',
|
|
a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe',
|
|
b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4',
|
|
n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d',
|
|
hash: hash.sha256,
|
|
gRed: false,
|
|
g: [
|
|
'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21',
|
|
'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34'
|
|
]
|
|
});
|
|
|
|
defineCurve('p256', {
|
|
type: 'short',
|
|
prime: null,
|
|
p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff',
|
|
a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc',
|
|
b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b',
|
|
n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551',
|
|
hash: hash.sha256,
|
|
gRed: false,
|
|
g: [
|
|
'6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296',
|
|
'4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5'
|
|
]
|
|
});
|
|
|
|
defineCurve('p384', {
|
|
type: 'short',
|
|
prime: null,
|
|
p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'fffffffe ffffffff 00000000 00000000 ffffffff',
|
|
a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'fffffffe ffffffff 00000000 00000000 fffffffc',
|
|
b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' +
|
|
'5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef',
|
|
n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' +
|
|
'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973',
|
|
hash: hash.sha384,
|
|
gRed: false,
|
|
g: [
|
|
'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' +
|
|
'5502f25d bf55296c 3a545e38 72760ab7',
|
|
'3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' +
|
|
'0a60b1ce 1d7e819d 7a431d7c 90ea0e5f'
|
|
]
|
|
});
|
|
|
|
defineCurve('p521', {
|
|
type: 'short',
|
|
prime: null,
|
|
p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff',
|
|
a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'ffffffff ffffffff ffffffff ffffffff fffffffc',
|
|
b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' +
|
|
'99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' +
|
|
'3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00',
|
|
n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
|
'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' +
|
|
'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409',
|
|
hash: hash.sha512,
|
|
gRed: false,
|
|
g: [
|
|
'000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' +
|
|
'053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' +
|
|
'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66',
|
|
'00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' +
|
|
'579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' +
|
|
'3fad0761 353c7086 a272c240 88be9476 9fd16650'
|
|
]
|
|
});
|
|
|
|
defineCurve('curve25519', {
|
|
type: 'mont',
|
|
prime: 'p25519',
|
|
p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed',
|
|
a: '76d06',
|
|
b: '1',
|
|
n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed',
|
|
hash: hash.sha256,
|
|
gRed: false,
|
|
g: [
|
|
'9'
|
|
]
|
|
});
|
|
|
|
defineCurve('ed25519', {
|
|
type: 'edwards',
|
|
prime: 'p25519',
|
|
p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed',
|
|
a: '-1',
|
|
c: '1',
|
|
// -121665 * (121666^(-1)) (mod P)
|
|
d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3',
|
|
n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed',
|
|
hash: hash.sha256,
|
|
gRed: false,
|
|
g: [
|
|
'216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a',
|
|
|
|
// 4/5
|
|
'6666666666666666666666666666666666666666666666666666666666666658'
|
|
]
|
|
});
|
|
|
|
var pre;
|
|
try {
|
|
pre = require('./precomputed/secp256k1');
|
|
} catch (e) {
|
|
pre = undefined;
|
|
}
|
|
|
|
defineCurve('secp256k1', {
|
|
type: 'short',
|
|
prime: 'k256',
|
|
p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f',
|
|
a: '0',
|
|
b: '7',
|
|
n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141',
|
|
h: '1',
|
|
hash: hash.sha256,
|
|
|
|
// Precomputed endomorphism
|
|
beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee',
|
|
lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72',
|
|
basis: [
|
|
{
|
|
a: '3086d221a7d46bcde86c90e49284eb15',
|
|
b: '-e4437ed6010e88286f547fa90abfe4c3'
|
|
},
|
|
{
|
|
a: '114ca50f7a8e2f3f657c1108d9d44cfd8',
|
|
b: '3086d221a7d46bcde86c90e49284eb15'
|
|
}
|
|
],
|
|
|
|
gRed: false,
|
|
g: [
|
|
'79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
|
|
'483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8',
|
|
pre
|
|
]
|
|
});
|
|
|
|
},{"../elliptic":285,"./precomputed/secp256k1":298,"hash.js":301}],292:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var BN = require('bn.js');
|
|
var HmacDRBG = require('hmac-drbg');
|
|
var elliptic = require('../../elliptic');
|
|
var utils = elliptic.utils;
|
|
var assert = utils.assert;
|
|
|
|
var KeyPair = require('./key');
|
|
var Signature = require('./signature');
|
|
|
|
function EC(options) {
|
|
if (!(this instanceof EC))
|
|
return new EC(options);
|
|
|
|
// Shortcut `elliptic.ec(curve-name)`
|
|
if (typeof options === 'string') {
|
|
assert(elliptic.curves.hasOwnProperty(options), 'Unknown curve ' + options);
|
|
|
|
options = elliptic.curves[options];
|
|
}
|
|
|
|
// Shortcut for `elliptic.ec(elliptic.curves.curveName)`
|
|
if (options instanceof elliptic.curves.PresetCurve)
|
|
options = { curve: options };
|
|
|
|
this.curve = options.curve.curve;
|
|
this.n = this.curve.n;
|
|
this.nh = this.n.ushrn(1);
|
|
this.g = this.curve.g;
|
|
|
|
// Point on curve
|
|
this.g = options.curve.g;
|
|
this.g.precompute(options.curve.n.bitLength() + 1);
|
|
|
|
// Hash for function for DRBG
|
|
this.hash = options.hash || options.curve.hash;
|
|
}
|
|
module.exports = EC;
|
|
|
|
EC.prototype.keyPair = function keyPair(options) {
|
|
return new KeyPair(this, options);
|
|
};
|
|
|
|
EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) {
|
|
return KeyPair.fromPrivate(this, priv, enc);
|
|
};
|
|
|
|
EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) {
|
|
return KeyPair.fromPublic(this, pub, enc);
|
|
};
|
|
|
|
EC.prototype.genKeyPair = function genKeyPair(options) {
|
|
if (!options)
|
|
options = {};
|
|
|
|
// Instantiate Hmac_DRBG
|
|
var drbg = new HmacDRBG({
|
|
hash: this.hash,
|
|
pers: options.pers,
|
|
persEnc: options.persEnc || 'utf8',
|
|
entropy: options.entropy || elliptic.rand(this.hash.hmacStrength),
|
|
entropyEnc: options.entropy && options.entropyEnc || 'utf8',
|
|
nonce: this.n.toArray()
|
|
});
|
|
|
|
var bytes = this.n.byteLength();
|
|
var ns2 = this.n.sub(new BN(2));
|
|
do {
|
|
var priv = new BN(drbg.generate(bytes));
|
|
if (priv.cmp(ns2) > 0)
|
|
continue;
|
|
|
|
priv.iaddn(1);
|
|
return this.keyFromPrivate(priv);
|
|
} while (true);
|
|
};
|
|
|
|
EC.prototype._truncateToN = function truncateToN(msg, truncOnly) {
|
|
var delta = msg.byteLength() * 8 - this.n.bitLength();
|
|
if (delta > 0)
|
|
msg = msg.ushrn(delta);
|
|
if (!truncOnly && msg.cmp(this.n) >= 0)
|
|
return msg.sub(this.n);
|
|
else
|
|
return msg;
|
|
};
|
|
|
|
EC.prototype.sign = function sign(msg, key, enc, options) {
|
|
if (typeof enc === 'object') {
|
|
options = enc;
|
|
enc = null;
|
|
}
|
|
if (!options)
|
|
options = {};
|
|
|
|
key = this.keyFromPrivate(key, enc);
|
|
msg = this._truncateToN(new BN(msg, 16));
|
|
|
|
// Zero-extend key to provide enough entropy
|
|
var bytes = this.n.byteLength();
|
|
var bkey = key.getPrivate().toArray('be', bytes);
|
|
|
|
// Zero-extend nonce to have the same byte size as N
|
|
var nonce = msg.toArray('be', bytes);
|
|
|
|
// Instantiate Hmac_DRBG
|
|
var drbg = new HmacDRBG({
|
|
hash: this.hash,
|
|
entropy: bkey,
|
|
nonce: nonce,
|
|
pers: options.pers,
|
|
persEnc: options.persEnc || 'utf8'
|
|
});
|
|
|
|
// Number of bytes to generate
|
|
var ns1 = this.n.sub(new BN(1));
|
|
|
|
for (var iter = 0; true; iter++) {
|
|
var k = options.k ?
|
|
options.k(iter) :
|
|
new BN(drbg.generate(this.n.byteLength()));
|
|
k = this._truncateToN(k, true);
|
|
if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0)
|
|
continue;
|
|
|
|
var kp = this.g.mul(k);
|
|
if (kp.isInfinity())
|
|
continue;
|
|
|
|
var kpX = kp.getX();
|
|
var r = kpX.umod(this.n);
|
|
if (r.cmpn(0) === 0)
|
|
continue;
|
|
|
|
var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg));
|
|
s = s.umod(this.n);
|
|
if (s.cmpn(0) === 0)
|
|
continue;
|
|
|
|
var recoveryParam = (kp.getY().isOdd() ? 1 : 0) |
|
|
(kpX.cmp(r) !== 0 ? 2 : 0);
|
|
|
|
// Use complement of `s`, if it is > `n / 2`
|
|
if (options.canonical && s.cmp(this.nh) > 0) {
|
|
s = this.n.sub(s);
|
|
recoveryParam ^= 1;
|
|
}
|
|
|
|
return new Signature({ r: r, s: s, recoveryParam: recoveryParam });
|
|
}
|
|
};
|
|
|
|
EC.prototype.verify = function verify(msg, signature, key, enc) {
|
|
msg = this._truncateToN(new BN(msg, 16));
|
|
key = this.keyFromPublic(key, enc);
|
|
signature = new Signature(signature, 'hex');
|
|
|
|
// Perform primitive values validation
|
|
var r = signature.r;
|
|
var s = signature.s;
|
|
if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0)
|
|
return false;
|
|
if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0)
|
|
return false;
|
|
|
|
// Validate signature
|
|
var sinv = s.invm(this.n);
|
|
var u1 = sinv.mul(msg).umod(this.n);
|
|
var u2 = sinv.mul(r).umod(this.n);
|
|
|
|
if (!this.curve._maxwellTrick) {
|
|
var p = this.g.mulAdd(u1, key.getPublic(), u2);
|
|
if (p.isInfinity())
|
|
return false;
|
|
|
|
return p.getX().umod(this.n).cmp(r) === 0;
|
|
}
|
|
|
|
// NOTE: Greg Maxwell's trick, inspired by:
|
|
// https://git.io/vad3K
|
|
|
|
var p = this.g.jmulAdd(u1, key.getPublic(), u2);
|
|
if (p.isInfinity())
|
|
return false;
|
|
|
|
// Compare `p.x` of Jacobian point with `r`,
|
|
// this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the
|
|
// inverse of `p.z^2`
|
|
return p.eqXToP(r);
|
|
};
|
|
|
|
EC.prototype.recoverPubKey = function(msg, signature, j, enc) {
|
|
assert((3 & j) === j, 'The recovery param is more than two bits');
|
|
signature = new Signature(signature, enc);
|
|
|
|
var n = this.n;
|
|
var e = new BN(msg);
|
|
var r = signature.r;
|
|
var s = signature.s;
|
|
|
|
// A set LSB signifies that the y-coordinate is odd
|
|
var isYOdd = j & 1;
|
|
var isSecondKey = j >> 1;
|
|
if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey)
|
|
throw new Error('Unable to find sencond key candinate');
|
|
|
|
// 1.1. Let x = r + jn.
|
|
if (isSecondKey)
|
|
r = this.curve.pointFromX(r.add(this.curve.n), isYOdd);
|
|
else
|
|
r = this.curve.pointFromX(r, isYOdd);
|
|
|
|
var rInv = signature.r.invm(n);
|
|
var s1 = n.sub(e).mul(rInv).umod(n);
|
|
var s2 = s.mul(rInv).umod(n);
|
|
|
|
// 1.6.1 Compute Q = r^-1 (sR - eG)
|
|
// Q = r^-1 (sR + -eG)
|
|
return this.g.mulAdd(s1, r, s2);
|
|
};
|
|
|
|
EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) {
|
|
signature = new Signature(signature, enc);
|
|
if (signature.recoveryParam !== null)
|
|
return signature.recoveryParam;
|
|
|
|
for (var i = 0; i < 4; i++) {
|
|
var Qprime;
|
|
try {
|
|
Qprime = this.recoverPubKey(e, signature, i);
|
|
} catch (e) {
|
|
continue;
|
|
}
|
|
|
|
if (Qprime.eq(Q))
|
|
return i;
|
|
}
|
|
throw new Error('Unable to find valid recovery factor');
|
|
};
|
|
|
|
},{"../../elliptic":285,"./key":293,"./signature":294,"bn.js":280,"hmac-drbg":314}],293:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var BN = require('bn.js');
|
|
var elliptic = require('../../elliptic');
|
|
var utils = elliptic.utils;
|
|
var assert = utils.assert;
|
|
|
|
function KeyPair(ec, options) {
|
|
this.ec = ec;
|
|
this.priv = null;
|
|
this.pub = null;
|
|
|
|
// KeyPair(ec, { priv: ..., pub: ... })
|
|
if (options.priv)
|
|
this._importPrivate(options.priv, options.privEnc);
|
|
if (options.pub)
|
|
this._importPublic(options.pub, options.pubEnc);
|
|
}
|
|
module.exports = KeyPair;
|
|
|
|
KeyPair.fromPublic = function fromPublic(ec, pub, enc) {
|
|
if (pub instanceof KeyPair)
|
|
return pub;
|
|
|
|
return new KeyPair(ec, {
|
|
pub: pub,
|
|
pubEnc: enc
|
|
});
|
|
};
|
|
|
|
KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) {
|
|
if (priv instanceof KeyPair)
|
|
return priv;
|
|
|
|
return new KeyPair(ec, {
|
|
priv: priv,
|
|
privEnc: enc
|
|
});
|
|
};
|
|
|
|
KeyPair.prototype.validate = function validate() {
|
|
var pub = this.getPublic();
|
|
|
|
if (pub.isInfinity())
|
|
return { result: false, reason: 'Invalid public key' };
|
|
if (!pub.validate())
|
|
return { result: false, reason: 'Public key is not a point' };
|
|
if (!pub.mul(this.ec.curve.n).isInfinity())
|
|
return { result: false, reason: 'Public key * N != O' };
|
|
|
|
return { result: true, reason: null };
|
|
};
|
|
|
|
KeyPair.prototype.getPublic = function getPublic(compact, enc) {
|
|
// compact is optional argument
|
|
if (typeof compact === 'string') {
|
|
enc = compact;
|
|
compact = null;
|
|
}
|
|
|
|
if (!this.pub)
|
|
this.pub = this.ec.g.mul(this.priv);
|
|
|
|
if (!enc)
|
|
return this.pub;
|
|
|
|
return this.pub.encode(enc, compact);
|
|
};
|
|
|
|
KeyPair.prototype.getPrivate = function getPrivate(enc) {
|
|
if (enc === 'hex')
|
|
return this.priv.toString(16, 2);
|
|
else
|
|
return this.priv;
|
|
};
|
|
|
|
KeyPair.prototype._importPrivate = function _importPrivate(key, enc) {
|
|
this.priv = new BN(key, enc || 16);
|
|
|
|
// Ensure that the priv won't be bigger than n, otherwise we may fail
|
|
// in fixed multiplication method
|
|
this.priv = this.priv.umod(this.ec.curve.n);
|
|
};
|
|
|
|
KeyPair.prototype._importPublic = function _importPublic(key, enc) {
|
|
if (key.x || key.y) {
|
|
// Montgomery points only have an `x` coordinate.
|
|
// Weierstrass/Edwards points on the other hand have both `x` and
|
|
// `y` coordinates.
|
|
if (this.ec.curve.type === 'mont') {
|
|
assert(key.x, 'Need x coordinate');
|
|
} else if (this.ec.curve.type === 'short' ||
|
|
this.ec.curve.type === 'edwards') {
|
|
assert(key.x && key.y, 'Need both x and y coordinate');
|
|
}
|
|
this.pub = this.ec.curve.point(key.x, key.y);
|
|
return;
|
|
}
|
|
this.pub = this.ec.curve.decodePoint(key, enc);
|
|
};
|
|
|
|
// ECDH
|
|
KeyPair.prototype.derive = function derive(pub) {
|
|
return pub.mul(this.priv).getX();
|
|
};
|
|
|
|
// ECDSA
|
|
KeyPair.prototype.sign = function sign(msg, enc, options) {
|
|
return this.ec.sign(msg, this, enc, options);
|
|
};
|
|
|
|
KeyPair.prototype.verify = function verify(msg, signature) {
|
|
return this.ec.verify(msg, signature, this);
|
|
};
|
|
|
|
KeyPair.prototype.inspect = function inspect() {
|
|
return '<Key priv: ' + (this.priv && this.priv.toString(16, 2)) +
|
|
' pub: ' + (this.pub && this.pub.inspect()) + ' >';
|
|
};
|
|
|
|
},{"../../elliptic":285,"bn.js":280}],294:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var BN = require('bn.js');
|
|
|
|
var elliptic = require('../../elliptic');
|
|
var utils = elliptic.utils;
|
|
var assert = utils.assert;
|
|
|
|
function Signature(options, enc) {
|
|
if (options instanceof Signature)
|
|
return options;
|
|
|
|
if (this._importDER(options, enc))
|
|
return;
|
|
|
|
assert(options.r && options.s, 'Signature without r or s');
|
|
this.r = new BN(options.r, 16);
|
|
this.s = new BN(options.s, 16);
|
|
if (options.recoveryParam === undefined)
|
|
this.recoveryParam = null;
|
|
else
|
|
this.recoveryParam = options.recoveryParam;
|
|
}
|
|
module.exports = Signature;
|
|
|
|
function Position() {
|
|
this.place = 0;
|
|
}
|
|
|
|
function getLength(buf, p) {
|
|
var initial = buf[p.place++];
|
|
if (!(initial & 0x80)) {
|
|
return initial;
|
|
}
|
|
var octetLen = initial & 0xf;
|
|
var val = 0;
|
|
for (var i = 0, off = p.place; i < octetLen; i++, off++) {
|
|
val <<= 8;
|
|
val |= buf[off];
|
|
}
|
|
p.place = off;
|
|
return val;
|
|
}
|
|
|
|
function rmPadding(buf) {
|
|
var i = 0;
|
|
var len = buf.length - 1;
|
|
while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) {
|
|
i++;
|
|
}
|
|
if (i === 0) {
|
|
return buf;
|
|
}
|
|
return buf.slice(i);
|
|
}
|
|
|
|
Signature.prototype._importDER = function _importDER(data, enc) {
|
|
data = utils.toArray(data, enc);
|
|
var p = new Position();
|
|
if (data[p.place++] !== 0x30) {
|
|
return false;
|
|
}
|
|
var len = getLength(data, p);
|
|
if ((len + p.place) !== data.length) {
|
|
return false;
|
|
}
|
|
if (data[p.place++] !== 0x02) {
|
|
return false;
|
|
}
|
|
var rlen = getLength(data, p);
|
|
var r = data.slice(p.place, rlen + p.place);
|
|
p.place += rlen;
|
|
if (data[p.place++] !== 0x02) {
|
|
return false;
|
|
}
|
|
var slen = getLength(data, p);
|
|
if (data.length !== slen + p.place) {
|
|
return false;
|
|
}
|
|
var s = data.slice(p.place, slen + p.place);
|
|
if (r[0] === 0 && (r[1] & 0x80)) {
|
|
r = r.slice(1);
|
|
}
|
|
if (s[0] === 0 && (s[1] & 0x80)) {
|
|
s = s.slice(1);
|
|
}
|
|
|
|
this.r = new BN(r);
|
|
this.s = new BN(s);
|
|
this.recoveryParam = null;
|
|
|
|
return true;
|
|
};
|
|
|
|
function constructLength(arr, len) {
|
|
if (len < 0x80) {
|
|
arr.push(len);
|
|
return;
|
|
}
|
|
var octets = 1 + (Math.log(len) / Math.LN2 >>> 3);
|
|
arr.push(octets | 0x80);
|
|
while (--octets) {
|
|
arr.push((len >>> (octets << 3)) & 0xff);
|
|
}
|
|
arr.push(len);
|
|
}
|
|
|
|
Signature.prototype.toDER = function toDER(enc) {
|
|
var r = this.r.toArray();
|
|
var s = this.s.toArray();
|
|
|
|
// Pad values
|
|
if (r[0] & 0x80)
|
|
r = [ 0 ].concat(r);
|
|
// Pad values
|
|
if (s[0] & 0x80)
|
|
s = [ 0 ].concat(s);
|
|
|
|
r = rmPadding(r);
|
|
s = rmPadding(s);
|
|
|
|
while (!s[0] && !(s[1] & 0x80)) {
|
|
s = s.slice(1);
|
|
}
|
|
var arr = [ 0x02 ];
|
|
constructLength(arr, r.length);
|
|
arr = arr.concat(r);
|
|
arr.push(0x02);
|
|
constructLength(arr, s.length);
|
|
var backHalf = arr.concat(s);
|
|
var res = [ 0x30 ];
|
|
constructLength(res, backHalf.length);
|
|
res = res.concat(backHalf);
|
|
return utils.encode(res, enc);
|
|
};
|
|
|
|
},{"../../elliptic":285,"bn.js":280}],295:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var hash = require('hash.js');
|
|
var elliptic = require('../../elliptic');
|
|
var utils = elliptic.utils;
|
|
var assert = utils.assert;
|
|
var parseBytes = utils.parseBytes;
|
|
var KeyPair = require('./key');
|
|
var Signature = require('./signature');
|
|
|
|
function EDDSA(curve) {
|
|
assert(curve === 'ed25519', 'only tested with ed25519 so far');
|
|
|
|
if (!(this instanceof EDDSA))
|
|
return new EDDSA(curve);
|
|
|
|
var curve = elliptic.curves[curve].curve;
|
|
this.curve = curve;
|
|
this.g = curve.g;
|
|
this.g.precompute(curve.n.bitLength() + 1);
|
|
|
|
this.pointClass = curve.point().constructor;
|
|
this.encodingLength = Math.ceil(curve.n.bitLength() / 8);
|
|
this.hash = hash.sha512;
|
|
}
|
|
|
|
module.exports = EDDSA;
|
|
|
|
/**
|
|
* @param {Array|String} message - message bytes
|
|
* @param {Array|String|KeyPair} secret - secret bytes or a keypair
|
|
* @returns {Signature} - signature
|
|
*/
|
|
EDDSA.prototype.sign = function sign(message, secret) {
|
|
message = parseBytes(message);
|
|
var key = this.keyFromSecret(secret);
|
|
var r = this.hashInt(key.messagePrefix(), message);
|
|
var R = this.g.mul(r);
|
|
var Rencoded = this.encodePoint(R);
|
|
var s_ = this.hashInt(Rencoded, key.pubBytes(), message)
|
|
.mul(key.priv());
|
|
var S = r.add(s_).umod(this.curve.n);
|
|
return this.makeSignature({ R: R, S: S, Rencoded: Rencoded });
|
|
};
|
|
|
|
/**
|
|
* @param {Array} message - message bytes
|
|
* @param {Array|String|Signature} sig - sig bytes
|
|
* @param {Array|String|Point|KeyPair} pub - public key
|
|
* @returns {Boolean} - true if public key matches sig of message
|
|
*/
|
|
EDDSA.prototype.verify = function verify(message, sig, pub) {
|
|
message = parseBytes(message);
|
|
sig = this.makeSignature(sig);
|
|
var key = this.keyFromPublic(pub);
|
|
var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message);
|
|
var SG = this.g.mul(sig.S());
|
|
var RplusAh = sig.R().add(key.pub().mul(h));
|
|
return RplusAh.eq(SG);
|
|
};
|
|
|
|
EDDSA.prototype.hashInt = function hashInt() {
|
|
var hash = this.hash();
|
|
for (var i = 0; i < arguments.length; i++)
|
|
hash.update(arguments[i]);
|
|
return utils.intFromLE(hash.digest()).umod(this.curve.n);
|
|
};
|
|
|
|
EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) {
|
|
return KeyPair.fromPublic(this, pub);
|
|
};
|
|
|
|
EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) {
|
|
return KeyPair.fromSecret(this, secret);
|
|
};
|
|
|
|
EDDSA.prototype.makeSignature = function makeSignature(sig) {
|
|
if (sig instanceof Signature)
|
|
return sig;
|
|
return new Signature(this, sig);
|
|
};
|
|
|
|
/**
|
|
* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2
|
|
*
|
|
* EDDSA defines methods for encoding and decoding points and integers. These are
|
|
* helper convenience methods, that pass along to utility functions implied
|
|
* parameters.
|
|
*
|
|
*/
|
|
EDDSA.prototype.encodePoint = function encodePoint(point) {
|
|
var enc = point.getY().toArray('le', this.encodingLength);
|
|
enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0;
|
|
return enc;
|
|
};
|
|
|
|
EDDSA.prototype.decodePoint = function decodePoint(bytes) {
|
|
bytes = utils.parseBytes(bytes);
|
|
|
|
var lastIx = bytes.length - 1;
|
|
var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80);
|
|
var xIsOdd = (bytes[lastIx] & 0x80) !== 0;
|
|
|
|
var y = utils.intFromLE(normed);
|
|
return this.curve.pointFromY(y, xIsOdd);
|
|
};
|
|
|
|
EDDSA.prototype.encodeInt = function encodeInt(num) {
|
|
return num.toArray('le', this.encodingLength);
|
|
};
|
|
|
|
EDDSA.prototype.decodeInt = function decodeInt(bytes) {
|
|
return utils.intFromLE(bytes);
|
|
};
|
|
|
|
EDDSA.prototype.isPoint = function isPoint(val) {
|
|
return val instanceof this.pointClass;
|
|
};
|
|
|
|
},{"../../elliptic":285,"./key":296,"./signature":297,"hash.js":301}],296:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var elliptic = require('../../elliptic');
|
|
var utils = elliptic.utils;
|
|
var assert = utils.assert;
|
|
var parseBytes = utils.parseBytes;
|
|
var cachedProperty = utils.cachedProperty;
|
|
|
|
/**
|
|
* @param {EDDSA} eddsa - instance
|
|
* @param {Object} params - public/private key parameters
|
|
*
|
|
* @param {Array<Byte>} [params.secret] - secret seed bytes
|
|
* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms)
|
|
* @param {Array<Byte>} [params.pub] - public key point encoded as bytes
|
|
*
|
|
*/
|
|
function KeyPair(eddsa, params) {
|
|
this.eddsa = eddsa;
|
|
this._secret = parseBytes(params.secret);
|
|
if (eddsa.isPoint(params.pub))
|
|
this._pub = params.pub;
|
|
else
|
|
this._pubBytes = parseBytes(params.pub);
|
|
}
|
|
|
|
KeyPair.fromPublic = function fromPublic(eddsa, pub) {
|
|
if (pub instanceof KeyPair)
|
|
return pub;
|
|
return new KeyPair(eddsa, { pub: pub });
|
|
};
|
|
|
|
KeyPair.fromSecret = function fromSecret(eddsa, secret) {
|
|
if (secret instanceof KeyPair)
|
|
return secret;
|
|
return new KeyPair(eddsa, { secret: secret });
|
|
};
|
|
|
|
KeyPair.prototype.secret = function secret() {
|
|
return this._secret;
|
|
};
|
|
|
|
cachedProperty(KeyPair, 'pubBytes', function pubBytes() {
|
|
return this.eddsa.encodePoint(this.pub());
|
|
});
|
|
|
|
cachedProperty(KeyPair, 'pub', function pub() {
|
|
if (this._pubBytes)
|
|
return this.eddsa.decodePoint(this._pubBytes);
|
|
return this.eddsa.g.mul(this.priv());
|
|
});
|
|
|
|
cachedProperty(KeyPair, 'privBytes', function privBytes() {
|
|
var eddsa = this.eddsa;
|
|
var hash = this.hash();
|
|
var lastIx = eddsa.encodingLength - 1;
|
|
|
|
var a = hash.slice(0, eddsa.encodingLength);
|
|
a[0] &= 248;
|
|
a[lastIx] &= 127;
|
|
a[lastIx] |= 64;
|
|
|
|
return a;
|
|
});
|
|
|
|
cachedProperty(KeyPair, 'priv', function priv() {
|
|
return this.eddsa.decodeInt(this.privBytes());
|
|
});
|
|
|
|
cachedProperty(KeyPair, 'hash', function hash() {
|
|
return this.eddsa.hash().update(this.secret()).digest();
|
|
});
|
|
|
|
cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() {
|
|
return this.hash().slice(this.eddsa.encodingLength);
|
|
});
|
|
|
|
KeyPair.prototype.sign = function sign(message) {
|
|
assert(this._secret, 'KeyPair can only verify');
|
|
return this.eddsa.sign(message, this);
|
|
};
|
|
|
|
KeyPair.prototype.verify = function verify(message, sig) {
|
|
return this.eddsa.verify(message, sig, this);
|
|
};
|
|
|
|
KeyPair.prototype.getSecret = function getSecret(enc) {
|
|
assert(this._secret, 'KeyPair is public only');
|
|
return utils.encode(this.secret(), enc);
|
|
};
|
|
|
|
KeyPair.prototype.getPublic = function getPublic(enc) {
|
|
return utils.encode(this.pubBytes(), enc);
|
|
};
|
|
|
|
module.exports = KeyPair;
|
|
|
|
},{"../../elliptic":285}],297:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var BN = require('bn.js');
|
|
var elliptic = require('../../elliptic');
|
|
var utils = elliptic.utils;
|
|
var assert = utils.assert;
|
|
var cachedProperty = utils.cachedProperty;
|
|
var parseBytes = utils.parseBytes;
|
|
|
|
/**
|
|
* @param {EDDSA} eddsa - eddsa instance
|
|
* @param {Array<Bytes>|Object} sig -
|
|
* @param {Array<Bytes>|Point} [sig.R] - R point as Point or bytes
|
|
* @param {Array<Bytes>|bn} [sig.S] - S scalar as bn or bytes
|
|
* @param {Array<Bytes>} [sig.Rencoded] - R point encoded
|
|
* @param {Array<Bytes>} [sig.Sencoded] - S scalar encoded
|
|
*/
|
|
function Signature(eddsa, sig) {
|
|
this.eddsa = eddsa;
|
|
|
|
if (typeof sig !== 'object')
|
|
sig = parseBytes(sig);
|
|
|
|
if (Array.isArray(sig)) {
|
|
sig = {
|
|
R: sig.slice(0, eddsa.encodingLength),
|
|
S: sig.slice(eddsa.encodingLength)
|
|
};
|
|
}
|
|
|
|
assert(sig.R && sig.S, 'Signature without R or S');
|
|
|
|
if (eddsa.isPoint(sig.R))
|
|
this._R = sig.R;
|
|
if (sig.S instanceof BN)
|
|
this._S = sig.S;
|
|
|
|
this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded;
|
|
this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded;
|
|
}
|
|
|
|
cachedProperty(Signature, 'S', function S() {
|
|
return this.eddsa.decodeInt(this.Sencoded());
|
|
});
|
|
|
|
cachedProperty(Signature, 'R', function R() {
|
|
return this.eddsa.decodePoint(this.Rencoded());
|
|
});
|
|
|
|
cachedProperty(Signature, 'Rencoded', function Rencoded() {
|
|
return this.eddsa.encodePoint(this.R());
|
|
});
|
|
|
|
cachedProperty(Signature, 'Sencoded', function Sencoded() {
|
|
return this.eddsa.encodeInt(this.S());
|
|
});
|
|
|
|
Signature.prototype.toBytes = function toBytes() {
|
|
return this.Rencoded().concat(this.Sencoded());
|
|
};
|
|
|
|
Signature.prototype.toHex = function toHex() {
|
|
return utils.encode(this.toBytes(), 'hex').toUpperCase();
|
|
};
|
|
|
|
module.exports = Signature;
|
|
|
|
},{"../../elliptic":285,"bn.js":280}],298:[function(require,module,exports){
|
|
module.exports = {
|
|
doubles: {
|
|
step: 4,
|
|
points: [
|
|
[
|
|
'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a',
|
|
'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821'
|
|
],
|
|
[
|
|
'8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508',
|
|
'11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf'
|
|
],
|
|
[
|
|
'175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739',
|
|
'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695'
|
|
],
|
|
[
|
|
'363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640',
|
|
'4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9'
|
|
],
|
|
[
|
|
'8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c',
|
|
'4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36'
|
|
],
|
|
[
|
|
'723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda',
|
|
'96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f'
|
|
],
|
|
[
|
|
'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa',
|
|
'5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999'
|
|
],
|
|
[
|
|
'100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0',
|
|
'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09'
|
|
],
|
|
[
|
|
'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d',
|
|
'9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d'
|
|
],
|
|
[
|
|
'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d',
|
|
'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088'
|
|
],
|
|
[
|
|
'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1',
|
|
'9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d'
|
|
],
|
|
[
|
|
'53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0',
|
|
'5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8'
|
|
],
|
|
[
|
|
'8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047',
|
|
'10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a'
|
|
],
|
|
[
|
|
'385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862',
|
|
'283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453'
|
|
],
|
|
[
|
|
'6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7',
|
|
'7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160'
|
|
],
|
|
[
|
|
'3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd',
|
|
'56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0'
|
|
],
|
|
[
|
|
'85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83',
|
|
'7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6'
|
|
],
|
|
[
|
|
'948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a',
|
|
'53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589'
|
|
],
|
|
[
|
|
'6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8',
|
|
'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17'
|
|
],
|
|
[
|
|
'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d',
|
|
'4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda'
|
|
],
|
|
[
|
|
'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725',
|
|
'7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd'
|
|
],
|
|
[
|
|
'213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754',
|
|
'4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2'
|
|
],
|
|
[
|
|
'4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c',
|
|
'17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6'
|
|
],
|
|
[
|
|
'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6',
|
|
'6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f'
|
|
],
|
|
[
|
|
'76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39',
|
|
'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01'
|
|
],
|
|
[
|
|
'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891',
|
|
'893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3'
|
|
],
|
|
[
|
|
'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b',
|
|
'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f'
|
|
],
|
|
[
|
|
'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03',
|
|
'2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7'
|
|
],
|
|
[
|
|
'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d',
|
|
'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78'
|
|
],
|
|
[
|
|
'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070',
|
|
'7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1'
|
|
],
|
|
[
|
|
'90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4',
|
|
'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150'
|
|
],
|
|
[
|
|
'8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da',
|
|
'662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82'
|
|
],
|
|
[
|
|
'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11',
|
|
'1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc'
|
|
],
|
|
[
|
|
'8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e',
|
|
'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b'
|
|
],
|
|
[
|
|
'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41',
|
|
'2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51'
|
|
],
|
|
[
|
|
'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef',
|
|
'67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45'
|
|
],
|
|
[
|
|
'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8',
|
|
'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120'
|
|
],
|
|
[
|
|
'324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d',
|
|
'648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84'
|
|
],
|
|
[
|
|
'4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96',
|
|
'35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d'
|
|
],
|
|
[
|
|
'9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd',
|
|
'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d'
|
|
],
|
|
[
|
|
'6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5',
|
|
'9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8'
|
|
],
|
|
[
|
|
'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266',
|
|
'40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8'
|
|
],
|
|
[
|
|
'7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71',
|
|
'34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac'
|
|
],
|
|
[
|
|
'928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac',
|
|
'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f'
|
|
],
|
|
[
|
|
'85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751',
|
|
'1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962'
|
|
],
|
|
[
|
|
'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e',
|
|
'493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907'
|
|
],
|
|
[
|
|
'827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241',
|
|
'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec'
|
|
],
|
|
[
|
|
'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3',
|
|
'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d'
|
|
],
|
|
[
|
|
'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f',
|
|
'4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414'
|
|
],
|
|
[
|
|
'1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19',
|
|
'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd'
|
|
],
|
|
[
|
|
'146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be',
|
|
'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0'
|
|
],
|
|
[
|
|
'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9',
|
|
'6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811'
|
|
],
|
|
[
|
|
'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2',
|
|
'8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1'
|
|
],
|
|
[
|
|
'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13',
|
|
'7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c'
|
|
],
|
|
[
|
|
'174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c',
|
|
'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73'
|
|
],
|
|
[
|
|
'959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba',
|
|
'2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd'
|
|
],
|
|
[
|
|
'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151',
|
|
'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405'
|
|
],
|
|
[
|
|
'64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073',
|
|
'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589'
|
|
],
|
|
[
|
|
'8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458',
|
|
'38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e'
|
|
],
|
|
[
|
|
'13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b',
|
|
'69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27'
|
|
],
|
|
[
|
|
'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366',
|
|
'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1'
|
|
],
|
|
[
|
|
'8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa',
|
|
'40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482'
|
|
],
|
|
[
|
|
'8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0',
|
|
'620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945'
|
|
],
|
|
[
|
|
'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787',
|
|
'7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573'
|
|
],
|
|
[
|
|
'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e',
|
|
'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82'
|
|
]
|
|
]
|
|
},
|
|
naf: {
|
|
wnd: 7,
|
|
points: [
|
|
[
|
|
'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9',
|
|
'388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672'
|
|
],
|
|
[
|
|
'2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4',
|
|
'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6'
|
|
],
|
|
[
|
|
'5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc',
|
|
'6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da'
|
|
],
|
|
[
|
|
'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe',
|
|
'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37'
|
|
],
|
|
[
|
|
'774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb',
|
|
'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b'
|
|
],
|
|
[
|
|
'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8',
|
|
'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81'
|
|
],
|
|
[
|
|
'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e',
|
|
'581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58'
|
|
],
|
|
[
|
|
'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34',
|
|
'4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77'
|
|
],
|
|
[
|
|
'2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c',
|
|
'85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a'
|
|
],
|
|
[
|
|
'352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5',
|
|
'321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c'
|
|
],
|
|
[
|
|
'2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f',
|
|
'2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67'
|
|
],
|
|
[
|
|
'9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714',
|
|
'73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402'
|
|
],
|
|
[
|
|
'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729',
|
|
'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55'
|
|
],
|
|
[
|
|
'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db',
|
|
'2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482'
|
|
],
|
|
[
|
|
'6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4',
|
|
'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82'
|
|
],
|
|
[
|
|
'1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5',
|
|
'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396'
|
|
],
|
|
[
|
|
'605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479',
|
|
'2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49'
|
|
],
|
|
[
|
|
'62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d',
|
|
'80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf'
|
|
],
|
|
[
|
|
'80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f',
|
|
'1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a'
|
|
],
|
|
[
|
|
'7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb',
|
|
'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7'
|
|
],
|
|
[
|
|
'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9',
|
|
'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933'
|
|
],
|
|
[
|
|
'49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963',
|
|
'758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a'
|
|
],
|
|
[
|
|
'77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74',
|
|
'958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6'
|
|
],
|
|
[
|
|
'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530',
|
|
'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37'
|
|
],
|
|
[
|
|
'463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b',
|
|
'5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e'
|
|
],
|
|
[
|
|
'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247',
|
|
'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6'
|
|
],
|
|
[
|
|
'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1',
|
|
'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476'
|
|
],
|
|
[
|
|
'2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120',
|
|
'4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40'
|
|
],
|
|
[
|
|
'7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435',
|
|
'91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61'
|
|
],
|
|
[
|
|
'754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18',
|
|
'673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683'
|
|
],
|
|
[
|
|
'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8',
|
|
'59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5'
|
|
],
|
|
[
|
|
'186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb',
|
|
'3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b'
|
|
],
|
|
[
|
|
'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f',
|
|
'55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417'
|
|
],
|
|
[
|
|
'5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143',
|
|
'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868'
|
|
],
|
|
[
|
|
'290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba',
|
|
'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a'
|
|
],
|
|
[
|
|
'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45',
|
|
'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6'
|
|
],
|
|
[
|
|
'766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a',
|
|
'744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996'
|
|
],
|
|
[
|
|
'59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e',
|
|
'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e'
|
|
],
|
|
[
|
|
'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8',
|
|
'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d'
|
|
],
|
|
[
|
|
'7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c',
|
|
'30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2'
|
|
],
|
|
[
|
|
'948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519',
|
|
'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e'
|
|
],
|
|
[
|
|
'7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab',
|
|
'100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437'
|
|
],
|
|
[
|
|
'3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca',
|
|
'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311'
|
|
],
|
|
[
|
|
'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf',
|
|
'8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4'
|
|
],
|
|
[
|
|
'1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610',
|
|
'68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575'
|
|
],
|
|
[
|
|
'733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4',
|
|
'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d'
|
|
],
|
|
[
|
|
'15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c',
|
|
'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d'
|
|
],
|
|
[
|
|
'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940',
|
|
'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629'
|
|
],
|
|
[
|
|
'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980',
|
|
'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06'
|
|
],
|
|
[
|
|
'311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3',
|
|
'66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374'
|
|
],
|
|
[
|
|
'34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf',
|
|
'9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee'
|
|
],
|
|
[
|
|
'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63',
|
|
'4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1'
|
|
],
|
|
[
|
|
'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448',
|
|
'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b'
|
|
],
|
|
[
|
|
'32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf',
|
|
'5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661'
|
|
],
|
|
[
|
|
'7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5',
|
|
'8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6'
|
|
],
|
|
[
|
|
'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6',
|
|
'8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e'
|
|
],
|
|
[
|
|
'16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5',
|
|
'5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d'
|
|
],
|
|
[
|
|
'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99',
|
|
'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc'
|
|
],
|
|
[
|
|
'78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51',
|
|
'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4'
|
|
],
|
|
[
|
|
'494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5',
|
|
'42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c'
|
|
],
|
|
[
|
|
'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5',
|
|
'204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b'
|
|
],
|
|
[
|
|
'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997',
|
|
'4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913'
|
|
],
|
|
[
|
|
'841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881',
|
|
'73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154'
|
|
],
|
|
[
|
|
'5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5',
|
|
'39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865'
|
|
],
|
|
[
|
|
'36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66',
|
|
'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc'
|
|
],
|
|
[
|
|
'336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726',
|
|
'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224'
|
|
],
|
|
[
|
|
'8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede',
|
|
'6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e'
|
|
],
|
|
[
|
|
'1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94',
|
|
'60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6'
|
|
],
|
|
[
|
|
'85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31',
|
|
'3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511'
|
|
],
|
|
[
|
|
'29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51',
|
|
'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b'
|
|
],
|
|
[
|
|
'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252',
|
|
'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2'
|
|
],
|
|
[
|
|
'4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5',
|
|
'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c'
|
|
],
|
|
[
|
|
'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b',
|
|
'6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3'
|
|
],
|
|
[
|
|
'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4',
|
|
'322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d'
|
|
],
|
|
[
|
|
'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f',
|
|
'6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700'
|
|
],
|
|
[
|
|
'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889',
|
|
'2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4'
|
|
],
|
|
[
|
|
'591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246',
|
|
'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196'
|
|
],
|
|
[
|
|
'11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984',
|
|
'998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4'
|
|
],
|
|
[
|
|
'3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a',
|
|
'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257'
|
|
],
|
|
[
|
|
'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030',
|
|
'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13'
|
|
],
|
|
[
|
|
'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197',
|
|
'6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096'
|
|
],
|
|
[
|
|
'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593',
|
|
'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38'
|
|
],
|
|
[
|
|
'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef',
|
|
'21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f'
|
|
],
|
|
[
|
|
'347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38',
|
|
'60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448'
|
|
],
|
|
[
|
|
'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a',
|
|
'49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a'
|
|
],
|
|
[
|
|
'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111',
|
|
'5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4'
|
|
],
|
|
[
|
|
'4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502',
|
|
'7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437'
|
|
],
|
|
[
|
|
'3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea',
|
|
'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7'
|
|
],
|
|
[
|
|
'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26',
|
|
'8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d'
|
|
],
|
|
[
|
|
'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986',
|
|
'39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a'
|
|
],
|
|
[
|
|
'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e',
|
|
'62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54'
|
|
],
|
|
[
|
|
'48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4',
|
|
'25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77'
|
|
],
|
|
[
|
|
'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda',
|
|
'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517'
|
|
],
|
|
[
|
|
'6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859',
|
|
'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10'
|
|
],
|
|
[
|
|
'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f',
|
|
'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125'
|
|
],
|
|
[
|
|
'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c',
|
|
'6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e'
|
|
],
|
|
[
|
|
'13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942',
|
|
'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1'
|
|
],
|
|
[
|
|
'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a',
|
|
'1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2'
|
|
],
|
|
[
|
|
'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80',
|
|
'5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423'
|
|
],
|
|
[
|
|
'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d',
|
|
'438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8'
|
|
],
|
|
[
|
|
'8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1',
|
|
'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758'
|
|
],
|
|
[
|
|
'52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63',
|
|
'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375'
|
|
],
|
|
[
|
|
'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352',
|
|
'6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d'
|
|
],
|
|
[
|
|
'7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193',
|
|
'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec'
|
|
],
|
|
[
|
|
'5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00',
|
|
'9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0'
|
|
],
|
|
[
|
|
'32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58',
|
|
'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c'
|
|
],
|
|
[
|
|
'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7',
|
|
'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4'
|
|
],
|
|
[
|
|
'8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8',
|
|
'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f'
|
|
],
|
|
[
|
|
'4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e',
|
|
'67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649'
|
|
],
|
|
[
|
|
'3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d',
|
|
'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826'
|
|
],
|
|
[
|
|
'674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b',
|
|
'299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5'
|
|
],
|
|
[
|
|
'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f',
|
|
'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87'
|
|
],
|
|
[
|
|
'30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6',
|
|
'462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b'
|
|
],
|
|
[
|
|
'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297',
|
|
'62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc'
|
|
],
|
|
[
|
|
'93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a',
|
|
'7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c'
|
|
],
|
|
[
|
|
'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c',
|
|
'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f'
|
|
],
|
|
[
|
|
'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52',
|
|
'4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a'
|
|
],
|
|
[
|
|
'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb',
|
|
'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46'
|
|
],
|
|
[
|
|
'463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065',
|
|
'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f'
|
|
],
|
|
[
|
|
'7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917',
|
|
'603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03'
|
|
],
|
|
[
|
|
'74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9',
|
|
'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08'
|
|
],
|
|
[
|
|
'30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3',
|
|
'553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8'
|
|
],
|
|
[
|
|
'9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57',
|
|
'712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373'
|
|
],
|
|
[
|
|
'176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66',
|
|
'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3'
|
|
],
|
|
[
|
|
'75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8',
|
|
'9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8'
|
|
],
|
|
[
|
|
'809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721',
|
|
'9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1'
|
|
],
|
|
[
|
|
'1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180',
|
|
'4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9'
|
|
]
|
|
]
|
|
}
|
|
};
|
|
|
|
},{}],299:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = exports;
|
|
var BN = require('bn.js');
|
|
var minAssert = require('minimalistic-assert');
|
|
var minUtils = require('minimalistic-crypto-utils');
|
|
|
|
utils.assert = minAssert;
|
|
utils.toArray = minUtils.toArray;
|
|
utils.zero2 = minUtils.zero2;
|
|
utils.toHex = minUtils.toHex;
|
|
utils.encode = minUtils.encode;
|
|
|
|
// Represent num in a w-NAF form
|
|
function getNAF(num, w) {
|
|
var naf = [];
|
|
var ws = 1 << (w + 1);
|
|
var k = num.clone();
|
|
while (k.cmpn(1) >= 0) {
|
|
var z;
|
|
if (k.isOdd()) {
|
|
var mod = k.andln(ws - 1);
|
|
if (mod > (ws >> 1) - 1)
|
|
z = (ws >> 1) - mod;
|
|
else
|
|
z = mod;
|
|
k.isubn(z);
|
|
} else {
|
|
z = 0;
|
|
}
|
|
naf.push(z);
|
|
|
|
// Optimization, shift by word if possible
|
|
var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1;
|
|
for (var i = 1; i < shift; i++)
|
|
naf.push(0);
|
|
k.iushrn(shift);
|
|
}
|
|
|
|
return naf;
|
|
}
|
|
utils.getNAF = getNAF;
|
|
|
|
// Represent k1, k2 in a Joint Sparse Form
|
|
function getJSF(k1, k2) {
|
|
var jsf = [
|
|
[],
|
|
[]
|
|
];
|
|
|
|
k1 = k1.clone();
|
|
k2 = k2.clone();
|
|
var d1 = 0;
|
|
var d2 = 0;
|
|
while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) {
|
|
|
|
// First phase
|
|
var m14 = (k1.andln(3) + d1) & 3;
|
|
var m24 = (k2.andln(3) + d2) & 3;
|
|
if (m14 === 3)
|
|
m14 = -1;
|
|
if (m24 === 3)
|
|
m24 = -1;
|
|
var u1;
|
|
if ((m14 & 1) === 0) {
|
|
u1 = 0;
|
|
} else {
|
|
var m8 = (k1.andln(7) + d1) & 7;
|
|
if ((m8 === 3 || m8 === 5) && m24 === 2)
|
|
u1 = -m14;
|
|
else
|
|
u1 = m14;
|
|
}
|
|
jsf[0].push(u1);
|
|
|
|
var u2;
|
|
if ((m24 & 1) === 0) {
|
|
u2 = 0;
|
|
} else {
|
|
var m8 = (k2.andln(7) + d2) & 7;
|
|
if ((m8 === 3 || m8 === 5) && m14 === 2)
|
|
u2 = -m24;
|
|
else
|
|
u2 = m24;
|
|
}
|
|
jsf[1].push(u2);
|
|
|
|
// Second phase
|
|
if (2 * d1 === u1 + 1)
|
|
d1 = 1 - d1;
|
|
if (2 * d2 === u2 + 1)
|
|
d2 = 1 - d2;
|
|
k1.iushrn(1);
|
|
k2.iushrn(1);
|
|
}
|
|
|
|
return jsf;
|
|
}
|
|
utils.getJSF = getJSF;
|
|
|
|
function cachedProperty(obj, name, computer) {
|
|
var key = '_' + name;
|
|
obj.prototype[name] = function cachedProperty() {
|
|
return this[key] !== undefined ? this[key] :
|
|
this[key] = computer.call(this);
|
|
};
|
|
}
|
|
utils.cachedProperty = cachedProperty;
|
|
|
|
function parseBytes(bytes) {
|
|
return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') :
|
|
bytes;
|
|
}
|
|
utils.parseBytes = parseBytes;
|
|
|
|
function intFromLE(bytes) {
|
|
return new BN(bytes, 'hex', 'le');
|
|
}
|
|
utils.intFromLE = intFromLE;
|
|
|
|
|
|
},{"bn.js":280,"minimalistic-assert":315,"minimalistic-crypto-utils":316}],300:[function(require,module,exports){
|
|
arguments[4][175][0].apply(exports,arguments)
|
|
},{"crypto":46,"dup":175}],301:[function(require,module,exports){
|
|
var hash = exports;
|
|
|
|
hash.utils = require('./hash/utils');
|
|
hash.common = require('./hash/common');
|
|
hash.sha = require('./hash/sha');
|
|
hash.ripemd = require('./hash/ripemd');
|
|
hash.hmac = require('./hash/hmac');
|
|
|
|
// Proxy hash functions to the main object
|
|
hash.sha1 = hash.sha.sha1;
|
|
hash.sha256 = hash.sha.sha256;
|
|
hash.sha224 = hash.sha.sha224;
|
|
hash.sha384 = hash.sha.sha384;
|
|
hash.sha512 = hash.sha.sha512;
|
|
hash.ripemd160 = hash.ripemd.ripemd160;
|
|
|
|
},{"./hash/common":302,"./hash/hmac":303,"./hash/ripemd":304,"./hash/sha":305,"./hash/utils":312}],302:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = require('./utils');
|
|
var assert = require('minimalistic-assert');
|
|
|
|
function BlockHash() {
|
|
this.pending = null;
|
|
this.pendingTotal = 0;
|
|
this.blockSize = this.constructor.blockSize;
|
|
this.outSize = this.constructor.outSize;
|
|
this.hmacStrength = this.constructor.hmacStrength;
|
|
this.padLength = this.constructor.padLength / 8;
|
|
this.endian = 'big';
|
|
|
|
this._delta8 = this.blockSize / 8;
|
|
this._delta32 = this.blockSize / 32;
|
|
}
|
|
exports.BlockHash = BlockHash;
|
|
|
|
BlockHash.prototype.update = function update(msg, enc) {
|
|
// Convert message to array, pad it, and join into 32bit blocks
|
|
msg = utils.toArray(msg, enc);
|
|
if (!this.pending)
|
|
this.pending = msg;
|
|
else
|
|
this.pending = this.pending.concat(msg);
|
|
this.pendingTotal += msg.length;
|
|
|
|
// Enough data, try updating
|
|
if (this.pending.length >= this._delta8) {
|
|
msg = this.pending;
|
|
|
|
// Process pending data in blocks
|
|
var r = msg.length % this._delta8;
|
|
this.pending = msg.slice(msg.length - r, msg.length);
|
|
if (this.pending.length === 0)
|
|
this.pending = null;
|
|
|
|
msg = utils.join32(msg, 0, msg.length - r, this.endian);
|
|
for (var i = 0; i < msg.length; i += this._delta32)
|
|
this._update(msg, i, i + this._delta32);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
BlockHash.prototype.digest = function digest(enc) {
|
|
this.update(this._pad());
|
|
assert(this.pending === null);
|
|
|
|
return this._digest(enc);
|
|
};
|
|
|
|
BlockHash.prototype._pad = function pad() {
|
|
var len = this.pendingTotal;
|
|
var bytes = this._delta8;
|
|
var k = bytes - ((len + this.padLength) % bytes);
|
|
var res = new Array(k + this.padLength);
|
|
res[0] = 0x80;
|
|
for (var i = 1; i < k; i++)
|
|
res[i] = 0;
|
|
|
|
// Append length
|
|
len <<= 3;
|
|
if (this.endian === 'big') {
|
|
for (var t = 8; t < this.padLength; t++)
|
|
res[i++] = 0;
|
|
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
res[i++] = (len >>> 24) & 0xff;
|
|
res[i++] = (len >>> 16) & 0xff;
|
|
res[i++] = (len >>> 8) & 0xff;
|
|
res[i++] = len & 0xff;
|
|
} else {
|
|
res[i++] = len & 0xff;
|
|
res[i++] = (len >>> 8) & 0xff;
|
|
res[i++] = (len >>> 16) & 0xff;
|
|
res[i++] = (len >>> 24) & 0xff;
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
res[i++] = 0;
|
|
|
|
for (t = 8; t < this.padLength; t++)
|
|
res[i++] = 0;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
},{"./utils":312,"minimalistic-assert":315}],303:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = require('./utils');
|
|
var assert = require('minimalistic-assert');
|
|
|
|
function Hmac(hash, key, enc) {
|
|
if (!(this instanceof Hmac))
|
|
return new Hmac(hash, key, enc);
|
|
this.Hash = hash;
|
|
this.blockSize = hash.blockSize / 8;
|
|
this.outSize = hash.outSize / 8;
|
|
this.inner = null;
|
|
this.outer = null;
|
|
|
|
this._init(utils.toArray(key, enc));
|
|
}
|
|
module.exports = Hmac;
|
|
|
|
Hmac.prototype._init = function init(key) {
|
|
// Shorten key, if needed
|
|
if (key.length > this.blockSize)
|
|
key = new this.Hash().update(key).digest();
|
|
assert(key.length <= this.blockSize);
|
|
|
|
// Add padding to key
|
|
for (var i = key.length; i < this.blockSize; i++)
|
|
key.push(0);
|
|
|
|
for (i = 0; i < key.length; i++)
|
|
key[i] ^= 0x36;
|
|
this.inner = new this.Hash().update(key);
|
|
|
|
// 0x36 ^ 0x5c = 0x6a
|
|
for (i = 0; i < key.length; i++)
|
|
key[i] ^= 0x6a;
|
|
this.outer = new this.Hash().update(key);
|
|
};
|
|
|
|
Hmac.prototype.update = function update(msg, enc) {
|
|
this.inner.update(msg, enc);
|
|
return this;
|
|
};
|
|
|
|
Hmac.prototype.digest = function digest(enc) {
|
|
this.outer.update(this.inner.digest());
|
|
return this.outer.digest(enc);
|
|
};
|
|
|
|
},{"./utils":312,"minimalistic-assert":315}],304:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = require('./utils');
|
|
var common = require('./common');
|
|
|
|
var rotl32 = utils.rotl32;
|
|
var sum32 = utils.sum32;
|
|
var sum32_3 = utils.sum32_3;
|
|
var sum32_4 = utils.sum32_4;
|
|
var BlockHash = common.BlockHash;
|
|
|
|
function RIPEMD160() {
|
|
if (!(this instanceof RIPEMD160))
|
|
return new RIPEMD160();
|
|
|
|
BlockHash.call(this);
|
|
|
|
this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ];
|
|
this.endian = 'little';
|
|
}
|
|
utils.inherits(RIPEMD160, BlockHash);
|
|
exports.ripemd160 = RIPEMD160;
|
|
|
|
RIPEMD160.blockSize = 512;
|
|
RIPEMD160.outSize = 160;
|
|
RIPEMD160.hmacStrength = 192;
|
|
RIPEMD160.padLength = 64;
|
|
|
|
RIPEMD160.prototype._update = function update(msg, start) {
|
|
var A = this.h[0];
|
|
var B = this.h[1];
|
|
var C = this.h[2];
|
|
var D = this.h[3];
|
|
var E = this.h[4];
|
|
var Ah = A;
|
|
var Bh = B;
|
|
var Ch = C;
|
|
var Dh = D;
|
|
var Eh = E;
|
|
for (var j = 0; j < 80; j++) {
|
|
var T = sum32(
|
|
rotl32(
|
|
sum32_4(A, f(j, B, C, D), msg[r[j] + start], K(j)),
|
|
s[j]),
|
|
E);
|
|
A = E;
|
|
E = D;
|
|
D = rotl32(C, 10);
|
|
C = B;
|
|
B = T;
|
|
T = sum32(
|
|
rotl32(
|
|
sum32_4(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)),
|
|
sh[j]),
|
|
Eh);
|
|
Ah = Eh;
|
|
Eh = Dh;
|
|
Dh = rotl32(Ch, 10);
|
|
Ch = Bh;
|
|
Bh = T;
|
|
}
|
|
T = sum32_3(this.h[1], C, Dh);
|
|
this.h[1] = sum32_3(this.h[2], D, Eh);
|
|
this.h[2] = sum32_3(this.h[3], E, Ah);
|
|
this.h[3] = sum32_3(this.h[4], A, Bh);
|
|
this.h[4] = sum32_3(this.h[0], B, Ch);
|
|
this.h[0] = T;
|
|
};
|
|
|
|
RIPEMD160.prototype._digest = function digest(enc) {
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h, 'little');
|
|
else
|
|
return utils.split32(this.h, 'little');
|
|
};
|
|
|
|
function f(j, x, y, z) {
|
|
if (j <= 15)
|
|
return x ^ y ^ z;
|
|
else if (j <= 31)
|
|
return (x & y) | ((~x) & z);
|
|
else if (j <= 47)
|
|
return (x | (~y)) ^ z;
|
|
else if (j <= 63)
|
|
return (x & z) | (y & (~z));
|
|
else
|
|
return x ^ (y | (~z));
|
|
}
|
|
|
|
function K(j) {
|
|
if (j <= 15)
|
|
return 0x00000000;
|
|
else if (j <= 31)
|
|
return 0x5a827999;
|
|
else if (j <= 47)
|
|
return 0x6ed9eba1;
|
|
else if (j <= 63)
|
|
return 0x8f1bbcdc;
|
|
else
|
|
return 0xa953fd4e;
|
|
}
|
|
|
|
function Kh(j) {
|
|
if (j <= 15)
|
|
return 0x50a28be6;
|
|
else if (j <= 31)
|
|
return 0x5c4dd124;
|
|
else if (j <= 47)
|
|
return 0x6d703ef3;
|
|
else if (j <= 63)
|
|
return 0x7a6d76e9;
|
|
else
|
|
return 0x00000000;
|
|
}
|
|
|
|
var r = [
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
|
|
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
|
|
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
|
|
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
|
|
];
|
|
|
|
var rh = [
|
|
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
|
|
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
|
|
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
|
|
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
|
|
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
|
|
];
|
|
|
|
var s = [
|
|
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
|
|
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
|
|
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
|
|
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
|
|
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
|
|
];
|
|
|
|
var sh = [
|
|
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
|
|
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
|
|
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
|
|
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
|
|
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
|
|
];
|
|
|
|
},{"./common":302,"./utils":312}],305:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
exports.sha1 = require('./sha/1');
|
|
exports.sha224 = require('./sha/224');
|
|
exports.sha256 = require('./sha/256');
|
|
exports.sha384 = require('./sha/384');
|
|
exports.sha512 = require('./sha/512');
|
|
|
|
},{"./sha/1":306,"./sha/224":307,"./sha/256":308,"./sha/384":309,"./sha/512":310}],306:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = require('../utils');
|
|
var common = require('../common');
|
|
var shaCommon = require('./common');
|
|
|
|
var rotl32 = utils.rotl32;
|
|
var sum32 = utils.sum32;
|
|
var sum32_5 = utils.sum32_5;
|
|
var ft_1 = shaCommon.ft_1;
|
|
var BlockHash = common.BlockHash;
|
|
|
|
var sha1_K = [
|
|
0x5A827999, 0x6ED9EBA1,
|
|
0x8F1BBCDC, 0xCA62C1D6
|
|
];
|
|
|
|
function SHA1() {
|
|
if (!(this instanceof SHA1))
|
|
return new SHA1();
|
|
|
|
BlockHash.call(this);
|
|
this.h = [
|
|
0x67452301, 0xefcdab89, 0x98badcfe,
|
|
0x10325476, 0xc3d2e1f0 ];
|
|
this.W = new Array(80);
|
|
}
|
|
|
|
utils.inherits(SHA1, BlockHash);
|
|
module.exports = SHA1;
|
|
|
|
SHA1.blockSize = 512;
|
|
SHA1.outSize = 160;
|
|
SHA1.hmacStrength = 80;
|
|
SHA1.padLength = 64;
|
|
|
|
SHA1.prototype._update = function _update(msg, start) {
|
|
var W = this.W;
|
|
|
|
for (var i = 0; i < 16; i++)
|
|
W[i] = msg[start + i];
|
|
|
|
for(; i < W.length; i++)
|
|
W[i] = rotl32(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
|
|
|
|
var a = this.h[0];
|
|
var b = this.h[1];
|
|
var c = this.h[2];
|
|
var d = this.h[3];
|
|
var e = this.h[4];
|
|
|
|
for (i = 0; i < W.length; i++) {
|
|
var s = ~~(i / 20);
|
|
var t = sum32_5(rotl32(a, 5), ft_1(s, b, c, d), e, W[i], sha1_K[s]);
|
|
e = d;
|
|
d = c;
|
|
c = rotl32(b, 30);
|
|
b = a;
|
|
a = t;
|
|
}
|
|
|
|
this.h[0] = sum32(this.h[0], a);
|
|
this.h[1] = sum32(this.h[1], b);
|
|
this.h[2] = sum32(this.h[2], c);
|
|
this.h[3] = sum32(this.h[3], d);
|
|
this.h[4] = sum32(this.h[4], e);
|
|
};
|
|
|
|
SHA1.prototype._digest = function digest(enc) {
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h, 'big');
|
|
else
|
|
return utils.split32(this.h, 'big');
|
|
};
|
|
|
|
},{"../common":302,"../utils":312,"./common":311}],307:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = require('../utils');
|
|
var SHA256 = require('./256');
|
|
|
|
function SHA224() {
|
|
if (!(this instanceof SHA224))
|
|
return new SHA224();
|
|
|
|
SHA256.call(this);
|
|
this.h = [
|
|
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
|
|
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ];
|
|
}
|
|
utils.inherits(SHA224, SHA256);
|
|
module.exports = SHA224;
|
|
|
|
SHA224.blockSize = 512;
|
|
SHA224.outSize = 224;
|
|
SHA224.hmacStrength = 192;
|
|
SHA224.padLength = 64;
|
|
|
|
SHA224.prototype._digest = function digest(enc) {
|
|
// Just truncate output
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h.slice(0, 7), 'big');
|
|
else
|
|
return utils.split32(this.h.slice(0, 7), 'big');
|
|
};
|
|
|
|
|
|
},{"../utils":312,"./256":308}],308:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = require('../utils');
|
|
var common = require('../common');
|
|
var shaCommon = require('./common');
|
|
var assert = require('minimalistic-assert');
|
|
|
|
var sum32 = utils.sum32;
|
|
var sum32_4 = utils.sum32_4;
|
|
var sum32_5 = utils.sum32_5;
|
|
var ch32 = shaCommon.ch32;
|
|
var maj32 = shaCommon.maj32;
|
|
var s0_256 = shaCommon.s0_256;
|
|
var s1_256 = shaCommon.s1_256;
|
|
var g0_256 = shaCommon.g0_256;
|
|
var g1_256 = shaCommon.g1_256;
|
|
|
|
var BlockHash = common.BlockHash;
|
|
|
|
var sha256_K = [
|
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
|
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
|
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
|
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
|
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
|
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
];
|
|
|
|
function SHA256() {
|
|
if (!(this instanceof SHA256))
|
|
return new SHA256();
|
|
|
|
BlockHash.call(this);
|
|
this.h = [
|
|
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
|
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
|
];
|
|
this.k = sha256_K;
|
|
this.W = new Array(64);
|
|
}
|
|
utils.inherits(SHA256, BlockHash);
|
|
module.exports = SHA256;
|
|
|
|
SHA256.blockSize = 512;
|
|
SHA256.outSize = 256;
|
|
SHA256.hmacStrength = 192;
|
|
SHA256.padLength = 64;
|
|
|
|
SHA256.prototype._update = function _update(msg, start) {
|
|
var W = this.W;
|
|
|
|
for (var i = 0; i < 16; i++)
|
|
W[i] = msg[start + i];
|
|
for (; i < W.length; i++)
|
|
W[i] = sum32_4(g1_256(W[i - 2]), W[i - 7], g0_256(W[i - 15]), W[i - 16]);
|
|
|
|
var a = this.h[0];
|
|
var b = this.h[1];
|
|
var c = this.h[2];
|
|
var d = this.h[3];
|
|
var e = this.h[4];
|
|
var f = this.h[5];
|
|
var g = this.h[6];
|
|
var h = this.h[7];
|
|
|
|
assert(this.k.length === W.length);
|
|
for (i = 0; i < W.length; i++) {
|
|
var T1 = sum32_5(h, s1_256(e), ch32(e, f, g), this.k[i], W[i]);
|
|
var T2 = sum32(s0_256(a), maj32(a, b, c));
|
|
h = g;
|
|
g = f;
|
|
f = e;
|
|
e = sum32(d, T1);
|
|
d = c;
|
|
c = b;
|
|
b = a;
|
|
a = sum32(T1, T2);
|
|
}
|
|
|
|
this.h[0] = sum32(this.h[0], a);
|
|
this.h[1] = sum32(this.h[1], b);
|
|
this.h[2] = sum32(this.h[2], c);
|
|
this.h[3] = sum32(this.h[3], d);
|
|
this.h[4] = sum32(this.h[4], e);
|
|
this.h[5] = sum32(this.h[5], f);
|
|
this.h[6] = sum32(this.h[6], g);
|
|
this.h[7] = sum32(this.h[7], h);
|
|
};
|
|
|
|
SHA256.prototype._digest = function digest(enc) {
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h, 'big');
|
|
else
|
|
return utils.split32(this.h, 'big');
|
|
};
|
|
|
|
},{"../common":302,"../utils":312,"./common":311,"minimalistic-assert":315}],309:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = require('../utils');
|
|
|
|
var SHA512 = require('./512');
|
|
|
|
function SHA384() {
|
|
if (!(this instanceof SHA384))
|
|
return new SHA384();
|
|
|
|
SHA512.call(this);
|
|
this.h = [
|
|
0xcbbb9d5d, 0xc1059ed8,
|
|
0x629a292a, 0x367cd507,
|
|
0x9159015a, 0x3070dd17,
|
|
0x152fecd8, 0xf70e5939,
|
|
0x67332667, 0xffc00b31,
|
|
0x8eb44a87, 0x68581511,
|
|
0xdb0c2e0d, 0x64f98fa7,
|
|
0x47b5481d, 0xbefa4fa4 ];
|
|
}
|
|
utils.inherits(SHA384, SHA512);
|
|
module.exports = SHA384;
|
|
|
|
SHA384.blockSize = 1024;
|
|
SHA384.outSize = 384;
|
|
SHA384.hmacStrength = 192;
|
|
SHA384.padLength = 128;
|
|
|
|
SHA384.prototype._digest = function digest(enc) {
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h.slice(0, 12), 'big');
|
|
else
|
|
return utils.split32(this.h.slice(0, 12), 'big');
|
|
};
|
|
|
|
},{"../utils":312,"./512":310}],310:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = require('../utils');
|
|
var common = require('../common');
|
|
var assert = require('minimalistic-assert');
|
|
|
|
var rotr64_hi = utils.rotr64_hi;
|
|
var rotr64_lo = utils.rotr64_lo;
|
|
var shr64_hi = utils.shr64_hi;
|
|
var shr64_lo = utils.shr64_lo;
|
|
var sum64 = utils.sum64;
|
|
var sum64_hi = utils.sum64_hi;
|
|
var sum64_lo = utils.sum64_lo;
|
|
var sum64_4_hi = utils.sum64_4_hi;
|
|
var sum64_4_lo = utils.sum64_4_lo;
|
|
var sum64_5_hi = utils.sum64_5_hi;
|
|
var sum64_5_lo = utils.sum64_5_lo;
|
|
|
|
var BlockHash = common.BlockHash;
|
|
|
|
var sha512_K = [
|
|
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
|
|
0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
|
|
0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
|
|
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
|
|
0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
|
|
0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
|
|
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
|
|
0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
|
|
0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
|
|
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
|
|
0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
|
|
0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
|
|
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
|
|
0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
|
|
0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
|
|
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
|
|
0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
|
|
0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
|
|
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
|
|
0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
|
|
0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
|
|
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
|
|
0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
|
|
0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
|
|
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
|
|
0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
|
|
0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
|
|
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
|
|
0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
|
|
0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
|
|
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
|
|
0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
|
|
0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
|
|
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
|
|
0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
|
|
0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
|
|
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
|
|
0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
|
|
0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
|
|
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
|
|
];
|
|
|
|
function SHA512() {
|
|
if (!(this instanceof SHA512))
|
|
return new SHA512();
|
|
|
|
BlockHash.call(this);
|
|
this.h = [
|
|
0x6a09e667, 0xf3bcc908,
|
|
0xbb67ae85, 0x84caa73b,
|
|
0x3c6ef372, 0xfe94f82b,
|
|
0xa54ff53a, 0x5f1d36f1,
|
|
0x510e527f, 0xade682d1,
|
|
0x9b05688c, 0x2b3e6c1f,
|
|
0x1f83d9ab, 0xfb41bd6b,
|
|
0x5be0cd19, 0x137e2179 ];
|
|
this.k = sha512_K;
|
|
this.W = new Array(160);
|
|
}
|
|
utils.inherits(SHA512, BlockHash);
|
|
module.exports = SHA512;
|
|
|
|
SHA512.blockSize = 1024;
|
|
SHA512.outSize = 512;
|
|
SHA512.hmacStrength = 192;
|
|
SHA512.padLength = 128;
|
|
|
|
SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) {
|
|
var W = this.W;
|
|
|
|
// 32 x 32bit words
|
|
for (var i = 0; i < 32; i++)
|
|
W[i] = msg[start + i];
|
|
for (; i < W.length; i += 2) {
|
|
var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2
|
|
var c0_lo = g1_512_lo(W[i - 4], W[i - 3]);
|
|
var c1_hi = W[i - 14]; // i - 7
|
|
var c1_lo = W[i - 13];
|
|
var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15
|
|
var c2_lo = g0_512_lo(W[i - 30], W[i - 29]);
|
|
var c3_hi = W[i - 32]; // i - 16
|
|
var c3_lo = W[i - 31];
|
|
|
|
W[i] = sum64_4_hi(
|
|
c0_hi, c0_lo,
|
|
c1_hi, c1_lo,
|
|
c2_hi, c2_lo,
|
|
c3_hi, c3_lo);
|
|
W[i + 1] = sum64_4_lo(
|
|
c0_hi, c0_lo,
|
|
c1_hi, c1_lo,
|
|
c2_hi, c2_lo,
|
|
c3_hi, c3_lo);
|
|
}
|
|
};
|
|
|
|
SHA512.prototype._update = function _update(msg, start) {
|
|
this._prepareBlock(msg, start);
|
|
|
|
var W = this.W;
|
|
|
|
var ah = this.h[0];
|
|
var al = this.h[1];
|
|
var bh = this.h[2];
|
|
var bl = this.h[3];
|
|
var ch = this.h[4];
|
|
var cl = this.h[5];
|
|
var dh = this.h[6];
|
|
var dl = this.h[7];
|
|
var eh = this.h[8];
|
|
var el = this.h[9];
|
|
var fh = this.h[10];
|
|
var fl = this.h[11];
|
|
var gh = this.h[12];
|
|
var gl = this.h[13];
|
|
var hh = this.h[14];
|
|
var hl = this.h[15];
|
|
|
|
assert(this.k.length === W.length);
|
|
for (var i = 0; i < W.length; i += 2) {
|
|
var c0_hi = hh;
|
|
var c0_lo = hl;
|
|
var c1_hi = s1_512_hi(eh, el);
|
|
var c1_lo = s1_512_lo(eh, el);
|
|
var c2_hi = ch64_hi(eh, el, fh, fl, gh, gl);
|
|
var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl);
|
|
var c3_hi = this.k[i];
|
|
var c3_lo = this.k[i + 1];
|
|
var c4_hi = W[i];
|
|
var c4_lo = W[i + 1];
|
|
|
|
var T1_hi = sum64_5_hi(
|
|
c0_hi, c0_lo,
|
|
c1_hi, c1_lo,
|
|
c2_hi, c2_lo,
|
|
c3_hi, c3_lo,
|
|
c4_hi, c4_lo);
|
|
var T1_lo = sum64_5_lo(
|
|
c0_hi, c0_lo,
|
|
c1_hi, c1_lo,
|
|
c2_hi, c2_lo,
|
|
c3_hi, c3_lo,
|
|
c4_hi, c4_lo);
|
|
|
|
c0_hi = s0_512_hi(ah, al);
|
|
c0_lo = s0_512_lo(ah, al);
|
|
c1_hi = maj64_hi(ah, al, bh, bl, ch, cl);
|
|
c1_lo = maj64_lo(ah, al, bh, bl, ch, cl);
|
|
|
|
var T2_hi = sum64_hi(c0_hi, c0_lo, c1_hi, c1_lo);
|
|
var T2_lo = sum64_lo(c0_hi, c0_lo, c1_hi, c1_lo);
|
|
|
|
hh = gh;
|
|
hl = gl;
|
|
|
|
gh = fh;
|
|
gl = fl;
|
|
|
|
fh = eh;
|
|
fl = el;
|
|
|
|
eh = sum64_hi(dh, dl, T1_hi, T1_lo);
|
|
el = sum64_lo(dl, dl, T1_hi, T1_lo);
|
|
|
|
dh = ch;
|
|
dl = cl;
|
|
|
|
ch = bh;
|
|
cl = bl;
|
|
|
|
bh = ah;
|
|
bl = al;
|
|
|
|
ah = sum64_hi(T1_hi, T1_lo, T2_hi, T2_lo);
|
|
al = sum64_lo(T1_hi, T1_lo, T2_hi, T2_lo);
|
|
}
|
|
|
|
sum64(this.h, 0, ah, al);
|
|
sum64(this.h, 2, bh, bl);
|
|
sum64(this.h, 4, ch, cl);
|
|
sum64(this.h, 6, dh, dl);
|
|
sum64(this.h, 8, eh, el);
|
|
sum64(this.h, 10, fh, fl);
|
|
sum64(this.h, 12, gh, gl);
|
|
sum64(this.h, 14, hh, hl);
|
|
};
|
|
|
|
SHA512.prototype._digest = function digest(enc) {
|
|
if (enc === 'hex')
|
|
return utils.toHex32(this.h, 'big');
|
|
else
|
|
return utils.split32(this.h, 'big');
|
|
};
|
|
|
|
function ch64_hi(xh, xl, yh, yl, zh) {
|
|
var r = (xh & yh) ^ ((~xh) & zh);
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function ch64_lo(xh, xl, yh, yl, zh, zl) {
|
|
var r = (xl & yl) ^ ((~xl) & zl);
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function maj64_hi(xh, xl, yh, yl, zh) {
|
|
var r = (xh & yh) ^ (xh & zh) ^ (yh & zh);
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function maj64_lo(xh, xl, yh, yl, zh, zl) {
|
|
var r = (xl & yl) ^ (xl & zl) ^ (yl & zl);
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function s0_512_hi(xh, xl) {
|
|
var c0_hi = rotr64_hi(xh, xl, 28);
|
|
var c1_hi = rotr64_hi(xl, xh, 2); // 34
|
|
var c2_hi = rotr64_hi(xl, xh, 7); // 39
|
|
|
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function s0_512_lo(xh, xl) {
|
|
var c0_lo = rotr64_lo(xh, xl, 28);
|
|
var c1_lo = rotr64_lo(xl, xh, 2); // 34
|
|
var c2_lo = rotr64_lo(xl, xh, 7); // 39
|
|
|
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function s1_512_hi(xh, xl) {
|
|
var c0_hi = rotr64_hi(xh, xl, 14);
|
|
var c1_hi = rotr64_hi(xh, xl, 18);
|
|
var c2_hi = rotr64_hi(xl, xh, 9); // 41
|
|
|
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function s1_512_lo(xh, xl) {
|
|
var c0_lo = rotr64_lo(xh, xl, 14);
|
|
var c1_lo = rotr64_lo(xh, xl, 18);
|
|
var c2_lo = rotr64_lo(xl, xh, 9); // 41
|
|
|
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function g0_512_hi(xh, xl) {
|
|
var c0_hi = rotr64_hi(xh, xl, 1);
|
|
var c1_hi = rotr64_hi(xh, xl, 8);
|
|
var c2_hi = shr64_hi(xh, xl, 7);
|
|
|
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function g0_512_lo(xh, xl) {
|
|
var c0_lo = rotr64_lo(xh, xl, 1);
|
|
var c1_lo = rotr64_lo(xh, xl, 8);
|
|
var c2_lo = shr64_lo(xh, xl, 7);
|
|
|
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function g1_512_hi(xh, xl) {
|
|
var c0_hi = rotr64_hi(xh, xl, 19);
|
|
var c1_hi = rotr64_hi(xl, xh, 29); // 61
|
|
var c2_hi = shr64_hi(xh, xl, 6);
|
|
|
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
function g1_512_lo(xh, xl) {
|
|
var c0_lo = rotr64_lo(xh, xl, 19);
|
|
var c1_lo = rotr64_lo(xl, xh, 29); // 61
|
|
var c2_lo = shr64_lo(xh, xl, 6);
|
|
|
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
|
if (r < 0)
|
|
r += 0x100000000;
|
|
return r;
|
|
}
|
|
|
|
},{"../common":302,"../utils":312,"minimalistic-assert":315}],311:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = require('../utils');
|
|
var rotr32 = utils.rotr32;
|
|
|
|
function ft_1(s, x, y, z) {
|
|
if (s === 0)
|
|
return ch32(x, y, z);
|
|
if (s === 1 || s === 3)
|
|
return p32(x, y, z);
|
|
if (s === 2)
|
|
return maj32(x, y, z);
|
|
}
|
|
exports.ft_1 = ft_1;
|
|
|
|
function ch32(x, y, z) {
|
|
return (x & y) ^ ((~x) & z);
|
|
}
|
|
exports.ch32 = ch32;
|
|
|
|
function maj32(x, y, z) {
|
|
return (x & y) ^ (x & z) ^ (y & z);
|
|
}
|
|
exports.maj32 = maj32;
|
|
|
|
function p32(x, y, z) {
|
|
return x ^ y ^ z;
|
|
}
|
|
exports.p32 = p32;
|
|
|
|
function s0_256(x) {
|
|
return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22);
|
|
}
|
|
exports.s0_256 = s0_256;
|
|
|
|
function s1_256(x) {
|
|
return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25);
|
|
}
|
|
exports.s1_256 = s1_256;
|
|
|
|
function g0_256(x) {
|
|
return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >>> 3);
|
|
}
|
|
exports.g0_256 = g0_256;
|
|
|
|
function g1_256(x) {
|
|
return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >>> 10);
|
|
}
|
|
exports.g1_256 = g1_256;
|
|
|
|
},{"../utils":312}],312:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var assert = require('minimalistic-assert');
|
|
var inherits = require('inherits');
|
|
|
|
exports.inherits = inherits;
|
|
|
|
function toArray(msg, enc) {
|
|
if (Array.isArray(msg))
|
|
return msg.slice();
|
|
if (!msg)
|
|
return [];
|
|
var res = [];
|
|
if (typeof msg === 'string') {
|
|
if (!enc) {
|
|
for (var i = 0; i < msg.length; i++) {
|
|
var c = msg.charCodeAt(i);
|
|
var hi = c >> 8;
|
|
var lo = c & 0xff;
|
|
if (hi)
|
|
res.push(hi, lo);
|
|
else
|
|
res.push(lo);
|
|
}
|
|
} else if (enc === 'hex') {
|
|
msg = msg.replace(/[^a-z0-9]+/ig, '');
|
|
if (msg.length % 2 !== 0)
|
|
msg = '0' + msg;
|
|
for (i = 0; i < msg.length; i += 2)
|
|
res.push(parseInt(msg[i] + msg[i + 1], 16));
|
|
}
|
|
} else {
|
|
for (i = 0; i < msg.length; i++)
|
|
res[i] = msg[i] | 0;
|
|
}
|
|
return res;
|
|
}
|
|
exports.toArray = toArray;
|
|
|
|
function toHex(msg) {
|
|
var res = '';
|
|
for (var i = 0; i < msg.length; i++)
|
|
res += zero2(msg[i].toString(16));
|
|
return res;
|
|
}
|
|
exports.toHex = toHex;
|
|
|
|
function htonl(w) {
|
|
var res = (w >>> 24) |
|
|
((w >>> 8) & 0xff00) |
|
|
((w << 8) & 0xff0000) |
|
|
((w & 0xff) << 24);
|
|
return res >>> 0;
|
|
}
|
|
exports.htonl = htonl;
|
|
|
|
function toHex32(msg, endian) {
|
|
var res = '';
|
|
for (var i = 0; i < msg.length; i++) {
|
|
var w = msg[i];
|
|
if (endian === 'little')
|
|
w = htonl(w);
|
|
res += zero8(w.toString(16));
|
|
}
|
|
return res;
|
|
}
|
|
exports.toHex32 = toHex32;
|
|
|
|
function zero2(word) {
|
|
if (word.length === 1)
|
|
return '0' + word;
|
|
else
|
|
return word;
|
|
}
|
|
exports.zero2 = zero2;
|
|
|
|
function zero8(word) {
|
|
if (word.length === 7)
|
|
return '0' + word;
|
|
else if (word.length === 6)
|
|
return '00' + word;
|
|
else if (word.length === 5)
|
|
return '000' + word;
|
|
else if (word.length === 4)
|
|
return '0000' + word;
|
|
else if (word.length === 3)
|
|
return '00000' + word;
|
|
else if (word.length === 2)
|
|
return '000000' + word;
|
|
else if (word.length === 1)
|
|
return '0000000' + word;
|
|
else
|
|
return word;
|
|
}
|
|
exports.zero8 = zero8;
|
|
|
|
function join32(msg, start, end, endian) {
|
|
var len = end - start;
|
|
assert(len % 4 === 0);
|
|
var res = new Array(len / 4);
|
|
for (var i = 0, k = start; i < res.length; i++, k += 4) {
|
|
var w;
|
|
if (endian === 'big')
|
|
w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3];
|
|
else
|
|
w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k];
|
|
res[i] = w >>> 0;
|
|
}
|
|
return res;
|
|
}
|
|
exports.join32 = join32;
|
|
|
|
function split32(msg, endian) {
|
|
var res = new Array(msg.length * 4);
|
|
for (var i = 0, k = 0; i < msg.length; i++, k += 4) {
|
|
var m = msg[i];
|
|
if (endian === 'big') {
|
|
res[k] = m >>> 24;
|
|
res[k + 1] = (m >>> 16) & 0xff;
|
|
res[k + 2] = (m >>> 8) & 0xff;
|
|
res[k + 3] = m & 0xff;
|
|
} else {
|
|
res[k + 3] = m >>> 24;
|
|
res[k + 2] = (m >>> 16) & 0xff;
|
|
res[k + 1] = (m >>> 8) & 0xff;
|
|
res[k] = m & 0xff;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
exports.split32 = split32;
|
|
|
|
function rotr32(w, b) {
|
|
return (w >>> b) | (w << (32 - b));
|
|
}
|
|
exports.rotr32 = rotr32;
|
|
|
|
function rotl32(w, b) {
|
|
return (w << b) | (w >>> (32 - b));
|
|
}
|
|
exports.rotl32 = rotl32;
|
|
|
|
function sum32(a, b) {
|
|
return (a + b) >>> 0;
|
|
}
|
|
exports.sum32 = sum32;
|
|
|
|
function sum32_3(a, b, c) {
|
|
return (a + b + c) >>> 0;
|
|
}
|
|
exports.sum32_3 = sum32_3;
|
|
|
|
function sum32_4(a, b, c, d) {
|
|
return (a + b + c + d) >>> 0;
|
|
}
|
|
exports.sum32_4 = sum32_4;
|
|
|
|
function sum32_5(a, b, c, d, e) {
|
|
return (a + b + c + d + e) >>> 0;
|
|
}
|
|
exports.sum32_5 = sum32_5;
|
|
|
|
function sum64(buf, pos, ah, al) {
|
|
var bh = buf[pos];
|
|
var bl = buf[pos + 1];
|
|
|
|
var lo = (al + bl) >>> 0;
|
|
var hi = (lo < al ? 1 : 0) + ah + bh;
|
|
buf[pos] = hi >>> 0;
|
|
buf[pos + 1] = lo;
|
|
}
|
|
exports.sum64 = sum64;
|
|
|
|
function sum64_hi(ah, al, bh, bl) {
|
|
var lo = (al + bl) >>> 0;
|
|
var hi = (lo < al ? 1 : 0) + ah + bh;
|
|
return hi >>> 0;
|
|
}
|
|
exports.sum64_hi = sum64_hi;
|
|
|
|
function sum64_lo(ah, al, bh, bl) {
|
|
var lo = al + bl;
|
|
return lo >>> 0;
|
|
}
|
|
exports.sum64_lo = sum64_lo;
|
|
|
|
function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) {
|
|
var carry = 0;
|
|
var lo = al;
|
|
lo = (lo + bl) >>> 0;
|
|
carry += lo < al ? 1 : 0;
|
|
lo = (lo + cl) >>> 0;
|
|
carry += lo < cl ? 1 : 0;
|
|
lo = (lo + dl) >>> 0;
|
|
carry += lo < dl ? 1 : 0;
|
|
|
|
var hi = ah + bh + ch + dh + carry;
|
|
return hi >>> 0;
|
|
}
|
|
exports.sum64_4_hi = sum64_4_hi;
|
|
|
|
function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) {
|
|
var lo = al + bl + cl + dl;
|
|
return lo >>> 0;
|
|
}
|
|
exports.sum64_4_lo = sum64_4_lo;
|
|
|
|
function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
|
|
var carry = 0;
|
|
var lo = al;
|
|
lo = (lo + bl) >>> 0;
|
|
carry += lo < al ? 1 : 0;
|
|
lo = (lo + cl) >>> 0;
|
|
carry += lo < cl ? 1 : 0;
|
|
lo = (lo + dl) >>> 0;
|
|
carry += lo < dl ? 1 : 0;
|
|
lo = (lo + el) >>> 0;
|
|
carry += lo < el ? 1 : 0;
|
|
|
|
var hi = ah + bh + ch + dh + eh + carry;
|
|
return hi >>> 0;
|
|
}
|
|
exports.sum64_5_hi = sum64_5_hi;
|
|
|
|
function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
|
|
var lo = al + bl + cl + dl + el;
|
|
|
|
return lo >>> 0;
|
|
}
|
|
exports.sum64_5_lo = sum64_5_lo;
|
|
|
|
function rotr64_hi(ah, al, num) {
|
|
var r = (al << (32 - num)) | (ah >>> num);
|
|
return r >>> 0;
|
|
}
|
|
exports.rotr64_hi = rotr64_hi;
|
|
|
|
function rotr64_lo(ah, al, num) {
|
|
var r = (ah << (32 - num)) | (al >>> num);
|
|
return r >>> 0;
|
|
}
|
|
exports.rotr64_lo = rotr64_lo;
|
|
|
|
function shr64_hi(ah, al, num) {
|
|
return ah >>> num;
|
|
}
|
|
exports.shr64_hi = shr64_hi;
|
|
|
|
function shr64_lo(ah, al, num) {
|
|
var r = (ah << (32 - num)) | (al >>> num);
|
|
return r >>> 0;
|
|
}
|
|
exports.shr64_lo = shr64_lo;
|
|
|
|
},{"inherits":313,"minimalistic-assert":315}],313:[function(require,module,exports){
|
|
arguments[4][262][0].apply(exports,arguments)
|
|
},{"dup":262}],314:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var hash = require('hash.js');
|
|
var utils = require('minimalistic-crypto-utils');
|
|
var assert = require('minimalistic-assert');
|
|
|
|
function HmacDRBG(options) {
|
|
if (!(this instanceof HmacDRBG))
|
|
return new HmacDRBG(options);
|
|
this.hash = options.hash;
|
|
this.predResist = !!options.predResist;
|
|
|
|
this.outLen = this.hash.outSize;
|
|
this.minEntropy = options.minEntropy || this.hash.hmacStrength;
|
|
|
|
this._reseed = null;
|
|
this.reseedInterval = null;
|
|
this.K = null;
|
|
this.V = null;
|
|
|
|
var entropy = utils.toArray(options.entropy, options.entropyEnc || 'hex');
|
|
var nonce = utils.toArray(options.nonce, options.nonceEnc || 'hex');
|
|
var pers = utils.toArray(options.pers, options.persEnc || 'hex');
|
|
assert(entropy.length >= (this.minEntropy / 8),
|
|
'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');
|
|
this._init(entropy, nonce, pers);
|
|
}
|
|
module.exports = HmacDRBG;
|
|
|
|
HmacDRBG.prototype._init = function init(entropy, nonce, pers) {
|
|
var seed = entropy.concat(nonce).concat(pers);
|
|
|
|
this.K = new Array(this.outLen / 8);
|
|
this.V = new Array(this.outLen / 8);
|
|
for (var i = 0; i < this.V.length; i++) {
|
|
this.K[i] = 0x00;
|
|
this.V[i] = 0x01;
|
|
}
|
|
|
|
this._update(seed);
|
|
this._reseed = 1;
|
|
this.reseedInterval = 0x1000000000000; // 2^48
|
|
};
|
|
|
|
HmacDRBG.prototype._hmac = function hmac() {
|
|
return new hash.hmac(this.hash, this.K);
|
|
};
|
|
|
|
HmacDRBG.prototype._update = function update(seed) {
|
|
var kmac = this._hmac()
|
|
.update(this.V)
|
|
.update([ 0x00 ]);
|
|
if (seed)
|
|
kmac = kmac.update(seed);
|
|
this.K = kmac.digest();
|
|
this.V = this._hmac().update(this.V).digest();
|
|
if (!seed)
|
|
return;
|
|
|
|
this.K = this._hmac()
|
|
.update(this.V)
|
|
.update([ 0x01 ])
|
|
.update(seed)
|
|
.digest();
|
|
this.V = this._hmac().update(this.V).digest();
|
|
};
|
|
|
|
HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) {
|
|
// Optional entropy enc
|
|
if (typeof entropyEnc !== 'string') {
|
|
addEnc = add;
|
|
add = entropyEnc;
|
|
entropyEnc = null;
|
|
}
|
|
|
|
entropy = utils.toArray(entropy, entropyEnc);
|
|
add = utils.toArray(add, addEnc);
|
|
|
|
assert(entropy.length >= (this.minEntropy / 8),
|
|
'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');
|
|
|
|
this._update(entropy.concat(add || []));
|
|
this._reseed = 1;
|
|
};
|
|
|
|
HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) {
|
|
if (this._reseed > this.reseedInterval)
|
|
throw new Error('Reseed is required');
|
|
|
|
// Optional encoding
|
|
if (typeof enc !== 'string') {
|
|
addEnc = add;
|
|
add = enc;
|
|
enc = null;
|
|
}
|
|
|
|
// Optional additional data
|
|
if (add) {
|
|
add = utils.toArray(add, addEnc || 'hex');
|
|
this._update(add);
|
|
}
|
|
|
|
var temp = [];
|
|
while (temp.length < len) {
|
|
this.V = this._hmac().update(this.V).digest();
|
|
temp = temp.concat(this.V);
|
|
}
|
|
|
|
var res = temp.slice(0, len);
|
|
this._update(add);
|
|
this._reseed++;
|
|
return utils.encode(res, enc);
|
|
};
|
|
|
|
},{"hash.js":301,"minimalistic-assert":315,"minimalistic-crypto-utils":316}],315:[function(require,module,exports){
|
|
arguments[4][83][0].apply(exports,arguments)
|
|
},{"dup":83}],316:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
var utils = exports;
|
|
|
|
function toArray(msg, enc) {
|
|
if (Array.isArray(msg))
|
|
return msg.slice();
|
|
if (!msg)
|
|
return [];
|
|
var res = [];
|
|
if (typeof msg !== 'string') {
|
|
for (var i = 0; i < msg.length; i++)
|
|
res[i] = msg[i] | 0;
|
|
return res;
|
|
}
|
|
if (enc === 'hex') {
|
|
msg = msg.replace(/[^a-z0-9]+/ig, '');
|
|
if (msg.length % 2 !== 0)
|
|
msg = '0' + msg;
|
|
for (var i = 0; i < msg.length; i += 2)
|
|
res.push(parseInt(msg[i] + msg[i + 1], 16));
|
|
} else {
|
|
for (var i = 0; i < msg.length; i++) {
|
|
var c = msg.charCodeAt(i);
|
|
var hi = c >> 8;
|
|
var lo = c & 0xff;
|
|
if (hi)
|
|
res.push(hi, lo);
|
|
else
|
|
res.push(lo);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
utils.toArray = toArray;
|
|
|
|
function zero2(word) {
|
|
if (word.length === 1)
|
|
return '0' + word;
|
|
else
|
|
return word;
|
|
}
|
|
utils.zero2 = zero2;
|
|
|
|
function toHex(msg) {
|
|
var res = '';
|
|
for (var i = 0; i < msg.length; i++)
|
|
res += zero2(msg[i].toString(16));
|
|
return res;
|
|
}
|
|
utils.toHex = toHex;
|
|
|
|
utils.encode = function encode(arr, enc) {
|
|
if (enc === 'hex')
|
|
return toHex(arr);
|
|
else
|
|
return arr;
|
|
};
|
|
|
|
},{}],317:[function(require,module,exports){
|
|
module.exports={
|
|
"name": "elliptic",
|
|
"version": "6.4.0",
|
|
"description": "EC cryptography",
|
|
"main": "lib/elliptic.js",
|
|
"files": [
|
|
"lib"
|
|
],
|
|
"scripts": {
|
|
"jscs": "jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js",
|
|
"jshint": "jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js",
|
|
"lint": "npm run jscs && npm run jshint",
|
|
"unit": "istanbul test _mocha --reporter=spec test/index.js",
|
|
"test": "npm run lint && npm run unit",
|
|
"version": "grunt dist && git add dist/"
|
|
},
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "git+ssh://git@github.com/indutny/elliptic.git"
|
|
},
|
|
"keywords": [
|
|
"EC",
|
|
"Elliptic",
|
|
"curve",
|
|
"Cryptography"
|
|
],
|
|
"author": {
|
|
"name": "Fedor Indutny",
|
|
"email": "fedor@indutny.com"
|
|
},
|
|
"license": "MIT",
|
|
"bugs": {
|
|
"url": "https://github.com/indutny/elliptic/issues"
|
|
},
|
|
"homepage": "https://github.com/indutny/elliptic",
|
|
"devDependencies": {
|
|
"brfs": "^1.4.3",
|
|
"coveralls": "^2.11.3",
|
|
"grunt": "^0.4.5",
|
|
"grunt-browserify": "^5.0.0",
|
|
"grunt-cli": "^1.2.0",
|
|
"grunt-contrib-connect": "^1.0.0",
|
|
"grunt-contrib-copy": "^1.0.0",
|
|
"grunt-contrib-uglify": "^1.0.1",
|
|
"grunt-mocha-istanbul": "^3.0.1",
|
|
"grunt-saucelabs": "^8.6.2",
|
|
"istanbul": "^0.4.2",
|
|
"jscs": "^2.9.0",
|
|
"jshint": "^2.6.0",
|
|
"mocha": "^2.1.0"
|
|
},
|
|
"dependencies": {
|
|
"bn.js": "^4.4.0",
|
|
"brorand": "^1.0.1",
|
|
"hash.js": "^1.0.0",
|
|
"hmac-drbg": "^1.0.0",
|
|
"inherits": "^2.0.1",
|
|
"minimalistic-assert": "^1.0.0",
|
|
"minimalistic-crypto-utils": "^1.0.0"
|
|
},
|
|
"gitHead": "6b0d2b76caae91471649c8e21f0b1d3ba0f96090",
|
|
"_id": "elliptic@6.4.0",
|
|
"_shasum": "cac9af8762c85836187003c8dfe193e5e2eae5df",
|
|
"_from": "elliptic@latest",
|
|
"_npmVersion": "3.10.8",
|
|
"_nodeVersion": "7.0.0",
|
|
"_npmUser": {
|
|
"name": "indutny",
|
|
"email": "fedor@indutny.com"
|
|
},
|
|
"dist": {
|
|
"shasum": "cac9af8762c85836187003c8dfe193e5e2eae5df",
|
|
"tarball": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz"
|
|
},
|
|
"maintainers": [
|
|
{
|
|
"name": "indutny",
|
|
"email": "fedor@indutny.com"
|
|
}
|
|
],
|
|
"_npmOperationalInternal": {
|
|
"host": "packages-18-east.internal.npmjs.com",
|
|
"tmp": "tmp/elliptic-6.4.0.tgz_1487798866428_0.30510620190761983"
|
|
},
|
|
"directories": {},
|
|
"_resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
|
|
"readme": "ERROR: No README data found!"
|
|
}
|
|
|
|
},{}],318:[function(require,module,exports){
|
|
arguments[4][262][0].apply(exports,arguments)
|
|
},{"dup":262}],319:[function(require,module,exports){
|
|
(function (global){
|
|
/**
|
|
* @license
|
|
* Lodash <https://lodash.com/>
|
|
* Copyright JS Foundation and other contributors <https://js.foundation/>
|
|
* Released under MIT license <https://lodash.com/license>
|
|
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
|
* 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.4';
|
|
|
|
/** 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';
|
|
|
|
/** 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*$/,
|
|
reLeadingDot = /^\./,
|
|
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 and trailing whitespace. */
|
|
var reTrim = /^\s+|\s+$/g,
|
|
reTrimStart = /^\s+/,
|
|
reTrimEnd = /\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 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)',
|
|
rsOrdUpper = '\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)',
|
|
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 {
|
|
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;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Adds the key-value `pair` to `map`.
|
|
*
|
|
* @private
|
|
* @param {Object} map The map to modify.
|
|
* @param {Array} pair The key-value pair to add.
|
|
* @returns {Object} Returns `map`.
|
|
*/
|
|
function addMapEntry(map, pair) {
|
|
// Don't return `map.set` because it's not chainable in IE 11.
|
|
map.set(pair[0], pair[1]);
|
|
return map;
|
|
}
|
|
|
|
/**
|
|
* Adds `value` to `set`.
|
|
*
|
|
* @private
|
|
* @param {Object} set The set to modify.
|
|
* @param {*} value The value to add.
|
|
* @returns {Object} Returns `set`.
|
|
*/
|
|
function addSetEntry(set, value) {
|
|
// Don't return `set.add` because it's not chainable in IE 11.
|
|
set.add(value);
|
|
return set;
|
|
}
|
|
|
|
/**
|
|
* 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 `_.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 `_.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, baseClone, 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);
|
|
|
|
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) {
|
|
if (isObject(srcValue)) {
|
|
stack || (stack = new Stack);
|
|
baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
|
|
}
|
|
else {
|
|
var newValue = customizer
|
|
? customizer(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 = object[key],
|
|
srcValue = 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) || (srcIndex && 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) {
|
|
var index = -1;
|
|
iteratees = arrayMap(iteratees.length ? iteratees : [identity], 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 (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) {
|
|
value = iteratee(value);
|
|
|
|
var low = 0,
|
|
high = array == null ? 0 : array.length,
|
|
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 `map`.
|
|
*
|
|
* @private
|
|
* @param {Object} map The map to clone.
|
|
* @param {Function} cloneFunc The function to clone values.
|
|
* @param {boolean} [isDeep] Specify a deep clone.
|
|
* @returns {Object} Returns the cloned map.
|
|
*/
|
|
function cloneMap(map, isDeep, cloneFunc) {
|
|
var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);
|
|
return arrayReduce(array, addMapEntry, new map.constructor);
|
|
}
|
|
|
|
/**
|
|
* 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 `set`.
|
|
*
|
|
* @private
|
|
* @param {Object} set The set to clone.
|
|
* @param {Function} cloneFunc The function to clone values.
|
|
* @param {boolean} [isDeep] Specify a deep clone.
|
|
* @returns {Object} Returns the cloned set.
|
|
*/
|
|
function cloneSet(set, isDeep, cloneFunc) {
|
|
var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);
|
|
return arrayReduce(array, addSetEntry, new set.constructor);
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
// 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;
|
|
}
|
|
// Assume cyclic values are equal.
|
|
var stacked = stack.get(array);
|
|
if (stacked && stack.get(other)) {
|
|
return stacked == other;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
// Assume cyclic values are equal.
|
|
var stacked = stack.get(object);
|
|
if (stacked && stack.get(other)) {
|
|
return stacked == other;
|
|
}
|
|
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 = 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`, `Number`, `RegExp`, or `String`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to clone.
|
|
* @param {string} tag The `toStringTag` of the object to clone.
|
|
* @param {Function} cloneFunc The function to clone values.
|
|
* @param {boolean} [isDeep] Specify a deep clone.
|
|
* @returns {Object} Returns the initialized clone.
|
|
*/
|
|
function initCloneByTag(object, tag, cloneFunc, 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 cloneMap(object, isDeep, cloneFunc);
|
|
|
|
case numberTag:
|
|
case stringTag:
|
|
return new Ctor(object);
|
|
|
|
case regexpTag:
|
|
return cloneRegExp(object);
|
|
|
|
case setTag:
|
|
return cloneSet(object, isDeep, cloneFunc);
|
|
|
|
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) {
|
|
length = length == null ? MAX_SAFE_INTEGER : length;
|
|
return !!length &&
|
|
(typeof value == 'number' || 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;
|
|
}
|
|
|
|
/**
|
|
* 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 (reLeadingDot.test(string)) {
|
|
result.push('');
|
|
}
|
|
string.replace(rePropName, function(match, number, quote, string) {
|
|
result.push(quote ? string.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']
|
|
*/
|
|
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': 40 },
|
|
* { 'user': 'barney', 'age': 34 }
|
|
* ];
|
|
*
|
|
* _.sortBy(users, [function(o) { return o.user; }]);
|
|
* // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
|
|
*
|
|
* _.sortBy(users, ['user', 'age']);
|
|
* // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['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,
|
|
result = wait - timeSinceLastCall;
|
|
|
|
return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
|
|
}
|
|
|
|
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.
|
|
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 '<p>' + func(text) + '</p>';
|
|
* });
|
|
*
|
|
* p('fred, barney, & pebbles');
|
|
* // => '<p>fred, barney, & pebbles</p>'
|
|
*/
|
|
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('<body>');
|
|
* // => 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 = value.replace(reTrim, '');
|
|
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(args) {
|
|
args.push(undefined, customDefaultsAssignIn);
|
|
return apply(assignInWith, undefined, args);
|
|
});
|
|
|
|
/**
|
|
* 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) {
|
|
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 (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('<b><%- value %></b>');
|
|
* compiled({ 'value': '<script>' });
|
|
* // => '<b><script></b>'
|
|
*
|
|
* // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
|
|
* var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
|
|
* compiled({ 'users': ['fred', 'barney'] });
|
|
* // => '<li>fred</li><li>barney</li>'
|
|
*
|
|
* // Use the internal `print` function in "evaluate" delimiters.
|
|
* var compiled = _.template('<% print("hello " + user); %>!');
|
|
* compiled({ 'user': 'barney' });
|
|
* // => 'hello barney!'
|
|
*
|
|
* // Use the ES template literal delimiter as an "interpolate" delimiter.
|
|
* // Disable support by replacing the "interpolate" delimiter.
|
|
* var compiled = _.template('hello ${ user }!');
|
|
* compiled({ 'user': 'pebbles' });
|
|
* // => 'hello pebbles!'
|
|
*
|
|
* // Use backslashes to treat delimiters as plain text.
|
|
* var compiled = _.template('<%= "\\<%- value %\\>" %>');
|
|
* compiled({ 'value': 'ignored' });
|
|
* // => '<%- value %>'
|
|
*
|
|
* // Use the `imports` option to import `jQuery` as `jq`.
|
|
* var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
|
|
* var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
|
|
* compiled({ 'users': ['fred', 'barney'] });
|
|
* // => '<li>fred</li><li>barney</li>'
|
|
*
|
|
* // Use the `sourceURL` option to specify a custom sourceURL for the template.
|
|
* var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
|
|
* compiled(data);
|
|
* // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
|
|
*
|
|
* // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
|
|
* var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
|
|
* compiled.source;
|
|
* // => function(data) {
|
|
* // var __t, __p = '';
|
|
* // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
|
|
* // return __p;
|
|
* // }
|
|
*
|
|
* // Use custom template delimiters.
|
|
* _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
|
|
* var compiled = _.template('hello {{ user }}!');
|
|
* compiled({ 'user': 'mustache' });
|
|
* // => 'hello mustache!'
|
|
*
|
|
* // Use the `source` property to inline compiled templates for meaningful
|
|
* // line numbers in error messages and stack traces.
|
|
* fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
|
|
* var JST = {\
|
|
* "main": ' + _.template(mainText).source + '\
|
|
* };\
|
|
* ');
|
|
*/
|
|
function template(string, options, guard) {
|
|
// Based on John Resig's `tmpl` implementation
|
|
// (http://ejohn.org/blog/javascript-micro-templating/)
|
|
// and Laura Doktorova's doT.js (https://github.com/olado/doT).
|
|
var settings = lodash.templateSettings;
|
|
|
|
if (guard && isIterateeCall(string, options, guard)) {
|
|
options = undefined;
|
|
}
|
|
string = toString(string);
|
|
options = assignInWith({}, options, settings, customDefaultsAssignIn);
|
|
|
|
var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
|
|
importsKeys = keys(imports),
|
|
importsValues = baseValues(imports, importsKeys);
|
|
|
|
var isEscaping,
|
|
isEvaluating,
|
|
index = 0,
|
|
interpolate = options.interpolate || reNoMatch,
|
|
source = "__p += '";
|
|
|
|
// Compile the regexp to match each delimiter.
|
|
var reDelimiters = RegExp(
|
|
(options.escape || reNoMatch).source + '|' +
|
|
interpolate.source + '|' +
|
|
(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
|
|
(options.evaluate || reNoMatch).source + '|$'
|
|
, 'g');
|
|
|
|
// Use a sourceURL for easier debugging.
|
|
var sourceURL = '//# sourceURL=' +
|
|
('sourceURL' in options
|
|
? options.sourceURL
|
|
: ('lodash.templateSources[' + (++templateCounter) + ']')
|
|
) + '\n';
|
|
|
|
string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
|
|
interpolateValue || (interpolateValue = esTemplateValue);
|
|
|
|
// Escape characters that can't be included in string literals.
|
|
source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
|
|
|
|
// Replace delimiters with snippets.
|
|
if (escapeValue) {
|
|
isEscaping = true;
|
|
source += "' +\n__e(" + escapeValue + ") +\n'";
|
|
}
|
|
if (evaluateValue) {
|
|
isEvaluating = true;
|
|
source += "';\n" + evaluateValue + ";\n__p += '";
|
|
}
|
|
if (interpolateValue) {
|
|
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
|
|
}
|
|
index = offset + match.length;
|
|
|
|
// The JS engine embedded in Adobe products needs `match` returned in
|
|
// order to produce the correct `offset` value.
|
|
return match;
|
|
});
|
|
|
|
source += "';\n";
|
|
|
|
// If `variable` is not specified wrap a with-statement around the generated
|
|
// code to add the data object to the top of the scope chain.
|
|
var variable = options.variable;
|
|
if (!variable) {
|
|
source = 'with (obj) {\n' + source + '\n}\n';
|
|
}
|
|
// Cleanup code by stripping empty strings.
|
|
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
|
|
.replace(reEmptyStringMiddle, '$1')
|
|
.replace(reEmptyStringTrailing, '$1;');
|
|
|
|
// Frame code as the function body.
|
|
source = 'function(' + (variable || 'obj') + ') {\n' +
|
|
(variable
|
|
? ''
|
|
: 'obj || (obj = {});\n'
|
|
) +
|
|
"var __t, __p = ''" +
|
|
(isEscaping
|
|
? ', __e = _.escape'
|
|
: ''
|
|
) +
|
|
(isEvaluating
|
|
? ', __j = Array.prototype.join;\n' +
|
|
"function print() { __p += __j.call(arguments, '') }\n"
|
|
: ';\n'
|
|
) +
|
|
source +
|
|
'return __p\n}';
|
|
|
|
var result = attempt(function() {
|
|
return Function(importsKeys, sourceURL + 'return ' + source)
|
|
.apply(undefined, importsValues);
|
|
});
|
|
|
|
// Provide the compiled function's source by its `toString` method or
|
|
// the `source` property as a convenience for inlining compiled templates.
|
|
result.source = source;
|
|
if (isError(result)) {
|
|
throw result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts `string`, as a whole, to lower case just like
|
|
* [String#toLowerCase](https://mdn.io/toLowerCase).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the lower cased string.
|
|
* @example
|
|
*
|
|
* _.toLower('--Foo-Bar--');
|
|
* // => '--foo-bar--'
|
|
*
|
|
* _.toLower('fooBar');
|
|
* // => 'foobar'
|
|
*
|
|
* _.toLower('__FOO_BAR__');
|
|
* // => '__foo_bar__'
|
|
*/
|
|
function toLower(value) {
|
|
return toString(value).toLowerCase();
|
|
}
|
|
|
|
/**
|
|
* Converts `string`, as a whole, to upper case just like
|
|
* [String#toUpperCase](https://mdn.io/toUpperCase).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the upper cased string.
|
|
* @example
|
|
*
|
|
* _.toUpper('--foo-bar--');
|
|
* // => '--FOO-BAR--'
|
|
*
|
|
* _.toUpper('fooBar');
|
|
* // => 'FOOBAR'
|
|
*
|
|
* _.toUpper('__foo_bar__');
|
|
* // => '__FOO_BAR__'
|
|
*/
|
|
function toUpper(value) {
|
|
return toString(value).toUpperCase();
|
|
}
|
|
|
|
/**
|
|
* Removes leading and trailing whitespace or specified characters from `string`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to trim.
|
|
* @param {string} [chars=whitespace] The characters to trim.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {string} Returns the trimmed string.
|
|
* @example
|
|
*
|
|
* _.trim(' abc ');
|
|
* // => 'abc'
|
|
*
|
|
* _.trim('-_-abc-_-', '_-');
|
|
* // => 'abc'
|
|
*
|
|
* _.map([' foo ', ' bar '], _.trim);
|
|
* // => ['foo', 'bar']
|
|
*/
|
|
function trim(string, chars, guard) {
|
|
string = toString(string);
|
|
if (string && (guard || chars === undefined)) {
|
|
return string.replace(reTrim, '');
|
|
}
|
|
if (!string || !(chars = baseToString(chars))) {
|
|
return string;
|
|
}
|
|
var strSymbols = stringToArray(string),
|
|
chrSymbols = stringToArray(chars),
|
|
start = charsStartIndex(strSymbols, chrSymbols),
|
|
end = charsEndIndex(strSymbols, chrSymbols) + 1;
|
|
|
|
return castSlice(strSymbols, start, end).join('');
|
|
}
|
|
|
|
/**
|
|
* Removes trailing whitespace or specified characters from `string`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to trim.
|
|
* @param {string} [chars=whitespace] The characters to trim.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {string} Returns the trimmed string.
|
|
* @example
|
|
*
|
|
* _.trimEnd(' abc ');
|
|
* // => ' abc'
|
|
*
|
|
* _.trimEnd('-_-abc-_-', '_-');
|
|
* // => '-_-abc'
|
|
*/
|
|
function trimEnd(string, chars, guard) {
|
|
string = toString(string);
|
|
if (string && (guard || chars === undefined)) {
|
|
return string.replace(reTrimEnd, '');
|
|
}
|
|
if (!string || !(chars = baseToString(chars))) {
|
|
return string;
|
|
}
|
|
var strSymbols = stringToArray(string),
|
|
end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
|
|
|
|
return castSlice(strSymbols, 0, end).join('');
|
|
}
|
|
|
|
/**
|
|
* Removes leading whitespace or specified characters from `string`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to trim.
|
|
* @param {string} [chars=whitespace] The characters to trim.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {string} Returns the trimmed string.
|
|
* @example
|
|
*
|
|
* _.trimStart(' abc ');
|
|
* // => 'abc '
|
|
*
|
|
* _.trimStart('-_-abc-_-', '_-');
|
|
* // => 'abc-_-'
|
|
*/
|
|
function trimStart(string, chars, guard) {
|
|
string = toString(string);
|
|
if (string && (guard || chars === undefined)) {
|
|
return string.replace(reTrimStart, '');
|
|
}
|
|
if (!string || !(chars = baseToString(chars))) {
|
|
return string;
|
|
}
|
|
var strSymbols = stringToArray(string),
|
|
start = charsStartIndex(strSymbols, stringToArray(chars));
|
|
|
|
return castSlice(strSymbols, start).join('');
|
|
}
|
|
|
|
/**
|
|
* Truncates `string` if it's longer than the given maximum string length.
|
|
* The last characters of the truncated string are replaced with the omission
|
|
* string which defaults to "...".
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to truncate.
|
|
* @param {Object} [options={}] The options object.
|
|
* @param {number} [options.length=30] The maximum string length.
|
|
* @param {string} [options.omission='...'] The string to indicate text is omitted.
|
|
* @param {RegExp|string} [options.separator] The separator pattern to truncate to.
|
|
* @returns {string} Returns the truncated string.
|
|
* @example
|
|
*
|
|
* _.truncate('hi-diddly-ho there, neighborino');
|
|
* // => 'hi-diddly-ho there, neighbo...'
|
|
*
|
|
* _.truncate('hi-diddly-ho there, neighborino', {
|
|
* 'length': 24,
|
|
* 'separator': ' '
|
|
* });
|
|
* // => 'hi-diddly-ho there,...'
|
|
*
|
|
* _.truncate('hi-diddly-ho there, neighborino', {
|
|
* 'length': 24,
|
|
* 'separator': /,? +/
|
|
* });
|
|
* // => 'hi-diddly-ho there...'
|
|
*
|
|
* _.truncate('hi-diddly-ho there, neighborino', {
|
|
* 'omission': ' [...]'
|
|
* });
|
|
* // => 'hi-diddly-ho there, neig [...]'
|
|
*/
|
|
function truncate(string, options) {
|
|
var length = DEFAULT_TRUNC_LENGTH,
|
|
omission = DEFAULT_TRUNC_OMISSION;
|
|
|
|
if (isObject(options)) {
|
|
var separator = 'separator' in options ? options.separator : separator;
|
|
length = 'length' in options ? toInteger(options.length) : length;
|
|
omission = 'omission' in options ? baseToString(options.omission) : omission;
|
|
}
|
|
string = toString(string);
|
|
|
|
var strLength = string.length;
|
|
if (hasUnicode(string)) {
|
|
var strSymbols = stringToArray(string);
|
|
strLength = strSymbols.length;
|
|
}
|
|
if (length >= strLength) {
|
|
return string;
|
|
}
|
|
var end = length - stringSize(omission);
|
|
if (end < 1) {
|
|
return omission;
|
|
}
|
|
var result = strSymbols
|
|
? castSlice(strSymbols, 0, end).join('')
|
|
: string.slice(0, end);
|
|
|
|
if (separator === undefined) {
|
|
return result + omission;
|
|
}
|
|
if (strSymbols) {
|
|
end += (result.length - end);
|
|
}
|
|
if (isRegExp(separator)) {
|
|
if (string.slice(end).search(separator)) {
|
|
var match,
|
|
substring = result;
|
|
|
|
if (!separator.global) {
|
|
separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
|
|
}
|
|
separator.lastIndex = 0;
|
|
while ((match = separator.exec(substring))) {
|
|
var newEnd = match.index;
|
|
}
|
|
result = result.slice(0, newEnd === undefined ? end : newEnd);
|
|
}
|
|
} else if (string.indexOf(baseToString(separator), end) != end) {
|
|
var index = result.lastIndexOf(separator);
|
|
if (index > -1) {
|
|
result = result.slice(0, index);
|
|
}
|
|
}
|
|
return result + omission;
|
|
}
|
|
|
|
/**
|
|
* The inverse of `_.escape`; this method converts the HTML entities
|
|
* `&`, `<`, `>`, `"`, and `'` in `string` to
|
|
* their corresponding characters.
|
|
*
|
|
* **Note:** No other HTML entities are unescaped. To unescape additional
|
|
* HTML entities use a third-party library like [_he_](https://mths.be/he).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.6.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to unescape.
|
|
* @returns {string} Returns the unescaped string.
|
|
* @example
|
|
*
|
|
* _.unescape('fred, barney, & pebbles');
|
|
* // => 'fred, barney, & pebbles'
|
|
*/
|
|
function unescape(string) {
|
|
string = toString(string);
|
|
return (string && reHasEscapedHtml.test(string))
|
|
? string.replace(reEscapedHtml, unescapeHtmlChar)
|
|
: string;
|
|
}
|
|
|
|
/**
|
|
* Converts `string`, as space separated words, to upper case.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the upper cased string.
|
|
* @example
|
|
*
|
|
* _.upperCase('--foo-bar');
|
|
* // => 'FOO BAR'
|
|
*
|
|
* _.upperCase('fooBar');
|
|
* // => 'FOO BAR'
|
|
*
|
|
* _.upperCase('__foo_bar__');
|
|
* // => 'FOO BAR'
|
|
*/
|
|
var upperCase = createCompounder(function(result, word, index) {
|
|
return result + (index ? ' ' : '') + word.toUpperCase();
|
|
});
|
|
|
|
/**
|
|
* Converts the first character of `string` to upper case.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the converted string.
|
|
* @example
|
|
*
|
|
* _.upperFirst('fred');
|
|
* // => 'Fred'
|
|
*
|
|
* _.upperFirst('FRED');
|
|
* // => 'FRED'
|
|
*/
|
|
var upperFirst = createCaseFirst('toUpperCase');
|
|
|
|
/**
|
|
* Splits `string` into an array of its words.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to inspect.
|
|
* @param {RegExp|string} [pattern] The pattern to match words.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Array} Returns the words of `string`.
|
|
* @example
|
|
*
|
|
* _.words('fred, barney, & pebbles');
|
|
* // => ['fred', 'barney', 'pebbles']
|
|
*
|
|
* _.words('fred, barney, & pebbles', /[^, ]+/g);
|
|
* // => ['fred', 'barney', '&', 'pebbles']
|
|
*/
|
|
function words(string, pattern, guard) {
|
|
string = toString(string);
|
|
pattern = guard ? undefined : pattern;
|
|
|
|
if (pattern === undefined) {
|
|
return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
|
|
}
|
|
return string.match(pattern) || [];
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Attempts to invoke `func`, returning either the result or the caught error
|
|
* object. Any additional arguments are provided to `func` when it's invoked.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Util
|
|
* @param {Function} func The function to attempt.
|
|
* @param {...*} [args] The arguments to invoke `func` with.
|
|
* @returns {*} Returns the `func` result or error object.
|
|
* @example
|
|
*
|
|
* // Avoid throwing errors for invalid selectors.
|
|
* var elements = _.attempt(function(selector) {
|
|
* return document.querySelectorAll(selector);
|
|
* }, '>_>');
|
|
*
|
|
* if (_.isError(elements)) {
|
|
* elements = [];
|
|
* }
|
|
*/
|
|
var attempt = baseRest(function(func, args) {
|
|
try {
|
|
return apply(func, undefined, args);
|
|
} catch (e) {
|
|
return isError(e) ? e : new Error(e);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Binds methods of an object to the object itself, overwriting the existing
|
|
* method.
|
|
*
|
|
* **Note:** This method doesn't set the "length" property of bound functions.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {Object} object The object to bind and assign the bound methods to.
|
|
* @param {...(string|string[])} methodNames The object method names to bind.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* var view = {
|
|
* 'label': 'docs',
|
|
* 'click': function() {
|
|
* console.log('clicked ' + this.label);
|
|
* }
|
|
* };
|
|
*
|
|
* _.bindAll(view, ['click']);
|
|
* jQuery(element).on('click', view.click);
|
|
* // => Logs 'clicked docs' when clicked.
|
|
*/
|
|
var bindAll = flatRest(function(object, methodNames) {
|
|
arrayEach(methodNames, function(key) {
|
|
key = toKey(key);
|
|
baseAssignValue(object, key, bind(object[key], object));
|
|
});
|
|
return object;
|
|
});
|
|
|
|
/**
|
|
* Creates a function that iterates over `pairs` and invokes the corresponding
|
|
* function of the first predicate to return truthy. The predicate-function
|
|
* pairs are invoked with the `this` binding and arguments of the created
|
|
* function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {Array} pairs The predicate-function pairs.
|
|
* @returns {Function} Returns the new composite function.
|
|
* @example
|
|
*
|
|
* var func = _.cond([
|
|
* [_.matches({ 'a': 1 }), _.constant('matches A')],
|
|
* [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
|
|
* [_.stubTrue, _.constant('no match')]
|
|
* ]);
|
|
*
|
|
* func({ 'a': 1, 'b': 2 });
|
|
* // => 'matches A'
|
|
*
|
|
* func({ 'a': 0, 'b': 1 });
|
|
* // => 'matches B'
|
|
*
|
|
* func({ 'a': '1', 'b': '2' });
|
|
* // => 'no match'
|
|
*/
|
|
function cond(pairs) {
|
|
var length = pairs == null ? 0 : pairs.length,
|
|
toIteratee = getIteratee();
|
|
|
|
pairs = !length ? [] : arrayMap(pairs, function(pair) {
|
|
if (typeof pair[1] != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
return [toIteratee(pair[0]), pair[1]];
|
|
});
|
|
|
|
return baseRest(function(args) {
|
|
var index = -1;
|
|
while (++index < length) {
|
|
var pair = pairs[index];
|
|
if (apply(pair[0], this, args)) {
|
|
return apply(pair[1], this, args);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes the predicate properties of `source` with
|
|
* the corresponding property values of a given object, returning `true` if
|
|
* all predicates return truthy, else `false`.
|
|
*
|
|
* **Note:** The created function is equivalent to `_.conformsTo` with
|
|
* `source` partially applied.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {Object} source The object of property predicates to conform to.
|
|
* @returns {Function} Returns the new spec function.
|
|
* @example
|
|
*
|
|
* var objects = [
|
|
* { 'a': 2, 'b': 1 },
|
|
* { 'a': 1, 'b': 2 }
|
|
* ];
|
|
*
|
|
* _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
|
|
* // => [{ 'a': 1, 'b': 2 }]
|
|
*/
|
|
function conforms(source) {
|
|
return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that returns `value`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.4.0
|
|
* @category Util
|
|
* @param {*} value The value to return from the new function.
|
|
* @returns {Function} Returns the new constant function.
|
|
* @example
|
|
*
|
|
* var objects = _.times(2, _.constant({ 'a': 1 }));
|
|
*
|
|
* console.log(objects);
|
|
* // => [{ 'a': 1 }, { 'a': 1 }]
|
|
*
|
|
* console.log(objects[0] === objects[1]);
|
|
* // => true
|
|
*/
|
|
function constant(value) {
|
|
return function() {
|
|
return value;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Checks `value` to determine whether a default value should be returned in
|
|
* its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
|
|
* or `undefined`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.14.0
|
|
* @category Util
|
|
* @param {*} value The value to check.
|
|
* @param {*} defaultValue The default value.
|
|
* @returns {*} Returns the resolved value.
|
|
* @example
|
|
*
|
|
* _.defaultTo(1, 10);
|
|
* // => 1
|
|
*
|
|
* _.defaultTo(undefined, 10);
|
|
* // => 10
|
|
*/
|
|
function defaultTo(value, defaultValue) {
|
|
return (value == null || value !== value) ? defaultValue : value;
|
|
}
|
|
|
|
/**
|
|
* Creates a function that returns the result of invoking the given functions
|
|
* with the `this` binding of the created function, where each successive
|
|
* invocation is supplied the return value of the previous.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Util
|
|
* @param {...(Function|Function[])} [funcs] The functions to invoke.
|
|
* @returns {Function} Returns the new composite function.
|
|
* @see _.flowRight
|
|
* @example
|
|
*
|
|
* function square(n) {
|
|
* return n * n;
|
|
* }
|
|
*
|
|
* var addSquare = _.flow([_.add, square]);
|
|
* addSquare(1, 2);
|
|
* // => 9
|
|
*/
|
|
var flow = createFlow();
|
|
|
|
/**
|
|
* This method is like `_.flow` except that it creates a function that
|
|
* invokes the given functions from right to left.
|
|
*
|
|
* @static
|
|
* @since 3.0.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {...(Function|Function[])} [funcs] The functions to invoke.
|
|
* @returns {Function} Returns the new composite function.
|
|
* @see _.flow
|
|
* @example
|
|
*
|
|
* function square(n) {
|
|
* return n * n;
|
|
* }
|
|
*
|
|
* var addSquare = _.flowRight([square, _.add]);
|
|
* addSquare(1, 2);
|
|
* // => 9
|
|
*/
|
|
var flowRight = createFlow(true);
|
|
|
|
/**
|
|
* This method returns the first argument it receives.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {*} value Any value.
|
|
* @returns {*} Returns `value`.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1 };
|
|
*
|
|
* console.log(_.identity(object) === object);
|
|
* // => true
|
|
*/
|
|
function identity(value) {
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes `func` with the arguments of the created
|
|
* function. If `func` is a property name, the created function returns the
|
|
* property value for a given element. If `func` is an array or object, the
|
|
* created function returns `true` for elements that contain the equivalent
|
|
* source properties, otherwise it returns `false`.
|
|
*
|
|
* @static
|
|
* @since 4.0.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {*} [func=_.identity] The value to convert to a callback.
|
|
* @returns {Function} Returns the callback.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'age': 36, 'active': true },
|
|
* { 'user': 'fred', 'age': 40, 'active': false }
|
|
* ];
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
|
|
* // => [{ 'user': 'barney', 'age': 36, 'active': true }]
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.filter(users, _.iteratee(['user', 'fred']));
|
|
* // => [{ 'user': 'fred', 'age': 40 }]
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.map(users, _.iteratee('user'));
|
|
* // => ['barney', 'fred']
|
|
*
|
|
* // Create custom iteratee shorthands.
|
|
* _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
|
|
* return !_.isRegExp(func) ? iteratee(func) : function(string) {
|
|
* return func.test(string);
|
|
* };
|
|
* });
|
|
*
|
|
* _.filter(['abc', 'def'], /ef/);
|
|
* // => ['def']
|
|
*/
|
|
function iteratee(func) {
|
|
return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that performs a partial deep comparison between a given
|
|
* object and `source`, returning `true` if the given object has equivalent
|
|
* property values, else `false`.
|
|
*
|
|
* **Note:** The created function is equivalent to `_.isMatch` with `source`
|
|
* 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 Util
|
|
* @param {Object} source The object of property values to match.
|
|
* @returns {Function} Returns the new spec function.
|
|
* @example
|
|
*
|
|
* var objects = [
|
|
* { 'a': 1, 'b': 2, 'c': 3 },
|
|
* { 'a': 4, 'b': 5, 'c': 6 }
|
|
* ];
|
|
*
|
|
* _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
|
|
* // => [{ 'a': 4, 'b': 5, 'c': 6 }]
|
|
*/
|
|
function matches(source) {
|
|
return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that performs a partial deep comparison between the
|
|
* value at `path` of a given object to `srcValue`, returning `true` if the
|
|
* object value is equivalent, else `false`.
|
|
*
|
|
* **Note:** Partial comparisons will match empty array and empty object
|
|
* `srcValue` values against any array or object value, respectively. See
|
|
* `_.isEqual` for a list of supported value comparisons.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.2.0
|
|
* @category Util
|
|
* @param {Array|string} path The path of the property to get.
|
|
* @param {*} srcValue The value to match.
|
|
* @returns {Function} Returns the new spec function.
|
|
* @example
|
|
*
|
|
* var objects = [
|
|
* { 'a': 1, 'b': 2, 'c': 3 },
|
|
* { 'a': 4, 'b': 5, 'c': 6 }
|
|
* ];
|
|
*
|
|
* _.find(objects, _.matchesProperty('a', 4));
|
|
* // => { 'a': 4, 'b': 5, 'c': 6 }
|
|
*/
|
|
function matchesProperty(path, srcValue) {
|
|
return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes the method at `path` of a given object.
|
|
* Any additional arguments are provided to the invoked method.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.7.0
|
|
* @category Util
|
|
* @param {Array|string} path The path of the method to invoke.
|
|
* @param {...*} [args] The arguments to invoke the method with.
|
|
* @returns {Function} Returns the new invoker function.
|
|
* @example
|
|
*
|
|
* var objects = [
|
|
* { 'a': { 'b': _.constant(2) } },
|
|
* { 'a': { 'b': _.constant(1) } }
|
|
* ];
|
|
*
|
|
* _.map(objects, _.method('a.b'));
|
|
* // => [2, 1]
|
|
*
|
|
* _.map(objects, _.method(['a', 'b']));
|
|
* // => [2, 1]
|
|
*/
|
|
var method = baseRest(function(path, args) {
|
|
return function(object) {
|
|
return baseInvoke(object, path, args);
|
|
};
|
|
});
|
|
|
|
/**
|
|
* The opposite of `_.method`; this method creates a function that invokes
|
|
* the method at a given path of `object`. Any additional arguments are
|
|
* provided to the invoked method.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.7.0
|
|
* @category Util
|
|
* @param {Object} object The object to query.
|
|
* @param {...*} [args] The arguments to invoke the method with.
|
|
* @returns {Function} Returns the new invoker function.
|
|
* @example
|
|
*
|
|
* var array = _.times(3, _.constant),
|
|
* object = { 'a': array, 'b': array, 'c': array };
|
|
*
|
|
* _.map(['a[2]', 'c[0]'], _.methodOf(object));
|
|
* // => [2, 0]
|
|
*
|
|
* _.map([['a', '2'], ['c', '0']], _.methodOf(object));
|
|
* // => [2, 0]
|
|
*/
|
|
var methodOf = baseRest(function(object, args) {
|
|
return function(path) {
|
|
return baseInvoke(object, path, args);
|
|
};
|
|
});
|
|
|
|
/**
|
|
* Adds all own enumerable string keyed function properties of a source
|
|
* object to the destination object. If `object` is a function, then methods
|
|
* are added to its prototype as well.
|
|
*
|
|
* **Note:** Use `_.runInContext` to create a pristine `lodash` function to
|
|
* avoid conflicts caused by modifying the original.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {Function|Object} [object=lodash] The destination object.
|
|
* @param {Object} source The object of functions to add.
|
|
* @param {Object} [options={}] The options object.
|
|
* @param {boolean} [options.chain=true] Specify whether mixins are chainable.
|
|
* @returns {Function|Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* function vowels(string) {
|
|
* return _.filter(string, function(v) {
|
|
* return /[aeiou]/i.test(v);
|
|
* });
|
|
* }
|
|
*
|
|
* _.mixin({ 'vowels': vowels });
|
|
* _.vowels('fred');
|
|
* // => ['e']
|
|
*
|
|
* _('fred').vowels().value();
|
|
* // => ['e']
|
|
*
|
|
* _.mixin({ 'vowels': vowels }, { 'chain': false });
|
|
* _('fred').vowels();
|
|
* // => ['e']
|
|
*/
|
|
function mixin(object, source, options) {
|
|
var props = keys(source),
|
|
methodNames = baseFunctions(source, props);
|
|
|
|
if (options == null &&
|
|
!(isObject(source) && (methodNames.length || !props.length))) {
|
|
options = source;
|
|
source = object;
|
|
object = this;
|
|
methodNames = baseFunctions(source, keys(source));
|
|
}
|
|
var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
|
|
isFunc = isFunction(object);
|
|
|
|
arrayEach(methodNames, function(methodName) {
|
|
var func = source[methodName];
|
|
object[methodName] = func;
|
|
if (isFunc) {
|
|
object.prototype[methodName] = function() {
|
|
var chainAll = this.__chain__;
|
|
if (chain || chainAll) {
|
|
var result = object(this.__wrapped__),
|
|
actions = result.__actions__ = copyArray(this.__actions__);
|
|
|
|
actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
|
|
result.__chain__ = chainAll;
|
|
return result;
|
|
}
|
|
return func.apply(object, arrayPush([this.value()], arguments));
|
|
};
|
|
}
|
|
});
|
|
|
|
return object;
|
|
}
|
|
|
|
/**
|
|
* Reverts the `_` variable to its previous value and returns a reference to
|
|
* the `lodash` function.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @returns {Function} Returns the `lodash` function.
|
|
* @example
|
|
*
|
|
* var lodash = _.noConflict();
|
|
*/
|
|
function noConflict() {
|
|
if (root._ === this) {
|
|
root._ = oldDash;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* This method returns `undefined`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.3.0
|
|
* @category Util
|
|
* @example
|
|
*
|
|
* _.times(2, _.noop);
|
|
* // => [undefined, undefined]
|
|
*/
|
|
function noop() {
|
|
// No operation performed.
|
|
}
|
|
|
|
/**
|
|
* Creates a function that gets the argument at index `n`. If `n` is negative,
|
|
* the nth argument from the end is returned.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {number} [n=0] The index of the argument to return.
|
|
* @returns {Function} Returns the new pass-thru function.
|
|
* @example
|
|
*
|
|
* var func = _.nthArg(1);
|
|
* func('a', 'b', 'c', 'd');
|
|
* // => 'b'
|
|
*
|
|
* var func = _.nthArg(-2);
|
|
* func('a', 'b', 'c', 'd');
|
|
* // => 'c'
|
|
*/
|
|
function nthArg(n) {
|
|
n = toInteger(n);
|
|
return baseRest(function(args) {
|
|
return baseNth(args, n);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes `iteratees` with the arguments it receives
|
|
* and returns their results.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {...(Function|Function[])} [iteratees=[_.identity]]
|
|
* The iteratees to invoke.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var func = _.over([Math.max, Math.min]);
|
|
*
|
|
* func(1, 2, 3, 4);
|
|
* // => [4, 1]
|
|
*/
|
|
var over = createOver(arrayMap);
|
|
|
|
/**
|
|
* Creates a function that checks if **all** of the `predicates` return
|
|
* truthy when invoked with the arguments it receives.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {...(Function|Function[])} [predicates=[_.identity]]
|
|
* The predicates to check.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var func = _.overEvery([Boolean, isFinite]);
|
|
*
|
|
* func('1');
|
|
* // => true
|
|
*
|
|
* func(null);
|
|
* // => false
|
|
*
|
|
* func(NaN);
|
|
* // => false
|
|
*/
|
|
var overEvery = createOver(arrayEvery);
|
|
|
|
/**
|
|
* Creates a function that checks if **any** of the `predicates` return
|
|
* truthy when invoked with the arguments it receives.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {...(Function|Function[])} [predicates=[_.identity]]
|
|
* The predicates to check.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var func = _.overSome([Boolean, isFinite]);
|
|
*
|
|
* func('1');
|
|
* // => true
|
|
*
|
|
* func(null);
|
|
* // => true
|
|
*
|
|
* func(NaN);
|
|
* // => false
|
|
*/
|
|
var overSome = createOver(arraySome);
|
|
|
|
/**
|
|
* Creates a function that returns the value at `path` of a given object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.4.0
|
|
* @category Util
|
|
* @param {Array|string} path The path of the property to get.
|
|
* @returns {Function} Returns the new accessor function.
|
|
* @example
|
|
*
|
|
* var objects = [
|
|
* { 'a': { 'b': 2 } },
|
|
* { 'a': { 'b': 1 } }
|
|
* ];
|
|
*
|
|
* _.map(objects, _.property('a.b'));
|
|
* // => [2, 1]
|
|
*
|
|
* _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
|
|
* // => [1, 2]
|
|
*/
|
|
function property(path) {
|
|
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
|
|
}
|
|
|
|
/**
|
|
* The opposite of `_.property`; this method creates a function that returns
|
|
* the value at a given path of `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Util
|
|
* @param {Object} object The object to query.
|
|
* @returns {Function} Returns the new accessor function.
|
|
* @example
|
|
*
|
|
* var array = [0, 1, 2],
|
|
* object = { 'a': array, 'b': array, 'c': array };
|
|
*
|
|
* _.map(['a[2]', 'c[0]'], _.propertyOf(object));
|
|
* // => [2, 0]
|
|
*
|
|
* _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
|
|
* // => [2, 0]
|
|
*/
|
|
function propertyOf(object) {
|
|
return function(path) {
|
|
return object == null ? undefined : baseGet(object, path);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates an array of numbers (positive and/or negative) progressing from
|
|
* `start` up to, but not including, `end`. A step of `-1` is used if a negative
|
|
* `start` is specified without an `end` or `step`. If `end` is not specified,
|
|
* it's set to `start` with `start` then set to `0`.
|
|
*
|
|
* **Note:** JavaScript follows the IEEE-754 standard for resolving
|
|
* floating-point values which can produce unexpected results.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {number} [start=0] The start of the range.
|
|
* @param {number} end The end of the range.
|
|
* @param {number} [step=1] The value to increment or decrement by.
|
|
* @returns {Array} Returns the range of numbers.
|
|
* @see _.inRange, _.rangeRight
|
|
* @example
|
|
*
|
|
* _.range(4);
|
|
* // => [0, 1, 2, 3]
|
|
*
|
|
* _.range(-4);
|
|
* // => [0, -1, -2, -3]
|
|
*
|
|
* _.range(1, 5);
|
|
* // => [1, 2, 3, 4]
|
|
*
|
|
* _.range(0, 20, 5);
|
|
* // => [0, 5, 10, 15]
|
|
*
|
|
* _.range(0, -4, -1);
|
|
* // => [0, -1, -2, -3]
|
|
*
|
|
* _.range(1, 4, 0);
|
|
* // => [1, 1, 1]
|
|
*
|
|
* _.range(0);
|
|
* // => []
|
|
*/
|
|
var range = createRange();
|
|
|
|
/**
|
|
* This method is like `_.range` except that it populates values in
|
|
* descending order.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {number} [start=0] The start of the range.
|
|
* @param {number} end The end of the range.
|
|
* @param {number} [step=1] The value to increment or decrement by.
|
|
* @returns {Array} Returns the range of numbers.
|
|
* @see _.inRange, _.range
|
|
* @example
|
|
*
|
|
* _.rangeRight(4);
|
|
* // => [3, 2, 1, 0]
|
|
*
|
|
* _.rangeRight(-4);
|
|
* // => [-3, -2, -1, 0]
|
|
*
|
|
* _.rangeRight(1, 5);
|
|
* // => [4, 3, 2, 1]
|
|
*
|
|
* _.rangeRight(0, 20, 5);
|
|
* // => [15, 10, 5, 0]
|
|
*
|
|
* _.rangeRight(0, -4, -1);
|
|
* // => [-3, -2, -1, 0]
|
|
*
|
|
* _.rangeRight(1, 4, 0);
|
|
* // => [1, 1, 1]
|
|
*
|
|
* _.rangeRight(0);
|
|
* // => []
|
|
*/
|
|
var rangeRight = createRange(true);
|
|
|
|
/**
|
|
* This method returns a new empty array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.13.0
|
|
* @category Util
|
|
* @returns {Array} Returns the new empty array.
|
|
* @example
|
|
*
|
|
* var arrays = _.times(2, _.stubArray);
|
|
*
|
|
* console.log(arrays);
|
|
* // => [[], []]
|
|
*
|
|
* console.log(arrays[0] === arrays[1]);
|
|
* // => false
|
|
*/
|
|
function stubArray() {
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* This method returns `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.13.0
|
|
* @category Util
|
|
* @returns {boolean} Returns `false`.
|
|
* @example
|
|
*
|
|
* _.times(2, _.stubFalse);
|
|
* // => [false, false]
|
|
*/
|
|
function stubFalse() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method returns a new empty object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.13.0
|
|
* @category Util
|
|
* @returns {Object} Returns the new empty object.
|
|
* @example
|
|
*
|
|
* var objects = _.times(2, _.stubObject);
|
|
*
|
|
* console.log(objects);
|
|
* // => [{}, {}]
|
|
*
|
|
* console.log(objects[0] === objects[1]);
|
|
* // => false
|
|
*/
|
|
function stubObject() {
|
|
return {};
|
|
}
|
|
|
|
/**
|
|
* This method returns an empty string.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.13.0
|
|
* @category Util
|
|
* @returns {string} Returns the empty string.
|
|
* @example
|
|
*
|
|
* _.times(2, _.stubString);
|
|
* // => ['', '']
|
|
*/
|
|
function stubString() {
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* This method returns `true`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.13.0
|
|
* @category Util
|
|
* @returns {boolean} Returns `true`.
|
|
* @example
|
|
*
|
|
* _.times(2, _.stubTrue);
|
|
* // => [true, true]
|
|
*/
|
|
function stubTrue() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Invokes the iteratee `n` times, returning an array of the results of
|
|
* each invocation. The iteratee is invoked with one argument; (index).
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {number} n The number of times to invoke `iteratee`.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the array of results.
|
|
* @example
|
|
*
|
|
* _.times(3, String);
|
|
* // => ['0', '1', '2']
|
|
*
|
|
* _.times(4, _.constant(0));
|
|
* // => [0, 0, 0, 0]
|
|
*/
|
|
function times(n, iteratee) {
|
|
n = toInteger(n);
|
|
if (n < 1 || n > MAX_SAFE_INTEGER) {
|
|
return [];
|
|
}
|
|
var index = MAX_ARRAY_LENGTH,
|
|
length = nativeMin(n, MAX_ARRAY_LENGTH);
|
|
|
|
iteratee = getIteratee(iteratee);
|
|
n -= MAX_ARRAY_LENGTH;
|
|
|
|
var result = baseTimes(length, iteratee);
|
|
while (++index < n) {
|
|
iteratee(index);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to a property path array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {*} value The value to convert.
|
|
* @returns {Array} Returns the new property path array.
|
|
* @example
|
|
*
|
|
* _.toPath('a.b.c');
|
|
* // => ['a', 'b', 'c']
|
|
*
|
|
* _.toPath('a[0].b.c');
|
|
* // => ['a', '0', 'b', 'c']
|
|
*/
|
|
function toPath(value) {
|
|
if (isArray(value)) {
|
|
return arrayMap(value, toKey);
|
|
}
|
|
return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
|
|
}
|
|
|
|
/**
|
|
* Generates a unique ID. If `prefix` is given, the ID is appended to it.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {string} [prefix=''] The value to prefix the ID with.
|
|
* @returns {string} Returns the unique ID.
|
|
* @example
|
|
*
|
|
* _.uniqueId('contact_');
|
|
* // => 'contact_104'
|
|
*
|
|
* _.uniqueId();
|
|
* // => '105'
|
|
*/
|
|
function uniqueId(prefix) {
|
|
var id = ++idCounter;
|
|
return toString(prefix) + id;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Adds two numbers.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.4.0
|
|
* @category Math
|
|
* @param {number} augend The first number in an addition.
|
|
* @param {number} addend The second number in an addition.
|
|
* @returns {number} Returns the total.
|
|
* @example
|
|
*
|
|
* _.add(6, 4);
|
|
* // => 10
|
|
*/
|
|
var add = createMathOperation(function(augend, addend) {
|
|
return augend + addend;
|
|
}, 0);
|
|
|
|
/**
|
|
* Computes `number` rounded up to `precision`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.10.0
|
|
* @category Math
|
|
* @param {number} number The number to round up.
|
|
* @param {number} [precision=0] The precision to round up to.
|
|
* @returns {number} Returns the rounded up number.
|
|
* @example
|
|
*
|
|
* _.ceil(4.006);
|
|
* // => 5
|
|
*
|
|
* _.ceil(6.004, 2);
|
|
* // => 6.01
|
|
*
|
|
* _.ceil(6040, -2);
|
|
* // => 6100
|
|
*/
|
|
var ceil = createRound('ceil');
|
|
|
|
/**
|
|
* Divide two numbers.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.7.0
|
|
* @category Math
|
|
* @param {number} dividend The first number in a division.
|
|
* @param {number} divisor The second number in a division.
|
|
* @returns {number} Returns the quotient.
|
|
* @example
|
|
*
|
|
* _.divide(6, 4);
|
|
* // => 1.5
|
|
*/
|
|
var divide = createMathOperation(function(dividend, divisor) {
|
|
return dividend / divisor;
|
|
}, 1);
|
|
|
|
/**
|
|
* Computes `number` rounded down to `precision`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.10.0
|
|
* @category Math
|
|
* @param {number} number The number to round down.
|
|
* @param {number} [precision=0] The precision to round down to.
|
|
* @returns {number} Returns the rounded down number.
|
|
* @example
|
|
*
|
|
* _.floor(4.006);
|
|
* // => 4
|
|
*
|
|
* _.floor(0.046, 2);
|
|
* // => 0.04
|
|
*
|
|
* _.floor(4060, -2);
|
|
* // => 4000
|
|
*/
|
|
var floor = createRound('floor');
|
|
|
|
/**
|
|
* Computes the maximum value of `array`. If `array` is empty or falsey,
|
|
* `undefined` is returned.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @returns {*} Returns the maximum value.
|
|
* @example
|
|
*
|
|
* _.max([4, 2, 8, 6]);
|
|
* // => 8
|
|
*
|
|
* _.max([]);
|
|
* // => undefined
|
|
*/
|
|
function max(array) {
|
|
return (array && array.length)
|
|
? baseExtremum(array, identity, baseGt)
|
|
: undefined;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.max` except that it accepts `iteratee` which is
|
|
* invoked for each element in `array` to generate the criterion by which
|
|
* the value is ranked. The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {*} Returns the maximum value.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'n': 1 }, { 'n': 2 }];
|
|
*
|
|
* _.maxBy(objects, function(o) { return o.n; });
|
|
* // => { 'n': 2 }
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.maxBy(objects, 'n');
|
|
* // => { 'n': 2 }
|
|
*/
|
|
function maxBy(array, iteratee) {
|
|
return (array && array.length)
|
|
? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
|
|
: undefined;
|
|
}
|
|
|
|
/**
|
|
* Computes the mean of the values in `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @returns {number} Returns the mean.
|
|
* @example
|
|
*
|
|
* _.mean([4, 2, 8, 6]);
|
|
* // => 5
|
|
*/
|
|
function mean(array) {
|
|
return baseMean(array, identity);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.mean` except that it accepts `iteratee` which is
|
|
* invoked for each element in `array` to generate the value to be averaged.
|
|
* The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.7.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {number} Returns the mean.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
|
|
*
|
|
* _.meanBy(objects, function(o) { return o.n; });
|
|
* // => 5
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.meanBy(objects, 'n');
|
|
* // => 5
|
|
*/
|
|
function meanBy(array, iteratee) {
|
|
return baseMean(array, getIteratee(iteratee, 2));
|
|
}
|
|
|
|
/**
|
|
* Computes the minimum value of `array`. If `array` is empty or falsey,
|
|
* `undefined` is returned.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @returns {*} Returns the minimum value.
|
|
* @example
|
|
*
|
|
* _.min([4, 2, 8, 6]);
|
|
* // => 2
|
|
*
|
|
* _.min([]);
|
|
* // => undefined
|
|
*/
|
|
function min(array) {
|
|
return (array && array.length)
|
|
? baseExtremum(array, identity, baseLt)
|
|
: undefined;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.min` except that it accepts `iteratee` which is
|
|
* invoked for each element in `array` to generate the criterion by which
|
|
* the value is ranked. The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {*} Returns the minimum value.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'n': 1 }, { 'n': 2 }];
|
|
*
|
|
* _.minBy(objects, function(o) { return o.n; });
|
|
* // => { 'n': 1 }
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.minBy(objects, 'n');
|
|
* // => { 'n': 1 }
|
|
*/
|
|
function minBy(array, iteratee) {
|
|
return (array && array.length)
|
|
? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
|
|
: undefined;
|
|
}
|
|
|
|
/**
|
|
* Multiply two numbers.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.7.0
|
|
* @category Math
|
|
* @param {number} multiplier The first number in a multiplication.
|
|
* @param {number} multiplicand The second number in a multiplication.
|
|
* @returns {number} Returns the product.
|
|
* @example
|
|
*
|
|
* _.multiply(6, 4);
|
|
* // => 24
|
|
*/
|
|
var multiply = createMathOperation(function(multiplier, multiplicand) {
|
|
return multiplier * multiplicand;
|
|
}, 1);
|
|
|
|
/**
|
|
* Computes `number` rounded to `precision`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.10.0
|
|
* @category Math
|
|
* @param {number} number The number to round.
|
|
* @param {number} [precision=0] The precision to round to.
|
|
* @returns {number} Returns the rounded number.
|
|
* @example
|
|
*
|
|
* _.round(4.006);
|
|
* // => 4
|
|
*
|
|
* _.round(4.006, 2);
|
|
* // => 4.01
|
|
*
|
|
* _.round(4060, -2);
|
|
* // => 4100
|
|
*/
|
|
var round = createRound('round');
|
|
|
|
/**
|
|
* Subtract two numbers.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Math
|
|
* @param {number} minuend The first number in a subtraction.
|
|
* @param {number} subtrahend The second number in a subtraction.
|
|
* @returns {number} Returns the difference.
|
|
* @example
|
|
*
|
|
* _.subtract(6, 4);
|
|
* // => 2
|
|
*/
|
|
var subtract = createMathOperation(function(minuend, subtrahend) {
|
|
return minuend - subtrahend;
|
|
}, 0);
|
|
|
|
/**
|
|
* Computes the sum of the values in `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.4.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @returns {number} Returns the sum.
|
|
* @example
|
|
*
|
|
* _.sum([4, 2, 8, 6]);
|
|
* // => 20
|
|
*/
|
|
function sum(array) {
|
|
return (array && array.length)
|
|
? baseSum(array, identity)
|
|
: 0;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.sum` except that it accepts `iteratee` which is
|
|
* invoked for each element in `array` to generate the value to be summed.
|
|
* The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {number} Returns the sum.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
|
|
*
|
|
* _.sumBy(objects, function(o) { return o.n; });
|
|
* // => 20
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.sumBy(objects, 'n');
|
|
* // => 20
|
|
*/
|
|
function sumBy(array, iteratee) {
|
|
return (array && array.length)
|
|
? baseSum(array, getIteratee(iteratee, 2))
|
|
: 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
// Add methods that return wrapped values in chain sequences.
|
|
lodash.after = after;
|
|
lodash.ary = ary;
|
|
lodash.assign = assign;
|
|
lodash.assignIn = assignIn;
|
|
lodash.assignInWith = assignInWith;
|
|
lodash.assignWith = assignWith;
|
|
lodash.at = at;
|
|
lodash.before = before;
|
|
lodash.bind = bind;
|
|
lodash.bindAll = bindAll;
|
|
lodash.bindKey = bindKey;
|
|
lodash.castArray = castArray;
|
|
lodash.chain = chain;
|
|
lodash.chunk = chunk;
|
|
lodash.compact = compact;
|
|
lodash.concat = concat;
|
|
lodash.cond = cond;
|
|
lodash.conforms = conforms;
|
|
lodash.constant = constant;
|
|
lodash.countBy = countBy;
|
|
lodash.create = create;
|
|
lodash.curry = curry;
|
|
lodash.curryRight = curryRight;
|
|
lodash.debounce = debounce;
|
|
lodash.defaults = defaults;
|
|
lodash.defaultsDeep = defaultsDeep;
|
|
lodash.defer = defer;
|
|
lodash.delay = delay;
|
|
lodash.difference = difference;
|
|
lodash.differenceBy = differenceBy;
|
|
lodash.differenceWith = differenceWith;
|
|
lodash.drop = drop;
|
|
lodash.dropRight = dropRight;
|
|
lodash.dropRightWhile = dropRightWhile;
|
|
lodash.dropWhile = dropWhile;
|
|
lodash.fill = fill;
|
|
lodash.filter = filter;
|
|
lodash.flatMap = flatMap;
|
|
lodash.flatMapDeep = flatMapDeep;
|
|
lodash.flatMapDepth = flatMapDepth;
|
|
lodash.flatten = flatten;
|
|
lodash.flattenDeep = flattenDeep;
|
|
lodash.flattenDepth = flattenDepth;
|
|
lodash.flip = flip;
|
|
lodash.flow = flow;
|
|
lodash.flowRight = flowRight;
|
|
lodash.fromPairs = fromPairs;
|
|
lodash.functions = functions;
|
|
lodash.functionsIn = functionsIn;
|
|
lodash.groupBy = groupBy;
|
|
lodash.initial = initial;
|
|
lodash.intersection = intersection;
|
|
lodash.intersectionBy = intersectionBy;
|
|
lodash.intersectionWith = intersectionWith;
|
|
lodash.invert = invert;
|
|
lodash.invertBy = invertBy;
|
|
lodash.invokeMap = invokeMap;
|
|
lodash.iteratee = iteratee;
|
|
lodash.keyBy = keyBy;
|
|
lodash.keys = keys;
|
|
lodash.keysIn = keysIn;
|
|
lodash.map = map;
|
|
lodash.mapKeys = mapKeys;
|
|
lodash.mapValues = mapValues;
|
|
lodash.matches = matches;
|
|
lodash.matchesProperty = matchesProperty;
|
|
lodash.memoize = memoize;
|
|
lodash.merge = merge;
|
|
lodash.mergeWith = mergeWith;
|
|
lodash.method = method;
|
|
lodash.methodOf = methodOf;
|
|
lodash.mixin = mixin;
|
|
lodash.negate = negate;
|
|
lodash.nthArg = nthArg;
|
|
lodash.omit = omit;
|
|
lodash.omitBy = omitBy;
|
|
lodash.once = once;
|
|
lodash.orderBy = orderBy;
|
|
lodash.over = over;
|
|
lodash.overArgs = overArgs;
|
|
lodash.overEvery = overEvery;
|
|
lodash.overSome = overSome;
|
|
lodash.partial = partial;
|
|
lodash.partialRight = partialRight;
|
|
lodash.partition = partition;
|
|
lodash.pick = pick;
|
|
lodash.pickBy = pickBy;
|
|
lodash.property = property;
|
|
lodash.propertyOf = propertyOf;
|
|
lodash.pull = pull;
|
|
lodash.pullAll = pullAll;
|
|
lodash.pullAllBy = pullAllBy;
|
|
lodash.pullAllWith = pullAllWith;
|
|
lodash.pullAt = pullAt;
|
|
lodash.range = range;
|
|
lodash.rangeRight = rangeRight;
|
|
lodash.rearg = rearg;
|
|
lodash.reject = reject;
|
|
lodash.remove = remove;
|
|
lodash.rest = rest;
|
|
lodash.reverse = reverse;
|
|
lodash.sampleSize = sampleSize;
|
|
lodash.set = set;
|
|
lodash.setWith = setWith;
|
|
lodash.shuffle = shuffle;
|
|
lodash.slice = slice;
|
|
lodash.sortBy = sortBy;
|
|
lodash.sortedUniq = sortedUniq;
|
|
lodash.sortedUniqBy = sortedUniqBy;
|
|
lodash.split = split;
|
|
lodash.spread = spread;
|
|
lodash.tail = tail;
|
|
lodash.take = take;
|
|
lodash.takeRight = takeRight;
|
|
lodash.takeRightWhile = takeRightWhile;
|
|
lodash.takeWhile = takeWhile;
|
|
lodash.tap = tap;
|
|
lodash.throttle = throttle;
|
|
lodash.thru = thru;
|
|
lodash.toArray = toArray;
|
|
lodash.toPairs = toPairs;
|
|
lodash.toPairsIn = toPairsIn;
|
|
lodash.toPath = toPath;
|
|
lodash.toPlainObject = toPlainObject;
|
|
lodash.transform = transform;
|
|
lodash.unary = unary;
|
|
lodash.union = union;
|
|
lodash.unionBy = unionBy;
|
|
lodash.unionWith = unionWith;
|
|
lodash.uniq = uniq;
|
|
lodash.uniqBy = uniqBy;
|
|
lodash.uniqWith = uniqWith;
|
|
lodash.unset = unset;
|
|
lodash.unzip = unzip;
|
|
lodash.unzipWith = unzipWith;
|
|
lodash.update = update;
|
|
lodash.updateWith = updateWith;
|
|
lodash.values = values;
|
|
lodash.valuesIn = valuesIn;
|
|
lodash.without = without;
|
|
lodash.words = words;
|
|
lodash.wrap = wrap;
|
|
lodash.xor = xor;
|
|
lodash.xorBy = xorBy;
|
|
lodash.xorWith = xorWith;
|
|
lodash.zip = zip;
|
|
lodash.zipObject = zipObject;
|
|
lodash.zipObjectDeep = zipObjectDeep;
|
|
lodash.zipWith = zipWith;
|
|
|
|
// Add aliases.
|
|
lodash.entries = toPairs;
|
|
lodash.entriesIn = toPairsIn;
|
|
lodash.extend = assignIn;
|
|
lodash.extendWith = assignInWith;
|
|
|
|
// Add methods to `lodash.prototype`.
|
|
mixin(lodash, lodash);
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
// Add methods that return unwrapped values in chain sequences.
|
|
lodash.add = add;
|
|
lodash.attempt = attempt;
|
|
lodash.camelCase = camelCase;
|
|
lodash.capitalize = capitalize;
|
|
lodash.ceil = ceil;
|
|
lodash.clamp = clamp;
|
|
lodash.clone = clone;
|
|
lodash.cloneDeep = cloneDeep;
|
|
lodash.cloneDeepWith = cloneDeepWith;
|
|
lodash.cloneWith = cloneWith;
|
|
lodash.conformsTo = conformsTo;
|
|
lodash.deburr = deburr;
|
|
lodash.defaultTo = defaultTo;
|
|
lodash.divide = divide;
|
|
lodash.endsWith = endsWith;
|
|
lodash.eq = eq;
|
|
lodash.escape = escape;
|
|
lodash.escapeRegExp = escapeRegExp;
|
|
lodash.every = every;
|
|
lodash.find = find;
|
|
lodash.findIndex = findIndex;
|
|
lodash.findKey = findKey;
|
|
lodash.findLast = findLast;
|
|
lodash.findLastIndex = findLastIndex;
|
|
lodash.findLastKey = findLastKey;
|
|
lodash.floor = floor;
|
|
lodash.forEach = forEach;
|
|
lodash.forEachRight = forEachRight;
|
|
lodash.forIn = forIn;
|
|
lodash.forInRight = forInRight;
|
|
lodash.forOwn = forOwn;
|
|
lodash.forOwnRight = forOwnRight;
|
|
lodash.get = get;
|
|
lodash.gt = gt;
|
|
lodash.gte = gte;
|
|
lodash.has = has;
|
|
lodash.hasIn = hasIn;
|
|
lodash.head = head;
|
|
lodash.identity = identity;
|
|
lodash.includes = includes;
|
|
lodash.indexOf = indexOf;
|
|
lodash.inRange = inRange;
|
|
lodash.invoke = invoke;
|
|
lodash.isArguments = isArguments;
|
|
lodash.isArray = isArray;
|
|
lodash.isArrayBuffer = isArrayBuffer;
|
|
lodash.isArrayLike = isArrayLike;
|
|
lodash.isArrayLikeObject = isArrayLikeObject;
|
|
lodash.isBoolean = isBoolean;
|
|
lodash.isBuffer = isBuffer;
|
|
lodash.isDate = isDate;
|
|
lodash.isElement = isElement;
|
|
lodash.isEmpty = isEmpty;
|
|
lodash.isEqual = isEqual;
|
|
lodash.isEqualWith = isEqualWith;
|
|
lodash.isError = isError;
|
|
lodash.isFinite = isFinite;
|
|
lodash.isFunction = isFunction;
|
|
lodash.isInteger = isInteger;
|
|
lodash.isLength = isLength;
|
|
lodash.isMap = isMap;
|
|
lodash.isMatch = isMatch;
|
|
lodash.isMatchWith = isMatchWith;
|
|
lodash.isNaN = isNaN;
|
|
lodash.isNative = isNative;
|
|
lodash.isNil = isNil;
|
|
lodash.isNull = isNull;
|
|
lodash.isNumber = isNumber;
|
|
lodash.isObject = isObject;
|
|
lodash.isObjectLike = isObjectLike;
|
|
lodash.isPlainObject = isPlainObject;
|
|
lodash.isRegExp = isRegExp;
|
|
lodash.isSafeInteger = isSafeInteger;
|
|
lodash.isSet = isSet;
|
|
lodash.isString = isString;
|
|
lodash.isSymbol = isSymbol;
|
|
lodash.isTypedArray = isTypedArray;
|
|
lodash.isUndefined = isUndefined;
|
|
lodash.isWeakMap = isWeakMap;
|
|
lodash.isWeakSet = isWeakSet;
|
|
lodash.join = join;
|
|
lodash.kebabCase = kebabCase;
|
|
lodash.last = last;
|
|
lodash.lastIndexOf = lastIndexOf;
|
|
lodash.lowerCase = lowerCase;
|
|
lodash.lowerFirst = lowerFirst;
|
|
lodash.lt = lt;
|
|
lodash.lte = lte;
|
|
lodash.max = max;
|
|
lodash.maxBy = maxBy;
|
|
lodash.mean = mean;
|
|
lodash.meanBy = meanBy;
|
|
lodash.min = min;
|
|
lodash.minBy = minBy;
|
|
lodash.stubArray = stubArray;
|
|
lodash.stubFalse = stubFalse;
|
|
lodash.stubObject = stubObject;
|
|
lodash.stubString = stubString;
|
|
lodash.stubTrue = stubTrue;
|
|
lodash.multiply = multiply;
|
|
lodash.nth = nth;
|
|
lodash.noConflict = noConflict;
|
|
lodash.noop = noop;
|
|
lodash.now = now;
|
|
lodash.pad = pad;
|
|
lodash.padEnd = padEnd;
|
|
lodash.padStart = padStart;
|
|
lodash.parseInt = parseInt;
|
|
lodash.random = random;
|
|
lodash.reduce = reduce;
|
|
lodash.reduceRight = reduceRight;
|
|
lodash.repeat = repeat;
|
|
lodash.replace = replace;
|
|
lodash.result = result;
|
|
lodash.round = round;
|
|
lodash.runInContext = runInContext;
|
|
lodash.sample = sample;
|
|
lodash.size = size;
|
|
lodash.snakeCase = snakeCase;
|
|
lodash.some = some;
|
|
lodash.sortedIndex = sortedIndex;
|
|
lodash.sortedIndexBy = sortedIndexBy;
|
|
lodash.sortedIndexOf = sortedIndexOf;
|
|
lodash.sortedLastIndex = sortedLastIndex;
|
|
lodash.sortedLastIndexBy = sortedLastIndexBy;
|
|
lodash.sortedLastIndexOf = sortedLastIndexOf;
|
|
lodash.startCase = startCase;
|
|
lodash.startsWith = startsWith;
|
|
lodash.subtract = subtract;
|
|
lodash.sum = sum;
|
|
lodash.sumBy = sumBy;
|
|
lodash.template = template;
|
|
lodash.times = times;
|
|
lodash.toFinite = toFinite;
|
|
lodash.toInteger = toInteger;
|
|
lodash.toLength = toLength;
|
|
lodash.toLower = toLower;
|
|
lodash.toNumber = toNumber;
|
|
lodash.toSafeInteger = toSafeInteger;
|
|
lodash.toString = toString;
|
|
lodash.toUpper = toUpper;
|
|
lodash.trim = trim;
|
|
lodash.trimEnd = trimEnd;
|
|
lodash.trimStart = trimStart;
|
|
lodash.truncate = truncate;
|
|
lodash.unescape = unescape;
|
|
lodash.uniqueId = uniqueId;
|
|
lodash.upperCase = upperCase;
|
|
lodash.upperFirst = upperFirst;
|
|
|
|
// Add aliases.
|
|
lodash.each = forEach;
|
|
lodash.eachRight = forEachRight;
|
|
lodash.first = head;
|
|
|
|
mixin(lodash, (function() {
|
|
var source = {};
|
|
baseForOwn(lodash, function(func, methodName) {
|
|
if (!hasOwnProperty.call(lodash.prototype, methodName)) {
|
|
source[methodName] = func;
|
|
}
|
|
});
|
|
return source;
|
|
}()), { 'chain': false });
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* The semantic version number.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type {string}
|
|
*/
|
|
lodash.VERSION = VERSION;
|
|
|
|
// Assign default placeholders.
|
|
arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
|
|
lodash[methodName].placeholder = lodash;
|
|
});
|
|
|
|
// Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
|
|
arrayEach(['drop', 'take'], function(methodName, index) {
|
|
LazyWrapper.prototype[methodName] = function(n) {
|
|
n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
|
|
|
|
var result = (this.__filtered__ && !index)
|
|
? new LazyWrapper(this)
|
|
: this.clone();
|
|
|
|
if (result.__filtered__) {
|
|
result.__takeCount__ = nativeMin(n, result.__takeCount__);
|
|
} else {
|
|
result.__views__.push({
|
|
'size': nativeMin(n, MAX_ARRAY_LENGTH),
|
|
'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
|
|
});
|
|
}
|
|
return result;
|
|
};
|
|
|
|
LazyWrapper.prototype[methodName + 'Right'] = function(n) {
|
|
return this.reverse()[methodName](n).reverse();
|
|
};
|
|
});
|
|
|
|
// Add `LazyWrapper` methods that accept an `iteratee` value.
|
|
arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
|
|
var type = index + 1,
|
|
isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
|
|
|
|
LazyWrapper.prototype[methodName] = function(iteratee) {
|
|
var result = this.clone();
|
|
result.__iteratees__.push({
|
|
'iteratee': getIteratee(iteratee, 3),
|
|
'type': type
|
|
});
|
|
result.__filtered__ = result.__filtered__ || isFilter;
|
|
return result;
|
|
};
|
|
});
|
|
|
|
// Add `LazyWrapper` methods for `_.head` and `_.last`.
|
|
arrayEach(['head', 'last'], function(methodName, index) {
|
|
var takeName = 'take' + (index ? 'Right' : '');
|
|
|
|
LazyWrapper.prototype[methodName] = function() {
|
|
return this[takeName](1).value()[0];
|
|
};
|
|
});
|
|
|
|
// Add `LazyWrapper` methods for `_.initial` and `_.tail`.
|
|
arrayEach(['initial', 'tail'], function(methodName, index) {
|
|
var dropName = 'drop' + (index ? '' : 'Right');
|
|
|
|
LazyWrapper.prototype[methodName] = function() {
|
|
return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
|
|
};
|
|
});
|
|
|
|
LazyWrapper.prototype.compact = function() {
|
|
return this.filter(identity);
|
|
};
|
|
|
|
LazyWrapper.prototype.find = function(predicate) {
|
|
return this.filter(predicate).head();
|
|
};
|
|
|
|
LazyWrapper.prototype.findLast = function(predicate) {
|
|
return this.reverse().find(predicate);
|
|
};
|
|
|
|
LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
|
|
if (typeof path == 'function') {
|
|
return new LazyWrapper(this);
|
|
}
|
|
return this.map(function(value) {
|
|
return baseInvoke(value, path, args);
|
|
});
|
|
});
|
|
|
|
LazyWrapper.prototype.reject = function(predicate) {
|
|
return this.filter(negate(getIteratee(predicate)));
|
|
};
|
|
|
|
LazyWrapper.prototype.slice = function(start, end) {
|
|
start = toInteger(start);
|
|
|
|
var result = this;
|
|
if (result.__filtered__ && (start > 0 || end < 0)) {
|
|
return new LazyWrapper(result);
|
|
}
|
|
if (start < 0) {
|
|
result = result.takeRight(-start);
|
|
} else if (start) {
|
|
result = result.drop(start);
|
|
}
|
|
if (end !== undefined) {
|
|
end = toInteger(end);
|
|
result = end < 0 ? result.dropRight(-end) : result.take(end - start);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
LazyWrapper.prototype.takeRightWhile = function(predicate) {
|
|
return this.reverse().takeWhile(predicate).reverse();
|
|
};
|
|
|
|
LazyWrapper.prototype.toArray = function() {
|
|
return this.take(MAX_ARRAY_LENGTH);
|
|
};
|
|
|
|
// Add `LazyWrapper` methods to `lodash.prototype`.
|
|
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
|
var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
|
|
isTaker = /^(?:head|last)$/.test(methodName),
|
|
lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
|
|
retUnwrapped = isTaker || /^find/.test(methodName);
|
|
|
|
if (!lodashFunc) {
|
|
return;
|
|
}
|
|
lodash.prototype[methodName] = function() {
|
|
var value = this.__wrapped__,
|
|
args = isTaker ? [1] : arguments,
|
|
isLazy = value instanceof LazyWrapper,
|
|
iteratee = args[0],
|
|
useLazy = isLazy || isArray(value);
|
|
|
|
var interceptor = function(value) {
|
|
var result = lodashFunc.apply(lodash, arrayPush([value], args));
|
|
return (isTaker && chainAll) ? result[0] : result;
|
|
};
|
|
|
|
if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
|
|
// Avoid lazy use if the iteratee has a "length" value other than `1`.
|
|
isLazy = useLazy = false;
|
|
}
|
|
var chainAll = this.__chain__,
|
|
isHybrid = !!this.__actions__.length,
|
|
isUnwrapped = retUnwrapped && !chainAll,
|
|
onlyLazy = isLazy && !isHybrid;
|
|
|
|
if (!retUnwrapped && useLazy) {
|
|
value = onlyLazy ? value : new LazyWrapper(this);
|
|
var result = func.apply(value, args);
|
|
result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
|
|
return new LodashWrapper(result, chainAll);
|
|
}
|
|
if (isUnwrapped && onlyLazy) {
|
|
return func.apply(this, args);
|
|
}
|
|
result = this.thru(interceptor);
|
|
return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
|
|
};
|
|
});
|
|
|
|
// Add `Array` methods to `lodash.prototype`.
|
|
arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
|
|
var func = arrayProto[methodName],
|
|
chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
|
|
retUnwrapped = /^(?:pop|shift)$/.test(methodName);
|
|
|
|
lodash.prototype[methodName] = function() {
|
|
var args = arguments;
|
|
if (retUnwrapped && !this.__chain__) {
|
|
var value = this.value();
|
|
return func.apply(isArray(value) ? value : [], args);
|
|
}
|
|
return this[chainName](function(value) {
|
|
return func.apply(isArray(value) ? value : [], args);
|
|
});
|
|
};
|
|
});
|
|
|
|
// Map minified method names to their real names.
|
|
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
|
var lodashFunc = lodash[methodName];
|
|
if (lodashFunc) {
|
|
var key = (lodashFunc.name + ''),
|
|
names = realNames[key] || (realNames[key] = []);
|
|
|
|
names.push({ 'name': methodName, 'func': lodashFunc });
|
|
}
|
|
});
|
|
|
|
realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
|
|
'name': 'wrapper',
|
|
'func': undefined
|
|
}];
|
|
|
|
// Add methods to `LazyWrapper`.
|
|
LazyWrapper.prototype.clone = lazyClone;
|
|
LazyWrapper.prototype.reverse = lazyReverse;
|
|
LazyWrapper.prototype.value = lazyValue;
|
|
|
|
// Add chain sequence methods to the `lodash` wrapper.
|
|
lodash.prototype.at = wrapperAt;
|
|
lodash.prototype.chain = wrapperChain;
|
|
lodash.prototype.commit = wrapperCommit;
|
|
lodash.prototype.next = wrapperNext;
|
|
lodash.prototype.plant = wrapperPlant;
|
|
lodash.prototype.reverse = wrapperReverse;
|
|
lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
|
|
|
|
// Add lazy aliases.
|
|
lodash.prototype.first = lodash.prototype.head;
|
|
|
|
if (symIterator) {
|
|
lodash.prototype[symIterator] = wrapperToIterator;
|
|
}
|
|
return lodash;
|
|
});
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
// Export lodash.
|
|
var _ = runInContext();
|
|
|
|
// Some AMD build optimizers, like r.js, check for condition patterns like:
|
|
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
|
|
// Expose Lodash on the global object to prevent errors when Lodash is
|
|
// loaded by a script tag in the presence of an AMD loader.
|
|
// See http://requirejs.org/docs/errors.html#mismatch for more details.
|
|
// Use `_.noConflict` to remove Lodash from the global object.
|
|
root._ = _;
|
|
|
|
// Define as an anonymous module so, through path mapping, it can be
|
|
// referenced as the "underscore" module.
|
|
define(function() {
|
|
return _;
|
|
});
|
|
}
|
|
// Check for `exports` after `define` in case a build optimizer adds it.
|
|
else if (freeModule) {
|
|
// Export for Node.js.
|
|
(freeModule.exports = _)._ = _;
|
|
// Export for CommonJS support.
|
|
freeExports._ = _;
|
|
}
|
|
else {
|
|
// Export to the global object.
|
|
root._ = _;
|
|
}
|
|
}.call(this));
|
|
|
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{}],320:[function(require,module,exports){
|
|
module.exports={
|
|
"name": "bitcore-lib",
|
|
"version": "0.15.0",
|
|
"description": "A pure and powerful JavaScript Bitcoin library.",
|
|
"author": "BitPay <dev@bitpay.com>",
|
|
"main": "index.js",
|
|
"scripts": {
|
|
"lint": "gulp lint",
|
|
"test": "gulp test",
|
|
"coverage": "gulp coverage",
|
|
"build": "gulp"
|
|
},
|
|
"keywords": [
|
|
"bitcoin",
|
|
"transaction",
|
|
"address",
|
|
"p2p",
|
|
"ecies",
|
|
"cryptocurrency",
|
|
"blockchain",
|
|
"payment",
|
|
"bip21",
|
|
"bip32",
|
|
"bip37",
|
|
"bip69",
|
|
"bip70",
|
|
"multisig"
|
|
],
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "https://github.com/bitpay/bitcore-lib.git"
|
|
},
|
|
"browser": {
|
|
"request": "browser-request"
|
|
},
|
|
"dependencies": {
|
|
"bn.js": "=4.11.8",
|
|
"bs58": "=4.0.1",
|
|
"buffer-compare": "=1.1.1",
|
|
"elliptic": "=6.4.0",
|
|
"inherits": "=2.0.1",
|
|
"lodash": "=4.17.4"
|
|
},
|
|
"devDependencies": {
|
|
"bitcore-build": "https://github.com/bitpay/bitcore-build.git#d4e8b2b2f1e2c065c3a807dcb6a6250f61d67ab3",
|
|
"brfs": "^1.2.0",
|
|
"chai": "^1.10.0",
|
|
"gulp": "^3.8.10",
|
|
"sinon": "^1.13.0"
|
|
},
|
|
"license": "MIT"
|
|
}
|
|
|
|
},{}],"bitcore-lib":[function(require,module,exports){
|
|
(function (global,Buffer){
|
|
'use strict';
|
|
|
|
var bitcore = module.exports;
|
|
|
|
// module information
|
|
bitcore.version = 'v' + require('./package.json').version;
|
|
bitcore.versionGuard = function(version) {
|
|
if (version !== undefined) {
|
|
var message = 'More than one instance of bitcore-lib found. ' +
|
|
'Please make sure to require bitcore-lib and check that submodules do' +
|
|
' not also include their own bitcore-lib dependency.';
|
|
throw new Error(message);
|
|
}
|
|
};
|
|
bitcore.versionGuard(global._bitcore);
|
|
global._bitcore = bitcore.version;
|
|
|
|
// crypto
|
|
bitcore.crypto = {};
|
|
bitcore.crypto.BN = require('./lib/crypto/bn');
|
|
bitcore.crypto.ECDSA = require('./lib/crypto/ecdsa');
|
|
bitcore.crypto.Hash = require('./lib/crypto/hash');
|
|
bitcore.crypto.Random = require('./lib/crypto/random');
|
|
bitcore.crypto.Point = require('./lib/crypto/point');
|
|
bitcore.crypto.Signature = require('./lib/crypto/signature');
|
|
|
|
// encoding
|
|
bitcore.encoding = {};
|
|
bitcore.encoding.Base58 = require('./lib/encoding/base58');
|
|
bitcore.encoding.Base58Check = require('./lib/encoding/base58check');
|
|
bitcore.encoding.BufferReader = require('./lib/encoding/bufferreader');
|
|
bitcore.encoding.BufferWriter = require('./lib/encoding/bufferwriter');
|
|
bitcore.encoding.Varint = require('./lib/encoding/varint');
|
|
|
|
// utilities
|
|
bitcore.util = {};
|
|
bitcore.util.buffer = require('./lib/util/buffer');
|
|
bitcore.util.js = require('./lib/util/js');
|
|
bitcore.util.preconditions = require('./lib/util/preconditions');
|
|
|
|
// errors thrown by the library
|
|
bitcore.errors = require('./lib/errors');
|
|
|
|
// main bitcoin library
|
|
bitcore.Address = require('./lib/address');
|
|
bitcore.Block = require('./lib/block');
|
|
bitcore.MerkleBlock = require('./lib/block/merkleblock');
|
|
bitcore.BlockHeader = require('./lib/block/blockheader');
|
|
bitcore.HDPrivateKey = require('./lib/hdprivatekey.js');
|
|
bitcore.HDPublicKey = require('./lib/hdpublickey.js');
|
|
bitcore.Networks = require('./lib/networks');
|
|
bitcore.Opcode = require('./lib/opcode');
|
|
bitcore.PrivateKey = require('./lib/privatekey');
|
|
bitcore.PublicKey = require('./lib/publickey');
|
|
bitcore.Script = require('./lib/script');
|
|
bitcore.Transaction = require('./lib/transaction');
|
|
bitcore.URI = require('./lib/uri');
|
|
bitcore.Unit = require('./lib/unit');
|
|
|
|
// dependencies, subject to change
|
|
bitcore.deps = {};
|
|
bitcore.deps.bnjs = require('bn.js');
|
|
bitcore.deps.bs58 = require('bs58');
|
|
bitcore.deps.Buffer = Buffer;
|
|
bitcore.deps.elliptic = require('elliptic');
|
|
bitcore.deps._ = require('lodash');
|
|
|
|
// Internal usage, exposed for testing/advanced tweaking
|
|
bitcore.Transaction.sighash = require('./lib/transaction/sighash');
|
|
|
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
|
|
},{"./lib/address":1,"./lib/block":4,"./lib/block/blockheader":3,"./lib/block/merkleblock":5,"./lib/crypto/bn":6,"./lib/crypto/ecdsa":7,"./lib/crypto/hash":8,"./lib/crypto/point":9,"./lib/crypto/random":10,"./lib/crypto/signature":11,"./lib/encoding/base58":12,"./lib/encoding/base58check":13,"./lib/encoding/bufferreader":14,"./lib/encoding/bufferwriter":15,"./lib/encoding/varint":16,"./lib/errors":17,"./lib/hdprivatekey.js":19,"./lib/hdpublickey.js":20,"./lib/networks":21,"./lib/opcode":22,"./lib/privatekey":23,"./lib/publickey":24,"./lib/script":25,"./lib/transaction":28,"./lib/transaction/sighash":36,"./lib/unit":40,"./lib/uri":41,"./lib/util/buffer":42,"./lib/util/js":43,"./lib/util/preconditions":44,"./package.json":320,"bn.js":280,"bs58":281,"buffer":47,"elliptic":285,"lodash":319}]},{},[]);
|