commit a0bc2d79de628b435dd30de9718ed9121f6bcad9 Author: Captain Nick Lucifer* Date: Fri Mar 10 23:21:16 2023 +0545 dot.dot.dot.exampol diff --git a/README.md b/README.md new file mode 100644 index 0000000..65aa733 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ + +# Examples + +## nodejs + + $ npm install + $ node node.js diff --git a/lnsocket.js b/lnsocket.js new file mode 100644 index 0000000..737b5be --- /dev/null +++ b/lnsocket.js @@ -0,0 +1,449 @@ + +var Module = (() => { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( +function(Module) { + Module = Module || {}; + +var Module=typeof Module!="undefined"?Module:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});Module.getRandomValue=function(){const window_="object"===typeof window?window:this;const crypto_=typeof window_.crypto!=="undefined"?window_.crypto:window_.msCrypto;let randomBytesNode;let fn;if(!crypto_){randomBytesNode=require("crypto").randomBytes;fn=randomValuesNode}else{fn=randomValuesStandard}function randomValuesNode(){return randomBytesNode(1)[0]>>>0}function randomValuesStandard(){var buf=new Uint32Array(1);crypto_.getRandomValues(buf);return buf[0]>>>0}return fn}();var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;function logExceptionOnExit(e){if(e instanceof ExitStatus)return;let toLog=e;err("exiting due to exception: "+toLog)}var fs;var nodePath;var requireNodeFS;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}requireNodeFS=(()=>{if(!nodePath){fs=require("fs");nodePath=require("path")}});read_=function shell_read(filename,binary){requireNodeFS();filename=nodePath["normalize"](filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=(filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret});readAsync=((filename,onload,onerror)=>{requireNodeFS();filename=nodePath["normalize"](filename);fs.readFile(filename,function(err,data){if(err)onerror(err);else onload(data.buffer)})});if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",function(reason){throw reason});quit_=((status,toThrow)=>{if(keepRuntimeAlive()){process["exitCode"]=status;throw toThrow}logExceptionOnExit(toThrow);process["exit"](status)});Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=(url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText});if(ENVIRONMENT_IS_WORKER){readBinary=(url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)})}readAsync=((url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=(()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()});xhr.onerror=onerror;xhr.send(null)})}setWindowTitle=(title=>document.title=title)}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function getCFunc(ident){var func=Module["_"+ident];return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function keepRuntimeAlive(){return noExitRuntime}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){{if(Module["onAbort"]){Module["onAbort"](what)}}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith("file://")}var wasmBinaryFile;wasmBinaryFile="lnsocket.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary(wasmBinaryFile)})}else{if(readAsync){return new Promise(function(resolve,reject){readAsync(wasmBinaryFile,function(response){resolve(new Uint8Array(response))},reject)})}}}return Promise.resolve().then(function(){return getBinary(wasmBinaryFile)})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["i"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["m"];addOnInit(Module["asm"]["j"]);removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(function(instance){return instance}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch=="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiationResult,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiationResult)})})}else{return instantiateArrayBuffer(receiveInstantiationResult)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync().catch(readyPromiseReject);return{}}var ASM_CONSTS={70236:function(){return Module.getRandomValue()},70272:function(){if(Module.getRandomValue===undefined){try{var window_="object"===typeof window?window:self;var crypto_=typeof window_.crypto!=="undefined"?window_.crypto:window_.msCrypto;var randomValuesStandard=function(){var buf=new Uint32Array(1);crypto_.getRandomValues(buf);return buf[0]>>>0};randomValuesStandard();Module.getRandomValue=randomValuesStandard}catch(e){try{var crypto=require("crypto");var randomValueNodeJS=function(){var buf=crypto["randomBytes"](4);return(buf[0]<<24|buf[1]<<16|buf[2]<<8|buf[3])>>>0};randomValueNodeJS();Module.getRandomValue=randomValueNodeJS}catch(e){throw"No secure random number generator found"}}}}};function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func=="number"){if(callback.arg===undefined){getWasmTableEntry(func)()}else{getWasmTableEntry(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}function getWasmTableEntry(funcPtr){return wasmTable.get(funcPtr)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function _abort(){abort("")}var readAsmConstArgsArray=[];function readAsmConstArgs(sigPtr,buf){readAsmConstArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){var readAsmConstArgsDouble=ch<105;if(readAsmConstArgsDouble&&buf&1)buf++;readAsmConstArgsArray.push(readAsmConstArgsDouble?HEAPF64[buf++>>1]:HEAP32[buf]);++buf}return readAsmConstArgsArray}function _emscripten_asm_const_int(code,sigPtr,argbuf){var args=readAsmConstArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;abortOnCannotGrowMemory(requestedSize)}var SYSCALLS={buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0}var asmLibraryArg={"a":___assert_fail,"b":_abort,"h":_emscripten_asm_const_int,"g":_emscripten_memcpy_big,"c":_emscripten_resize_heap,"f":_fd_close,"d":_fd_seek,"e":_fd_write};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["j"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["k"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["l"]).apply(null,arguments)};var _lnsocket_make_default_initmsg=Module["_lnsocket_make_default_initmsg"]=function(){return(_lnsocket_make_default_initmsg=Module["_lnsocket_make_default_initmsg"]=Module["asm"]["n"]).apply(null,arguments)};var _lnsocket_encrypt=Module["_lnsocket_encrypt"]=function(){return(_lnsocket_encrypt=Module["_lnsocket_encrypt"]=Module["asm"]["o"]).apply(null,arguments)};var _lnsocket_decrypt=Module["_lnsocket_decrypt"]=function(){return(_lnsocket_decrypt=Module["_lnsocket_decrypt"]=Module["asm"]["p"]).apply(null,arguments)};var _lnsocket_decrypt_header=Module["_lnsocket_decrypt_header"]=function(){return(_lnsocket_decrypt_header=Module["_lnsocket_decrypt_header"]=Module["asm"]["q"]).apply(null,arguments)};var _lnsocket_make_ping_msg=Module["_lnsocket_make_ping_msg"]=function(){return(_lnsocket_make_ping_msg=Module["_lnsocket_make_ping_msg"]=Module["asm"]["r"]).apply(null,arguments)};var _lnsocket_msgbuf=Module["_lnsocket_msgbuf"]=function(){return(_lnsocket_msgbuf=Module["_lnsocket_msgbuf"]=Module["asm"]["s"]).apply(null,arguments)};var _lnsocket_create=Module["_lnsocket_create"]=function(){return(_lnsocket_create=Module["_lnsocket_create"]=Module["asm"]["t"]).apply(null,arguments)};var _lnsocket_destroy=Module["_lnsocket_destroy"]=function(){return(_lnsocket_destroy=Module["_lnsocket_destroy"]=Module["asm"]["u"]).apply(null,arguments)};var _lnsocket_secp=Module["_lnsocket_secp"]=function(){return(_lnsocket_secp=Module["_lnsocket_secp"]=Module["asm"]["v"]).apply(null,arguments)};var _lnsocket_genkey=Module["_lnsocket_genkey"]=function(){return(_lnsocket_genkey=Module["_lnsocket_genkey"]=Module["asm"]["w"]).apply(null,arguments)};var _lnsocket_setkey=Module["_lnsocket_setkey"]=function(){return(_lnsocket_setkey=Module["_lnsocket_setkey"]=Module["asm"]["x"]).apply(null,arguments)};var _lnsocket_print_errors=Module["_lnsocket_print_errors"]=function(){return(_lnsocket_print_errors=Module["_lnsocket_print_errors"]=Module["asm"]["y"]).apply(null,arguments)};var _lnsocket_act_two=Module["_lnsocket_act_two"]=function(){return(_lnsocket_act_two=Module["_lnsocket_act_two"]=Module["asm"]["z"]).apply(null,arguments)};var _commando_make_rpc_msg=Module["_commando_make_rpc_msg"]=function(){return(_commando_make_rpc_msg=Module["_commando_make_rpc_msg"]=Module["asm"]["A"]).apply(null,arguments)};var _lnsocket_act_one=Module["_lnsocket_act_one"]=function(){return(_lnsocket_act_one=Module["_lnsocket_act_one"]=Module["asm"]["B"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return(stackSave=Module["stackSave"]=Module["asm"]["C"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return(stackRestore=Module["stackRestore"]=Module["asm"]["D"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return(stackAlloc=Module["stackAlloc"]=Module["asm"]["E"]).apply(null,arguments)};Module["ccall"]=ccall;Module["cwrap"]=cwrap;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run(); + + + return Module.ready +} +); +})(); +if (typeof exports === 'object' && typeof module === 'object') + module.exports = Module; +else if (typeof define === 'function' && define['amd']) + define([], function() { return Module; }); +else if (typeof exports === 'object') + exports["Module"] = Module; + +async function lnsocket_init() { + const module = await Module() + + function SocketImpl(host) { + if (!(this instanceof SocketImpl)) + return new SocketImpl(host) + + if (typeof WebSocket !== 'undefined') { + console.log("WebSocket", typeof WebSocket) + const ok = host.startsWith("ws://") || host.startsWith("wss://") + if (!ok) + throw new Error("host must start with ws:// or wss://") + const ws = new WebSocket(host) + ws.ondata = function(fn) { + ws.onmessage = (v) => { + const data = v.data.arrayBuffer() + fn(data) + } + } + return ws + } + + // + // we're in nodejs + // + const net = require('net') + let [hostname,port] = host.split(":") + port = +port || 9735 + const socket = net.createConnection(port, hostname, () => { + socket.emit("open") + }) + socket.addEventListener = socket.on.bind(socket) + + if (socket.onmessage) + throw new Error("socket already has onmessage?") + + socket.ondata = (fn) => { + socket.on('data', fn) + } + + socket.close = () => { + socket.destroy() + } + + if (socket.send) + throw new Error("socket already has send?") + + socket.send = function socket_send(data) { + return new Promise((resolve, reject) => { + socket.write(data, resolve) + }); + } + + return socket + } + + const ACT_ONE_SIZE = 50 + const ACT_TWO_SIZE = 50 + const ACT_THREE_SIZE = 66 + const DEFAULT_TIMEOUT = 15000 + + const COMMANDO_REPLY_CONTINUES = 0x594b + const COMMANDO_REPLY_TERM = 0x594d + + const lnsocket_create = module.cwrap("lnsocket_create", "number") + const lnsocket_destroy = module.cwrap("lnsocket_destroy", "number") + const lnsocket_encrypt = module.cwrap("lnsocket_encrypt", "number", ["int", "array", "int", "int"]) + const lnsocket_decrypt = module.cwrap("lnsocket_decrypt", "number", ["int", "array", "int"]) + const lnsocket_decrypt_header = module.cwrap("lnsocket_decrypt_header", "number", ["number", "array"]) + const lnsocket_msgbuf = module.cwrap("lnsocket_msgbuf", "number", ["int"]) + const lnsocket_act_one = module.cwrap("lnsocket_act_one", "number", ["number", "string"]) + const lnsocket_act_two = module.cwrap("lnsocket_act_two", "number", ["number", "array"]) + const lnsocket_print_errors = module.cwrap("lnsocket_print_errors", "int") + const lnsocket_genkey = module.cwrap("lnsocket_genkey", null, ["number"]) + const lnsocket_setkey = module.cwrap("lnsocket_setkey", "number", ["number", "array"]) + const lnsocket_make_default_initmsg = module.cwrap("lnsocket_make_default_initmsg", "int", ["int", "int"]) + const lnsocket_make_ping_msg = module.cwrap("lnsocket_make_ping_msg", "int", ["int", "int", "int", "int"]) + const commando_make_rpc_msg = module.cwrap("commando_make_rpc_msg", "int", ["string", "string", "string", "number", "int", "int"]) + + function concat_u8_arrays(arrays) { + // sum of individual array lengths + let totalLength = arrays.reduce((acc, value) => + acc + (value.length || value.byteLength) + , 0); + + if (!arrays.length) return null; + + let result = new Uint8Array(totalLength); + + let length = 0; + for (let array of arrays) { + if (array instanceof ArrayBuffer) + result.set(new Uint8Array(array), length); + else + result.set(array, length); + + length += (array.length || array.byteLength); + } + + return result; + } + + function parse_msgtype(buf) { + return buf[0] << 8 | buf[1] + } + + function wasm_free(buf) { + module._free(buf); + } + + function char_to_hex(cstr) { + const c = cstr.charCodeAt(0) + // c >= 0 && c <= 9 + if (c >= 48 && c <= 57) { + return c - 48; + } + // c >= a && c <= f + if (c >= 97 && c <= 102) { + return c - 97 + 10; + } + // c >= A && c <= F + if (c >= 65 && c <= 70) { + return c - 65 + 10; + } + return -1; + } + + + function hex_decode(str, buflen) + { + let bufsize = buflen || 33 + let c1, c2 + let i = 0 + let j = 0 + let buf = new Uint8Array(bufsize) + let slen = str.length + while (slen > 1) { + if (-1==(c1 = char_to_hex(str[j])) || -1==(c2 = char_to_hex(str[j+1]))) + return null; + if (!bufsize) + return null; + j += 2 + slen -= 2 + buf[i++] = (c1 << 4) | c2 + bufsize--; + } + + return buf + } + + function wasm_alloc(len) { + const buf = module._malloc(len); + module.HEAPU8.set(Uint8Array, buf); + return buf + } + + function wasm_mem(ptr, size) { + return new Uint8Array(module.HEAPU8.buffer, ptr, size); + } + + function LNSocket(opts) { + if (!(this instanceof LNSocket)) + return new LNSocket(opts) + + this.opts = opts || { + timeout: DEFAULT_TIMEOUT + } + this.queue = [] + this.ln = lnsocket_create() + } + + LNSocket.prototype.queue_recv = function() { + let self = this + return new Promise((resolve, reject) => { + const checker = setInterval(() => { + const val = self.queue.shift() + if (val) { + clearInterval(checker) + resolve(val) + } else if (!self.connected) { + clearInterval(checker) + reject() + } + }, 5); + }) + } + + LNSocket.prototype.print_errors = function _lnsocket_print_errors() { + lnsocket_print_errors(this.ln) + } + + LNSocket.prototype.genkey = function _lnsocket_genkey() { + lnsocket_genkey(this.ln) + } + + LNSocket.prototype.setkeyraw = function lnsocket_setkeyraw(rawkey) { + return lnsocket_setkey(this.ln, rawkey) + } + + LNSocket.prototype.setkey = function _lnsocket_setkey(key) { + const rawkey = hex_decode(key) + return this.setkeyraw(rawkey) + } + + LNSocket.prototype.act_one_data = function _lnsocket_act_one(node_id) { + const act_one_ptr = lnsocket_act_one(this.ln, node_id) + if (act_one_ptr === 0) + return null + return wasm_mem(act_one_ptr, ACT_ONE_SIZE) + } + + LNSocket.prototype.act_two = function _lnsocket_act_two(act2) { + const act_three_ptr = lnsocket_act_two(this.ln, new Uint8Array(act2)) + if (act_three_ptr === 0) { + this.print_errors() + return null + } + return wasm_mem(act_three_ptr, ACT_THREE_SIZE) + } + + LNSocket.prototype.connect = async function lnsocket_connect(node_id, host) { + await handle_connect(this, node_id, host) + + const act1 = this.act_one_data(node_id) + this.ws.send(act1) + const act2 = await this.read_all(ACT_TWO_SIZE) + if (act2.length != ACT_TWO_SIZE) { + throw new Error(`expected act2 to be ${ACT_TWO_SIZE} long, got ${act2.length}`) + } + const act3 = this.act_two(act2) + this.ws.send(act3) + } + + LNSocket.prototype.connect_and_init = async function _connect_and_init(node_id, host) { + await this.connect(node_id, host) + await this.perform_init() + } + + LNSocket.prototype.read_all = async function read_all(n) { + let count = 0 + let chunks = [] + if (!this.connected) + throw new Error("read_all: not connected") + while (true) { + let res = await this.queue_recv() + + const remaining = n - count + + if (res.byteLength > remaining) { + chunks.push(res.slice(0, remaining)) + this.queue.unshift(res.slice(remaining)) + break + } else if (res.byteLength === remaining) { + chunks.push(res) + break + } + + chunks.push(res) + count += res.byteLength + } + + return concat_u8_arrays(chunks) + } + + LNSocket.prototype.read_header = async function read_header() { + const header = await this.read_all(18) + if (header.length != 18) + throw new Error("Failed to read header") + return lnsocket_decrypt_header(this.ln, header) + } + + LNSocket.prototype.rpc = async function lnsocket_rpc(opts) { + const msg = this.make_commando_msg(opts) + this.write(msg) + const res = await this.read_all_rpc() + return JSON.parse(res) + } + + LNSocket.prototype.recv = async function lnsocket_recv() { + const msg = await this.read() + const msgtype = parse_msgtype(msg.slice(0,2)) + const res = [msgtype, msg.slice(2)] + return res + } + + LNSocket.prototype.read_all_rpc = async function read_all_rpc() { + let chunks = [] + while (true) { + const [typ, msg] = await this.recv() + switch (typ) { + case COMMANDO_REPLY_TERM: + chunks.push(msg.slice(8)) + return new TextDecoder().decode(concat_u8_arrays(chunks)); + case COMMANDO_REPLY_CONTINUES: + chunks.push(msg.slice(8)) + break + default: + console.log("got unknown type", typ) + continue + } + } + } + + LNSocket.prototype.make_commando_msg = function _lnsocket_make_commando_msg(opts) { + const buflen = 4096 + let len = 0; + const buf = wasm_alloc(buflen); + + const params = JSON.stringify(opts.params||{}) + if (!(len = commando_make_rpc_msg(opts.method, params, opts.rune, + 0, buf, buflen))) { + throw new Error("couldn't make commando msg"); + } + + const dat = wasm_mem(buf, len) + wasm_free(buf); + return dat + } + + LNSocket.prototype.make_ping_msg = function _lnsocket_make_ping_msg(num_pong_bytes=1, ignored_bytes=1) { + const buflen = 32 + let len = 0; + const buf = wasm_alloc(buflen) + + if (!(len = lnsocket_make_ping_msg(buf, buflen, num_pong_bytes, ignored_bytes))) + throw new Error("couldn't make ping msg"); + + const dat = wasm_mem(buf, len) + wasm_free(buf); + return dat + } + + LNSocket.prototype.encrypt = function _lnsocket_encrypt(dat) { + const len = lnsocket_encrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("encrypt error") + } + const enc = wasm_mem(lnsocket_msgbuf(this.ln), len) + return enc + } + + LNSocket.prototype.decrypt = function _lnsocket_decrypt(dat) { + const len = lnsocket_decrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("decrypt error") + } + return wasm_mem(lnsocket_msgbuf(this.ln), len) + } + + LNSocket.prototype.write = function _lnsocket_write(dat) { + this.ws.send(this.encrypt(dat)) + } + + LNSocket.prototype.read = async function _lnsocket_read() { + const size = await this.read_header() + const enc = await this.read_all(size+16) + return this.decrypt(enc) + } + + LNSocket.prototype.make_default_initmsg = function _lnsocket_make_default_initmsg() { + const buflen = 1024 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + if (!(len = lnsocket_make_default_initmsg(buf, buflen))) + throw new Error("couldn't make initmsg"); + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.perform_init = async function lnsocket_connect() { + await this.read() + const our_init = this.make_default_initmsg() + this.write(our_init) + } + + LNSocket.prototype.ping_pong = async function lnsocket_ping_pong() { + const pingmsg = this.make_ping_msg() + this.write(pingmsg) + return await this.read() + } + + LNSocket.prototype.disconnect = function lnsocket_disconnect() { + if (this.connected === true && this.ws) { + this.ws.close() + return true + } + return false + } + + LNSocket.prototype.destroy = function _lnsocket_destroy() { + this.disconnect() + lnsocket_destroy(this.ln) + } + + function handle_connect(ln, node_id, host) { + const ws = new SocketImpl(host) + return new Promise((resolve, reject) => { + const timeout = ln.opts.timeout || DEFAULT_TIMEOUT + const timer = setTimeout(reject, timeout); + + ws.ondata((v) => { + ln.queue.push(v) + }); + + ws.addEventListener('open', function(ev) { + ln.ws = ws + ln.connected = true + clearTimeout(timer) + resolve(ws) + }); + + ws.addEventListener('close', function(ev) { + ln.connected = false + }); + }) + } + + return LNSocket +} + +Module.init = Module.lnsocket_init = lnsocket_init diff --git a/lnsocket.wasm b/lnsocket.wasm new file mode 100755 index 0000000..5a20010 Binary files /dev/null and b/lnsocket.wasm differ diff --git a/node.js b/node.js new file mode 100644 index 0000000..67e986c --- /dev/null +++ b/node.js @@ -0,0 +1,17 @@ +const LNSocket = require('../') + +async function go() { + const ln = await LNSocket() + + ln.genkey() + await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "24.84.152.187") + + const rune = "uQux-hID66AX5rFUpkt1p9CU_7DsTMyUC4G5yq7-dcw9MTMmbWV0aG9kPWdldGluZm8=" + const res = await ln.rpc({ method: "getinfo", rune }) + + ln.destroy() + console.log(res) + return res +} + +go() diff --git a/node_modules/.bin/nopt b/node_modules/.bin/nopt new file mode 120000 index 0000000..6b6566e --- /dev/null +++ b/node_modules/.bin/nopt @@ -0,0 +1 @@ +../nopt/bin/nopt.js \ No newline at end of file diff --git a/node_modules/.bin/tap b/node_modules/.bin/tap new file mode 120000 index 0000000..999914b --- /dev/null +++ b/node_modules/.bin/tap @@ -0,0 +1 @@ +../tap/bin/tap.js \ No newline at end of file diff --git a/node_modules/.bin/uglifyjs b/node_modules/.bin/uglifyjs new file mode 120000 index 0000000..fef3468 --- /dev/null +++ b/node_modules/.bin/uglifyjs @@ -0,0 +1 @@ +../uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..886ee5a --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,195 @@ +{ + "name": "examples", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/buffer-equal": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.2.tgz", + "integrity": "sha512-4hr0gS7+NK47X6WbA/okVFrN5qGh3WLT7N3hMRv7+hlkXnbUIdU2u05n6r0RQv6cq6xke06nVl70r0NW0WM2OQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/bunker": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/bunker/-/bunker-0.1.2.tgz", + "integrity": "sha512-YnahkcXBNT522S46k5LUA9P18lzvgkunbMl0qIJQ8oeRMQ+dAg3YI3k32q5TnO+AAUErFHO6R768To6jslgYmQ==", + "dev": true, + "dependencies": { + "burrito": ">=0.2.5 <0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/burrito": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/burrito/-/burrito-0.2.12.tgz", + "integrity": "sha512-ZhhT5iVTAgzQ+s8rily7m45Swxe/cU3dVCHTzqmHVWD/cc0Ds3W4Q4MExbkevY+fm0Me3lEwpehIy6TH7p+ehw==", + "dev": true, + "dependencies": { + "traverse": "~0.5.1", + "uglify-js": "~1.1.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/burrito/node_modules/traverse": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.5.2.tgz", + "integrity": "sha512-PUBVcfB3RqgLpzgTRGNiqK4duqrDbgGa1bobbUtzUwLiBNAjZ7vd5eCOdBxqZ/Fgezagr9o69IxP2fZp41RGFA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==", + "dev": true + }, + "node_modules/deep-equal": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.0.0.tgz", + "integrity": "sha512-p1bI/kkDPT6auUI0U+WLuIIrzmDIDo80I406J8tT4y6I4ZGtBuMeTudrKDtBdMJFAcxqrQdx27gosqPVyY3IvQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/difflet": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/difflet/-/difflet-0.2.6.tgz", + "integrity": "sha512-ruldDDRmY1t678UOAJBng6sL77f62SqjHj0498YC0EJhxIe2yKkqJn2qEchwG3eU/dqJ/RxPZkAnYjePS4pDCw==", + "dev": true, + "dependencies": { + "charm": "0.1.x", + "deep-is": "0.1.x", + "traverse": "0.6.x" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/lnsocket": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/lnsocket/-/lnsocket-0.2.5.tgz", + "integrity": "sha512-gGmxaG9+w1IV3D5qRc/HX0WOBs8H5Osg00OBAOEdbP3UXjyU1/3JQgGOqrCoplbUu4BXUWKbX1IrROrhq2VQYw==" + }, + "node_modules/mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha512-8OCq0De/h9ZxseqzCH8Kw/Filf5pF/vMI6+BH7Lu0jXz2pqYCjTAQRolSxRIi+Ax+oCCjlxoJMP0YQ4XlrQNHg==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true + }, + "node_modules/nopt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", + "integrity": "sha512-gIOTA/uJuhPwFqp+spY7VQ1satbnGlD+iQVZxI18K6hs8Evq4sX81Ml7BB5byP/LsbR2yBVtmvdEmhi7evJ6Aw==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/runforcover": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", + "integrity": "sha512-yarCIK2HcAOadqnKW419+FA38qpWDCKcOr5RZU+jnyLL/hn3No9BHZY+YJDEzvQ0k8Oyl7ffLjZv9ZUxvyKoLQ==", + "dev": true, + "dependencies": { + "bunker": "0.1.X" + }, + "engines": { + "node": "*" + } + }, + "node_modules/slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/tap": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/tap/-/tap-0.2.6.tgz", + "integrity": "sha512-uLvaKbh3+A4nh+P3SrfX52kWGkVvP37UYI7LxKjRkd6Bjdqbyc7MARaPFGl7SdwyNwWtZHlUxQX3w9pVNf3FKQ==", + "bundleDependencies": [ + "inherits", + "tap-consumer", + "yamlish" + ], + "dev": true, + "dependencies": { + "buffer-equal": "~0.0.0", + "deep-equal": "~0.0.0", + "difflet": "~0.2.0", + "inherits": "*", + "mkdirp": "~0.3", + "nopt": "~2", + "runforcover": "~0.0.2", + "slide": "*", + "yamlish": "*" + }, + "bin": { + "tap": "bin/tap.js" + } + }, + "node_modules/tap/node_modules/inherits": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "WTFPL2" + }, + "node_modules/tap/node_modules/yamlish": { + "version": "0.0.5", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/traverse": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz", + "integrity": "sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uglify-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.1.1.tgz", + "integrity": "sha512-YYY9Dle1leC+btgrHnAR05eq0aRdcPJsXlYYD+SYw2lqc5HFuFNHg3wWEW4SNE0iXXEUl0fz43gTQ3r1YK76rg==", + "dev": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": "*" + } + } + } +} diff --git a/node_modules/abbrev/LICENSE b/node_modules/abbrev/LICENSE new file mode 100644 index 0000000..9bcfa9d --- /dev/null +++ b/node_modules/abbrev/LICENSE @@ -0,0 +1,46 @@ +This software is dual-licensed under the ISC and MIT licenses. +You may use this software under EITHER of the following licenses. + +---------- + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +---------- + +Copyright Isaac Z. Schlueter and Contributors +All rights reserved. + +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. diff --git a/node_modules/abbrev/README.md b/node_modules/abbrev/README.md new file mode 100644 index 0000000..99746fe --- /dev/null +++ b/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/node_modules/abbrev/abbrev.js b/node_modules/abbrev/abbrev.js new file mode 100644 index 0000000..7b1dc5d --- /dev/null +++ b/node_modules/abbrev/abbrev.js @@ -0,0 +1,61 @@ +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} diff --git a/node_modules/abbrev/package.json b/node_modules/abbrev/package.json new file mode 100644 index 0000000..bf4e801 --- /dev/null +++ b/node_modules/abbrev/package.json @@ -0,0 +1,21 @@ +{ + "name": "abbrev", + "version": "1.1.1", + "description": "Like ruby's abbrev module, but in js", + "author": "Isaac Z. Schlueter ", + "main": "abbrev.js", + "scripts": { + "test": "tap test.js --100", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "repository": "http://github.com/isaacs/abbrev-js", + "license": "ISC", + "devDependencies": { + "tap": "^10.1" + }, + "files": [ + "abbrev.js" + ] +} diff --git a/node_modules/buffer-equal/.travis.yml b/node_modules/buffer-equal/.travis.yml new file mode 100644 index 0000000..dad2273 --- /dev/null +++ b/node_modules/buffer-equal/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - "0.10" diff --git a/node_modules/buffer-equal/LICENSE b/node_modules/buffer-equal/LICENSE new file mode 100644 index 0000000..ee27ba4 --- /dev/null +++ b/node_modules/buffer-equal/LICENSE @@ -0,0 +1,18 @@ +This software is released under the MIT license: + +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. diff --git a/node_modules/buffer-equal/README.markdown b/node_modules/buffer-equal/README.markdown new file mode 100644 index 0000000..8c062fd --- /dev/null +++ b/node_modules/buffer-equal/README.markdown @@ -0,0 +1,62 @@ +buffer-equal +============ + +Return whether two buffers are equal. + +[![build status](https://secure.travis-ci.org/substack/node-buffer-equal.png)](http://travis-ci.org/substack/node-buffer-equal) + +example +======= + +``` js +var bufferEqual = require('buffer-equal'); + +console.dir(bufferEqual( + new Buffer([253,254,255]), + new Buffer([253,254,255]) +)); +console.dir(bufferEqual( + new Buffer('abc'), + new Buffer('abcd') +)); +console.dir(bufferEqual( + new Buffer('abc'), + 'abc' +)); +``` + +output: + +``` +true +false +undefined +``` + +methods +======= + +``` js +var bufferEqual = require('buffer-equal') +``` + +bufferEqual(a, b) +----------------- + +Return whether the two buffers `a` and `b` are equal. + +If `a` or `b` is not a buffer, return `undefined`. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install buffer-equal +``` + +license +======= + +MIT diff --git a/node_modules/buffer-equal/example/eq.js b/node_modules/buffer-equal/example/eq.js new file mode 100644 index 0000000..1eb0509 --- /dev/null +++ b/node_modules/buffer-equal/example/eq.js @@ -0,0 +1,14 @@ +var bufferEqual = require('../'); + +console.dir(bufferEqual( + new Buffer([253,254,255]), + new Buffer([253,254,255]) +)); +console.dir(bufferEqual( + new Buffer('abc'), + new Buffer('abcd') +)); +console.dir(bufferEqual( + new Buffer('abc'), + 'abc' +)); diff --git a/node_modules/buffer-equal/index.js b/node_modules/buffer-equal/index.js new file mode 100644 index 0000000..e640d4e --- /dev/null +++ b/node_modules/buffer-equal/index.js @@ -0,0 +1,14 @@ +var Buffer = require('buffer').Buffer; // for use with browserify + +module.exports = function (a, b) { + if (!Buffer.isBuffer(a)) return undefined; + if (!Buffer.isBuffer(b)) return undefined; + if (typeof a.equals === 'function') return a.equals(b); + if (a.length !== b.length) return false; + + for (var i = 0; i < a.length; i++) { + if (a[i] !== b[i]) return false; + } + + return true; +}; diff --git a/node_modules/buffer-equal/package.json b/node_modules/buffer-equal/package.json new file mode 100644 index 0000000..3642209 --- /dev/null +++ b/node_modules/buffer-equal/package.json @@ -0,0 +1,33 @@ +{ + "name" : "buffer-equal", + "description" : "return whether two buffers are equal", + "version" : "0.0.2", + "repository" : { + "type" : "git", + "url" : "git://github.com/substack/node-buffer-equal.git" + }, + "main" : "index.js", + "keywords" : [ + "buffer", + "equal" + ], + "directories" : { + "example" : "example", + "test" : "test" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "devDependencies" : { + "tap" : "0.2.4" + }, + "engines" : { + "node" : ">=0.4.0" + }, + "license" : "MIT", + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + } +} diff --git a/node_modules/buffer-equal/test/eq.js b/node_modules/buffer-equal/test/eq.js new file mode 100644 index 0000000..3d34006 --- /dev/null +++ b/node_modules/buffer-equal/test/eq.js @@ -0,0 +1,35 @@ +var bufferEqual = require('../'); +var test = require('tap').test; + +test('equal', function (t) { + var eq = bufferEqual( + new Buffer([253,254,255]), + new Buffer([253,254,255]) + ); + t.strictEqual(eq, true); + t.end(); +}); + +test('not equal', function (t) { + var eq = bufferEqual( + new Buffer('abc'), + new Buffer('abcd') + ); + t.strictEqual(eq, false); + t.end(); +}); + +test('not equal not buffer', function (t) { + var eq = bufferEqual( + new Buffer('abc'), + 'abc' + ); + t.strictEqual(eq, undefined); + t.end(); +}); + +test('equal not buffer', function (t) { + var eq = bufferEqual('abc', 'abc'); + t.strictEqual(eq, undefined); + t.end(); +}); diff --git a/node_modules/bunker/.npmignore b/node_modules/bunker/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/bunker/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/bunker/.travis.yml b/node_modules/bunker/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/bunker/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/bunker/README.markdown b/node_modules/bunker/README.markdown new file mode 100644 index 0000000..0d0c387 --- /dev/null +++ b/node_modules/bunker/README.markdown @@ -0,0 +1,82 @@ +bunker +====== + +Bunker is a module to calculate code coverage using native javascript +[burrito](https://github.com/substack/node-burrito) AST trickery. + +[![build status](https://secure.travis-ci.org/substack/node-bunker.png)](http://travis-ci.org/substack/node-bunker) + +![code coverage](http://substack.net/images/code_coverage.png) + +examples +======== + +tiny +---- + +````javascript +var bunker = require('bunker'); +var b = bunker('var x = 0; for (var i = 0; i < 30; i++) { x++ }'); + +var counts = {}; + +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node }; + } + counts[node.id].times ++; +}); + +b.run(); + +Object.keys(counts).forEach(function (key) { + var count = counts[key]; + console.log(count.times + ' : ' + count.node.source()); +}); +```` + +output: + + $ node example/tiny.js + 1 : var x=0; + 31 : i<30 + 30 : i++ + 30 : x++; + 30 : x++ + +methods +======= + +var bunker = require('bunker'); + +var b = bunker(src) +------------------- + +Create a new bunker code coverageifier with some source `src`. + +The bunker object `b` is an `EventEmitter` that emits `'node'` events with two +parameters: + +* `node` - the [burrito](https://github.com/substack/node-burrito) node object +* `stack` - the stack, [stackedy](https://github.com/substack/node-stackedy) style + +b.include(src) +-------------- + +Include some source into the bunker. + +b.compile() +----------- + +Return the source wrapped with burrito. + +b.assign(context={}) +-------------------- + +Assign the statement-tracking functions into `context`. + +b.run(context={}) +----------------- + +Run the source using `vm.runInNewContext()` with some `context`. +The statement-tracking functions will be added to `context` by `assign()`. diff --git a/node_modules/bunker/example/prof.js b/node_modules/bunker/example/prof.js new file mode 100644 index 0000000..5cac4cc --- /dev/null +++ b/node_modules/bunker/example/prof.js @@ -0,0 +1,51 @@ +var bunker = require('bunker'); +var b = bunker('(' + function () { + function beep () { + var x = 0; + for (var i = 0; i < 1000; i++) { + for (var j = 0; j < 100; j++) { + x += j; + } + } + return x; + } + + beep(); + +} + ')()'); + +var counts = {}; + +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node, elapsed : 0 }; + } + counts[node.id].times ++; + + var now = Date.now(); + + if (last.id !== undefined) { + counts[last.id].elapsed += last. + } + + if (node.name === 'call') { + var start = now; + + last.id = node.id; + counts[node.id].elapsed += Date.now() - start; + } + else { + counts[node.id].elapsed += now - last; + last = now; + } +}); + +b.run(); + +Object.keys(counts).forEach(function (key) { + var count = counts[key]; + console.log( + [ count.times, count.node.source(), count.elapsed ] + .join(' : ') + ); +}); diff --git a/node_modules/bunker/example/tiny.js b/node_modules/bunker/example/tiny.js new file mode 100644 index 0000000..aa5b034 --- /dev/null +++ b/node_modules/bunker/example/tiny.js @@ -0,0 +1,18 @@ +var bunker = require('bunker'); +var b = bunker('var x = 0; for (var i = 0; i < 30; i++) { x++ }'); + +var counts = {}; + +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node }; + } + counts[node.id].times ++; +}); + +b.run(); + +Object.keys(counts).forEach(function (key) { + var count = counts[key]; + console.log(count.times + ' : ' + count.node.source()); +}); diff --git a/node_modules/bunker/example/top/run.js b/node_modules/bunker/example/top/run.js new file mode 100644 index 0000000..d9eaa10 --- /dev/null +++ b/node_modules/bunker/example/top/run.js @@ -0,0 +1,31 @@ +var bunker = require('bunker'); +var fs = require('fs'); +var src = fs.readFileSync(__dirname + '/src.js', 'utf8'); + +var counts = {}; + +var b = bunker(src); +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node }; + } + counts[node.id].times ++; +}); + +b.run({ + setInterval : setInterval, + clearInterval : clearInterval, + end : function () { + Object.keys(counts) + .sort(function (a, b) { + return counts[b].times - counts[a].times + }) + .forEach(function (key) { + var count = counts[key]; + console.log( + count.times + ' : ' + count.node.source() + ); + }) + ; + } +}); diff --git a/node_modules/bunker/example/top/src.js b/node_modules/bunker/example/top/src.js new file mode 100644 index 0000000..0c92e48 --- /dev/null +++ b/node_modules/bunker/example/top/src.js @@ -0,0 +1,18 @@ +function boop () { + for (var i = 0; i < 30; i++) { + nop(); + } +} + +function nop () { + return undefined; +} + +var times = 0; +var iv = setInterval(function () { + if (++times === 10) { + clearInterval(iv); + end(); + } + else boop() +}, 100); diff --git a/node_modules/bunker/index.js b/node_modules/bunker/index.js new file mode 100644 index 0000000..ed5d437 --- /dev/null +++ b/node_modules/bunker/index.js @@ -0,0 +1,116 @@ +var burrito = require('burrito'); +var vm = require('vm'); +var EventEmitter = require('events').EventEmitter; + +module.exports = function (src) { + var b = new Bunker(); + if (src) b.include(src); + return b; +}; + +function Bunker () { + this.sources = []; + this.nodes = []; + + this.names = { + call : burrito.generateName(6), + expr : burrito.generateName(6), + stat : burrito.generateName(6), + return : burrito.generateName(6) + }; +} + +Bunker.prototype = new EventEmitter; + +Bunker.prototype.include = function (src) { + this.sources.push(src); + this.source = null; + return this; +}; + +Bunker.prototype.compile = function () { + var src = this.sources.join('\n'); + var nodes = this.nodes; + var names = this.names; + + return burrito(src, function (node) { + var i = nodes.length; + + if (node.name === 'call') { + nodes.push(node); + node.wrap(names.call + '(' + i + ')(%s)'); + } + else if (node.name === 'stat' || node.name === 'throw' + || node.name === 'var') { + nodes.push(node); + node.wrap('{' + names.stat + '(' + i + ');%s}'); + } + else if (node.name === 'return') { + nodes.push(node); + // We need to wrap the new source in a function definition + // so that UglifyJS will allow the presence of return + var stat = names.stat + '(' + i + ');'; + var wrapped = 'function ' + names.return + '() {' + + stat + node.source() + +'}' + ; + var parsed = burrito.parse(wrapped); + // Remove the function definition from the AST + parsed[1] = parsed[1][0][3]; + node.state.update(parsed, true); + } + else if (node.name === 'binary') { + nodes.push(node); + node.wrap(names.expr + '(' + i + ')(%s)'); + } + else if (node.name === 'unary-postfix' || node.name === 'unary-prefix') { + nodes.push(node); + node.wrap(names.expr + '(' + i + ')(%s)'); + } + + if (i !== nodes.length) { + node.id = i; + } + }); +}; + +Bunker.prototype.assign = function (context) { + if (!context) context = {}; + + var self = this; + var stack = []; + + context[self.names.call] = function (i) { + var node = self.nodes[i]; + stack.unshift(node); + self.emit('node', node, stack); + + return function (expr) { + stack.shift(); + return expr; + }; + }; + + context[self.names.expr] = function (i) { + var node = self.nodes[i]; + self.emit('node', node, stack); + + return function (expr) { + return expr; + }; + }; + + context[self.names.stat] = function (i) { + var node = self.nodes[i]; + self.emit('node', node, stack); + }; + + return context; +}; + +Bunker.prototype.run = function (context) { + var src = this.compile(); + vm.runInNewContext(src, this.assign(context)); + + return this; +}; diff --git a/node_modules/bunker/package.json b/node_modules/bunker/package.json new file mode 100644 index 0000000..e7bf398 --- /dev/null +++ b/node_modules/bunker/package.json @@ -0,0 +1,35 @@ +{ + "name" : "bunker", + "version" : "0.1.2", + "description" : "code coverage in native javascript", + "main" : "index.js", + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "dependencies" : { + "burrito" : ">=0.2.5 <0.3" + }, + "devDependencies" : { + "tap" : "~0.2.4" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-bunker.git" + }, + "keywords" : [ + "code", + "coverage" + ], + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + }, + "license" : "MIT/X11", + "engine" : { "node" : ">=0.4" } +} diff --git a/node_modules/bunker/test/cover.js b/node_modules/bunker/test/cover.js new file mode 100644 index 0000000..b04795d --- /dev/null +++ b/node_modules/bunker/test/cover.js @@ -0,0 +1,36 @@ +var test = require('tap').test; +var bunker = require('../'); +var fs = require('fs'); + +var src = fs.readdirSync(__dirname + '/src').reduce(function (acc, file) { + acc[file] = fs.readFileSync(__dirname + '/src/' + file, 'utf8'); + return acc; +}, {}); + +test('cover', function (t) { + t.plan(1); + + var b = bunker(src['cover.js']); + var counts = {}; + + b.on('node', function (node) { + counts[node.name] = (counts[node.name] || 0) + 1; + }); + + b.run({ + setInterval : setInterval, + clearInterval : function () { + process.nextTick(function () { + t.same(counts, { + binary : 11, + 'unary-postfix' : 11, + 'var' : 2, + call : 2, // setInterval and clearInterval + stat : 1, // clearInterval + }); + }); + + return clearInterval.apply(this, arguments); + }, + }); +}); diff --git a/node_modules/bunker/test/return.js b/node_modules/bunker/test/return.js new file mode 100644 index 0000000..9be1700 --- /dev/null +++ b/node_modules/bunker/test/return.js @@ -0,0 +1,29 @@ +var test = require('tap').test; +var bunker = require('../'); + +test('cover', function (t) { + t.plan(1); + + var b = bunker('(' + function () { + function foo () {} + function bar () {} + + (function () { + return foo(); + })(); + } + ')()'); + var counts = {}; + + b.on('node', function (node) { + counts[node.name] = (counts[node.name] || 0) + 1; + }); + b.run(); + + process.nextTick(function () { + t.same(counts, { + stat : 2, + call : 2, + return : 1, + }); + }); +}); diff --git a/node_modules/bunker/test/src/cover.js b/node_modules/bunker/test/src/cover.js new file mode 100644 index 0000000..e640151 --- /dev/null +++ b/node_modules/bunker/test/src/cover.js @@ -0,0 +1,6 @@ +var i = 0; +var iv = setInterval(function () { + if (i++ === 10) { + clearInterval(iv); + } +}, 10); diff --git a/node_modules/burrito/.npmignore b/node_modules/burrito/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/burrito/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/burrito/.travis.yml b/node_modules/burrito/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/burrito/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/burrito/README.markdown b/node_modules/burrito/README.markdown new file mode 100644 index 0000000..7c9097c --- /dev/null +++ b/node_modules/burrito/README.markdown @@ -0,0 +1,187 @@ +burrito +======= + +Burrito makes it easy to do crazy stuff with the javascript AST. + +This is super useful if you want to roll your own stack traces or build a code +coverage tool. + +[![build status](https://secure.travis-ci.org/substack/node-burrito.png)](http://travis-ci.org/substack/node-burrito) + +![node.wrap("burrito")](http://substack.net/images/burrito.png) + +examples +======== + +microwave +--------- + +examples/microwave.js + +````javascript +var burrito = require('burrito'); + +var res = burrito.microwave('Math.sin(2)', function (node) { + if (node.name === 'num') node.wrap('Math.PI / %s'); +}); + +console.log(res); // sin(pi / 2) == 1 +```` + +output: + + 1 + +wrap +---- + +examples/wrap.js + +````javascript +var burrito = require('burrito'); + +var src = burrito('f() && g(h())\nfoo()', function (node) { + if (node.name === 'call') node.wrap('qqq(%s)'); +}); + +console.log(src); +```` + +output: + + qqq(f()) && qqq(g(qqq(h()))); + + qqq(foo()); + +methods +======= + + var burrito = require('burrito'); + +burrito(code, cb) +----------------- + +Given some source `code` and a function `trace`, walk the ast by expression. + +The `cb` gets called with a node object described below. + +If `code` is an Array then it is assumbed to be an AST which you can generate +yourself with `burrito.parse()`. The AST must be annotated, so make sure to +`burrito.parse(src, false, true)`. + +burrito.microwave(code, context={}, cb) +--------------------------------------- + +Like `burrito()` except the result is run using +`vm.runInNewContext(res, context)`. + +node object +=========== + +node.name +--------- + +Name is a string that contains the type of the expression as named by uglify. + +node.wrap(s) +------------ + +Wrap the current expression in `s`. + +If `s` is a string, `"%s"` will be replaced with the stringified current +expression. + +If `s` is a function, it is called with the stringified current expression and +should return a new stringified expression. + +If the `node.name === "binary"`, you get the subterms "%a" and "%b" to play with +too. These subterms are applied if `s` is a function too: `s(expr, a, b)`. + +Protip: to insert multiple statements you can use javascript's lesser-known block +syntax that it gets from C: + +````javascript +if (node.name === 'stat') node.wrap('{ foo(); %s }') +```` + +node.node +--------- + +raw ast data generated by uglify + +node.value +---------- + +`node.node.slice(1)` to skip the annotations + +node.start +---------- + +The start location of the expression, like this: + +````javascript +{ type: 'name', + value: 'b', + line: 0, + col: 3, + pos: 3, + nlb: false, + comments_before: [] } +```` + +node.end +-------- + +The end location of the expression, formatted the same as `node.start`. + +node.state +---------- + +The state of the traversal using traverse. + +node.source() +------------- + +Returns a stringified version of the expression. + +node.parent() +------------- + +Returns the parent `node` or `null` if the node is the root element. + +node.label() +------------ + +Return the label of the present node or `null` if there is no label. + +Labels are returned for "call", "var", "defun", and "function" nodes. + +Returns an array for "var" nodes since `var` statements can +contain multiple labels in assignment. + +install +======= + +With [npm](http://npmjs.org) you can just: + + npm install burrito + +in the browser +============== + +Burrito works in browser with +[browserify](https://github.com/substack/node-browserify). + +It has been tested against: + +* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0 +* Firefox 3.5 +* Chrome 6.0 +* Opera 10.6 +* Safari 5.0 + +kudos +===== + +Heavily inspired by (and previously mostly lifted outright from) isaacs's nifty +tmp/instrument.js thingy from uglify-js. diff --git a/node_modules/burrito/example/microwave.js b/node_modules/burrito/example/microwave.js new file mode 100644 index 0000000..c6fcf45 --- /dev/null +++ b/node_modules/burrito/example/microwave.js @@ -0,0 +1,8 @@ +var burrito = require('burrito'); + +var res = burrito.microwave('Math.sin(2)', function (node) { + console.dir(node); + if (node.name === 'num') node.wrap('Math.PI / %s'); +}); + +console.log(res); // sin(pi / 2) == 1 diff --git a/node_modules/burrito/example/web/bs.js b/node_modules/burrito/example/web/bs.js new file mode 100644 index 0000000..3583c7f --- /dev/null +++ b/node_modules/burrito/example/web/bs.js @@ -0,0 +1,4832 @@ +var require = function (file, cwd) { + var resolved = require.resolve(file, cwd || '/'); + var mod = require.modules[resolved]; + if (!mod) throw new Error( + 'Failed to resolve module ' + file + ', tried ' + resolved + ); + var res = mod._cached ? mod._cached : mod(); + return res; +} +var __require = require; + +require.paths = []; +require.modules = {}; +require.extensions = [".js",".coffee"]; + +require.resolve = (function () { + var core = { + 'assert': true, + 'events': true, + 'fs': true, + 'path': true, + 'vm': true + }; + + return function (x, cwd) { + if (!cwd) cwd = '/'; + + if (core[x]) return x; + var path = require.modules.path(); + var y = cwd || '.'; + + if (x.match(/^(?:\.\.?\/|\/)/)) { + var m = loadAsFileSync(path.resolve(y, x)) + || loadAsDirectorySync(path.resolve(y, x)); + if (m) return m; + } + + var n = loadNodeModulesSync(x, y); + if (n) return n; + + throw new Error("Cannot find module '" + x + "'"); + + function loadAsFileSync (x) { + if (require.modules[x]) { + return x; + } + + for (var i = 0; i < require.extensions.length; i++) { + var ext = require.extensions[i]; + if (require.modules[x + ext]) return x + ext; + } + } + + function loadAsDirectorySync (x) { + x = x.replace(/\/+$/, ''); + var pkgfile = x + '/package.json'; + if (require.modules[pkgfile]) { + var pkg = require.modules[pkgfile](); + var b = pkg.browserify; + if (typeof b === 'object' && b.main) { + var m = loadAsFileSync(path.resolve(x, b.main)); + if (m) return m; + } + else if (typeof b === 'string') { + var m = loadAsFileSync(path.resolve(x, b)); + if (m) return m; + } + else if (pkg.main) { + var m = loadAsFileSync(path.resolve(x, pkg.main)); + if (m) return m; + } + } + + return loadAsFileSync(x + '/index'); + } + + function loadNodeModulesSync (x, start) { + var dirs = nodeModulesPathsSync(start); + for (var i = 0; i < dirs.length; i++) { + var dir = dirs[i]; + var m = loadAsFileSync(dir + '/' + x); + if (m) return m; + var n = loadAsDirectorySync(dir + '/' + x); + if (n) return n; + } + + var m = loadAsFileSync(x); + if (m) return m; + } + + function nodeModulesPathsSync (start) { + var parts; + if (start === '/') parts = [ '' ]; + else parts = path.normalize(start).split('/'); + + var dirs = []; + for (var i = parts.length - 1; i >= 0; i--) { + if (parts[i] === 'node_modules') continue; + var dir = parts.slice(0, i + 1).join('/') + '/node_modules'; + dirs.push(dir); + } + + return dirs; + } + }; +})(); + +require.alias = function (from, to) { + var path = require.modules.path(); + var res = null; + try { + res = require.resolve(from + '/package.json', '/'); + } + catch (err) { + res = require.resolve(from, '/'); + } + var basedir = path.dirname(res); + + var keys = Object_keys(require.modules); + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (key.slice(0, basedir.length + 1) === basedir + '/') { + var f = key.slice(basedir.length); + require.modules[to + f] = require.modules[basedir + f]; + } + else if (key === basedir) { + require.modules[to] = require.modules[basedir]; + } + } +}; + +var Object_keys = Object.keys || function (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +if (typeof process === 'undefined') process = {}; + +if (!process.nextTick) process.nextTick = function (fn) { + setTimeout(fn, 0); +}; + +if (!process.title) process.title = 'browser'; + +if (!process.binding) process.binding = function (name) { + if (name === 'evals') return require('vm') + else throw new Error('No such module') +}; + +if (!process.cwd) process.cwd = function () { return '.' }; + +require.modules["path"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "."; + var __filename = "path"; + + var require = function (file) { + return __require(file, "."); + }; + + require.resolve = function (file) { + return __require.resolve(name, "."); + }; + + require.modules = __require.modules; + __require.modules["path"]._cached = module.exports; + + (function () { + function filter (xs, fn) { + var res = []; + for (var i = 0; i < xs.length; i++) { + if (fn(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length; i >= 0; i--) { + var last = parts[i]; + if (last == '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Regex to split a filename into [*, dir, basename, ext] +// posix version +var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { +var resolvedPath = '', + resolvedAbsolute = false; + +for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) + ? arguments[i] + : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string' || !path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; +} + +// At this point the path should be resolved to a full absolute path, but +// handle relative paths to be safe (might happen when process.cwd() fails) + +// Normalize the path +resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { +var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.slice(-1) === '/'; + +// Normalize the path +path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + return p && typeof p === 'string'; + }).join('/')); +}; + + +exports.dirname = function(path) { + var dir = splitPathRe.exec(path)[1] || ''; + var isWindows = false; + if (!dir) { + // No dirname + return '.'; + } else if (dir.length === 1 || + (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) { + // It is just a slash or a drive letter with a slash + return dir; + } else { + // It is a full dirname, strip trailing slash + return dir.substring(0, dir.length - 1); + } +}; + + +exports.basename = function(path, ext) { + var f = splitPathRe.exec(path)[2] || ''; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPathRe.exec(path)[3] || ''; +}; +; + }).call(module.exports); + + __require.modules["path"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito"; + var __filename = "/node_modules/burrito/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/burrito"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"burrito","description":"Wrap up expressions with a trace function while walking the AST with rice and beans on the side","version":"0.2.8","repository":{"type":"git","url":"git://github.com/substack/node-burrito.git"},"main":"./index.js","keywords":["trace","ast","walk","syntax","source","tree","uglify"],"directories":{"lib":".","example":"example","test":"test"},"scripts":{"test":"expresso"},"dependencies":{"traverse":">=0.5.1 <0.6","uglify-js":"1.0.4"},"devDependencies":{"expresso":"=0.7.x"},"engines":{"node":">=0.4.0"},"license":"BSD","author":{"name":"James Halliday","email":"mail@substack.net","url":"http://substack.net"}}; + }).call(module.exports); + + __require.modules["/node_modules/burrito/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"uglify-js","author":{"name":"Mihai Bazon","email":"mihai.bazon@gmail.com","url":"http://mihai.bazon.net/blog"},"version":"1.0.4","main":"./uglify-js.js","bin":{"uglifyjs":"./bin/uglifyjs"},"repository":{"type":"git","url":"git@github.com:mishoo/UglifyJS.git"}}; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/uglify-js.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"]._cached = module.exports; + + (function () { + //convienence function(src, [options]); +function uglify(orig_code, options){ + options || (options = {}); + var jsp = uglify.parser; + var pro = uglify.uglify; + + var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST + ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names + ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations + var final_code = pro.gen_code(ast, options.gen_options); // compressed code here + return final_code; +}; + +uglify.parser = require("./lib/parse-js"); +uglify.uglify = require("./lib/process"); + +module.exports = uglify; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"]._cached = module.exports; + + (function () { + /*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + + This version is suitable for Node.js. With minimal changes (the + exports stuff) it should work on any JS platform. + + This file contains the tokenizer/parser. It is a port to JavaScript + of parse-js [1], a JavaScript parser library written in Common Lisp + by Marijn Haverbeke. Thank you Marijn! + + [1] http://marijn.haverbeke.nl/parse-js/ + + Exported functions: + + - tokenizer(code) -- returns a function. Call the returned + function to fetch the next token. + + - parse(code) -- returns an AST of the given JavaScript code. + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2010 (c) Mihai Bazon + Based on parse-js (http://marijn.haverbeke.nl/parse-js/). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +/* -----[ Tokenizer (constants) ]----- */ + +var KEYWORDS = array_to_hash([ + "break", + "case", + "catch", + "const", + "continue", + "default", + "delete", + "do", + "else", + "finally", + "for", + "function", + "if", + "in", + "instanceof", + "new", + "return", + "switch", + "throw", + "try", + "typeof", + "var", + "void", + "while", + "with" +]); + +var RESERVED_WORDS = array_to_hash([ + "abstract", + "boolean", + "byte", + "char", + "class", + "debugger", + "double", + "enum", + "export", + "extends", + "final", + "float", + "goto", + "implements", + "import", + "int", + "interface", + "long", + "native", + "package", + "private", + "protected", + "public", + "short", + "static", + "super", + "synchronized", + "throws", + "transient", + "volatile" +]); + +var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([ + "return", + "new", + "delete", + "throw", + "else", + "case" +]); + +var KEYWORDS_ATOM = array_to_hash([ + "false", + "null", + "true", + "undefined" +]); + +var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^")); + +var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; +var RE_OCT_NUMBER = /^0[0-7]+$/; +var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; + +var OPERATORS = array_to_hash([ + "in", + "instanceof", + "typeof", + "new", + "void", + "delete", + "++", + "--", + "+", + "-", + "!", + "~", + "&", + "|", + "^", + "*", + "/", + "%", + ">>", + "<<", + ">>>", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "?", + "=", + "+=", + "-=", + "/=", + "*=", + "%=", + ">>=", + "<<=", + ">>>=", + "|=", + "^=", + "&=", + "&&", + "||" +]); + +var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\v\u200b")); + +var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:")); + +var PUNC_CHARS = array_to_hash(characters("[]{}(),;:")); + +var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy")); + +/* -----[ Tokenizer ]----- */ + +// regexps adapted from http://xregexp.com/plugins/#unicode +var UNICODE = { + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), + non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") +}; + +function is_letter(ch) { + return UNICODE.letter.test(ch); +}; + +function is_digit(ch) { + ch = ch.charCodeAt(0); + return ch >= 48 && ch <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9 +}; + +function is_alphanumeric_char(ch) { + return is_digit(ch) || is_letter(ch); +}; + +function is_unicode_combining_mark(ch) { + return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); +}; + +function is_unicode_connector_punctuation(ch) { + return UNICODE.connector_punctuation.test(ch); +}; + +function is_identifier_start(ch) { + return ch == "$" || ch == "_" || is_letter(ch); +}; + +function is_identifier_char(ch) { + return is_identifier_start(ch) + || is_unicode_combining_mark(ch) + || is_digit(ch) + || is_unicode_connector_punctuation(ch) + || ch == "\u200c" // zero-width non-joiner + || ch == "\u200d" // zero-width joiner (in my ECMA-262 PDF, this is also 200c) + ; +}; + +function parse_js_number(num) { + if (RE_HEX_NUMBER.test(num)) { + return parseInt(num.substr(2), 16); + } else if (RE_OCT_NUMBER.test(num)) { + return parseInt(num.substr(1), 8); + } else if (RE_DEC_NUMBER.test(num)) { + return parseFloat(num); + } +}; + +function JS_Parse_Error(message, line, col, pos) { + this.message = message; + this.line = line; + this.col = col; + this.pos = pos; + try { + ({})(); + } catch(ex) { + this.stack = ex.stack; + }; +}; + +JS_Parse_Error.prototype.toString = function() { + return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; +}; + +function js_error(message, line, col, pos) { + throw new JS_Parse_Error(message, line, col, pos); +}; + +function is_token(token, type, val) { + return token.type == type && (val == null || token.value == val); +}; + +var EX_EOF = {}; + +function tokenizer($TEXT) { + + var S = { + text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''), + pos : 0, + tokpos : 0, + line : 0, + tokline : 0, + col : 0, + tokcol : 0, + newline_before : false, + regex_allowed : false, + comments_before : [] + }; + + function peek() { return S.text.charAt(S.pos); }; + + function next(signal_eof) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) + throw EX_EOF; + if (ch == "\n") { + S.newline_before = true; + ++S.line; + S.col = 0; + } else { + ++S.col; + } + return ch; + }; + + function eof() { + return !S.peek(); + }; + + function find(what, signal_eof) { + var pos = S.text.indexOf(what, S.pos); + if (signal_eof && pos == -1) throw EX_EOF; + return pos; + }; + + function start_token() { + S.tokline = S.line; + S.tokcol = S.col; + S.tokpos = S.pos; + }; + + function token(type, value, is_comment) { + S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) || + (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) || + (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value))); + var ret = { + type : type, + value : value, + line : S.tokline, + col : S.tokcol, + pos : S.tokpos, + nlb : S.newline_before + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + } + S.newline_before = false; + return ret; + }; + + function skip_whitespace() { + while (HOP(WHITESPACE_CHARS, peek())) + next(); + }; + + function read_while(pred) { + var ret = "", ch = peek(), i = 0; + while (ch && pred(ch, i++)) { + ret += next(); + ch = peek(); + } + return ret; + }; + + function parse_error(err) { + js_error(err, S.tokline, S.tokcol, S.tokpos); + }; + + function read_num(prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = read_while(function(ch, i){ + if (ch == "x" || ch == "X") { + if (has_x) return false; + return has_x = true; + } + if (!has_x && (ch == "E" || ch == "e")) { + if (has_e) return false; + return has_e = after_e = true; + } + if (ch == "-") { + if (after_e || (i == 0 && !prefix)) return true; + return false; + } + if (ch == "+") return after_e; + after_e = false; + if (ch == ".") { + if (!has_dot && !has_x) + return has_dot = true; + return false; + } + return is_alphanumeric_char(ch); + }); + if (prefix) + num = prefix + num; + var valid = parse_js_number(num); + if (!isNaN(valid)) { + return token("num", valid); + } else { + parse_error("Invalid syntax: " + num); + } + }; + + function read_escaped_char() { + var ch = next(true); + switch (ch) { + case "n" : return "\n"; + case "r" : return "\r"; + case "t" : return "\t"; + case "b" : return "\b"; + case "v" : return "\v"; + case "f" : return "\f"; + case "0" : return "\0"; + case "x" : return String.fromCharCode(hex_bytes(2)); + case "u" : return String.fromCharCode(hex_bytes(4)); + default : return ch; + } + }; + + function hex_bytes(n) { + var num = 0; + for (; n > 0; --n) { + var digit = parseInt(next(true), 16); + if (isNaN(digit)) + parse_error("Invalid hex-character pattern in string"); + num = (num << 4) | digit; + } + return num; + }; + + function read_string() { + return with_eof_error("Unterminated string constant", function(){ + var quote = next(), ret = ""; + for (;;) { + var ch = next(true); + if (ch == "\\") ch = read_escaped_char(); + else if (ch == quote) break; + ret += ch; + } + return token("string", ret); + }); + }; + + function read_line_comment() { + next(); + var i = find("\n"), ret; + if (i == -1) { + ret = S.text.substr(S.pos); + S.pos = S.text.length; + } else { + ret = S.text.substring(S.pos, i); + S.pos = i; + } + return token("comment1", ret, true); + }; + + function read_multiline_comment() { + next(); + return with_eof_error("Unterminated multiline comment", function(){ + var i = find("*/", true), + text = S.text.substring(S.pos, i), + tok = token("comment2", text, true); + S.pos = i + 2; + S.line += text.split("\n").length - 1; + S.newline_before = text.indexOf("\n") >= 0; + + // https://github.com/mishoo/UglifyJS/issues/#issue/100 + if (/^@cc_on/i.test(text)) { + warn("WARNING: at line " + S.line); + warn("*** Found \"conditional comment\": " + text); + warn("*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer."); + } + + return tok; + }); + }; + + function read_name() { + var backslash = false, name = "", ch; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") backslash = true, next(); + else if (is_identifier_char(ch)) name += next(); + else break; + } + else { + if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = read_escaped_char(); + if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + return name; + }; + + function read_regexp() { + return with_eof_error("Unterminated regular expression", function(){ + var prev_backslash = false, regexp = "", ch, in_class = false; + while ((ch = next(true))) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = read_name(); + return token("regexp", [ regexp, mods ]); + }); + }; + + function read_operator(prefix) { + function grow(op) { + if (!peek()) return op; + var bigger = op + peek(); + if (HOP(OPERATORS, bigger)) { + next(); + return grow(bigger); + } else { + return op; + } + }; + return token("operator", grow(prefix || next())); + }; + + function handle_slash() { + next(); + var regex_allowed = S.regex_allowed; + switch (peek()) { + case "/": + S.comments_before.push(read_line_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + case "*": + S.comments_before.push(read_multiline_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + } + return S.regex_allowed ? read_regexp() : read_operator("/"); + }; + + function handle_dot() { + next(); + return is_digit(peek()) + ? read_num(".") + : token("punc", "."); + }; + + function read_word() { + var word = read_name(); + return !HOP(KEYWORDS, word) + ? token("name", word) + : HOP(OPERATORS, word) + ? token("operator", word) + : HOP(KEYWORDS_ATOM, word) + ? token("atom", word) + : token("keyword", word); + }; + + function with_eof_error(eof_error, cont) { + try { + return cont(); + } catch(ex) { + if (ex === EX_EOF) parse_error(eof_error); + else throw ex; + } + }; + + function next_token(force_regexp) { + if (force_regexp) + return read_regexp(); + skip_whitespace(); + start_token(); + var ch = peek(); + if (!ch) return token("eof"); + if (is_digit(ch)) return read_num(); + if (ch == '"' || ch == "'") return read_string(); + if (HOP(PUNC_CHARS, ch)) return token("punc", next()); + if (ch == ".") return handle_dot(); + if (ch == "/") return handle_slash(); + if (HOP(OPERATOR_CHARS, ch)) return read_operator(); + if (ch == "\\" || is_identifier_start(ch)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + }; + + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + + return next_token; + +}; + +/* -----[ Parser (constants) ]----- */ + +var UNARY_PREFIX = array_to_hash([ + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" +]); + +var UNARY_POSTFIX = array_to_hash([ "--", "++" ]); + +var ASSIGNMENT = (function(a, ret, i){ + while (i < a.length) { + ret[a[i]] = a[i].substr(0, a[i].length - 1); + i++; + } + return ret; +})( + ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="], + { "=": true }, + 0 +); + +var PRECEDENCE = (function(a, ret){ + for (var i = 0, n = 1; i < a.length; ++i, ++n) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = n; + } + } + return ret; +})( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); + +var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + +var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + +/* -----[ Parser ]----- */ + +function NodeWithToken(str, start, end) { + this.name = str; + this.start = start; + this.end = end; +}; + +NodeWithToken.prototype.toString = function() { return this.name; }; + +function parse($TEXT, exigent_mode, embed_tokens) { + + var S = { + input : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT, + token : null, + prev : null, + peeked : null, + in_function : 0, + in_loop : 0, + labels : [] + }; + + S.token = next(); + + function is(type, value) { + return is_token(S.token, type, value); + }; + + function peek() { return S.peeked || (S.peeked = S.input()); }; + + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + return S.token; + }; + + function prev() { + return S.prev; + }; + + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, + line != null ? line : ctx.tokline, + col != null ? col : ctx.tokcol, + pos != null ? pos : ctx.tokpos); + }; + + function token_error(token, msg) { + croak(msg, token.line, token.col); + }; + + function unexpected(token) { + if (token == null) + token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + }; + + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type); + }; + + function expect(punc) { return expect_token("punc", punc); }; + + function can_insert_semicolon() { + return !exigent_mode && ( + S.token.nlb || is("eof") || is("punc", "}") + ); + }; + + function semicolon() { + if (is("punc", ";")) next(); + else if (!can_insert_semicolon()) unexpected(); + }; + + function as() { + return slice(arguments); + }; + + function parenthesised() { + expect("("); + var ex = expression(); + expect(")"); + return ex; + }; + + function add_tokens(str, start, end) { + return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end); + }; + + function maybe_embed_tokens(parser) { + if (embed_tokens) return function() { + var start = S.token; + var ast = parser.apply(this, arguments); + ast[0] = add_tokens(ast[0], start, prev()); + return ast; + }; + else return parser; + }; + + var statement = maybe_embed_tokens(function() { + if (is("operator", "/")) { + S.peeked = null; + S.token = S.input(true); // force regexp + } + switch (S.token.type) { + case "num": + case "string": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") + ? labeled_statement(prog1(S.token.value, next, next)) + : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return as("block", block_()); + case "[": + case "(": + return simple_statement(); + case ";": + next(); + return as("block"); + default: + unexpected(); + } + + case "keyword": + switch (prog1(S.token.value, next)) { + case "break": + return break_cont("break"); + + case "continue": + return break_cont("continue"); + + case "debugger": + semicolon(); + return as("debugger"); + + case "do": + return (function(body){ + expect_token("keyword", "while"); + return as("do", prog1(parenthesised, semicolon), body); + })(in_loop(statement)); + + case "for": + return for_(); + + case "function": + return function_(true); + + case "if": + return if_(); + + case "return": + if (S.in_function == 0) + croak("'return' outside of function"); + return as("return", + is("punc", ";") + ? (next(), null) + : can_insert_semicolon() + ? null + : prog1(expression, semicolon)); + + case "switch": + return as("switch", parenthesised(), switch_block_()); + + case "throw": + return as("throw", prog1(expression, semicolon)); + + case "try": + return try_(); + + case "var": + return prog1(var_, semicolon); + + case "const": + return prog1(const_, semicolon); + + case "while": + return as("while", parenthesised(), in_loop(statement)); + + case "with": + return as("with", parenthesised(), statement()); + + default: + unexpected(); + } + } + }); + + function labeled_statement(label) { + S.labels.push(label); + var start = S.token, stat = statement(); + if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0])) + unexpected(start); + S.labels.pop(); + return as("label", label, stat); + }; + + function simple_statement() { + return as("stat", prog1(expression, semicolon)); + }; + + function break_cont(type) { + var name; + if (!can_insert_semicolon()) { + name = is("name") ? S.token.value : null; + } + if (name != null) { + next(); + if (!member(name, S.labels)) + croak("Label " + name + " without matching loop or statement"); + } + else if (S.in_loop == 0) + croak(type + " not inside a loop or switch"); + semicolon(); + return as(type, name); + }; + + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") + ? (next(), var_(true)) + : expression(true, true); + if (is("operator", "in")) + return for_in(init); + } + return regular_for(init); + }; + + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(); + expect(";"); + var step = is("punc", ")") ? null : expression(); + expect(")"); + return as("for", init, test, step, in_loop(statement)); + }; + + function for_in(init) { + var lhs = init[0] == "var" ? as("name", init[1][0]) : init; + next(); + var obj = expression(); + expect(")"); + return as("for-in", init, lhs, obj, in_loop(statement)); + }; + + var function_ = maybe_embed_tokens(function(in_statement) { + var name = is("name") ? prog1(S.token.value, next) : null; + if (in_statement && !name) + unexpected(); + expect("("); + return as(in_statement ? "defun" : "function", + name, + // arguments + (function(first, a){ + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + if (!is("name")) unexpected(); + a.push(S.token.value); + next(); + } + next(); + return a; + })(true, []), + // body + (function(){ + ++S.in_function; + var loop = S.in_loop; + S.in_loop = 0; + var a = block_(); + --S.in_function; + S.in_loop = loop; + return a; + })()); + }); + + function if_() { + var cond = parenthesised(), body = statement(), belse; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return as("if", cond, body, belse); + }; + + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + }; + + var switch_block_ = curry(in_loop, function(){ + expect("{"); + var a = [], cur = null; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { + next(); + cur = []; + a.push([ expression(), cur ]); + expect(":"); + } + else if (is("keyword", "default")) { + next(); + expect(":"); + cur = []; + a.push([ null, cur ]); + } + else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + next(); + return a; + }); + + function try_() { + var body = block_(), bcatch, bfinally; + if (is("keyword", "catch")) { + next(); + expect("("); + if (!is("name")) + croak("Name expected"); + var name = S.token.value; + next(); + expect(")"); + bcatch = [ name, block_() ]; + } + if (is("keyword", "finally")) { + next(); + bfinally = block_(); + } + if (!bcatch && !bfinally) + croak("Missing catch/finally blocks"); + return as("try", body, bcatch, bfinally); + }; + + function vardefs(no_in) { + var a = []; + for (;;) { + if (!is("name")) + unexpected(); + var name = S.token.value; + next(); + if (is("operator", "=")) { + next(); + a.push([ name, expression(false, no_in) ]); + } else { + a.push([ name ]); + } + if (!is("punc", ",")) + break; + next(); + } + return a; + }; + + function var_(no_in) { + return as("var", vardefs(no_in)); + }; + + function const_() { + return as("const", vardefs()); + }; + + function new_() { + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(as("new", newexp, args), true); + }; + + var expr_atom = maybe_embed_tokens(function(allow_calls) { + if (is("operator", "new")) { + next(); + return new_(); + } + if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) { + return make_unary("unary-prefix", + prog1(S.token.value, next), + expr_atom(allow_calls)); + } + if (is("punc")) { + switch (S.token.value) { + case "(": + next(); + return subscripts(prog1(expression, curry(expect, ")")), allow_calls); + case "[": + next(); + return subscripts(array_(), allow_calls); + case "{": + next(); + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + return subscripts(function_(false), allow_calls); + } + if (HOP(ATOMIC_START_TOKEN, S.token.type)) { + var atom = S.token.type == "regexp" + ? as("regexp", S.token.value[0], S.token.value[1]) + : as(S.token.type, S.token.value); + return subscripts(prog1(atom, next), allow_calls); + } + unexpected(); + }); + + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push([ "atom", "undefined" ]); + } else { + a.push(expression(false)); + } + } + next(); + return a; + }; + + function array_() { + return as("array", expr_list("]", !exigent_mode, true)); + }; + + function object_() { + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!exigent_mode && is("punc", "}")) + // allow trailing comma + break; + var type = S.token.type; + var name = as_property_name(); + if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) { + a.push([ as_name(), function_(false), name ]); + } else { + expect(":"); + a.push([ name, expression(false) ]); + } + } + next(); + return as("object", a); + }; + + function as_property_name() { + switch (S.token.type) { + case "num": + case "string": + return prog1(S.token.value, next); + } + return as_name(); + }; + + function as_name() { + switch (S.token.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return prog1(S.token.value, next); + default: + unexpected(); + } + }; + + function subscripts(expr, allow_calls) { + if (is("punc", ".")) { + next(); + return subscripts(as("dot", expr, as_name()), allow_calls); + } + if (is("punc", "[")) { + next(); + return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(as("call", expr, expr_list(")")), true); + } + if (allow_calls && is("operator") && HOP(UNARY_POSTFIX, S.token.value)) { + return prog1(curry(make_unary, "unary-postfix", S.token.value, expr), + next); + } + return expr; + }; + + function make_unary(tag, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) + croak("Invalid use of " + op + " operator"); + return as(tag, op, expr); + }; + + function expr_op(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op && op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(expr_atom(true), prec, no_in); + return expr_op(as("binary", op, left, right), min_prec, no_in); + } + return left; + }; + + function expr_ops(no_in) { + return expr_op(expr_atom(true), 0, no_in); + }; + + function maybe_conditional(no_in) { + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return as("conditional", expr, yes, expression(false, no_in)); + } + return expr; + }; + + function is_assignable(expr) { + if (!exigent_mode) return true; + switch (expr[0]) { + case "dot": + case "sub": + case "new": + case "call": + return true; + case "name": + return expr[1] != "this"; + } + }; + + function maybe_assign(no_in) { + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && HOP(ASSIGNMENT, val)) { + if (is_assignable(left)) { + next(); + return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in)); + } + croak("Invalid assignment"); + } + return left; + }; + + var expression = maybe_embed_tokens(function(commas, no_in) { + if (arguments.length == 0) + commas = true; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return as("seq", expr, expression(true, no_in)); + } + return expr; + }); + + function in_loop(cont) { + try { + ++S.in_loop; + return cont(); + } finally { + --S.in_loop; + } + }; + + return as("toplevel", (function(a){ + while (!is("eof")) + a.push(statement()); + return a; + })([])); + +}; + +/* -----[ Utilities ]----- */ + +function curry(f) { + var args = slice(arguments, 1); + return function() { return f.apply(this, args.concat(slice(arguments))); }; +}; + +function prog1(ret) { + if (ret instanceof Function) + ret = ret(); + for (var i = 1, n = arguments.length; --n > 0; ++i) + arguments[i](); + return ret; +}; + +function array_to_hash(a) { + var ret = {}; + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start == null ? 0 : start); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] === name) + return true; + return false; +}; + +function HOP(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +var warn = function() {}; + +/* -----[ Exports ]----- */ + +exports.tokenizer = tokenizer; +exports.parse = parse; +exports.slice = slice; +exports.curry = curry; +exports.member = member; +exports.array_to_hash = array_to_hash; +exports.PRECEDENCE = PRECEDENCE; +exports.KEYWORDS_ATOM = KEYWORDS_ATOM; +exports.RESERVED_WORDS = RESERVED_WORDS; +exports.KEYWORDS = KEYWORDS; +exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN; +exports.OPERATORS = OPERATORS; +exports.is_alphanumeric_char = is_alphanumeric_char; +exports.set_logger = function(logger) { + warn = logger; +}; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/process.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"]._cached = module.exports; + + (function () { + /*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + + This version is suitable for Node.js. With minimal changes (the + exports stuff) it should work on any JS platform. + + This file implements some AST processors. They work on data built + by parse-js. + + Exported functions: + + - ast_mangle(ast, options) -- mangles the variable/function names + in the AST. Returns an AST. + + - ast_squeeze(ast) -- employs various optimizations to make the + final generated code even smaller. Returns an AST. + + - gen_code(ast, options) -- generates JS code from the AST. Pass + true (or an object, see the code for some options) as second + argument to get "pretty" (indented) code. + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2010 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +var jsp = require("./parse-js"), + slice = jsp.slice, + member = jsp.member, + PRECEDENCE = jsp.PRECEDENCE, + OPERATORS = jsp.OPERATORS; + +/* -----[ helper for AST traversal ]----- */ + +function ast_walker(ast) { + function _vardefs(defs) { + return [ this[0], MAP(defs, function(def){ + var a = [ def[0] ]; + if (def.length > 1) + a[1] = walk(def[1]); + return a; + }) ]; + }; + function _block(statements) { + var out = [ this[0] ]; + if (statements != null) + out.push(MAP(statements, walk)); + return out; + }; + var walkers = { + "string": function(str) { + return [ this[0], str ]; + }, + "num": function(num) { + return [ this[0], num ]; + }, + "name": function(name) { + return [ this[0], name ]; + }, + "toplevel": function(statements) { + return [ this[0], MAP(statements, walk) ]; + }, + "block": _block, + "splice": _block, + "var": _vardefs, + "const": _vardefs, + "try": function(t, c, f) { + return [ + this[0], + MAP(t, walk), + c != null ? [ c[0], MAP(c[1], walk) ] : null, + f != null ? MAP(f, walk) : null + ]; + }, + "throw": function(expr) { + return [ this[0], walk(expr) ]; + }, + "new": function(ctor, args) { + return [ this[0], walk(ctor), MAP(args, walk) ]; + }, + "switch": function(expr, body) { + return [ this[0], walk(expr), MAP(body, function(branch){ + return [ branch[0] ? walk(branch[0]) : null, + MAP(branch[1], walk) ]; + }) ]; + }, + "break": function(label) { + return [ this[0], label ]; + }, + "continue": function(label) { + return [ this[0], label ]; + }, + "conditional": function(cond, t, e) { + return [ this[0], walk(cond), walk(t), walk(e) ]; + }, + "assign": function(op, lvalue, rvalue) { + return [ this[0], op, walk(lvalue), walk(rvalue) ]; + }, + "dot": function(expr) { + return [ this[0], walk(expr) ].concat(slice(arguments, 1)); + }, + "call": function(expr, args) { + return [ this[0], walk(expr), MAP(args, walk) ]; + }, + "function": function(name, args, body) { + return [ this[0], name, args.slice(), MAP(body, walk) ]; + }, + "defun": function(name, args, body) { + return [ this[0], name, args.slice(), MAP(body, walk) ]; + }, + "if": function(conditional, t, e) { + return [ this[0], walk(conditional), walk(t), walk(e) ]; + }, + "for": function(init, cond, step, block) { + return [ this[0], walk(init), walk(cond), walk(step), walk(block) ]; + }, + "for-in": function(vvar, key, hash, block) { + return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ]; + }, + "while": function(cond, block) { + return [ this[0], walk(cond), walk(block) ]; + }, + "do": function(cond, block) { + return [ this[0], walk(cond), walk(block) ]; + }, + "return": function(expr) { + return [ this[0], walk(expr) ]; + }, + "binary": function(op, left, right) { + return [ this[0], op, walk(left), walk(right) ]; + }, + "unary-prefix": function(op, expr) { + return [ this[0], op, walk(expr) ]; + }, + "unary-postfix": function(op, expr) { + return [ this[0], op, walk(expr) ]; + }, + "sub": function(expr, subscript) { + return [ this[0], walk(expr), walk(subscript) ]; + }, + "object": function(props) { + return [ this[0], MAP(props, function(p){ + return p.length == 2 + ? [ p[0], walk(p[1]) ] + : [ p[0], walk(p[1]), p[2] ]; // get/set-ter + }) ]; + }, + "regexp": function(rx, mods) { + return [ this[0], rx, mods ]; + }, + "array": function(elements) { + return [ this[0], MAP(elements, walk) ]; + }, + "stat": function(stat) { + return [ this[0], walk(stat) ]; + }, + "seq": function() { + return [ this[0] ].concat(MAP(slice(arguments), walk)); + }, + "label": function(name, block) { + return [ this[0], name, walk(block) ]; + }, + "with": function(expr, block) { + return [ this[0], walk(expr), walk(block) ]; + }, + "atom": function(name) { + return [ this[0], name ]; + } + }; + + var user = {}; + var stack = []; + function walk(ast) { + if (ast == null) + return null; + try { + stack.push(ast); + var type = ast[0]; + var gen = user[type]; + if (gen) { + var ret = gen.apply(ast, ast.slice(1)); + if (ret != null) + return ret; + } + gen = walkers[type]; + return gen.apply(ast, ast.slice(1)); + } finally { + stack.pop(); + } + }; + + function with_walkers(walkers, cont){ + var save = {}, i; + for (i in walkers) if (HOP(walkers, i)) { + save[i] = user[i]; + user[i] = walkers[i]; + } + var ret = cont(); + for (i in save) if (HOP(save, i)) { + if (!save[i]) delete user[i]; + else user[i] = save[i]; + } + return ret; + }; + + return { + walk: walk, + with_walkers: with_walkers, + parent: function() { + return stack[stack.length - 2]; // last one is current node + }, + stack: function() { + return stack; + } + }; +}; + +/* -----[ Scope and mangling ]----- */ + +function Scope(parent) { + this.names = {}; // names defined in this scope + this.mangled = {}; // mangled names (orig.name => mangled) + this.rev_mangled = {}; // reverse lookup (mangled => orig.name) + this.cname = -1; // current mangled name + this.refs = {}; // names referenced from this scope + this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes + this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes + this.parent = parent; // parent scope + this.children = []; // sub-scopes + if (parent) { + this.level = parent.level + 1; + parent.children.push(this); + } else { + this.level = 0; + } +}; + +var base54 = (function(){ + var DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"; + return function(num) { + var ret = ""; + do { + ret = DIGITS.charAt(num % 54) + ret; + num = Math.floor(num / 54); + } while (num > 0); + return ret; + }; +})(); + +Scope.prototype = { + has: function(name) { + for (var s = this; s; s = s.parent) + if (HOP(s.names, name)) + return s; + }, + has_mangled: function(mname) { + for (var s = this; s; s = s.parent) + if (HOP(s.rev_mangled, mname)) + return s; + }, + toJSON: function() { + return { + names: this.names, + uses_eval: this.uses_eval, + uses_with: this.uses_with + }; + }, + + next_mangled: function() { + // we must be careful that the new mangled name: + // + // 1. doesn't shadow a mangled name from a parent + // scope, unless we don't reference the original + // name from this scope OR from any sub-scopes! + // This will get slow. + // + // 2. doesn't shadow an original name from a parent + // scope, in the event that the name is not mangled + // in the parent scope and we reference that name + // here OR IN ANY SUBSCOPES! + // + // 3. doesn't shadow a name that is referenced but not + // defined (possibly global defined elsewhere). + for (;;) { + var m = base54(++this.cname), prior; + + // case 1. + prior = this.has_mangled(m); + if (prior && this.refs[prior.rev_mangled[m]] === prior) + continue; + + // case 2. + prior = this.has(m); + if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m)) + continue; + + // case 3. + if (HOP(this.refs, m) && this.refs[m] == null) + continue; + + // I got "do" once. :-/ + if (!is_identifier(m)) + continue; + + return m; + } + }, + set_mangle: function(name, m) { + this.rev_mangled[m] = name; + return this.mangled[name] = m; + }, + get_mangled: function(name, newMangle) { + if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use + var s = this.has(name); + if (!s) return name; // not in visible scope, no mangle + if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope + if (!newMangle) return name; // not found and no mangling requested + return s.set_mangle(name, s.next_mangled()); + }, + define: function(name) { + if (name != null) + return this.names[name] = name; + } +}; + +function ast_add_scope(ast) { + + var current_scope = null; + var w = ast_walker(), walk = w.walk; + var having_eval = []; + + function with_new_scope(cont) { + current_scope = new Scope(current_scope); + var ret = current_scope.body = cont(); + ret.scope = current_scope; + current_scope = current_scope.parent; + return ret; + }; + + function define(name) { + return current_scope.define(name); + }; + + function reference(name) { + current_scope.refs[name] = true; + }; + + function _lambda(name, args, body) { + var is_defun = this[0] == "defun"; + return [ this[0], is_defun ? define(name) : name, args, with_new_scope(function(){ + if (!is_defun) define(name); + MAP(args, define); + return MAP(body, walk); + })]; + }; + + return with_new_scope(function(){ + // process AST + var ret = w.with_walkers({ + "function": _lambda, + "defun": _lambda, + "with": function(expr, block) { + for (var s = current_scope; s; s = s.parent) + s.uses_with = true; + }, + "var": function(defs) { + MAP(defs, function(d){ define(d[0]) }); + }, + "const": function(defs) { + MAP(defs, function(d){ define(d[0]) }); + }, + "try": function(t, c, f) { + if (c != null) return [ + this[0], + MAP(t, walk), + [ define(c[0]), MAP(c[1], walk) ], + f != null ? MAP(f, walk) : null + ]; + }, + "name": function(name) { + if (name == "eval") + having_eval.push(current_scope); + reference(name); + } + }, function(){ + return walk(ast); + }); + + // the reason why we need an additional pass here is + // that names can be used prior to their definition. + + // scopes where eval was detected and their parents + // are marked with uses_eval, unless they define the + // "eval" name. + MAP(having_eval, function(scope){ + if (!scope.has("eval")) while (scope) { + scope.uses_eval = true; + scope = scope.parent; + } + }); + + // for referenced names it might be useful to know + // their origin scope. current_scope here is the + // toplevel one. + function fixrefs(scope, i) { + // do children first; order shouldn't matter + for (i = scope.children.length; --i >= 0;) + fixrefs(scope.children[i]); + for (i in scope.refs) if (HOP(scope.refs, i)) { + // find origin scope and propagate the reference to origin + for (var origin = scope.has(i), s = scope; s; s = s.parent) { + s.refs[i] = origin; + if (s === origin) break; + } + } + }; + fixrefs(current_scope); + + return ret; + }); + +}; + +/* -----[ mangle names ]----- */ + +function ast_mangle(ast, options) { + var w = ast_walker(), walk = w.walk, scope; + options = options || {}; + + function get_mangled(name, newMangle) { + if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel + if (options.except && member(name, options.except)) + return name; + return scope.get_mangled(name, newMangle); + }; + + function get_define(name) { + if (options.defines) { + // we always lookup a defined symbol for the current scope FIRST, so declared + // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value + if (!scope.has(name)) { + if (HOP(options.defines, name)) { + return options.defines[name]; + } + } + return null; + } + }; + + function _lambda(name, args, body) { + var is_defun = this[0] == "defun", extra; + if (name) { + if (is_defun) name = get_mangled(name); + else { + extra = {}; + name = extra[name] = scope.next_mangled(); + } + } + body = with_scope(body.scope, function(){ + args = MAP(args, function(name){ return get_mangled(name) }); + return MAP(body, walk); + }, extra); + return [ this[0], name, args, body ]; + }; + + function with_scope(s, cont, extra) { + var _scope = scope; + scope = s; + if (extra) for (var i in extra) if (HOP(extra, i)) { + s.set_mangle(i, extra[i]); + } + for (var i in s.names) if (HOP(s.names, i)) { + get_mangled(i, true); + } + var ret = cont(); + ret.scope = s; + scope = _scope; + return ret; + }; + + function _vardefs(defs) { + return [ this[0], MAP(defs, function(d){ + return [ get_mangled(d[0]), walk(d[1]) ]; + }) ]; + }; + + return w.with_walkers({ + "function": _lambda, + "defun": function() { + // move function declarations to the top when + // they are not in some block. + var ast = _lambda.apply(this, arguments); + switch (w.parent()[0]) { + case "toplevel": + case "function": + case "defun": + return MAP.at_top(ast); + } + return ast; + }, + "var": _vardefs, + "const": _vardefs, + "name": function(name) { + return get_define(name) || [ this[0], get_mangled(name) ]; + }, + "try": function(t, c, f) { + return [ this[0], + MAP(t, walk), + c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null, + f != null ? MAP(f, walk) : null ]; + }, + "toplevel": function(body) { + var self = this; + return with_scope(self.scope, function(){ + return [ self[0], MAP(body, walk) ]; + }); + } + }, function() { + return walk(ast_add_scope(ast)); + }); +}; + +/* -----[ + - compress foo["bar"] into foo.bar, + - remove block brackets {} where possible + - join consecutive var declarations + - various optimizations for IFs: + - if (cond) foo(); else bar(); ==> cond?foo():bar(); + - if (cond) foo(); ==> cond&&foo(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); // also for throw + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + ]----- */ + +var warn = function(){}; + +function best_of(ast1, ast2) { + return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1; +}; + +function last_stat(b) { + if (b[0] == "block" && b[1] && b[1].length > 0) + return b[1][b[1].length - 1]; + return b; +} + +function aborts(t) { + if (t) { + t = last_stat(t); + if (t[0] == "return" || t[0] == "break" || t[0] == "continue" || t[0] == "throw") + return true; + } +}; + +function boolean_expr(expr) { + return ( (expr[0] == "unary-prefix" + && member(expr[1], [ "!", "delete" ])) || + + (expr[0] == "binary" + && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) || + + (expr[0] == "binary" + && member(expr[1], [ "&&", "||" ]) + && boolean_expr(expr[2]) + && boolean_expr(expr[3])) || + + (expr[0] == "conditional" + && boolean_expr(expr[2]) + && boolean_expr(expr[3])) || + + (expr[0] == "assign" + && expr[1] === true + && boolean_expr(expr[3])) || + + (expr[0] == "seq" + && boolean_expr(expr[expr.length - 1])) + ); +}; + +function make_conditional(c, t, e) { + var make_real_conditional = function() { + if (c[0] == "unary-prefix" && c[1] == "!") { + return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ]; + } else { + return e ? [ "conditional", c, t, e ] : [ "binary", "&&", c, t ]; + } + }; + // shortcut the conditional if the expression has a constant value + return when_constant(c, function(ast, val){ + warn_unreachable(val ? e : t); + return (val ? t : e); + }, make_real_conditional); +}; + +function empty(b) { + return !b || (b[0] == "block" && (!b[1] || b[1].length == 0)); +}; + +function is_string(node) { + return (node[0] == "string" || + node[0] == "unary-prefix" && node[1] == "typeof" || + node[0] == "binary" && node[1] == "+" && + (is_string(node[2]) || is_string(node[3]))); +}; + +var when_constant = (function(){ + + var $NOT_CONSTANT = {}; + + // this can only evaluate constant expressions. If it finds anything + // not constant, it throws $NOT_CONSTANT. + function evaluate(expr) { + switch (expr[0]) { + case "string": + case "num": + return expr[1]; + case "name": + case "atom": + switch (expr[1]) { + case "true": return true; + case "false": return false; + } + break; + case "unary-prefix": + switch (expr[1]) { + case "!": return !evaluate(expr[2]); + case "typeof": return typeof evaluate(expr[2]); + case "~": return ~evaluate(expr[2]); + case "-": return -evaluate(expr[2]); + case "+": return +evaluate(expr[2]); + } + break; + case "binary": + var left = expr[2], right = expr[3]; + switch (expr[1]) { + case "&&" : return evaluate(left) && evaluate(right); + case "||" : return evaluate(left) || evaluate(right); + case "|" : return evaluate(left) | evaluate(right); + case "&" : return evaluate(left) & evaluate(right); + case "^" : return evaluate(left) ^ evaluate(right); + case "+" : return evaluate(left) + evaluate(right); + case "*" : return evaluate(left) * evaluate(right); + case "/" : return evaluate(left) / evaluate(right); + case "-" : return evaluate(left) - evaluate(right); + case "<<" : return evaluate(left) << evaluate(right); + case ">>" : return evaluate(left) >> evaluate(right); + case ">>>" : return evaluate(left) >>> evaluate(right); + case "==" : return evaluate(left) == evaluate(right); + case "===" : return evaluate(left) === evaluate(right); + case "!=" : return evaluate(left) != evaluate(right); + case "!==" : return evaluate(left) !== evaluate(right); + case "<" : return evaluate(left) < evaluate(right); + case "<=" : return evaluate(left) <= evaluate(right); + case ">" : return evaluate(left) > evaluate(right); + case ">=" : return evaluate(left) >= evaluate(right); + case "in" : return evaluate(left) in evaluate(right); + case "instanceof" : return evaluate(left) instanceof evaluate(right); + } + } + throw $NOT_CONSTANT; + }; + + return function(expr, yes, no) { + try { + var val = evaluate(expr), ast; + switch (typeof val) { + case "string": ast = [ "string", val ]; break; + case "number": ast = [ "num", val ]; break; + case "boolean": ast = [ "name", String(val) ]; break; + default: throw new Error("Can't handle constant of type: " + (typeof val)); + } + return yes.call(expr, ast, val); + } catch(ex) { + if (ex === $NOT_CONSTANT) { + if (expr[0] == "binary" + && (expr[1] == "===" || expr[1] == "!==") + && ((is_string(expr[2]) && is_string(expr[3])) + || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) { + expr[1] = expr[1].substr(0, 2); + } + else if (no && expr[0] == "binary" + && (expr[1] == "||" || expr[1] == "&&")) { + // the whole expression is not constant but the lval may be... + try { + var lval = evaluate(expr[2]); + expr = ((expr[1] == "&&" && (lval ? expr[3] : lval)) || + (expr[1] == "||" && (lval ? lval : expr[3])) || + expr); + } catch(ex2) { + // IGNORE... lval is not constant + } + } + return no ? no.call(expr, expr) : null; + } + else throw ex; + } + }; + +})(); + +function warn_unreachable(ast) { + if (!empty(ast)) + warn("Dropping unreachable code: " + gen_code(ast, true)); +}; + +function prepare_ifs(ast) { + var w = ast_walker(), walk = w.walk; + // In this first pass, we rewrite ifs which abort with no else with an + // if-else. For example: + // + // if (x) { + // blah(); + // return y; + // } + // foobar(); + // + // is rewritten into: + // + // if (x) { + // blah(); + // return y; + // } else { + // foobar(); + // } + function redo_if(statements) { + statements = MAP(statements, walk); + + for (var i = 0; i < statements.length; ++i) { + var fi = statements[i]; + if (fi[0] != "if") continue; + + if (fi[3] && walk(fi[3])) continue; + + var t = walk(fi[2]); + if (!aborts(t)) continue; + + var conditional = walk(fi[1]); + + var e_body = statements.slice(i + 1); + var e; + if (e_body.length == 1) e = e_body[0]; + else e = [ "block", e_body ]; + + var ret = statements.slice(0, i).concat([ [ + fi[0], // "if" + conditional, // conditional + t, // then + e // else + ] ]); + + return redo_if(ret); + } + + return statements; + }; + + function redo_if_lambda(name, args, body) { + body = redo_if(body); + return [ this[0], name, args.slice(), body ]; + }; + + function redo_if_block(statements) { + var out = [ this[0] ]; + if (statements != null) + out.push(redo_if(statements)); + return out; + }; + + return w.with_walkers({ + "defun": redo_if_lambda, + "function": redo_if_lambda, + "block": redo_if_block, + "splice": redo_if_block, + "toplevel": function(statements) { + return [ this[0], redo_if(statements) ]; + }, + "try": function(t, c, f) { + return [ + this[0], + redo_if(t), + c != null ? [ c[0], redo_if(c[1]) ] : null, + f != null ? redo_if(f) : null + ]; + }, + "with": function(expr, block) { + return [ this[0], walk(expr), redo_if(block) ]; + } + }, function() { + return walk(ast); + }); +}; + +function ast_squeeze(ast, options) { + options = defaults(options, { + make_seqs : true, + dead_code : true, + keep_comps : true, + no_warnings : false + }); + + var w = ast_walker(), walk = w.walk, scope; + + function negate(c) { + var not_c = [ "unary-prefix", "!", c ]; + switch (c[0]) { + case "unary-prefix": + return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c; + case "seq": + c = slice(c); + c[c.length - 1] = negate(c[c.length - 1]); + return c; + case "conditional": + return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]); + case "binary": + var op = c[1], left = c[2], right = c[3]; + if (!options.keep_comps) switch (op) { + case "<=" : return [ "binary", ">", left, right ]; + case "<" : return [ "binary", ">=", left, right ]; + case ">=" : return [ "binary", "<", left, right ]; + case ">" : return [ "binary", "<=", left, right ]; + } + switch (op) { + case "==" : return [ "binary", "!=", left, right ]; + case "!=" : return [ "binary", "==", left, right ]; + case "===" : return [ "binary", "!==", left, right ]; + case "!==" : return [ "binary", "===", left, right ]; + case "&&" : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]); + case "||" : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]); + } + break; + } + return not_c; + }; + + function with_scope(s, cont) { + var _scope = scope; + scope = s; + var ret = cont(); + ret.scope = s; + scope = _scope; + return ret; + }; + + function rmblock(block) { + if (block != null && block[0] == "block" && block[1]) { + if (block[1].length == 1) + block = block[1][0]; + else if (block[1].length == 0) + block = [ "block" ]; + } + return block; + }; + + function _lambda(name, args, body) { + var is_defun = this[0] == "defun"; + body = with_scope(body.scope, function(){ + var ret = tighten(MAP(body, walk), "lambda"); + if (!is_defun && name && !HOP(scope.refs, name)) + name = null; + return ret; + }); + return [ this[0], name, args, body ]; + }; + + // we get here for blocks that have been already transformed. + // this function does a few things: + // 1. discard useless blocks + // 2. join consecutive var declarations + // 3. remove obviously dead code + // 4. transform consecutive statements using the comma operator + // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... } + function tighten(statements, block_type) { + statements = statements.reduce(function(a, stat){ + if (stat[0] == "block") { + if (stat[1]) { + a.push.apply(a, stat[1]); + } + } else { + a.push(stat); + } + return a; + }, []); + + statements = (function(a, prev){ + statements.forEach(function(cur){ + if (prev && ((cur[0] == "var" && prev[0] == "var") || + (cur[0] == "const" && prev[0] == "const"))) { + prev[1] = prev[1].concat(cur[1]); + } else { + a.push(cur); + prev = cur; + } + }); + return a; + })([]); + + if (options.dead_code) statements = (function(a, has_quit){ + statements.forEach(function(st){ + if (has_quit) { + if (member(st[0], [ "function", "defun" , "var", "const" ])) { + a.push(st); + } + else if (!options.no_warnings) + warn_unreachable(st); + } + else { + a.push(st); + if (member(st[0], [ "return", "throw", "break", "continue" ])) + has_quit = true; + } + }); + return a; + })([]); + + if (options.make_seqs) statements = (function(a, prev) { + statements.forEach(function(cur){ + if (prev && prev[0] == "stat" && cur[0] == "stat") { + prev[1] = [ "seq", prev[1], cur[1] ]; + } else { + a.push(cur); + prev = cur; + } + }); + return a; + })([]); + + if (block_type == "lambda") statements = (function(i, a, stat){ + while (i < statements.length) { + stat = statements[i++]; + if (stat[0] == "if" && !stat[3]) { + if (stat[2][0] == "return" && stat[2][1] == null) { + a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ])); + break; + } + var last = last_stat(stat[2]); + if (last[0] == "return" && last[1] == null) { + a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ])); + break; + } + } + a.push(stat); + } + return a; + })(0, []); + + return statements; + }; + + function make_if(c, t, e) { + return when_constant(c, function(ast, val){ + if (val) { + warn_unreachable(e); + return t; + } else { + warn_unreachable(t); + return e; + } + }, function() { + return make_real_if(c, t, e); + }); + }; + + function make_real_if(c, t, e) { + c = walk(c); + t = walk(t); + e = walk(e); + + if (empty(t)) { + c = negate(c); + t = e; + e = null; + } else if (empty(e)) { + e = null; + } else { + // if we have both else and then, maybe it makes sense to switch them? + (function(){ + var a = gen_code(c); + var n = negate(c); + var b = gen_code(n); + if (b.length < a.length) { + var tmp = t; + t = e; + e = tmp; + c = n; + } + })(); + } + if (empty(e) && empty(t)) + return [ "stat", c ]; + var ret = [ "if", c, t, e ]; + if (t[0] == "if" && empty(t[3]) && empty(e)) { + ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ])); + } + else if (t[0] == "stat") { + if (e) { + if (e[0] == "stat") { + ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]); + } + } + else { + ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]); + } + } + else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) { + ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]); + } + else if (e && aborts(t)) { + ret = [ [ "if", c, t ] ]; + if (e[0] == "block") { + if (e[1]) ret = ret.concat(e[1]); + } + else { + ret.push(e); + } + ret = walk([ "block", ret ]); + } + else if (t && aborts(e)) { + ret = [ [ "if", negate(c), e ] ]; + if (t[0] == "block") { + if (t[1]) ret = ret.concat(t[1]); + } else { + ret.push(t); + } + ret = walk([ "block", ret ]); + } + return ret; + }; + + function _do_while(cond, body) { + return when_constant(cond, function(cond, val){ + if (!val) { + warn_unreachable(body); + return [ "block" ]; + } else { + return [ "for", null, null, null, walk(body) ]; + } + }); + }; + + ast = prepare_ifs(ast); + ast = ast_add_scope(ast); + + return w.with_walkers({ + "sub": function(expr, subscript) { + if (subscript[0] == "string") { + var name = subscript[1]; + if (is_identifier(name)) + return [ "dot", walk(expr), name ]; + else if (/^[1-9][0-9]*$/.test(name) || name === "0") + return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ]; + } + }, + "if": make_if, + "toplevel": function(body) { + return [ "toplevel", with_scope(this.scope, function(){ + return tighten(MAP(body, walk)); + }) ]; + }, + "switch": function(expr, body) { + var last = body.length - 1; + return [ "switch", walk(expr), MAP(body, function(branch, i){ + var block = tighten(MAP(branch[1], walk)); + if (i == last && block.length > 0) { + var node = block[block.length - 1]; + if (node[0] == "break" && !node[1]) + block.pop(); + } + return [ branch[0] ? walk(branch[0]) : null, block ]; + }) ]; + }, + "function": _lambda, + "defun": _lambda, + "block": function(body) { + if (body) return rmblock([ "block", tighten(MAP(body, walk)) ]); + }, + "binary": function(op, left, right) { + return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){ + return best_of(walk(c), this); + }, function no() { + return this; + }); + }, + "conditional": function(c, t, e) { + return make_conditional(walk(c), walk(t), walk(e)); + }, + "try": function(t, c, f) { + return [ + "try", + tighten(MAP(t, walk)), + c != null ? [ c[0], tighten(MAP(c[1], walk)) ] : null, + f != null ? tighten(MAP(f, walk)) : null + ]; + }, + "unary-prefix": function(op, expr) { + expr = walk(expr); + var ret = [ "unary-prefix", op, expr ]; + if (op == "!") + ret = best_of(ret, negate(expr)); + return when_constant(ret, function(ast, val){ + return walk(ast); // it's either true or false, so minifies to !0 or !1 + }, function() { return ret }); + }, + "name": function(name) { + switch (name) { + case "true": return [ "unary-prefix", "!", [ "num", 0 ]]; + case "false": return [ "unary-prefix", "!", [ "num", 1 ]]; + } + }, + "new": function(ctor, args) { + if (ctor[0] == "name" && ctor[1] == "Array" && !scope.has("Array")) { + if (args.length != 1) { + return [ "array", args ]; + } else { + return [ "call", [ "name", "Array" ], args ]; + } + } + }, + "call": function(expr, args) { + if (expr[0] == "name" && expr[1] == "Array" && args.length != 1 && !scope.has("Array")) { + return [ "array", args ]; + } + }, + "while": _do_while + }, function() { + return walk(ast); + }); +}; + +/* -----[ re-generate code from the AST ]----- */ + +var DOT_CALL_NO_PARENS = jsp.array_to_hash([ + "name", + "array", + "object", + "string", + "dot", + "sub", + "call", + "regexp" +]); + +function make_string(str, ascii_only) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\t": return "\\t"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + } + return s; + }); + if (ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; + else return '"' + str.replace(/\x22/g, '\\"') + '"'; +}; + +function to_ascii(str) { + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + while (code.length < 4) code = "0" + code; + return "\\u" + code; + }); +}; + +var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]); + +function gen_code(ast, options) { + options = defaults(options, { + indent_start : 0, + indent_level : 4, + quote_keys : false, + space_colon : false, + beautify : false, + ascii_only : false + }); + var beautify = !!options.beautify; + var indentation = 0, + newline = beautify ? "\n" : "", + space = beautify ? " " : ""; + + function encode_string(str) { + return make_string(str, options.ascii_only); + }; + + function make_name(name) { + name = name.toString(); + if (options.ascii_only) + name = to_ascii(name); + return name; + }; + + function indent(line) { + if (line == null) + line = ""; + if (beautify) + line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line; + return line; + }; + + function with_indent(cont, incr) { + if (incr == null) incr = 1; + indentation += incr; + try { return cont.apply(null, slice(arguments, 1)); } + finally { indentation -= incr; } + }; + + function add_spaces(a) { + if (beautify) + return a.join(" "); + var b = []; + for (var i = 0; i < a.length; ++i) { + var next = a[i + 1]; + b.push(a[i]); + if (next && + ((/[a-z0-9_\x24]$/i.test(a[i].toString()) && /^[a-z0-9_\x24]/i.test(next.toString())) || + (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString())))) { + b.push(" "); + } + } + return b.join(""); + }; + + function add_commas(a) { + return a.join("," + space); + }; + + function parenthesize(expr) { + var gen = make(expr); + for (var i = 1; i < arguments.length; ++i) { + var el = arguments[i]; + if ((el instanceof Function && el(expr)) || expr[0] == el) + return "(" + gen + ")"; + } + return gen; + }; + + function best_of(a) { + if (a.length == 1) { + return a[0]; + } + if (a.length == 2) { + var b = a[1]; + a = a[0]; + return a.length <= b.length ? a : b; + } + return best_of([ a[0], best_of(a.slice(1)) ]); + }; + + function needs_parens(expr) { + if (expr[0] == "function" || expr[0] == "object") { + // dot/call on a literal function requires the + // function literal itself to be parenthesized + // only if it's the first "thing" in a + // statement. This means that the parent is + // "stat", but it could also be a "seq" and + // we're the first in this "seq" and the + // parent is "stat", and so on. Messy stuff, + // but it worths the trouble. + var a = slice($stack), self = a.pop(), p = a.pop(); + while (p) { + if (p[0] == "stat") return true; + if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) || + ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) { + self = p; + p = a.pop(); + } else { + return false; + } + } + } + return !HOP(DOT_CALL_NO_PARENS, expr[0]); + }; + + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".") ], m; + if (Math.floor(num) === num) { + a.push("0x" + num.toString(16).toLowerCase(), // probably pointless + "0" + num.toString(8)); // same. + if ((m = /^(.*?)(0+)$/.exec(num))) { + a.push(m[1] + "e" + m[2].length); + } + } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { + a.push(m[2] + "e-" + (m[1].length + m[2].length), + str.substr(str.indexOf("."))); + } + return best_of(a); + }; + + var generators = { + "string": encode_string, + "num": make_num, + "name": make_name, + "toplevel": function(statements) { + return make_block_statements(statements) + .join(newline + newline); + }, + "splice": function(statements) { + var parent = $stack[$stack.length - 2][0]; + if (HOP(SPLICE_NEEDS_BRACKETS, parent)) { + // we need block brackets in this case + return make_block.apply(this, arguments); + } else { + return MAP(make_block_statements(statements, true), + function(line, i) { + // the first line is already indented + return i > 0 ? indent(line) : line; + }).join(newline); + } + }, + "block": make_block, + "var": function(defs) { + return "var " + add_commas(MAP(defs, make_1vardef)) + ";"; + }, + "const": function(defs) { + return "const " + add_commas(MAP(defs, make_1vardef)) + ";"; + }, + "try": function(tr, ca, fi) { + var out = [ "try", make_block(tr) ]; + if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1])); + if (fi) out.push("finally", make_block(fi)); + return add_spaces(out); + }, + "throw": function(expr) { + return add_spaces([ "throw", make(expr) ]) + ";"; + }, + "new": function(ctor, args) { + args = args.length > 0 ? "(" + add_commas(MAP(args, make)) + ")" : ""; + return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){ + var w = ast_walker(), has_call = {}; + try { + w.with_walkers({ + "call": function() { throw has_call }, + "function": function() { return this } + }, function(){ + w.walk(expr); + }); + } catch(ex) { + if (ex === has_call) + return true; + throw ex; + } + }) + args ]); + }, + "switch": function(expr, body) { + return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]); + }, + "break": function(label) { + var out = "break"; + if (label != null) + out += " " + make_name(label); + return out + ";"; + }, + "continue": function(label) { + var out = "continue"; + if (label != null) + out += " " + make_name(label); + return out + ";"; + }, + "conditional": function(co, th, el) { + return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?", + parenthesize(th, "seq"), ":", + parenthesize(el, "seq") ]); + }, + "assign": function(op, lvalue, rvalue) { + if (op && op !== true) op += "="; + else op = "="; + return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]); + }, + "dot": function(expr) { + var out = make(expr), i = 1; + if (expr[0] == "num") { + if (!/\./.test(expr[1])) + out += "."; + } else if (needs_parens(expr)) + out = "(" + out + ")"; + while (i < arguments.length) + out += "." + make_name(arguments[i++]); + return out; + }, + "call": function(func, args) { + var f = make(func); + if (needs_parens(func)) + f = "(" + f + ")"; + return f + "(" + add_commas(MAP(args, function(expr){ + return parenthesize(expr, "seq"); + })) + ")"; + }, + "function": make_function, + "defun": make_function, + "if": function(co, th, el) { + var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ]; + if (el) { + out.push("else", make(el)); + } + return add_spaces(out); + }, + "for": function(init, cond, step, block) { + var out = [ "for" ]; + init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space); + cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space); + step = (step != null ? make(step) : "").replace(/;*\s*$/, ""); + var args = init + cond + step; + if (args == "; ; ") args = ";;"; + out.push("(" + args + ")", make(block)); + return add_spaces(out); + }, + "for-in": function(vvar, key, hash, block) { + return add_spaces([ "for", "(" + + (vvar ? make(vvar).replace(/;+$/, "") : make(key)), + "in", + make(hash) + ")", make(block) ]); + }, + "while": function(condition, block) { + return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]); + }, + "do": function(condition, block) { + return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";"; + }, + "return": function(expr) { + var out = [ "return" ]; + if (expr != null) out.push(make(expr)); + return add_spaces(out) + ";"; + }, + "binary": function(operator, lvalue, rvalue) { + var left = make(lvalue), right = make(rvalue); + // XXX: I'm pretty sure other cases will bite here. + // we need to be smarter. + // adding parens all the time is the safest bet. + if (member(lvalue[0], [ "assign", "conditional", "seq" ]) || + lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]]) { + left = "(" + left + ")"; + } + if (member(rvalue[0], [ "assign", "conditional", "seq" ]) || + rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] && + !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) { + right = "(" + right + ")"; + } + return add_spaces([ left, operator, right ]); + }, + "unary-prefix": function(operator, expr) { + var val = make(expr); + if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) + val = "(" + val + ")"; + return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val; + }, + "unary-postfix": function(operator, expr) { + var val = make(expr); + if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) + val = "(" + val + ")"; + return val + operator; + }, + "sub": function(expr, subscript) { + var hash = make(expr); + if (needs_parens(expr)) + hash = "(" + hash + ")"; + return hash + "[" + make(subscript) + "]"; + }, + "object": function(props) { + if (props.length == 0) + return "{}"; + return "{" + newline + with_indent(function(){ + return MAP(props, function(p){ + if (p.length == 3) { + // getter/setter. The name is in p[0], the arg.list in p[1][2], the + // body in p[1][3] and type ("get" / "set") in p[2]. + return indent(make_function(p[0], p[1][2], p[1][3], p[2])); + } + var key = p[0], val = make(p[1]); + if (options.quote_keys) { + key = encode_string(key); + } else if ((typeof key == "number" || !beautify && +key + "" == key) + && parseFloat(key) >= 0) { + key = make_num(+key); + } else if (!is_identifier(key)) { + key = encode_string(key); + } + return indent(add_spaces(beautify && options.space_colon + ? [ key, ":", val ] + : [ key + ":", val ])); + }).join("," + newline); + }) + newline + indent("}"); + }, + "regexp": function(rx, mods) { + return "/" + rx + "/" + mods; + }, + "array": function(elements) { + if (elements.length == 0) return "[]"; + return add_spaces([ "[", add_commas(MAP(elements, function(el){ + if (!beautify && el[0] == "atom" && el[1] == "undefined") return ""; + return parenthesize(el, "seq"); + })), "]" ]); + }, + "stat": function(stmt) { + return make(stmt).replace(/;*\s*$/, ";"); + }, + "seq": function() { + return add_commas(MAP(slice(arguments), make)); + }, + "label": function(name, block) { + return add_spaces([ make_name(name), ":", make(block) ]); + }, + "with": function(expr, block) { + return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]); + }, + "atom": function(name) { + return make_name(name); + } + }; + + // The squeezer replaces "block"-s that contain only a single + // statement with the statement itself; technically, the AST + // is correct, but this can create problems when we output an + // IF having an ELSE clause where the THEN clause ends in an + // IF *without* an ELSE block (then the outer ELSE would refer + // to the inner IF). This function checks for this case and + // adds the block brackets if needed. + function make_then(th) { + if (th[0] == "do") { + // https://github.com/mishoo/UglifyJS/issues/#issue/57 + // IE croaks with "syntax error" on code like this: + // if (foo) do ... while(cond); else ... + // we need block brackets around do/while + return make([ "block", [ th ]]); + } + var b = th; + while (true) { + var type = b[0]; + if (type == "if") { + if (!b[3]) + // no else, we must add the block + return make([ "block", [ th ]]); + b = b[3]; + } + else if (type == "while" || type == "do") b = b[2]; + else if (type == "for" || type == "for-in") b = b[4]; + else break; + } + return make(th); + }; + + function make_function(name, args, body, keyword) { + var out = keyword || "function"; + if (name) { + out += " " + make_name(name); + } + out += "(" + add_commas(MAP(args, make_name)) + ")"; + return add_spaces([ out, make_block(body) ]); + }; + + function make_block_statements(statements, noindent) { + for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) { + var stat = statements[i]; + var code = make(stat); + if (code != ";") { + if (!beautify && i == last) { + if ((stat[0] == "while" && empty(stat[2])) || + (member(stat[0], [ "for", "for-in"] ) && empty(stat[4])) || + (stat[0] == "if" && empty(stat[2]) && !stat[3]) || + (stat[0] == "if" && stat[3] && empty(stat[3]))) { + code = code.replace(/;*\s*$/, ";"); + } else { + code = code.replace(/;+\s*$/, ""); + } + } + a.push(code); + } + } + return noindent ? a : MAP(a, indent); + }; + + function make_switch_block(body) { + var n = body.length; + if (n == 0) return "{}"; + return "{" + newline + MAP(body, function(branch, i){ + var has_body = branch[1].length > 0, code = with_indent(function(){ + return indent(branch[0] + ? add_spaces([ "case", make(branch[0]) + ":" ]) + : "default:"); + }, 0.5) + (has_body ? newline + with_indent(function(){ + return make_block_statements(branch[1]).join(newline); + }) : ""); + if (!beautify && has_body && i < n - 1) + code += ";"; + return code; + }).join(newline) + newline + indent("}"); + }; + + function make_block(statements) { + if (!statements) return ";"; + if (statements.length == 0) return "{}"; + return "{" + newline + with_indent(function(){ + return make_block_statements(statements).join(newline); + }) + newline + indent("}"); + }; + + function make_1vardef(def) { + var name = def[0], val = def[1]; + if (val != null) + name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]); + return name; + }; + + var $stack = []; + + function make(node) { + var type = node[0]; + var gen = generators[type]; + if (!gen) + throw new Error("Can't find generator for \"" + type + "\""); + $stack.push(node); + var ret = gen.apply(type, node.slice(1)); + $stack.pop(); + return ret; + }; + + return make(ast); +}; + +function split_lines(code, max_line_length) { + var splits = [ 0 ]; + jsp.parse(function(){ + var next_token = jsp.tokenizer(code); + var last_split = 0; + var prev_token; + function current_length(tok) { + return tok.pos - last_split; + }; + function split_here(tok) { + last_split = tok.pos; + splits.push(last_split); + }; + function custom(){ + var tok = next_token.apply(this, arguments); + out: { + if (prev_token) { + if (prev_token.type == "keyword") break out; + } + if (current_length(tok) > max_line_length) { + switch (tok.type) { + case "keyword": + case "atom": + case "name": + case "punc": + split_here(tok); + break out; + } + } + } + prev_token = tok; + return tok; + }; + custom.context = function() { + return next_token.context.apply(this, arguments); + }; + return custom; + }()); + return splits.map(function(pos, i){ + return code.substring(pos, splits[i + 1] || code.length); + }).join("\n"); +}; + +/* -----[ Utilities ]----- */ + +function repeat_string(str, i) { + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; +}; + +function defaults(args, defs) { + var ret = {}; + if (args === true) + args = {}; + for (var i in defs) if (HOP(defs, i)) { + ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; + } + return ret; +}; + +function is_identifier(name) { + return /^[a-z_$][a-z0-9_$]*$/i.test(name) + && name != "this" + && !HOP(jsp.KEYWORDS_ATOM, name) + && !HOP(jsp.RESERVED_WORDS, name) + && !HOP(jsp.KEYWORDS, name); +}; + +function HOP(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +// some utilities + +var MAP; + +(function(){ + MAP = function(a, f, o) { + var ret = []; + for (var i = 0; i < a.length; ++i) { + var val = f.call(o, a[i], i); + if (val instanceof AtTop) ret.unshift(val.v); + else ret.push(val); + } + return ret; + }; + MAP.at_top = function(val) { return new AtTop(val) }; + function AtTop(val) { this.v = val }; +})(); + +/* -----[ Exports ]----- */ + +exports.ast_walker = ast_walker; +exports.ast_mangle = ast_mangle; +exports.ast_squeeze = ast_squeeze; +exports.gen_code = gen_code; +exports.ast_add_scope = ast_add_scope; +exports.set_logger = function(logger) { warn = logger }; +exports.make_string = make_string; +exports.split_lines = split_lines; +exports.MAP = MAP; + +// keep this last! +exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"]._cached = module.exports; + + (function () { + var jsp = require("./parse-js"), + pro = require("./process"), + slice = jsp.slice, + member = jsp.member, + PRECEDENCE = jsp.PRECEDENCE, + OPERATORS = jsp.OPERATORS; + +function ast_squeeze_more(ast) { + var w = pro.ast_walker(), walk = w.walk; + return w.with_walkers({ + "call": function(expr, args) { + if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) { + // foo.toString() ==> foo+"" + return [ "binary", "+", expr[1], [ "string", "" ]]; + } + } + }, function() { + return walk(ast); + }); +}; + +exports.ast_squeeze_more = ast_squeeze_more; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/traverse/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/traverse"; + var __filename = "/node_modules/burrito/node_modules/traverse/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/traverse"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/traverse"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/traverse/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"traverse","version":"0.5.0","description":"Traverse and transform objects by visiting every node on a recursive walk","author":"James Halliday","license":"MIT/X11","main":"./index","repository":{"type":"git","url":"http://github.com/substack/js-traverse.git"},"devDependencies":{"expresso":"0.7.x"},"scripts":{"test":"expresso"}}; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/traverse/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/traverse/index.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/traverse"; + var __filename = "/node_modules/burrito/node_modules/traverse/index.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/traverse"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/traverse"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/traverse/index.js"]._cached = module.exports; + + (function () { + module.exports = Traverse; +function Traverse (obj) { + if (!(this instanceof Traverse)) return new Traverse(obj); + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = [], nodes = []; + + return (function clone (src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(Object_keys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); +}; + +function walk (root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker (node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node : node, + node_ : node_, + path : [].concat(path), + parent : parents[parents.length - 1], + parents : parents, + key : path.slice(-1)[0], + isRoot : path.length === 0, + level : path.length, + circular : null, + update : function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) keepGoing = false; + }, + 'delete' : function () { + delete state.parent.node[state.key]; + }, + remove : function () { + if (Array_isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + }, + keys : null, + before : function (f) { modifiers.before = f }, + after : function (f) { modifiers.after = f }, + pre : function (f) { modifiers.pre = f }, + post : function (f) { modifiers.post = f }, + stop : function () { alive = false }, + block : function () { keepGoing = false } + }; + + if (!alive) return state; + + if (typeof node === 'object' && node !== null) { + state.keys = Object_keys(node); + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + + if (modifiers.before) modifiers.before.call(state, state.node); + + if (!keepGoing) return state; + + if (typeof state.node == 'object' + && state.node !== null && !state.circular) { + parents.push(state); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && Object.hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == state.keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; +} + +function copy (src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (Array_isArray(src)) { + dst = []; + } + else if (src instanceof Date) { + dst = new Date(src); + } + else if (src instanceof Boolean) { + dst = new Boolean(src); + } + else if (src instanceof Number) { + dst = new Number(src); + } + else if (src instanceof String) { + dst = new String(src); + } + else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } + else if (src.__proto__ || src.constructor.prototype) { + var proto = src.__proto__ || src.constructor.prototype || {}; + var T = function () {}; + T.prototype = proto; + dst = new T; + if (!dst.__proto__) dst.__proto__ = proto; + } + + forEach(Object_keys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; +} + +var Object_keys = Object.keys || function keys (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +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); + } +}; + +forEach(Object_keys(Traverse.prototype), function (key) { + Traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = Traverse(obj); + return t[key].apply(t, args); + }; +}); +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/traverse/index.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["vm"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "."; + var __filename = "vm"; + + var require = function (file) { + return __require(file, "."); + }; + + require.resolve = function (file) { + return __require.resolve(name, "."); + }; + + require.modules = __require.modules; + __require.modules["vm"]._cached = module.exports; + + (function () { + 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 Script = exports.Script = function NodeScript (code) { + if (!(this instanceof Script)) return new Script(code); + this.code = code; +}; + +var iframe = document.createElement('iframe'); +if (!iframe.style) iframe.style = {}; +iframe.style.display = 'none'; + +var iframeCapable = true; // until proven otherwise +if (navigator.appName === 'Microsoft Internet Explorer') { + var m = navigator.appVersion.match(/\bMSIE (\d+\.\d+);/); + if (m && parseFloat(m[1]) <= 9.0) { + iframeCapable = false; + } +} + +Script.prototype.runInNewContext = function (context) { + if (!context) context = {}; + + if (!iframeCapable) { + var keys = Object_keys(context); + var args = []; + for (var i = 0; i < keys.length; i++) { + args.push(context[keys[i]]); + } + + var fn = Function(keys, this.code); + return fn.apply(null, args); + } + + document.body.appendChild(iframe); + + var win = iframe.contentWindow + || (window.frames && window.frames[window.frames.length - 1]) + || window[window.length - 1] + ; + + forEach(Object_keys(context), function (key) { + win[key] = context[key]; + iframe[key] = context[key]; + }); + + if (win.eval) { + // chrome and ff can just .eval() + var res = win.eval(this.code); + } + else { + // this works in IE9 but not anything newer + iframe.setAttribute('src', + 'javascript:__browserifyVmResult=(' + this.code + ')' + ); + if ('__browserifyVmResult' in win) { + var res = win.__browserifyVmResult; + } + else { + iframeCapable = false; + res = this.runInThisContext(context); + } + } + + forEach(Object_keys(win), function (key) { + context[key] = win[key]; + }); + + document.body.removeChild(iframe); + + return res; +}; + +Script.prototype.runInThisContext = function () { + return eval(this.code); // maybe... +}; + +Script.prototype.runInContext = function (context) { + // seems to be just runInNewContext on magical context objects which are + // otherwise indistinguishable from objects except plain old objects + // for the parameter segfaults node + return this.runInNewContext(context); +}; + +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) { + // not really sure what this one does + // seems to just make a shallow copy + var copy = {}; + forEach(Object_keys(context), function (key) { + copy[key] = context[key]; + }); + return copy; +}; +; + }).call(module.exports); + + __require.modules["vm"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify"; + var __filename = "/node_modules/jsonify/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"jsonify","version":"0.0.0","description":"JSON without touching any globals","main":"index.js","directories":{"lib":".","test":"test"},"devDependencies":{"tap":"0.0.x","garbage":"0.0.x"},"scripts":{"test":"tap test"},"repository":{"type":"git","url":"http://github.com/substack/jsonify.git"},"keywords":["json","browser"],"author":{"name":"Douglas Crockford","url":"http://crockford.com/"},"license":"Public Domain"}; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/index.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify"; + var __filename = "/node_modules/jsonify/index.js"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/index.js"]._cached = module.exports; + + (function () { + exports.parse = require('./lib/parse'); +exports.stringify = require('./lib/stringify'); +; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/index.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/lib/parse.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify/lib"; + var __filename = "/node_modules/jsonify/lib/parse.js"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/lib/parse.js"]._cached = module.exports; + + (function () { + var at, // The index of the current character + ch, // The current character + escapee = { + '"': '"', + '\\': '\\', + '/': '/', + b: '\b', + f: '\f', + n: '\n', + r: '\r', + t: '\t' + }, + text, + + error = function (m) { + // Call error when something is wrong. + throw { + name: 'SyntaxError', + message: m, + at: at, + text: text + }; + }, + + next = function (c) { + // If a c parameter is provided, verify that it matches the current character. + if (c && c !== ch) { + error("Expected '" + c + "' instead of '" + ch + "'"); + } + + // Get the next character. When there are no more characters, + // return the empty string. + + ch = text.charAt(at); + at += 1; + return ch; + }, + + number = function () { + // Parse a number value. + var number, + string = ''; + + if (ch === '-') { + string = '-'; + next('-'); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + if (ch === '.') { + string += '.'; + while (next() && ch >= '0' && ch <= '9') { + string += ch; + } + } + if (ch === 'e' || ch === 'E') { + string += ch; + next(); + if (ch === '-' || ch === '+') { + string += ch; + next(); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + } + number = +string; + if (!isFinite(number)) { + error("Bad number"); + } else { + return number; + } + }, + + string = function () { + // Parse a string value. + var hex, + i, + string = '', + uffff; + + // When parsing for string values, we must look for " and \ characters. + if (ch === '"') { + while (next()) { + if (ch === '"') { + next(); + return string; + } else if (ch === '\\') { + next(); + if (ch === 'u') { + uffff = 0; + for (i = 0; i < 4; i += 1) { + hex = parseInt(next(), 16); + if (!isFinite(hex)) { + break; + } + uffff = uffff * 16 + hex; + } + string += String.fromCharCode(uffff); + } else if (typeof escapee[ch] === 'string') { + string += escapee[ch]; + } else { + break; + } + } else { + string += ch; + } + } + } + error("Bad string"); + }, + + white = function () { + +// Skip whitespace. + + while (ch && ch <= ' ') { + next(); + } + }, + + word = function () { + +// true, false, or null. + + switch (ch) { + case 't': + next('t'); + next('r'); + next('u'); + next('e'); + return true; + case 'f': + next('f'); + next('a'); + next('l'); + next('s'); + next('e'); + return false; + case 'n': + next('n'); + next('u'); + next('l'); + next('l'); + return null; + } + error("Unexpected '" + ch + "'"); + }, + + value, // Place holder for the value function. + + array = function () { + +// Parse an array value. + + var array = []; + + if (ch === '[') { + next('['); + white(); + if (ch === ']') { + next(']'); + return array; // empty array + } + while (ch) { + array.push(value()); + white(); + if (ch === ']') { + next(']'); + return array; + } + next(','); + white(); + } + } + error("Bad array"); + }, + + object = function () { + +// Parse an object value. + + var key, + object = {}; + + if (ch === '{') { + next('{'); + white(); + if (ch === '}') { + next('}'); + return object; // empty object + } + while (ch) { + key = string(); + white(); + next(':'); + if (Object.hasOwnProperty.call(object, key)) { + error('Duplicate key "' + key + '"'); + } + object[key] = value(); + white(); + if (ch === '}') { + next('}'); + return object; + } + next(','); + white(); + } + } + error("Bad object"); + }; + +value = function () { + +// Parse a JSON value. It could be an object, an array, a string, a number, +// or a word. + + white(); + switch (ch) { + case '{': + return object(); + case '[': + return array(); + case '"': + return string(); + case '-': + return number(); + default: + return ch >= '0' && ch <= '9' ? number() : word(); + } +}; + +// Return the json_parse function. It will have access to all of the above +// functions and variables. + +module.exports = function (source, reviver) { + var result; + + text = source; + at = 0; + ch = ' '; + result = value(); + white(); + if (ch) { + error("Syntax error"); + } + + // If there is a reviver function, we recursively walk the new structure, + // passing each name/value pair to the reviver function for possible + // transformation, starting with a temporary root object that holds the result + // in an empty key. If there is not a reviver function, we simply return the + // result. + + return typeof reviver === 'function' ? (function walk(holder, key) { + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + }({'': result}, '')) : result; +}; +; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/lib/parse.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/lib/stringify.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify/lib"; + var __filename = "/node_modules/jsonify/lib/stringify.js"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/lib/stringify.js"]._cached = module.exports; + + (function () { + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + +function quote(string) { + // If the string contains no control characters, no quote characters, and no + // backslash characters, then we can safely slap some quotes around it. + // Otherwise we must also replace the offending characters with safe escape + // sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; +} + +function str(key, holder) { + // Produce a string from holder[key]. + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + + // If the value has a toJSON method, call it to obtain a replacement value. + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + + // If we were called with a replacer function, then call the replacer to + // obtain a replacement value. + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + + // What happens next depends on the value's type. + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + // JSON numbers must be finite. Encode non-finite numbers as null. + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + // If the value is a boolean or null, convert it to a string. Note: + // typeof null does not produce 'null'. The case is included here in + // the remote chance that this gets fixed someday. + return String(value); + + case 'object': + if (!value) return 'null'; + gap += indent; + partial = []; + + // Array.isArray + if (Object.prototype.toString.apply(value) === '[object Array]') { + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + + // Join all of the elements together, separated with commas, and + // wrap them in brackets. + v = partial.length === 0 ? '[]' : gap ? + '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + + // If the replacer is an array, use it to select the members to be + // stringified. + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + else { + // Otherwise, iterate through all of the keys in the object. + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + + // Join all of the member texts together, separated with commas, + // and wrap them in braces. + + v = partial.length === 0 ? '{}' : gap ? + '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : + '{' + partial.join(',') + '}'; + gap = mind; + return v; + } +} + +module.exports = function (value, replacer, space) { + var i; + gap = ''; + indent = ''; + + // If the space parameter is a number, make an indent string containing that + // many spaces. + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + } + // If the space parameter is a string, it will be used as the indent string. + else if (typeof space === 'string') { + indent = space; + } + + // If there is a replacer, it must be a function or an array. + // Otherwise, throw an error. + rep = replacer; + if (replacer && typeof replacer !== 'function' + && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + + // Make a fake root object containing our value under the key of ''. + // Return the result of stringifying the value. + return str('', {'': value}); +}; +; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/lib/stringify.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/index.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito"; + var __filename = "/node_modules/burrito/index.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/index.js"]._cached = module.exports; + + (function () { + var uglify = require('uglify-js'); +var parser = uglify.parser; +var parse = function (expr) { + if (typeof expr !== 'string') throw 'expression should be a string'; + + //try { + var args = [].slice.call(arguments); + var ast = parser.parse.apply(null, args); + /* } + catch (err) { + if (err.message === undefined + || err.line === undefined + || err.col === undefined + || err.pos === undefined + ) { throw err } + + var e = new SyntaxError( + err.message + + '\n at line ' + err.line + ':' + err.col + ' in expression:\n\n' + + ' ' + expr.split(/\r?\n/)[err.line] + ); + + e.original = err; + e.line = err.line; + e.col = err.col; + e.pos = err.pos; + throw e; + } + */ + return ast; +}; + +var deparse = function (ast, b) { + return uglify.uglify.gen_code(ast, { beautify : b }); +}; + +var traverse = require('traverse'); +var vm = require('vm'); + +var burrito = module.exports = function (code, cb) { + var ast = Array_isArray(code) + ? code // already an ast + : parse(code.toString(), false, true) + ; + + var ast_ = traverse(ast).map(function mapper () { + wrapNode(this, cb); + }); + + return deparse(parse(deparse(ast_)), true); +}; + +var wrapNode = burrito.wrapNode = function (state, cb) { + var node = state.node; + + var ann = Array_isArray(node) && node[0] + && typeof node[0] === 'object' && node[0].name + ? node[0] + : null + ; + + if (!ann) return undefined; + + var self = { + name : ann.name, + node : node, + start : node[0].start, + end : node[0].end, + value : node.slice(1), + state : state + }; + + self.wrap = function (s) { + var subsrc = deparse( + traverse(node).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + }) + ); + + if (self.name === 'binary') { + var a = deparse(traverse(node[2]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + var b = deparse(traverse(node[3]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + } + + var src = ''; + + if (typeof s === 'function') { + if (self.name === 'binary') { + src = s(subsrc, a, b); + } + else { + src = s(subsrc); + } + } + else { + src = s.toString() + .replace(/%s/g, function () { + return subsrc + }) + ; + + if (self.name === 'binary') { + src = src + .replace(/%a/g, function () { return a }) + .replace(/%b/g, function () { return b }) + ; + } + } + + var expr = parse(src); + state.update(expr, true); + }; + + var cache = {}; + + self.parent = state.isRoot ? null : function () { + if (!cache.parent) { + var s = state; + var x; + do { + s = s.parent; + if (s) x = wrapNode(s); + } while (s && !x); + + cache.parent = x; + } + + return cache.parent; + }; + + self.source = function () { + if (!cache.source) cache.source = deparse(node); + return cache.source; + }; + + self.label = function () { + return burrito.label(self); + }; + + if (cb) cb.call(state, self); + + if (self.node[0].name === 'conditional') { + self.wrap('[%s][0]'); + } + + return self; +} + +burrito.microwave = function (code, context, cb) { + if (!cb) { cb = context; context = {} }; + if (!context) context = {}; + + var src = burrito(code, cb); + return vm.runInNewContext(src, context); +}; + +burrito.generateName = function (len) { + var name = ''; + var lower = '$'.charCodeAt(0); + var upper = 'z'.charCodeAt(0); + + while (name.length < len) { + var c = String.fromCharCode(Math.floor( + Math.random() * (upper - lower + 1) + lower + )); + if ((name + c).match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) name += c; + } + + return name; +}; + +burrito.parse = parse; +burrito.deparse = deparse; + +burrito.label = function (node) { + if (node.name === 'call') { + if (typeof node.value[0] === 'string') { + return node.value[0]; + } + else if (node.value[0] && typeof node.value[0][1] === 'string') { + return node.value[0][1]; + } + else { + return null; + } + } + else if (node.name === 'var') { + return node.value[0].map(function (x) { return x[0] }); + } + else if (node.name === 'defun') { + return node.value[0]; + } + else if (node.name === 'function') { + return node.value[0]; + } + else { + return null; + } +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/index.js"]._cached = module.exports; + return module.exports; +}; + +process.nextTick(function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/"; + var __filename = "//home/substack/projects/node-burrito/example/web"; + + var require = function (file) { + return __require(file, "/"); + }; + require.modules = __require.modules; + + var burrito = require('burrito'); +var json = require('jsonify'); + +var src = [ + 'function f () { g() }', + 'function g () { h() }', + 'function h () { throw "moo" + Array(x).join("!") }', + 'var x = 4', + 'f()' +].join('\r\n'); + +window.onload = function () { + burrito(src, function (node) { + document.body.innerHTML += node.name + '
\n'; + }); +}; +if (document.readyState === 'complete') window.onload(); +; +}); diff --git a/node_modules/burrito/example/web/index.html b/node_modules/burrito/example/web/index.html new file mode 100644 index 0000000..66804fb --- /dev/null +++ b/node_modules/burrito/example/web/index.html @@ -0,0 +1,14 @@ + + + + + + +

+
+
diff --git a/node_modules/burrito/example/web/main.js b/node_modules/burrito/example/web/main.js
new file mode 100644
index 0000000..cc81a8b
--- /dev/null
+++ b/node_modules/burrito/example/web/main.js
@@ -0,0 +1,17 @@
+var burrito = require('burrito');
+var json = require('jsonify');
+
+var src = [
+    'function f () { g() }',
+    'function g () { h() }',
+    'function h () { throw "moo" + Array(x).join("!") }',
+    'var x = 4',
+    'f()'
+].join('\r\n');
+
+window.onload = function () {
+    burrito(src, function (node) {
+        document.body.innerHTML += node.name + '
\n'; + }); +}; +if (document.readyState === 'complete') window.onload(); diff --git a/node_modules/burrito/example/web/server.js b/node_modules/burrito/example/web/server.js new file mode 100644 index 0000000..6bce020 --- /dev/null +++ b/node_modules/burrito/example/web/server.js @@ -0,0 +1,12 @@ +var express = require('express'); +var browserify = require('browserify'); + +var app = express.createServer(); +app.use(express.static(__dirname)); +app.use(browserify({ + entry : __dirname + '/main.js', + watch : true, +})); + +app.listen(8081); +console.log('Listening on :8081'); diff --git a/node_modules/burrito/example/wrap.js b/node_modules/burrito/example/wrap.js new file mode 100644 index 0000000..1642401 --- /dev/null +++ b/node_modules/burrito/example/wrap.js @@ -0,0 +1,7 @@ +var burrito = require('burrito'); + +var src = burrito('f() && g(h())\nfoo()', function (node) { + if (node.name === 'call') node.wrap('qqq(%s)'); +}); + +console.log(src); diff --git a/node_modules/burrito/index.js b/node_modules/burrito/index.js new file mode 100644 index 0000000..60ef569 --- /dev/null +++ b/node_modules/burrito/index.js @@ -0,0 +1,208 @@ +var uglify = require('uglify-js'); +var parser = uglify.parser; +var parse = function (expr) { + if (typeof expr !== 'string') throw 'expression should be a string'; + + try { + var ast = parser.parse.apply(null, arguments); + } + catch (err) { + if (err.message === undefined + || err.line === undefined + || err.col === undefined + || err.pos === undefined + ) { throw err } + + var e = new SyntaxError( + err.message + + '\n at line ' + err.line + ':' + err.col + ' in expression:\n\n' + + ' ' + expr.split(/\r?\n/)[err.line] + ); + + e.original = err; + e.line = err.line; + e.col = err.col; + e.pos = err.pos; + throw e; + } + return ast; +}; + +var deparse = function (ast, b) { + return uglify.uglify.gen_code(ast, { beautify : b }); +}; + +var traverse = require('traverse'); +var vm = require('vm'); + +var burrito = module.exports = function (code, cb) { + var ast = Array_isArray(code) + ? code // already an ast + : parse(code.toString(), false, true) + ; + + var ast_ = traverse(ast).map(function mapper () { + wrapNode(this, cb); + }); + + return deparse(parse(deparse(ast_)), true); +}; + +var wrapNode = burrito.wrapNode = function (state, cb) { + var node = state.node; + + var ann = Array_isArray(node) && node[0] + && typeof node[0] === 'object' && node[0].name + ? node[0] + : null + ; + + if (!ann) return undefined; + + var self = { + name : ann.name, + node : node, + start : node[0].start, + end : node[0].end, + value : node.slice(1), + state : state + }; + + self.wrap = function (s) { + var subsrc = deparse( + traverse(node).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + }) + ); + + if (self.name === 'binary') { + var a = deparse(traverse(node[2]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + var b = deparse(traverse(node[3]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + } + + var src = ''; + + if (typeof s === 'function') { + if (self.name === 'binary') { + src = s(subsrc, a, b); + } + else { + src = s(subsrc); + } + } + else { + src = s.toString() + .replace(/%s/g, function () { + return subsrc + }) + ; + + if (self.name === 'binary') { + src = src + .replace(/%a/g, function () { return a }) + .replace(/%b/g, function () { return b }) + ; + } + } + + var expr = parse(src); + state.update(expr, true); + }; + + var cache = {}; + + self.parent = state.isRoot ? null : function () { + if (!cache.parent) { + var s = state; + var x; + do { + s = s.parent; + if (s) x = wrapNode(s); + } while (s && !x); + + cache.parent = x; + } + + return cache.parent; + }; + + self.source = function () { + if (!cache.source) cache.source = deparse(node); + return cache.source; + }; + + self.label = function () { + return burrito.label(self); + }; + + if (cb) cb.call(state, self); + + if (self.node[0].name === 'conditional') { + self.wrap('[%s][0]'); + } + + return self; +} + +burrito.microwave = function (code, context, cb) { + if (!cb) { cb = context; context = {} }; + if (!context) context = {}; + + var src = burrito(code, cb); + return vm.runInNewContext(src, context); +}; + +burrito.generateName = function (len) { + var name = ''; + var lower = '$'.charCodeAt(0); + var upper = 'z'.charCodeAt(0); + + while (name.length < len) { + var c = String.fromCharCode(Math.floor( + Math.random() * (upper - lower + 1) + lower + )); + if ((name + c).match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) name += c; + } + + return name; +}; + +burrito.parse = parse; +burrito.deparse = deparse; + +burrito.label = function (node) { + if (node.name === 'call') { + if (typeof node.value[0] === 'string') { + return node.value[0]; + } + else if (node.value[0] && typeof node.value[0][1] === 'string') { + return node.value[0][1]; + } + else if (node.value[0][0] === 'dot') { + return node.value[0][node.value[0].length - 1]; + } + else { + return null; + } + } + else if (node.name === 'var') { + return node.value[0].map(function (x) { return x[0] }); + } + else if (node.name === 'defun') { + return node.value[0]; + } + else if (node.name === 'function') { + return node.value[0]; + } + else { + return null; + } +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; diff --git a/node_modules/burrito/node_modules/traverse/.npmignore b/node_modules/burrito/node_modules/traverse/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/burrito/node_modules/traverse/LICENSE b/node_modules/burrito/node_modules/traverse/LICENSE new file mode 100644 index 0000000..7b75500 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/LICENSE @@ -0,0 +1,24 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: +http://www.opensource.org/licenses/mit-license.php + +Copyright 2010 James Halliday (mail@substack.net) + +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. diff --git a/node_modules/burrito/node_modules/traverse/README.markdown b/node_modules/burrito/node_modules/traverse/README.markdown new file mode 100644 index 0000000..f86ef76 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/README.markdown @@ -0,0 +1,237 @@ +traverse +======== + +Traverse and transform objects by visiting every node on a recursive walk. + +examples +======== + +transform negative numbers in-place +----------------------------------- + +negative.js + +````javascript +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); +```` + +Output: + + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ] + +collect leaf nodes +------------------ + +leaves.js + +````javascript +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); +```` + +Output: + + [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +scrub circular references +------------------------- + +scrub.js: + +````javascript +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); +```` + +output: + + { a: 1, b: 2, c: [ 3, 4 ] } + +context +======= + +Each method that takes a callback has a context (its `this` object) with these +attributes: + +this.node +--------- + +The present node on the recursive walk + +this.path +--------- + +An array of string keys from the root to the present node + +this.parent +----------- + +The context of the node's parent. +This is `undefined` for the root node. + +this.key +-------- + +The name of the key of the present node in its parent. +This is `undefined` for the root node. + +this.isRoot, this.notRoot +------------------------- + +Whether the present node is the root node + +this.isLeaf, this.notLeaf +------------------------- + +Whether or not the present node is a leaf node (has no children) + +this.level +---------- + +Depth of the node within the traversal + +this.circular +------------- + +If the node equals one of its parents, the `circular` attribute is set to the +context of that parent and the traversal progresses no deeper. + +this.update(value, stopHere=false) +---------------------------------- + +Set a new value for the present node. + +All the elements in `value` will be recursively traversed unless `stopHere` is +true. + +this.remove(stopHere=false) +------------- + +Remove the current element from the output. If the node is in an Array it will +be spliced off. Otherwise it will be deleted from its parent. + +this.delete(stopHere=false) +------------- + +Delete the current element from its parent in the output. Calls `delete` even on +Arrays. + +this.before(fn) +--------------- + +Call this function before any of the children are traversed. + +You can assign into `this.keys` here to traverse in a custom order. + +this.after(fn) +-------------- + +Call this function after any of the children are traversed. + +this.pre(fn) +------------ + +Call this function before each of the children are traversed. + +this.post(fn) +------------- + +Call this function after each of the children are traversed. + +methods +======= + +.map(fn) +-------- + +Execute `fn` for each node in the object and return a new object with the +results of the walk. To update nodes in the result use `this.update(value)`. + +.forEach(fn) +------------ + +Execute `fn` for each node in the object but unlike `.map()`, when +`this.update()` is called it updates the object in-place. + +.reduce(fn, acc) +---------------- + +For each node in the object, perform a +[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function)) +with the return value of `fn(acc, node)`. + +If `acc` isn't specified, `acc` is set to the root object for the first step +and the root element is skipped. + +.paths() +-------- + +Return an `Array` of every possible non-cyclic path in the object. +Paths are `Array`s of string keys. + +.nodes() +-------- + +Return an `Array` of every node in the object. + +.clone() +-------- + +Create a deep clone of the object. + +install +======= + +Using [npm](http://npmjs.org) do: + + $ npm install traverse + +test +==== + +Using [expresso](http://github.com/visionmedia/expresso) do: + + $ expresso + + 100% wahoo, your stuff is not broken! + +in the browser +============== + +Use [browserify](https://github.com/substack/node-browserify) to run traverse in +the browser. + +traverse has been tested and works with: + +* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0 +* Firefox 3.5 +* Chrome 6.0 +* Opera 10.6 +* Safari 5.0 diff --git a/node_modules/burrito/node_modules/traverse/examples/json.js b/node_modules/burrito/node_modules/traverse/examples/json.js new file mode 100755 index 0000000..50d612e --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/examples/json.js @@ -0,0 +1,16 @@ +var traverse = require('traverse'); + +var id = 54; +var callbacks = {}; +var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + +var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } +}); + +console.dir(scrubbed); +console.dir(callbacks); diff --git a/node_modules/burrito/node_modules/traverse/examples/leaves.js b/node_modules/burrito/node_modules/traverse/examples/leaves.js new file mode 100755 index 0000000..c1b310b --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/examples/leaves.js @@ -0,0 +1,15 @@ +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); diff --git a/node_modules/burrito/node_modules/traverse/examples/negative.js b/node_modules/burrito/node_modules/traverse/examples/negative.js new file mode 100755 index 0000000..78608a0 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/examples/negative.js @@ -0,0 +1,8 @@ +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); diff --git a/node_modules/burrito/node_modules/traverse/examples/scrub.js b/node_modules/burrito/node_modules/traverse/examples/scrub.js new file mode 100755 index 0000000..5d15b91 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/examples/scrub.js @@ -0,0 +1,10 @@ +// scrub out circular references +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); diff --git a/node_modules/burrito/node_modules/traverse/examples/stringify.js b/node_modules/burrito/node_modules/traverse/examples/stringify.js new file mode 100755 index 0000000..167b68b --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/examples/stringify.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node +var traverse = require('traverse'); + +var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +var s = ''; +traverse(obj).forEach(function to_s (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + to_s(key); + s += ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'string') { + s += '"' + node.toString().replace(/"/g, '\\"') + '"'; + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } +}); + +console.log('JSON.stringify: ' + JSON.stringify(obj)); +console.log('this stringify: ' + s); diff --git a/node_modules/burrito/node_modules/traverse/index.js b/node_modules/burrito/node_modules/traverse/index.js new file mode 100644 index 0000000..038a1ad --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/index.js @@ -0,0 +1,267 @@ +module.exports = Traverse; +function Traverse (obj) { + if (!(this instanceof Traverse)) return new Traverse(obj); + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = [], nodes = []; + + return (function clone (src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(Object_keys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); +}; + +function walk (root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker (node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node : node, + node_ : node_, + path : [].concat(path), + parent : parents[parents.length - 1], + parents : parents, + key : path.slice(-1)[0], + isRoot : path.length === 0, + level : path.length, + circular : null, + update : function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) keepGoing = false; + }, + 'delete' : function (stopHere) { + delete state.parent.node[state.key]; + if (stopHere) keepGoing = false; + }, + remove : function (stopHere) { + if (Array_isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + if (stopHere) keepGoing = false; + }, + keys : null, + before : function (f) { modifiers.before = f }, + after : function (f) { modifiers.after = f }, + pre : function (f) { modifiers.pre = f }, + post : function (f) { modifiers.post = f }, + stop : function () { alive = false }, + block : function () { keepGoing = false } + }; + + if (!alive) return state; + + if (typeof node === 'object' && node !== null) { + state.keys = Object_keys(node); + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + + if (modifiers.before) modifiers.before.call(state, state.node); + + if (!keepGoing) return state; + + if (typeof state.node == 'object' + && state.node !== null && !state.circular) { + parents.push(state); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && Object.hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == state.keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; +} + +function copy (src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (Array_isArray(src)) { + dst = []; + } + else if (src instanceof Date) { + dst = new Date(src); + } + else if (src instanceof Boolean) { + dst = new Boolean(src); + } + else if (src instanceof Number) { + dst = new Number(src); + } + else if (src instanceof String) { + dst = new String(src); + } + else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } + else if (src.__proto__ || src.constructor.prototype) { + var proto = src.__proto__ || src.constructor.prototype || {}; + var T = function () {}; + T.prototype = proto; + dst = new T; + if (!dst.__proto__) dst.__proto__ = proto; + } + + forEach(Object_keys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; +} + +var Object_keys = Object.keys || function keys (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +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); + } +}; + +forEach(Object_keys(Traverse.prototype), function (key) { + Traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = Traverse(obj); + return t[key].apply(t, args); + }; +}); diff --git a/node_modules/burrito/node_modules/traverse/main.js b/node_modules/burrito/node_modules/traverse/main.js new file mode 100755 index 0000000..d562d37 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/main.js @@ -0,0 +1,10 @@ +// scrub out circular references +var traverse = require('./index.js'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); diff --git a/node_modules/burrito/node_modules/traverse/package.json b/node_modules/burrito/node_modules/traverse/package.json new file mode 100644 index 0000000..f86322a --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/package.json @@ -0,0 +1,18 @@ +{ + "name" : "traverse", + "version" : "0.5.2", + "description" : "Traverse and transform objects by visiting every node on a recursive walk", + "author" : "James Halliday", + "license" : "MIT/X11", + "main" : "./index", + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/js-traverse.git" + }, + "devDependencies" : { + "expresso" : "0.7.x" + }, + "scripts" : { + "test" : "expresso" + } +} diff --git a/node_modules/burrito/node_modules/traverse/test/circular.js b/node_modules/burrito/node_modules/traverse/test/circular.js new file mode 100644 index 0000000..9162601 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/circular.js @@ -0,0 +1,115 @@ +var assert = require('assert'); +var Traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); +var util = require('util'); + +exports.circular = function () { + var obj = { x : 3 }; + obj.y = obj; + var foundY = false; + Traverse(obj).forEach(function (x) { + if (this.path.join('') == 'y') { + assert.equal( + util.inspect(this.circular.node), + util.inspect(obj) + ); + foundY = true; + } + }); + assert.ok(foundY); +}; + +exports.deepCirc = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + + var times = 0; + Traverse(obj).forEach(function (x) { + if (this.circular) { + assert.deepEqual(this.circular.path, []); + assert.deepEqual(this.path, [ 'y', 2 ]); + times ++; + } + }); + + assert.deepEqual(times, 1); +}; + +exports.doubleCirc = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var circs = []; + Traverse(obj).forEach(function (x) { + if (this.circular) { + circs.push({ circ : this.circular, self : this, node : x }); + } + }); + + assert.deepEqual(circs[0].self.path, [ 'x', 3, 2 ]); + assert.deepEqual(circs[0].circ.path, []); + + assert.deepEqual(circs[1].self.path, [ 'y', 2 ]); + assert.deepEqual(circs[1].circ.path, []); + + assert.deepEqual(circs.length, 2); +}; + +exports.circDubForEach = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + Traverse(obj).forEach(function (x) { + if (this.circular) this.update('...'); + }); + + assert.deepEqual(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); +}; + +exports.circDubMap = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var c = Traverse(obj).map(function (x) { + if (this.circular) { + this.update('...'); + } + }); + + assert.deepEqual(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); +}; + +exports.circClone = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var clone = Traverse.clone(obj); + assert.ok(obj !== clone); + + assert.ok(clone.y[2] === clone); + assert.ok(clone.y[2] !== obj); + assert.ok(clone.x[3][2] === clone); + assert.ok(clone.x[3][2] !== obj); + assert.deepEqual(clone.x.slice(0,3), [1,2,3]); + assert.deepEqual(clone.y.slice(0,2), [4,5]); +}; + +exports.circMapScrub = function () { + var obj = { a : 1, b : 2 }; + obj.c = obj; + + var scrubbed = Traverse(obj).map(function (node) { + if (this.circular) this.remove(); + }); + assert.deepEqual( + Object.keys(scrubbed).sort(), + [ 'a', 'b' ] + ); + assert.ok(deepEqual(scrubbed, { a : 1, b : 2 })); + + assert.equal(obj.c, obj); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/date.js b/node_modules/burrito/node_modules/traverse/test/date.js new file mode 100644 index 0000000..4ca06dc --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/date.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports.dateEach = function () { + var obj = { x : new Date, y : 10, z : 5 }; + + var counts = {}; + + Traverse(obj).forEach(function (node) { + var t = (node instanceof Date && 'Date') || typeof node; + counts[t] = (counts[t] || 0) + 1; + }); + + assert.deepEqual(counts, { + object : 1, + Date : 1, + number : 2, + }); +}; + +exports.dateMap = function () { + var obj = { x : new Date, y : 10, z : 5 }; + + var res = Traverse(obj).map(function (node) { + if (typeof node === 'number') this.update(node + 100); + }); + + assert.ok(obj.x !== res.x); + assert.deepEqual(res, { + x : obj.x, + y : 110, + z : 105, + }); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/equal.js b/node_modules/burrito/node_modules/traverse/test/equal.js new file mode 100644 index 0000000..decc755 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/equal.js @@ -0,0 +1,220 @@ +var assert = require('assert'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.deepDates = function () { + assert.ok( + deepEqual( + { d : new Date, x : [ 1, 2, 3 ] }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'dates should be equal' + ); + + var d0 = new Date; + setTimeout(function () { + assert.ok( + !deepEqual( + { d : d0, x : [ 1, 2, 3 ], }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'microseconds should count in date equality' + ); + }, 5); +}; + +exports.deepCircular = function () { + var a = [1]; + a.push(a); // a = [ 1, *a ] + + var b = [1]; + b.push(a); // b = [ 1, [ 1, *a ] ] + + assert.ok( + !deepEqual(a, b), + 'circular ref mount points count towards equality' + ); + + var c = [1]; + c.push(c); // c = [ 1, *c ] + assert.ok( + deepEqual(a, c), + 'circular refs are structurally the same here' + ); + + var d = [1]; + d.push(a); // c = [ 1, [ 1, *d ] ] + assert.ok( + deepEqual(b, d), + 'non-root circular ref structural comparison' + ); +}; + +exports.deepInstances = function () { + assert.ok( + !deepEqual([ new Boolean(false) ], [ false ]), + 'boolean instances are not real booleans' + ); + + assert.ok( + !deepEqual([ new String('x') ], [ 'x' ]), + 'string instances are not real strings' + ); + + assert.ok( + !deepEqual([ new Number(4) ], [ 4 ]), + 'number instances are not real numbers' + ); + + assert.ok( + deepEqual([ new RegExp('x') ], [ /x/ ]), + 'regexp instances are real regexps' + ); + + assert.ok( + !deepEqual([ new RegExp(/./) ], [ /../ ]), + 'these regexps aren\'t the same' + ); + + assert.ok( + !deepEqual( + [ function (x) { return x * 2 } ], + [ function (x) { return x * 2 } ] + ), + 'functions with the same .toString() aren\'t necessarily the same' + ); + + var f = function (x) { return x * 2 }; + assert.ok( + deepEqual([ f ], [ f ]), + 'these functions are actually equal' + ); +}; + +exports.deepEqual = function () { + assert.ok( + !deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }), + 'arrays are not objects' + ); +}; + +exports.falsy = function () { + assert.ok( + !deepEqual([ undefined ], [ null ]), + 'null is not undefined!' + ); + + assert.ok( + !deepEqual([ null ], [ undefined ]), + 'undefined is not null!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'undefined is not null, however deeply!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); +}; + +exports.deletedArrayEqual = function () { + var xs = [ 1, 2, 3, 4 ]; + delete xs[2]; + + var ys = Object.create(Array.prototype); + ys[0] = 1; + ys[1] = 2; + ys[3] = 4; + + assert.ok( + deepEqual(xs, ys), + 'arrays with deleted elements are only equal to' + + ' arrays with similarly deleted elements' + ); + + assert.ok( + !deepEqual(xs, [ 1, 2, undefined, 4 ]), + 'deleted array elements cannot be undefined' + ); + + assert.ok( + !deepEqual(xs, [ 1, 2, null, 4 ]), + 'deleted array elements cannot be null' + ); +}; + +exports.deletedObjectEqual = function () { + var obj = { a : 1, b : 2, c : 3 }; + delete obj.c; + + assert.ok( + deepEqual(obj, { a : 1, b : 2 }), + 'deleted object elements should not show up' + ); + + assert.ok( + !deepEqual(obj, { a : 1, b : 2, c : undefined }), + 'deleted object elements are not undefined' + ); + + assert.ok( + !deepEqual(obj, { a : 1, b : 2, c : null }), + 'deleted object elements are not null' + ); +}; + +exports.emptyKeyEqual = function () { + assert.ok(!deepEqual( + { a : 1 }, { a : 1, '' : 55 } + )); +}; + +exports.deepArguments = function () { + assert.ok( + !deepEqual( + [ 4, 5, 6 ], + (function () { return arguments })(4, 5, 6) + ), + 'arguments are not arrays' + ); + + assert.ok( + deepEqual( + (function () { return arguments })(4, 5, 6), + (function () { return arguments })(4, 5, 6) + ), + 'arguments should equal' + ); +}; + +exports.deepUn = function () { + assert.ok(!deepEqual({ a : 1, b : 2 }, undefined)); + assert.ok(!deepEqual({ a : 1, b : 2 }, {})); + assert.ok(!deepEqual(undefined, { a : 1, b : 2 })); + assert.ok(!deepEqual({}, { a : 1, b : 2 })); + assert.ok(deepEqual(undefined, undefined)); + assert.ok(deepEqual(null, null)); + assert.ok(!deepEqual(undefined, null)); +}; + +exports.deepLevels = function () { + var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ]; + assert.ok(!deepEqual(xs, [])); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/instance.js b/node_modules/burrito/node_modules/traverse/test/instance.js new file mode 100644 index 0000000..8d73525 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/instance.js @@ -0,0 +1,17 @@ +var assert = require('assert'); +var Traverse = require('../'); +var EventEmitter = require('events').EventEmitter; + +exports['check instanceof on node elems'] = function () { + + var counts = { emitter : 0 }; + + Traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }]) + .forEach(function (node) { + if (node instanceof EventEmitter) counts.emitter ++; + }) + ; + + assert.equal(counts.emitter, 2); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/interface.js b/node_modules/burrito/node_modules/traverse/test/interface.js new file mode 100644 index 0000000..fce5bf9 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/interface.js @@ -0,0 +1,42 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['interface map'] = function () { + var obj = { a : [ 5,6,7 ], b : { c : [8] } }; + + assert.deepEqual( + Traverse.paths(obj) + .sort() + .map(function (path) { return path.join('/') }) + .slice(1) + .join(' ') + , + 'a a/0 a/1 a/2 b b/c b/c/0' + ); + + assert.deepEqual( + Traverse.nodes(obj), + [ + { a: [ 5, 6, 7 ], b: { c: [ 8 ] } }, + [ 5, 6, 7 ], 5, 6, 7, + { c: [ 8 ] }, [ 8 ], 8 + ] + ); + + assert.deepEqual( + Traverse.map(obj, function (node) { + if (typeof node == 'number') { + return node + 1000; + } + else if (Array.isArray(node)) { + return node.join(' '); + } + }), + { a: '5 6 7', b: { c: '8' } } + ); + + var nodes = 0; + Traverse.forEach(obj, function (node) { nodes ++ }); + assert.deepEqual(nodes, 8); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/json.js b/node_modules/burrito/node_modules/traverse/test/json.js new file mode 100644 index 0000000..0a04529 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/json.js @@ -0,0 +1,47 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['json test'] = function () { + var id = 54; + var callbacks = {}; + var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + + var scrubbed = Traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } + }); + + assert.equal( + scrubbed.moo, '[Function]', + 'obj.moo replaced with "[Function]"' + ); + + assert.equal( + scrubbed.foo[3], '[Function]', + 'obj.foo[3] replaced with "[Function]"' + ); + + assert.deepEqual(scrubbed, { + moo : '[Function]', + foo : [ 2, 3, 4, "[Function]" ] + }, 'Full JSON string matches'); + + assert.deepEqual( + typeof obj.moo, 'function', + 'Original obj.moo still a function' + ); + + assert.deepEqual( + typeof obj.foo[3], 'function', + 'Original obj.foo[3] still a function' + ); + + assert.deepEqual(callbacks, { + 54: { id: 54, f : obj.moo, path: [ 'moo' ] }, + 55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] }, + }, 'Check the generated callbacks list'); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/keys.js b/node_modules/burrito/node_modules/traverse/test/keys.js new file mode 100644 index 0000000..7ecd545 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/keys.js @@ -0,0 +1,29 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['sort test'] = function () { + var acc = []; + Traverse({ + a: 30, + b: 22, + id: 9 + }).forEach(function (node) { + if ((! Array.isArray(node)) && typeof node === 'object') { + this.before(function(node) { + this.keys = Object.keys(node); + this.keys.sort(function(a, b) { + a = [a === "id" ? 0 : 1, a]; + b = [b === "id" ? 0 : 1, b]; + return a < b ? -1 : a > b ? 1 : 0; + }); + }); + } + if (this.isLeaf) acc.push(node); + }); + + assert.equal( + acc.join(' '), + '9 30 22', + 'Traversal in a custom order' + ); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/leaves.js b/node_modules/burrito/node_modules/traverse/test/leaves.js new file mode 100644 index 0000000..e520b72 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/leaves.js @@ -0,0 +1,21 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['leaves test'] = function () { + var acc = []; + Traverse({ + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 } + }).forEach(function (x) { + if (this.isLeaf) acc.push(x); + }); + + assert.equal( + acc.join(' '), + '1 2 3 4 5 6 7 8 9', + 'Traversal in the right(?) order' + ); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/lib/deep_equal.js b/node_modules/burrito/node_modules/traverse/test/lib/deep_equal.js new file mode 100644 index 0000000..4fa07bb --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/lib/deep_equal.js @@ -0,0 +1,92 @@ +var traverse = require('../../'); + +module.exports = function (a, b) { + if (arguments.length !== 2) { + throw new Error( + 'deepEqual requires exactly two objects to compare against' + ); + } + + var equal = true; + var node = b; + + traverse(a).forEach(function (y) { + var notEqual = (function () { + equal = false; + //this.stop(); + return undefined; + }).bind(this); + + //if (node === undefined || node === null) return notEqual(); + + if (!this.isRoot) { + /* + if (!Object.hasOwnProperty.call(node, this.key)) { + return notEqual(); + } + */ + if (typeof node !== 'object') return notEqual(); + node = node[this.key]; + } + + var x = node; + + this.post(function () { + node = x; + }); + + var toS = function (o) { + return Object.prototype.toString.call(o); + }; + + if (this.circular) { + if (traverse(b).get(this.circular.path) !== x) notEqual(); + } + else if (typeof x !== typeof y) { + notEqual(); + } + else if (x === null || y === null || x === undefined || y === undefined) { + if (x !== y) notEqual(); + } + else if (x.__proto__ !== y.__proto__) { + notEqual(); + } + else if (x === y) { + // nop + } + else if (typeof x === 'function') { + if (x instanceof RegExp) { + // both regexps on account of the __proto__ check + if (x.toString() != y.toString()) notEqual(); + } + else if (x !== y) notEqual(); + } + else if (typeof x === 'object') { + if (toS(y) === '[object Arguments]' + || toS(x) === '[object Arguments]') { + if (toS(x) !== toS(y)) { + notEqual(); + } + } + else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) + || x.getTime() !== y.getTime()) { + notEqual(); + } + } + else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) return notEqual(); + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + + return equal; +}; diff --git a/node_modules/burrito/node_modules/traverse/test/mutability.js b/node_modules/burrito/node_modules/traverse/test/mutability.js new file mode 100644 index 0000000..2236f56 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/mutability.js @@ -0,0 +1,252 @@ +var assert = require('assert'); +var Traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.mutate = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).forEach(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.mutateT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.forEach(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.map = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.mapT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.map(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.clone = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).clone(); + assert.deepEqual(obj, res); + assert.ok(obj !== res); + obj.a ++; + assert.deepEqual(res.a, 1); + obj.c.push(5); + assert.deepEqual(res.c, [ 3, 4 ]); +}; + +exports.cloneT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.clone(obj); + assert.deepEqual(obj, res); + assert.ok(obj !== res); + obj.a ++; + assert.deepEqual(res.a, 1); + obj.c.push(5); + assert.deepEqual(res.c, [ 3, 4 ]); +}; + +exports.reduce = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; + }, []); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, [ 1, 2, 3, 4 ]); +}; + +exports.reduceInit = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).reduce(function (acc, x) { + if (this.isRoot) assert.fail('got root'); + return acc; + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, obj); +}; + +exports.remove = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + assert.deepEqual(obj, { a : 1, c : [ 3 ] }); +}; + +exports.removeNoStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f']) +} + +exports.removeStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(true); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'f']) +} + +exports.removeMap = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, c : [ 3 ] }); +}; + +exports.delete = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined ] } + )); + + assert.ok(deepEqual( + obj, { a : 1, c : [ 3 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, null ] } + )); +}; + +exports.deleteNoStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'd', 'e']) +} + +exports.deleteStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(true); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c']) +} + +exports.deleteRedux = function () { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined, 5 ] } + )); + + assert.ok(deepEqual( + obj, { a : 1, c : [ 3 ,, 5 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, null, 5 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, 5 ] } + )); +}; + +exports.deleteMap = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4 ] } + )); + + var xs = [ 3, 4 ]; + delete xs[1]; + + assert.ok(deepEqual( + res, { a : 1, c : xs } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3, ] } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3 ] } + )); +}; + +exports.deleteMapRedux = function () { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4, 5 ] } + )); + + var xs = [ 3, 4, 5 ]; + delete xs[1]; + + assert.ok(deepEqual( + res, { a : 1, c : xs } + )); + + assert.ok(!deepEqual( + res, { a : 1, c : [ 3, 5 ] } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3 ,, 5 ] } + )); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/negative.js b/node_modules/burrito/node_modules/traverse/test/negative.js new file mode 100644 index 0000000..f92dfb0 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/negative.js @@ -0,0 +1,20 @@ +var Traverse = require('../'); +var assert = require('assert'); + +exports['negative update test'] = function () { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + var fixed = Traverse.map(obj, function (x) { + if (x < 0) this.update(x + 128); + }); + + assert.deepEqual(fixed, + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ], + 'Negative values += 128' + ); + + assert.deepEqual(obj, + [ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ], + 'Original references not modified' + ); +} + diff --git a/node_modules/burrito/node_modules/traverse/test/obj.js b/node_modules/burrito/node_modules/traverse/test/obj.js new file mode 100644 index 0000000..d46fd38 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/obj.js @@ -0,0 +1,15 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['traverse an object with nested functions'] = function () { + var to = setTimeout(function () { + assert.fail('never ran'); + }, 1000); + + function Cons (x) { + clearTimeout(to); + assert.equal(x, 10); + }; + Traverse(new Cons(10)); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/siblings.js b/node_modules/burrito/node_modules/traverse/test/siblings.js new file mode 100644 index 0000000..99c0f1b --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/siblings.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var traverse = require('../'); + +exports.siblings = function () { + var obj = { a : 1, b : 2, c : [ 4, 5, 6 ] }; + + var res = traverse(obj).reduce(function (acc, x) { + var p = '/' + this.path.join('/'); + if (this.parent) { + acc[p] = { + siblings : this.parent.keys, + key : this.key, + index : this.parent.keys.indexOf(this.key) + }; + } + else { + acc[p] = { + siblings : [], + key : this.key, + index : -1 + } + } + return acc; + }, {}); + + assert.deepEqual(res, { + '/' : { siblings : [], key : undefined, index : -1 }, + '/a' : { siblings : [ 'a', 'b', 'c' ], key : 'a', index : 0 }, + '/b' : { siblings : [ 'a', 'b', 'c' ], key : 'b', index : 1 }, + '/c' : { siblings : [ 'a', 'b', 'c' ], key : 'c', index : 2 }, + '/c/0' : { siblings : [ '0', '1', '2' ], key : '0', index : 0 }, + '/c/1' : { siblings : [ '0', '1', '2' ], key : '1', index : 1 }, + '/c/2' : { siblings : [ '0', '1', '2' ], key : '2', index : 2 } + }); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/stop.js b/node_modules/burrito/node_modules/traverse/test/stop.js new file mode 100644 index 0000000..3529847 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/stop.js @@ -0,0 +1,41 @@ +var assert = require('assert'); +var traverse = require('../'); + +exports.stop = function () { + var visits = 0; + traverse('abcdefghij'.split('')).forEach(function (node) { + if (typeof node === 'string') { + visits ++; + if (node === 'e') this.stop() + } + }); + + assert.equal(visits, 5); +}; + +exports.stopMap = function () { + var s = traverse('abcdefghij'.split('')).map(function (node) { + if (typeof node === 'string') { + if (node === 'e') this.stop() + return node.toUpperCase(); + } + }).join(''); + + assert.equal(s, 'ABCDEfghij'); +}; + +exports.stopReduce = function () { + var obj = { + a : [ 4, 5 ], + b : [ 6, [ 7, 8, 9 ] ] + }; + var xs = traverse(obj).reduce(function (acc, node) { + if (this.isLeaf) { + if (node === 7) this.stop(); + else acc.push(node) + } + return acc; + }, []); + + assert.deepEqual(xs, [ 4, 5, 6 ]); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/stringify.js b/node_modules/burrito/node_modules/traverse/test/stringify.js new file mode 100644 index 0000000..932f5d3 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/stringify.js @@ -0,0 +1,36 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports.stringify = function () { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + + var s = ''; + Traverse(obj).forEach(function (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + s += '"' + key + '"' + ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } + }); + + assert.equal(s, JSON.stringify(obj)); +} + diff --git a/node_modules/burrito/node_modules/traverse/test/subexpr.js b/node_modules/burrito/node_modules/traverse/test/subexpr.js new file mode 100644 index 0000000..a217beb --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/subexpr.js @@ -0,0 +1,34 @@ +var traverse = require('../'); +var assert = require('assert'); + +exports.subexpr = function () { + var obj = [ 'a', 4, 'b', 5, 'c', 6 ]; + var r = traverse(obj).map(function (x) { + if (typeof x === 'number') { + this.update([ x - 0.1, x, x + 0.1 ], true); + } + }); + + assert.deepEqual(obj, [ 'a', 4, 'b', 5, 'c', 6 ]); + assert.deepEqual(r, [ + 'a', [ 3.9, 4, 4.1 ], + 'b', [ 4.9, 5, 5.1 ], + 'c', [ 5.9, 6, 6.1 ], + ]); +}; + +exports.block = function () { + var obj = [ [ 1 ], [ 2 ], [ 3 ] ]; + var r = traverse(obj).map(function (x) { + if (Array.isArray(x) && !this.isRoot) { + if (x[0] === 5) this.block() + else this.update([ [ x[0] + 1 ] ]) + } + }); + + assert.deepEqual(r, [ + [ [ [ [ [ 5 ] ] ] ] ], + [ [ [ [ 5 ] ] ] ], + [ [ [ 5 ] ] ], + ]); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/super_deep.js b/node_modules/burrito/node_modules/traverse/test/super_deep.js new file mode 100644 index 0000000..acac2fd --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/super_deep.js @@ -0,0 +1,55 @@ +var assert = require('assert'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.super_deep = function () { + var util = require('util'); + var a0 = make(); + var a1 = make(); + assert.ok(deepEqual(a0, a1)); + + a0.c.d.moo = true; + assert.ok(!deepEqual(a0, a1)); + + a1.c.d.moo = true; + assert.ok(deepEqual(a0, a1)); + + // TODO: this one + //a0.c.a = a1; + //assert.ok(!deepEqual(a0, a1)); +}; + +function make () { + var a = { self : 'a' }; + var b = { self : 'b' }; + var c = { self : 'c' }; + var d = { self : 'd' }; + var e = { self : 'e' }; + + a.a = a; + a.b = b; + a.c = c; + + b.a = a; + b.b = b; + b.c = c; + + c.a = a; + c.b = b; + c.c = c; + c.d = d; + + d.a = a; + d.b = b; + d.c = c; + d.d = d; + d.e = e; + + e.a = a; + e.b = b; + e.c = c; + e.d = d; + e.e = e; + + return a; +} diff --git a/node_modules/burrito/package.json b/node_modules/burrito/package.json new file mode 100644 index 0000000..bd27547 --- /dev/null +++ b/node_modules/burrito/package.json @@ -0,0 +1,43 @@ +{ + "name" : "burrito", + "description" : "Wrap up expressions with a trace function while walking the AST with rice and beans on the side", + "version" : "0.2.12", + "repository" : { + "type" : "git", + "url" : "git://github.com/substack/node-burrito.git" + }, + "main" : "./index.js", + "keywords" : [ + "trace", + "ast", + "walk", + "syntax", + "source", + "tree", + "uglify" + ], + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "dependencies" : { + "traverse" : "~0.5.1", + "uglify-js" : "~1.1.1" + }, + "devDependencies" : { + "tap" : "~0.2.5" + }, + "engines" : { + "node" : ">=0.4.0" + }, + "license" : "BSD", + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + } +} diff --git a/node_modules/burrito/test/ast.js b/node_modules/burrito/test/ast.js new file mode 100644 index 0000000..503b5ab --- /dev/null +++ b/node_modules/burrito/test/ast.js @@ -0,0 +1,31 @@ +var test = require('tap').test; +var burrito = require('../'); +var vm = require('vm'); + +test('ast', function (t) { + t.plan(2); + + var ast = burrito.parse('f(g(h(5)))', false, true); + var src = burrito(ast, function (node) { + if (node.name === 'call') { + node.wrap(function (s) { + return 'z(' + s + ')'; + }); + } + }); + + var times = 0; + t.equal( + vm.runInNewContext(src, { + f : function (x) { return x + 1 }, + g : function (x) { return x + 2 }, + h : function (x) { return x + 3 }, + z : function (x) { + times ++; + return x * 10; + }, + }), + (((((5 + 3) * 10) + 2) * 10) + 1) * 10 + ); + t.equal(times, 3); +}); diff --git a/node_modules/burrito/test/err.js b/node_modules/burrito/test/err.js new file mode 100644 index 0000000..af1611d --- /dev/null +++ b/node_modules/burrito/test/err.js @@ -0,0 +1,52 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('wrap error', function (t) { + t.plan(6); + + try { + var src = burrito('f() && g()', function (node) { + if (node.name === 'binary') node.wrap('h(%a, %b') + }); + t.fail('should have blown up'); + } + catch (err) { + t.ok(err.message.match(/unexpected/i)); + t.ok(err instanceof SyntaxError); + t.ok(!err.stack.match(/uglify-js/)); + t.equal(err.line, 0); + t.equal(err.col, 10); + t.equal(err.pos, 10); + } +}); + +test('non string', function (t) { + t.plan(3); + + t.throws(function () { + burrito.parse(new Buffer('[]')); + }); + + t.throws(function () { + burrito.parse(new String('[]')); + }); + + t.throws(function () { + burrito.parse(); + }); +}); + +test('syntax error', function (t) { + t.plan(3); + try { + var src = burrito('f() && g())', function (node) { + if (node.name === 'binary') node.wrap('h(%a, %b)') + }); + assert.fail('should have blown up'); + } + catch (err) { + t.ok(err.message.match(/unexpected/i)); + t.ok(err instanceof SyntaxError); + t.ok(!err.stack.match(/uglify-js/)); + } +}); diff --git a/node_modules/burrito/test/fail.js b/node_modules/burrito/test/fail.js new file mode 100644 index 0000000..70d453f --- /dev/null +++ b/node_modules/burrito/test/fail.js @@ -0,0 +1,9 @@ +var burrito = require('../'); +var test = require('tap').test; +var fs = require('fs'); +var src = fs.readFileSync(__dirname + '/fail/src.js', 'utf8'); + +test('fail', function (t) { + burrito(src, function (node) {}); + t.end(); +}); diff --git a/node_modules/burrito/test/fail/src.js b/node_modules/burrito/test/fail/src.js new file mode 100644 index 0000000..eb02736 --- /dev/null +++ b/node_modules/burrito/test/fail/src.js @@ -0,0 +1,60 @@ +var path = require('path') + +module.exports = function(fs, ready) { + var global_files = {} + + var recurse = function(dir, okay) { + fs.readdir(dir, function(err, dir_files) { + var countdown = 0 + , files = [] + , dirs = [] + , checked = 0 + dir_files.forEach(function(file, idx, all) { + fs.stat(path.join(dir, file), function(err, stat) { + if(stat.isDirectory() && !/node_modules/g.test(dir)) { + dirs.push(file) + } else if(/\.js$/g.test(file)) { + files.push(file) + } + + if(++checked >= dir_files.length) + recurse_dirs() + }) + }) + + function recurse_dirs() { + var total = 0 + dirs.forEach(function(this_dir) { + recurse(path.join(dir, this_dir), function(err, data) { + if(++total >= dirs.length) + recurse_files() + }) + }) + + if(!dirs.length) + recurse_files() + } + + function recurse_files() { + var total = 0 + files.forEach(function(file) { + fs.readFile(path.join(dir, file), 'utf8', function(err, src) { + global_files[path.join(dir, file)] = src + ++total >= files.length && + okay(null, global_files) + }) + }) + + if(!files.length) + okay(null, global_files) + } + + if(!dir_files.length) + okay(null, global_files) + }) + } + + recurse('.', ready) +} + + diff --git a/node_modules/burrito/test/label.js b/node_modules/burrito/test/label.js new file mode 100644 index 0000000..368d7c4 --- /dev/null +++ b/node_modules/burrito/test/label.js @@ -0,0 +1,92 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('call label', function (t) { + t.plan(1); + + burrito('foo(10)', function (node) { + if (node.name === 'call') { + t.equal(node.label(), 'foo'); + } + }); +}); + +test('var label', function (t) { + t.plan(1); + + burrito('var x = 2', function (node) { + if (node.name === 'var') { + t.same(node.label(), [ 'x' ]); + } + }); +}); + +test('vars label', function (t) { + t.plan(1); + + burrito('var x = 2, y = 3', function (node) { + if (node.name === 'var') { + t.same(node.label(), [ 'x', 'y' ]); + } + }); +}); + +test('defun label', function (t) { + t.plan(1); + + burrito('function moo () {}', function (node) { + if (node.name === 'defun') { + t.same(node.label(), 'moo'); + } + }); +}); + +test('function label', function (t) { + t.plan(1); + + burrito('(function zzz () {})()', function (node) { + if (node.name === 'function') { + t.same(node.label(), 'zzz'); + } + }); +}); + +test('anon function label', function (t) { + t.plan(1); + + burrito('(function () {})()', function (node) { + if (node.name === 'function') { + t.equal(node.label(), null); + } + }); +}); + +test('dot call label', function (t) { + t.plan(1); + + burrito('process.nextTick(fn)', function (node) { + if (node.name === 'call') { + t.equal(node.label(), 'nextTick'); + } + }); +}); + +test('triple dot label', function (t) { + t.plan(1); + + burrito('a.b.c(fn)', function (node) { + if (node.name === 'call') { + t.equal(node.label(), 'c'); + } + }); +}); + +test('expr label', function (t) { + t.plan(1); + + burrito('a.b[x+1](fn)', function (node) { + if (node.name === 'call') { + t.ok(node.label() === null); + } + }); +}); diff --git a/node_modules/burrito/test/microwave.js b/node_modules/burrito/test/microwave.js new file mode 100644 index 0000000..43f80a7 --- /dev/null +++ b/node_modules/burrito/test/microwave.js @@ -0,0 +1,34 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('microwave', function (t) { + t.plan(4); + + var context = { + f : function (x) { return x + 1 }, + g : function (x) { return x + 2 }, + h : function (x) { return x + 3 }, + z : function (x) { + t.ok(true); // 3 times + return x * 10; + }, + }; + + var res = burrito.microwave('f(g(h(5)))', context, function (node) { + if (node.name === 'call') { + node.wrap(function (s) { + return 'z(' + s + ')'; + }); + } + }); + + t.equal(res, (((((5 + 3) * 10) + 2) * 10) + 1) * 10); +}); + +test('empty context', function (t) { + var res = burrito.microwave('Math.sin(2)', function (node) { + if (node.name === 'num') node.wrap('Math.PI / %s'); + }); + t.equal(res, 1); + t.end(); +}); diff --git a/node_modules/burrito/test/parent.js b/node_modules/burrito/test/parent.js new file mode 100644 index 0000000..2d613af --- /dev/null +++ b/node_modules/burrito/test/parent.js @@ -0,0 +1,27 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('check parent', function (t) { + t.plan(5); + var src = 'Math.tan(0) + Math.sin(0)'; + + var res = burrito.microwave(src, function (node) { + if (node.name === 'binary') { + node.wrap('%a - %b'); + } + else if (node.name === 'num') { + t.equal(node.parent().value[0][0], 'dot'); + + var fn = node.parent().value[0][2]; + if (fn === 'sin') { + node.wrap('Math.PI / 2'); + } + else if (fn === 'tan') { + node.wrap('Math.PI / 4'); + } + else t.fail('Unknown fn'); + } + }); + + t.equal(res, Math.tan(Math.PI / 4) - Math.sin(Math.PI / 2)); // ~ 0 +}); diff --git a/node_modules/burrito/test/wrap.js b/node_modules/burrito/test/wrap.js new file mode 100644 index 0000000..b9eda49 --- /dev/null +++ b/node_modules/burrito/test/wrap.js @@ -0,0 +1,159 @@ +var test = require('tap').test; +var burrito = require('../'); +var vm = require('vm'); + +test('preserve ternary parentheses', function (t) { + var originalSource = '"anything" + (x ? y : z) + "anything"'; + var burritoSource = burrito(originalSource, function (node) { + // do nothing. we just want to check that ternary parens are persisted + }); + + var ctxt = { + x : false, + y : 'y_'+~~(Math.random()*10), + z : 'z_'+~~(Math.random()*10) + }; + + var expectedOutput = vm.runInNewContext(originalSource, ctxt); + var burritoOutput = vm.runInNewContext(burritoSource, ctxt); + + t.equal(burritoOutput, expectedOutput); + + ctxt.x = true; + + expectedOutput = vm.runInNewContext(originalSource, ctxt); + burritoOutput = vm.runInNewContext(burritoSource, ctxt); + + t.equal(burritoOutput, expectedOutput); + t.end(); +}); + +test('wrap calls', function (t) { + t.plan(20); + var src = burrito('f() && g(h())\nfoo()', function (node) { + if (node.name === 'call') node.wrap('qqq(%s)'); + if (node.name === 'binary') node.wrap('bbb(%s)'); + t.ok(node.state); + t.equal(this, node.state); + }); + + var times = { bbb : 0, qqq : 0 }; + + var res = []; + vm.runInNewContext(src, { + bbb : function (x) { + times.bbb ++; + res.push(x); + return x; + }, + qqq : function (x) { + times.qqq ++; + res.push(x); + return x; + }, + f : function () { return true }, + g : function (h) { + t.equal(h, 7); + return h !== 7 + }, + h : function () { return 7 }, + foo : function () { return 'foo!' }, + }); + + t.same(res, [ + true, // f() + 7, // h() + false, // g(h()) + false, // f() && g(h()) + 'foo!', // foo() + ]); + t.equal(times.bbb, 1); + t.equal(times.qqq, 4); + t.end(); +}); + +test('wrap fn', function (t) { + var src = burrito('f(g(h(5)))', function (node) { + if (node.name === 'call') { + node.wrap(function (s) { + return 'z(' + s + ')'; + }); + } + }); + + var times = 0; + t.equal( + vm.runInNewContext(src, { + f : function (x) { return x + 1 }, + g : function (x) { return x + 2 }, + h : function (x) { return x + 3 }, + z : function (x) { + times ++; + return x * 10; + }, + }), + (((((5 + 3) * 10) + 2) * 10) + 1) * 10 + ); + t.equal(times, 3); + t.end(); +}); + +test('binary string', function (t) { + var src = 'z(x + y)'; + var context = { + x : 3, + y : 4, + z : function (n) { return n * 10 }, + }; + + var res = burrito.microwave(src, context, function (node) { + if (node.name === 'binary') { + node.wrap('%a*2 - %b*2'); + } + }); + + t.equal(res, 10 * (3*2 - 4*2)); + t.end(); +}); + +test('binary fn', function (t) { + var src = 'z(x + y)'; + var context = { + x : 3, + y : 4, + z : function (n) { return n * 10 }, + }; + + var res = burrito.microwave(src, context, function (node) { + if (node.name === 'binary') { + node.wrap(function (expr, a, b) { + return '(' + a + ')*2 - ' + '(' + b + ')*2'; + }); + } + }); + + t.equal(res, 10 * (3*2 - 4*2)); + t.end(); +}); + +test('intersperse', function (t) { + var src = '(' + (function () { + f(); + g(); + }).toString() + ')()'; + + var times = { f : 0, g : 0, zzz : 0 }; + + var context = { + f : function () { times.f ++ }, + g : function () { times.g ++ }, + zzz : function () { times.zzz ++ }, + }; + + burrito.microwave(src, context, function (node) { + if (node.name === 'stat') node.wrap('{ zzz(); %s }'); + }); + + t.same(times, { f : 1, g : 1, zzz : 3 }); + t.end(); +}); diff --git a/node_modules/charm/README.markdown b/node_modules/charm/README.markdown new file mode 100644 index 0000000..a0648ff --- /dev/null +++ b/node_modules/charm/README.markdown @@ -0,0 +1,216 @@ +charm +===== + +Use +[ansi terminal characters](http://www.termsys.demon.co.uk/vtansi.htm) +to write colors and cursor positions. + +![me lucky charms](http://substack.net/images/charms.png) + +example +======= + +lucky +----- + +````javascript +var charm = require('charm')(); +charm.pipe(process.stdout); +charm.reset(); + +var colors = [ 'red', 'cyan', 'yellow', 'green', 'blue' ]; +var text = 'Always after me lucky charms.'; + +var offset = 0; +var iv = setInterval(function () { + var y = 0, dy = 1; + for (var i = 0; i < 40; i++) { + var color = colors[(i + offset) % colors.length]; + var c = text[(i + offset) % text.length]; + charm + .move(1, dy) + .foreground(color) + .write(c) + ; + y += dy; + if (y <= 0 || y >= 5) dy *= -1; + } + charm.position(0, 1); + offset ++; +}, 150); +```` + +events +====== + +Charm objects pass along the data events from their input stream except for +events generated from querying the terminal device. + +Because charm puts stdin into raw mode, charm emits two special events: "^C" and +"^D" when the user types those combos. It's super convenient with these events +to do: + +````javascript +charm.on('^C', process.exit) +```` + +The above is set on all `charm` streams. If you want to add your own handling for these +special events simply: + +````javascript +charm.removeAllListeners('^C') +charm.on('^C', function () { + // Don't exit. Do some mad science instead. +}) +```` + +methods +======= + +var charm = require('charm')(param or stream, ...) +-------------------------------------------------- + +Create a new readable/writable `charm` stream. + +You can pass in readable or writable streams as parameters and they will be +piped to or from accordingly. You can also pass `process` in which case +`process.stdin` and `process.stdout` will be used. + +You can `pipe()` to and from the `charm` object you get back. + +charm.reset() +------------- + +Reset the entire screen, like the /usr/bin/reset command. + +charm.destroy(), charm.end() +---------------------------- + +Emit an `"end"` event downstream. + +charm.write(msg) +---------------- + +Pass along `msg` to the output stream. + +charm.position(x, y) +-------------------- + +Set the cursor position to the absolute coordinates `x, y`. + +charm.position(cb) +------------------ + +Query the absolute cursor position from the input stream through the output +stream (the shell does this automatically) and get the response back as +`cb(x, y)`. + +charm.move(x, y) +---------------- + +Move the cursor position by the relative coordinates `x, y`. + +charm.up(y) +----------- + +Move the cursor up by `y` rows. + +charm.down(y) +------------- + +Move the cursor down by `y` rows. + +charm.left(x) +------------- + +Move the cursor left by `x` columns. + +charm.right(x) +-------------- + +Move the cursor right by `x` columns. + +charm.push(withAttributes=false) +-------------------------------- + +Push the cursor state and optionally the attribute state. + +charm.pop(withAttributes=false) +------------------------------- + +Pop the cursor state and optionally the attribute state. + +charm.erase(s) +-------------- + +Erase a region defined by the string `s`. + +`s` can be: + +* end - erase from the cursor to the end of the line +* start - erase from the cursor to the start of the line +* line - erase the current line +* down - erase everything below the current line +* up - erase everything above the current line +* screen - erase the entire screen + +charm.display(attr) +------------------- + +Set the display mode with the string `attr`. + +`attr` can be: + +* reset +* bright +* dim +* underscore +* blink +* reverse +* hidden + +charm.foreground(color) +----------------------- + +Set the foreground color with the string `color`, which can be: + +* red +* yellow +* green +* blue +* cyan +* magenta +* black +* white + +or `color` can be an integer from 0 to 255, inclusive. + +charm.background(color) +----------------------- + +Set the background color with the string `color`, which can be: + +* red +* yellow +* green +* blue +* cyan +* magenta +* black +* white + +or `color` can be an integer from 0 to 255, inclusive. + +charm.cursor(visible) +--------------------- + +Set the cursor visibility with a boolean `visible`. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install charm +``` diff --git a/node_modules/charm/example/256.js b/node_modules/charm/example/256.js new file mode 100644 index 0000000..6851386 --- /dev/null +++ b/node_modules/charm/example/256.js @@ -0,0 +1,17 @@ +var charm = require('../')(process); + +function exit () { + charm.display('reset'); + process.exit(); +} +charm.on('^C', exit); + +var ix = 0; +var iv = setInterval(function () { + charm.background(ix++).write(' '); + if (ix === 256) { + clearInterval(iv); + charm.write('\n'); + exit(); + } +}, 10); diff --git a/node_modules/charm/example/column.js b/node_modules/charm/example/column.js new file mode 100644 index 0000000..2647e71 --- /dev/null +++ b/node_modules/charm/example/column.js @@ -0,0 +1,11 @@ +var charm = require('../')(); +charm.pipe(process.stdout); + +charm + .column(16) + .write('beep') + .down() + .column(32) + .write('boop\n') + .end() +; diff --git a/node_modules/charm/example/cursor.js b/node_modules/charm/example/cursor.js new file mode 100644 index 0000000..0c565b0 --- /dev/null +++ b/node_modules/charm/example/cursor.js @@ -0,0 +1,22 @@ +var charm = require('../')(process); + +charm.position(5, 10); + +charm.position(function (x, y) { + console.dir([ x, y ]); + + charm.move(7,2); + charm.push(); + process.stdout.write('lul'); + + charm.left(3).up(1).foreground('magenta'); + process.stdout.write('v'); + charm.left(1).up(1).display('reset'); + process.stdout.write('|'); + + charm.down(3); + charm.pop().background('blue'); + process.stdout.write('popped\npow'); + charm.display('reset').erase('line'); + charm.destroy(); +}); diff --git a/node_modules/charm/example/http_spin.js b/node_modules/charm/example/http_spin.js new file mode 100644 index 0000000..727e3e8 --- /dev/null +++ b/node_modules/charm/example/http_spin.js @@ -0,0 +1,36 @@ +var http = require('http'); +var charmer = require('../'); + +http.createServer(function (req, res) { + res.setHeader('content-type', 'text/ansi'); + + var charm = charmer(); + charm.pipe(res); + charm.reset(); + + var radius = 10; + var theta = 0; + var points = []; + + var iv = setInterval(function () { + var x = 2 + (radius + Math.cos(theta) * radius) * 2; + var y = 2 + radius + Math.sin(theta) * radius; + + points.unshift([ x, y ]); + var colors = [ 'red', 'yellow', 'green', 'cyan', 'blue', 'magenta' ]; + + points.forEach(function (p, i) { + charm.position(p[0], p[1]); + var c = colors[Math.floor(i / 12)]; + charm.background(c).write(' ') + }); + points = points.slice(0, 12 * colors.length - 1); + + theta += Math.PI / 40; + }, 50); + + req.connection.on('end', function () { + clearInterval(iv); + charm.end(); + }); +}).listen(8081); diff --git a/node_modules/charm/example/lucky.js b/node_modules/charm/example/lucky.js new file mode 100644 index 0000000..01fe801 --- /dev/null +++ b/node_modules/charm/example/lucky.js @@ -0,0 +1,24 @@ +var charm = require('../')(); +charm.pipe(process.stdout); +charm.reset(); + +var colors = [ 'red', 'cyan', 'yellow', 'green', 'blue' ]; +var text = 'Always after me lucky charms.'; + +var offset = 0; +var iv = setInterval(function () { + var y = 0, dy = 1; + for (var i = 0; i < 40; i++) { + var color = colors[(i + offset) % colors.length]; + var c = text[(i + offset) % text.length]; + charm + .move(1, dy) + .foreground(color) + .write(c) + ; + y += dy; + if (y <= 0 || y >= 5) dy *= -1; + } + charm.position(0, 1); + offset ++; +}, 150); diff --git a/node_modules/charm/example/position.js b/node_modules/charm/example/position.js new file mode 100644 index 0000000..2c5ae9b --- /dev/null +++ b/node_modules/charm/example/position.js @@ -0,0 +1,7 @@ +var charm = require('charm')(process); + +charm.on('^C', process.exit); + +charm.position(function (x, y) { + console.log('(%d, %d)', x, y); +}); diff --git a/node_modules/charm/example/progress.js b/node_modules/charm/example/progress.js new file mode 100644 index 0000000..9da3c13 --- /dev/null +++ b/node_modules/charm/example/progress.js @@ -0,0 +1,18 @@ +var charm = require('../')(); +charm.pipe(process.stdout); + +charm.write('Progress: 0 %'); +var i = 0; + +var iv = setInterval(function () { + charm.left(i.toString().length + 2); + i ++; + charm.write(i + ' %'); + if (i === 100) { + charm.end('\nDone!\n'); + clearInterval(iv); + } +}, 25); + +charm.on('^C',process.exit); + diff --git a/node_modules/charm/example/resize.js b/node_modules/charm/example/resize.js new file mode 100644 index 0000000..bda80b6 --- /dev/null +++ b/node_modules/charm/example/resize.js @@ -0,0 +1,62 @@ +var c = require('../')(); +c.pipe(process.stdout); +c.on('^C', process.exit); + +var queue = (function () { + var tasks = []; + var pending = false; + + return { + abort : function () { + tasks = []; + next(); + }, + push : function (t) { + tasks.push(t); + if (!pending) next(); + } + }; + + function next () { + pending = true; + process.nextTick(function () { + if (tasks.length === 0) return; + var t = tasks.shift(); + t(); + pending = false; + next(); + }); + } +})(); + +process.stdout.on('resize', draw); +draw(); +setInterval(function () {}, 1e8); + +function draw () { + var cols = process.stdout.columns; + var rows = process.stdout.rows; + queue.abort(); + + queue.push(function () { + c.reset(); + c.background('blue'); + c.position(1, 1); + c.write(Array(cols + 1).join(' ')); + }); + + for (var y = 1; y < rows; y++) { + queue.push(function () { + c.position(1, y); + c.write(' '); + c.position(cols, y); + c.write(' '); + }); + } + + queue.push(function () { + c.position(1, rows); + c.write(Array(cols + 1).join(' ')); + c.display('reset'); + }); +} diff --git a/node_modules/charm/example/spin.js b/node_modules/charm/example/spin.js new file mode 100644 index 0000000..fd3e23a --- /dev/null +++ b/node_modules/charm/example/spin.js @@ -0,0 +1,23 @@ +var charm = require('../')(process); +charm.reset(); + +var radius = 10; +var theta = 0; +var points = []; + +var iv = setInterval(function () { + var x = 2 + (radius + Math.cos(theta) * radius) * 2; + var y = 2 + radius + Math.sin(theta) * radius; + + points.unshift([ x, y ]); + var colors = [ 'red', 'yellow', 'green', 'cyan', 'blue', 'magenta' ]; + + points.forEach(function (p, i) { + charm.position(p[0], p[1]); + var c = colors[Math.floor(i / 12)]; + charm.background(c).write(' ') + }); + points = points.slice(0, 12 * colors.length - 1); + + theta += Math.PI / 40; +}, 50); diff --git a/node_modules/charm/index.js b/node_modules/charm/index.js new file mode 100644 index 0000000..e1e7bdc --- /dev/null +++ b/node_modules/charm/index.js @@ -0,0 +1,305 @@ +var tty = require('tty'); +var encode = require('./lib/encode'); +var Stream = require('stream').Stream; + +var exports = module.exports = function () { + var input = null; + function setInput (s) { + if (input) throw new Error('multiple inputs specified') + else input = s + } + + var output = null; + function setOutput (s) { + if (output) throw new Error('multiple outputs specified') + else output = s + } + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + if (!arg) continue; + if (arg.readable) setInput(arg) + else if (arg.stdin || arg.input) setInput(arg.stdin || arg.input) + + if (arg.writable) setOutput(arg) + else if (arg.stdout || arg.output) setOutput(arg.stdout || arg.output) + + } + + if (input && typeof input.fd === 'number' && tty.isatty(input.fd)) { + if (process.stdin.setRawMode) { + process.stdin.setRawMode(true); + } + else tty.setRawMode(true); + } + + var charm = new Charm; + if (input) { + input.pipe(charm); + } + + if (output) { + charm.pipe(output); + } + + charm.once('^C', process.exit); + charm.once('end', function () { + if (input) { + if (typeof input.fd === 'number' && tty.isatty(input.fd)) { + if (process.stdin.setRawMode) { + process.stdin.setRawMode(false); + } + else tty.setRawMode(false); + } + input.destroy(); + } + }); + + return charm; +}; + +var Charm = exports.Charm = function Charm () { + this.writable = true; + this.readable = true; + this.pending = []; +} + +Charm.prototype = new Stream; + +Charm.prototype.write = function (buf) { + var self = this; + + if (self.pending.length) { + var codes = extractCodes(buf); + var matched = false; + + for (var i = 0; i < codes.length; i++) { + for (var j = 0; j < self.pending.length; j++) { + var cb = self.pending[j]; + if (cb(codes[i])) { + matched = true; + self.pending.splice(j, 1); + break; + } + } + } + + if (matched) return; + } + + if (buf.length === 1) { + if (buf[0] === 3) self.emit('^C'); + if (buf[0] === 4) self.emit('^D'); + } + + self.emit('data', buf); + + return self; +}; + + +Charm.prototype.destroy = function () { + this.end(); +}; + +Charm.prototype.end = function (buf) { + if (buf) this.write(buf); + this.emit('end'); +}; + +Charm.prototype.reset = function (cb) { + this.write(encode('c')); + return this; +}; + +Charm.prototype.position = function (x, y) { + // get/set absolute coordinates + if (typeof x === 'function') { + var cb = x; + this.pending.push(function (buf) { + if (buf[0] === 27 && buf[1] === encode.ord('[') + && buf[buf.length-1] === encode.ord('R')) { + var pos = buf.toString() + .slice(2,-1) + .split(';') + .map(Number) + ; + cb(pos[1], pos[0]); + return true; + } + }); + this.write(encode('[6n')); + } + else { + this.write(encode( + '[' + Math.floor(y) + ';' + Math.floor(x) + 'f' + )); + } + return this; +}; + +Charm.prototype.move = function (x, y) { + // set relative coordinates + var bufs = []; + + if (y < 0) this.up(-y) + else if (y > 0) this.down(y) + + if (x > 0) this.right(x) + else if (x < 0) this.left(-x) + + return this; +}; + +Charm.prototype.up = function (y) { + if (y === undefined) y = 1; + this.write(encode('[' + Math.floor(y) + 'A')); + return this; +}; + +Charm.prototype.down = function (y) { + if (y === undefined) y = 1; + this.write(encode('[' + Math.floor(y) + 'B')); + return this; +}; + +Charm.prototype.right = function (x) { + if (x === undefined) x = 1; + this.write(encode('[' + Math.floor(x) + 'C')); + return this; +}; + +Charm.prototype.left = function (x) { + if (x === undefined) x = 1; + this.write(encode('[' + Math.floor(x) + 'D')); + return this; +}; + +Charm.prototype.column = function (x) { + this.write(encode('[' + Math.floor(x) + 'G')); + return this; +}; + +Charm.prototype.push = function (withAttributes) { + this.write(encode(withAttributes ? '7' : '[s')); + return this; +}; + +Charm.prototype.pop = function (withAttributes) { + this.write(encode(withAttributes ? '8' : '[u')); + return this; +}; + +Charm.prototype.erase = function (s) { + if (s === 'end' || s === '$') { + this.write(encode('[K')); + } + else if (s === 'start' || s === '^') { + this.write(encode('[1K')); + } + else if (s === 'line') { + this.write(encode('[2K')); + } + else if (s === 'down') { + this.write(encode('[J')); + } + else if (s === 'up') { + this.write(encode('[1J')); + } + else if (s === 'screen') { + this.write(encode('[1J')); + } + else { + this.emit('error', new Error('Unknown erase type: ' + s)); + } + return this; +}; + +Charm.prototype.display = function (attr) { + var c = { + reset : 0, + bright : 1, + dim : 2, + underscore : 4, + blink : 5, + reverse : 7, + hidden : 8 + }[attr]; + if (c === undefined) { + this.emit('error', new Error('Unknown attribute: ' + attr)); + } + this.write(encode('[' + c + 'm')); + return this; +}; + +Charm.prototype.foreground = function (color) { + if (typeof color === 'number') { + if (color < 0 || color >= 256) { + this.emit('error', new Error('Color out of range: ' + color)); + } + this.write(encode('[38;5;' + color + 'm')); + } + else { + var c = { + black : 30, + red : 31, + green : 32, + yellow : 33, + blue : 34, + magenta : 35, + cyan : 36, + white : 37 + }[color.toLowerCase()]; + + if (!c) this.emit('error', new Error('Unknown color: ' + color)); + this.write(encode('[' + c + 'm')); + } + return this; +}; + +Charm.prototype.background = function (color) { + if (typeof color === 'number') { + if (color < 0 || color >= 256) { + this.emit('error', new Error('Color out of range: ' + color)); + } + this.write(encode('[48;5;' + color + 'm')); + } + else { + var c = { + black : 40, + red : 41, + green : 42, + yellow : 43, + blue : 44, + magenta : 45, + cyan : 46, + white : 47 + }[color.toLowerCase()]; + + if (!c) this.emit('error', new Error('Unknown color: ' + color)); + this.write(encode('[' + c + 'm')); + } + return this; +}; + +Charm.prototype.cursor = function (visible) { + this.write(encode(visible ? '[?25h' : '[?25l')); + return this; +}; + +var extractCodes = exports.extractCodes = function (buf) { + var codes = []; + var start = -1; + + for (var i = 0; i < buf.length; i++) { + if (buf[i] === 27) { + if (start >= 0) codes.push(buf.slice(start, i)); + start = i; + } + else if (start >= 0 && i === buf.length - 1) { + codes.push(buf.slice(start)); + } + } + + return codes; +} diff --git a/node_modules/charm/lib/encode.js b/node_modules/charm/lib/encode.js new file mode 100644 index 0000000..3b6417a --- /dev/null +++ b/node_modules/charm/lib/encode.js @@ -0,0 +1,18 @@ +var encode = module.exports = function (xs) { + function bytes (s) { + if (typeof s === 'string') { + return s.split('').map(ord); + } + else if (Array.isArray(s)) { + return s.reduce(function (acc, c) { + return acc.concat(bytes(c)); + }, []); + } + } + + return new Buffer([ 0x1b ].concat(bytes(xs))); +}; + +var ord = encode.ord = function ord (c) { + return c.charCodeAt(0) +}; diff --git a/node_modules/charm/package.json b/node_modules/charm/package.json new file mode 100644 index 0000000..b635f60 --- /dev/null +++ b/node_modules/charm/package.json @@ -0,0 +1,32 @@ +{ + "name" : "charm", + "version" : "0.1.2", + "description" : "ansi control sequences for terminal cursor hopping and colors", + "main" : "index.js", + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-charm.git" + }, + "keywords" : [ + "terminal", + "ansi", + "cursor", + "color", + "console", + "control", + "escape", + "sequence" + ], + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + }, + "license" : "MIT/X11", + "engine" : { "node" : ">=0.4" } +} diff --git a/node_modules/deep-equal/README.markdown b/node_modules/deep-equal/README.markdown new file mode 100644 index 0000000..c3293d3 --- /dev/null +++ b/node_modules/deep-equal/README.markdown @@ -0,0 +1,55 @@ +deep-equal +========== + +Node's `assert.deepEqual() algorithm` as a standalone module. + +example +======= + +``` js +var equal = require('deep-equal'); +console.dir([ + equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + ), + equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + ) +]); +``` + +methods +======= + +var deepEqual = require('deep-equal') + +deepEqual(a, b) +--------------- + +Compare objects `a` and `b`, returning whether they are equal according to a +recursive equality algorithm. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install deep-equal +``` + +test +==== + +With [npm](http://npmjs.org) do: + +``` +npm test +``` + +license +======= + +MIT. Derived largely from node's assert module. diff --git a/node_modules/deep-equal/example/cmp.js b/node_modules/deep-equal/example/cmp.js new file mode 100644 index 0000000..67014b8 --- /dev/null +++ b/node_modules/deep-equal/example/cmp.js @@ -0,0 +1,11 @@ +var equal = require('../'); +console.dir([ + equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + ), + equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + ) +]); diff --git a/node_modules/deep-equal/index.js b/node_modules/deep-equal/index.js new file mode 100644 index 0000000..e4e37be --- /dev/null +++ b/node_modules/deep-equal/index.js @@ -0,0 +1,84 @@ +var pSlice = Array.prototype.slice; +var Object_keys = typeof Object.keys === 'function' + ? Object.keys + : function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; + } +; + +var deepEqual = module.exports = function (actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. 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 { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull(value) { + return value === null || value === undefined; +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return deepEqual(a, b); + } + try { + var ka = Object_keys(a), + kb = Object_keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // 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])) return false; + } + return true; +} diff --git a/node_modules/deep-equal/package.json b/node_modules/deep-equal/package.json new file mode 100644 index 0000000..9020c5b --- /dev/null +++ b/node_modules/deep-equal/package.json @@ -0,0 +1,33 @@ +{ + "name" : "deep-equal", + "version" : "0.0.0", + "description" : "node's assert.deepEqual algorithm", + "main" : "index.js", + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "devDependencies" : { + "tap" : "0.0.x" + }, + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-deep-equal.git" + }, + "keywords" : [ + "equality", + "equal", + "compare" + ], + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + }, + "license" : "MIT/X11", + "engine" : { "node" : ">=0.4" } +} diff --git a/node_modules/deep-equal/test/cmp.js b/node_modules/deep-equal/test/cmp.js new file mode 100644 index 0000000..8418f0f --- /dev/null +++ b/node_modules/deep-equal/test/cmp.js @@ -0,0 +1,18 @@ +var test = require('tap').test; +var equal = require('../'); + +test('equal', function (t) { + t.ok(equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + )); + t.end(); +}); + +test('not equal', function (t) { + t.notOk(equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + )); + t.end(); +}); diff --git a/node_modules/deep-is/.travis.yml b/node_modules/deep-is/.travis.yml new file mode 100644 index 0000000..58f2371 --- /dev/null +++ b/node_modules/deep-is/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.10 diff --git a/node_modules/deep-is/LICENSE b/node_modules/deep-is/LICENSE new file mode 100644 index 0000000..c38f840 --- /dev/null +++ b/node_modules/deep-is/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012, 2013 Thorsten Lorenz +Copyright (c) 2012 James Halliday +Copyright (c) 2009 Thomas Robinson <280north.com> + +This software is released under the MIT license: + +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. diff --git a/node_modules/deep-is/README.markdown b/node_modules/deep-is/README.markdown new file mode 100644 index 0000000..eb69a83 --- /dev/null +++ b/node_modules/deep-is/README.markdown @@ -0,0 +1,70 @@ +deep-is +========== + +Node's `assert.deepEqual() algorithm` as a standalone module. Exactly like +[deep-equal](https://github.com/substack/node-deep-equal) except for the fact that `deepEqual(NaN, NaN) === true`. + +This module is around [5 times faster](https://gist.github.com/2790507) +than wrapping `assert.deepEqual()` in a `try/catch`. + +[![browser support](http://ci.testling.com/thlorenz/deep-is.png)](http://ci.testling.com/thlorenz/deep-is) + +[![build status](https://secure.travis-ci.org/thlorenz/deep-is.png)](http://travis-ci.org/thlorenz/deep-is) + +example +======= + +``` js +var equal = require('deep-is'); +console.dir([ + equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + ), + equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + ) +]); +``` + +methods +======= + +var deepIs = require('deep-is') + +deepIs(a, b) +--------------- + +Compare objects `a` and `b`, returning whether they are equal according to a +recursive equality algorithm. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install deep-is +``` + +test +==== + +With [npm](http://npmjs.org) do: + +``` +npm test +``` + +license +======= + +Copyright (c) 2012, 2013 Thorsten Lorenz +Copyright (c) 2012 James Halliday + +Derived largely from node's assert module, which has the copyright statement: + +Copyright (c) 2009 Thomas Robinson <280north.com> + +Released under the MIT license, see LICENSE for details. diff --git a/node_modules/deep-is/example/cmp.js b/node_modules/deep-is/example/cmp.js new file mode 100644 index 0000000..67014b8 --- /dev/null +++ b/node_modules/deep-is/example/cmp.js @@ -0,0 +1,11 @@ +var equal = require('../'); +console.dir([ + equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + ), + equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + ) +]); diff --git a/node_modules/deep-is/index.js b/node_modules/deep-is/index.js new file mode 100644 index 0000000..506fe27 --- /dev/null +++ b/node_modules/deep-is/index.js @@ -0,0 +1,102 @@ +var pSlice = Array.prototype.slice; +var Object_keys = typeof Object.keys === 'function' + ? Object.keys + : function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; + } +; + +var deepEqual = module.exports = function (actual, expected) { + // enforce Object.is +0 !== -0 + if (actual === 0 && expected === 0) { + return areZerosEqual(actual, expected); + + // 7.1. All identical values are equivalent, as determined by ===. + } else if (actual === expected) { + return true; + + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + } else if (isNumberNaN(actual)) { + return isNumberNaN(expected); + + // 7.3. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. 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 { + return objEquiv(actual, expected); + } +}; + +function isUndefinedOrNull(value) { + return value === null || value === undefined; +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function isNumberNaN(value) { + // NaN === NaN -> false + return typeof value == 'number' && value !== value; +} + +function areZerosEqual(zeroA, zeroB) { + // (1 / +0|0) -> Infinity, but (1 / -0) -> -Infinity and (Infinity !== -Infinity) + return (1 / zeroA) === (1 / zeroB); +} + +function objEquiv(a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return deepEqual(a, b); + } + try { + var ka = Object_keys(a), + kb = Object_keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // 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])) return false; + } + return true; +} diff --git a/node_modules/deep-is/package.json b/node_modules/deep-is/package.json new file mode 100644 index 0000000..dae72d7 --- /dev/null +++ b/node_modules/deep-is/package.json @@ -0,0 +1,58 @@ +{ + "name": "deep-is", + "version": "0.1.4", + "description": "node's assert.deepEqual algorithm except for NaN being equal to NaN", + "main": "index.js", + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "scripts": { + "test": "tape test/*.js" + }, + "devDependencies": { + "tape": "~1.0.2" + }, + "repository": { + "type": "git", + "url": "http://github.com/thlorenz/deep-is.git" + }, + "keywords": [ + "equality", + "equal", + "compare" + ], + "author": { + "name": "Thorsten Lorenz", + "email": "thlorenz@gmx.de", + "url": "http://thlorenz.com" + }, + "license": "MIT", + "testling": { + "files": "test/*.js", + "browsers": { + "ie": [ + 6, + 7, + 8, + 9 + ], + "ff": [ + 3.5, + 10, + 15 + ], + "chrome": [ + 10, + 22 + ], + "safari": [ + 5.1 + ], + "opera": [ + 12 + ] + } + } +} diff --git a/node_modules/deep-is/test/NaN.js b/node_modules/deep-is/test/NaN.js new file mode 100644 index 0000000..ddaa5a7 --- /dev/null +++ b/node_modules/deep-is/test/NaN.js @@ -0,0 +1,16 @@ +var test = require('tape'); +var equal = require('../'); + +test('NaN and 0 values', function (t) { + t.ok(equal(NaN, NaN)); + t.notOk(equal(0, NaN)); + t.ok(equal(0, 0)); + t.notOk(equal(0, 1)); + t.end(); +}); + + +test('nested NaN values', function (t) { + t.ok(equal([ NaN, 1, NaN ], [ NaN, 1, NaN ])); + t.end(); +}); diff --git a/node_modules/deep-is/test/cmp.js b/node_modules/deep-is/test/cmp.js new file mode 100644 index 0000000..3071013 --- /dev/null +++ b/node_modules/deep-is/test/cmp.js @@ -0,0 +1,23 @@ +var test = require('tape'); +var equal = require('../'); + +test('equal', function (t) { + t.ok(equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + )); + t.end(); +}); + +test('not equal', function (t) { + t.notOk(equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + )); + t.end(); +}); + +test('nested nulls', function (t) { + t.ok(equal([ null, null, null ], [ null, null, null ])); + t.end(); +}); diff --git a/node_modules/deep-is/test/neg-vs-pos-0.js b/node_modules/deep-is/test/neg-vs-pos-0.js new file mode 100644 index 0000000..ac26130 --- /dev/null +++ b/node_modules/deep-is/test/neg-vs-pos-0.js @@ -0,0 +1,15 @@ +var test = require('tape'); +var equal = require('../'); + +test('0 values', function (t) { + t.ok(equal( 0, 0), ' 0 === 0'); + t.ok(equal( 0, +0), ' 0 === +0'); + t.ok(equal(+0, +0), '+0 === +0'); + t.ok(equal(-0, -0), '-0 === -0'); + + t.notOk(equal(-0, 0), '-0 !== 0'); + t.notOk(equal(-0, +0), '-0 !== +0'); + + t.end(); +}); + diff --git a/node_modules/difflet/.travis.yml b/node_modules/difflet/.travis.yml new file mode 100644 index 0000000..09d3ef3 --- /dev/null +++ b/node_modules/difflet/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - 0.10 diff --git a/node_modules/difflet/README.markdown b/node_modules/difflet/README.markdown new file mode 100644 index 0000000..9ad4303 --- /dev/null +++ b/node_modules/difflet/README.markdown @@ -0,0 +1,116 @@ +difflet +======= + +Create colorful diffs for javascript objects. + +example +======= + +string.js +--------- + +``` js +var difflet = require('difflet'); + +var s = difflet.compare({ a : 2, c : 5 }, { a : 3, b : 4 }); +process.stdout.write(s); +``` + +output: + +![colorful output](http://substack.net/images/screenshots/difflet_string.png) + +colors.js +--------- + +``` js +var diff = require('difflet')({ indent : 2 }); + +var prev = { + yy : 6, + zz : 5, + a : [1,2,3], + fn : 'beep', + c : { x : 7, z : 3 } +}; + +var next = { + a : [ 1, 2, "z", /beep/, new Buffer(3) ], + fn : function qqq () {}, + b : [5,6,7], + c : { x : 8, y : 5 } +}; + +diff(prev, next).pipe(process.stdout); +``` + +output: + +![colorful output](http://substack.net/images/screenshots/difflet_colors.png) + +green for inserts, blue for updates, red for deletes + +methods +======= + +var difflet = require('difflet') + +var diff = difflet(opts={}) +--------------------------- + +Create a difflet from optional options `opts`. + +With `opts.start(type, stream)` and `opts.stop(type, stream)`, +you can write custom handlers for all the types of differences: +`'inserted'`, `'updated'`, and `'deleted'`. +By default green is used for insertions, blue for updates, and red for +deletions. + +If `opts.indent` is set, output will span multiple lines and `opts.indent` +spaces will be used for leading whitespace. + +If `opts.comma === 'first'` then commas will be placed at the start of lines. + +Setting `opts.comment` to `true` will turn on comments with the previous +contents like this: + +![object comments](http://substack.net/images/screenshots/difflet_object_comments.png) + +diff(prev, next) +---------------- + +Return a stream with the colorful changes between objects `prev` and `next`. + +diff.compare(prev, next) +------------------------ + +Return a string with the colorful changes between `prev` and `next`. + +difflet.compare(prev, next) +--------------------------- + +Return a string with the colorful changes between `prev` and `next` with the +default options. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install difflet +``` + +test +==== + +With [npm](http://npmjs.org) do: + +``` +npm test +``` + +license +======= + +MIT/X11 diff --git a/node_modules/difflet/example/cmp_array.js b/node_modules/difflet/example/cmp_array.js new file mode 100644 index 0000000..bc5733f --- /dev/null +++ b/node_modules/difflet/example/cmp_array.js @@ -0,0 +1,6 @@ +var difflet = require('../'); +var s = difflet({ indent : 2, comment : true }).compare( + [ 1, [2,3,{a:4}], 3 ], + [ 1, [[5],6,7], 4 ] +); +process.stdout.write(s); diff --git a/node_modules/difflet/example/cmp_object.js b/node_modules/difflet/example/cmp_object.js new file mode 100644 index 0000000..5e00e2c --- /dev/null +++ b/node_modules/difflet/example/cmp_object.js @@ -0,0 +1,6 @@ +var difflet = require('../'); +var s = difflet({ indent : 2, comment : true }).compare( + { z : [6,7], a : 'abcdefgh', b : [ 31, 'xxt' ] }, + { x : 5, a : 'abdcefg', b : [ 51, 'xxs' ] } +); +console.log(s); diff --git a/node_modules/difflet/example/colors.js b/node_modules/difflet/example/colors.js new file mode 100644 index 0000000..332bbae --- /dev/null +++ b/node_modules/difflet/example/colors.js @@ -0,0 +1,18 @@ +var diff = require('../')({ indent : 2 }); + +var prev = { + yy : 6, + zz : 5, + a : [1,2,3], + fn : 'beep', + c : { x : 7, z : 3 } +}; + +var next = { + a : [ 1, 2, "z", /beep/, new Buffer(3) ], + fn : function qqq () {}, + b : [5,6,7], + c : { x : 8, y : 5 } +}; + +diff(prev, next).pipe(process.stdout); diff --git a/node_modules/difflet/example/comma_first.js b/node_modules/difflet/example/comma_first.js new file mode 100644 index 0000000..67ece23 --- /dev/null +++ b/node_modules/difflet/example/comma_first.js @@ -0,0 +1,12 @@ +var diff = require('../')({ + indent : 2, + comma : 'first', +}); + +var prev = { yy : 6, zz : 5, a : [1,2,3] }; +var next = { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer(3) ], + fn : 8, + b : [5,6,7] +}; +diff(prev, next).pipe(process.stdout); diff --git a/node_modules/difflet/example/diff.js b/node_modules/difflet/example/diff.js new file mode 100644 index 0000000..08f6e7a --- /dev/null +++ b/node_modules/difflet/example/diff.js @@ -0,0 +1,15 @@ +var difflet = require('../'); +var a = { + x : 4, + z : 8, + xs : [ 5, 2, 1, { 0 : 'c' } ], +}; + +var b = { + x : 4, + y : 5, + xs : [ 5, 2, 2, { c : 5 } ], +}; + +var s = difflet({ comment : true, indent : 2 }).compare(a, b); +console.log(s); diff --git a/node_modules/difflet/example/html.js b/node_modules/difflet/example/html.js new file mode 100644 index 0000000..9ff4a29 --- /dev/null +++ b/node_modules/difflet/example/html.js @@ -0,0 +1,34 @@ +var difflet = require('../'); +var ent = require('ent'); + +var tags = { + inserted : '', + updated : '', + deleted : '', +}; +var diff = difflet({ + start : function (t, s) { + s.write(tags[t]); + }, + stop : function (t, s) { + s.write(''); + }, + write : function (buf) { + stream.write(ent.encode(buf)) + }, +}); + +var prev = { + yy : 6, + zz : 5, + a : [1,2,3], + fn : function qq () {} +}; +var next = { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer([0,1,2]) ], + fn : 'I <3 robots', + b : [5,6,7] +}; + +var stream = diff(prev, next); +stream.pipe(process.stdout, { end : false }); diff --git a/node_modules/difflet/example/string.js b/node_modules/difflet/example/string.js new file mode 100644 index 0000000..6cff6cb --- /dev/null +++ b/node_modules/difflet/example/string.js @@ -0,0 +1,4 @@ +var difflet = require('../'); + +var s = difflet.compare({ a : 2, c : 5 }, { a : 3, b : 4 }); +process.stdout.write(s); diff --git a/node_modules/difflet/index.js b/node_modules/difflet/index.js new file mode 100644 index 0000000..278e6b9 --- /dev/null +++ b/node_modules/difflet/index.js @@ -0,0 +1,377 @@ +var traverse = require('traverse'); +var Stream = require('stream').Stream; +var charm = require('charm'); +var deepEqual = require('deep-is'); + +var exports = module.exports = function (opts_) { + var fn = difflet.bind(null, opts_); + fn.compare = function (prev, next) { + var opts = Object.keys(opts_ || {}).reduce(function (acc, key) { + acc[key] = opts_[key]; + return acc; + }, {}); + var s = opts.stream = new Stream; + var data = ''; + s.write = function (buf) { data += buf }; + s.end = function () {}; + s.readable = true; + s.writable = true; + + difflet(opts, prev, next); + return data; + }; + return fn; +}; + +exports.compare = function (prev, next) { + return exports({}).compare(prev, next); +}; + +function difflet (opts, prev, next) { + var stream = opts.stream || new Stream; + if (!opts.stream) { + stream.readable = true; + stream.writable = true; + stream.write = function (buf) { this.emit('data', buf) }; + stream.end = function () { this.emit('end') }; + } + + if (!opts) opts = {}; + if (opts.start === undefined && opts.stop === undefined) { + var c = charm(stream); + opts.start = function (type) { + c.foreground({ + inserted : 'green', + updated : 'blue', + deleted : 'red', + comment : 'cyan', + }[type]); + c.display('bright'); + }; + opts.stop = function (type) { + c.display('reset'); + }; + } + var write = function (buf) { + if (opts.write) opts.write(buf, stream) + else stream.write(buf) + }; + + var commaFirst = opts.comma === 'first'; + + var stringify = function (node, params) { + return stringifier.call(this, true, node, params || opts); + }; + var plainStringify = function (node, params) { + return stringifier.call(this, false, node, params || opts); + }; + + var levels = 0; + function set (type) { + if (levels === 0) opts.start(type, stream); + levels ++; + } + + function unset (type) { + if (--levels === 0) opts.stop(type, stream); + } + + function stringifier (insertable, node, opts) { + var indent = opts.indent; + + if (insertable) { + var prevNode = traverse.get(prev, this.path || []); + } + var inserted = insertable && prevNode === undefined; + + var indentx; + try { + indentx = indent ? Array( + ((this.path || []).length + 1) * indent + 1 + ).join(' ') : ''; + } catch (e) { + // at times we get an invalid Array size here and need to prevent crashing + indentx = ''; + } + if (commaFirst) indentx = indentx.slice(indent); + + if (Array.isArray(node)) { + var updated = (prevNode || traverse.has(prev, this.path)) + && !Array.isArray(prevNode); + if (updated) { + set('updated'); + } + + if (opts.comment && !Array.isArray(prevNode)) { + indent = 0; + } + + this.before(function () { + if (inserted) set('inserted'); + if (indent && commaFirst) { + if ((this.path || []).length === 0 + || Array.isArray(this.parent.node)) { + write('[ '); + } + else write('\n' + indentx + '[ '); + } + else if (indent) { + write('[\n' + indentx); + } + else { + write('['); + } + }); + + this.post(function (child) { + if (!child.isLast && !(indent && commaFirst)) { + write(','); + } + + var prev = prevNode && prevNode[child.key]; + if (indent && opts.comment && child.node !== prev + && (typeof child.node !== 'object' || typeof prev !== 'object') + ) { + set('comment'); + write(' // != '); + traverse(prev).forEach(function (x) { + plainStringify.call(this, x, { indent : 0 }); + }); + unset('comment'); + } + + if (!child.isLast) { + if (indent && commaFirst) { + write('\n' + indentx + ', '); + } + else if (indent) { + write('\n' + indentx); + } + } + }); + + this.after(function () { + if (indent && commaFirst) write('\n' + indentx); + else if (indent) write('\n' + indentx.slice(indent)); + + write(']'); + if (updated) unset('updated'); + if (inserted) unset('inserted'); + }); + } + else if (isRegExp(node)) { + this.block(); + + if (inserted) { + set('inserted'); + write(node.toString()); + unset('inserted'); + } + else if (insertable && prevNode !== node) { + set('updated'); + write(node.toString()); + unset('updated'); + } + else write(node.toString()); + } + else if (typeof node === 'object' + && node && typeof node.inspect === 'function') { + this.block(); + if (inserted) { + set('inserted'); + write(node.inspect()); + unset('inserted'); + } + else if (!(prevNode && typeof prevNode.inspect === 'function' + && prevNode.inspect() === node.inspect())) { + set('updated'); + write(node.inspect()); + unset('updated'); + } + else write(node.inspect()); + } + else if (typeof node == 'object' && node !== null) { + var insertedKey = false; + var deleted = insertable && typeof prevNode === 'object' && prevNode + ? Object.keys(prevNode).filter(function (key) { + return !Object.hasOwnProperty.call(node, key); + }) + : [] + ; + + this.before(function () { + if (inserted) set('inserted'); + write(indent && commaFirst && !this.isRoot + ? '\n' + indentx + '{ ' + : '{' + ); + }); + + this.pre(function (x, key) { + if (insertable) { + var obj = traverse.get(prev, this.path.concat(key)); + if (obj === undefined) { + insertedKey = true; + set('inserted'); + } + } + + if (indent && !commaFirst) write('\n' + indentx); + + plainStringify(key); + write(indent ? ' : ' : ':'); + }); + + this.post(function (child) { + if (!child.isLast && !(indent && commaFirst)) { + write(','); + } + + if (child.isLast && deleted.length) { + if (insertedKey) unset('inserted'); + insertedKey = false; + } + else if (insertedKey) { + unset('inserted'); + insertedKey = false; + } + + var prev = prevNode && prevNode[child.key]; + if (indent && opts.comment && child.node !== prev + && (typeof child.node !== 'object' || typeof prev !== 'object') + ) { + set('comment'); + write(' // != '); + traverse(prev).forEach(function (x) { + plainStringify.call(this, x, { indent : 0 }); + }); + unset('comment'); + } + + if (child.isLast && deleted.length) { + if (insertedKey) unset('inserted'); + insertedKey = false; + + if (indent && commaFirst) { + write('\n' + indentx + ', ') + } + else if (opts.comment && indent) { + write('\n' + indentx); + } + else if (indent) { + write(',\n' + indentx); + } + else write(','); + } + else { + if (!child.isLast) { + if (indent && commaFirst) { + write('\n' + indentx + ', '); + } + } + } + }); + + this.after(function () { + if (inserted) unset('inserted'); + + if (deleted.length) { + if (indent && !commaFirst + && Object.keys(node).length === 0) { + write('\n' + indentx); + } + + set('deleted'); + deleted.forEach(function (key, ix) { + if (indent && opts.comment) { + unset('deleted'); + set('comment'); + write('// '); + unset('comment'); + set('deleted'); + } + + plainStringify(key); + write(indent ? ' : ' : ':'); + traverse(prevNode[key]).forEach(function (x) { + plainStringify.call(this, x, { indent : 0 }); + }); + + var last = ix === deleted.length - 1; + if (insertable && !last) { + if (indent && commaFirst) { + write('\n' + indentx + ', '); + } + else if (indent) { + write(',\n' + indentx); + } + else write(','); + } + }); + unset('deleted'); + } + + if (commaFirst && indent) { + write(indentx.slice(indent) + ' }'); + } + else if (indent) { + write('\n' + indentx.slice(indent) + '}'); + } + else write('}'); + }); + } + else { + var changed = false; + + if (inserted) set('inserted'); + else if (insertable && !deepEqual(prevNode, node)) { + changed = true; + set('updated'); + } + + if (typeof node === 'string') { + write('"' + node.toString().replace(/"/g, '\\"') + '"'); + } + else if (isRegExp(node)) { + write(node.toString()); + } + else if (typeof node === 'function') { + write(node.name + ? '[Function: ' + node.name + ']' + : '[Function]' + ); + } + else if (node === undefined) { + write('undefined'); + } + else if (node === null) { + write('null'); + } + else { + write(node.toString()); + } + + if (inserted) unset('inserted'); + else if (changed) unset('updated'); + } + } + + if (opts.stream) { + traverse(next).forEach(stringify); + } + else process.nextTick(function () { + traverse(next).forEach(stringify); + stream.emit('end'); + }); + + return stream; +} + +function isRegExp (node) { + return node instanceof RegExp || (node + && typeof node.test === 'function' + && typeof node.exec === 'function' + && typeof node.compile === 'function' + && node.constructor && node.constructor.name === 'RegExp' + ); +} diff --git a/node_modules/difflet/package.json b/node_modules/difflet/package.json new file mode 100644 index 0000000..ac804db --- /dev/null +++ b/node_modules/difflet/package.json @@ -0,0 +1,41 @@ +{ + "name" : "difflet", + "description" : "colorful diffs for javascript objects", + "version" : "0.2.6", + "repository" : { + "type" : "git", + "url" : "git://github.com/substack/difflet.git" + }, + "main" : "index.js", + "keywords" : [ + "diff", + "object", + "compare" + ], + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "dependencies" : { + "traverse" : "0.6.x", + "charm" : "0.1.x", + "deep-is" : "0.1.x" + }, + "devDependencies" : { + "tap" : "0.1.x", + "ent" : "0.0.x" + }, + "engines" : { + "node" : ">=0.4.0" + }, + "license" : "MIT", + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + } +} diff --git a/node_modules/difflet/test/diffing-NaN.js b/node_modules/difflet/test/diffing-NaN.js new file mode 100644 index 0000000..d29e6e1 --- /dev/null +++ b/node_modules/difflet/test/diffing-NaN.js @@ -0,0 +1,17 @@ +var difflet = require('../'); +var diff = difflet(); +var test = require('tap').test; + +test('diffing NaN against NaN', function (t) { + t.plan(1); + var d = diff.compare(NaN, NaN); + + t.equal(d, 'NaN'); +}); + +test('diffing { o: NaN } against { o: NaN }', function (t) { + t.plan(1); + var d = diff.compare({ o: NaN }, { o: NaN }); + + t.equal(d, '{"o":NaN}'); +}); diff --git a/node_modules/difflet/test/html.js b/node_modules/difflet/test/html.js new file mode 100644 index 0000000..26d2ed4 --- /dev/null +++ b/node_modules/difflet/test/html.js @@ -0,0 +1,80 @@ +var difflet = require('../'); +var test = require('tap').test; +var ent = require('ent'); + +var tags = { + inserted : 'g', + updated : 'b', + deleted : 'r', +}; + +test('html output', function (t) { + t.plan(1); + var diff = difflet({ + start : function (t, s) { + s.write('<' + tags[t] + '>'); + }, + stop : function (t, s) { + s.write(''); + }, + write : function (buf, s) { + s.write(ent.encode(buf)); + } + }); + + var stream = diff( + { yy : 6, zz : 5, a : [1,2,3], fn : function qqq () {} }, + { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer([0,1,2]) ], + fn : function rrr () {}, + b : [5,6,7] + } + ); + + var data = '' + stream.on('data', function (buf) { data += buf }); + stream.on('end', function () { + t.equal(data, + '{"a":[1,2,3,[4],"z",' + + '/beep/,<Buffer 00 01 02>],' + + '"fn":[Function: rrr],' + + '"b":[5,6,7],"yy":6,' + + '"zz":5}' + ); + t.end(); + }); +}); + +test('compare html output', function (t) { + t.plan(1); + + var diff = difflet({ + start : function (t, s) { + s.write('<' + tags[t] + '>'); + }, + stop : function (t, s) { + s.write(''); + }, + write : function (buf, s) { + s.write(ent.encode(buf)); + } + }); + + var data = diff.compare( + { yy : 6, zz : 5, a : [1,2,3], fn : function qqq () {} }, + { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer([0,1,2]) ], + fn : function rrr () {}, + b : [5,6,7] + } + ); + + t.equal(data, + '{"a":[1,2,3,[4],"z",' + + '/beep/,<Buffer 00 01 02>],' + + '"fn":[Function: rrr],' + + '"b":[5,6,7],"yy":6,' + + '"zz":5}' + ); + t.end(); +}); diff --git a/node_modules/lnsocket/.envrc b/node_modules/lnsocket/.envrc new file mode 100644 index 0000000..db6b53e --- /dev/null +++ b/node_modules/lnsocket/.envrc @@ -0,0 +1,6 @@ +#use nix + +export PATH=$PWD:$PATH +export TODO_FILE=$PWD/TODO + +todo.sh ls || : diff --git a/node_modules/lnsocket/.gitmodules b/node_modules/lnsocket/.gitmodules new file mode 100644 index 0000000..967defe --- /dev/null +++ b/node_modules/lnsocket/.gitmodules @@ -0,0 +1,3 @@ +[submodule "deps/secp256k1"] + path = deps/secp256k1 + url = https://github.com/bitcoin-core/secp256k1 diff --git a/node_modules/lnsocket/LICENSE b/node_modules/lnsocket/LICENSE new file mode 100644 index 0000000..0a6688b --- /dev/null +++ b/node_modules/lnsocket/LICENSE @@ -0,0 +1,22 @@ +Copyright 2022 William Casarin. MIT license + +This license applies to everywhere in the codebase, but files with licenses at +the top of the file override this for those files. + +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. diff --git a/node_modules/lnsocket/Makefile b/node_modules/lnsocket/Makefile new file mode 100644 index 0000000..47b2a7c --- /dev/null +++ b/node_modules/lnsocket/Makefile @@ -0,0 +1,210 @@ + +CFLAGS=-Wall -Os -Ideps/secp256k1/include -Ideps/libsodium/src/libsodium/include -Ideps +LDFLAGS= + +SUBMODULES=deps/secp256k1 + +# Build for the simulator +XCODEDIR=$(shell xcode-select -p) +SIM_SDK=$(XCODEDIR)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk +IOS_SDK=$(XCODEDIR)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk + +HEADERS=config.h deps/secp256k1/include/secp256k1.h deps/libsodium/src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h +ARS=libsecp256k1.a libsodium.a lnsocket.a +WASM_ARS=target/js/libsecp256k1.a target/js/libsodium.a target/js/lnsocket.a +OBJS=sha256.o hkdf.o hmac.o sha512.o lnsocket.o error.o handshake.o crypto.o bigsize.o commando.o bech32.o +ARM64_OBJS=$(OBJS:.o=-arm64.o) +X86_64_OBJS=$(OBJS:.o=-x86_64.o) +WASM_OBJS=$(OBJS:.o=-wasm.o) lnsocket_wasm-wasm.o +BINS=test lnrpc + +DEPS=$(OBJS) $(ARS) $(HEADERS) + +all: $(BINS) $(ARS) + +ios: target/ios/lnsocket.a target/ios/libsodium.a target/ios/libsecp256k1.a + +js: target/js/lnsocket.js target/js/lnsocket.wasm + +node: target/node/lnsocket.js target/node/lnsocket.wasm + +target/node/lnsocket.js: target/tmp/node/lnsocket.js lnsocket_lib.js + @mkdir -p target/node + cat $^ > $@ + +target/js/lnsocket.js: target/tmp/js/lnsocket.js lnsocket_lib.js + @mkdir -p target/js + cat $^ > $@ + +libsodium-1.0.18-stable.tar.gz: + wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable.tar.gz + +deps/libsodium/configure: libsodium-1.0.18-stable.tar.gz + tar xvf $^; \ + mkdir -p deps; \ + mv libsodium-stable deps/libsodium + +deps/secp256k1/.git: + @tools/refresh-submodules.sh $(SUBMODULES) + +lnsocket.a: $(OBJS) + ar rcs $@ $(OBJS) + +target/arm64/lnsocket.a: $(ARM64_OBJS) + @mkdir -p target/arm64 + ar rcs $@ $^ + +target/x86_64/lnsocket.a: $(X86_64_OBJS) + @mkdir -p target/x86_64 + ar rcs $@ $^ + +target/js/lnsocket.a: $(WASM_OBJS) + @mkdir -p target/js + emar rcs $@ $^ + +target/ios/lnsocket.a: target/x86_64/lnsocket.a target/arm64/lnsocket.a + @mkdir -p target/ios + lipo -create $^ -output $@ + +%-arm64.o: %.c config.h + @echo "cc $@" + @$(CC) $(CFLAGS) -c $< -o $@ -arch arm64 -isysroot $(IOS_SDK) -target arm64-apple-ios -fembed-bitcode + +%-wasm.o: %.c config.h + @echo "emcc $@" + @emcc $(CFLAGS) -c $< -o $@ + +%-x86_64.o: %.c config.h + @echo "cc $@" + @$(CC) $(CFLAGS) -c $< -o $@ -arch x86_64 -isysroot $(SIM_SDK) -mios-simulator-version-min=6.0.0 -target x86_64-apple-ios-simulator + +# TODO cross compiled config?? +config.h: configurator + ./configurator > $@ + +configurator: configurator.c + $(CC) $< -o $@ + +%.o: %.c $(HEADERS) + @echo "cc $@" + @$(CC) $(CFLAGS) -c $< -o $@ + +deps/secp256k1/include/secp256k1.h: deps/secp256k1/.git + +deps/libsodium/src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h: deps/libsodium/configure + +deps/secp256k1/config.log: deps/secp256k1/configure + cd deps/secp256k1; \ + ./configure --disable-shared --enable-module-ecdh + +deps/libsodium/config.status: deps/libsodium/configure + cd deps/libsodium; \ + ./configure --disable-shared --enable-minimal + +deps/secp256k1/configure: deps/secp256k1/.git + cd deps/secp256k1; \ + patch -p1 < ../../tools/0001-configure-customizable-AR-and-RANLIB.patch; \ + ./autogen.sh + +deps/libsodium/config.log: deps/libsodium/configure + cd deps/libsodium; \ + ./configure + +deps/secp256k1/.libs/libsecp256k1.a: deps/secp256k1/config.log + cd deps/secp256k1; \ + make -j libsecp256k1.la + +libsecp256k1.a: deps/secp256k1/.libs/libsecp256k1.a + cp $< $@ + +libsodium.a: deps/libsodium/src/libsodium/.libs/libsodium.a + cp $< $@ + +target/ios/libsodium.a: deps/libsodium/libsodium-ios/lib/libsodium.a + @mkdir -p target/ios + cp $< $@ + +target/ios/libsecp256k1.a: deps/secp256k1/libsecp256k1-ios/lib/libsecp256k1.a + @mkdir -p target/ios + cp $< $@ + +target/js/libsecp256k1.a: deps/secp256k1/libsecp256k1-wasm/lib/libsecp256k1.a + @mkdir -p target/js + cp $< $@ + +target/js/libsodium.a: deps/libsodium/libsodium-js/lib/libsodium.a + @mkdir -p target/js + cp $< $@ + +deps/libsodium/libsodium-ios/lib/libsodium.a: deps/libsodium/configure + cd deps/libsodium; \ + ./dist-build/ios.sh + +deps/secp256k1/libsecp256k1-ios/lib/libsecp256k1.a: deps/secp256k1/configure + ./tools/secp-ios.sh + +deps/secp256k1/libsecp256k1-wasm/lib/libsecp256k1.a: deps/secp256k1/configure + ./tools/secp-wasm.sh + +deps/libsodium/libsodium-js/lib/libsodium.a: deps/libsodium/configure + cd deps/libsodium; \ + ./dist-build/emscripten.sh --standard + +deps/libsodium/src/libsodium/.libs/libsodium.a: deps/libsodium/config.log + cd deps/libsodium/src/libsodium; \ + make -j libsodium.la + +install: $(DEPS) + mkdir -p $(PREFIX)/lib $(PREFIX)/include + cp lnsocket.h $(PREFIX)/include + cp lnsocket.a libsecp256k1.a libsodium.a $(PREFIX)/lib + +install-js: js + mkdir -p $(PREFIX)/share/lnsocket + cp target/js/lnsocket.wasm target/js/lnsocket.js $(PREFIX)/share/lnsocket + +dist-node: node + @mkdir -p dist/node + cp target/node/lnsocket.wasm target/node/lnsocket.js dist/node + +install-all: install install-js + +check: test + @./test + +gocheck: + go test ./lnsocket.go + +test: test.o $(DEPS) + @echo "ld test" + @$(CC) $(CFLAGS) test.o $(OBJS) $(ARS) $(LDFLAGS) -o $@ + +lnrpc: lnrpc.o $(DEPS) + @echo "ld lnrpc" + @$(CC) $(CFLAGS) lnrpc.o $(OBJS) $(ARS) $(LDFLAGS) -o $@ + +target/js/lnsocket.wasm: target/tmp/js/lnsocket.js + cp target/tmp/js/lnsocket.wasm target/js/lnsocket.wasm + +target/node/lnsocket.wasm: target/tmp/node/lnsocket.js + cp target/tmp/node/lnsocket.wasm target/node/lnsocket.wasm + +target/tmp/node/lnsocket.js: $(WASM_ARS) lnsocket_pre.js + @mkdir -p target/tmp/node + emcc --pre-js lnsocket_pre.js -s MODULARIZE -flto -s 'EXPORTED_FUNCTIONS=["_malloc", "_free"]' -s EXPORTED_RUNTIME_METHODS=ccall,cwrap $(CFLAGS) -Wl,-whole-archive $(WASM_ARS) -Wl,-no-whole-archive -o $@ + +target/tmp/js/lnsocket.js: $(WASM_ARS) lnsocket_pre.js + @mkdir -p target/tmp/js + emcc --pre-js lnsocket_pre.js -s ENVIRONMENT=web -s MODULARIZE -flto -s 'EXPORTED_FUNCTIONS=["_malloc", "_free"]' -s EXPORTED_RUNTIME_METHODS=ccall,cwrap $(CFLAGS) -Wl,-whole-archive $(WASM_ARS) -Wl,-no-whole-archive -o $@ + +tags: fake + find . -name '*.c' -or -name '*.h' | xargs ctags + +clean: fake + rm -rf $(BINS) config.h $(OBJS) $(ARM64_OBJS) $(X86_64_OBJS) $(WASM_OBJS) target + +distclean: clean + rm -rf $(ARS) deps target + + +.PHONY: fake diff --git a/node_modules/lnsocket/README.md b/node_modules/lnsocket/README.md new file mode 100644 index 0000000..36735a9 --- /dev/null +++ b/node_modules/lnsocket/README.md @@ -0,0 +1,82 @@ + +# lnsocket + +A simple C library for sending messages over the lightning network + +Thanks to Rusty and the clightning project for much of this code, I have +adapted it to be more library friendly. + + +## Motivation + +I wanted a way to send custom messages to my lightning node, such as RPC. +Building this as a simple C library will allow you to speak the lightning +network in native applications, like on mobile. + + +## Dependencies + +You'll need `libtool`, `autoconf`, and `automake` for the `libsodium` & +`secp256k1` submodules, but otherwise there are no dependencies. + +You'll need `emscripten` for the `wasm` build. + +## Building + + $ make + +### iOS + + $ make ios + +This will build `lnsocket.a`, `libsodium.a` and `libsecp256k1.a` under +`target/ios` for `arm64` and `ios-sim-x86`. + + +### WASM/JS/Web + + $ make js + +This will build `lnsocket.js` and `lnsocket.wasm` in `target/js` so that you +can connect to the lightning network from your browser via websockets. See +[examples/websockets.js](examples/websockets.js) for a demo. + +### NodeJS + + $ npm install --save lnsocket + +See [examples/node.js](examples/node.js) + +### Go + +There is a Go version of lnsocket written using lnd's brontide[^3]. + +You can import it via: + + import "github.com/jb55/lnsocket/go" + +It is currently used in fiatjaf's makeinvoice go library[^4] if you want an +example of its usage. + +## C Examples + +* See [test.c](test.c) for a ping/pong example + +* See [lnrpc.c](lnrpc.c) for an RPC example + +## Contributing + +Send patches to `jb55@jb55.com` + + $ git config format.subjectPrefix 'PATCH lnsocket' + $ git config sendemail.to 'William Casarin ' + $ git send-email --annotate HEAD^ + +See git-send-email.io[^1] for configuring your mailer + +You can open a PR on github[^2] as well + +[^1]: https://git-send-email.io/ +[^2]: https://github.com/jb55/lnsocket +[^3]: https://github.com/lightningnetwork/lnd/tree/master/brontide +[^4]: https://github.com/fiatjaf/makeinvoice/blob/d523b35084af04883f94323dc11a50c2a99d253d/makeinvoice.go#L366 diff --git a/node_modules/lnsocket/TODO b/node_modules/lnsocket/TODO new file mode 100644 index 0000000..84db60b --- /dev/null +++ b/node_modules/lnsocket/TODO @@ -0,0 +1,7 @@ +dynamic lib +automatic towire/fromwire serialization +better helpers for building tlvs +(C) python bindings +(A) websocket test suite +(B) nodejs tests +C tests diff --git a/node_modules/lnsocket/bech32.c b/node_modules/lnsocket/bech32.c new file mode 100644 index 0000000..d660c39 --- /dev/null +++ b/node_modules/lnsocket/bech32.c @@ -0,0 +1,211 @@ +/* Stolen from https://github.com/sipa/bech32/blob/master/ref/c/segwit_addr.c, + * with only the two ' > 90' checks hoisted, and more internals exposed */ + +/* Copyright (c) 2017, 2021 Pieter Wuille + * + * 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. + */ + +#include "config.h" +#include +#include +#include "bech32.h" + +static uint32_t bech32_polymod_step(uint32_t pre) { + uint8_t b = pre >> 25; + return ((pre & 0x1FFFFFF) << 5) ^ + (-((b >> 0) & 1) & 0x3b6a57b2UL) ^ + (-((b >> 1) & 1) & 0x26508e6dUL) ^ + (-((b >> 2) & 1) & 0x1ea119faUL) ^ + (-((b >> 3) & 1) & 0x3d4233ddUL) ^ + (-((b >> 4) & 1) & 0x2a1462b3UL); +} + +static uint32_t bech32_final_constant(bech32_encoding enc) { + if (enc == BECH32_ENCODING_BECH32) return 1; + if (enc == BECH32_ENCODING_BECH32M) return 0x2bc830a3; + assert(0); +} + +const char bech32_charset[] = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; + +const int8_t bech32_charset_rev[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, + -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, + 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, + -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, + 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 +}; + +int bech32_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len, size_t max_input_len, bech32_encoding enc) { + uint32_t chk = 1; + size_t i = 0; + while (hrp[i] != 0) { + int ch = hrp[i]; + if (ch < 33 || ch > 126) { + return 0; + } + + if (ch >= 'A' && ch <= 'Z') return 0; + chk = bech32_polymod_step(chk) ^ (ch >> 5); + ++i; + } + if (i + 7 + data_len > max_input_len) return 0; + chk = bech32_polymod_step(chk); + while (*hrp != 0) { + chk = bech32_polymod_step(chk) ^ (*hrp & 0x1f); + *(output++) = *(hrp++); + } + *(output++) = '1'; + for (i = 0; i < data_len; ++i) { + if (*data >> 5) return 0; + chk = bech32_polymod_step(chk) ^ (*data); + *(output++) = bech32_charset[*(data++)]; + } + for (i = 0; i < 6; ++i) { + chk = bech32_polymod_step(chk); + } + chk ^= bech32_final_constant(enc); + for (i = 0; i < 6; ++i) { + *(output++) = bech32_charset[(chk >> ((5 - i) * 5)) & 0x1f]; + } + *output = 0; + return 1; +} + +bech32_encoding bech32_decode(char* hrp, uint8_t *data, size_t *data_len, const char *input, size_t max_input_len) { + uint32_t chk = 1; + size_t i; + size_t input_len = strlen(input); + size_t hrp_len; + int have_lower = 0, have_upper = 0; + if (input_len < 8 || input_len > max_input_len) { + return BECH32_ENCODING_NONE; + } + *data_len = 0; + while (*data_len < input_len && input[(input_len - 1) - *data_len] != '1') { + ++(*data_len); + } + hrp_len = input_len - (1 + *data_len); + if (1 + *data_len >= input_len || *data_len < 6) { + return BECH32_ENCODING_NONE; + } + *(data_len) -= 6; + for (i = 0; i < hrp_len; ++i) { + int ch = input[i]; + if (ch < 33 || ch > 126) { + return BECH32_ENCODING_NONE; + } + if (ch >= 'a' && ch <= 'z') { + have_lower = 1; + } else if (ch >= 'A' && ch <= 'Z') { + have_upper = 1; + ch = (ch - 'A') + 'a'; + } + hrp[i] = ch; + chk = bech32_polymod_step(chk) ^ (ch >> 5); + } + hrp[i] = 0; + chk = bech32_polymod_step(chk); + for (i = 0; i < hrp_len; ++i) { + chk = bech32_polymod_step(chk) ^ (input[i] & 0x1f); + } + ++i; + while (i < input_len) { + int v = (input[i] & 0x80) ? -1 : bech32_charset_rev[(int)input[i]]; + if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1; + if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1; + if (v == -1) { + return BECH32_ENCODING_NONE; + } + chk = bech32_polymod_step(chk) ^ v; + if (i + 6 < input_len) { + data[i - (1 + hrp_len)] = v; + } + ++i; + } + if (have_lower && have_upper) { + return BECH32_ENCODING_NONE; + } + if (chk == bech32_final_constant(BECH32_ENCODING_BECH32)) { + return BECH32_ENCODING_BECH32; + } else if (chk == bech32_final_constant(BECH32_ENCODING_BECH32M)) { + return BECH32_ENCODING_BECH32M; + } else { + return BECH32_ENCODING_NONE; + } +} + +int bech32_convert_bits(uint8_t* out, size_t* outlen, int outbits, const uint8_t* in, size_t inlen, int inbits, int pad) { + uint32_t val = 0; + int bits = 0; + uint32_t maxv = (((uint32_t)1) << outbits) - 1; + while (inlen--) { + val = (val << inbits) | *(in++); + bits += inbits; + while (bits >= outbits) { + bits -= outbits; + out[(*outlen)++] = (val >> bits) & maxv; + } + } + if (pad) { + if (bits) { + out[(*outlen)++] = (val << (outbits - bits)) & maxv; + } + } else if (((val << (outbits - bits)) & maxv) || bits >= inbits) { + return 0; + } + return 1; +} + +int segwit_addr_encode(char *output, const char *hrp, int witver, const uint8_t *witprog, size_t witprog_len) { + uint8_t data[65]; + size_t datalen = 0; + bech32_encoding enc = BECH32_ENCODING_BECH32; + if (witver > 16) return 0; + if (witver == 0 && witprog_len != 20 && witprog_len != 32) return 0; + if (witprog_len < 2 || witprog_len > 40) return 0; + if (witver > 0) enc = BECH32_ENCODING_BECH32M; + data[0] = witver; + bech32_convert_bits(data + 1, &datalen, 5, witprog, witprog_len, 8, 1); + ++datalen; + return bech32_encode(output, hrp, data, datalen, 90, enc); +} + +int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { + uint8_t data[84]; + char hrp_actual[84]; + size_t data_len; + bech32_encoding enc = bech32_decode(hrp_actual, data, &data_len, addr, 90); + if (enc == BECH32_ENCODING_NONE) return 0; + if (data_len == 0 || data_len > 65) return 0; + if (strncmp(hrp, hrp_actual, 84) != 0) return 0; + if (data[0] > 16) return 0; + if (data[0] == 0 && enc != BECH32_ENCODING_BECH32) return 0; + if (data[0] > 0 && enc != BECH32_ENCODING_BECH32M) return 0; + *witdata_len = 0; + if (!bech32_convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) return 0; + if (*witdata_len < 2 || *witdata_len > 40) return 0; + if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) return 0; + *witver = data[0]; + return 1; +} diff --git a/node_modules/lnsocket/bech32.h b/node_modules/lnsocket/bech32.h new file mode 100644 index 0000000..614ad32 --- /dev/null +++ b/node_modules/lnsocket/bech32.h @@ -0,0 +1,134 @@ +/* Stolen from https://github.com/sipa/bech32/blob/master/ref/c/segwit_addr.h, + * with only the two ' > 90' checks hoisted */ + +/* Copyright (c) 2017, 2021 Pieter Wuille + * + * 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. + */ + +#ifndef LIGHTNING_COMMON_BECH32_H +#define LIGHTNING_COMMON_BECH32_H +#include "config.h" + +#include +#include + +/** Encode a SegWit address + * + * Out: output: Pointer to a buffer of size 73 + strlen(hrp) that will be + * updated to contain the null-terminated address. + * In: hrp: Pointer to the null-terminated human readable part to use + * (chain/network specific). + * ver: Version of the witness program (between 0 and 16 inclusive). + * prog: Data bytes for the witness program (between 2 and 40 bytes). + * prog_len: Number of data bytes in prog. + * Returns 1 if successful. + */ +int segwit_addr_encode( + char *output, + const char *hrp, + int ver, + const uint8_t *prog, + size_t prog_len +); + +/** Decode a SegWit address + * + * Out: ver: Pointer to an int that will be updated to contain the witness + * program version (between 0 and 16 inclusive). + * prog: Pointer to a buffer of size 40 that will be updated to + * contain the witness program bytes. + * prog_len: Pointer to a size_t that will be updated to contain the length + * of bytes in prog. + * hrp: Pointer to the null-terminated human readable part that is + * expected (chain/network specific). + * addr: Pointer to the null-terminated address. + * Returns 1 if successful. + */ +int segwit_addr_decode( + int* ver, + uint8_t* prog, + size_t* prog_len, + const char* hrp, + const char* addr +); + +/** Supported encodings. */ +typedef enum { + BECH32_ENCODING_NONE, + BECH32_ENCODING_BECH32, + BECH32_ENCODING_BECH32M +} bech32_encoding; + +/** Encode a Bech32 or Bech32m string + * + * Out: output: Pointer to a buffer of size strlen(hrp) + data_len + 8 that + * will be updated to contain the null-terminated Bech32 string. + * In: hrp : Pointer to the null-terminated human readable part. + * data : Pointer to an array of 5-bit values. + * data_len: Length of the data array. + * max_input_len: Maximum valid length of input (90 for segwit usage). + * enc: Which encoding to use (BECH32_ENCODING_BECH32{,M}). + * Returns 1 if successful. + */ +int bech32_encode( + char *output, + const char *hrp, + const uint8_t *data, + size_t data_len, + size_t max_input_len, + bech32_encoding enc +); + +/** Decode a Bech32 or Bech32m string + * + * Out: hrp: Pointer to a buffer of size strlen(input) - 6. Will be + * updated to contain the null-terminated human readable part. + * data: Pointer to a buffer of size strlen(input) - 8 that will + * hold the encoded 5-bit data values. + * data_len: Pointer to a size_t that will be updated to be the number + * of entries in data. + * In: input: Pointer to a null-terminated Bech32 string. + * max_input_len: Maximum valid length of input (90 for segwit usage). + * Returns BECH32_ENCODING_BECH32{,M} to indicate decoding was successful + * with the specified encoding standard. BECH32_ENCODING_NONE is returned if + * decoding failed. + */ +bech32_encoding bech32_decode( + char *hrp, + uint8_t *data, + size_t *data_len, + const char *input, + size_t max_input_len +); + +/* Helper from bech32: translates inbits-bit bytes to outbits-bit bytes. + * @outlen is incremented as bytes are added. + * @pad is true if we're to pad, otherwise truncate last byte if necessary + */ +int bech32_convert_bits(uint8_t* out, size_t* outlen, int outbits, + const uint8_t* in, size_t inlen, int inbits, + int pad); + +/* The charset, and reverse mapping */ +extern const char bech32_charset[32]; +extern const int8_t bech32_charset_rev[128]; + +#endif /* LIGHTNING_COMMON_BECH32_H */ + diff --git a/node_modules/lnsocket/bigsize.c b/node_modules/lnsocket/bigsize.c new file mode 100644 index 0000000..ea8d238 --- /dev/null +++ b/node_modules/lnsocket/bigsize.c @@ -0,0 +1,140 @@ +/* Copyright Rusty Russell (Blockstream) 2015. + William Casarin 2022 + +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. +*/ + + +#include +#include "config.h" +#include "bigsize.h" + +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif + +size_t bigsize_len(bigsize_t v) +{ + if (v < 0xfd) { + return 1; + } else if (v <= 0xffff) { + return 3; + } else if (v <= 0xffffffff) { + return 5; + } else { + return 9; + } +} + +size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN], bigsize_t v) +{ + u8 *p = buf; + + if (v < 0xfd) { + *(p++) = v; + } else if (v <= 0xffff) { + (*p++) = 0xfd; + (*p++) = v >> 8; + (*p++) = v; + } else if (v <= 0xffffffff) { + (*p++) = 0xfe; + (*p++) = v >> 24; + (*p++) = v >> 16; + (*p++) = v >> 8; + (*p++) = v; + } else { + (*p++) = 0xff; + (*p++) = v >> 56; + (*p++) = v >> 48; + (*p++) = v >> 40; + (*p++) = v >> 32; + (*p++) = v >> 24; + (*p++) = v >> 16; + (*p++) = v >> 8; + (*p++) = v; + } + return p - buf; +} + +size_t bigsize_get(const u8 *p, size_t max, bigsize_t *val) +{ + if (max < 1) { + SUPERVERBOSE("EOF"); + return 0; + } + + switch (*p) { + case 0xfd: + if (max < 3) { + SUPERVERBOSE("unexpected EOF"); + return 0; + } + *val = ((u64)p[1] << 8) + p[2]; + if (*val < 0xfd) { + SUPERVERBOSE("decoded bigsize is not canonical"); + return 0; + } + return 3; + case 0xfe: + if (max < 5) { + SUPERVERBOSE("unexpected EOF"); + return 0; + } + *val = ((u64)p[1] << 24) + ((u64)p[2] << 16) + + ((u64)p[3] << 8) + p[4]; + if ((*val >> 16) == 0) { + SUPERVERBOSE("decoded bigsize is not canonical"); + return 0; + } + return 5; + case 0xff: + if (max < 9) { + SUPERVERBOSE("unexpected EOF"); + return 0; + } + *val = ((u64)p[1] << 56) + ((u64)p[2] << 48) + + ((u64)p[3] << 40) + ((u64)p[4] << 32) + + ((u64)p[5] << 24) + ((u64)p[6] << 16) + + ((u64)p[7] << 8) + p[8]; + if ((*val >> 32) == 0) { + SUPERVERBOSE("decoded bigsize is not canonical"); + return 0; + } + return 9; + default: + *val = *p; + return 1; + } +} + +int cursor_pull_bigsize(struct cursor *cur, bigsize_t *out) +{ + return bigsize_get(cur->p, cur->end - cur->p, out); +} + +int cursor_push_bigsize(struct cursor *cur, const bigsize_t val) +{ + u8 buf[BIGSIZE_MAX_LEN]; + size_t len; + + len = bigsize_put(buf, val); + + return cursor_push(cur, buf, len); +} + diff --git a/node_modules/lnsocket/bigsize.h b/node_modules/lnsocket/bigsize.h new file mode 100644 index 0000000..a630789 --- /dev/null +++ b/node_modules/lnsocket/bigsize.h @@ -0,0 +1,31 @@ +#ifndef LNSOCKET_BIGSIZE_H +#define LNSOCKET_BIGSIZE_H +#include "config.h" +#include "cursor.h" +#include + +/* typedef for clarity. */ +typedef u64 bigsize_t; + +#define BIGSIZE_MAX_LEN 9 + +/* Returns length of buf used. */ +size_t bigsize_put(unsigned char buf[BIGSIZE_MAX_LEN], bigsize_t v); + +/* Returns 0 on failure, otherwise length (<= max) used. */ +size_t bigsize_get(const unsigned char *p, size_t max, bigsize_t *val); + +/* How many bytes does it take to encode v? */ +size_t bigsize_len(bigsize_t v); + +/* Used for wire generation */ +typedef bigsize_t bigsize; + +/* marshal/unmarshal functions */ +void towire_bigsize(unsigned char **pptr, const bigsize_t val); +bigsize_t fromwire_bigsize(const unsigned char **cursor, size_t *max); + +int cursor_pull_bigsize(struct cursor *cur, bigsize_t *out); +int cursor_push_bigsize(struct cursor *cur, const bigsize_t val); + +#endif /* LNSOCKET_BIGSIZE_H */ diff --git a/node_modules/lnsocket/commando.c b/node_modules/lnsocket/commando.c new file mode 100644 index 0000000..cab71da --- /dev/null +++ b/node_modules/lnsocket/commando.c @@ -0,0 +1,36 @@ + +#include "lnsocket.h" +#include "cursor.h" +#include "endian.h" +#include "commando.h" +#include "export.h" + +int EXPORT commando_make_rpc_msg(const char *method, const char *params, + const char *rune, unsigned int req_id, unsigned char *buf, int buflen) +{ + struct cursor msgbuf; + int ok; + + make_cursor(buf, buf+buflen, &msgbuf); + + params = (params == NULL || params[0] == '\0') ? "[]" : params; + + if (!cursor_push_u16(&msgbuf, COMMANDO_CMD)) + return 0; + + if (!cursor_push_u64(&msgbuf, (u64)req_id)) + return 0; + + ok = cursor_push_str(&msgbuf, "{\"method\":\"") && + cursor_push_str(&msgbuf, method) && + cursor_push_str(&msgbuf, "\",\"params\":") && + cursor_push_str(&msgbuf, params) && + cursor_push_str(&msgbuf, ",\"rune\":\"") && + cursor_push_str(&msgbuf, rune) && + cursor_push_str(&msgbuf, "\"}"); + + if (!ok) + return 0; + + return msgbuf.p - msgbuf.start; +} diff --git a/node_modules/lnsocket/commando.h b/node_modules/lnsocket/commando.h new file mode 100644 index 0000000..1e4d211 --- /dev/null +++ b/node_modules/lnsocket/commando.h @@ -0,0 +1,14 @@ + +#ifndef LNSOCKET_COMMANDO +#define LNSOCKET_COMMANDO + +#include +#include "export.h" + +#define COMMANDO_CMD 0x4c4f +#define COMMANDO_REPLY_CONTINUES 0x594b +#define COMMANDO_REPLY_TERM 0x594d + +int EXPORT commando_make_rpc_msg(const char *method, const char *params, const char *rune, unsigned int req_id, unsigned char *buf, int buflen); + +#endif /* LNSOCKET_COMMANDO */ diff --git a/node_modules/lnsocket/compiler.h b/node_modules/lnsocket/compiler.h new file mode 100644 index 0000000..deb0621 --- /dev/null +++ b/node_modules/lnsocket/compiler.h @@ -0,0 +1,85 @@ + +#ifndef COMPILER_H +#define COMPILER_H + +#include +#include +#include +#include "config.h" + +#if HAVE_UNALIGNED_ACCESS +#define alignment_ok(p, n) 1 +#else +#define alignment_ok(p, n) ((size_t)(p) % (n) == 0) +#endif + +#define UNUSED __attribute__((__unused__)) + +/** + * BUILD_ASSERT - assert a build-time dependency. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can only be used within a function. + * + * Example: + * #include + * ... + * static char *foo_to_char(struct foo *foo) + * { + * // This code needs string to be at start of foo. + * BUILD_ASSERT(offsetof(struct foo, string) == 0); + * return (char *)foo; + * } + */ +#define BUILD_ASSERT(cond) \ + do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) + +/** + * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can be used in an expression: its value is "0". + * + * Example: + * #define foo_to_char(foo) \ + * ((char *)(foo) \ + * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) + */ +#define BUILD_ASSERT_OR_ZERO(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#define memclear(mem, size) memset(mem, 0, size) +#define memclear_2(m1, s1, m2, s2) { memclear(m1, s1); memclear(m2, s2); } +#define memclear_3(m1, s1, m2, s2, m3, s3) { memclear(m1, s1); memclear(m2, s2); memclear(m3, s3); } + +static inline void *memcheck_(const void *data, size_t len) +{ + (void)len; + return (void *)data; +} + +#if HAVE_TYPEOF +/** + * memcheck - check that a memory region is initialized + * @data: start of region + * @len: length in bytes + * + * When running under valgrind, this causes an error to be printed + * if the entire region is not defined. Otherwise valgrind only + * reports an error when an undefined value is used for a branch, or + * written out. + * + * Example: + * // Search for space, but make sure it's all initialized. + * if (memchr(memcheck(somebytes, bytes_len), ' ', bytes_len)) { + * printf("space was found!\n"); + * } + */ +#define memcheck(data, len) ((__typeof__((data)+0))memcheck_((data), (len))) +#else +#define memcheck(data, len) memcheck_((data), (len)) +#endif + +#endif /* COMPILER_H */ diff --git a/node_modules/lnsocket/configurator.c b/node_modules/lnsocket/configurator.c new file mode 100644 index 0000000..68d7fc6 --- /dev/null +++ b/node_modules/lnsocket/configurator.c @@ -0,0 +1,1110 @@ +/* Simple tool to create config.h. + * Would be much easier with ccan modules, but deliberately standalone. + * + * Copyright 2011 Rusty Russell . MIT license. + * + * c12r_err, c12r_errx functions copied from ccan/err/err.c + * Copyright Rusty Russell . CC0 (Public domain) License. + * + * 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. + */ +#define _POSIX_C_SOURCE 200809L /* For pclose, popen, strdup */ + +#define EXIT_BAD_USAGE 1 +#define EXIT_TROUBLE_RUNNING 2 +#define EXIT_BAD_TEST 3 +#define EXIT_BAD_INPUT 4 + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define popen _popen +#define pclose _pclose +#endif + +#ifdef _MSC_VER +#define DEFAULT_COMPILER "cl" +/* Note: Dash options avoid POSIX path conversion when used under msys bash + * and are therefore preferred to slash (e.g. -nologo over /nologo) + * Note: Disable Warning 4200 "nonstandard extension used : zero-sized array + * in struct/union" for flexible array members. + */ +#define DEFAULT_FLAGS "-nologo -Zi -W4 -wd4200 " \ + "-D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS" +#define DEFAULT_OUTPUT_EXE_FLAG "-Fe:" +#else +#define DEFAULT_COMPILER "cc" +#define DEFAULT_FLAGS "-g3 -ggdb -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition" +#define DEFAULT_OUTPUT_EXE_FLAG "-o" +#endif + +#define OUTPUT_FILE "configurator.out" +#define INPUT_FILE "configuratortest.c" + +#ifdef _WIN32 +#define DIR_SEP "\\" +#else +#define DIR_SEP "/" +#endif + +static const char *progname = ""; +static int verbose; +static bool like_a_libtool = false; + +struct test { + const char *name; + const char *desc; + /* + * Template style flags (pick one): + * OUTSIDE_MAIN: + * - put a simple boilerplate main below it. + * DEFINES_FUNC: + * - defines a static function called func; adds ref to avoid warnings + * INSIDE_MAIN: + * - put this inside main(). + * DEFINES_EVERYTHING: + * - don't add any boilerplate at all. + * + * Execution flags: + * EXECUTE: + * - a runtime test; must compile, exit 0 means flag is set. + * MAY_NOT_COMPILE: + * - Only useful with EXECUTE: don't get upset if it doesn't compile. + * : + * - a compile test, if it compiles must run and exit 0. + */ + const char *style; + const char *depends; + const char *link; + const char *fragment; + const char *flags; + const char *overrides; /* On success, force this to '1' */ + bool done; + bool answer; +}; + +/* Terminated by a NULL name */ +static struct test *tests; + +static const struct test base_tests[] = { + { "HAVE_UNALIGNED_ACCESS", "unaligned access to int", + "DEFINES_EVERYTHING|EXECUTE", NULL, NULL, + "#include \n" + "int main(int argc, char *argv[]) {\n" + " (void)argc;\n" + " char pad[sizeof(int *) * 1];\n" + " memcpy(pad, argv[0], sizeof(pad));\n" + " int *x = (int *)pad, *y = (int *)(pad + 1);\n" + " return *x == *y;\n" + "}\n" }, + { "HAVE_TYPEOF", "__typeof__ support", + "INSIDE_MAIN", NULL, NULL, + "__typeof__(argc) i; i = argc; return i == argc ? 0 : 1;" }, + { "HAVE_BIG_ENDIAN", "big endian", + "INSIDE_MAIN|EXECUTE", NULL, NULL, + "union { int i; char c[sizeof(int)]; } u;\n" + "u.i = 0x01020304;\n" + "return u.c[0] == 0x01 && u.c[1] == 0x02 && u.c[2] == 0x03 && u.c[3] == 0x04 ? 0 : 1;" }, + { "HAVE_BYTESWAP_H", "", + "OUTSIDE_MAIN", NULL, NULL, + "#include \n" }, + { "HAVE_BSWAP_64", "bswap64 in byteswap.h", + "DEFINES_FUNC", "HAVE_BYTESWAP_H", NULL, + "#include \n" + "static int func(int x) { return bswap_64(x); }" }, + { "HAVE_LITTLE_ENDIAN", "little endian", + "INSIDE_MAIN|EXECUTE", NULL, NULL, + "union { int i; char c[sizeof(int)]; } u;\n" + "u.i = 0x01020304;\n" + "return u.c[0] == 0x04 && u.c[1] == 0x03 && u.c[2] == 0x02 && u.c[3] == 0x01 ? 0 : 1;" }, + /* + { "HAVE_32BIT_OFF_T", "off_t is 32 bits", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL, + "#include \n" + "int main(void) {\n" + " return sizeof(off_t) == 4 ? 0 : 1;\n" + "}\n" }, + { "HAVE_ALIGNOF", "__alignof__ support", + "INSIDE_MAIN", NULL, NULL, + "return __alignof__(double) > 0 ? 0 : 1;" }, + { "HAVE_ASPRINTF", "asprintf() declaration", + "DEFINES_FUNC", NULL, NULL, + "#ifndef _GNU_SOURCE\n" + "#define _GNU_SOURCE\n" + "#endif\n" + "#include \n" + "static char *func(int x) {" + " char *p;\n" + " if (asprintf(&p, \"%u\", x) == -1) \n" + " p = NULL;\n" + " return p;\n" + "}" }, + { "HAVE_ATTRIBUTE_COLD", "__attribute__((cold)) support", + "DEFINES_FUNC", NULL, NULL, + "static int __attribute__((cold)) func(int x) { return x; }" }, + { "HAVE_ATTRIBUTE_CONST", "__attribute__((const)) support", + "DEFINES_FUNC", NULL, NULL, + "static int __attribute__((const)) func(int x) { return x; }" }, + { "HAVE_ATTRIBUTE_DEPRECATED", "__attribute__((deprecated)) support", + "DEFINES_FUNC", NULL, NULL, + "static int __attribute__((deprecated)) func(int x) { return x; }" }, + { "HAVE_ATTRIBUTE_NONNULL", "__attribute__((nonnull)) support", + "DEFINES_FUNC", NULL, NULL, + "static char *__attribute__((nonnull)) func(char *p) { return p; }" }, + { "HAVE_ATTRIBUTE_RETURNS_NONNULL", "__attribute__((returns_nonnull)) support", + "DEFINES_FUNC", NULL, NULL, + "static const char *__attribute__((returns_nonnull)) func(void) { return \"hi\"; }" }, + { "HAVE_ATTRIBUTE_SENTINEL", "__attribute__((sentinel)) support", + "DEFINES_FUNC", NULL, NULL, + "static int __attribute__((sentinel)) func(int i, ...) { return i; }" }, + { "HAVE_ATTRIBUTE_PURE", "__attribute__((pure)) support", + "DEFINES_FUNC", NULL, NULL, + "static int __attribute__((pure)) func(int x) { return x; }" }, + { "HAVE_ATTRIBUTE_MAY_ALIAS", "__attribute__((may_alias)) support", + "OUTSIDE_MAIN", NULL, NULL, + "typedef short __attribute__((__may_alias__)) short_a;" }, + { "HAVE_ATTRIBUTE_NORETURN", "__attribute__((noreturn)) support", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static void __attribute__((noreturn)) func(int x) { exit(x); }" }, + { "HAVE_ATTRIBUTE_PRINTF", "__attribute__ format printf support", + "DEFINES_FUNC", NULL, NULL, + "static void __attribute__((format(__printf__, 1, 2))) func(const char *fmt, ...) { (void)fmt; }" }, + { "HAVE_ATTRIBUTE_UNUSED", "__attribute__((unused)) support", + "OUTSIDE_MAIN", NULL, NULL, + "static int __attribute__((unused)) func(int x) { return x; }" }, + { "HAVE_ATTRIBUTE_USED", "__attribute__((used)) support", + "OUTSIDE_MAIN", NULL, NULL, + "static int __attribute__((used)) func(int x) { return x; }" }, + { "HAVE_BACKTRACE", "backtrace() in ", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static int func(int x) {" + " void *bt[10];\n" + " return backtrace(bt, 10) < x;\n" + "}" }, + { "HAVE_BUILTIN_CHOOSE_EXPR", "__builtin_choose_expr support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_choose_expr(1, 0, \"garbage\");" }, + { "HAVE_BUILTIN_CLZ", "__builtin_clz support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_clz(1) == (sizeof(int)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CLZL", "__builtin_clzl support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_clzl(1) == (sizeof(long)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CLZLL", "__builtin_clzll support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_clzll(1) == (sizeof(long long)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CTZ", "__builtin_ctz support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ctz(1 << (sizeof(int)*8 - 1)) == (sizeof(int)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CTZL", "__builtin_ctzl support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ctzl(1UL << (sizeof(long)*8 - 1)) == (sizeof(long)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CTZLL", "__builtin_ctzll support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ctzll(1ULL << (sizeof(long long)*8 - 1)) == (sizeof(long long)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CONSTANT_P", "__builtin_constant_p support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_constant_p(1) ? 0 : 1;" }, + { "HAVE_BUILTIN_EXPECT", "__builtin_expect support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_expect(argc == 1, 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_FFS", "__builtin_ffs support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ffs(0) == 0 ? 0 : 1;" }, + { "HAVE_BUILTIN_FFSL", "__builtin_ffsl support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ffsl(0L) == 0 ? 0 : 1;" }, + { "HAVE_BUILTIN_FFSLL", "__builtin_ffsll support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ffsll(0LL) == 0 ? 0 : 1;" }, + { "HAVE_BUILTIN_POPCOUNT", "__builtin_popcount support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_popcount(255) == 8 ? 0 : 1;" }, + { "HAVE_BUILTIN_POPCOUNTL", "__builtin_popcountl support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_popcountl(255L) == 8 ? 0 : 1;" }, + { "HAVE_BUILTIN_POPCOUNTLL", "__builtin_popcountll support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_popcountll(255LL) == 8 ? 0 : 1;" }, + { "HAVE_BUILTIN_TYPES_COMPATIBLE_P", "__builtin_types_compatible_p support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_types_compatible_p(char *, int) ? 1 : 0;" }, + { "HAVE_ICCARM_INTRINSICS", "", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "int func(int v) {\n" + " return __CLZ(__RBIT(v));\n" + "}" }, + { "HAVE_CLOCK_GETTIME", "clock_gettime() declaration", + "DEFINES_FUNC", "HAVE_STRUCT_TIMESPEC", NULL, + "#include \n" + "static struct timespec func(void) {\n" + " struct timespec ts;\n" + " clock_gettime(CLOCK_REALTIME, &ts);\n" + " return ts;\n" + "}\n" }, + { "HAVE_CLOCK_GETTIME_IN_LIBRT", "clock_gettime() in librt", + "DEFINES_FUNC", + "HAVE_STRUCT_TIMESPEC !HAVE_CLOCK_GETTIME", + "-lrt", + "#include \n" + "static struct timespec func(void) {\n" + " struct timespec ts;\n" + " clock_gettime(CLOCK_REALTIME, &ts);\n" + " return ts;\n" + "}\n", + "HAVE_CLOCK_GETTIME" }, + { "HAVE_COMPOUND_LITERALS", "compound literal support", + "INSIDE_MAIN", NULL, NULL, + "int *foo = (int[]) { 1, 2, 3, 4 };\n" + "return foo[0] ? 0 : 1;" }, + { "HAVE_FCHDIR", "fchdir support", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL, + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "int main(void) {\n" + " int fd = open(\"..\", O_RDONLY);\n" + " return fchdir(fd) == 0 ? 0 : 1;\n" + "}\n" }, + { "HAVE_ERR_H", "", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static void func(int arg) {\n" + " if (arg == 0)\n" + " err(1, \"err %u\", arg);\n" + " if (arg == 1)\n" + " errx(1, \"err %u\", arg);\n" + " if (arg == 3)\n" + " warn(\"warn %u\", arg);\n" + " if (arg == 4)\n" + " warnx(\"warn %u\", arg);\n" + "}\n" }, + { "HAVE_FILE_OFFSET_BITS", "_FILE_OFFSET_BITS to get 64-bit offsets", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", + "HAVE_32BIT_OFF_T", NULL, + "#define _FILE_OFFSET_BITS 64\n" + "#include \n" + "int main(void) {\n" + " return sizeof(off_t) == 8 ? 0 : 1;\n" + "}\n" }, + { "HAVE_FOR_LOOP_DECLARATION", "for loop declaration support", + "INSIDE_MAIN", NULL, NULL, + "int ret = 1;\n" + "for (int i = 0; i < argc; i++) { ret = 0; };\n" + "return ret;" }, + { "HAVE_FLEXIBLE_ARRAY_MEMBER", "flexible array member support", + "OUTSIDE_MAIN", NULL, NULL, + "struct foo { unsigned int x; int arr[]; };" }, + { "HAVE_GETPAGESIZE", "getpagesize() in ", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static int func(void) { return getpagesize(); }" }, + { "HAVE_ISBLANK", "isblank() in ", + "DEFINES_FUNC", NULL, NULL, + "#ifndef _GNU_SOURCE\n" + "#define _GNU_SOURCE\n" + "#endif\n" + "#include \n" + "static int func(void) { return isblank(' '); }" }, + { "HAVE_MEMMEM", "memmem in ", + "DEFINES_FUNC", NULL, NULL, + "#ifndef _GNU_SOURCE\n" + "#define _GNU_SOURCE\n" + "#endif\n" + "#include \n" + "static void *func(void *h, size_t hl, void *n, size_t nl) {\n" + "return memmem(h, hl, n, nl);" + "}\n", }, + { "HAVE_MEMRCHR", "memrchr in ", + "DEFINES_FUNC", NULL, NULL, + "#ifndef _GNU_SOURCE\n" + "#define _GNU_SOURCE\n" + "#endif\n" + "#include \n" + "static void *func(void *s, int c, size_t n) {\n" + "return memrchr(s, c, n);" + "}\n", }, + { "HAVE_MMAP", "mmap() declaration", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static void *func(int fd) {\n" + " return mmap(0, 65536, PROT_READ, MAP_SHARED, fd, 0);\n" + "}" }, + { "HAVE_PROC_SELF_MAPS", "/proc/self/maps exists", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL, + "#include \n" + "#include \n" + "#include \n" + "int main(void) {\n" + " return open(\"/proc/self/maps\", O_RDONLY) != -1 ? 0 : 1;\n" + "}\n" }, + { "HAVE_QSORT_R_PRIVATE_LAST", "qsort_r cmp takes trailing arg", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL, + "#ifndef _GNU_SOURCE\n" + "#define _GNU_SOURCE\n" + "#endif\n" + "#include \n" + "static int cmp(const void *lp, const void *rp, void *priv) {\n" + " *(unsigned int *)priv = 1;\n" + " return *(const int *)lp - *(const int *)rp; }\n" + "int main(void) {\n" + " int array[] = { 9, 2, 5 };\n" + " unsigned int called = 0;\n" + " qsort_r(array, 3, sizeof(int), cmp, &called);\n" + " return called && array[0] == 2 && array[1] == 5 && array[2] == 9 ? 0 : 1;\n" + "}\n" }, + { "HAVE_STRUCT_TIMESPEC", "struct timespec declaration", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static void func(void) {\n" + " struct timespec ts;\n" + " ts.tv_sec = ts.tv_nsec = 1;\n" + "}\n" }, + { "HAVE_SECTION_START_STOP", "__attribute__((section)) and __start/__stop", + "DEFINES_FUNC", NULL, NULL, + "static void *__attribute__((__section__(\"mysec\"))) p = &p;\n" + "static int func(void) {\n" + " extern void *__start_mysec[], *__stop_mysec[];\n" + " return __stop_mysec - __start_mysec;\n" + "}\n" }, + { "HAVE_STACK_GROWS_UPWARDS", "stack grows upwards", + "DEFINES_EVERYTHING|EXECUTE", NULL, NULL, + "#include \n" + "static ptrdiff_t nest(const void *base, unsigned int i)\n" + "{\n" + " if (i == 0)\n" + " return (const char *)&i - (const char *)base;\n" + " return nest(base, i-1);\n" + "}\n" + "int main(int argc, char *argv[]) {\n" + " (void)argv;\n" + " return (nest(&argc, argc) > 0) ? 0 : 1;\n" + "}\n" }, + { "HAVE_STATEMENT_EXPR", "statement expression support", + "INSIDE_MAIN", NULL, NULL, + "return ({ int x = argc; x == argc ? 0 : 1; });" }, + { "HAVE_SYS_FILIO_H", "", + "OUTSIDE_MAIN", NULL, NULL, + "#include \n" }, + { "HAVE_SYS_TERMIOS_H", "", + "OUTSIDE_MAIN", NULL, NULL, + "#include \n" }, + { "HAVE_SYS_UNISTD_H", "", + "OUTSIDE_MAIN", NULL, NULL, + "#include \n" }, + { "HAVE_UTIME", "utime() declaration", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "#include \n" + "static int func(const char *filename) {\n" + " struct utimbuf times = { 0 };\n" + " return utime(filename, ×);\n" + "}" }, + { "HAVE_WARN_UNUSED_RESULT", "__attribute__((warn_unused_result))", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "#include \n" + "static __attribute__((warn_unused_result)) int func(int i) {\n" + " return i + 1;\n" + "}" }, + { "HAVE_OPENMP", "#pragma omp and -fopenmp support", + "INSIDE_MAIN|EXECUTE|MAY_NOT_COMPILE", NULL, NULL, + "int i;\n" + "#pragma omp parallel for\n" + "for(i = 0; i < 0; i++) {};\n" + "return 0;\n", + "-Werror -fopenmp" }, + { "HAVE_VALGRIND_MEMCHECK_H", "", + "OUTSIDE_MAIN", NULL, NULL, + "#include \n" }, + { "HAVE_UCONTEXT", "working \n" + "static int x = 0;\n" + "static char stack[2048];\n" + "static ucontext_t a, b;\n" + "static void fn(void) {\n" + " x |= 2;\n" + " setcontext(&b);\n" + " x |= 4;\n" + "}\n" + "int main(void) {\n" + " x |= 1;\n" + " getcontext(&a);\n" + " a.uc_stack.ss_sp = stack;\n" + " a.uc_stack.ss_size = sizeof(stack);\n" + " makecontext(&a, fn, 0);\n" + " swapcontext(&b, &a);\n" + " return (x == 3) ? 0 : 1;\n" + "}\n" + }, + { "HAVE_POINTER_SAFE_MAKECONTEXT", "passing pointers via makecontext()", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", + "HAVE_UCONTEXT", NULL, + "#include \n" + "#include \n" + "static int worked = 0;\n" + "static char stack[1024];\n" + "static ucontext_t a, b;\n" + "static void fn(void *p, void *q) {\n" + " void *cp = &worked;\n" + " void *cq = (void *)(~((ptrdiff_t)cp));\n" + " if ((p == cp) && (q == cq))\n" + " worked = 1;\n" + " setcontext(&b);\n" + "}\n" + "int main(void) {\n" + " void *ap = &worked;\n" + " void *aq = (void *)(~((ptrdiff_t)ap));\n" + " getcontext(&a);\n" + " a.uc_stack.ss_sp = stack;\n" + " a.uc_stack.ss_size = sizeof(stack);\n" + " makecontext(&a, (void (*)(void))fn, 2, ap, aq);\n" + " swapcontext(&b, &a);\n" + " return worked ? 0 : 1;\n" + "}\n" + }, + { "HAVE_BUILTIN_CPU_SUPPORTS", "__builtin_cpu_supports()", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static bool func(void) {\n" + " return __builtin_cpu_supports(\"mmx\");\n" + "}" + }, + { "HAVE_CLOSEFROM", "closefrom() offered by system", + "DEFINES_EVERYTHING", NULL, NULL, + "#include \n" + "#include \n" + "int main(void) {\n" + " closefrom(STDERR_FILENO + 1);\n" + " return 0;\n" + "}\n" + }, + { "HAVE_F_CLOSEM", "F_CLOSEM defined for fctnl.", + "DEFINES_EVERYTHING", NULL, NULL, + "#include \n" + "#include \n" + "int main(void) {\n" + " int res = fcntl(STDERR_FILENO + 1, F_CLOSEM, 0);\n" + " return res < 0;\n" + "}\n" + }, + { "HAVE_NR_CLOSE_RANGE", "close_range syscall available as __NR_close_range.", + "DEFINES_EVERYTHING", NULL, NULL, + "#include \n" + "#include \n" + "#include \n" + "int main(void) {\n" + " int res = syscall(__NR_close_range, STDERR_FILENO + 1, INT_MAX, 0);\n" + " return res < 0;\n" + "}\n" + }, + { "HAVE_F_MAXFD", "F_MAXFD defined for fcntl.", + "DEFINES_EVERYTHING", NULL, NULL, + "#include \n" + "#include \n" + "int main(void) {\n" + " int res = fcntl(0, F_MAXFD);\n" + " return res < 0;\n" + "}\n" + }, + */ +}; + +static void c12r_err(int eval, const char *fmt, ...) +{ + int err_errno = errno; + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, ": %s\n", strerror(err_errno)); + exit(eval); +} + +static void c12r_errx(int eval, const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(eval); +} + +static void start_test(const char *what, const char *why) +{ + if (like_a_libtool) { + printf("%s%s... ", what, why); + fflush(stdout); + } +} + +static void end_test(bool result) +{ + if (like_a_libtool) + printf("%s\n", result ? "yes" : "no"); +} + +static size_t fcopy(FILE *fsrc, FILE *fdst) +{ + char buffer[BUFSIZ]; + size_t rsize, wsize; + size_t copied = 0; + + while ((rsize = fread(buffer, 1, BUFSIZ, fsrc)) > 0) { + wsize = fwrite(buffer, 1, rsize, fdst); + copied += wsize; + if (wsize != rsize) + break; + } + + return copied; +} + +static char *grab_stream(FILE *file) +{ + size_t max, ret, size = 0; + char *buffer; + + max = BUFSIZ; + buffer = malloc(max); + while ((ret = fread(buffer+size, 1, max - size, file)) == max - size) { + size += ret; + buffer = realloc(buffer, max *= 2); + } + size += ret; + if (ferror(file)) + c12r_err(EXIT_TROUBLE_RUNNING, "reading from command"); + buffer[size] = '\0'; + return buffer; +} + +static char *run(const char *cmd, int *exitstatus) +{ + static const char redir[] = " 2>&1"; + size_t cmdlen; + char *cmdredir; + FILE *cmdout; + char *ret; + + cmdlen = strlen(cmd); + cmdredir = malloc(cmdlen + sizeof(redir)); + memcpy(cmdredir, cmd, cmdlen); + memcpy(cmdredir + cmdlen, redir, sizeof(redir)); + + cmdout = popen(cmdredir, "r"); + if (!cmdout) + c12r_err(EXIT_TROUBLE_RUNNING, "popen \"%s\"", cmdredir); + + free(cmdredir); + + ret = grab_stream(cmdout); + *exitstatus = pclose(cmdout); + return ret; +} + +static char *connect_args(const char *argv[], const char *outflag, + const char *files) +{ + unsigned int i; + char *ret; + size_t len = strlen(outflag) + strlen(files) + 1; + + for (i = 1; argv[i]; i++) + len += 1 + strlen(argv[i]); + + ret = malloc(len); + len = 0; + for (i = 1; argv[i]; i++) { + strcpy(ret + len, argv[i]); + len += strlen(argv[i]); + if (argv[i+1] || *outflag) + ret[len++] = ' '; + } + strcpy(ret + len, outflag); + len += strlen(outflag); + strcpy(ret + len, files); + return ret; +} + +static struct test *find_test(const char *name) +{ + unsigned int i; + + for (i = 0; tests[i].name; i++) { + if (strcmp(tests[i].name, name) == 0) + return &tests[i]; + } + c12r_errx(EXIT_BAD_TEST, "Unknown test %s", name); + abort(); +} + +#define PRE_BOILERPLATE "/* Test program generated by configurator. */\n" +#define MAIN_START_BOILERPLATE \ + "int main(int argc, char *argv[]) {\n" \ + " (void)argc;\n" \ + " (void)argv;\n" +#define USE_FUNC_BOILERPLATE "(void)func;\n" +#define MAIN_BODY_BOILERPLATE "return 0;\n" +#define MAIN_END_BOILERPLATE "}\n" + +static bool run_test(const char *cmd, const char *wrapper, struct test *test) +{ + char *output, *newcmd; + FILE *outf; + int status; + + if (test->done) + return test->answer; + + if (test->depends) { + size_t len; + const char *deps = test->depends; + char *dep; + + /* Space-separated dependencies, could be ! for inverse. */ + while ((len = strcspn(deps, " ")) != 0) { + bool positive = true; + if (deps[len]) { + dep = strdup(deps); + dep[len] = '\0'; + } else { + dep = (char *)deps; + } + + if (dep[0] == '!') { + dep++; + positive = false; + } + if (run_test(cmd, wrapper, find_test(dep)) != positive) { + test->answer = false; + test->done = true; + return test->answer; + } + if (deps[len]) + free(dep); + + deps += len; + deps += strspn(deps, " "); + } + } + + outf = fopen(INPUT_FILE, verbose > 1 ? "w+" : "w"); + if (!outf) + c12r_err(EXIT_TROUBLE_RUNNING, "creating %s", INPUT_FILE); + + fprintf(outf, "%s", PRE_BOILERPLATE); + + if (strstr(test->style, "INSIDE_MAIN")) { + fprintf(outf, "%s", MAIN_START_BOILERPLATE); + fprintf(outf, "%s", test->fragment); + fprintf(outf, "%s", MAIN_END_BOILERPLATE); + } else if (strstr(test->style, "OUTSIDE_MAIN")) { + fprintf(outf, "%s", test->fragment); + fprintf(outf, "%s", MAIN_START_BOILERPLATE); + fprintf(outf, "%s", MAIN_BODY_BOILERPLATE); + fprintf(outf, "%s", MAIN_END_BOILERPLATE); + } else if (strstr(test->style, "DEFINES_FUNC")) { + fprintf(outf, "%s", test->fragment); + fprintf(outf, "%s", MAIN_START_BOILERPLATE); + fprintf(outf, "%s", USE_FUNC_BOILERPLATE); + fprintf(outf, "%s", MAIN_BODY_BOILERPLATE); + fprintf(outf, "%s", MAIN_END_BOILERPLATE); + } else if (strstr(test->style, "DEFINES_EVERYTHING")) { + fprintf(outf, "%s", test->fragment); + } else + c12r_errx(EXIT_BAD_TEST, "Unknown style for test %s: %s", + test->name, test->style); + + if (verbose > 1) { + fseek(outf, 0, SEEK_SET); + fcopy(outf, stdout); + } + + fclose(outf); + + newcmd = strdup(cmd); + + if (test->flags) { + newcmd = realloc(newcmd, strlen(newcmd) + strlen(" ") + + strlen(test->flags) + 1); + strcat(newcmd, " "); + strcat(newcmd, test->flags); + if (verbose > 1) + printf("Extra flags line: %s", newcmd); + } + + if (test->link) { + newcmd = realloc(newcmd, strlen(newcmd) + strlen(" ") + + strlen(test->link) + 1); + strcat(newcmd, " "); + strcat(newcmd, test->link); + if (verbose > 1) + printf("Extra link line: %s", newcmd); + } + + start_test("checking for ", test->desc); + output = run(newcmd, &status); + + free(newcmd); + + if (status != 0 || strstr(output, "warning")) { + if (verbose) + printf("Compile %s for %s, status %i: %s\n", + status ? "fail" : "warning", + test->name, status, output); + if (strstr(test->style, "EXECUTE") + && !strstr(test->style, "MAY_NOT_COMPILE")) + c12r_errx(EXIT_BAD_TEST, + "Test for %s did not compile:\n%s", + test->name, output); + test->answer = false; + free(output); + } else { + /* Compile succeeded. */ + free(output); + /* We run INSIDE_MAIN tests for sanity checking. */ + if (strstr(test->style, "EXECUTE") + || strstr(test->style, "INSIDE_MAIN")) { + char *cmd = malloc(strlen(wrapper) + strlen(" ." DIR_SEP OUTPUT_FILE) + 1); + + strcpy(cmd, wrapper); + strcat(cmd, " ." DIR_SEP OUTPUT_FILE); + output = run(cmd, &status); + free(cmd); + if (!strstr(test->style, "EXECUTE") && status != 0) + c12r_errx(EXIT_BAD_TEST, + "Test for %s failed with %i:\n%s", + test->name, status, output); + if (verbose && status) + printf("%s exited %i\n", test->name, status); + free(output); + } + test->answer = (status == 0); + } + test->done = true; + end_test(test->answer); + + if (test->answer && test->overrides) { + struct test *override = find_test(test->overrides); + override->done = true; + override->answer = true; + } + return test->answer; +} + +static char *any_field(char **fieldname) +{ + char buf[1000]; + for (;;) { + char *p, *eq; + + if (!fgets(buf, sizeof(buf), stdin)) + return NULL; + + p = buf; + /* Ignore whitespace, lines starting with # */ + while (*p == ' ' || *p == '\t') + p++; + if (*p == '#' || *p == '\n') + continue; + + eq = strchr(p, '='); + if (!eq) + c12r_errx(EXIT_BAD_INPUT, "no = in line: %s", p); + *eq = '\0'; + *fieldname = strdup(p); + p = eq + 1; + if (strlen(p) && p[strlen(p)-1] == '\n') + p[strlen(p)-1] = '\0'; + return strdup(p); + } +} + +static char *read_field(const char *name, bool compulsory) +{ + char *fieldname, *value; + + value = any_field(&fieldname); + if (!value) { + if (!compulsory) + return NULL; + c12r_errx(EXIT_BAD_INPUT, "Could not read field %s", name); + } + if (strcmp(fieldname, name) != 0) + c12r_errx(EXIT_BAD_INPUT, + "Expected field %s not %s", name, fieldname); + return value; +} + +/* Test descriptions from stdin: + * Lines starting with # or whitespace-only are ignored. + * + * First three non-ignored lines must be: + * var= + * desc= + * style=OUTSIDE_MAIN DEFINES_FUNC INSIDE_MAIN DEFINES_EVERYTHING EXECUTE MAY_NOT_COMPILE + * + * Followed by optional lines: + * depends= + * link= + * flags= + * overrides= + * + * Finally a code line, either: + * code= OR + * code= + * + * + * + * And looks like this next comment: */ +/*END*/ +static bool read_test(struct test *test) +{ + char *field, *value; + char buf[1000]; + + memset(test, 0, sizeof(*test)); + test->name = read_field("var", false); + if (!test->name) + return false; + test->desc = read_field("desc", true); + test->style = read_field("style", true); + /* Read any optional fields. */ + while ((value = any_field(&field)) != NULL) { + if (strcmp(field, "depends") == 0) + test->depends = value; + else if (strcmp(field, "link") == 0) + test->link = value; + else if (strcmp(field, "flags") == 0) + test->flags = value; + else if (strcmp(field, "overrides") == 0) + test->overrides = value; + else if (strcmp(field, "code") == 0) + break; + else + c12r_errx(EXIT_BAD_INPUT, "Unknown field %s in %s", + field, test->name); + } + if (!value) + c12r_errx(EXIT_BAD_INPUT, "Missing code in %s", test->name); + + if (strlen(value) == 0) { + /* Multiline program, read to END comment */ + while (fgets(buf, sizeof(buf), stdin) != 0) { + size_t n; + if (strncmp(buf, "/*END*/", 7) == 0) + break; + n = strlen(value); + value = realloc(value, n + strlen(buf) + 1); + strcpy(value + n, buf); + n += strlen(buf); + } + } + test->fragment = value; + return true; +} + +static void read_tests(size_t num_tests) +{ + while (read_test(tests + num_tests)) { + num_tests++; + tests = realloc(tests, (num_tests + 1) * sizeof(tests[0])); + tests[num_tests].name = NULL; + } +} + +int main(int argc, const char *argv[]) +{ + char *cmd; + unsigned int i; + const char *default_args[] + = { "", DEFAULT_COMPILER, DEFAULT_FLAGS, NULL }; + const char *outflag = DEFAULT_OUTPUT_EXE_FLAG; + const char *configurator_cc = NULL; + const char *wrapper = ""; + const char *orig_cc; + const char *varfile = NULL; + const char *headerfile = NULL; + bool extra_tests = false; + FILE *outf; + + if (argc > 0) + progname = argv[0]; + + while (argc > 1) { + if (strcmp(argv[1], "--help") == 0) { + printf("Usage: configurator [-v] [--var-file=] [-O] [--configurator-cc=] [--wrapper=] [--autotools-style] [--extra-tests] [ ...]\n" + " will have \" \" appended\n" + "Default: %s %s %s\n", + DEFAULT_COMPILER, DEFAULT_FLAGS, + DEFAULT_OUTPUT_EXE_FLAG); + exit(0); + } + if (strncmp(argv[1], "-O", 2) == 0) { + argc--; + argv++; + outflag = argv[1] + 2; + if (!*outflag) { + fprintf(stderr, + "%s: option requires an argument -- O\n", + argv[0]); + exit(EXIT_BAD_USAGE); + } + } else if (strcmp(argv[1], "-v") == 0) { + argc--; + argv++; + verbose++; + } else if (strcmp(argv[1], "-vv") == 0) { + argc--; + argv++; + verbose += 2; + } else if (strncmp(argv[1], "--configurator-cc=", 18) == 0) { + configurator_cc = argv[1] + 18; + argc--; + argv++; + } else if (strncmp(argv[1], "--wrapper=", 10) == 0) { + wrapper = argv[1] + 10; + argc--; + argv++; + } else if (strncmp(argv[1], "--var-file=", 11) == 0) { + varfile = argv[1] + 11; + argc--; + argv++; + } else if (strcmp(argv[1], "--autotools-style") == 0) { + like_a_libtool = true; + argc--; + argv++; + } else if (strncmp(argv[1], "--header-file=", 14) == 0) { + headerfile = argv[1] + 14; + argc--; + argv++; + } else if (strcmp(argv[1], "--extra-tests") == 0) { + extra_tests = true; + argc--; + argv++; + } else if (strcmp(argv[1], "--") == 0) { + break; + } else if (argv[1][0] == '-') { + c12r_errx(EXIT_BAD_USAGE, "Unknown option %s", argv[1]); + } else { + break; + } + } + + if (argc == 1) + argv = default_args; + + /* Copy with NULL entry at end */ + tests = calloc(sizeof(base_tests)/sizeof(base_tests[0]) + 1, + sizeof(base_tests[0])); + memcpy(tests, base_tests, sizeof(base_tests)); + + if (extra_tests) + read_tests(sizeof(base_tests)/sizeof(base_tests[0])); + + orig_cc = argv[1]; + if (configurator_cc) + argv[1] = configurator_cc; + + cmd = connect_args(argv, outflag, OUTPUT_FILE " " INPUT_FILE); + if (like_a_libtool) { + start_test("Making autoconf users comfortable", ""); + sleep(1); + end_test(1); + } + for (i = 0; tests[i].name; i++) + run_test(cmd, wrapper, &tests[i]); + free(cmd); + + remove(OUTPUT_FILE); + remove(INPUT_FILE); + + if (varfile) { + FILE *vars; + + if (strcmp(varfile, "-") == 0) + vars = stdout; + else { + start_test("Writing variables to ", varfile); + vars = fopen(varfile, "a"); + if (!vars) + c12r_err(EXIT_TROUBLE_RUNNING, + "Could not open %s", varfile); + } + for (i = 0; tests[i].name; i++) + fprintf(vars, "%s=%u\n", tests[i].name, tests[i].answer); + if (vars != stdout) { + if (fclose(vars) != 0) + c12r_err(EXIT_TROUBLE_RUNNING, + "Closing %s", varfile); + end_test(1); + } + } + + if (headerfile) { + start_test("Writing header to ", headerfile); + outf = fopen(headerfile, "w"); + if (!outf) + c12r_err(EXIT_TROUBLE_RUNNING, + "Could not open %s", headerfile); + } else + outf = stdout; + + fprintf(outf, "/* Generated by CCAN configurator */\n" + "#ifndef CCAN_CONFIG_H\n" + "#define CCAN_CONFIG_H\n"); + fprintf(outf, "#ifndef _GNU_SOURCE\n"); + fprintf(outf, "#define _GNU_SOURCE /* Always use GNU extensions. */\n"); + fprintf(outf, "#endif\n"); + fprintf(outf, "#define CCAN_COMPILER \"%s\"\n", orig_cc); + cmd = connect_args(argv + 1, "", ""); + fprintf(outf, "#define CCAN_CFLAGS \"%s\"\n", cmd); + free(cmd); + fprintf(outf, "#define CCAN_OUTPUT_EXE_CFLAG \"%s\"\n\n", outflag); + /* This one implies "#include +#include + +void le64_nonce(unsigned char *npub, u64 nonce) +{ + /* BOLT #8: + * + * ...with nonce `n` encoded as 32 zero bits, followed by a + * *little-endian* 64-bit value. Note: this follows the Noise Protocol + * convention, rather than our normal endian + */ + le64 le_nonce = cpu_to_le64(nonce); + const size_t zerolen = crypto_aead_chacha20poly1305_ietf_NPUBBYTES - sizeof(le_nonce); + + BUILD_ASSERT(crypto_aead_chacha20poly1305_ietf_NPUBBYTES >= sizeof(le_nonce)); + /* First part is 0, followed by nonce. */ + memset(npub, 0, zerolen); + memcpy(npub + zerolen, &le_nonce, sizeof(le_nonce)); +} + +/* out1, out2 = HKDF(in1, in2)` */ +void hkdf_two_keys(struct secret *out1, struct secret *out2, + const struct secret *in1, + const struct secret *in2) +{ + /* BOLT #8: + * + * * `HKDF(salt,ikm)`: a function defined in `RFC 5869`[3](#reference-3), + * evaluated with a zero-length `info` field + * * All invocations of `HKDF` implicitly return 64 bytes + * of cryptographic randomness using the extract-and-expand + * component of the `HKDF`. + */ + struct secret okm[2]; + size_t in2_size = in2 == NULL ? 0 : sizeof(*in2); + + hkdf_sha256(okm, sizeof(okm), in1, sizeof(*in1), in2, in2_size, + NULL, 0); + *out1 = okm[0]; + *out2 = okm[1]; +} + + +static void maybe_rotate_key(u64 *n, struct secret *k, struct secret *ck) +{ + struct secret new_k, new_ck; + + /* BOLT #8: + * + * A key is to be rotated after a party encrypts or decrypts 1000 times + * with it (i.e. every 500 messages). This can be properly accounted + * for by rotating the key once the nonce dedicated to it + * exceeds 1000. + */ + if (*n != 1000) + return; + + /* BOLT #8: + * + * Key rotation for a key `k` is performed according to the following + * steps: + * + * 1. Let `ck` be the chaining key obtained at the end of Act Three. + * 2. `ck', k' = HKDF(ck, k)` + * 3. Reset the nonce for the key to `n = 0`. + * 4. `k = k'` + * 5. `ck = ck'` + */ + hkdf_two_keys(&new_ck, &new_k, ck, k); + + *ck = new_ck; + *k = new_k; + *n = 0; +} + +int cryptomsg_decrypt_body(struct crypto_state *cs, const u8 *in, size_t inlen, u8 *out, size_t outcap) +{ + unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; + unsigned long long mlen; + + if (inlen < 16 || outcap < cryptomsg_decrypt_size(inlen)) + return 0; + + le64_nonce(npub, cs->rn++); + + /* BOLT #8: + * + * 5. Decrypt `c` (using `ChaCha20-Poly1305`, `rn`, and `rk`), to + * obtain decrypted plaintext packet `p`. + * * The nonce `rn` MUST be incremented after this step. + */ + if (crypto_aead_chacha20poly1305_ietf_decrypt(out, + &mlen, NULL, + memcheck(in, inlen), + inlen, + NULL, 0, + npub, cs->rk.data) != 0) { + /* FIXME: Report error! */ + return 0; + } + + assert(mlen == cryptomsg_decrypt_size(inlen)); + + maybe_rotate_key(&cs->rn, &cs->rk, &cs->r_ck); + + return 1; +} + +int cryptomsg_decrypt_header(struct crypto_state *cs, u8 hdr[18], u16 *lenp) +{ + unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; + unsigned long long mlen; + be16 len; + + le64_nonce(npub, cs->rn++); + + /* BOLT #8: + * + * 2. Let the encrypted length prefix be known as `lc`. + * 3. Decrypt `lc` (using `ChaCha20-Poly1305`, `rn`, and `rk`), to + * obtain the size of the encrypted packet `l`. + * * A zero-length byte slice is to be passed as the AD + * (associated data). + * * The nonce `rn` MUST be incremented after this step. + */ + if (crypto_aead_chacha20poly1305_ietf_decrypt((unsigned char *)&len, + &mlen, NULL, + memcheck(hdr, 18), 18, + NULL, 0, + npub, cs->rk.data) != 0) { + return 0; + } + assert(mlen == sizeof(len)); + *lenp = be16_to_cpu(len); + return 1; +} + +u8 *cryptomsg_encrypt_msg(struct crypto_state *cs, const u8 *msg, unsigned long long mlen, u8 *out, size_t *outlen, size_t outcap) +{ + unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; + unsigned long long clen; + be16 l; + int ret; + + *outlen = sizeof(l) + 16 + mlen + 16; + + if (outcap < mlen) { + *outlen = 0; + return NULL; + } + + /* BOLT #8: + * + * In order to encrypt and send a Lightning message (`m`) to the + * network stream, given a sending key (`sk`) and a nonce (`sn`), the + * following steps are completed: + * + * 1. Let `l = len(m)`. + * * where `len` obtains the length in bytes of the Lightning + * message + * + * 2. Serialize `l` into 2 bytes encoded as a big-endian integer. + */ + l = cpu_to_be16(mlen); + + /* BOLT #8: + * + * 3. Encrypt `l` (using `ChaChaPoly-1305`, `sn`, and `sk`), to obtain + * `lc` (18 bytes) + * * The nonce `sn` is encoded as a 96-bit little-endian number. As + * the decoded nonce is 64 bits, the 96-bit nonce is encoded as: + * 32 bits of leading 0s followed by a 64-bit value. + * * The nonce `sn` MUST be incremented after this step. + * * A zero-length byte slice is to be passed as the AD (associated + data). + */ + le64_nonce(npub, cs->sn++); + ret = crypto_aead_chacha20poly1305_ietf_encrypt(out, &clen, + (unsigned char *) + memcheck(&l, sizeof(l)), + sizeof(l), + NULL, 0, + NULL, npub, + cs->sk.data); + assert(ret == 0); + assert(clen == sizeof(l) + 16); + + /* BOLT #8: + * + * 4. Finally, encrypt the message itself (`m`) using the same + * procedure used to encrypt the length prefix. Let + * encrypted ciphertext be known as `c`. + * + * * The nonce `sn` MUST be incremented after this step. + */ + le64_nonce(npub, cs->sn++); + ret = crypto_aead_chacha20poly1305_ietf_encrypt(out + clen, &clen, + memcheck(msg, mlen), + mlen, + NULL, 0, + NULL, npub, + cs->sk.data); + assert(ret == 0); + assert(clen == mlen + 16); + + maybe_rotate_key(&cs->sn, &cs->sk, &cs->s_ck); + + return out; +} diff --git a/node_modules/lnsocket/crypto.h b/node_modules/lnsocket/crypto.h new file mode 100644 index 0000000..5a6e7d3 --- /dev/null +++ b/node_modules/lnsocket/crypto.h @@ -0,0 +1,55 @@ + +#ifndef LNSOCKET_CRYPTO_H +#define LNSOCKET_CRYPTO_H + +#include +#include "typedefs.h" + +#define PUBKEY_CMPR_LEN 33 + +struct secret { + u8 data[32]; +}; + +struct node_id { + u8 k[PUBKEY_CMPR_LEN]; +}; + +struct pubkey { + secp256k1_pubkey pubkey; +}; + +struct privkey { + struct secret secret; +}; + +struct keypair { + struct pubkey pub; + struct privkey priv; +}; + +struct crypto_state { + /* Received and sent nonces. */ + u64 rn, sn; + /* Sending and receiving keys. */ + struct secret sk, rk; + /* Chaining key for re-keying */ + struct secret s_ck, r_ck; +}; + +void le64_nonce(unsigned char *npub, u64 nonce); + +void hkdf_two_keys(struct secret *out1, struct secret *out2, + const struct secret *in1, + const struct secret *in2); + +int cryptomsg_decrypt_body(struct crypto_state *cs, const u8 *in, size_t inlen, u8 *out, size_t outcap); +int cryptomsg_decrypt_header(struct crypto_state *cs, u8 hdr[18], u16 *lenp); +unsigned char *cryptomsg_encrypt_msg(struct crypto_state *cs, const u8 *msg, unsigned long long mlen, u8 *out, size_t *outlen, size_t outcap); + +static inline int cryptomsg_decrypt_size(size_t inlen) +{ + return inlen - 16; +} + +#endif /* LNSOCKET_CRYPTO_H */ diff --git a/node_modules/lnsocket/cursor.h b/node_modules/lnsocket/cursor.h new file mode 100644 index 0000000..eb15a99 --- /dev/null +++ b/node_modules/lnsocket/cursor.h @@ -0,0 +1,393 @@ + + +#ifndef LNSOCKET_CURSOR_H +#define LNSOCKET_CURSOR_H + +#include "typedefs.h" +#include "varint.h" + +#include +#include +#include + +#define unlikely(x) __builtin_expect((x),0) +#define likely(x) __builtin_expect((x),1) + +struct cursor { + unsigned char *start; + unsigned char *p; + unsigned char *end; +}; + +struct array { + struct cursor cur; + unsigned int elem_size; +}; + +static inline void reset_cursor(struct cursor *cursor) +{ + cursor->p = cursor->start; +} + +static inline void wipe_cursor(struct cursor *cursor) +{ + reset_cursor(cursor); + memset(cursor->start, 0, cursor->end - cursor->start); +} + +static inline void make_cursor(u8 *start, u8 *end, struct cursor *cursor) +{ + cursor->start = start; + cursor->p = start; + cursor->end = end; +} + +static inline void make_array(struct array *a, u8* start, u8 *end, unsigned int elem_size) +{ + make_cursor(start, end, &a->cur); + a->elem_size = elem_size; +} + +static inline int cursor_eof(struct cursor *c) +{ + return c->p == c->end; +} + +static inline void *cursor_malloc(struct cursor *mem, unsigned long size) +{ + void *ret; + + if (mem->p + size > mem->end) { + return NULL; + } + + ret = mem->p; + mem->p += size; + + return ret; +} + +static inline void *cursor_alloc(struct cursor *mem, unsigned long size) +{ + void *ret; + if (!(ret = cursor_malloc(mem, size))) { + return 0; + } + + memset(ret, 0, size); + return ret; +} + +static inline int cursor_slice(struct cursor *mem, struct cursor *slice, size_t size) +{ + u8 *p; + if (!(p = cursor_alloc(mem, size))) { + return 0; + } + make_cursor(p, mem->p, slice); + return 1; +} + + +static inline void copy_cursor(struct cursor *src, struct cursor *dest) +{ + dest->start = src->start; + dest->p = src->p; + dest->end = src->end; +} + +static inline int pull_byte(struct cursor *cursor, u8 *c) +{ + if (unlikely(cursor->p + 1 > cursor->end)) + return 0; + + *c = *cursor->p; + cursor->p++; + + return 1; +} + +static inline int cursor_pull_c_str(struct cursor *cursor, const char **str) +{ + *str = (const char*)cursor->p; + + for (; cursor->p < cursor->end; cursor->p++) { + if (*cursor->p == 0) { + cursor->p++; + return 1; + } + } + + return 0; +} + + +static inline int cursor_push_byte(struct cursor *cursor, u8 c) +{ + if (unlikely(cursor->p + 1 > cursor->end)) { + return 0; + } + + *cursor->p = c; + cursor->p++; + + return 1; +} + +static inline int cursor_pull(struct cursor *cursor, u8 *data, int len) +{ + if (unlikely(cursor->p + len > cursor->end)) { + return 0; + } + + memcpy(data, cursor->p, len); + cursor->p += len; + + return 1; +} + +static inline int pull_data_into_cursor(struct cursor *cursor, + struct cursor *dest, + unsigned char **data, + int len) +{ + int ok; + + if (unlikely(dest->p + len > dest->end)) { + printf("not enough room in dest buffer\n"); + return 0; + } + + ok = cursor_pull(cursor, dest->p, len); + if (!ok) return 0; + + *data = dest->p; + dest->p += len; + + return 1; +} + +static inline int cursor_dropn(struct cursor *cur, int size, int n) +{ + if (n == 0) + return 1; + + if (unlikely(cur->p - size*n < cur->start)) { + return 0; + } + + cur->p -= size*n; + return 1; +} + +static inline int cursor_drop(struct cursor *cur, int size) +{ + return cursor_dropn(cur, size, 1); +} + +static inline unsigned char *cursor_topn(struct cursor *cur, int len, int n) +{ + n += 1; + if (unlikely(cur->p - len*n < cur->start)) { + return NULL; + } + return cur->p - len*n; +} + +static inline unsigned char *cursor_top(struct cursor *cur, int len) +{ + if (unlikely(cur->p - len < cur->start)) { + return NULL; + } + return cur->p - len; +} + +static inline int cursor_top_int(struct cursor *cur, int *i) +{ + u8 *p; + if (unlikely(!(p = cursor_top(cur, sizeof(*i))))) { + return 0; + } + *i = *((int*)p); + return 1; +} + +static inline int cursor_pop(struct cursor *cur, u8 *data, int len) +{ + if (unlikely(cur->p - len < cur->start)) { + return 0; + } + + cur->p -= len; + memcpy(data, cur->p, len); + + return 1; +} + +static inline int cursor_push(struct cursor *cursor, const void *data, int len) +{ + if (unlikely(cursor->p + len >= cursor->end)) { + return 0; + } + + if (cursor->p != data) + memcpy(cursor->p, data, len); + + cursor->p += len; + + return 1; +} + +static inline int cursor_push_int(struct cursor *cursor, int i) +{ + return cursor_push(cursor, (u8*)&i, sizeof(i)); +} + +static inline size_t cursor_count(struct cursor *cursor, size_t elem_size) +{ + return (cursor->p - cursor->start)/elem_size; +} + +/* TODO: push_varint */ +static inline int push_varint(struct cursor *cursor, int n) +{ + int ok, len; + unsigned char b; + len = 0; + + while (1) { + b = (n & 0xFF) | 0x80; + n >>= 7; + if (n == 0) { + b &= 0x7F; + ok = cursor_push_byte(cursor, b); + len++; + if (!ok) return 0; + break; + } + + ok = cursor_push_byte(cursor, b); + len++; + if (!ok) return 0; + } + + return len; +} + +/* TODO: pull_varint */ +static inline int pull_varint(struct cursor *cursor, int *n) +{ + int ok, i; + unsigned char b; + *n = 0; + + for (i = 0;; i++) { + ok = pull_byte(cursor, &b); + if (!ok) return 0; + + *n |= ((int)b & 0x7F) << (i * 7); + + /* is_last */ + if ((b & 0x80) == 0) { + return i+1; + } + + if (i == 4) return 0; + } + + return 0; +} + +static inline int cursor_pull_int(struct cursor *cursor, int *i) +{ + return cursor_pull(cursor, (u8*)i, sizeof(*i)); +} + +static inline void *index_cursor(struct cursor *cursor, unsigned int index, int elem_size) +{ + u8 *p; + p = &cursor->start[elem_size * index]; + + if (unlikely(p >= cursor->end)) + return NULL; + + return (void*)p; +} + + +static inline int push_sized_str(struct cursor *cursor, const char *str, int len) +{ + return cursor_push(cursor, (u8*)str, len); +} + +static inline int cursor_push_str(struct cursor *cursor, const char *str) +{ + return cursor_push(cursor, (u8*)str, strlen(str)); +} + +static inline int cursor_push_c_str(struct cursor *cursor, const char *str) +{ + return cursor_push_str(cursor, str) && cursor_push_byte(cursor, 0); +} + +/* TODO: push varint size */ +static inline int push_prefixed_str(struct cursor *cursor, const char *str) +{ + int ok, len; + len = strlen(str); + ok = push_varint(cursor, len); + if (!ok) return 0; + return push_sized_str(cursor, str, len); +} + +static inline int pull_prefixed_str(struct cursor *cursor, struct cursor *dest_buf, const char **str) +{ + int len, ok; + + ok = pull_varint(cursor, &len); + if (!ok) return 0; + + if (unlikely(dest_buf->p + len > dest_buf->end)) { + return 0; + } + + ok = pull_data_into_cursor(cursor, dest_buf, (unsigned char**)str, len); + if (!ok) return 0; + + ok = cursor_push_byte(dest_buf, 0); + + return 1; +} + +static inline int cursor_remaining_capacity(struct cursor *cursor) +{ + return cursor->end - cursor->p; +} + + +#define max(a,b) ((a) > (b) ? (a) : (b)) +static inline void cursor_print_around(struct cursor *cur, int range) +{ + unsigned char *c; + + printf("[%ld/%ld]\n", cur->p - cur->start, cur->end - cur->start); + + c = max(cur->p - range, cur->start); + for (; c < cur->end && c < (cur->p + range); c++) { + printf("%02x", *c); + } + printf("\n"); + + c = max(cur->p - range, cur->start); + for (; c < cur->end && c < (cur->p + range); c++) { + if (c == cur->p) { + printf("^"); + continue; + } + printf(" "); + } + printf("\n"); +} +#undef max + +#endif diff --git a/node_modules/lnsocket/dist/node/lnsocket.js b/node_modules/lnsocket/dist/node/lnsocket.js new file mode 100644 index 0000000..11e88a4 --- /dev/null +++ b/node_modules/lnsocket/dist/node/lnsocket.js @@ -0,0 +1,391 @@ + +var Module = (() => { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( +function(Module) { + Module = Module || {}; + +var Module=typeof Module!="undefined"?Module:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});Module.getRandomValue=function(){const window_="object"===typeof window?window:this;const crypto_=typeof window_.crypto!=="undefined"?window_.crypto:window_.msCrypto;let randomBytesNode;if(!crypto_){randomBytesNode=require("crypto").randomBytes;fn=randomValuesNode}else{fn=randomValuesStandard}function randomValuesNode(){return randomBytesNode(1)[0]>>>0}function randomValuesStandard(){var buf=new Uint32Array(1);crypto_.getRandomValues(buf);return buf[0]>>>0}return fn}();var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;function logExceptionOnExit(e){if(e instanceof ExitStatus)return;let toLog=e;err("exiting due to exception: "+toLog)}var fs;var nodePath;var requireNodeFS;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}requireNodeFS=(()=>{if(!nodePath){fs=require("fs");nodePath=require("path")}});read_=function shell_read(filename,binary){requireNodeFS();filename=nodePath["normalize"](filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=(filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret});readAsync=((filename,onload,onerror)=>{requireNodeFS();filename=nodePath["normalize"](filename);fs.readFile(filename,function(err,data){if(err)onerror(err);else onload(data.buffer)})});if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",function(reason){throw reason});quit_=((status,toThrow)=>{if(keepRuntimeAlive()){process["exitCode"]=status;throw toThrow}logExceptionOnExit(toThrow);process["exit"](status)});Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=(url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText});if(ENVIRONMENT_IS_WORKER){readBinary=(url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)})}readAsync=((url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=(()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()});xhr.onerror=onerror;xhr.send(null)})}setWindowTitle=(title=>document.title=title)}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function getCFunc(ident){var func=Module["_"+ident];return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeKeepaliveCounter=0;function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounter>0}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){{if(Module["onAbort"]){Module["onAbort"](what)}}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith("file://")}var wasmBinaryFile;wasmBinaryFile="lnsocket.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary(wasmBinaryFile)})}else{if(readAsync){return new Promise(function(resolve,reject){readAsync(wasmBinaryFile,function(response){resolve(new Uint8Array(response))},reject)})}}}return Promise.resolve().then(function(){return getBinary(wasmBinaryFile)})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["i"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["m"];addOnInit(Module["asm"]["j"]);removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(function(instance){return instance}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch=="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiationResult,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiationResult)})})}else{return instantiateArrayBuffer(receiveInstantiationResult)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync().catch(readyPromiseReject);return{}}var ASM_CONSTS={70252:function(){return Module.getRandomValue()},70288:function(){if(Module.getRandomValue===undefined){try{var window_="object"===typeof window?window:self;var crypto_=typeof window_.crypto!=="undefined"?window_.crypto:window_.msCrypto;var randomValuesStandard=function(){var buf=new Uint32Array(1);crypto_.getRandomValues(buf);return buf[0]>>>0};randomValuesStandard();Module.getRandomValue=randomValuesStandard}catch(e){try{var crypto=require("crypto");var randomValueNodeJS=function(){var buf=crypto["randomBytes"](4);return(buf[0]<<24|buf[1]<<16|buf[2]<<8|buf[3])>>>0};randomValueNodeJS();Module.getRandomValue=randomValueNodeJS}catch(e){throw"No secure random number generator found"}}}}};function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func=="number"){if(callback.arg===undefined){getWasmTableEntry(func)()}else{getWasmTableEntry(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}function getWasmTableEntry(funcPtr){return wasmTable.get(funcPtr)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function _abort(){abort("")}var readAsmConstArgsArray=[];function readAsmConstArgs(sigPtr,buf){readAsmConstArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){var readAsmConstArgsDouble=ch<105;if(readAsmConstArgsDouble&&buf&1)buf++;readAsmConstArgsArray.push(readAsmConstArgsDouble?HEAPF64[buf++>>1]:HEAP32[buf]);++buf}return readAsmConstArgsArray}function _emscripten_asm_const_int(code,sigPtr,argbuf){var args=readAsmConstArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;abortOnCannotGrowMemory(requestedSize)}var SYSCALLS={buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0}var asmLibraryArg={"a":___assert_fail,"b":_abort,"h":_emscripten_asm_const_int,"g":_emscripten_memcpy_big,"c":_emscripten_resize_heap,"f":_fd_close,"d":_fd_seek,"e":_fd_write};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["j"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["k"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["l"]).apply(null,arguments)};var _lnsocket_make_default_initmsg=Module["_lnsocket_make_default_initmsg"]=function(){return(_lnsocket_make_default_initmsg=Module["_lnsocket_make_default_initmsg"]=Module["asm"]["n"]).apply(null,arguments)};var _lnsocket_encrypt=Module["_lnsocket_encrypt"]=function(){return(_lnsocket_encrypt=Module["_lnsocket_encrypt"]=Module["asm"]["o"]).apply(null,arguments)};var _lnsocket_decrypt=Module["_lnsocket_decrypt"]=function(){return(_lnsocket_decrypt=Module["_lnsocket_decrypt"]=Module["asm"]["p"]).apply(null,arguments)};var _lnsocket_decrypt_header=Module["_lnsocket_decrypt_header"]=function(){return(_lnsocket_decrypt_header=Module["_lnsocket_decrypt_header"]=Module["asm"]["q"]).apply(null,arguments)};var _lnsocket_make_ping_msg=Module["_lnsocket_make_ping_msg"]=function(){return(_lnsocket_make_ping_msg=Module["_lnsocket_make_ping_msg"]=Module["asm"]["r"]).apply(null,arguments)};var _lnsocket_msgbuf=Module["_lnsocket_msgbuf"]=function(){return(_lnsocket_msgbuf=Module["_lnsocket_msgbuf"]=Module["asm"]["s"]).apply(null,arguments)};var _lnsocket_create=Module["_lnsocket_create"]=function(){return(_lnsocket_create=Module["_lnsocket_create"]=Module["asm"]["t"]).apply(null,arguments)};var _lnsocket_destroy=Module["_lnsocket_destroy"]=function(){return(_lnsocket_destroy=Module["_lnsocket_destroy"]=Module["asm"]["u"]).apply(null,arguments)};var _lnsocket_secp=Module["_lnsocket_secp"]=function(){return(_lnsocket_secp=Module["_lnsocket_secp"]=Module["asm"]["v"]).apply(null,arguments)};var _lnsocket_genkey=Module["_lnsocket_genkey"]=function(){return(_lnsocket_genkey=Module["_lnsocket_genkey"]=Module["asm"]["w"]).apply(null,arguments)};var _lnsocket_print_errors=Module["_lnsocket_print_errors"]=function(){return(_lnsocket_print_errors=Module["_lnsocket_print_errors"]=Module["asm"]["x"]).apply(null,arguments)};var _lnsocket_act_two=Module["_lnsocket_act_two"]=function(){return(_lnsocket_act_two=Module["_lnsocket_act_two"]=Module["asm"]["y"]).apply(null,arguments)};var _commando_make_rpc_msg=Module["_commando_make_rpc_msg"]=function(){return(_commando_make_rpc_msg=Module["_commando_make_rpc_msg"]=Module["asm"]["z"]).apply(null,arguments)};var _lnsocket_act_one=Module["_lnsocket_act_one"]=function(){return(_lnsocket_act_one=Module["_lnsocket_act_one"]=Module["asm"]["A"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return(stackSave=Module["stackSave"]=Module["asm"]["B"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return(stackRestore=Module["stackRestore"]=Module["asm"]["C"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return(stackAlloc=Module["stackAlloc"]=Module["asm"]["D"]).apply(null,arguments)};Module["ccall"]=ccall;Module["cwrap"]=cwrap;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run(); + + + return Module.ready +} +); +})(); +if (typeof exports === 'object' && typeof module === 'object') + module.exports = Module; +else if (typeof define === 'function' && define['amd']) + define([], function() { return Module; }); +else if (typeof exports === 'object') + exports["Module"] = Module; + +async function lnsocket_init() { + const module = await Module() + + function SocketImpl(host) { + if (!(this instanceof SocketImpl)) + return new SocketImpl(host) + + if (typeof WebSocket !== 'undefined') { + console.log("WebSocket", typeof WebSocket) + const ok = host.startsWith("ws://") || host.startsWith("wss://") + if (!ok) + throw new Error("host must start with ws:// or wss://") + const ws = new WebSocket(host) + ws.ondata = function(fn) { + ws.onmessage = (v) => { + const data = v.data.arrayBuffer() + fn(data) + } + } + return ws + } + + // + // we're in nodejs + // + const net = require('net') + let [hostname,port] = host.split(":") + port = +port || 9735 + const socket = net.createConnection(port, hostname, () => { + socket.emit("open") + }) + socket.addEventListener = socket.on.bind(socket) + + if (socket.onmessage) + throw new Error("socket already has onmessage?") + + socket.ondata = (fn) => { + socket.on('data', fn) + } + + socket.close = () => { + socket.destroy() + } + + if (socket.send) + throw new Error("socket already has send?") + + socket.send = function socket_send(data) { + return new Promise((resolve, reject) => { + socket.write(data, resolve) + }); + } + + return socket + } + + const ACT_ONE_SIZE = 50 + const ACT_TWO_SIZE = 50 + const ACT_THREE_SIZE = 66 + const DEFAULT_TIMEOUT = 15000 + + const COMMANDO_REPLY_CONTINUES = 0x594b + const COMMANDO_REPLY_TERM = 0x594d + + const lnsocket_create = module.cwrap("lnsocket_create", "number") + const lnsocket_destroy = module.cwrap("lnsocket_destroy", "number") + const lnsocket_encrypt = module.cwrap("lnsocket_encrypt", "number", ["int", "array", "int", "int"]) + const lnsocket_decrypt = module.cwrap("lnsocket_decrypt", "number", ["int", "array", "int"]) + const lnsocket_decrypt_header = module.cwrap("lnsocket_decrypt_header", "number", ["number", "array"]) + const lnsocket_msgbuf = module.cwrap("lnsocket_msgbuf", "number", ["int"]) + const lnsocket_act_one = module.cwrap("lnsocket_act_one", "number", ["number", "string"]) + const lnsocket_act_two = module.cwrap("lnsocket_act_two", "number", ["number", "array"]) + const lnsocket_print_errors = module.cwrap("lnsocket_print_errors", "int") + const lnsocket_genkey = module.cwrap("lnsocket_genkey", "int") + const lnsocket_make_default_initmsg = module.cwrap("lnsocket_make_default_initmsg", "int", ["int", "int"]) + const lnsocket_make_ping_msg = module.cwrap("lnsocket_make_ping_msg", "int", ["int", "int", "int", "int"]) + const commando_make_rpc_msg = module.cwrap("commando_make_rpc_msg", "int", ["string", "string", "string", "number", "int", "int"]) + + function concat_u8_arrays(arrays) { + // sum of individual array lengths + let totalLength = arrays.reduce((acc, value) => + acc + (value.length || value.byteLength) + , 0); + + if (!arrays.length) return null; + + let result = new Uint8Array(totalLength); + + let length = 0; + for (let array of arrays) { + if (array instanceof ArrayBuffer) + result.set(new Uint8Array(array), length); + else + result.set(array, length); + + length += (array.length || array.byteLength); + } + + return result; + } + + function parse_msgtype(buf) { + return buf[0] << 8 | buf[1] + } + + function wasm_mem(ptr, size) { + return new Uint8Array(module.HEAPU8.buffer, ptr, size); + } + + function LNSocket(opts) { + if (!(this instanceof LNSocket)) + return new LNSocket(opts) + + this.opts = opts || { + timeout: DEFAULT_TIMEOUT + } + this.queue = [] + this.ln = lnsocket_create() + } + + LNSocket.prototype.queue_recv = function() { + let self = this + return new Promise((resolve, reject) => { + const checker = setInterval(() => { + const val = self.queue.shift() + if (val) { + clearInterval(checker) + resolve(val) + } else if (!self.connected) { + clearInterval(checker) + reject() + } + }, 5); + }) + } + + LNSocket.prototype.print_errors = function _lnsocket_print_errors() { + lnsocket_print_errors(this.ln) + } + + LNSocket.prototype.genkey = function _lnsocket_genkey() { + lnsocket_genkey(this.ln) + } + + LNSocket.prototype.act_one_data = function _lnsocket_act_one(node_id) { + const act_one_ptr = lnsocket_act_one(this.ln, node_id) + if (act_one_ptr === 0) + return null + return wasm_mem(act_one_ptr, ACT_ONE_SIZE) + } + + LNSocket.prototype.act_two = function _lnsocket_act_two(act2) { + const act_three_ptr = lnsocket_act_two(this.ln, new Uint8Array(act2)) + if (act_three_ptr === 0) { + this.print_errors() + return null + } + return wasm_mem(act_three_ptr, ACT_THREE_SIZE) + } + + LNSocket.prototype.connect = async function lnsocket_connect(node_id, host) { + await handle_connect(this, node_id, host) + + const act1 = this.act_one_data(node_id) + this.ws.send(act1) + const act2 = await this.read_all(ACT_TWO_SIZE) + if (act2.length != ACT_TWO_SIZE) { + throw new Error(`expected act2 to be ${ACT_TWO_SIZE} long, got ${act2.length}`) + } + const act3 = this.act_two(act2) + this.ws.send(act3) + } + + LNSocket.prototype.connect_and_init = async function _connect_and_init(node_id, host) { + await this.connect(node_id, host) + await this.perform_init() + } + + LNSocket.prototype.read_all = async function read_all(n) { + let count = 0 + let chunks = [] + if (!this.connected) + throw new Error("read_all: not connected") + while (true) { + let res = await this.queue_recv() + + const remaining = n - count + + if (res.byteLength > remaining) { + chunks.push(res.slice(0, remaining)) + this.queue.unshift(res.slice(remaining)) + break + } else if (res.byteLength === remaining) { + chunks.push(res) + break + } + + chunks.push(res) + count += res.byteLength + } + + return concat_u8_arrays(chunks) + } + + LNSocket.prototype.read_header = async function read_header() { + const header = await this.read_all(18) + if (header.length != 18) + throw new Error("Failed to read header") + return lnsocket_decrypt_header(this.ln, header) + } + + LNSocket.prototype.rpc = async function lnsocket_rpc(opts) { + const msg = this.make_commando_msg(opts) + this.write(msg) + const res = await this.read_all_rpc() + return JSON.parse(res) + } + + LNSocket.prototype.recv = async function lnsocket_recv() { + const msg = await this.read() + const msgtype = parse_msgtype(msg.slice(0,2)) + const res = [msgtype, msg.slice(2)] + return res + } + + LNSocket.prototype.read_all_rpc = async function read_all_rpc() { + let chunks = [] + while (true) { + const [typ, msg] = await this.recv() + switch (typ) { + case COMMANDO_REPLY_TERM: + chunks.push(msg.slice(8)) + return new TextDecoder().decode(concat_u8_arrays(chunks)); + case COMMANDO_REPLY_CONTINUES: + chunks.push(msg.slice(8)) + break + default: + console.log("got unknown type", typ) + continue + } + } + } + + LNSocket.prototype.make_commando_msg = function _lnsocket_make_commando_msg(opts) { + const buflen = 4096 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + const params = JSON.stringify(opts.params||{}) + if (!(len = commando_make_rpc_msg(opts.method, params, opts.rune, + 0, buf, buflen))) { + throw new Error("couldn't make commando msg"); + } + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.make_ping_msg = function _lnsocket_make_ping_msg(num_pong_bytes=1, ignored_bytes=1) { + const buflen = 32 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + if (!(len = lnsocket_make_ping_msg(buf, buflen, num_pong_bytes, ignored_bytes))) + throw new Error("couldn't make ping msg"); + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.encrypt = function _lnsocket_encrypt(dat) { + const len = lnsocket_encrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("encrypt error") + } + const enc = wasm_mem(lnsocket_msgbuf(this.ln), len) + return enc + } + + LNSocket.prototype.decrypt = function _lnsocket_decrypt(dat) { + const len = lnsocket_decrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("decrypt error") + } + return wasm_mem(lnsocket_msgbuf(this.ln), len) + } + + LNSocket.prototype.write = function _lnsocket_write(dat) { + this.ws.send(this.encrypt(dat)) + } + + LNSocket.prototype.read = async function _lnsocket_read() { + const size = await this.read_header() + const enc = await this.read_all(size+16) + return this.decrypt(enc) + } + + LNSocket.prototype.make_default_initmsg = function _lnsocket_make_default_initmsg() { + const buflen = 1024 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + if (!(len = lnsocket_make_default_initmsg(buf, buflen))) + throw new Error("couldn't make initmsg"); + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.perform_init = async function lnsocket_connect() { + await this.read() + const our_init = this.make_default_initmsg() + this.write(our_init) + } + + LNSocket.prototype.ping_pong = async function lnsocket_ping_pong() { + const pingmsg = this.make_ping_msg() + this.write(pingmsg) + return await this.read() + } + + LNSocket.prototype.disconnect = function lnsocket_disconnect() { + if (this.connected === true && this.ws) { + this.ws.close() + return true + } + return false + } + + LNSocket.prototype.destroy = function _lnsocket_destroy() { + this.disconnect() + lnsocket_destroy(this.ln) + } + + function handle_connect(ln, node_id, host) { + const ws = new SocketImpl(host) + return new Promise((resolve, reject) => { + const timeout = ln.opts.timeout || DEFAULT_TIMEOUT + const timer = setTimeout(reject, timeout); + + ws.ondata((v) => { + ln.queue.push(v) + }); + + ws.addEventListener('open', function(ev) { + ln.ws = ws + ln.connected = true + clearTimeout(timer) + resolve(ws) + }); + + ws.addEventListener('close', function(ev) { + ln.connected = false + }); + }) + } + + return LNSocket +} + +Module.init = Module.lnsocket_init = lnsocket_init diff --git a/node_modules/lnsocket/dist/node/lnsocket.wasm b/node_modules/lnsocket/dist/node/lnsocket.wasm new file mode 100755 index 0000000..59c3bb0 Binary files /dev/null and b/node_modules/lnsocket/dist/node/lnsocket.wasm differ diff --git a/node_modules/lnsocket/endian.h b/node_modules/lnsocket/endian.h new file mode 100644 index 0000000..0f7781e --- /dev/null +++ b/node_modules/lnsocket/endian.h @@ -0,0 +1,385 @@ +/* CC0 (Public domain) */ +#ifndef CCAN_ENDIAN_H +#define CCAN_ENDIAN_H +#include + +#include "config.h" +#include "cursor.h" + +/** + * BSWAP_16 - reverse bytes in a constant uint16_t value. + * @val: constant value whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_16(0x1234)]; + * }; + */ +#define BSWAP_16(val) \ + ((((uint16_t)(val) & 0x00ff) << 8) \ + | (((uint16_t)(val) & 0xff00) >> 8)) + +/** + * BSWAP_32 - reverse bytes in a constant uint32_t value. + * @val: constant value whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_32(0xff000000)]; + * }; + */ +#define BSWAP_32(val) \ + ((((uint32_t)(val) & 0x000000ff) << 24) \ + | (((uint32_t)(val) & 0x0000ff00) << 8) \ + | (((uint32_t)(val) & 0x00ff0000) >> 8) \ + | (((uint32_t)(val) & 0xff000000) >> 24)) + +/** + * BSWAP_64 - reverse bytes in a constant uint64_t value. + * @val: constantvalue whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_64(0xff00000000000000ULL)]; + * }; + */ +#define BSWAP_64(val) \ + ((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \ + | (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \ + | (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \ + | (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \ + | (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \ + | (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \ + | (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \ + | (((uint64_t)(val) & 0xff00000000000000ULL) >> 56)) + +#if HAVE_BYTESWAP_H +#include +#else +/** + * bswap_16 - reverse bytes in a uint16_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 4 as two bytes reversed" + * printf("1024 is %u as two bytes reversed\n", bswap_16(1024)); + */ +static inline uint16_t bswap_16(uint16_t val) +{ + return BSWAP_16(val); +} + +/** + * bswap_32 - reverse bytes in a uint32_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 262144 as four bytes reversed" + * printf("1024 is %u as four bytes reversed\n", bswap_32(1024)); + */ +static inline uint32_t bswap_32(uint32_t val) +{ + return BSWAP_32(val); +} +#endif /* !HAVE_BYTESWAP_H */ + +#if !HAVE_BSWAP_64 +/** + * bswap_64 - reverse bytes in a uint64_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 1125899906842624 as eight bytes reversed" + * printf("1024 is %llu as eight bytes reversed\n", + * (unsigned long long)bswap_64(1024)); + */ +static inline uint64_t bswap_64(uint64_t val) +{ + return BSWAP_64(val); +} +#endif + +/* Needed for Glibc like endiness check */ +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +/* Sanity check the defines. We don't handle weird endianness. */ +#if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN +#error "Unknown endian" +#elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN +#error "Can't compile for both big and little endian." +#elif HAVE_LITTLE_ENDIAN +#ifndef __BYTE_ORDER +#define __BYTE_ORDER __LITTLE_ENDIAN +#elif __BYTE_ORDER != __LITTLE_ENDIAN +#error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN" +#endif +#elif HAVE_BIG_ENDIAN +#ifndef __BYTE_ORDER +#define __BYTE_ORDER __BIG_ENDIAN +#elif __BYTE_ORDER != __BIG_ENDIAN +#error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN" +#endif +#endif + + +#ifdef __CHECKER__ +/* sparse needs forcing to remove bitwise attribute from ccan/short_types */ +#define ENDIAN_CAST __attribute__((force)) +#define ENDIAN_TYPE __attribute__((bitwise)) +#else +#define ENDIAN_CAST +#define ENDIAN_TYPE +#endif + +typedef uint64_t ENDIAN_TYPE leint64_t; +typedef uint64_t ENDIAN_TYPE beint64_t; +typedef uint32_t ENDIAN_TYPE leint32_t; +typedef uint32_t ENDIAN_TYPE beint32_t; +typedef uint16_t ENDIAN_TYPE leint16_t; +typedef uint16_t ENDIAN_TYPE beint16_t; + +#if HAVE_LITTLE_ENDIAN +/** + * CPU_TO_LE64 - convert a constant uint64_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native)) + +/** + * CPU_TO_LE32 - convert a constant uint32_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native)) + +/** + * CPU_TO_LE16 - convert a constant uint16_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native)) + +/** + * LE64_TO_CPU - convert a little-endian uint64_t constant + * @le_val: little-endian constant to convert + */ +#define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) + +/** + * LE32_TO_CPU - convert a little-endian uint32_t constant + * @le_val: little-endian constant to convert + */ +#define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) + +/** + * LE16_TO_CPU - convert a little-endian uint16_t constant + * @le_val: little-endian constant to convert + */ +#define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) + +#else /* ... HAVE_BIG_ENDIAN */ +#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native)) +#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native)) +#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native)) +#define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) +#define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) +#define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) +#endif /* HAVE_BIG_ENDIAN */ + +#if HAVE_BIG_ENDIAN +/** + * CPU_TO_BE64 - convert a constant uint64_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native)) + +/** + * CPU_TO_BE32 - convert a constant uint32_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native)) + +/** + * CPU_TO_BE16 - convert a constant uint16_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native)) + +/** + * BE64_TO_CPU - convert a big-endian uint64_t constant + * @le_val: big-endian constant to convert + */ +#define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) + +/** + * BE32_TO_CPU - convert a big-endian uint32_t constant + * @le_val: big-endian constant to convert + */ +#define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) + +/** + * BE16_TO_CPU - convert a big-endian uint16_t constant + * @le_val: big-endian constant to convert + */ +#define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) + +#else /* ... HAVE_LITTLE_ENDIAN */ +#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native)) +#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native)) +#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native)) +#define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) +#define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) +#define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) +#endif /* HAVE_LITTE_ENDIAN */ + + +/** + * cpu_to_le64 - convert a uint64_t value to little-endian + * @native: value to convert + */ +static inline leint64_t cpu_to_le64(uint64_t native) +{ + return CPU_TO_LE64(native); +} + +/** + * cpu_to_le32 - convert a uint32_t value to little-endian + * @native: value to convert + */ +static inline leint32_t cpu_to_le32(uint32_t native) +{ + return CPU_TO_LE32(native); +} + +/** + * cpu_to_le16 - convert a uint16_t value to little-endian + * @native: value to convert + */ +static inline leint16_t cpu_to_le16(uint16_t native) +{ + return CPU_TO_LE16(native); +} + +/** + * le64_to_cpu - convert a little-endian uint64_t value + * @le_val: little-endian value to convert + */ +static inline uint64_t le64_to_cpu(leint64_t le_val) +{ + return LE64_TO_CPU(le_val); +} + +/** + * le32_to_cpu - convert a little-endian uint32_t value + * @le_val: little-endian value to convert + */ +static inline uint32_t le32_to_cpu(leint32_t le_val) +{ + return LE32_TO_CPU(le_val); +} + +/** + * le16_to_cpu - convert a little-endian uint16_t value + * @le_val: little-endian value to convert + */ +static inline uint16_t le16_to_cpu(leint16_t le_val) +{ + return LE16_TO_CPU(le_val); +} + +/** + * cpu_to_be64 - convert a uint64_t value to big endian. + * @native: value to convert + */ +static inline beint64_t cpu_to_be64(uint64_t native) +{ + return CPU_TO_BE64(native); +} + +/** + * cpu_to_be32 - convert a uint32_t value to big endian. + * @native: value to convert + */ +static inline beint32_t cpu_to_be32(uint32_t native) +{ + return CPU_TO_BE32(native); +} + +/** + * cpu_to_be16 - convert a uint16_t value to big endian. + * @native: value to convert + */ +static inline beint16_t cpu_to_be16(uint16_t native) +{ + return CPU_TO_BE16(native); +} + +/** + * be64_to_cpu - convert a big-endian uint64_t value + * @be_val: big-endian value to convert + */ +static inline uint64_t be64_to_cpu(beint64_t be_val) +{ + return BE64_TO_CPU(be_val); +} + +/** + * be32_to_cpu - convert a big-endian uint32_t value + * @be_val: big-endian value to convert + */ +static inline uint32_t be32_to_cpu(beint32_t be_val) +{ + return BE32_TO_CPU(be_val); +} + +/** + * be16_to_cpu - convert a big-endian uint16_t value + * @be_val: big-endian value to convert + */ +static inline uint16_t be16_to_cpu(beint16_t be_val) +{ + return BE16_TO_CPU(be_val); +} + +/** + * be64/be32/be16 - 64/32/16 bit big-endian representation. + */ +typedef beint64_t be64; +typedef beint32_t be32; +typedef beint16_t be16; + +/** + * le64/le32/le16 - 64/32/16 bit little-endian representation. + */ +typedef leint64_t le64; +typedef leint32_t le32; +typedef leint16_t le16; + +static inline int cursor_push_u16(struct cursor *cursor, u16 i) +{ + be16 v = cpu_to_be16(i); + return cursor_push(cursor, &v, sizeof(v)); +} + +static inline int cursor_pull_u16(struct cursor *cursor, u16 *i) +{ + be16 ret; + if (!cursor_pull(cursor, (u8*)&ret, sizeof(ret))) + return 0; + *i = be16_to_cpu(ret); + return 1; +} + +static inline int cursor_push_u64(struct cursor *cur, u64 v) +{ + be64 l = cpu_to_be64(v); + return cursor_push(cur, (u8*)&l, sizeof(l)); +} + + +#endif /* CCAN_ENDIAN_H */ diff --git a/node_modules/lnsocket/error.c b/node_modules/lnsocket/error.c new file mode 100644 index 0000000..a8451a7 --- /dev/null +++ b/node_modules/lnsocket/error.c @@ -0,0 +1,49 @@ + +#include "error.h" + +#include +#include + +int note_error_(struct errors *errs_, const char *fmt, ...) +{ + static char buf[512]; + struct error err; + struct cursor *errs; + va_list ap; + + errs = &errs_->cur; + + if (errs_->enabled == 0) + return 0; + + va_start(ap, fmt); + vsprintf(buf, fmt, ap); + va_end(ap); + + err.msg = buf; + + if (!cursor_push_error(errs, &err)) { + fprintf(stderr, "arena OOM when recording error, "); + fprintf(stderr, "errs->p at %ld, remaining %ld, strlen %ld\n", + errs->p - errs->start, errs->end - errs->p, strlen(buf)); + } + + return 0; +} + +void print_error_backtrace(struct errors *errors) +{ + struct cursor errs; + struct error err; + + copy_cursor(&errors->cur, &errs); + errs.p = errs.start; + + while (errs.p < errors->cur.p) { + if (!cursor_pull_error(&errs, &err)) { + fprintf(stderr, "backtrace: couldn't pull error\n"); + return; + } + fprintf(stderr, "%s\n", err.msg); + } +} diff --git a/node_modules/lnsocket/error.h b/node_modules/lnsocket/error.h new file mode 100644 index 0000000..656548b --- /dev/null +++ b/node_modules/lnsocket/error.h @@ -0,0 +1,32 @@ + +#ifndef LNSOCKET_ERROR_H +#define LNSOCKET_ERROR_H + +#include "cursor.h" + +struct error { + const char *msg; +}; + +struct errors { + struct cursor cur; + int enabled; +}; + +#define note_error(errs, fmt, ...) note_error_(errs, "%s:%s:%d: " fmt, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__) + +static inline int cursor_push_error(struct cursor *cur, struct error *err) +{ + return cursor_push_c_str(cur, err->msg); +} + +static inline int cursor_pull_error(struct cursor *cur, struct error *err) +{ + return cursor_pull_c_str(cur, &err->msg); +} + +int note_error_(struct errors *errs, const char *fmt, ...); + +void print_error_backtrace(struct errors *errors); + +#endif /* LNSOCKET_ERROR_H */ diff --git a/node_modules/lnsocket/examples/README.md b/node_modules/lnsocket/examples/README.md new file mode 100644 index 0000000..65aa733 --- /dev/null +++ b/node_modules/lnsocket/examples/README.md @@ -0,0 +1,7 @@ + +# Examples + +## nodejs + + $ npm install + $ node node.js diff --git a/node_modules/lnsocket/examples/node.js b/node_modules/lnsocket/examples/node.js new file mode 100644 index 0000000..dd64596 --- /dev/null +++ b/node_modules/lnsocket/examples/node.js @@ -0,0 +1,24 @@ +const LNSocket = require('lnsocket') + +async function go() { + const ln = await LNSocket() + + ln.genkey() + await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "24.84.152.187") + + const rune = "b3Xsg2AS2cknHYa6H94so7FAVQVdnRSP6Pv-1WOQEBc9NCZtZXRob2Q9b2ZmZXItc3VtbWFyeQ==" + const summary = await ln.rpc({ + rune, + method: "offer-summary", + params: { + offerid: "22db2cbdb2d6e1f4d727d099e2ea987c05212d6b4af56d92497e093b82360db7", + limit: 10 + } + }) + + ln.destroy() + console.log(summary.result) + return summary.result +} + +go() diff --git a/node_modules/lnsocket/examples/package.json b/node_modules/lnsocket/examples/package.json new file mode 100644 index 0000000..06fa952 --- /dev/null +++ b/node_modules/lnsocket/examples/package.json @@ -0,0 +1,18 @@ +{ + "name": "examples", + "description": "lnsocket examples", + "version": "0.1.0", + "repository": { + "url": "https://github.com/jb55/examples" + }, + "main": "node.js", + "scripts": { + "test": "tap test/*.js" + }, + "dependencies": { + "lnsocket": "^0.2.0" + }, + "devDependencies": { + "tap": "~0.2.5" + } +} diff --git a/node_modules/lnsocket/examples/websockets.html b/node_modules/lnsocket/examples/websockets.html new file mode 100644 index 0000000..9e44f98 --- /dev/null +++ b/node_modules/lnsocket/examples/websockets.html @@ -0,0 +1,16 @@ + + + + + + + + Hello World + + +

Hello World

+ + + + + diff --git a/node_modules/lnsocket/examples/websockets.js b/node_modules/lnsocket/examples/websockets.js new file mode 100644 index 0000000..205f065 --- /dev/null +++ b/node_modules/lnsocket/examples/websockets.js @@ -0,0 +1,16 @@ + +async function go() { + const LNSocket = await lnsocket_init() + const ln = LNSocket() + + ln.genkey() + //const their_init = await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "cln.jb55.com:443") + await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "ws://24.84.152.187:8324") + + const rune = "APaeUhcGPAMQwgV1Kn-hRRs5Bi4-D1nrfsHfCoTLl749MTAmbWV0aG9kPWdldGluZm8=" + const res = await ln.rpc({ method: "getinfo", rune }) + + document.body.innerHTML = `
${JSON.stringify(res.result, undefined, 2)}
` +} + +go() diff --git a/node_modules/lnsocket/export.h b/node_modules/lnsocket/export.h new file mode 100644 index 0000000..22167ed --- /dev/null +++ b/node_modules/lnsocket/export.h @@ -0,0 +1,12 @@ + +#ifndef LNSOCKET_COMMON_H +#define LNSOCKET_COMMON_H + +#ifdef __EMSCRIPTEN__ + #include + #define EXPORT EMSCRIPTEN_KEEPALIVE +#else + #define EXPORT +#endif + +#endif diff --git a/node_modules/lnsocket/go/go.mod b/node_modules/lnsocket/go/go.mod new file mode 100644 index 0000000..69a5269 --- /dev/null +++ b/node_modules/lnsocket/go/go.mod @@ -0,0 +1,37 @@ +module github.com/jb55/lnsocket/go + +require ( + github.com/btcsuite/btcd v0.22.0-beta.0.20211005184431-e3449998be39 + github.com/lightningnetwork/lnd v0.14.1-beta +) + +require ( + github.com/aead/siphash v1.0.1 // indirect + github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/btcsuite/btcutil v1.0.3-0.20210527170813-e2ba6805a890 // indirect + github.com/btcsuite/btcutil/psbt v1.0.3-0.20210527170813-e2ba6805a890 // indirect + github.com/btcsuite/btcwallet v0.13.0 // indirect + github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0 // indirect + github.com/btcsuite/btcwallet/wallet/txrules v1.1.0 // indirect + github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0 // indirect + github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec // indirect + github.com/btcsuite/btcwallet/wtxmgr v1.3.1-0.20210822222949-9b5a201c344c // indirect + github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect + github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/lru v1.0.0 // indirect + github.com/go-errors/errors v1.0.1 // indirect + github.com/kkdai/bstream v1.0.0 // indirect + github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect + github.com/lightninglabs/neutrino v0.13.0 // indirect + github.com/lightningnetwork/lnd/clock v1.1.0 // indirect + github.com/lightningnetwork/lnd/queue v1.1.0 // indirect + github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect + github.com/miekg/dns v1.1.43 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect + golang.org/x/net v0.0.0-20210913180222-943fd674d43e // indirect + golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect +) + +go 1.17 diff --git a/node_modules/lnsocket/go/go.sum b/node_modules/lnsocket/go/go.sum new file mode 100644 index 0000000..f95817f --- /dev/null +++ b/node_modules/lnsocket/go/go.sum @@ -0,0 +1,1009 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +git.schwanenlied.me/yawning/bsaes.git v0.0.0-20180720073208-c0276d75487e/go.mod h1:BWqTsj8PgcPriQJGl7el20J/7TuT1d/hSyFDXMEpoEo= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e/go.mod h1:Bdzq+51GR4/0DIhaICZEOm+OHvXGwwB2trKZ8B4Y6eQ= +github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82/go.mod h1:GbuBk21JqF+driLX3XtJYNZjGa45YDoa9IqCTzNSfEc= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Yawning/aez v0.0.0-20180114000226-4dad034d9db2/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta.0.20201208033208-6bd4c64a54fa/go.mod h1:Sv4JPQ3/M+teHz9Bo5jBpkNcP0x6r7rdihlNL/7tTAs= +github.com/btcsuite/btcd v0.22.0-beta.0.20210803133449-f5a1fb9965e4/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.0-beta.0.20211005184431-e3449998be39 h1:o6qacOzpKubr16y0RrE2fBauRZN1rDZ1YsE26ixCgQ0= +github.com/btcsuite/btcd v0.22.0-beta.0.20211005184431-e3449998be39/go.mod h1:3PH+KbvLFfzBTCevQenPiDedjGQGt6aa70dVjJDWGTA= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/btcutil v1.0.3-0.20210527170813-e2ba6805a890 h1:9aGy5p7oXRUB4MCTmWm0+jzuh79GpjPIfv1leA5POD4= +github.com/btcsuite/btcutil v1.0.3-0.20210527170813-e2ba6805a890/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/btcutil/psbt v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= +github.com/btcsuite/btcutil/psbt v1.0.3-0.20210527170813-e2ba6805a890 h1:0xUNvvwJ7RjzBs4nCF+YrK28S5P/b4uHkpPxY1ovGY4= +github.com/btcsuite/btcutil/psbt v1.0.3-0.20210527170813-e2ba6805a890/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= +github.com/btcsuite/btcwallet v0.13.0 h1:gtLWwueRm27KQiHJpycybv3uMdK1eo87JexfTfzvEhk= +github.com/btcsuite/btcwallet v0.13.0/go.mod h1:iLN1lG1MW0eREm+SikmPO8AZPz5NglBTEK/ErqkjGpo= +github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= +github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0 h1:8pO0pvPX1rFRfRiol4oV6kX7dY5y4chPwhfVwUfvwtk= +github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0/go.mod h1:ktYuJyumYtwG+QQ832Q+kqvxWJRAei3Nqs5qhSn4nww= +github.com/btcsuite/btcwallet/wallet/txrules v1.0.0/go.mod h1:UwQE78yCerZ313EXZwEiu3jNAtfXj2n2+c8RWiE/WNA= +github.com/btcsuite/btcwallet/wallet/txrules v1.1.0 h1:Vg8G8zhNVjaCdwJg2QOmLoWn4RTP7K0J9xlwY8CJnLY= +github.com/btcsuite/btcwallet/wallet/txrules v1.1.0/go.mod h1:Zn9UTqpiTH+HOd5BLzSBzULzlOPmcoeyQIA0cp0WbQQ= +github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= +github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0 h1:wZnOolEAeNOHzHTnznw/wQv+j35ftCIokNrnOTOU5o8= +github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= +github.com/btcsuite/btcwallet/walletdb v1.3.4/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= +github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= +github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec h1:zcAU3Ij8SmqaE+ITtS76fua2Niq7DRNp46sJRhi8PiI= +github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= +github.com/btcsuite/btcwallet/wtxmgr v1.3.0/go.mod h1:awQsh1n/0ZrEQ+JZgWvHeo153ubzEisf/FyNtwI0dDk= +github.com/btcsuite/btcwallet/wtxmgr v1.3.1-0.20210822222949-9b5a201c344c h1:owWPexGfK4eSK4/Zy+XK2lET5qsnW7FRAc8OCOdD0Fg= +github.com/btcsuite/btcwallet/wtxmgr v1.3.1-0.20210822222949-9b5a201c344c/go.mod h1:UM38ixX8VwJ9qey4umf//0H3ndn5kSImFZ46V54Nd5Q= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= +github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fergusstrange/embedded-postgres v1.10.0 h1:YnwF6xAQYmKLAXXrrRx4rHDLih47YJwVPvg8jeKfdNg= +github.com/fergusstrange/embedded-postgres v1.10.0/go.mod h1:a008U8/Rws5FtIOTGYDYa7beVWsT3qVKyqExqYYjL+c= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU= +github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs= +github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570= +github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= +github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= +github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/retry v0.0.0-20180821225755-9058e192b216/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= +github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= +github.com/juju/utils v0.0.0-20180820210520-bf9cc5bdd62d/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= +github.com/juju/version v0.0.0-20180108022336-b64dbd566305/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= +github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= +github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= +github.com/lightninglabs/neutrino v0.12.1/go.mod h1:GlKninWpRBbL7b8G0oQ36/8downfnFwKsr0hbRA6E/E= +github.com/lightninglabs/neutrino v0.13.0 h1:j3PKWEJCwqwMn/qLASz2j0IuCF6AumS9DaM0i0pM/nY= +github.com/lightninglabs/neutrino v0.13.0/go.mod h1:GlKninWpRBbL7b8G0oQ36/8downfnFwKsr0hbRA6E/E= +github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display/go.mod h1:2oKOBU042GKFHrdbgGiKax4xVrFiZu51lhacUZQ9MnE= +github.com/lightningnetwork/lightning-onion v1.0.2-0.20210520211913-522b799e65b1 h1:h1BsjPzWea790mAXISoiT/qr0JRcixTCDNLmjsDThSw= +github.com/lightningnetwork/lightning-onion v1.0.2-0.20210520211913-522b799e65b1/go.mod h1:rigfi6Af/KqsF7Za0hOgcyq2PNH4AN70AaMRxcJkff4= +github.com/lightningnetwork/lnd v0.14.1-beta h1:v9hOlJ1xYivYQ634Nt71up5QDh8mXVpYh4MXUbbWTRw= +github.com/lightningnetwork/lnd v0.14.1-beta/go.mod h1:o7zDwjZXm/bPP48qjwsqnZvvITyQl+fUv6UVoV4o+J8= +github.com/lightningnetwork/lnd/cert v1.1.0/go.mod h1:3MWXVLLPI0Mg0XETm9fT4N9Vyy/8qQLmaM5589bEggM= +github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= +github.com/lightningnetwork/lnd/clock v1.1.0 h1:/yfVAwtPmdx45aQBoXQImeY7sOIEr7IXlImRMBOZ7GQ= +github.com/lightningnetwork/lnd/clock v1.1.0/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= +github.com/lightningnetwork/lnd/healthcheck v1.0.0/go.mod h1:u92p1JGFJNMSkMvztKEwmt1P3TRnLeJBXZ3M85xkU1E= +github.com/lightningnetwork/lnd/healthcheck v1.2.0 h1:00bkNn+hGJM9j3Ht+ulf8YNcSx1HEYSDv5pf4HB1/uQ= +github.com/lightningnetwork/lnd/healthcheck v1.2.0/go.mod h1:WSz3lsUjErJQZ3gb+zW32nM3WIHNiZ3A40GVoaQY5wU= +github.com/lightningnetwork/lnd/kvdb v1.2.1 h1:QevYLPh6bh1SLIvlUaPbrpX/YMKzSPBfmGVvn2i8IlU= +github.com/lightningnetwork/lnd/kvdb v1.2.1/go.mod h1:x+IpsuDynubjokUofavLXroeGfS/WrqUXXTK6vN/gp4= +github.com/lightningnetwork/lnd/queue v1.0.1/go.mod h1:vaQwexir73flPW43Mrm7JOgJHmcEFBWWSl9HlyASoms= +github.com/lightningnetwork/lnd/queue v1.1.0 h1:YpCJjlIvVxN/R7ww2aNiY8ex7U2fucZDLJ67tI3HFx8= +github.com/lightningnetwork/lnd/queue v1.1.0/go.mod h1:YTkTVZCxz8tAYreH27EO3s8572ODumWrNdYW2E/YKxg= +github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0= +github.com/lightningnetwork/lnd/ticker v1.1.0 h1:ShoBiRP3pIxZHaETndfQ5kEe+S4NdAY1hiX7YbZ4QE4= +github.com/lightningnetwork/lnd/ticker v1.1.0/go.mod h1:ubqbSVCn6RlE0LazXuBr7/Zi6QT0uQo++OgIRBxQUrk= +github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= +github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= +github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE= +github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/nwaples/rardecode v1.1.2 h1:Cj0yZY6T1Zx1R7AhTbyGSALm44/Mmq+BAPc4B/p/d3M= +github.com/nwaples/rardecode v1.1.2/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4= +github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLTs= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= +go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= +go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= +go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= +go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= +go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= +go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= +go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= +go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= +go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= +go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e h1:+b/22bPvDYt4NPDcy4xAGCmON713ONAWFeY3Z7I3tR8= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus= +google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/macaroon-bakery.v2 v2.0.1/go.mod h1:B4/T17l+ZWGwxFSZQmlBwp25x+og7OkhETfr3S9MbIA= +gopkg.in/macaroon.v2 v2.0.0/go.mod h1:+I6LnTMkm/uV5ew/0nsulNjL16SK4+C8yDmRUzHR17I= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/node_modules/lnsocket/go/lnsocket.go b/node_modules/lnsocket/go/lnsocket.go new file mode 100644 index 0000000..e21695a --- /dev/null +++ b/node_modules/lnsocket/go/lnsocket.go @@ -0,0 +1,190 @@ +package lnsocket + +import ( + "bytes" + "encoding/hex" + "fmt" + "io" + "net" + + "github.com/btcsuite/btcd/btcec" + "github.com/lightningnetwork/lnd/brontide" + "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/tor" +) + +const ( + COMMANDO_CMD = 0x4c4f + COMMANDO_REPLY_CONTINUES = 0x594b + COMMANDO_REPLY_TERM = 0x594d +) + +type CommandoMsg struct { + Rune string + Method string + Params string + RequestId uint64 +} + +func NewCommandoMsg(token string, method string, params string) CommandoMsg { + return CommandoMsg{ + Rune: token, + Method: method, + Params: params, + } +} + +// A compile time check to ensure Init implements the lnwire.Message +// interface. + +func (msg *CommandoMsg) MsgType() lnwire.MessageType { + return COMMANDO_CMD +} + +func (msg *CommandoMsg) Decode(reader io.Reader, size uint32) error { + return fmt.Errorf("implememt commando decode?") +} + +func (msg *CommandoMsg) Encode(buf *bytes.Buffer, pver uint32) error { + if err := lnwire.WriteUint64(buf, msg.RequestId); err != nil { + return err + } + + buf.WriteString("{\"method\": \"") + buf.WriteString(msg.Method) + buf.WriteString("\",\"params\":") + buf.WriteString(msg.Params) + buf.WriteString(",\"rune\":\"") + buf.WriteString(msg.Rune) + buf.WriteString("\"}") + + return nil +} + +type LNSocket struct { + Conn net.Conn + PrivKeyECDH *keychain.PrivKeyECDH +} + +func (ln *LNSocket) GenKey() { + remotePriv, _ := btcec.NewPrivateKey(btcec.S256()) + ln.PrivKeyECDH = &keychain.PrivKeyECDH{PrivKey: remotePriv} +} + +func (ln *LNSocket) ConnectWith(netAddr *lnwire.NetAddress) error { + conn, err := brontide.Dial(ln.PrivKeyECDH, netAddr, tor.DefaultConnTimeout, net.DialTimeout) + ln.Conn = conn + return err +} + +func (ln *LNSocket) Connect(hostname string, pubkey string) error { + addr, err := net.ResolveTCPAddr("tcp", hostname) + if err != nil { + return err + } + bytes, err := hex.DecodeString(pubkey) + if err != nil { + return err + } + key, err := btcec.ParsePubKey(bytes, btcec.S256()) + if err != nil { + return err + } + + netAddr := &lnwire.NetAddress{ + IdentityKey: key, + Address: addr, + } + + return ln.ConnectWith(netAddr) +} + +func (ln *LNSocket) PerformInit() error { + no_features := lnwire.NewRawFeatureVector() + init_reply_msg := lnwire.NewInitMessage(no_features, no_features) + + var b bytes.Buffer + _, err := lnwire.WriteMessage(&b, init_reply_msg, 0) + if err != nil { + return err + } + _, err = ln.Conn.Write(b.Bytes()) + + // receive the first init msg + _, _, err = ln.Recv() + if err != nil { + return err + } + + return nil +} + +func (ln *LNSocket) Rpc(token string, method string, params string) (string, error) { + commando_msg := NewCommandoMsg(token, method, params) + + var b bytes.Buffer + _, err := lnwire.WriteMessage(&b, &commando_msg, 0) + if err != nil { + return "", err + } + + bs := b.Bytes() + _, err = ln.Conn.Write(bs) + if err != nil { + return "", err + } + + return ln.rpcReadAll() +} + +func ParseMsgType(bytes []byte) uint16 { + return uint16(bytes[0])<<8 | uint16(bytes[1]) +} + +func (ln *LNSocket) Recv() (uint16, []byte, error) { + res := make([]byte, 65535) + n, err := ln.Conn.Read(res) + if err != nil { + return 0, nil, err + } + if n < 2 { + return 0, nil, fmt.Errorf("read too small") + } + res = res[:n] + msgtype := ParseMsgType(res) + return msgtype, res[2:], nil +} + +func (ln *LNSocket) rpcReadAll() (string, error) { + all := []byte{} + for { + msgtype, res, err := ln.Recv() + if err != nil { + return "", err + } + switch msgtype { + case COMMANDO_REPLY_CONTINUES: + all = append(all, res[8:]...) + continue + case COMMANDO_REPLY_TERM: + all = append(all, res[8:]...) + return string(all), nil + default: + continue + } + } +} + +func (ln *LNSocket) Disconnect() { + ln.Conn.Close() +} + +func (ln *LNSocket) ConnectAndInit(hostname string, pubkey string) error { + err := ln.Connect(hostname, pubkey) + if err != nil { + return err + } + + return ln.PerformInit() +} diff --git a/node_modules/lnsocket/handshake.c b/node_modules/lnsocket/handshake.c new file mode 100644 index 0000000..7cd46fb --- /dev/null +++ b/node_modules/lnsocket/handshake.c @@ -0,0 +1,481 @@ +/* Copyright Rusty Russell (Blockstream) 2015. + William Casarin 2022 + +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. +*/ + +#include "compiler.h" +#include "endian.h" +#include "error.h" +#include "handshake.h" +#include "hkdf.h" +#include "lnsocket_internal.h" +#include "sha256.h" +#include +#include +#include +#include +#include "export.h" + +struct keypair generate_key(secp256k1_context *ctx) +{ + struct keypair k; + + do { + randombytes_buf(k.priv.secret.data, sizeof(k.priv.secret.data)); + } while (!secp256k1_ec_pubkey_create(ctx, &k.pub.pubkey, + k.priv.secret.data)); + return k; +} + + +/* h = SHA-256(h || data) */ +static void sha_mix_in(struct sha256 *h, const void *data, size_t len) +{ + struct sha256_ctx shactx; + + sha256_init(&shactx); + sha256_update(&shactx, h->u.u8, sizeof(*h)); + sha256_update(&shactx, data, len); + sha256_done(&shactx, h); +} + +/* h = SHA-256(h || pub.serializeCompressed()) */ +static void sha_mix_in_key(secp256k1_context *ctx, struct sha256 *h, + const struct pubkey *key) +{ + u8 der[PUBKEY_CMPR_LEN]; + size_t len = sizeof(der); + + secp256k1_ec_pubkey_serialize(ctx, der, &len, &key->pubkey, + SECP256K1_EC_COMPRESSED); + assert(len == sizeof(der)); + sha_mix_in(h, der, sizeof(der)); +} + + +/* BOLT #8: + * * `encryptWithAD(k, n, ad, plaintext)`: outputs `encrypt(k, n, ad, + * plaintext)` + * * Where `encrypt` is an evaluation of `ChaCha20-Poly1305` (IETF + * variant) with the passed arguments, with nonce `n` + */ +static void encrypt_ad(const struct secret *k, u64 nonce, + const void *additional_data, size_t additional_data_len, + const void *plaintext, size_t plaintext_len, + void *output, size_t outputlen) +{ + unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; + unsigned long long clen; + int ret; + + assert(outputlen == plaintext_len + crypto_aead_chacha20poly1305_ietf_ABYTES); + le64_nonce(npub, nonce); + BUILD_ASSERT(sizeof(*k) == crypto_aead_chacha20poly1305_ietf_KEYBYTES); + + ret = crypto_aead_chacha20poly1305_ietf_encrypt( + output, &clen, memcheck(plaintext, plaintext_len), + plaintext_len, additional_data, additional_data_len, + NULL, npub, k->data); + + assert(ret == 0); + assert(clen == plaintext_len + crypto_aead_chacha20poly1305_ietf_ABYTES); +} + +static inline void check_act_one(const struct act_one *act1) +{ + /* BOLT #8: + * + * : 1 byte for the handshake version, 33 bytes for the compressed + * ephemeral public key of the initiator, and 16 bytes for the + * `poly1305` tag. + */ + BUILD_ASSERT(sizeof(act1->v) == 1); + BUILD_ASSERT(sizeof(act1->pubkey) == 33); + BUILD_ASSERT(sizeof(act1->tag) == 16); +} + +/* +static void print_hex(u8 *bytes, int len) { + int i; + for (i = 0; i < len; ++i) { + printf("%02x", bytes[i]); + } +} +*/ + +void new_handshake(secp256k1_context *secp, struct handshake *handshake, + const struct pubkey *responder_id) +{ + /* BOLT #8: + * + * Before the start of Act One, both sides initialize their + * per-sessions state as follows: + * + * 1. `h = SHA-256(protocolName)` + * * where `protocolName = "Noise_XK_secp256k1_ChaChaPoly_SHA256"` + * encoded as an ASCII string + */ + sha256(&handshake->h, "Noise_XK_secp256k1_ChaChaPoly_SHA256", + strlen("Noise_XK_secp256k1_ChaChaPoly_SHA256")); + + /* BOLT #8: + * + * 2. `ck = h` + */ + BUILD_ASSERT(sizeof(handshake->h) == sizeof(handshake->ck)); + memcpy(&handshake->ck, &handshake->h, sizeof(handshake->ck)); + + /* BOLT #8: + * + * 3. `h = SHA-256(h || prologue)` + * * where `prologue` is the ASCII string: `lightning` + */ + sha_mix_in(&handshake->h, "lightning", strlen("lightning")); + + /* BOLT #8: + * + * As a concluding step, both sides mix the responder's public key + * into the handshake digest: + * + * * The initiating node mixes in the responding node's static public + * key serialized in Bitcoin's compressed format: + * * `h = SHA-256(h || rs.pub.serializeCompressed())` + * + * * The responding node mixes in their local static public key + * serialized in Bitcoin's compressed format: + * * `h = SHA-256(h || ls.pub.serializeCompressed())` + */ + sha_mix_in_key(secp, &handshake->h, responder_id); +} + +/* +static void print_act_two(struct act_two *two) +{ + printf("ACT2 v %d pubkey ", two->v); + print_hex(two->pubkey, sizeof(two->pubkey)); + printf(" tag "); + print_hex(two->tag, sizeof(two->tag)); + printf("\n"); +} +*/ + +/* BOLT #8: + * * `decryptWithAD(k, n, ad, ciphertext)`: outputs `decrypt(k, n, ad, + * ciphertext)` + * * Where `decrypt` is an evaluation of `ChaCha20-Poly1305` (IETF + * variant) with the passed arguments, with nonce `n` + */ +static int decrypt(const struct secret *k, u64 nonce, + const void *additional_data, size_t additional_data_len, + const void *ciphertext, size_t ciphertext_len, + void *output, size_t outputlen) +{ + unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; + unsigned long long mlen; + + assert(outputlen == ciphertext_len - crypto_aead_chacha20poly1305_ietf_ABYTES); + + le64_nonce(npub, nonce); + BUILD_ASSERT(sizeof(*k) == crypto_aead_chacha20poly1305_ietf_KEYBYTES); + if (crypto_aead_chacha20poly1305_ietf_decrypt(output, &mlen, NULL, + memcheck(ciphertext, ciphertext_len), + ciphertext_len, + additional_data, additional_data_len, + npub, k->data) != 0) { + return 0; + } + + assert(mlen == ciphertext_len - crypto_aead_chacha20poly1305_ietf_ABYTES); + return 1; +} + +static int handshake_success(struct lnsocket *ln, struct handshake *h) +{ + struct crypto_state *cs = &ln->crypto_state; + + /* BOLT #8: + * + * 9. `rk, sk = HKDF(ck, zero)` + * * where `zero` is a zero-length plaintext, `rk` is the key to + * be used by the responder to decrypt the messages sent by the + * initiator, and `sk` is the key to be used by the responder + * to encrypt messages to the initiator + * + * * The final encryption keys, to be used for sending and + * receiving messages for the duration of the session, are + * generated. + */ + if (h->side == RESPONDER) + hkdf_two_keys(&cs->rk, &cs->sk, &h->ck, NULL); + else + hkdf_two_keys(&cs->sk, &cs->rk, &h->ck, NULL); + + cs->rn = cs->sn = 0; + cs->r_ck = cs->s_ck = h->ck; + + return 1; +} + +static struct act_three *build_act_three(struct lnsocket *ln) +{ + u8 spub[PUBKEY_CMPR_LEN]; + size_t len = sizeof(spub); + struct handshake *h = &ln->handshake; + + /* BOLT #8: + * 1. `c = encryptWithAD(temp_k2, 1, h, s.pub.serializeCompressed())` + * * where `s` is the static public key of the initiator + */ + secp256k1_ec_pubkey_serialize(ln->secp, spub, &len, + &ln->key.pub.pubkey, + SECP256K1_EC_COMPRESSED); + encrypt_ad(&h->temp_k, 1, &h->h, sizeof(h->h), spub, sizeof(spub), + h->act3.ciphertext, sizeof(h->act3.ciphertext)); + + /* BOLT #8: + * 2. `h = SHA-256(h || c)` + */ + sha_mix_in(&h->h, h->act3.ciphertext, sizeof(h->act3.ciphertext)); + + /* BOLT #8: + * + * 3. `se = ECDH(s.priv, re)` + * * where `re` is the ephemeral public key of the responder + */ + if (!secp256k1_ecdh(ln->secp, h->ss.data, &h->re.pubkey, + ln->key.priv.secret.data, NULL, NULL)) { + note_error(&ln->errs, "act3 ecdh handshake failed"); + return NULL; + } + + /* BOLT #8: + * + * 4. `ck, temp_k3 = HKDF(ck, se)` + * * The final intermediate shared secret is mixed into the running chaining key. + */ + hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss); + + /* BOLT #8: + * + * 5. `t = encryptWithAD(temp_k3, 0, h, zero)` + * * where `zero` is a zero-length plaintext + * + */ + encrypt_ad(&h->temp_k, 0, &h->h, sizeof(h->h), NULL, 0, + h->act3.tag, sizeof(h->act3.tag)); + + /* BOLT #8: + * + * 8. Send `m = 0 || c || t` over the network buffer. + * + */ + h->act3.v = 0; + + handshake_success(ln, &ln->handshake); + + return &h->act3; +} + + +// act2: handle the response to the message sent in act1 +struct act_three* EXPORT lnsocket_act_two(struct lnsocket *ln, struct act_two *act2) +{ + struct handshake *h = &ln->handshake; + + //print_act_two(act2); + + /* BOLT #8: + * + * 3. If `v` is an unrecognized handshake version, then the responder + * MUST abort the connection attempt. + */ + if (act2->v != 0) { + note_error(&ln->errs, "unrecognized handshake version"); + return NULL; + } + + //print_hex() + + /* BOLT #8: + * + * * The raw bytes of the remote party's ephemeral public key + * (`re`) are to be deserialized into a point on the curve using + * affine coordinates as encoded by the key's serialized + * composed format. + */ + if (secp256k1_ec_pubkey_parse(ln->secp, &h->re.pubkey, act2->pubkey, + sizeof(act2->pubkey)) != 1) { + note_error(&ln->errs, "failed to parse remote pubkey"); + return NULL; + } + + /* BOLT #8: + * + * 4. `h = SHA-256(h || re.serializeCompressed())` + */ + sha_mix_in_key(ln->secp, &h->h, &h->re); + + /* BOLT #8: + * + * 5. `es = ECDH(s.priv, re)` + */ + if (!secp256k1_ecdh(ln->secp, h->ss.data, &h->re.pubkey, + h->e.priv.secret.data, NULL, NULL)) { + note_error(&ln->errs, "act2 ecdh failed"); + return NULL; + } + + /* BOLT #8: + * + * 6. `ck, temp_k2 = HKDF(ck, ee)` + * * A new temporary encryption key is generated, which is + * used to generate the authenticating MAC. + */ + hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss); + + /* BOLT #8: + * + * 7. `p = decryptWithAD(temp_k2, 0, h, c)` + * * If the MAC check in this operation fails, then the initiator + * MUST terminate the connection without any further messages. + */ + if (!decrypt(&h->temp_k, 0, &h->h, sizeof(h->h), + act2->tag, sizeof(act2->tag), NULL, 0)) { + note_error(&ln->errs, "handshake decrypt failed"); + return NULL; + } + + /* BOLT #8: + * + * 8. `h = SHA-256(h || c)` + * * The received ciphertext is mixed into the handshake digest. + * This step serves to ensure the payload wasn't modified by a + * MITM. + */ + sha_mix_in(&h->h, act2->tag, sizeof(act2->tag)); + + return build_act_three(ln); +} + +// Prepare the very first message and send it the connected node +// Wait for a response in act2 +int act_one_initiator_prep(struct lnsocket *ln) +{ + struct handshake *h = &ln->handshake; + + h->e = generate_key(ln->secp); + + /* BOLT #8: + * + * 2. `h = SHA-256(h || e.pub.serializeCompressed())` + * * The newly generated ephemeral key is accumulated into the + * running handshake digest. + */ + sha_mix_in_key(ln->secp, &h->h, &h->e.pub); + + /* BOLT #8: + * + * 3. `es = ECDH(e.priv, rs)` + * * The initiator performs an ECDH between its newly generated ephemeral + * key and the remote node's static public key. + */ + if (!secp256k1_ecdh(ln->secp, h->ss.data, + &h->their_id.pubkey, h->e.priv.secret.data, + NULL, NULL)) { + return note_error(&ln->errs, "handshake failed, secp256k1_ecdh error"); + } + + /* BOLT #8: + * + * 4. `ck, temp_k1 = HKDF(ck, es)` + * * A new temporary encryption key is generated, which is + * used to generate the authenticating MAC. + */ + hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss); + + /* BOLT #8: + * 5. `c = encryptWithAD(temp_k1, 0, h, zero)` + * * where `zero` is a zero-length plaintext + */ + encrypt_ad(&h->temp_k, 0, &h->h, sizeof(h->h), NULL, 0, + h->act1.tag, sizeof(h->act1.tag)); + + /* BOLT #8: + * 6. `h = SHA-256(h || c)` + * * Finally, the generated ciphertext is accumulated into the + * authenticating handshake digest. + */ + sha_mix_in(&h->h, h->act1.tag, sizeof(h->act1.tag)); + + /* BOLT #8: + * + * 7. Send `m = 0 || e.pub.serializeCompressed() || c` to the responder over the network buffer. + */ + h->act1.v = 0; + size_t len = sizeof(h->act1.pubkey); + secp256k1_ec_pubkey_serialize(ln->secp, h->act1.pubkey, &len, + &h->e.pub.pubkey, + SECP256K1_EC_COMPRESSED); + + check_act_one(&h->act1); + + return 1; +} + +// act2: read the response to the message sent in act1 +static int act_two_initiator(struct lnsocket *ln, struct handshake *h) +{ + /* BOLT #8: + * + * 1. Read _exactly_ 50 bytes from the network buffer. + * + * 2. Parse the read message (`m`) into `v`, `re`, and `c`: + * * where `v` is the _first_ byte of `m`, `re` is the next 33 + * bytes of `m`, and `c` is the last 16 bytes of `m`. + */ + ssize_t size; + + if ((size = read(ln->socket, &h->act2, ACT_TWO_SIZE)) != ACT_TWO_SIZE) { + printf("read %ld bytes, expected %d\n", size, ACT_TWO_SIZE); + return note_error(&ln->errs, "%s", strerror(errno)); + } + + struct act_three *act3 = lnsocket_act_two(ln, &h->act2); + if (act3 == NULL) + return 0; + + if (write(ln->socket, act3, ACT_THREE_SIZE) != ACT_THREE_SIZE) { + return note_error(&ln->errs, "handshake failed on initial send"); + } + + return 1; +} + +int act_one_initiator(struct lnsocket *ln) +{ + if (!act_one_initiator_prep(ln)) + return 0; + + if (write(ln->socket, &ln->handshake.act1, ACT_ONE_SIZE) != ACT_ONE_SIZE) { + return note_error(&ln->errs, "handshake failed on initial send"); + } + + return act_two_initiator(ln, &ln->handshake); +} diff --git a/node_modules/lnsocket/handshake.h b/node_modules/lnsocket/handshake.h new file mode 100644 index 0000000..9c6a0f5 --- /dev/null +++ b/node_modules/lnsocket/handshake.h @@ -0,0 +1,147 @@ +/* Copyright Rusty Russell (Blockstream) 2015. + +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. +*/ + +#ifndef LNLINK_HANDSHAKE_H +#define LNLINK_HANDSHAKE_H + +#include "typedefs.h" +#include "sha256.h" +#include "crypto.h" + +#include + +#include +#include + +#define ACT_ONE_SIZE 50 +#define ACT_TWO_SIZE 50 +#define ACT_THREE_SIZE 66 + +enum bolt8_side { + INITIATOR, + RESPONDER +}; + +/* BOLT #8: + * + * Act One is sent from initiator to responder. During Act One, the + * initiator attempts to satisfy an implicit challenge by the responder. To + * complete this challenge, the initiator must know the static public key of + * the responder. + */ +struct act_one { + u8 v; + u8 pubkey[PUBKEY_CMPR_LEN]; + u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; +}; + +/* BOLT #8: + * + * Act Two is sent from the responder to the initiator. Act Two will + * _only_ take place if Act One was successful. Act One was successful if + * the responder was able to properly decrypt and check the MAC of the tag + * sent at the end of Act One. + */ +struct act_two { + u8 v; + u8 pubkey[PUBKEY_CMPR_LEN]; + u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; +}; + +/* BOLT #8: + * + * Act Three is the final phase in the authenticated key agreement described + * in this section. This act is sent from the initiator to the responder as a + * concluding step. Act Three is executed _if and only if_ Act Two was + * successful. During Act Three, the initiator transports its static public + * key to the responder encrypted with _strong_ forward secrecy, using the + * accumulated `HKDF` derived secret key at this point of the handshake. + */ +struct act_three { + u8 v; + u8 ciphertext[PUBKEY_CMPR_LEN + crypto_aead_chacha20poly1305_ietf_ABYTES]; + u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; +}; + +/* BOLT #8: + * + * Throughout the handshake process, each side maintains these variables: + * + * * `ck`: the **chaining key**. This value is the accumulated hash of all + * previous ECDH outputs. At the end of the handshake, `ck` is used to derive + * the encryption keys for Lightning messages. + * + * * `h`: the **handshake hash**. This value is the accumulated hash of _all_ + * handshake data that has been sent and received so far during the handshake + * process. + * + * * `temp_k1`, `temp_k2`, `temp_k3`: the **intermediate keys**. These are used to + * encrypt and decrypt the zero-length AEAD payloads at the end of each handshake + * message. + * + * * `e`: a party's **ephemeral keypair**. For each session, a node MUST generate a + * new ephemeral key with strong cryptographic randomness. + * + * * `s`: a party's **static keypair** (`ls` for local, `rs` for remote) + */ +struct handshake { + struct secret ck; + struct secret temp_k; + struct sha256 h; + struct keypair e; + struct secret ss; + + /* Used between the Acts */ + struct pubkey re; + struct act_one act1; + struct act_two act2; + struct act_three act3; + + /* Where is connection from/to */ + struct addrinfo addr; + + /* Who they are: set already if we're initiator. */ + struct pubkey their_id; + + /* Are we initiator or responder. */ + enum bolt8_side side; + + /* Function to call once handshake complete. */ + /* + struct io_plan *(*cb)(struct io_conn *conn, + const struct pubkey *their_id, + const struct wireaddr_internal *wireaddr, + struct crypto_state *cs, + void *cbarg); + void *cbarg; + */ +}; + +void new_handshake(secp256k1_context *secp, struct handshake *handshake, + const struct pubkey *responder_id); + +struct lnsocket; + +int act_one_initiator_prep(struct lnsocket *ln); +int act_one_initiator(struct lnsocket *ln); +struct keypair generate_key(secp256k1_context *ctx); + +#endif /* LNLINK_HANDSHAKE_H */ diff --git a/node_modules/lnsocket/hkdf.c b/node_modules/lnsocket/hkdf.c new file mode 100644 index 0000000..b044fd8 --- /dev/null +++ b/node_modules/lnsocket/hkdf.c @@ -0,0 +1,98 @@ +/* MIT (BSD) license */ + +#include "hmac.h" +#include "sha256.h" +#include +#include + +void hkdf_sha256(void *okm, size_t okm_size, + const void *s, size_t ssize, + const void *k, size_t ksize, + const void *info, size_t isize) +{ + struct hmac_sha256 prk, t; + struct hmac_sha256_ctx ctx; + unsigned char c; + + assert(okm_size < 255 * sizeof(t)); + + /* RFC 5869: + * + * 2.2. Step 1: Extract + * + * HKDF-Extract(salt, IKM) -> PRK + * + * Options: + * Hash a hash function; HashLen denotes the length of the + * hash function output in octets + * + * Inputs: + * salt optional salt value (a non-secret random value); + * if not provided, it is set to a string of HashLen zeros. + * IKM input keying material + * + * Output: + * PRK a pseudorandom key (of HashLen octets) + * + * The output PRK is calculated as follows: + * + * PRK = HMAC-Hash(salt, IKM) + */ + hmac_sha256(&prk, s, ssize, k, ksize); + + /* + * 2.3. Step 2: Expand + * + * HKDF-Expand(PRK, info, L) -> OKM + * + * Options: + * Hash a hash function; HashLen denotes the length of the + * hash function output in octets + * + * Inputs: + * PRK a pseudorandom key of at least HashLen octets + * (usually, the output from the extract step) + * info optional context and application specific information + * (can be a zero-length string) + * L length of output keying material in octets + * (<= 255*HashLen) + * + * Output: + * OKM output keying material (of L octets) + * + * The output OKM is calculated as follows: + * + * N = ceil(L/HashLen) + * T = T(1) | T(2) | T(3) | ... | T(N) + * OKM = first L octets of T + * + * where: + * T(0) = empty string (zero length) + * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) + * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) + * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) + * ... + * + * (where the constant concatenated to the end of each T(n) is a + * single octet.) + */ + c = 1; + hmac_sha256_init(&ctx, &prk, sizeof(prk)); + hmac_sha256_update(&ctx, info, isize); + hmac_sha256_update(&ctx, &c, 1); + hmac_sha256_done(&ctx, &t); + + while (okm_size > sizeof(t)) { + memcpy(okm, &t, sizeof(t)); + okm = (char *)okm + sizeof(t); + okm_size -= sizeof(t); + + c++; + hmac_sha256_init(&ctx, &prk, sizeof(prk)); + hmac_sha256_update(&ctx, &t, sizeof(t)); + hmac_sha256_update(&ctx, info, isize); + hmac_sha256_update(&ctx, &c, 1); + hmac_sha256_done(&ctx, &t); + } + memcpy(okm, &t, okm_size); +} diff --git a/node_modules/lnsocket/hkdf.h b/node_modules/lnsocket/hkdf.h new file mode 100644 index 0000000..b6da5fa --- /dev/null +++ b/node_modules/lnsocket/hkdf.h @@ -0,0 +1,22 @@ + +#ifndef CCAN_CRYPTO_HKDF_SHA256_H +#define CCAN_CRYPTO_HKDF_SHA256_H +/* BSD-MIT - see LICENSE file for details */ +#include + +/** + * hkdf_sha256 - generate a derived key + * @okm: where to output the key + * @okm_size: the number of bytes pointed to by @okm (must be less than 255*32) + * @s: salt + * @ssize: the number of bytes pointed to by @s + * @k: pointer to input key + * @ksize: the number of bytes pointed to by @k + * @info: pointer to info + * @isize: the number of bytes pointed to by @info + */ +void hkdf_sha256(void *okm, size_t okm_size, + const void *s, size_t ssize, + const void *k, size_t ksize, + const void *info, size_t isize); +#endif /* CCAN_CRYPTO_HKDF_SHA256_H */ diff --git a/node_modules/lnsocket/hmac.c b/node_modules/lnsocket/hmac.c new file mode 100644 index 0000000..d0b2683 --- /dev/null +++ b/node_modules/lnsocket/hmac.c @@ -0,0 +1,278 @@ +/* Copyright Rusty Russell (Blockstream) 2015. + +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. +*/ + +#include +#include "hmac.h" + +#define IPAD 0x3636363636363636ULL +#define OPAD 0x5C5C5C5C5C5C5C5CULL + +#define BLOCK_256_U64S (HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t)) +#define BLOCK_512_U64S (HMAC_SHA512_BLOCKSIZE / sizeof(uint64_t)) + +static inline void xor_block_256(uint64_t block[BLOCK_256_U64S], uint64_t pad) +{ + size_t i; + + for (i = 0; i < BLOCK_256_U64S; i++) + block[i] ^= pad; +} + + +static inline void xor_block_512(uint64_t block[BLOCK_512_U64S], uint64_t pad) +{ + size_t i; + + for (i = 0; i < BLOCK_512_U64S; i++) + block[i] ^= pad; +} + +void hmac_sha256_init(struct hmac_sha256_ctx *ctx, + const void *k, size_t ksize) +{ + struct sha256 hashed_key; + /* We use k_opad as k_ipad temporarily. */ + uint64_t *k_ipad = ctx->k_opad; + + /* (keys longer than B bytes are first hashed using H) */ + if (ksize > HMAC_SHA256_BLOCKSIZE) { + sha256(&hashed_key, k, ksize); + k = &hashed_key; + ksize = sizeof(hashed_key); + } + + /* From RFC2104: + * + * (1) append zeros to the end of K to create a B byte string + * (e.g., if K is of length 20 bytes and B=64, then K will be + * appended with 44 zero bytes 0x00) + */ + memcpy(k_ipad, k, ksize); + memset((char *)k_ipad + ksize, 0, HMAC_SHA256_BLOCKSIZE - ksize); + + /* + * (2) XOR (bitwise exclusive-OR) the B byte string computed + * in step (1) with ipad + */ + xor_block_256(k_ipad, IPAD); + + /* + * We start (4) here, appending text later: + * + * (3) append the stream of data 'text' to the B byte string resulting + * from step (2) + * (4) apply H to the stream generated in step (3) + */ + sha256_init(&ctx->sha); + sha256_update(&ctx->sha, k_ipad, HMAC_SHA256_BLOCKSIZE); + + /* + * (5) XOR (bitwise exclusive-OR) the B byte string computed in + * step (1) with opad + */ + xor_block_256(ctx->k_opad, IPAD^OPAD); +} + + +void hmac_sha512_init(struct hmac_sha512_ctx *ctx, + const void *k, size_t ksize) +{ + struct sha512 hashed_key; + /* We use k_opad as k_ipad temporarily. */ + uint64_t *k_ipad = ctx->k_opad; + + /* (keys longer than B bytes are first hashed using H) */ + if (ksize > HMAC_SHA512_BLOCKSIZE) { + sha512(&hashed_key, k, ksize); + k = &hashed_key; + ksize = sizeof(hashed_key); + } + + /* From RFC2104: + * + * (1) append zeros to the end of K to create a B byte string + * (e.g., if K is of length 20 bytes and B=64, then K will be + * appended with 44 zero bytes 0x00) + */ + memcpy(k_ipad, k, ksize); + memset((char *)k_ipad + ksize, 0, HMAC_SHA512_BLOCKSIZE - ksize); + + /* + * (2) XOR (bitwise exclusive-OR) the B byte string computed + * in step (1) with ipad + */ + xor_block_512(k_ipad, IPAD); + + /* + * We start (4) here, appending text later: + * + * (3) append the stream of data 'text' to the B byte string resulting + * from step (2) + * (4) apply H to the stream generated in step (3) + */ + sha512_init(&ctx->sha); + sha512_update(&ctx->sha, k_ipad, HMAC_SHA512_BLOCKSIZE); + + /* + * (5) XOR (bitwise exclusive-OR) the B byte string computed in + * step (1) with opad + */ + xor_block_512(ctx->k_opad, IPAD^OPAD); +} + + +void hmac_sha256_update(struct hmac_sha256_ctx *ctx, const void *p, size_t size) +{ + /* This is the appending-text part of this: + * + * (3) append the stream of data 'text' to the B byte string resulting + * from step (2) + * (4) apply H to the stream generated in step (3) + */ + sha256_update(&ctx->sha, p, size); +} + + +void hmac_sha512_update(struct hmac_sha512_ctx *ctx, const void *p, size_t size) +{ + sha512_update(&ctx->sha, p, size); +} + + +void hmac_sha256_done(struct hmac_sha256_ctx *ctx, + struct hmac_sha256 *hmac) +{ + /* (4) apply H to the stream generated in step (3) */ + sha256_done(&ctx->sha, &hmac->sha); + + /* + * (6) append the H result from step (4) to the B byte string + * resulting from step (5) + * (7) apply H to the stream generated in step (6) and output + * the result + */ + sha256_init(&ctx->sha); + sha256_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad)); + sha256_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha)); + sha256_done(&ctx->sha, &hmac->sha); +} + + +void hmac_sha512_done(struct hmac_sha512_ctx *ctx, + struct hmac_sha512 *hmac) +{ + /* (4) apply H to the stream generated in step (3) */ + sha512_done(&ctx->sha, &hmac->sha); + + /* + * (6) append the H result from step (4) to the B byte string + * resulting from step (5) + * (7) apply H to the stream generated in step (6) and output + * the result + */ + sha512_init(&ctx->sha); + sha512_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad)); + sha512_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha)); + sha512_done(&ctx->sha, &hmac->sha); +} + +#if 1 +void hmac_sha256(struct hmac_sha256 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize) +{ + struct hmac_sha256_ctx ctx; + + hmac_sha256_init(&ctx, k, ksize); + hmac_sha256_update(&ctx, d, dsize); + hmac_sha256_done(&ctx, hmac); +} + + +void hmac_sha512(struct hmac_sha512 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize) +{ + struct hmac_sha512_ctx ctx; + + hmac_sha512_init(&ctx, k, ksize); + hmac_sha512_update(&ctx, d, dsize); + hmac_sha512_done(&ctx, hmac); +} + + +#else +/* Direct mapping from MD5 example in RFC2104 */ +void hmac_sha256(struct hmac_sha256 *hmac, + const void *key, size_t key_len, + const void *text, size_t text_len) +{ + struct sha256_ctx context; + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + *//* start out by storing key in pads */ + unsigned char tk[32]; + int i; + + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + struct sha256_ctx tctx; + + sha256_init(&tctx); + sha256_update(&tctx, key, key_len); + sha256_done(&tctx, tk); + + key = tk; + key_len = 32; + } + bzero( k_ipad, sizeof k_ipad); + bzero( k_opad, sizeof k_opad); + bcopy( key, k_ipad, key_len); + bcopy( key, k_opad, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + sha256_init(&context); /* init context for 1st + * pass */ + sha256_update(&context, k_ipad, 64); /* start with inner pad */ + sha256_update(&context, text, text_len); /* then text of datagram */ + sha256_done(&context, &hmac->sha); /* finish up 1st pass */ + /* + * perform outer MD5 + */ + sha256_init(&context); /* init context for 2nd + * pass */ + sha256_update(&context, k_opad, 64); /* start with outer pad */ + sha256_update(&context, &hmac->sha, 32); /* then results of 1st + * hash */ + sha256_done(&context, &hmac->sha); /* finish up 2nd pass */ +} +#endif diff --git a/node_modules/lnsocket/hmac.h b/node_modules/lnsocket/hmac.h new file mode 100644 index 0000000..87952fd --- /dev/null +++ b/node_modules/lnsocket/hmac.h @@ -0,0 +1,116 @@ + +#ifndef CCAN_CRYPTO_HMAC_SHA256_H +#define CCAN_CRYPTO_HMAC_SHA256_H +/* BSD-MIT */ +#include +#include +#include "sha256.h" +#include "sha512.h" + +/* Number of bytes per block. */ +#define HMAC_SHA256_BLOCKSIZE 64 +#define HMAC_SHA512_BLOCKSIZE 128 + +/** + * struct hmac_sha256 - structure representing a completed HMAC. + */ +struct hmac_sha256 { + struct sha256 sha; +}; + + +struct hmac_sha512 { + struct sha512 sha; +}; + +/** + * hmac_sha256 - return hmac of an object with a key. + * @hmac: the hmac to fill in + * @k: pointer to the key, + * @ksize: the number of bytes pointed to by @k + * @d: pointer to memory, + * @dsize: the number of bytes pointed to by @d + */ +void hmac_sha256(struct hmac_sha256 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize); + +void hmac_sha512(struct hmac_sha512 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize); + +/** + * struct hmac_sha256_ctx - structure to store running context for hmac_sha256 + */ +struct hmac_sha256_ctx { + struct sha256_ctx sha; + uint64_t k_opad[HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t)]; +}; + + +struct hmac_sha512_ctx { + struct sha512_ctx sha; + uint64_t k_opad[HMAC_SHA512_BLOCKSIZE / sizeof(uint64_t)]; +}; + +/** + * hmac_sha256_init - initialize an HMAC_SHA256 context. + * @ctx: the hmac_sha256_ctx to initialize + * @k: pointer to the key, + * @ksize: the number of bytes pointed to by @k + * + * This must be called before hmac_sha256_update or hmac_sha256_done. + * + * If it was already initialized, this forgets anything which was + * hashed before. + * + * Example: + * static void hmac_all(const char *key, + * const char **arr, struct hmac_sha256 *hash) + * { + * size_t i; + * struct hmac_sha256_ctx ctx; + * + * hmac_sha256_init(&ctx, key, strlen(key)); + * for (i = 0; arr[i]; i++) + * hmac_sha256_update(&ctx, arr[i], strlen(arr[i])); + * hmac_sha256_done(&ctx, hash); + * } + */ +void hmac_sha256_init(struct hmac_sha256_ctx *ctx, + const void *k, size_t ksize); + +void hmac_sha512_init(struct hmac_sha512_ctx *ctx, + const void *k, size_t ksize); + + +/** + * hmac_sha256_update - include some memory in the hash. + * @ctx: the hmac_sha256_ctx to use + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * You can call this multiple times to hash more data, before calling + * hmac_sha256_done(). + */ +void hmac_sha256_update(struct hmac_sha256_ctx *ctx, + const void *p, size_t size); + +void hmac_sha512_update(struct hmac_sha512_ctx *ctx, + const void *p, size_t size); + +/** + * hmac_sha256_done - finish HMAC_SHA256 and return the hash + * @ctx: the hmac_sha256_ctx to complete + * @res: the hash to return. + * + * Note that @ctx is *destroyed* by this, and must be reinitialized. + * To avoid that, pass a copy instead. + */ +void hmac_sha256_done(struct hmac_sha256_ctx *hmac_sha256, + struct hmac_sha256 *res); + +void hmac_sha512_done(struct hmac_sha512_ctx *hmac_sha256, + struct hmac_sha512 *res); + +#endif /* CCAN_CRYPTO_HMAC_SHA256_H */ diff --git a/node_modules/lnsocket/index.js b/node_modules/lnsocket/index.js new file mode 100644 index 0000000..093f749 --- /dev/null +++ b/node_modules/lnsocket/index.js @@ -0,0 +1,11 @@ + +const Module = require("./dist/node/lnsocket.js") +const LNSocketReady = Module.lnsocket_init() + +async function load_lnsocket(opts) +{ + const LNSocket = await LNSocketReady + return new LNSocket(opts) +} + +module.exports = load_lnsocket diff --git a/node_modules/lnsocket/lnrpc.c b/node_modules/lnsocket/lnrpc.c new file mode 100644 index 0000000..d7e3cb1 --- /dev/null +++ b/node_modules/lnsocket/lnrpc.c @@ -0,0 +1,114 @@ + +#include + +#include "lnsocket.h" +#include "endian.h" +#include "typedefs.h" +#include "commando.h" + +#include +#include + +#include + +int usage() +{ + printf("lnrpc [params (json string)]\n\n"); + printf("currently supports commando for clightning, but potentially more rpc types in the future!\n"); + return 0; +} + +int main(int argc, const char *argv[]) +{ + static u8 msgbuf[4096]; + u8 *buf; + struct lnsocket *ln; + fd_set set; + struct timeval timeout = {0}; + + char *timeout_str; + u16 len, msgtype; + int ok = 1; + int socket, rv; + int verbose = getenv("VERBOSE") != 0; + //int verbose = 1; + + timeout_str = getenv("LNRPC_TIMEOUT"); + int timeout_ms = timeout_str ? atoi(timeout_str) : 5000; + + timeout.tv_sec = timeout_ms / 1000; + timeout.tv_usec = (timeout_ms % 1000) * 1000; + + FD_ZERO(&set); /* clear the set */ + + if (argc < 5) + return usage(); + + ln = lnsocket_create(); + assert(ln); + + lnsocket_genkey(ln); + + const char *nodeid = argv[1]; + const char *host = argv[2]; + const char *rune = argv[3]; + const char *method = argv[4]; + const char *params = argc < 7 ? argv[5] : NULL; + + if (!(ok = lnsocket_connect(ln, nodeid, host))) + goto done; + + if (!(ok = lnsocket_fd(ln, &socket))) + goto done; + + FD_SET(socket, &set); /* add our file descriptor to the set */ + + if (!(ok = lnsocket_perform_init(ln))) + goto done; + + if (verbose) + fprintf(stderr, "init success\n"); + + if (!(ok = len = commando_make_rpc_msg(method, params, rune, 1, msgbuf, sizeof(msgbuf)))) + goto done; + + if (!(ok = lnsocket_write(ln, msgbuf, len))) + goto done; + + if (verbose) + fprintf(stderr, "waiting for response...\n"); + + while (1) { + rv = select(socket + 1, &set, NULL, NULL, &timeout); + + if (rv == -1) { + perror("select"); + ok = 0; + goto done; + } else if (rv == 0) { + fprintf(stderr, "error: rpc request timeout\n"); + ok = 0; + goto done; + } + + if (!(ok = lnsocket_recv(ln, &msgtype, &buf, &len))) + goto done; + + switch (msgtype) { + case COMMANDO_REPLY_TERM: + printf("%.*s\n", len - 8, buf + 8); + goto done; + case COMMANDO_REPLY_CONTINUES: + printf("%.*s", len - 8, buf + 8); + continue; + default: + // ignore extra interleaved messages which can happen + continue; + } + } + +done: + lnsocket_print_errors(ln); + lnsocket_destroy(ln); + return !ok; +} diff --git a/node_modules/lnsocket/lnsocket.c b/node_modules/lnsocket/lnsocket.c new file mode 100644 index 0000000..471bde4 --- /dev/null +++ b/node_modules/lnsocket/lnsocket.c @@ -0,0 +1,632 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "handshake.h" +#include "error.h" +#include "crypto.h" +#include "endian.h" +#include "bigsize.h" +#include "compiler.h" +#include "lnsocket_internal.h" +#include "lnsocket.h" + +#define array_len(x) (sizeof(x)/sizeof(x[0])) + +#define MSGBUF_MEM (65536*2) +#define ERROR_MEM 4096 +#define DEFAULT_TIMEOUT 3000 + +int push_error(struct lnsocket *lnsocket, const char *err); + +static int char_to_hex(unsigned char *val, char c) +{ + if (c >= '0' && c <= '9') { + *val = c - '0'; + return 1; + } + if (c >= 'a' && c <= 'f') { + *val = c - 'a' + 10; + return 1; + } + if (c >= 'A' && c <= 'F') { + *val = c - 'A' + 10; + return 1; + } + return 0; +} + + +static int hex_decode(const char *str, size_t slen, void *buf, size_t bufsize) +{ + unsigned char v1, v2; + unsigned char *p = buf; + + while (slen > 1) { + if (!char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1])) + return 0; + if (!bufsize) + return 0; + *(p++) = (v1 << 4) | v2; + str += 2; + slen -= 2; + bufsize--; + } + return slen == 0 && bufsize == 0; +} + + +int parse_node_id(const char *str, struct node_id *dest) +{ + return hex_decode(str, strlen(str), dest->k, sizeof(*dest)); +} + +int pubkey_from_node_id(secp256k1_context *secp, struct pubkey *key, + const struct node_id *id) +{ + return secp256k1_ec_pubkey_parse(secp, &key->pubkey, + memcheck(id->k, sizeof(id->k)), + sizeof(id->k)); +} + + +static int read_all(int fd, void *data, size_t size) +{ + while (size) { + ssize_t done; + + done = read(fd, data, size); + if (done < 0 && errno == EINTR) + continue; + if (done <= 0) + return 0; + data = (char *)data + done; + size -= done; + } + + return 1; +} + +int EXPORT lnsocket_make_default_initmsg(unsigned char *msgbuf, int buflen) +{ + u8 global_features[2] = {0}; + u8 features[5] = {0}; + u16 len; + + /* + struct tlv network_tlv; + u8 tlvbuf[1024]; + const u8 genesis_block[] = { + 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, 0xc1, 0xa6, 0xa2, 0x46, + 0xae, 0x63, 0xf7, 0x4f, 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, + 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + const u8 *blockids[] = { genesis_block }; + + if (!lnsocket_make_network_tlv(tlvbuf, sizeof(tlvbuf), blockids, 1, + &network_tlv)) + return 0; + + + const struct tlv *init_tlvs[] = { &network_tlv } ; + */ + + const struct tlv *init_tlvs[] = { } ; + + if (!lnsocket_make_init_msg(msgbuf, buflen, + global_features, sizeof(global_features), + features, sizeof(features), + init_tlvs, 0, + &len)) + return 0; + + return (int)len; +} + +/* +static void print_hex(u8 *bytes, int len) { + int i; + for (i = 0; i < len; ++i) { + printf("%02x", bytes[i]); + } +} +*/ + +int lnsocket_perform_init(struct lnsocket *ln) +{ + u8 msgbuf[1024]; + u16 len; + u8 *buf; + + // read the init message from the other side and ignore it + if (!lnsocket_read(ln, &buf, &len)) + return 0; + + if (!(len = lnsocket_make_default_initmsg(msgbuf, sizeof(msgbuf)))) + return 0; + + if (!lnsocket_write(ln, msgbuf, len)) + return 0; + + return 1; +} + +// simple helper that pushes a message type and payload +int lnsocket_send(struct lnsocket *ln, unsigned short msg_type, const unsigned char *payload, unsigned short payload_len) +{ + reset_cursor(&ln->msgbuf); + + if (!cursor_push_u16(&ln->msgbuf, msg_type)) + return note_error(&ln->errs, "could not write type to msgbuf?"); + + if (!cursor_push(&ln->msgbuf, payload, payload_len)) + return note_error(&ln->errs, "payload too big"); + + return lnsocket_write(ln, ln->msgbuf.start, ln->msgbuf.p - ln->msgbuf.start); +} + +// simple helper that receives a message type and payload +int lnsocket_recv(struct lnsocket *ln, u16 *msg_type, unsigned char **payload, u16 *payload_len) +{ + struct cursor cur; + u8 *msg; + u16 msglen; + + if (!lnsocket_read(ln, &msg, &msglen)) + return 0; + + make_cursor(msg, msg + msglen, &cur); + + if (!cursor_pull_u16(&cur, msg_type)) + return note_error(&ln->errs, "could not read msgtype"); + + *payload_len = msglen - 2; + *payload = cur.p; + + if (*payload + *payload_len > cur.end) + return note_error(&ln->errs, "recv buffer overflow?"); + + return 1; +} + +int EXPORT lnsocket_decrypt(struct lnsocket *ln, unsigned char *packet, int size) +{ + struct cursor enc, dec; + + make_cursor(packet, packet + size, &enc); + reset_cursor(&ln->msgbuf); + if (!cursor_slice(&ln->msgbuf, &dec, size - 16)) + return note_error(&ln->errs, "out of memory: %d + %d = %d > %d", + ln->msgbuf.end - ln->msgbuf.p, size, + ln->msgbuf.end - ln->msgbuf.p + size, + MSGBUF_MEM + ); + + if (!cryptomsg_decrypt_body(&ln->crypto_state, + enc.start, enc.end - enc.start, + dec.start, dec.end - dec.start)) + return note_error(&ln->errs, "error decrypting body"); + + return dec.end - dec.start; +} + +// this is used in js +int EXPORT lnsocket_decrypt_header(struct lnsocket *ln, unsigned char *hdr) +{ + u16 size = 0; + if (!cryptomsg_decrypt_header(&ln->crypto_state, hdr, &size)) + return note_error(&ln->errs, + "Failed hdr decrypt with rn=%"PRIu64, + ln->crypto_state.rn-1); + return size; +} + +int lnsocket_read(struct lnsocket *ln, unsigned char **buf, unsigned short *len) +{ + struct cursor enc, dec; + u8 hdr[18]; + u16 size; + + reset_cursor(&ln->errs.cur); + reset_cursor(&ln->msgbuf); + + if (!read_all(ln->socket, hdr, sizeof(hdr))) + return note_error(&ln->errs,"Failed reading header: %s", + strerror(errno)); + + if (!cryptomsg_decrypt_header(&ln->crypto_state, hdr, &size)) + return note_error(&ln->errs, + "Failed hdr decrypt with rn=%"PRIu64, + ln->crypto_state.rn-1); + + if (!cursor_slice(&ln->msgbuf, &enc, size + 16)) + return note_error(&ln->errs, "out of memory"); + + if (!cursor_slice(&ln->msgbuf, &dec, size)) + return note_error(&ln->errs, "out of memory: %d + %d = %d > %d", + ln->msgbuf.end - ln->msgbuf.p, size, + ln->msgbuf.end - ln->msgbuf.p + size, + MSGBUF_MEM + ); + + if (!read_all(ln->socket, enc.p, enc.end - enc.start)) + return note_error(&ln->errs, "Failed reading body: %s", + strerror(errno)); + + if (!cryptomsg_decrypt_body(&ln->crypto_state, + enc.start, enc.end - enc.start, + dec.start, dec.end - dec.start)) + return note_error(&ln->errs, "error decrypting body"); + + *buf = dec.start; + *len = dec.end - dec.start; + + return 1; +} + +static int highest_byte(unsigned char *buf, int buflen) +{ + int i, highest; + for (i = 0, highest = 0; i < buflen; i++) { + if (buf[i] != 0) + highest = i; + } + return highest; +} + +#define max(a,b) ((a) > (b) ? (a) : (b)) +int lnsocket_set_feature_bit(unsigned char *buf, int buflen, int *newlen, unsigned int bit) +{ + if (newlen == NULL) + return 0; + + if (bit / 8 >= buflen) + return 0; + + *newlen = max(highest_byte(buf, buflen), (bit / 8) + 1); + buf[*newlen - 1 - bit / 8] |= (1 << (bit % 8)); + + return 1; +} +#undef max + +int cursor_push_tlv(struct cursor *cur, const struct tlv *tlv) +{ + /* BOLT #1: + * + * The sending node: + ... + * - MUST minimally encode `type` and `length`. + */ + return cursor_push_bigsize(cur, tlv->type) && + cursor_push_bigsize(cur, tlv->length) && + cursor_push(cur, tlv->value, tlv->length); +} + +int cursor_push_tlvs(struct cursor *cur, const struct tlv **tlvs, int n_tlvs) +{ + int i; + for (i = 0; i < n_tlvs; i++) { + if (!cursor_push_tlv(cur, tlvs[i])) + return 0; + } + + return 1; +} + +int lnsocket_make_network_tlv(unsigned char *buf, int buflen, + const unsigned char **blockids, int num_blockids, + struct tlv *tlv_out) +{ + struct cursor cur; + + if (!tlv_out) + return 0; + + tlv_out->type = 1; + tlv_out->value = buf; + + make_cursor(buf, buf + buflen, &cur); + + for (size_t i = 0; i < num_blockids; i++) { + if (!cursor_push(&cur, memcheck(blockids[i], 32), 32)) + return 0; + } + + tlv_out->length = cur.p - cur.start; + return 1; +} + +int lnsocket_make_ping_msg(unsigned char *buf, int buflen, u16 num_pong_bytes, u16 ignored_bytes) +{ + struct cursor msg; + int i; + + make_cursor(buf, buf + buflen, &msg); + + if (!cursor_push_u16(&msg, WIRE_PING)) + return 0; + if (!cursor_push_u16(&msg, num_pong_bytes)) + return 0; + if (!cursor_push_u16(&msg, ignored_bytes)) + return 0; + for (i = 0; i < ignored_bytes; i++) { + if (!cursor_push_byte(&msg, 0)) + return 0; + } + + return msg.p - msg.start; +} + +int lnsocket_make_init_msg(unsigned char *buf, int buflen, + const unsigned char *globalfeatures, u16 gflen, + const unsigned char *features, u16 flen, + const struct tlv **tlvs, + unsigned short num_tlvs, + unsigned short *outlen) +{ + struct cursor msg; + + make_cursor(buf, buf + buflen, &msg); + + if (!cursor_push_u16(&msg, WIRE_INIT)) + return 0; + + if (!cursor_push_u16(&msg, gflen)) + return 0; + + if (!cursor_push(&msg, globalfeatures, gflen)) + return 0; + + if (!cursor_push_u16(&msg, flen)) + return 0; + + if (!cursor_push(&msg, features, flen)) + return 0; + + if (!cursor_push_tlvs(&msg, tlvs, num_tlvs)) + return 0; + + *outlen = msg.p - msg.start; + + return 1; +} + +unsigned char* EXPORT lnsocket_msgbuf(struct lnsocket *ln) +{ + return ln->msgbuf.start; +} + +int EXPORT lnsocket_encrypt(struct lnsocket *ln, const u8 *msg, unsigned short msglen) +{ + ssize_t outcap; + size_t outlen; + + // this is just temporary so we don't need to move the memory cursor + reset_cursor(&ln->msgbuf); + + u8 *out = ln->msgbuf.start; + outcap = ln->msgbuf.end - ln->msgbuf.start; + +#ifndef __EMSCRIPTEN__ + if (!ln->socket) + return note_error(&ln->errs, "not connected"); +#endif + + if (outcap <= 0) + return note_error(&ln->errs, "out of memory"); + + if (!cryptomsg_encrypt_msg(&ln->crypto_state, msg, msglen, out, &outlen, (size_t)outcap)) + return note_error(&ln->errs, "encrypt message failed, out of memory"); + + return outlen; +} + +int lnsocket_write(struct lnsocket *ln, const u8 *msg, unsigned short msglen) +{ + ssize_t writelen, outlen; + u8 *out = ln->msgbuf.start; + + if (!(outlen = lnsocket_encrypt(ln, msg, msglen))) + return 0; + + if ((writelen = write(ln->socket, out, outlen)) != outlen) + return note_error(&ln->errs, + "write failed. wrote %ld bytes, expected %ld %s", + writelen, outlen, + writelen < 0 ? strerror(errno) : ""); + + return 1; +} + +struct lnsocket *lnsocket_create() +{ + struct cursor mem; + int memory = MSGBUF_MEM + ERROR_MEM + sizeof(struct lnsocket); + + void *arena = malloc(memory); + + if (!arena) + return NULL; + + make_cursor(arena, arena + memory, &mem); + struct lnsocket *lnsocket = cursor_alloc(&mem, sizeof(*lnsocket)); + + if (!lnsocket) + return NULL; + + lnsocket->secp = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | + SECP256K1_CONTEXT_SIGN); + + if (!cursor_slice(&mem, &lnsocket->msgbuf, MSGBUF_MEM)) + return NULL; + + if (!cursor_slice(&mem, &lnsocket->errs.cur, ERROR_MEM)) + return NULL; + + lnsocket->errs.enabled = 1; + + lnsocket->mem = mem; + return lnsocket; +} + +void lnsocket_destroy(struct lnsocket *lnsocket) +{ + if (!lnsocket) + return; + + secp256k1_context_destroy(lnsocket->secp); + free(lnsocket->mem.start); +} + +int is_zero(void *vp, int size) +{ + u8 *p = (u8*)vp; + const u8 *start = p; + + for (; p < start+size; p++) { + if (*p != 0) + return 0; + } + return 1; +} + +static int io_fd_block(int fd, int block) +{ + int flags = fcntl(fd, F_GETFL); + + if (flags == -1) + return 0; + + if (block) + flags &= ~O_NONBLOCK; + else + flags |= O_NONBLOCK; + + return fcntl(fd, F_SETFL, flags) != -1; +} + +const char *parse_port(char *host) +{ + int i, len; + + len = strlen(host); + + for (i = 0; i < len; i++) { + if (host[i] == ':') { + host[i] = 0; + return &host[i+1]; + } + } + + + return NULL; +} + +int lnsocket_connect_with(struct lnsocket *ln, const char *node_id, const char *host, int timeout_ms) +{ + int ret; + struct addrinfo *addrs = NULL; + struct pubkey their_id; + struct node_id their_node_id; + struct timeval timeout = {0}; + char onlyhost[strlen(host)+1]; + strncpy(onlyhost, host, sizeof(onlyhost)); + fd_set set; + + timeout.tv_sec = timeout_ms / 1000; + timeout.tv_usec = (timeout_ms % 1000) * 1000; + + FD_ZERO(&set); /* clear the set */ + + if (is_zero(&ln->key, sizeof(ln->key))) + return note_error(&ln->errs, "key not initialized, use lnsocket_set_key() or lnsocket_genkey()"); + + // convert node_id string to bytes + if (!parse_node_id(node_id, &their_node_id)) + return note_error(&ln->errs, "failed to parse node id"); + + // encode node_id bytes to secp pubkey + if (!pubkey_from_node_id(ln->secp, &their_id, &their_node_id)) + return note_error(&ln->errs, "failed to convert node_id to pubkey"); + + // parse ip into addrinfo + const char *port = parse_port(onlyhost); + if ((ret = getaddrinfo(onlyhost, port ? port : "9735", NULL, &addrs)) || !addrs) + return note_error(&ln->errs, "%s", gai_strerror(ret)); + + // create our network socket for comms + if (!(ln->socket = socket(AF_INET, SOCK_STREAM, 0))) + return note_error(&ln->errs, "creating socket failed"); + + FD_SET(ln->socket, &set); /* add our file descriptor to the set */ + + if (!io_fd_block(ln->socket, 0)) + return note_error(&ln->errs, "failed setting socket to non-blocking"); + + // connect to the node! + connect(ln->socket, addrs->ai_addr, addrs->ai_addrlen); + + if (!io_fd_block(ln->socket, 1)) + return note_error(&ln->errs, "failed setting socket to blocking"); + + ret = select(ln->socket + 1, NULL, &set, NULL, &timeout); + if (ret == -1) { + return note_error(&ln->errs, "select error"); + } else if (ret == 0) { + return note_error(&ln->errs, "connection timeout"); + } + + // prepare some data for ACT1 + new_handshake(ln->secp, &ln->handshake, &their_id); + + ln->handshake.side = INITIATOR; + ln->handshake.their_id = their_id; + + // let's do this! + return act_one_initiator(ln); +} + +int lnsocket_connect(struct lnsocket *ln, const char *node_id, const char *host) +{ + return lnsocket_connect_with(ln, node_id, host, DEFAULT_TIMEOUT); +} + +int lnsocket_fd(struct lnsocket *ln, int *fd) +{ + *fd = ln->socket; + return 1; +} + +void * lnsocket_secp(struct lnsocket *ln) +{ + return ln->secp; +} + +void lnsocket_genkey(struct lnsocket *ln) +{ + ln->key = generate_key(ln->secp); +} + +void lnsocket_print_errors(struct lnsocket *ln) +{ + print_error_backtrace(&ln->errs); +} + + diff --git a/node_modules/lnsocket/lnsocket.h b/node_modules/lnsocket/lnsocket.h new file mode 100644 index 0000000..10a326b --- /dev/null +++ b/node_modules/lnsocket/lnsocket.h @@ -0,0 +1,95 @@ +#ifndef LNSOCKET_H +#define LNSOCKET_H + +#include +#include + +struct lnsocket; + +#ifdef __EMSCRIPTEN__ + #include + #define EXPORT EMSCRIPTEN_KEEPALIVE +#else + #define EXPORT +#endif + +enum peer_wire { + WIRE_INIT = 16, + WIRE_ERROR = 17, + WIRE_WARNING = 1, + WIRE_PING = 18, + WIRE_PONG = 19, + WIRE_TX_ADD_INPUT = 66, + WIRE_TX_ADD_OUTPUT = 67, + WIRE_TX_REMOVE_INPUT = 68, + WIRE_TX_REMOVE_OUTPUT = 69, + WIRE_TX_COMPLETE = 70, + WIRE_TX_SIGNATURES = 71, + WIRE_OPEN_CHANNEL = 32, + WIRE_ACCEPT_CHANNEL = 33, + WIRE_FUNDING_CREATED = 34, + WIRE_FUNDING_SIGNED = 35, + WIRE_FUNDING_LOCKED = 36, + WIRE_OPEN_CHANNEL2 = 64, + WIRE_ACCEPT_CHANNEL2 = 65, + WIRE_INIT_RBF = 72, + WIRE_ACK_RBF = 73, + WIRE_SHUTDOWN = 38, + WIRE_CLOSING_SIGNED = 39, + WIRE_UPDATE_ADD_HTLC = 128, + WIRE_UPDATE_FULFILL_HTLC = 130, + WIRE_UPDATE_FAIL_HTLC = 131, + WIRE_UPDATE_FAIL_MALFORMED_HTLC = 135, + WIRE_COMMITMENT_SIGNED = 132, + WIRE_REVOKE_AND_ACK = 133, + WIRE_UPDATE_FEE = 134, + WIRE_UPDATE_BLOCKHEIGHT = 137, + WIRE_CHANNEL_REESTABLISH = 136, + WIRE_ANNOUNCEMENT_SIGNATURES = 259, + WIRE_CHANNEL_ANNOUNCEMENT = 256, + WIRE_NODE_ANNOUNCEMENT = 257, + WIRE_CHANNEL_UPDATE = 258, + WIRE_QUERY_SHORT_CHANNEL_IDS = 261, + WIRE_REPLY_SHORT_CHANNEL_IDS_END = 262, + WIRE_QUERY_CHANNEL_RANGE = 263, + WIRE_REPLY_CHANNEL_RANGE = 264, + WIRE_GOSSIP_TIMESTAMP_FILTER = 265, + WIRE_OBS2_ONION_MESSAGE = 387, + WIRE_ONION_MESSAGE = 513, +}; + +/* A single TLV field, consisting of the data and its associated metadata. */ +struct tlv { + uint64_t type; + size_t length; + unsigned char *value; +}; + +struct lnsocket EXPORT *lnsocket_create(); + +/* messages */ + +int lnsocket_make_network_tlv(unsigned char *buf, int buflen, const unsigned char **blockids, int num_blockids, struct tlv *tlv_out); +int EXPORT lnsocket_make_ping_msg(unsigned char *buf, int buflen, unsigned short num_pong_bytes, unsigned short ignored_bytes); +int lnsocket_make_init_msg(unsigned char *buf, int buflen, const unsigned char *globalfeatures, unsigned short gflen, const unsigned char *features, unsigned short flen, const struct tlv **tlvs, unsigned short num_tlvs, unsigned short *outlen); + +int lnsocket_perform_init(struct lnsocket *ln); + +int lnsocket_connect(struct lnsocket *, const char *node_id, const char *host); + +int lnsocket_fd(struct lnsocket *, int *fd); +int lnsocket_write(struct lnsocket *, const unsigned char *msg, unsigned short msg_len); +int lnsocket_read(struct lnsocket *, unsigned char **buf, unsigned short *len); + +int lnsocket_send(struct lnsocket *, unsigned short msg_type, const unsigned char *payload, unsigned short payload_len); +int lnsocket_recv(struct lnsocket *, unsigned short *msg_type, unsigned char **payload, unsigned short *payload_len); + +void* EXPORT lnsocket_secp(struct lnsocket *); +void EXPORT lnsocket_genkey(struct lnsocket *); +void EXPORT lnsocket_destroy(struct lnsocket *); +void EXPORT lnsocket_print_errors(struct lnsocket *); +int EXPORT lnsocket_make_default_initmsg(unsigned char *msgbuf, int buflen); +int EXPORT lnsocket_encrypt(struct lnsocket *ln, const unsigned char *msg, unsigned short msglen); +int EXPORT lnsocket_decrypt_header(struct lnsocket *ln, unsigned char *hdr); + +#endif /* LNSOCKET_H */ diff --git a/node_modules/lnsocket/lnsocket_internal.h b/node_modules/lnsocket/lnsocket_internal.h new file mode 100644 index 0000000..89298dd --- /dev/null +++ b/node_modules/lnsocket/lnsocket_internal.h @@ -0,0 +1,26 @@ +#ifndef LNSOCKET_INTERNAL_H +#define LNSOCKET_INTERNAL_H + +#include "crypto.h" +#include "error.h" +#include "handshake.h" + +struct lnsocket { + const char *errors[8]; + struct cursor mem; + struct cursor msgbuf; + struct errors errs; + int num_errors; + int socket; + struct keypair key; + struct pubkey responder_id; + struct handshake handshake; + struct crypto_state crypto_state; + secp256k1_context *secp; +}; + +int parse_node_id(const char *str, struct node_id *dest); +int pubkey_from_node_id(secp256k1_context *secp, struct pubkey *key, const struct node_id *id); +int is_zero(void *vp, int size); + +#endif /* LNSOCKET_INTERNAL_H */ diff --git a/node_modules/lnsocket/lnsocket_lib.js b/node_modules/lnsocket/lnsocket_lib.js new file mode 100644 index 0000000..6e8413f --- /dev/null +++ b/node_modules/lnsocket/lnsocket_lib.js @@ -0,0 +1,370 @@ + +async function lnsocket_init() { + const module = await Module() + + function SocketImpl(host) { + if (!(this instanceof SocketImpl)) + return new SocketImpl(host) + + if (typeof WebSocket !== 'undefined') { + console.log("WebSocket", typeof WebSocket) + const ok = host.startsWith("ws://") || host.startsWith("wss://") + if (!ok) + throw new Error("host must start with ws:// or wss://") + const ws = new WebSocket(host) + ws.ondata = function(fn) { + ws.onmessage = (v) => { + const data = v.data.arrayBuffer() + fn(data) + } + } + return ws + } + + // + // we're in nodejs + // + const net = require('net') + let [hostname,port] = host.split(":") + port = +port || 9735 + const socket = net.createConnection(port, hostname, () => { + socket.emit("open") + }) + socket.addEventListener = socket.on.bind(socket) + + if (socket.onmessage) + throw new Error("socket already has onmessage?") + + socket.ondata = (fn) => { + socket.on('data', fn) + } + + socket.close = () => { + socket.destroy() + } + + if (socket.send) + throw new Error("socket already has send?") + + socket.send = function socket_send(data) { + return new Promise((resolve, reject) => { + socket.write(data, resolve) + }); + } + + return socket + } + + const ACT_ONE_SIZE = 50 + const ACT_TWO_SIZE = 50 + const ACT_THREE_SIZE = 66 + const DEFAULT_TIMEOUT = 15000 + + const COMMANDO_REPLY_CONTINUES = 0x594b + const COMMANDO_REPLY_TERM = 0x594d + + const lnsocket_create = module.cwrap("lnsocket_create", "number") + const lnsocket_destroy = module.cwrap("lnsocket_destroy", "number") + const lnsocket_encrypt = module.cwrap("lnsocket_encrypt", "number", ["int", "array", "int", "int"]) + const lnsocket_decrypt = module.cwrap("lnsocket_decrypt", "number", ["int", "array", "int"]) + const lnsocket_decrypt_header = module.cwrap("lnsocket_decrypt_header", "number", ["number", "array"]) + const lnsocket_msgbuf = module.cwrap("lnsocket_msgbuf", "number", ["int"]) + const lnsocket_act_one = module.cwrap("lnsocket_act_one", "number", ["number", "string"]) + const lnsocket_act_two = module.cwrap("lnsocket_act_two", "number", ["number", "array"]) + const lnsocket_print_errors = module.cwrap("lnsocket_print_errors", "int") + const lnsocket_genkey = module.cwrap("lnsocket_genkey", "int") + const lnsocket_make_default_initmsg = module.cwrap("lnsocket_make_default_initmsg", "int", ["int", "int"]) + const lnsocket_make_ping_msg = module.cwrap("lnsocket_make_ping_msg", "int", ["int", "int", "int", "int"]) + const commando_make_rpc_msg = module.cwrap("commando_make_rpc_msg", "int", ["string", "string", "string", "number", "int", "int"]) + + function concat_u8_arrays(arrays) { + // sum of individual array lengths + let totalLength = arrays.reduce((acc, value) => + acc + (value.length || value.byteLength) + , 0); + + if (!arrays.length) return null; + + let result = new Uint8Array(totalLength); + + let length = 0; + for (let array of arrays) { + if (array instanceof ArrayBuffer) + result.set(new Uint8Array(array), length); + else + result.set(array, length); + + length += (array.length || array.byteLength); + } + + return result; + } + + function parse_msgtype(buf) { + return buf[0] << 8 | buf[1] + } + + function wasm_mem(ptr, size) { + return new Uint8Array(module.HEAPU8.buffer, ptr, size); + } + + function LNSocket(opts) { + if (!(this instanceof LNSocket)) + return new LNSocket(opts) + + this.opts = opts || { + timeout: DEFAULT_TIMEOUT + } + this.queue = [] + this.ln = lnsocket_create() + } + + LNSocket.prototype.queue_recv = function() { + let self = this + return new Promise((resolve, reject) => { + const checker = setInterval(() => { + const val = self.queue.shift() + if (val) { + clearInterval(checker) + resolve(val) + } else if (!self.connected) { + clearInterval(checker) + reject() + } + }, 5); + }) + } + + LNSocket.prototype.print_errors = function _lnsocket_print_errors() { + lnsocket_print_errors(this.ln) + } + + LNSocket.prototype.genkey = function _lnsocket_genkey() { + lnsocket_genkey(this.ln) + } + + LNSocket.prototype.act_one_data = function _lnsocket_act_one(node_id) { + const act_one_ptr = lnsocket_act_one(this.ln, node_id) + if (act_one_ptr === 0) + return null + return wasm_mem(act_one_ptr, ACT_ONE_SIZE) + } + + LNSocket.prototype.act_two = function _lnsocket_act_two(act2) { + const act_three_ptr = lnsocket_act_two(this.ln, new Uint8Array(act2)) + if (act_three_ptr === 0) { + this.print_errors() + return null + } + return wasm_mem(act_three_ptr, ACT_THREE_SIZE) + } + + LNSocket.prototype.connect = async function lnsocket_connect(node_id, host) { + await handle_connect(this, node_id, host) + + const act1 = this.act_one_data(node_id) + this.ws.send(act1) + const act2 = await this.read_all(ACT_TWO_SIZE) + if (act2.length != ACT_TWO_SIZE) { + throw new Error(`expected act2 to be ${ACT_TWO_SIZE} long, got ${act2.length}`) + } + const act3 = this.act_two(act2) + this.ws.send(act3) + } + + LNSocket.prototype.connect_and_init = async function _connect_and_init(node_id, host) { + await this.connect(node_id, host) + await this.perform_init() + } + + LNSocket.prototype.read_all = async function read_all(n) { + let count = 0 + let chunks = [] + if (!this.connected) + throw new Error("read_all: not connected") + while (true) { + let res = await this.queue_recv() + + const remaining = n - count + + if (res.byteLength > remaining) { + chunks.push(res.slice(0, remaining)) + this.queue.unshift(res.slice(remaining)) + break + } else if (res.byteLength === remaining) { + chunks.push(res) + break + } + + chunks.push(res) + count += res.byteLength + } + + return concat_u8_arrays(chunks) + } + + LNSocket.prototype.read_header = async function read_header() { + const header = await this.read_all(18) + if (header.length != 18) + throw new Error("Failed to read header") + return lnsocket_decrypt_header(this.ln, header) + } + + LNSocket.prototype.rpc = async function lnsocket_rpc(opts) { + const msg = this.make_commando_msg(opts) + this.write(msg) + const res = await this.read_all_rpc() + return JSON.parse(res) + } + + LNSocket.prototype.recv = async function lnsocket_recv() { + const msg = await this.read() + const msgtype = parse_msgtype(msg.slice(0,2)) + const res = [msgtype, msg.slice(2)] + return res + } + + LNSocket.prototype.read_all_rpc = async function read_all_rpc() { + let chunks = [] + while (true) { + const [typ, msg] = await this.recv() + switch (typ) { + case COMMANDO_REPLY_TERM: + chunks.push(msg.slice(8)) + return new TextDecoder().decode(concat_u8_arrays(chunks)); + case COMMANDO_REPLY_CONTINUES: + chunks.push(msg.slice(8)) + break + default: + console.log("got unknown type", typ) + continue + } + } + } + + LNSocket.prototype.make_commando_msg = function _lnsocket_make_commando_msg(opts) { + const buflen = 4096 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + const params = JSON.stringify(opts.params||{}) + if (!(len = commando_make_rpc_msg(opts.method, params, opts.rune, + 0, buf, buflen))) { + throw new Error("couldn't make commando msg"); + } + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.make_ping_msg = function _lnsocket_make_ping_msg(num_pong_bytes=1, ignored_bytes=1) { + const buflen = 32 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + if (!(len = lnsocket_make_ping_msg(buf, buflen, num_pong_bytes, ignored_bytes))) + throw new Error("couldn't make ping msg"); + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.encrypt = function _lnsocket_encrypt(dat) { + const len = lnsocket_encrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("encrypt error") + } + const enc = wasm_mem(lnsocket_msgbuf(this.ln), len) + return enc + } + + LNSocket.prototype.decrypt = function _lnsocket_decrypt(dat) { + const len = lnsocket_decrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("decrypt error") + } + return wasm_mem(lnsocket_msgbuf(this.ln), len) + } + + LNSocket.prototype.write = function _lnsocket_write(dat) { + this.ws.send(this.encrypt(dat)) + } + + LNSocket.prototype.read = async function _lnsocket_read() { + const size = await this.read_header() + const enc = await this.read_all(size+16) + return this.decrypt(enc) + } + + LNSocket.prototype.make_default_initmsg = function _lnsocket_make_default_initmsg() { + const buflen = 1024 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + if (!(len = lnsocket_make_default_initmsg(buf, buflen))) + throw new Error("couldn't make initmsg"); + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.perform_init = async function lnsocket_connect() { + await this.read() + const our_init = this.make_default_initmsg() + this.write(our_init) + } + + LNSocket.prototype.ping_pong = async function lnsocket_ping_pong() { + const pingmsg = this.make_ping_msg() + this.write(pingmsg) + return await this.read() + } + + LNSocket.prototype.disconnect = function lnsocket_disconnect() { + if (this.connected === true && this.ws) { + this.ws.close() + return true + } + return false + } + + LNSocket.prototype.destroy = function _lnsocket_destroy() { + this.disconnect() + lnsocket_destroy(this.ln) + } + + function handle_connect(ln, node_id, host) { + const ws = new SocketImpl(host) + return new Promise((resolve, reject) => { + const timeout = ln.opts.timeout || DEFAULT_TIMEOUT + const timer = setTimeout(reject, timeout); + + ws.ondata((v) => { + ln.queue.push(v) + }); + + ws.addEventListener('open', function(ev) { + ln.ws = ws + ln.connected = true + clearTimeout(timer) + resolve(ws) + }); + + ws.addEventListener('close', function(ev) { + ln.connected = false + }); + }) + } + + return LNSocket +} + +Module.init = Module.lnsocket_init = lnsocket_init diff --git a/node_modules/lnsocket/lnsocket_pre.js b/node_modules/lnsocket/lnsocket_pre.js new file mode 100644 index 0000000..35fe441 --- /dev/null +++ b/node_modules/lnsocket/lnsocket_pre.js @@ -0,0 +1,24 @@ +Module.getRandomValue = (function() { + const window_ = "object" === typeof window ? window : this + const crypto_ = typeof window_.crypto !== "undefined" ? window_.crypto : window_.msCrypto; + + let randomBytesNode + if (!crypto_) { + randomBytesNode = require('crypto').randomBytes + fn = randomValuesNode + } else { + fn = randomValuesStandard + } + + function randomValuesNode() { + return randomBytesNode(1)[0] >>> 0 + } + + function randomValuesStandard() { + var buf = new Uint32Array(1); + crypto_.getRandomValues(buf); + return buf[0] >>> 0; + }; + + return fn +})() diff --git a/node_modules/lnsocket/lnsocket_wasm.c b/node_modules/lnsocket/lnsocket_wasm.c new file mode 100644 index 0000000..28160c9 --- /dev/null +++ b/node_modules/lnsocket/lnsocket_wasm.c @@ -0,0 +1,39 @@ + +#include "handshake.h" +#include "lnsocket_internal.h" +#include + +struct act_three* lnsocket_act_two(struct lnsocket *ln, struct act_two *act2); + +void* EMSCRIPTEN_KEEPALIVE lnsocket_act_one(struct lnsocket *ln, const char *node_id) +{ + struct pubkey their_id; + struct node_id their_node_id; + + if (is_zero(&ln->key, sizeof(ln->key))) { + note_error(&ln->errs, "key not initialized, use lnsocket_set_key() or lnsocket_genkey()"); + return NULL; + } + + if (!parse_node_id(node_id, &their_node_id)) { + note_error(&ln->errs, "failed to parse node id"); + return NULL; + } + + if (!pubkey_from_node_id(ln->secp, &their_id, &their_node_id)) { + note_error(&ln->errs, "failed to convert node_id to pubkey"); + return NULL; + } + + new_handshake(ln->secp, &ln->handshake, &their_id); + + ln->handshake.side = INITIATOR; + ln->handshake.their_id = their_id; + + if (!act_one_initiator_prep(ln)) { + note_error(&ln->errs, "failed to build initial handshake data (act1)"); + return NULL; + } + + return &ln->handshake.act1; +} diff --git a/node_modules/lnsocket/package.json b/node_modules/lnsocket/package.json new file mode 100644 index 0000000..3caabf3 --- /dev/null +++ b/node_modules/lnsocket/package.json @@ -0,0 +1,13 @@ +{ + "name": "lnsocket", + "description": "Connect to the lightning network", + "version": "0.2.5", + "repository": { + "url": "https://github.com/jb55/lnsocket" + }, + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "tap": "~0.2.5" + } +} diff --git a/node_modules/lnsocket/sha256.c b/node_modules/lnsocket/sha256.c new file mode 100644 index 0000000..e8ddbb7 --- /dev/null +++ b/node_modules/lnsocket/sha256.c @@ -0,0 +1,302 @@ +/* MIT (BSD) license - see LICENSE file for details */ +/* SHA256 core code translated from the Bitcoin project's C++: + * + * src/crypto/sha256.cpp commit 417532c8acb93c36c2b6fd052b7c11b6a2906aa2 + * Copyright (c) 2014 The Bitcoin Core developers + * Distributed under the MIT software license, see the accompanying + * file COPYING or http://www.opensource.org/licenses/mit-license.php. + */ +#include "sha256.h" +#include "endian.h" +#include "compiler.h" +#include +#include +#include + +static void invalidate_sha256(struct sha256_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL + ctx->c.md_len = 0; +#else + ctx->bytes = (size_t)-1; +#endif +} + +static void check_sha256(struct sha256_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL + assert(ctx->c.md_len != 0); +#else + assert(ctx->bytes != (size_t)-1); +#endif +} + +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL +void sha256_init(struct sha256_ctx *ctx) +{ + SHA256_Init(&ctx->c); +} + +void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size) +{ + check_sha256(ctx); + SHA256_Update(&ctx->c, p, size); +} + +void sha256_done(struct sha256_ctx *ctx, struct sha256 *res) +{ + SHA256_Final(res->u.u8, &ctx->c); + invalidate_sha256(ctx); +} +#else +static uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) +{ + return z ^ (x & (y ^ z)); +} +static uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) +{ + return (x & y) | (z & (x | y)); +} +static uint32_t Sigma0(uint32_t x) +{ + return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); +} +static uint32_t Sigma1(uint32_t x) +{ + return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); +} +static uint32_t sigma0(uint32_t x) +{ + return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); +} +static uint32_t sigma1(uint32_t x) +{ + return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); +} + +/** One round of SHA-256. */ +static void Round(uint32_t a, uint32_t b, uint32_t c, uint32_t *d, uint32_t e, uint32_t f, uint32_t g, uint32_t *h, uint32_t k, uint32_t w) +{ + uint32_t t1 = *h + Sigma1(e) + Ch(e, f, g) + k + w; + uint32_t t2 = Sigma0(a) + Maj(a, b, c); + *d += t1; + *h = t1 + t2; +} + +/** Perform one SHA-256 transformation, processing a 64-byte chunk. */ +static void Transform(uint32_t *s, const uint32_t *chunk) +{ + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, &d, e, f, g, &h, 0x428a2f98, w0 = be32_to_cpu(chunk[0])); + Round(h, a, b, &c, d, e, f, &g, 0x71374491, w1 = be32_to_cpu(chunk[1])); + Round(g, h, a, &b, c, d, e, &f, 0xb5c0fbcf, w2 = be32_to_cpu(chunk[2])); + Round(f, g, h, &a, b, c, d, &e, 0xe9b5dba5, w3 = be32_to_cpu(chunk[3])); + Round(e, f, g, &h, a, b, c, &d, 0x3956c25b, w4 = be32_to_cpu(chunk[4])); + Round(d, e, f, &g, h, a, b, &c, 0x59f111f1, w5 = be32_to_cpu(chunk[5])); + Round(c, d, e, &f, g, h, a, &b, 0x923f82a4, w6 = be32_to_cpu(chunk[6])); + Round(b, c, d, &e, f, g, h, &a, 0xab1c5ed5, w7 = be32_to_cpu(chunk[7])); + Round(a, b, c, &d, e, f, g, &h, 0xd807aa98, w8 = be32_to_cpu(chunk[8])); + Round(h, a, b, &c, d, e, f, &g, 0x12835b01, w9 = be32_to_cpu(chunk[9])); + Round(g, h, a, &b, c, d, e, &f, 0x243185be, w10 = be32_to_cpu(chunk[10])); + Round(f, g, h, &a, b, c, d, &e, 0x550c7dc3, w11 = be32_to_cpu(chunk[11])); + Round(e, f, g, &h, a, b, c, &d, 0x72be5d74, w12 = be32_to_cpu(chunk[12])); + Round(d, e, f, &g, h, a, b, &c, 0x80deb1fe, w13 = be32_to_cpu(chunk[13])); + Round(c, d, e, &f, g, h, a, &b, 0x9bdc06a7, w14 = be32_to_cpu(chunk[14])); + Round(b, c, d, &e, f, g, h, &a, 0xc19bf174, w15 = be32_to_cpu(chunk[15])); + + Round(a, b, c, &d, e, f, g, &h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + + +static void add(struct sha256_ctx *ctx, const void *p, size_t len) +{ + const unsigned char *data = p; + size_t bufsize = ctx->bytes % 64; + + if (bufsize + len >= 64) { + /* Fill the buffer, and process it. */ + memcpy(ctx->buf.u8 + bufsize, data, 64 - bufsize); + ctx->bytes += 64 - bufsize; + data += 64 - bufsize; + len -= 64 - bufsize; + Transform(ctx->s, ctx->buf.u32); + bufsize = 0; + } + + while (len >= 64) { + /* Process full chunks directly from the source. */ + if (alignment_ok(data, sizeof(uint32_t))) + Transform(ctx->s, (const uint32_t *)data); + else { + memcpy(ctx->buf.u8, data, sizeof(ctx->buf)); + Transform(ctx->s, ctx->buf.u32); + } + ctx->bytes += 64; + data += 64; + len -= 64; + } + + if (len) { + /* Fill the buffer with what remains. */ + memcpy(ctx->buf.u8 + bufsize, data, len); + ctx->bytes += len; + } +} + +void sha256_init(struct sha256_ctx *ctx) +{ + struct sha256_ctx init = SHA256_INIT; + *ctx = init; +} + +void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size) +{ + check_sha256(ctx); + add(ctx, p, size); +} + +void sha256_done(struct sha256_ctx *ctx, struct sha256 *res) +{ + static const unsigned char pad[64] = {0x80}; + uint64_t sizedesc; + size_t i; + + sizedesc = cpu_to_be64((uint64_t)ctx->bytes << 3); + /* Add '1' bit to terminate, then all 0 bits, up to next block - 8. */ + add(ctx, pad, 1 + ((128 - 8 - (ctx->bytes % 64) - 1) % 64)); + /* Add number of bits of data (big endian) */ + add(ctx, &sizedesc, 8); + for (i = 0; i < sizeof(ctx->s) / sizeof(ctx->s[0]); i++) + res->u.u32[i] = cpu_to_be32(ctx->s[i]); + invalidate_sha256(ctx); +} +#endif + +void sha256(struct sha256 *sha, const void *p, size_t size) +{ + struct sha256_ctx ctx; + + sha256_init(&ctx); + sha256_update(&ctx, p, size); + sha256_done(&ctx, sha); +} + +void sha256_u8(struct sha256_ctx *ctx, uint8_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +void sha256_u16(struct sha256_ctx *ctx, uint16_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +void sha256_u32(struct sha256_ctx *ctx, uint32_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +void sha256_u64(struct sha256_ctx *ctx, uint64_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +/* Add as little-endian */ +void sha256_le16(struct sha256_ctx *ctx, uint16_t v) +{ + leint16_t lev = cpu_to_le16(v); + sha256_update(ctx, &lev, sizeof(lev)); +} + +void sha256_le32(struct sha256_ctx *ctx, uint32_t v) +{ + leint32_t lev = cpu_to_le32(v); + sha256_update(ctx, &lev, sizeof(lev)); +} + +void sha256_le64(struct sha256_ctx *ctx, uint64_t v) +{ + leint64_t lev = cpu_to_le64(v); + sha256_update(ctx, &lev, sizeof(lev)); +} + +/* Add as big-endian */ +void sha256_be16(struct sha256_ctx *ctx, uint16_t v) +{ + beint16_t bev = cpu_to_be16(v); + sha256_update(ctx, &bev, sizeof(bev)); +} + +void sha256_be32(struct sha256_ctx *ctx, uint32_t v) +{ + beint32_t bev = cpu_to_be32(v); + sha256_update(ctx, &bev, sizeof(bev)); +} + +void sha256_be64(struct sha256_ctx *ctx, uint64_t v) +{ + beint64_t bev = cpu_to_be64(v); + sha256_update(ctx, &bev, sizeof(bev)); +} + + diff --git a/node_modules/lnsocket/sha256.h b/node_modules/lnsocket/sha256.h new file mode 100644 index 0000000..2a92831 --- /dev/null +++ b/node_modules/lnsocket/sha256.h @@ -0,0 +1,155 @@ + +#ifndef CCAN_CRYPTO_SHA256_H +#define CCAN_CRYPTO_SHA256_H + + +/** Output length for `wally_sha256` */ +#define SHA256_LEN 32 + + +/* BSD-MIT - see LICENSE file for details */ +/* #include "config.h" */ +#include +#include + +/* Uncomment this to use openssl's SHA256 routines (and link with -lcrypto) */ +/*#define CCAN_CRYPTO_SHA256_USE_OPENSSL 1*/ + +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL +#include +#endif + +/** + * struct sha256 - structure representing a completed SHA256. + * @u.u8: an unsigned char array. + * @u.u32: a 32-bit integer array. + * + * Other fields may be added to the union in future. + */ +struct sha256 { + union { + uint32_t u32[8]; + unsigned char u8[32]; + } u; +}; + +/** + * sha256 - return sha256 of an object. + * @sha256: the sha256 to fill in + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * The bytes pointed to by @p is SHA256 hashed into @sha256. This is + * equivalent to sha256_init(), sha256_update() then sha256_done(). + */ +void sha256(struct sha256 *sha, const void *p, size_t size); + +/** + * struct sha256_ctx - structure to store running context for sha256 + */ +struct sha256_ctx { +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL + SHA256_CTX c; +#else + uint32_t s[8]; + union { + uint32_t u32[16]; + unsigned char u8[64]; + } buf; + size_t bytes; +#endif +}; + +/** + * sha256_init - initialize an SHA256 context. + * @ctx: the sha256_ctx to initialize + * + * This must be called before sha256_update or sha256_done, or + * alternately you can assign SHA256_INIT. + * + * If it was already initialized, this forgets anything which was + * hashed before. + * + * Example: + * static void hash_all(const char **arr, struct sha256 *hash) + * { + * size_t i; + * struct sha256_ctx ctx; + * + * sha256_init(&ctx); + * for (i = 0; arr[i]; i++) + * sha256_update(&ctx, arr[i], strlen(arr[i])); + * sha256_done(&ctx, hash); + * } + */ +void sha256_init(struct sha256_ctx *ctx); + +/** + * SHA256_INIT - initializer for an SHA256 context. + * + * This can be used to statically initialize an SHA256 context (instead + * of sha256_init()). + * + * Example: + * static void hash_all(const char **arr, struct sha256 *hash) + * { + * size_t i; + * struct sha256_ctx ctx = SHA256_INIT; + * + * for (i = 0; arr[i]; i++) + * sha256_update(&ctx, arr[i], strlen(arr[i])); + * sha256_done(&ctx, hash); + * } + */ +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL +#define SHA256_INIT \ + { { { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \ + 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \ + 0x0, 0x0, \ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ + 0x0, 0x20 } } +#else +#define SHA256_INIT \ + { { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \ + 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \ + { { 0 } }, 0 } +#endif + +/** + * sha256_update - include some memory in the hash. + * @ctx: the sha256_ctx to use + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * You can call this multiple times to hash more data, before calling + * sha256_done(). + */ +void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size); + +/** + * sha256_done - finish SHA256 and return the hash + * @ctx: the sha256_ctx to complete + * @res: the hash to return. + * + * Note that @ctx is *destroyed* by this, and must be reinitialized. + * To avoid that, pass a copy instead. + */ +void sha256_done(struct sha256_ctx *sha256, struct sha256 *res); + +/* Add various types to an SHA256 hash */ +void sha256_u8(struct sha256_ctx *ctx, uint8_t v); +void sha256_u16(struct sha256_ctx *ctx, uint16_t v); +void sha256_u32(struct sha256_ctx *ctx, uint32_t v); +void sha256_u64(struct sha256_ctx *ctx, uint64_t v); + +/* Add as little-endian */ +void sha256_le16(struct sha256_ctx *ctx, uint16_t v); +void sha256_le32(struct sha256_ctx *ctx, uint32_t v); +void sha256_le64(struct sha256_ctx *ctx, uint64_t v); + +/* Add as big-endian */ +void sha256_be16(struct sha256_ctx *ctx, uint16_t v); +void sha256_be32(struct sha256_ctx *ctx, uint32_t v); +void sha256_be64(struct sha256_ctx *ctx, uint64_t v); + +#endif /* CCAN_CRYPTO_SHA256_H */ diff --git a/node_modules/lnsocket/sha512.c b/node_modules/lnsocket/sha512.c new file mode 100644 index 0000000..1f866bb --- /dev/null +++ b/node_modules/lnsocket/sha512.c @@ -0,0 +1,261 @@ + +/* MIT (BSD) license - see LICENSE file for details */ +/* SHA512 core code translated from the Bitcoin project's C++: + * + * src/crypto/sha512.cpp commit f914f1a746d7f91951c1da262a4a749dd3ebfa71 + * Copyright (c) 2014 The Bitcoin Core developers + * Distributed under the MIT software license, see the accompanying + * file COPYING or http://www.opensource.org/licenses/mit-license.php. + */ +#include "sha512.h" +#include "endian.h" +#include "compiler.h" +#include +#include +#include + +static void invalidate_sha512(struct sha512_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + ctx->c.md_len = 0; +#else + ctx->bytes = (size_t)-1; +#endif +} + +static void check_sha512(struct sha512_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + assert(ctx->c.md_len != 0); +#else + assert(ctx->bytes != (size_t)-1); +#endif +} + +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL +void sha512_init(struct sha512_ctx *ctx) +{ + SHA512_Init(&ctx->c); +} + +void sha512_update(struct sha512_ctx *ctx, const void *p, size_t size) +{ + check_sha512(ctx); + SHA512_Update(&ctx->c, p, size); +} + +void sha512_done(struct sha512_ctx *ctx, struct sha512 *res) +{ + SHA512_Final(res->u.u8, &ctx->c); + invalidate_sha512(ctx); +} +#else +static uint64_t Ch(uint64_t x, uint64_t y, uint64_t z) +{ + return z ^ (x & (y ^ z)); +} +static uint64_t Maj(uint64_t x, uint64_t y, uint64_t z) +{ + return (x & y) | (z & (x | y)); +} +static uint64_t Sigma0(uint64_t x) +{ + return (x >> 28 | x << 36) ^ (x >> 34 | x << 30) ^ (x >> 39 | x << 25); +} +static uint64_t Sigma1(uint64_t x) +{ + return (x >> 14 | x << 50) ^ (x >> 18 | x << 46) ^ (x >> 41 | x << 23); +} +static uint64_t sigma0(uint64_t x) +{ + return (x >> 1 | x << 63) ^ (x >> 8 | x << 56) ^ (x >> 7); +} +static uint64_t sigma1(uint64_t x) +{ + return (x >> 19 | x << 45) ^ (x >> 61 | x << 3) ^ (x >> 6); +} + +/** One round of SHA-512. */ +static void Round(uint64_t a, uint64_t b, uint64_t c, uint64_t *d, uint64_t e, uint64_t f, uint64_t g, uint64_t *h, uint64_t k, uint64_t w) +{ + uint64_t t1 = *h + Sigma1(e) + Ch(e, f, g) + k + w; + uint64_t t2 = Sigma0(a) + Maj(a, b, c); + *d += t1; + *h = t1 + t2; +} + +/** Perform one SHA-512 transformation, processing a 128-byte chunk. */ +static void Transform(uint64_t *s, const uint64_t *chunk) +{ + uint64_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint64_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, &d, e, f, g, &h, 0x428a2f98d728ae22ull, w0 = be64_to_cpu(chunk[0])); + Round(h, a, b, &c, d, e, f, &g, 0x7137449123ef65cdull, w1 = be64_to_cpu(chunk[1])); + Round(g, h, a, &b, c, d, e, &f, 0xb5c0fbcfec4d3b2full, w2 = be64_to_cpu(chunk[2])); + Round(f, g, h, &a, b, c, d, &e, 0xe9b5dba58189dbbcull, w3 = be64_to_cpu(chunk[3])); + Round(e, f, g, &h, a, b, c, &d, 0x3956c25bf348b538ull, w4 = be64_to_cpu(chunk[4])); + Round(d, e, f, &g, h, a, b, &c, 0x59f111f1b605d019ull, w5 = be64_to_cpu(chunk[5])); + Round(c, d, e, &f, g, h, a, &b, 0x923f82a4af194f9bull, w6 = be64_to_cpu(chunk[6])); + Round(b, c, d, &e, f, g, h, &a, 0xab1c5ed5da6d8118ull, w7 = be64_to_cpu(chunk[7])); + Round(a, b, c, &d, e, f, g, &h, 0xd807aa98a3030242ull, w8 = be64_to_cpu(chunk[8])); + Round(h, a, b, &c, d, e, f, &g, 0x12835b0145706fbeull, w9 = be64_to_cpu(chunk[9])); + Round(g, h, a, &b, c, d, e, &f, 0x243185be4ee4b28cull, w10 = be64_to_cpu(chunk[10])); + Round(f, g, h, &a, b, c, d, &e, 0x550c7dc3d5ffb4e2ull, w11 = be64_to_cpu(chunk[11])); + Round(e, f, g, &h, a, b, c, &d, 0x72be5d74f27b896full, w12 = be64_to_cpu(chunk[12])); + Round(d, e, f, &g, h, a, b, &c, 0x80deb1fe3b1696b1ull, w13 = be64_to_cpu(chunk[13])); + Round(c, d, e, &f, g, h, a, &b, 0x9bdc06a725c71235ull, w14 = be64_to_cpu(chunk[14])); + Round(b, c, d, &e, f, g, h, &a, 0xc19bf174cf692694ull, w15 = be64_to_cpu(chunk[15])); + + Round(a, b, c, &d, e, f, g, &h, 0xe49b69c19ef14ad2ull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0xefbe4786384f25e3ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x0fc19dc68b8cd5b5ull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x240ca1cc77ac9c65ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x2de92c6f592b0275ull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4a7484aa6ea6e483ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5cb0a9dcbd41fbd4ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x76f988da831153b5ull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x983e5152ee66dfabull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa831c66d2db43210ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xb00327c898fb213full, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xbf597fc7beef0ee4ull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xc6e00bf33da88fc2ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd5a79147930aa725ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0x06ca6351e003826full, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x142929670a0e6e70ull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x27b70a8546d22ffcull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x2e1b21385c26c926ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x4d2c6dfc5ac42aedull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x53380d139d95b3dfull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x650a73548baf63deull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x766a0abb3c77b2a8ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x81c2c92e47edaee6ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x92722c851482353bull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0xa2bfe8a14cf10364ull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa81a664bbc423001ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xc24b8b70d0f89791ull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xc76c51a30654be30ull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xd192e819d6ef5218ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd69906245565a910ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xf40e35855771202aull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x106aa07032bbd1b8ull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x19a4c116b8d2d0c8ull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x1e376c085141ab53ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x2748774cdf8eeb99ull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x34b0bcb5e19b48a8ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x391c0cb3c5c95a63ull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4ed8aa4ae3418acbull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5b9cca4f7763e373ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x682e6ff3d6b2b8a3ull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x748f82ee5defb2fcull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0x78a5636f43172f60ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0x84c87814a1f0ab72ull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0x8cc702081a6439ecull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0x90befffa23631e28ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xa4506cebde82bde9ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xbef9a3f7b2c67915ull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0xc67178f2e372532bull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0xca273eceea26619cull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0xd186b8c721c0c207ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0xeada7dd6cde0eb1eull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0xf57d4f7fee6ed178ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x06f067aa72176fbaull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x0a637dc5a2c898a6ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x113f9804bef90daeull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x1b710b35131c471bull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x28db77f523047d84ull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0x32caab7b40c72493ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0x3c9ebe0a15c9bebcull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0x431d67c49c100d4cull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0x5fcb6fab3ad6faecull, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x6c44198c4a475817ull, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + +static void add(struct sha512_ctx *ctx, const void *p, size_t len) +{ + const unsigned char *data = p; + size_t bufsize = ctx->bytes % 128; + + if (bufsize + len >= 128) { + /* Fill the buffer, and process it. */ + memcpy(ctx->buf.u8 + bufsize, data, 128 - bufsize); + ctx->bytes += 128 - bufsize; + data += 128 - bufsize; + len -= 128 - bufsize; + Transform(ctx->s, ctx->buf.u64); + bufsize = 0; + } + + while (len >= 128) { + /* Process full chunks directly from the source. */ + if (alignment_ok(data, sizeof(uint64_t))) + Transform(ctx->s, (const uint64_t *)data); + else { + memcpy(ctx->buf.u8, data, sizeof(ctx->buf)); + Transform(ctx->s, ctx->buf.u64); + } + ctx->bytes += 128; + data += 128; + len -= 128; + } + + if (len) { + /* Fill the buffer with what remains. */ + memcpy(ctx->buf.u8 + bufsize, data, len); + ctx->bytes += len; + } +} + +void sha512_init(struct sha512_ctx *ctx) +{ + struct sha512_ctx init = SHA512_INIT; + *ctx = init; +} + +void sha512_update(struct sha512_ctx *ctx, const void *p, size_t size) +{ + check_sha512(ctx); + add(ctx, p, size); +} + +void sha512_done(struct sha512_ctx *ctx, struct sha512 *res) +{ + static const unsigned char pad[128] = { 0x80 }; + uint64_t sizedesc[2] = { 0, 0 }; + size_t i; + + sizedesc[1] = cpu_to_be64((uint64_t)ctx->bytes << 3); + + /* Add '1' bit to terminate, then all 0 bits, up to next block - 16. */ + add(ctx, pad, 1 + ((256 - 16 - (ctx->bytes % 128) - 1) % 128)); + /* Add number of bits of data (big endian) */ + add(ctx, sizedesc, sizeof(sizedesc)); + for (i = 0; i < sizeof(ctx->s) / sizeof(ctx->s[0]); i++) + res->u.u64[i] = cpu_to_be64(ctx->s[i]); + invalidate_sha512(ctx); +} +#endif /* CCAN_CRYPTO_SHA512_USE_OPENSSL */ + +void sha512(struct sha512 *sha, const void *p, size_t size) +{ + struct sha512_ctx ctx; + + sha512_init(&ctx); + sha512_update(&ctx, p, size); + sha512_done(&ctx, sha); + memset(&ctx, 0, sizeof(ctx)); +} diff --git a/node_modules/lnsocket/sha512.h b/node_modules/lnsocket/sha512.h new file mode 100644 index 0000000..48cc47b --- /dev/null +++ b/node_modules/lnsocket/sha512.h @@ -0,0 +1,138 @@ + +#ifndef CCAN_CRYPTO_SHA512_H +#define CCAN_CRYPTO_SHA512_H +/* BSD-MIT - see LICENSE file for details */ +#include +#include + +/** Output length for `wally_sha512` */ +#define SHA512_LEN 64 + +/* Uncomment this to use openssl's SHA512 routines (and link with -lcrypto) */ +/*#define CCAN_CRYPTO_SHA512_USE_OPENSSL 1*/ + +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL +#include +#endif + +/** + * struct sha512 - structure representing a completed SHA512. + * @u.u8: an unsigned char array. + * @u.u64: a 64-bit integer array. + * + * Other fields may be added to the union in future. + */ +struct sha512 { + union { + uint64_t u64[8]; + unsigned char u8[64]; + } u; +}; + +/** + * sha512 - return sha512 of an object. + * @sha512: the sha512 to fill in + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * The bytes pointed to by @p is SHA512 hashed into @sha512. This is + * equivalent to sha512_init(), sha512_update() then sha512_done(). + */ +void sha512(struct sha512 *sha, const void *p, size_t size); + +/** + * struct sha512_ctx - structure to store running context for sha512 + */ +struct sha512_ctx { +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + SHA512_CTX c; +#else + uint64_t s[8]; + union { + uint64_t u64[16]; + unsigned char u8[128]; + } buf; + size_t bytes; +#endif +}; + +/** + * sha512_init - initialize an SHA512 context. + * @ctx: the sha512_ctx to initialize + * + * This must be called before sha512_update or sha512_done, or + * alternately you can assign SHA512_INIT. + * + * If it was already initialized, this forgets anything which was + * hashed before. + * + * Example: + * static void hash_all(const char **arr, struct sha512 *hash) + * { + * size_t i; + * struct sha512_ctx ctx; + * + * sha512_init(&ctx); + * for (i = 0; arr[i]; i++) + * sha512_update(&ctx, arr[i], strlen(arr[i])); + * sha512_done(&ctx, hash); + * } + */ +void sha512_init(struct sha512_ctx *ctx); + +/** + * SHA512_INIT - initializer for an SHA512 context. + * + * This can be used to statically initialize an SHA512 context (instead + * of sha512_init()). + * + * Example: + * static void hash_all(const char **arr, struct sha512 *hash) + * { + * size_t i; + * struct sha512_ctx ctx = SHA512_INIT; + * + * for (i = 0; arr[i]; i++) + * sha512_update(&ctx, arr[i], strlen(arr[i])); + * sha512_done(&ctx, hash); + * } + */ +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + { { { 0x6a09e667f3bcc908ull, 0xbb67ae8584caa73bull, \ + 0x3c6ef372fe94f82bull, 0xa54ff53a5f1d36f1ull, \ + 0x510e527fade682d1ull, 0x9b05688c2b3e6c1full, \ + 0x1f83d9abfb41bd6bull, 0x5be0cd19137e2179ull }, \ + 0, 0, \ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ + 0, 0x40 } } +#else +#define SHA512_INIT \ + { { 0x6a09e667f3bcc908ull, 0xbb67ae8584caa73bull, \ + 0x3c6ef372fe94f82bull, 0xa54ff53a5f1d36f1ull, \ + 0x510e527fade682d1ull, 0x9b05688c2b3e6c1full, \ + 0x1f83d9abfb41bd6bull, 0x5be0cd19137e2179ull }, \ + { { 0 } }, 0 } +#endif + +/** + * sha512_update - include some memory in the hash. + * @ctx: the sha512_ctx to use + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * You can call this multiple times to hash more data, before calling + * sha512_done(). + */ +void sha512_update(struct sha512_ctx *ctx, const void *p, size_t size); + +/** + * sha512_done - finish SHA512 and return the hash + * @ctx: the sha512_ctx to complete + * @res: the hash to return. + * + * Note that @ctx is *destroyed* by this, and must be reinitialized. + * To avoid that, pass a copy instead. + */ +void sha512_done(struct sha512_ctx *sha512, struct sha512 *res); + +#endif /* CCAN_CRYPTO_SHA512_H */ diff --git a/node_modules/lnsocket/shell.nix b/node_modules/lnsocket/shell.nix new file mode 100644 index 0000000..694fd2d --- /dev/null +++ b/node_modules/lnsocket/shell.nix @@ -0,0 +1,5 @@ +{ pkgs ? import {} }: +pkgs.mkShell { + buildInputs = [ ]; + nativeBuildInputs = with pkgs; [ gdb autoreconfHook emscripten wabt go ]; +} diff --git a/node_modules/lnsocket/test.c b/node_modules/lnsocket/test.c new file mode 100644 index 0000000..4e8c161 --- /dev/null +++ b/node_modules/lnsocket/test.c @@ -0,0 +1,59 @@ + +#include "lnsocket.h" +#include "endian.h" +#include "typedefs.h" +#include +#include + +static void print_data(unsigned char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + printf("%02x", buf[i]); + } + printf("\n"); +} + +int main(int argc, const char *argv[]) +{ + static u8 msgbuf[4096]; + u8 *buf; + struct lnsocket *ln; + + u16 len; + int ok = 1; + + ln = lnsocket_create(); + assert(ln); + + lnsocket_genkey(ln); + + const char *nodeid = "03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71"; + if (!(ok = lnsocket_connect(ln, nodeid, "24.84.152.187"))) + goto done; + + if (!(ok = lnsocket_perform_init(ln))) + goto done; + + printf("init ok!\n"); + + if (!(ok = len = lnsocket_make_ping_msg(msgbuf, sizeof(msgbuf), 1, 1))) + goto done; + + if (!(ok = lnsocket_write(ln, msgbuf, len))) + goto done; + + printf("sent ping "); + print_data(msgbuf, len); + + if (!(ok = lnsocket_read(ln, &buf, &len))) + goto done; + + printf("got "); + print_data(buf, len); +done: + lnsocket_print_errors(ln); + lnsocket_destroy(ln); + return !ok; +} diff --git a/node_modules/lnsocket/tools/0001-configure-customizable-AR-and-RANLIB.patch b/node_modules/lnsocket/tools/0001-configure-customizable-AR-and-RANLIB.patch new file mode 100644 index 0000000..c606d89 --- /dev/null +++ b/node_modules/lnsocket/tools/0001-configure-customizable-AR-and-RANLIB.patch @@ -0,0 +1,67 @@ +From 0d253d52e804a5affb0f1c851ec250071e7345d9 Mon Sep 17 00:00:00 2001 +From: Tim Ruffing +Date: Sun, 13 Mar 2022 10:39:55 +0100 +Subject: [PATCH] configure: Use modern way to set AR + +This uses AM_PROG_AR to discover ar, which is the recommended way to do +so. Among other advantages, it honors the AR environment variable (as +set from the outside). The macro has been around since automake 1.11.2 +(Dec 2011). + +This commit also removes code that discovers ranlib and strip. ranlib +has been obsolete for decades (ar does its task now automatically), and +anyway LT_INIT takes care of discovering it. The code we used to set +STRIP was last mentioned in the automake 1.5 manual. Since automake 1.6 +(Mar 2002), strip is discovered automatically when necessary (look for +the *private* macro AM_PROG_INSTALL_STRIP in the automake manual). +--- + .gitignore | 1 + + configure.ac | 11 +++++------ + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/.gitignore b/.gitignore +index 53941f23a..d88627d72 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -46,6 +46,7 @@ coverage.*.html + + src/libsecp256k1-config.h + src/libsecp256k1-config.h.in ++build-aux/ar-lib + build-aux/config.guess + build-aux/config.sub + build-aux/depcomp +diff --git a/configure.ac b/configure.ac +index cc766b20a..16a492071 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -25,24 +25,23 @@ AC_CANONICAL_HOST + AH_TOP([#ifndef LIBSECP256K1_CONFIG_H]) + AH_TOP([#define LIBSECP256K1_CONFIG_H]) + AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/]) +-AM_INIT_AUTOMAKE([foreign subdir-objects]) + +-LT_INIT([win32-dll]) ++# Require Automake 1.11.2 for AM_PROG_AR ++AM_INIT_AUTOMAKE([1.11.2 foreign subdir-objects]) + + # Make the compilation flags quiet unless V=1 is used. + m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + + PKG_PROG_PKG_CONFIG + +-AC_PATH_TOOL(AR, ar) +-AC_PATH_TOOL(RANLIB, ranlib) +-AC_PATH_TOOL(STRIP, strip) +- + AC_PROG_CC + if test x"$ac_cv_prog_cc_c89" = x"no"; then + AC_MSG_ERROR([c89 compiler support required]) + fi + AM_PROG_AS ++AM_PROG_AR ++ ++LT_INIT([win32-dll]) + + build_windows=no + diff --git a/node_modules/lnsocket/tools/refresh-submodules.sh b/node_modules/lnsocket/tools/refresh-submodules.sh new file mode 100755 index 0000000..bedb8f3 --- /dev/null +++ b/node_modules/lnsocket/tools/refresh-submodules.sh @@ -0,0 +1,42 @@ +#! /bin/sh + +if [ $# = 0 ]; then + echo "Usage: $0 ..." >&2 + exit 1 +fi + +# If no git dir (or, if we're a submodule, git file), forget it. +[ -e .git ] || exit 0 + +# git submodule can't run in parallel. Really. +# Wait for it to finish if in parallel. +if ! mkdir .refresh-submodules 2>/dev/null ; then + # If we don't make progress in ~60 seconds, force delete and retry. + LIMIT=$((50 + $$ % 20)) + i=0 + while [ $i -lt $LIMIT ]; do + [ -d .refresh-submodules ] || exit 0 + sleep 1 + i=$((i + 1)) + done + rmdir .refresh-submodules + exec "$0" "$@" || exit 1 +fi + +trap "rmdir .refresh-submodules" EXIT + +# Be a little careful here, since we do rm -rf! +for m in "$@"; do + if ! grep -q "path = $m\$" .gitmodules; then + echo "$m is not a submodule!" >&2 + exit 1 + fi +done + +# git submodule can segfault. Really. +if [ "$(git submodule status "$@" | grep -c '^ ')" != $# ]; then + echo Reinitializing submodules "$@" ... + git submodule sync "$@" + rm -rf "$@" + git submodule update --init --recursive "$@" +fi diff --git a/node_modules/lnsocket/tools/secp-ios.sh b/node_modules/lnsocket/tools/secp-ios.sh new file mode 100755 index 0000000..3fa58a5 --- /dev/null +++ b/node_modules/lnsocket/tools/secp-ios.sh @@ -0,0 +1,74 @@ +#! /usr/bin/env bash +# +# Step 1. +# Configure for base system so simulator is covered +# +# Step 2. +# Make for iOS and iOS simulator +# +# Step 3. +# Merge libs into final version for xcode import + +cd deps/secp256k1 + +export PREFIX="$(pwd)/libsecp256k1-ios" +export IOS64_PREFIX="$PREFIX/tmp/ios64" +export SIMULATOR64_PREFIX="$PREFIX/tmp/simulator64" +export XCODEDIR=$(xcode-select -p) +export IOS_SIMULATOR_VERSION_MIN=${IOS_SIMULATOR_VERSION_MIN-"6.0.0"} +export IOS_VERSION_MIN=${IOS_VERSION_MIN-"6.0.0"} + +mkdir -p $SIMULATOR64_PREFIX $IOS64_PREFIX || exit 1 + +# Build for the simulator +export BASEDIR="${XCODEDIR}/Platforms/iPhoneSimulator.platform/Developer" +export PATH="${BASEDIR}/usr/bin:$BASEDIR/usr/sbin:$PATH" +export SDK="${BASEDIR}/SDKs/iPhoneSimulator.sdk" + +## x86_64 simulator +export CFLAGS="-O2 -arch x86_64 -isysroot ${SDK} -mios-simulator-version-min=${IOS_SIMULATOR_VERSION_MIN} -flto" +export LDFLAGS="-arch x86_64 -isysroot ${SDK} -mios-simulator-version-min=${IOS_SIMULATOR_VERSION_MIN} -flto" + +make distclean > /dev/null + +./configure --host=x86_64-apple-darwin10 \ + --disable-shared \ + --enable-module-ecdh \ + --prefix="$SIMULATOR64_PREFIX" + +make -j3 install || exit 1 + +# Build for iOS +export BASEDIR="${XCODEDIR}/Platforms/iPhoneOS.platform/Developer" +export PATH="${BASEDIR}/usr/bin:$BASEDIR/usr/sbin:$PATH" +export SDK="${BASEDIR}/SDKs/iPhoneOS.sdk" + +## 64-bit iOS +export CFLAGS="-O2 -arch arm64 -isysroot ${SDK} -mios-version-min=${IOS_VERSION_MIN} -flto -fembed-bitcode" +export LDFLAGS="-arch arm64 -isysroot ${SDK} -mios-version-min=${IOS_VERSION_MIN} -flto -fembed-bitcode" + +make distclean > /dev/null + +./configure --host=arm-apple-darwin10 \ + --disable-shared \ + --enable-module-ecdh \ + --prefix="$IOS64_PREFIX" || exit 1 + +make -j3 install || exit 1 + +# Create universal binary and include folder +rm -fr -- "$PREFIX/include" "$PREFIX/libsecp256k1.a" 2> /dev/null +mkdir -p -- "$PREFIX/lib" +lipo -create \ + "$SIMULATOR64_PREFIX/lib/libsecp256k1.a" \ + "$IOS64_PREFIX/lib/libsecp256k1.a" \ + -output "$PREFIX/lib/libsecp256k1.a" + +echo +echo "libsecp256k1 has been installed into $PREFIX" +echo +file -- "$PREFIX/lib/libsecp256k1.a" + +# Cleanup +rm -rf -- "$PREFIX/tmp" +make distclean > /dev/null diff --git a/node_modules/lnsocket/tools/secp-wasm.sh b/node_modules/lnsocket/tools/secp-wasm.sh new file mode 100755 index 0000000..59a7322 --- /dev/null +++ b/node_modules/lnsocket/tools/secp-wasm.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +cd deps/secp256k1 + +export CC=emcc +export AR=emar +export RANLIB=emranlib + +export PREFIX="$(pwd)/libsecp256k1-wasm" + +mkdir -p $PREFIX || exit 1 + +make distclean > /dev/null + +patch -N -p1 < ../../tools/0001-configure-customizable-AR-and-RANLIB.patch + +./configure --disable-shared \ + --disable-tests \ + --disable-exhaustive-tests \ + --disable-benchmark \ + --enable-module-ecdh \ + --prefix="$PREFIX" + +make -j3 install || exit 1 + +rm -rf -- "$PREFIX/tmp" +make distclean > /dev/null diff --git a/node_modules/lnsocket/typedefs.h b/node_modules/lnsocket/typedefs.h new file mode 100644 index 0000000..7996b87 --- /dev/null +++ b/node_modules/lnsocket/typedefs.h @@ -0,0 +1,13 @@ + +#ifndef LNSOCKET_TYPES_H +#define LNSOCKET_TYPES_H +#include + +typedef unsigned char u8; +typedef unsigned int u32; +typedef unsigned short u16; +typedef uint64_t u64; +typedef int64_t s64; + + +#endif /* LNSOCKET_TYPES_H */ diff --git a/node_modules/lnsocket/varint.c b/node_modules/lnsocket/varint.c new file mode 100644 index 0000000..aca37ce --- /dev/null +++ b/node_modules/lnsocket/varint.c @@ -0,0 +1,75 @@ + +#include "varint.h" + +size_t varint_size(uint64_t v) +{ + if (v < 0xfd) + return 1; + if (v <= 0xffff) + return 3; + if (v <= 0xffffffff) + return 5; + return 9; +} + +size_t varint_put(unsigned char buf[VARINT_MAX_LEN], uint64_t v) +{ + unsigned char *p = buf; + + if (v < 0xfd) { + *(p++) = v; + } else if (v <= 0xffff) { + (*p++) = 0xfd; + (*p++) = v; + (*p++) = v >> 8; + } else if (v <= 0xffffffff) { + (*p++) = 0xfe; + (*p++) = v; + (*p++) = v >> 8; + (*p++) = v >> 16; + (*p++) = v >> 24; + } else { + (*p++) = 0xff; + (*p++) = v; + (*p++) = v >> 8; + (*p++) = v >> 16; + (*p++) = v >> 24; + (*p++) = v >> 32; + (*p++) = v >> 40; + (*p++) = v >> 48; + (*p++) = v >> 56; + } + return p - buf; +} + +size_t varint_get(const unsigned char *p, size_t max, int64_t *val) +{ + if (max < 1) + return 0; + + switch (*p) { + case 0xfd: + if (max < 3) + return 0; + *val = ((uint64_t)p[2] << 8) + p[1]; + return 3; + case 0xfe: + if (max < 5) + return 0; + *val = ((uint64_t)p[4] << 24) + ((uint64_t)p[3] << 16) + + ((uint64_t)p[2] << 8) + p[1]; + return 5; + case 0xff: + if (max < 9) + return 0; + *val = ((uint64_t)p[8] << 56) + ((uint64_t)p[7] << 48) + + ((uint64_t)p[6] << 40) + ((uint64_t)p[5] << 32) + + ((uint64_t)p[4] << 24) + ((uint64_t)p[3] << 16) + + ((uint64_t)p[2] << 8) + p[1]; + return 9; + default: + *val = *p; + return 1; + } +} + diff --git a/node_modules/lnsocket/varint.h b/node_modules/lnsocket/varint.h new file mode 100644 index 0000000..1f093f7 --- /dev/null +++ b/node_modules/lnsocket/varint.h @@ -0,0 +1,14 @@ + +#ifndef LNSOCKET_VARINT_H +#define LNSOCKET_VARINT_H + +#define VARINT_MAX_LEN 9 + +#include +#include + +size_t varint_put(unsigned char buf[VARINT_MAX_LEN], uint64_t v); +size_t varint_size(uint64_t v); +size_t varint_get(const unsigned char *p, size_t max, int64_t *val); + +#endif /* LNSOCKET_VARINT_H */ diff --git a/node_modules/mkdirp/.npmignore b/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/mkdirp/.travis.yml b/node_modules/mkdirp/.travis.yml new file mode 100644 index 0000000..84fd7ca --- /dev/null +++ b/node_modules/mkdirp/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 diff --git a/node_modules/mkdirp/LICENSE b/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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. diff --git a/node_modules/mkdirp/examples/pow.js b/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/mkdirp/index.js b/node_modules/mkdirp/index.js new file mode 100644 index 0000000..fda6de8 --- /dev/null +++ b/node_modules/mkdirp/index.js @@ -0,0 +1,82 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f, made) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, mode, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode, made) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), mode, made); + sync(p, mode, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/node_modules/mkdirp/package.json b/node_modules/mkdirp/package.json new file mode 100644 index 0000000..8aa64fe --- /dev/null +++ b/node_modules/mkdirp/package.json @@ -0,0 +1,22 @@ +{ + "name" : "mkdirp", + "description" : "Recursively mkdir, like `mkdir -p`", + "version" : "0.3.5", + "author" : "James Halliday (http://substack.net)", + "main" : "./index", + "keywords" : [ + "mkdir", + "directory" + ], + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-mkdirp.git" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "devDependencies" : { + "tap" : "~0.4.0" + }, + "license" : "MIT" +} diff --git a/node_modules/mkdirp/readme.markdown b/node_modules/mkdirp/readme.markdown new file mode 100644 index 0000000..83b0216 --- /dev/null +++ b/node_modules/mkdirp/readme.markdown @@ -0,0 +1,63 @@ +# mkdirp + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +# example + +## pow.js + +```js +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); +``` + +Output + +``` +pow! +``` + +And now /tmp/foo/bar/baz exists, huzzah! + +# methods + +```js +var mkdirp = require('mkdirp'); +``` + +## mkdirp(dir, mode, cb) + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +## mkdirp.sync(dir, mode) + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +# install + +With [npm](http://npmjs.org) do: + +``` +npm install mkdirp +``` + +# license + +MIT diff --git a/node_modules/mkdirp/test/chmod.js b/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/mkdirp/test/clobber.js b/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/mkdirp/test/mkdirp.js b/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/mkdirp/test/perm.js b/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/mkdirp/test/perm_sync.js b/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/node_modules/mkdirp/test/race.js b/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/node_modules/mkdirp/test/rel.js b/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/mkdirp/test/return.js b/node_modules/mkdirp/test/return.js new file mode 100644 index 0000000..bce68e5 --- /dev/null +++ b/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/node_modules/mkdirp/test/return_sync.js b/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 0000000..7c222d3 --- /dev/null +++ b/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/node_modules/mkdirp/test/root.js b/node_modules/mkdirp/test/root.js new file mode 100644 index 0000000..97ad7a2 --- /dev/null +++ b/node_modules/mkdirp/test/root.js @@ -0,0 +1,18 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, 0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/node_modules/mkdirp/test/sync.js b/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..7530cad --- /dev/null +++ b/node_modules/mkdirp/test/sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, 0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/mkdirp/test/umask.js b/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..64ccafe --- /dev/null +++ b/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/mkdirp/test/umask_sync.js b/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..35bd5cb --- /dev/null +++ b/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/nopt/.npmignore b/node_modules/nopt/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/nopt/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/nopt/LICENSE b/node_modules/nopt/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/nopt/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +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. diff --git a/node_modules/nopt/README.md b/node_modules/nopt/README.md new file mode 100644 index 0000000..96798a1 --- /dev/null +++ b/node_modules/nopt/README.md @@ -0,0 +1,210 @@ +If you want to write an option parser, and have it be good, there are +two ways to do it. The Right Way, and the Wrong Way. + +The Wrong Way is to sit down and write an option parser. We've all done +that. + +The Right Way is to write some complex configurable program with so many +options that you go half-insane just trying to manage them all, and put +it off with duct-tape solutions until you see exactly to the core of the +problem, and finally snap and write an awesome option parser. + +If you want to write an option parser, don't write an option parser. +Write a package manager, or a source control system, or a service +restarter, or an operating system. You probably won't end up with a +good one of those, but if you don't give up, and you are relentless and +diligent enough in your procrastination, you may just end up with a very +nice option parser. + +## USAGE + + // my-program.js + var nopt = require("nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + , "many" : [String, Array] + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag"] + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + console.log(parsed) + +This would give you support for any of the following: + +```bash +$ node my-program.js --foo "blerp" --no-flag +{ "foo" : "blerp", "flag" : false } + +$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag +{ bar: 7, foo: "Mr. Hand", flag: true } + +$ node my-program.js --foo "blerp" -f -----p +{ foo: "blerp", flag: true, pick: true } + +$ node my-program.js -fp --foofoo +{ foo: "Mr. Foo", flag: true, pick: true } + +$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. +{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } + +$ node my-program.js --blatzk -fp # unknown opts are ok. +{ blatzk: true, flag: true, pick: true } + +$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value +{ blatzk: 1000, flag: true, pick: true } + +$ node my-program.js --no-blatzk -fp # unless they start with "no-" +{ blatzk: false, flag: true, pick: true } + +$ node my-program.js --baz b/a/z # known paths are resolved. +{ baz: "/Users/isaacs/b/a/z" } + +# if Array is one of the types, then it can take many +# values, and will always be an array. The other types provided +# specify what types are allowed in the list. + +$ node my-program.js --many 1 --many null --many foo +{ many: ["1", "null", "foo"] } + +$ node my-program.js --many foo +{ many: ["foo"] } +``` + +Read the tests at the bottom of `lib/nopt.js` for more examples of +what this puppy can do. + +## Types + +The following types are supported, and defined on `nopt.typeDefs` + +* String: A normal string. No parsing is done. +* path: A file system path. Gets resolved against cwd if not absolute. +* url: A url. If it doesn't parse, it isn't accepted. +* Number: Must be numeric. +* Date: Must parse as a date. If it does, and `Date` is one of the options, + then it will return a Date object, not a string. +* Boolean: Must be either `true` or `false`. If an option is a boolean, + then it does not need a value, and its presence will imply `true` as + the value. To negate boolean flags, do `--no-whatever` or `--whatever + false` +* NaN: Means that the option is strictly not allowed. Any value will + fail. +* Stream: An object matching the "Stream" class in node. Valuable + for use when validating programmatically. (npm uses this to let you + supply any WriteStream on the `outfd` and `logfd` config options.) +* Array: If `Array` is specified as one of the types, then the value + will be parsed as a list of options. This means that multiple values + can be specified, and that the value will always be an array. + +If a type is an array of values not on this list, then those are +considered valid values. For instance, in the example above, the +`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, +and any other value will be rejected. + +When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be +interpreted as their JavaScript equivalents, and numeric values will be +interpreted as a number. + +You can also mix types and values, or multiple types, in a list. For +instance `{ blah: [Number, null] }` would allow a value to be set to +either a Number or null. When types are ordered, this implies a +preference, and the first type that can be used to properly interpret +the value will be used. + +To define a new type, add it to `nopt.typeDefs`. Each item in that +hash is an object with a `type` member and a `validate` method. The +`type` member is an object that matches what goes in the type list. The +`validate` method is a function that gets called with `validate(data, +key, val)`. Validate methods should assign `data[key]` to the valid +value of `val` if it can be handled properly, or return boolean +`false` if it cannot. + +You can also call `nopt.clean(data, types, typeDefs)` to clean up a +config object and remove its invalid properties. + +## Error Handling + +By default, nopt outputs a warning to standard error when invalid +options are found. You can change this behavior by assigning a method +to `nopt.invalidHandler`. This method will be called with +the offending `nopt.invalidHandler(key, val, types)`. + +If no `nopt.invalidHandler` is assigned, then it will console.error +its whining. If it is assigned to boolean `false` then the warning is +suppressed. + +## Abbreviations + +Yes, they are supported. If you define options like this: + +```javascript +{ "foolhardyelephants" : Boolean +, "pileofmonkeys" : Boolean } +``` + +Then this will work: + +```bash +node program.js --foolhar --pil +node program.js --no-f --pileofmon +# etc. +``` + +## Shorthands + +Shorthands are a hash of shorter option names to a snippet of args that +they expand to. + +If multiple one-character shorthands are all combined, and the +combination does not unambiguously match any other option or shorthand, +then they will be broken up into their constituent parts. For example: + +```json +{ "s" : ["--loglevel", "silent"] +, "g" : "--global" +, "f" : "--force" +, "p" : "--parseable" +, "l" : "--long" +} +``` + +```bash +npm ls -sgflp +# just like doing this: +npm ls --loglevel silent --global --force --long --parseable +``` + +## The Rest of the args + +The config object returned by nopt is given a special member called +`argv`, which is an object with the following fields: + +* `remain`: The remaining args after all the parsing has occurred. +* `original`: The args as they originally appeared. +* `cooked`: The args after flags and shorthands are expanded. + +## Slicing + +Node programs are called with more or less the exact argv as it appears +in C land, after the v8 and node-specific options have been plucked off. +As such, `argv[0]` is always `node` and `argv[1]` is always the +JavaScript program being run. + +That's usually not very useful to you. So they're sliced off by +default. If you want them, then you can pass in `0` as the last +argument, or any other number that you'd like to slice off the start of +the list. diff --git a/node_modules/nopt/bin/nopt.js b/node_modules/nopt/bin/nopt.js new file mode 100755 index 0000000..30e9fdb --- /dev/null +++ b/node_modules/nopt/bin/nopt.js @@ -0,0 +1,51 @@ +#!/usr/bin/env node +var nopt = require("../lib/nopt") + , types = { num: Number + , bool: Boolean + , help: Boolean + , list: Array + , "num-list": [Number, Array] + , "str-list": [String, Array] + , "bool-list": [Boolean, Array] + , str: String + , clear: Boolean + , config: Boolean + , length: Number + } + , shorthands = { s: [ "--str", "astring" ] + , b: [ "--bool" ] + , nb: [ "--no-bool" ] + , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] + , "?": ["--help"] + , h: ["--help"] + , H: ["--help"] + , n: [ "--num", "125" ] + , c: ["--config"] + , l: ["--length"] + } + , parsed = nopt( types + , shorthands + , process.argv + , 2 ) + +console.log("parsed", parsed) + +if (parsed.help) { + console.log("") + console.log("nopt cli tester") + console.log("") + console.log("types") + console.log(Object.keys(types).map(function M (t) { + var type = types[t] + if (Array.isArray(type)) { + return [t, type.map(function (type) { return type.name })] + } + return [t, type && type.name] + }).reduce(function (s, i) { + s[i[0]] = i[1] + return s + }, {})) + console.log("") + console.log("shorthands") + console.log(shorthands) +} diff --git a/node_modules/nopt/examples/my-program.js b/node_modules/nopt/examples/my-program.js new file mode 100755 index 0000000..142447e --- /dev/null +++ b/node_modules/nopt/examples/my-program.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +//process.env.DEBUG_NOPT = 1 + +// my-program.js +var nopt = require("../lib/nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag", "true"] + , "g" : ["--flag"] + , "s" : "--flag" + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + +console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/node_modules/nopt/lib/nopt.js b/node_modules/nopt/lib/nopt.js new file mode 100644 index 0000000..9efab7a --- /dev/null +++ b/node_modules/nopt/lib/nopt.js @@ -0,0 +1,412 @@ +// info about each config option. + +var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG + ? function () { console.error.apply(console, arguments) } + : function () {} + +var url = require("url") + , path = require("path") + , Stream = require("stream").Stream + , abbrev = require("abbrev") + +module.exports = exports = nopt +exports.clean = clean + +exports.typeDefs = + { String : { type: String, validate: validateString } + , Boolean : { type: Boolean, validate: validateBoolean } + , url : { type: url, validate: validateUrl } + , Number : { type: Number, validate: validateNumber } + , path : { type: path, validate: validatePath } + , Stream : { type: Stream, validate: validateStream } + , Date : { type: Date, validate: validateDate } + } + +function nopt (types, shorthands, args, slice) { + args = args || process.argv + types = types || {} + shorthands = shorthands || {} + if (typeof slice !== "number") slice = 2 + + debug(types, shorthands, args, slice) + + args = args.slice(slice) + var data = {} + , key + , remain = [] + , cooked = args + , original = args.slice(0) + + parse(args, data, remain, types, shorthands) + // now data is full + clean(data, types, exports.typeDefs) + data.argv = {remain:remain,cooked:cooked,original:original} + Object.defineProperty(data.argv, 'toString', { value: function () { + return this.original.map(JSON.stringify).join(" ") + }, enumerable: false }) + return data +} + +function clean (data, types, typeDefs) { + typeDefs = typeDefs || exports.typeDefs + var remove = {} + , typeDefault = [false, true, null, String, Number, Array] + + Object.keys(data).forEach(function (k) { + if (k === "argv") return + var val = data[k] + , isArray = Array.isArray(val) + , type = types[k] + if (!isArray) val = [val] + if (!type) type = typeDefault + if (type === Array) type = typeDefault.concat(Array) + if (!Array.isArray(type)) type = [type] + + debug("val=%j", val) + debug("types=", type) + val = val.map(function (val) { + // if it's an unknown value, then parse false/true/null/numbers/dates + if (typeof val === "string") { + debug("string %j", val) + val = val.trim() + if ((val === "null" && ~type.indexOf(null)) + || (val === "true" && + (~type.indexOf(true) || ~type.indexOf(Boolean))) + || (val === "false" && + (~type.indexOf(false) || ~type.indexOf(Boolean)))) { + val = JSON.parse(val) + debug("jsonable %j", val) + } else if (~type.indexOf(Number) && !isNaN(val)) { + debug("convert to number", val) + val = +val + } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { + debug("convert to date", val) + val = new Date(val) + } + } + + if (!types.hasOwnProperty(k)) { + return val + } + + // allow `--no-blah` to set 'blah' to null if null is allowed + if (val === false && ~type.indexOf(null) && + !(~type.indexOf(false) || ~type.indexOf(Boolean))) { + val = null + } + + var d = {} + d[k] = val + debug("prevalidated val", d, val, types[k]) + if (!validate(d, k, val, types[k], typeDefs)) { + if (exports.invalidHandler) { + exports.invalidHandler(k, val, types[k], data) + } else if (exports.invalidHandler !== false) { + debug("invalid: "+k+"="+val, types[k]) + } + return remove + } + debug("validated val", d, val, types[k]) + return d[k] + }).filter(function (val) { return val !== remove }) + + if (!val.length) delete data[k] + else if (isArray) { + debug(isArray, data[k], val) + data[k] = val + } else data[k] = val[0] + + debug("k=%s val=%j", k, val, data[k]) + }) +} + +function validateString (data, k, val) { + data[k] = String(val) +} + +function validatePath (data, k, val) { + if (val === true) return false + val = String(val) + var homePattern = process.platform === 'win32' ? /^~(\/|\\)/ : /^~\// + if (val.match(homePattern) && process.env.HOME) { + val = path.resolve(process.env.HOME, val.substr(2)) + } + data[k] = path.resolve(String(val)) + return true +} + +function validateNumber (data, k, val) { + debug("validate Number %j %j %j", k, val, isNaN(val)) + if (isNaN(val)) return false + data[k] = +val +} + +function validateDate (data, k, val) { + debug("validate Date %j %j %j", k, val, Date.parse(val)) + var s = Date.parse(val) + if (isNaN(s)) return false + data[k] = new Date(val) +} + +function validateBoolean (data, k, val) { + if (val instanceof Boolean) val = val.valueOf() + else if (typeof val === "string") { + if (!isNaN(val)) val = !!(+val) + else if (val === "null" || val === "false") val = false + else val = true + } else val = !!val + data[k] = val +} + +function validateUrl (data, k, val) { + val = url.parse(String(val)) + if (!val.host) return false + data[k] = val.href +} + +function validateStream (data, k, val) { + if (!(val instanceof Stream)) return false + data[k] = val +} + +function validate (data, k, val, type, typeDefs) { + // arrays are lists of types. + if (Array.isArray(type)) { + for (var i = 0, l = type.length; i < l; i ++) { + if (type[i] === Array) continue + if (validate(data, k, val, type[i], typeDefs)) return true + } + delete data[k] + return false + } + + // an array of anything? + if (type === Array) return true + + // NaN is poisonous. Means that something is not allowed. + if (type !== type) { + debug("Poison NaN", k, val, type) + delete data[k] + return false + } + + // explicit list of values + if (val === type) { + debug("Explicitly allowed %j", val) + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + return true + } + + // now go through the list of typeDefs, validate against each one. + var ok = false + , types = Object.keys(typeDefs) + for (var i = 0, l = types.length; i < l; i ++) { + debug("test type %j %j %j", k, val, types[i]) + var t = typeDefs[types[i]] + if (t && type === t.type) { + var d = {} + ok = false !== t.validate(d, k, val) + val = d[k] + if (ok) { + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + break + } + } + } + debug("OK? %j (%j %j %j)", ok, k, val, types[i]) + + if (!ok) delete data[k] + return ok +} + +function parse (args, data, remain, types, shorthands) { + debug("parse", args, data, remain) + + var key = null + , abbrevs = abbrev(Object.keys(types)) + , shortAbbr = abbrev(Object.keys(shorthands)) + + for (var i = 0; i < args.length; i ++) { + var arg = args[i] + debug("arg", arg) + + if (arg.match(/^-{2,}$/)) { + // done with keys. + // the rest are args. + remain.push.apply(remain, args.slice(i + 1)) + args[i] = "--" + break + } + var hadEq = false + if (arg.charAt(0) === "-" && arg.length > 1) { + if (arg.indexOf("=") !== -1) { + hadEq = true + var v = arg.split("=") + arg = v.shift() + v = v.join("=") + args.splice.apply(args, [i, 1].concat([arg, v])) + } + + // see if it's a shorthand + // if so, splice and back up to re-parse it. + var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) + debug("arg=%j shRes=%j", arg, shRes) + if (shRes) { + debug(arg, shRes) + args.splice.apply(args, [i, 1].concat(shRes)) + if (arg !== shRes[0]) { + i -- + continue + } + } + arg = arg.replace(/^-+/, "") + var no = null + while (arg.toLowerCase().indexOf("no-") === 0) { + no = !no + arg = arg.substr(3) + } + + if (abbrevs[arg]) arg = abbrevs[arg] + + var isArray = types[arg] === Array || + Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 + + // allow unknown things to be arrays if specified multiple times. + if (!types.hasOwnProperty(arg) && data.hasOwnProperty(arg)) { + if (!Array.isArray(data[arg])) + data[arg] = [data[arg]] + isArray = true + } + + var val + , la = args[i + 1] + + var isBool = typeof no === 'boolean' || + types[arg] === Boolean || + Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || + (typeof types[arg] === 'undefined' && !hadEq) || + (la === "false" && + (types[arg] === null || + Array.isArray(types[arg]) && ~types[arg].indexOf(null))) + + if (isBool) { + // just set and move along + val = !no + // however, also support --bool true or --bool false + if (la === "true" || la === "false") { + val = JSON.parse(la) + la = null + if (no) val = !val + i ++ + } + + // also support "foo":[Boolean, "bar"] and "--foo bar" + if (Array.isArray(types[arg]) && la) { + if (~types[arg].indexOf(la)) { + // an explicit type + val = la + i ++ + } else if ( la === "null" && ~types[arg].indexOf(null) ) { + // null allowed + val = null + i ++ + } else if ( !la.match(/^-{2,}[^-]/) && + !isNaN(la) && + ~types[arg].indexOf(Number) ) { + // number + val = +la + i ++ + } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { + // string + val = la + i ++ + } + } + + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + continue + } + + if (types[arg] === String && la === undefined) + la = "" + + if (la && la.match(/^-{2,}$/)) { + la = undefined + i -- + } + + val = la === undefined ? true : la + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + i ++ + continue + } + remain.push(arg) + } +} + +function resolveShort (arg, shorthands, shortAbbr, abbrevs) { + // handle single-char shorthands glommed together, like + // npm ls -glp, but only if there is one dash, and only if + // all of the chars are single-char shorthands, and it's + // not a match to some other abbrev. + arg = arg.replace(/^-+/, '') + + // if it's an exact known option, then don't go any further + if (abbrevs[arg] === arg) + return null + + // if it's an exact known shortopt, same deal + if (shorthands[arg]) { + // make it an array, if it's a list of words + if (shorthands[arg] && !Array.isArray(shorthands[arg])) + shorthands[arg] = shorthands[arg].split(/\s+/) + + return shorthands[arg] + } + + // first check to see if this arg is a set of single-char shorthands + var singles = shorthands.___singles + if (!singles) { + singles = Object.keys(shorthands).filter(function (s) { + return s.length === 1 + }).reduce(function (l,r) { + l[r] = true + return l + }, {}) + shorthands.___singles = singles + debug('shorthand singles', singles) + } + + var chrs = arg.split("").filter(function (c) { + return singles[c] + }) + + if (chrs.join("") === arg) return chrs.map(function (c) { + return shorthands[c] + }).reduce(function (l, r) { + return l.concat(r) + }, []) + + + // if it's an arg abbrev, and not a literal shorthand, then prefer the arg + if (abbrevs[arg] && !shorthands[arg]) + return null + + // if it's an abbr for a shorthand, then use that + if (shortAbbr[arg]) + arg = shortAbbr[arg] + + // make it an array, if it's a list of words + if (shorthands[arg] && !Array.isArray(shorthands[arg])) + shorthands[arg] = shorthands[arg].split(/\s+/) + + return shorthands[arg] +} diff --git a/node_modules/nopt/package.json b/node_modules/nopt/package.json new file mode 100644 index 0000000..80a05bd --- /dev/null +++ b/node_modules/nopt/package.json @@ -0,0 +1,22 @@ +{ + "name": "nopt", + "version": "2.2.1", + "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "main": "lib/nopt.js", + "scripts": { + "test": "tap test/*.js" + }, + "repository": "http://github.com/isaacs/nopt", + "bin": "./bin/nopt.js", + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/nopt/raw/master/LICENSE" + }, + "dependencies": { + "abbrev": "1" + }, + "devDependencies": { + "tap": "~0.4.8" + } +} diff --git a/node_modules/nopt/test/basic.js b/node_modules/nopt/test/basic.js new file mode 100644 index 0000000..b31dccf --- /dev/null +++ b/node_modules/nopt/test/basic.js @@ -0,0 +1,243 @@ +var nopt = require("../") + , test = require('tap').test + + +test("passing a string results in a string", function (t) { + var parsed = nopt({ key: String }, {}, ["--key", "myvalue"], 0) + t.same(parsed.key, "myvalue") + t.end() +}) + +// https://github.com/npm/nopt/issues/31 +test("Empty String results in empty string, not true", function (t) { + var parsed = nopt({ empty: String }, {}, ["--empty"], 0) + t.same(parsed.empty, "") + t.end() +}) + +test("~ path is resolved to $HOME", function (t) { + var path = require("path") + if (!process.env.HOME) process.env.HOME = "/tmp" + var parsed = nopt({key: path}, {}, ["--key=~/val"], 0) + t.same(parsed.key, path.resolve(process.env.HOME, "val")) + t.end() +}) + +test("other tests", function (t) { + + var util = require("util") + , Stream = require("stream") + , path = require("path") + , url = require("url") + + , shorthands = + { s : ["--loglevel", "silent"] + , d : ["--loglevel", "info"] + , dd : ["--loglevel", "verbose"] + , ddd : ["--loglevel", "silly"] + , noreg : ["--no-registry"] + , reg : ["--registry"] + , "no-reg" : ["--no-registry"] + , silent : ["--loglevel", "silent"] + , verbose : ["--loglevel", "verbose"] + , h : ["--usage"] + , H : ["--usage"] + , "?" : ["--usage"] + , help : ["--usage"] + , v : ["--version"] + , f : ["--force"] + , desc : ["--description"] + , "no-desc" : ["--no-description"] + , "local" : ["--no-global"] + , l : ["--long"] + , p : ["--parseable"] + , porcelain : ["--parseable"] + , g : ["--global"] + } + + , types = + { aoa: Array + , nullstream: [null, Stream] + , date: Date + , str: String + , browser : String + , cache : path + , color : ["always", Boolean] + , depth : Number + , description : Boolean + , dev : Boolean + , editor : path + , force : Boolean + , global : Boolean + , globalconfig : path + , group : [String, Number] + , gzipbin : String + , logfd : [Number, Stream] + , loglevel : ["silent","win","error","warn","info","verbose","silly"] + , long : Boolean + , "node-version" : [false, String] + , npaturl : url + , npat : Boolean + , "onload-script" : [false, String] + , outfd : [Number, Stream] + , parseable : Boolean + , pre: Boolean + , prefix: path + , proxy : url + , "rebuild-bundle" : Boolean + , registry : url + , searchopts : String + , searchexclude: [null, String] + , shell : path + , t: [Array, String] + , tag : String + , tar : String + , tmp : path + , "unsafe-perm" : Boolean + , usage : Boolean + , user : String + , username : String + , userconfig : path + , version : Boolean + , viewer: path + , _exit : Boolean + , path: path + } + + ; [["-v", {version:true}, []] + ,["---v", {version:true}, []] + ,["ls -s --no-reg connect -d", + {loglevel:"info",registry:null},["ls","connect"]] + ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] + ,["ls --registry blargle", {}, ["ls"]] + ,["--no-registry", {registry:null}, []] + ,["--no-color true", {color:false}, []] + ,["--no-color false", {color:true}, []] + ,["--no-color", {color:false}, []] + ,["--color false", {color:false}, []] + ,["--color --logfd 7", {logfd:7,color:true}, []] + ,["--color=true", {color:true}, []] + ,["--logfd=10", {logfd:10}, []] + ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] + ,["--tmp=tmp -tar=gtar", + {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] + ,["--logfd x", {}, []] + ,["a -true -- -no-false", {true:true},["a","-no-false"]] + ,["a -no-false", {false:false},["a"]] + ,["a -no-no-true", {true:true}, ["a"]] + ,["a -no-no-no-false", {false:false}, ["a"]] + ,["---NO-no-No-no-no-no-nO-no-no"+ + "-No-no-no-no-no-no-no-no-no"+ + "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ + "-no-body-can-do-the-boogaloo-like-I-do" + ,{"body-can-do-the-boogaloo-like-I-do":false}, []] + ,["we are -no-strangers-to-love "+ + "--you-know=the-rules --and=so-do-i "+ + "---im-thinking-of=a-full-commitment "+ + "--no-you-would-get-this-from-any-other-guy "+ + "--no-gonna-give-you-up "+ + "-no-gonna-let-you-down=true "+ + "--no-no-gonna-run-around false "+ + "--desert-you=false "+ + "--make-you-cry false "+ + "--no-tell-a-lie "+ + "--no-no-and-hurt-you false" + ,{"strangers-to-love":false + ,"you-know":"the-rules" + ,"and":"so-do-i" + ,"you-would-get-this-from-any-other-guy":false + ,"gonna-give-you-up":false + ,"gonna-let-you-down":false + ,"gonna-run-around":false + ,"desert-you":false + ,"make-you-cry":false + ,"tell-a-lie":false + ,"and-hurt-you":false + },["we", "are"]] + ,["-t one -t two -t three" + ,{t: ["one", "two", "three"]} + ,[]] + ,["-t one -t null -t three four five null" + ,{t: ["one", "null", "three"]} + ,["four", "five", "null"]] + ,["-t foo" + ,{t:["foo"]} + ,[]] + ,["--no-t" + ,{t:["false"]} + ,[]] + ,["-no-no-t" + ,{t:["true"]} + ,[]] + ,["-aoa one -aoa null -aoa 100" + ,{aoa:["one", null, 100]} + ,[]] + ,["-str 100" + ,{str:"100"} + ,[]] + ,["--color always" + ,{color:"always"} + ,[]] + ,["--no-nullstream" + ,{nullstream:null} + ,[]] + ,["--nullstream false" + ,{nullstream:null} + ,[]] + ,["--notadate=2011-01-25" + ,{notadate: "2011-01-25"} + ,[]] + ,["--date 2011-01-25" + ,{date: new Date("2011-01-25")} + ,[]] + ,["-cl 1" + ,{config: true, length: 1} + ,[] + ,{config: Boolean, length: Number, clear: Boolean} + ,{c: "--config", l: "--length"}] + ,["--acount bla" + ,{"acount":true} + ,["bla"] + ,{account: Boolean, credentials: Boolean, options: String} + ,{a:"--account", c:"--credentials",o:"--options"}] + ,["--clear" + ,{clear:true} + ,[] + ,{clear:Boolean,con:Boolean,len:Boolean,exp:Boolean,add:Boolean,rep:Boolean} + ,{c:"--con",l:"--len",e:"--exp",a:"--add",r:"--rep"}] + ,["--file -" + ,{"file":"-"} + ,[] + ,{file:String} + ,{}] + ,["--file -" + ,{"file":true} + ,["-"] + ,{file:Boolean} + ,{}] + ,["--path" + ,{"path":null} + ,[]] + ,["--path ." + ,{"path":process.cwd()} + ,[]] + ].forEach(function (test) { + var argv = test[0].split(/\s+/) + , opts = test[1] + , rem = test[2] + , actual = nopt(test[3] || types, test[4] || shorthands, argv, 0) + , parsed = actual.argv + delete actual.argv + for (var i in opts) { + var e = JSON.stringify(opts[i]) + , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) + if (e && typeof e === "object") { + t.deepEqual(e, a) + } else { + t.equal(e, a) + } + } + t.deepEqual(rem, parsed.remain) + }) + t.end() +}) diff --git a/node_modules/runforcover/README.markdown b/node_modules/runforcover/README.markdown new file mode 100644 index 0000000..1e56ebd --- /dev/null +++ b/node_modules/runforcover/README.markdown @@ -0,0 +1,56 @@ +runforcover +====== + +Runforcover is a require-hook library that uses node-bunker to provide code coverage data +for your unit test library, whatever it might be. + +methods +======= +var runforcover = require('runforcover'); + +var coverage = runforcover.cover([RegExp | path]); +------- + +Attach runforcover to the global `require` object and patch `require.extensions['.js']` to +provide coverage metadata for all files required after this point. Returns a function +object that can be called to obtain a object keying files to `CoverageData` objects, with +a method for releasing control back to vanilla `require`. Usage: + +````javascript + +var coverage = runforcover.cover(/.*/g); + +require('some/library'); + +coverage(function(coverageData) { + // coverageData is an object keyed by filename. + var stats = coverageData['/full/path/to/file.js'].stats() + + // the percentage of lines run versus total lines in file + console.log(stats.percentage); + + // the number of missing lines + console.log(stats.missing); + + // the number of lines run (seen) + console.log(stats.seen); + + // an array of line objects representing 'missed' lines + stats.lines; + + stats.lines.forEach(function(line) { + // the line number of the line: + console.log(line.number); + + // returns a string containing the source data for the line: + console.log(line.source()); + }); + + // return control back to the original require function + coverage.release(); +}); +```` + +license +======= +new BSD. diff --git a/node_modules/runforcover/index.js b/node_modules/runforcover/index.js new file mode 100644 index 0000000..b5318ac --- /dev/null +++ b/node_modules/runforcover/index.js @@ -0,0 +1,127 @@ +var bunker = require('bunker'), + Module = require('module').Module, + path = require('path'), + fs = require('fs'), + vm = require('vm'); + +function CoverageData (filename, bunker) { + this.bunker = bunker; + this.filename = filename; + this.nodes = {}; +}; + +CoverageData.prototype.visit = function(node) { + ++(this.nodes[node.id] = this.nodes[node.id] || {node:node, count:0}).count; +}; + +CoverageData.prototype.missing = function() { + var nodes = this.nodes, + missing = this.bunker.nodes.filter(function(node) { + return !nodes[node.id]; + }); + + return missing; +}; + +CoverageData.prototype.stats = function() { + var missing = this.missing(), + filedata = fs.readFileSync(this.filename, 'utf8').split('\n'); + + var seenLines = [], + lines = + missing.sort(function(lhs, rhs) { + return lhs.node[0].start.line < rhs.node[0].start.line ? -1 : + lhs.node[0].start.line > rhs.node[0].start.line ? 1 : + 0; + }).filter(function(node) { + + var okay = (seenLines.indexOf(node.node[0].start.line) < 0); + if(okay) + seenLines.push(node.node[0].start.line); + return okay; + + }).map(function(node, idx, all) { + return { + lineno:node.node[0].start.line + 1, + source:function() { return filedata[node.node[0].start.line]; } + }; + }); + + return { + percentage:(filedata.length-seenLines.length)/filedata.length, + lines:lines, + missing:seenLines.length, + seen:(filedata.length-seenLines.length) + }; +}; + +module.exports.createEnvironment = function(module, filename) { + var req = function(path) { + return Module._load(path, module); + }; + req.resolve = function(request) { + return Module._resolveFilename(request, module)[1]; + } + req.paths = Module._paths; + req.main = process.mainModule; + req.extensions = Module._extensions; + req.registerExtension = function() { + throw new Error('require.registerExtension() removed. Use ' + + 'require.extensions instead.'); + } + require.cache = Module._cache; + + var ctxt = {}; + for(var k in global) + ctxt[k] = global[k]; + + ctxt.require = req; + ctxt.exports = module.exports; + ctxt.__filename = filename; + ctxt.__dirname = path.dirname(filename); + ctxt.process = process; + ctxt.console = console; + ctxt.module = module; + ctxt.global = ctxt; + + return ctxt; +}; + +module.exports.cover = function(fileRegex) { + var originalRequire = require.extensions['.js'], + coverageData = {}, + match = fileRegex instanceof RegExp ? + fileRegex : new RegExp( + fileRegex ? fileRegex.replace(/\//g, '\\/').replace(/\./g, '\\.') : '.*' + , 'g'), + target = this; + + require.extensions['.js'] = function(module, filename) { + if(!match.test(filename)) return originalRequire(module, filename); + + var context = target.createEnvironment(module, filename), + data = fs.readFileSync(filename, 'utf8'), + bunkerized = bunker(data), + coverage = coverageData[filename] = new CoverageData(filename, bunkerized); + + bunkerized.on('node', coverage.visit.bind(coverage)); + bunkerized.assign(context); + + var wrapper = '(function(ctxt) { with(ctxt) { return '+Module.wrap(bunkerized.compile())+'; } })', + compiledWrapper = vm.runInThisContext(wrapper, filename, true)(context); + + var args = [context.exports, context.require, module, filename, context.__dirname]; + return compiledWrapper.apply(module.exports, args); + }; + + var retval = function(ready) { + ready(coverageData); + }; + + retval.release = function() { + require.extensions['.js'] = originalRequire; + }; + + return retval; +}; + diff --git a/node_modules/runforcover/package.json b/node_modules/runforcover/package.json new file mode 100644 index 0000000..f2a2ac6 --- /dev/null +++ b/node_modules/runforcover/package.json @@ -0,0 +1,32 @@ +{ + "name" : "runforcover", + "version" : "0.0.2", + "description" : "require plugin for js code coverage using bunker", + "main" : "index.js", + "directories" : { + "lib" : ".", + "test" : "test" + }, + "dependencies" : { + "bunker" : "0.1.X" + }, + "scripts" : { + "test" : "node test/index.js" + }, + "repository" : { + "type" : "git", + "url" : "http://github.com/chrisdickinson/node-runforcover.git" + }, + "keywords" : [ + "code", + "coverage", + "bunker" + ], + "author" : { + "name" : "Chris Dickinson", + "email" : "chris@neversaw.us", + "url" : "http://neversaw.us" + }, + "license" : "new BSD", + "engine" : { "node" : ">=0.4" } +} diff --git a/node_modules/runforcover/test/index.js b/node_modules/runforcover/test/index.js new file mode 100644 index 0000000..ea59662 --- /dev/null +++ b/node_modules/runforcover/test/index.js @@ -0,0 +1 @@ +require('./interface').coverageInterface() diff --git a/node_modules/runforcover/test/interface.js b/node_modules/runforcover/test/interface.js new file mode 100644 index 0000000..a6455ed --- /dev/null +++ b/node_modules/runforcover/test/interface.js @@ -0,0 +1,50 @@ +var assert = require('assert'); +var runforcover = require('../'); + +exports.coverageInterface = function() { + assert.ok(runforcover.cover); + + var originalRequire = require.extensions['.js']; + + var coverage = runforcover.cover(); + + assert.notEqual(originalRequire, require.extensions['.js']); + + var file = require('./src/coverage'); + + coverage(function(coverageData) { + assert.equal(Object.keys(coverageData).length, 1); + assert.equal(Object.keys(coverageData)[0], __dirname + '/src/coverage.js'); + + var fileCoverageData = coverageData[Object.keys(coverageData)[0]]; + + assert.ok(fileCoverageData.stats); + assert.ok(fileCoverageData.missing); + + var stats = fileCoverageData.stats(); + + assert.ok(stats.percentage !== undefined); + assert.ok(stats.lines !== undefined); + assert.ok(stats.missing !== undefined); + assert.ok(stats.seen !== undefined); + + assert.equal(stats.lines.length, 3); + assert.equal(stats.lines[0].source(), ' if(a > 0) {'); + assert.equal(stats.lines[1].source(), ' return a + 1;'); + assert.equal(stats.lines[2].source(), ' return a - 1;'); + + file.something(1); + stats = fileCoverageData.stats(); + + assert.equal(stats.lines.length, 1); + assert.equal(stats.lines[0].source(), ' return a - 1;'); + + file.something(-1); + stats = fileCoverageData.stats(); + + assert.equal(stats.lines.length, 0); + + coverage.release(); + assert.equal(require.extensions['.js'], originalRequire); + }); +}; diff --git a/node_modules/runforcover/test/src/coverage.js b/node_modules/runforcover/test/src/coverage.js new file mode 100644 index 0000000..5b88dfe --- /dev/null +++ b/node_modules/runforcover/test/src/coverage.js @@ -0,0 +1,7 @@ +exports.something = function(a) { + if(a > 0) { + return a + 1; + } else { + return a - 1; + } +}; diff --git a/node_modules/slide/LICENSE b/node_modules/slide/LICENSE new file mode 100644 index 0000000..05eeeb8 --- /dev/null +++ b/node_modules/slide/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/slide/README.md b/node_modules/slide/README.md new file mode 100644 index 0000000..59ad738 --- /dev/null +++ b/node_modules/slide/README.md @@ -0,0 +1,143 @@ +# Controlling Flow: callbacks are easy + +## What's actually hard? + +- Doing a bunch of things in a specific order. +- Knowing when stuff is done. +- Handling failures. +- Breaking up functionality into parts (avoid nested inline callbacks) + + +## Common Mistakes + +- Abandoning convention and consistency. +- Putting all callbacks inline. +- Using libraries without grokking them. +- Trying to make async code look sync. + +## Define Conventions + +- Two kinds of functions: *actors* take action, *callbacks* get results. +- Essentially the continuation pattern. Resulting code *looks* similar + to fibers, but is *much* simpler to implement. +- Node works this way in the lowlevel APIs already, and it's very flexible. + +## Callbacks + +- Simple responders +- Must always be prepared to handle errors, that's why it's the first argument. +- Often inline anonymous, but not always. +- Can trap and call other callbacks with modified data, or pass errors upwards. + +## Actors + +- Last argument is a callback. +- If any error occurs, and can't be handled, pass it to the callback and return. +- Must not throw. Return value ignored. +- return x ==> return cb(null, x) +- throw er ==> return cb(er) + +```javascript +// return true if a path is either +// a symlink or a directory. +function isLinkOrDir (path, cb) { + fs.lstat(path, function (er, s) { + if (er) return cb(er) + return cb(null, s.isDirectory() || s.isSymbolicLink()) + }) +} +``` + +# asyncMap + +## Usecases + +- I have a list of 10 files, and need to read all of them, and then continue when they're all done. +- I have a dozen URLs, and need to fetch them all, and then continue when they're all done. +- I have 4 connected users, and need to send a message to all of them, and then continue when that's done. +- I have a list of n things, and I need to dosomething with all of them, in parallel, and get the results once they're all complete. + + +## Solution + +```javascript +var asyncMap = require("slide").asyncMap +function writeFiles (files, what, cb) { + asyncMap(files, function (f, cb) { + fs.writeFile(f, what, cb) + }, cb) +} +writeFiles([my, file, list], "foo", cb) +``` + +# chain + +## Usecases + +- I have to do a bunch of things, in order. Get db credentials out of a file, + read the data from the db, write that data to another file. +- If anything fails, do not continue. +- I still have to provide an array of functions, which is a lot of boilerplate, + and a pita if your functions take args like + +```javascript +function (cb) { + blah(a, b, c, cb) +} +``` + +- Results are discarded, which is a bit lame. +- No way to branch. + +## Solution + +- reduces boilerplate by converting an array of [fn, args] to an actor + that takes no arguments (except cb) +- A bit like Function#bind, but tailored for our use-case. +- bindActor(obj, "method", a, b, c) +- bindActor(fn, a, b, c) +- bindActor(obj, fn, a, b, c) +- branching, skipping over falsey arguments + +```javascript +chain([ + doThing && [thing, a, b, c] +, isFoo && [doFoo, "foo"] +, subChain && [chain, [one, two]] +], cb) +``` + +- tracking results: results are stored in an optional array passed as argument, + last result is always in results[results.length - 1]. +- treat chain.first and chain.last as placeholders for the first/last + result up until that point. + + +## Non-trivial example + +- Read number files in a directory +- Add the results together +- Ping a web service with the result +- Write the response to a file +- Delete the number files + +```javascript +var chain = require("slide").chain +function myProgram (cb) { + var res = [], last = chain.last, first = chain.first + chain([ + [fs, "readdir", "the-directory"] + , [readFiles, "the-directory", last] + , [sum, last] + , [ping, "POST", "example.com", 80, "/foo", last] + , [fs, "writeFile", "result.txt", last] + , [rmFiles, "./the-directory", first] + ], res, cb) +} +``` + +# Conclusion: Convention Profits + +- Consistent API from top to bottom. +- Sneak in at any point to inject functionality. Testable, reusable, ... +- When ruby and python users whine, you can smile condescendingly. diff --git a/node_modules/slide/index.js b/node_modules/slide/index.js new file mode 100644 index 0000000..0a9277f --- /dev/null +++ b/node_modules/slide/index.js @@ -0,0 +1 @@ +module.exports=require("./lib/slide") diff --git a/node_modules/slide/lib/async-map-ordered.js b/node_modules/slide/lib/async-map-ordered.js new file mode 100644 index 0000000..5cca79a --- /dev/null +++ b/node_modules/slide/lib/async-map-ordered.js @@ -0,0 +1,65 @@ + +throw new Error("TODO: Not yet implemented.") + +/* +usage: + +Like asyncMap, but only can take a single cb, and guarantees +the order of the results. +*/ + +module.exports = asyncMapOrdered + +function asyncMapOrdered (list, fn, cb_) { + if (typeof cb_ !== "function") throw new Error( + "No callback provided to asyncMapOrdered") + + if (typeof fn !== "function") throw new Error( + "No map function provided to asyncMapOrdered") + + if (list === undefined || list === null) return cb_(null, []) + if (!Array.isArray(list)) list = [list] + if (!list.length) return cb_(null, []) + + var errState = null + , l = list.length + , a = l + , res = [] + , resCount = 0 + , maxArgLen = 0 + + function cb (index) { return function () { + if (errState) return + var er = arguments[0] + var argLen = arguments.length + maxArgLen = Math.max(maxArgLen, argLen) + res[index] = argLen === 1 ? [er] : Array.apply(null, arguments) + + // see if any new things have been added. + if (list.length > l) { + var newList = list.slice(l) + a += (list.length - l) + var oldLen = l + l = list.length + process.nextTick(function () { + newList.forEach(function (ar, i) { fn(ar, cb(i + oldLen)) }) + }) + } + + if (er || --a === 0) { + errState = er + cb_.apply(null, [errState].concat(flip(res, resCount, maxArgLen))) + } + }} + // expect the supplied cb function to be called + // "n" times for each thing in the array. + list.forEach(function (ar) { + steps.forEach(function (fn, i) { fn(ar, cb(i)) }) + }) +} + +function flip (res, resCount, argLen) { + var flat = [] + // res = [[er, x, y], [er, x1, y1], [er, x2, y2, z2]] + // return [[x, x1, x2], [y, y1, y2], [undefined, undefined, z2]] + diff --git a/node_modules/slide/lib/async-map.js b/node_modules/slide/lib/async-map.js new file mode 100644 index 0000000..ccf345f --- /dev/null +++ b/node_modules/slide/lib/async-map.js @@ -0,0 +1,54 @@ + +/* +usage: + +// do something to a list of things +asyncMap(myListOfStuff, function (thing, cb) { doSomething(thing.foo, cb) }, cb) +// do more than one thing to each item +asyncMap(list, fooFn, barFn, cb) + +*/ + +module.exports = asyncMap + +function asyncMap () { + var steps = Array.prototype.slice.call(arguments) + , list = steps.shift() || [] + , cb_ = steps.pop() + if (typeof cb_ !== "function") throw new Error( + "No callback provided to asyncMap") + if (!list) return cb_(null, []) + if (!Array.isArray(list)) list = [list] + var n = steps.length + , data = [] // 2d array + , errState = null + , l = list.length + , a = l * n + if (!a) return cb_(null, []) + function cb (er) { + if (er && !errState) errState = er + + var argLen = arguments.length + for (var i = 1; i < argLen; i ++) if (arguments[i] !== undefined) { + data[i - 1] = (data[i - 1] || []).concat(arguments[i]) + } + // see if any new things have been added. + if (list.length > l) { + var newList = list.slice(l) + a += (list.length - l) * n + l = list.length + process.nextTick(function () { + newList.forEach(function (ar) { + steps.forEach(function (fn) { fn(ar, cb) }) + }) + }) + } + + if (--a === 0) cb_.apply(null, [errState].concat(data)) + } + // expect the supplied cb function to be called + // "n" times for each thing in the array. + list.forEach(function (ar) { + steps.forEach(function (fn) { fn(ar, cb) }) + }) +} diff --git a/node_modules/slide/lib/bind-actor.js b/node_modules/slide/lib/bind-actor.js new file mode 100644 index 0000000..6a37072 --- /dev/null +++ b/node_modules/slide/lib/bind-actor.js @@ -0,0 +1,16 @@ +module.exports = bindActor +function bindActor () { + var args = + Array.prototype.slice.call + (arguments) // jswtf. + , obj = null + , fn + if (typeof args[0] === "object") { + obj = args.shift() + fn = args.shift() + if (typeof fn === "string") + fn = obj[ fn ] + } else fn = args.shift() + return function (cb) { + fn.apply(obj, args.concat(cb)) } +} diff --git a/node_modules/slide/lib/chain.js b/node_modules/slide/lib/chain.js new file mode 100644 index 0000000..17b3711 --- /dev/null +++ b/node_modules/slide/lib/chain.js @@ -0,0 +1,20 @@ +module.exports = chain +var bindActor = require("./bind-actor.js") +chain.first = {} ; chain.last = {} +function chain (things, cb) { + var res = [] + ;(function LOOP (i, len) { + if (i >= len) return cb(null,res) + if (Array.isArray(things[i])) + things[i] = bindActor.apply(null, + things[i].map(function(i){ + return (i===chain.first) ? res[0] + : (i===chain.last) + ? res[res.length - 1] : i })) + if (!things[i]) return LOOP(i + 1, len) + things[i](function (er, data) { + if (er) return cb(er, res) + if (data !== undefined) res = res.concat(data) + LOOP(i + 1, len) + }) + })(0, things.length) } diff --git a/node_modules/slide/lib/slide.js b/node_modules/slide/lib/slide.js new file mode 100644 index 0000000..6e9ec23 --- /dev/null +++ b/node_modules/slide/lib/slide.js @@ -0,0 +1,3 @@ +exports.asyncMap = require("./async-map") +exports.bindActor = require("./bind-actor") +exports.chain = require("./chain") diff --git a/node_modules/slide/package.json b/node_modules/slide/package.json new file mode 100644 index 0000000..7799184 --- /dev/null +++ b/node_modules/slide/package.json @@ -0,0 +1,20 @@ +{ + "name": "slide", + "version": "1.1.6", + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "contributors": [ + "S. Sriram (http://www.565labs.com)" + ], + "description": "A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS", + "main": "./lib/slide.js", + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/slide-flow-control.git" + }, + "license": "ISC" +} diff --git a/node_modules/tap/.npmignore b/node_modules/tap/.npmignore new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/tap/AUTHORS b/node_modules/tap/AUTHORS new file mode 100644 index 0000000..898b613 --- /dev/null +++ b/node_modules/tap/AUTHORS @@ -0,0 +1,8 @@ +# contributors sorted by whether or not they're me +Isaac Z. Schlueter +baudehlo +James Halliday +Jason Smith (air) +Pedro P. Candel +Stein Martin Hustad +Trent Mick diff --git a/node_modules/tap/LICENSE b/node_modules/tap/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/tap/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +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. diff --git a/node_modules/tap/README.md b/node_modules/tap/README.md new file mode 100644 index 0000000..7e061aa --- /dev/null +++ b/node_modules/tap/README.md @@ -0,0 +1,82 @@ +This is a mix-and-match set of utilities that you can use to write test +harnesses and frameworks that communicate with one another using the +Test Anything Protocol. + +If you don't yet know what TAP is, [you better ask +somebody](http://testanything.org/). + +Default Usage: + +1. Make a directory. Maybe call it 'test'. That'd be nice and obvious. +2. Put a bunch of test scripts in there. If they're node programs, then + they should be ".js". Anything else is assumed to be some kind of shell + script, which should have a shebang line. +3. `npm install tap` +4. `tap ./tests` + +The output will be TAP-compliant. + +For extra special bonus points, you can do something like this: + + var test = require("tap").test + test("make sure the thingie is a thing", function (t) { + t.equal(thingie, "thing", "thingie should be thing") + t.type(thingie, "string", "type of thingie is string") + t.ok(true, "this is always true") + t.notOk(false, "this is never true") + t.test("a child test", function (t) { + t.equal(this, superEasy, "right!?") + t.similar(7, 2, "ever notice 7 is kinda like 2?", {todo: true}) + t.test("so skippable", {skip: true}, function (t) { + t.plan(1) // only one test in this block + t.ok(true, "but when the flag changes, it'll pass") + // no need to end, since we had a plan. + }) + t.end() + }) + t.ok(99, "can also skip individual assertions", {skip: true}) + // end lets it know it's over. + t.end() + }) + test("another one", function (t) { + t.plan(1) + t.ok(true, "It's ok to plan, and also end. Watch.") + t.end() // but it must match the plan! + }) + +Node-tap is actually a collection of several modules, any of which may be +mixed and matched however you please. + +If you don't like this test framework, and think you can do much much +better, *I strongly encourage you to do so!* If you use this library, +however, at least to output TAP-compliant results when `process.env.TAP` +is set, then the data coming out of your framework will be much more +consumable by machines. + +You can also use this to build programs that *consume* the TAP data, so +this is very useful for CI systems and such. + +* tap-assert: A collection of assert functions that return TAP result + objects. +* tap-consumer: A stream interface for consuming TAP data. +* tap-producer: A class that produces a TAP stream by taking in result + objects. +* tap-results: A class for keeping track of TAP result objects as they + pass by, counting up skips, passes, fails, and so on. +* tap-runner: A program that runs through a directory running all the + tests in it. (Tests which may or may not be TAP-outputting tests. But + it's better if they are.) +* tap-test: A class for actually running tests. +* tap-harness: A class that runs tests. (Tests are also Harnesses, + which is how sub-tests run.) +* tap-global-harness: A default harness that provides the top-level + support for running TAP tests. + +## Experimental Code Coverage with runforcover & bunker: + +``` +TAP_COV=1 tap ./tests [--cover=./lib,foo.js] [--cover-dir=./coverage] +``` + +This feature is experimental, and will most likely change somewhat +before being finalized. Feedback welcome. diff --git a/node_modules/tap/bin/tap-http.js b/node_modules/tap/bin/tap-http.js new file mode 100644 index 0000000..296910f --- /dev/null +++ b/node_modules/tap/bin/tap-http.js @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +// just an example, really +// Run with `node tap-http.js path/to/tests/` + +var argv = process.argv.slice(2) + , path = require("path") + , Runner = require("../lib/tap-runner") + + , http = require("http") + , server = http.createServer(function (req, res) { + // it'd be nice to return a non-200 if the tests fail, but we don't + // know the status until it's done, so that would mean not being able + // to pipe the output + res.writeHead(200, {'content-type': 'text/plain'}) + new Runner(argv, null).pipe(res) + }) + +server.listen(1337) diff --git a/node_modules/tap/bin/tap-reader.js b/node_modules/tap/bin/tap-reader.js new file mode 100755 index 0000000..b196cc2 --- /dev/null +++ b/node_modules/tap/bin/tap-reader.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +// read a tap stream from stdin. + +var TapConsumer = require("../lib/tap-consumer") + , TapProducer = require("../lib/tap-producer") + +var tc = new TapConsumer + , tp = new TapProducer + +//process.stdin.pipe(tc) +process.stdin.on("data", function (c) { + c = c + "" + // console.error(JSON.stringify(c).substr(0, 100)) + tc.write(c) +}) +process.stdin.on("end", function () { tc.end() }) +process.stdin.resume() +//tc.pipe(tp) +tc.on("data", function (c) { + tp.write(c) +}) +tc.on("end", function () { tp.end() }) + +tp.on("data", function (c) { + console.error(["output write", c]) + process.stdout.write(c) +}) + +tp.on("end", function (er, total, ok) { + if (er) throw er + process.exit(total - ok) +}) diff --git a/node_modules/tap/bin/tap.js b/node_modules/tap/bin/tap.js new file mode 100755 index 0000000..e6e7c8e --- /dev/null +++ b/node_modules/tap/bin/tap.js @@ -0,0 +1,127 @@ +#!/usr/bin/env node + +var argv = process.argv.slice(2) + , path = require("path") + , Runner = require("../lib/tap-runner") + + , nopt = require("nopt") + + , knownOpts = + { cover: [path, false] + , "cover-dir": path + , stderr: Boolean + , stdout: Boolean + , diag: Boolean + , version: Boolean + , tap: Boolean + , timeout: Number + } + + , shorthands = + // debugging 1: show stderr + { d: ["--stderr"] + // debugging 2: show stderr and tap + , dd: ["--stderr", "--tap"] + // debugging 3: show stderr, tap, AND always show diagnostics. + , ddd: ["--stderr", "--tap", "--diag"] + , e: ["--stderr"] + , t: ["--timeout"] + , o: ["--tap"] + , c: ["--cover"] + , v: ["--version"] + , "?": ["--help"] + , h: ["--help"] + } + + , defaults = + { cover: "./lib" + , "cover-dir": "./coverage" + , stderr: process.env.TAP_STDERR + , tap: process.env.TAP + , diag: process.env.TAP_DIAG + , timeout: +process.env.TAP_TIMEOUT || 30 + , version: false + , help: false } + + , options = nopt(knownOpts, shorthands) + +if (options.version) { + console.log(require("../package.json").version) + process.exit(0) +} + +if (options.help) { + console.log(function(){/* + +Usage: + tap + + Run the files as tap tests, parse the output, and report the results + +Options: + + --stderr Print standard error output of tests to standard error. + --tap Print raw tap output. + --diag Print diagnostic output for passed tests, as well as failed. + (Implies --tap) + --timeout Maximum time to wait for a subtest, in seconds. Default: 30 + --version Print the version of node tap + --help Print this help + +Please report bugs! https://github.com/isaacs/node-tap/issues + +*/}.toString().split(/\n/).slice(1, -1).join("\n")) + process.exit(0) +} + + +Object.keys(defaults).forEach(function (k) { + if (!options.hasOwnProperty(k)) options[k] = defaults[k] +}) + +// other tests that might rely on these +if (options.diag) process.env.TAP_DIAG = true +if (options.tap) process.env.TAP = true +if (options.timeout) process.env.TAP_TIMEOUT = options.timeout + +var r = new Runner(options) + , TapProducer = require("../lib/tap-producer") + +if (options.tap || options.diag) { + r.pipe(process.stdout) +} else { + r.on("file", function (file, results, details) { + var s = (details.ok ? "" : "not ") + "ok "+results.name + , n = details.pass + "/" + details.testsTotal + , dots = new Array(Math.max(1, 60 - s.length - n.length)).join(".") + console.log("%s %s %s", s, dots, n) + if (details.ok) { + if (details.skip) { + console.log(" skipped: %s", details.skipTotal) + } + } else { + // console.error(details) + console.log(" Command: %s", results.command) + console.log(" " + TapProducer.encode(details.list) + .split(/\n/).join("\n ")) + } + }) + r.on("end", function () { + //console.log(r) + var s = "total" + , n = r.results.pass + "/" + r.results.testsTotal + , dots = new Array(60 - s.length - n.length).join(".") + , ok = r.results.ok ? "ok" : "not ok" + console.log("%s %s %s\n\n%s", s, dots, n, ok) + if (r.doCoverage) { + console.error( "\nCoverage: %s\n" + , path.resolve(r.coverageOutDir, "index.html") ) + } + }) +} + + + +r.on("end", function () { + process.exit(r.results.tests - r.results.pass) +}) diff --git a/node_modules/tap/coverage-example/lib/bar.js b/node_modules/tap/coverage-example/lib/bar.js new file mode 100644 index 0000000..e7cb7ad --- /dev/null +++ b/node_modules/tap/coverage-example/lib/bar.js @@ -0,0 +1,15 @@ +var Bar = module.exports = function(str) { + this.bar = str; + this.str = str; +}; + +Bar.prototype.foo = function() { + var self = this; + return self.bar; +}; + +Bar.prototype.baz = function() { + var self = this; + return self.str; +}; + diff --git a/node_modules/tap/coverage-example/lib/foo.js b/node_modules/tap/coverage-example/lib/foo.js new file mode 100644 index 0000000..cb9ee8f --- /dev/null +++ b/node_modules/tap/coverage-example/lib/foo.js @@ -0,0 +1,15 @@ +var Foo = module.exports = function(str) { + this.foo = str; + this.str = str; +}; + +Foo.prototype.bar = function() { + var self = this; + return self.foo; +}; + +Foo.prototype.baz = function() { + var self = this; + return self.str; +}; + diff --git a/node_modules/tap/coverage-example/test/bar.test.js b/node_modules/tap/coverage-example/test/bar.test.js new file mode 100644 index 0000000..91e4bc2 --- /dev/null +++ b/node_modules/tap/coverage-example/test/bar.test.js @@ -0,0 +1,20 @@ +var test = require('tap').test, + Bar = require('../lib/bar'), + bar; + +test('setup', function(t) { + bar = new Bar('baz'); + t.ok(bar); + t.end(); +}); + +test('bar', function(t) { + t.equal('baz', bar.foo()); + t.end(); +}); + +test('teardown', function(t) { + t.ok(true); + t.end(); +}); + diff --git a/node_modules/tap/coverage-example/test/baz.test.js b/node_modules/tap/coverage-example/test/baz.test.js new file mode 100644 index 0000000..fae22d8 --- /dev/null +++ b/node_modules/tap/coverage-example/test/baz.test.js @@ -0,0 +1,29 @@ +var test = require('tap').test, + Foo = require('../lib/foo'), + Bar = require('../lib/bar'), + foo, bar; + +test('setup', function(t) { + foo = new Foo('baz'); + t.ok(foo); + bar = new Bar('baz'); + t.ok(bar); + t.end(); +}); + +test('baz from Foo', function(t) { + t.equal('baz', foo.baz()); + t.end(); +}); + +test('baz from Bar', function(t) { + t.equal('baz', bar.baz()); + t.end(); +}); + + +test('teardown', function(t) { + t.ok(true); + t.end(); +}); + diff --git a/node_modules/tap/coverage-example/test/foo.test.js b/node_modules/tap/coverage-example/test/foo.test.js new file mode 100644 index 0000000..2aed8fd --- /dev/null +++ b/node_modules/tap/coverage-example/test/foo.test.js @@ -0,0 +1,20 @@ +var test = require('tap').test, + Foo = require('../lib/foo'), + foo; + +test('setup', function(t) { + foo = new Foo('baz'); + t.ok(foo); + t.end(); +}); + +test('bar', function(t) { + t.equal('baz', foo.bar()); + t.end(); +}); + +test('teardown', function(t) { + t.ok(true); + t.end(); +}); + diff --git a/node_modules/tap/example/lib/math.js b/node_modules/tap/example/lib/math.js new file mode 100644 index 0000000..f798626 --- /dev/null +++ b/node_modules/tap/example/lib/math.js @@ -0,0 +1 @@ +module.exports = Math diff --git a/node_modules/tap/example/test/test-example.js b/node_modules/tap/example/test/test-example.js new file mode 100644 index 0000000..cd2549b --- /dev/null +++ b/node_modules/tap/example/test/test-example.js @@ -0,0 +1,237 @@ +var tap = require("tap") + , test = tap.test + , plan = tap.plan + , math + +test("load sut", function (t) { + math = require("../lib/math") + t.ok(math, "object loaded") + t.end() +}) + +test("validate constants", function (t) { + t.equal(math.LN10, 2.302585092994046, "ln 10") + t.equal(math.PI, 3.141592653589793, "pi") + t.equal(math.E, 2.718281828459045, "e") + t.equal(math.LOG10E, 0.4342944819032518, "log 10 e") + t.equal(math.SQRT2, 1.4142135623730951, "sqrt 2") + t.equal(math.SQRT1_2, 0.7071067811865476, "sqrt 1/2") + t.equal(math.LN2, 0.6931471805599453, "ln2") + t.end() +}) + +test("using this", function (t) { + // this also works. + this.equal(t, this, "call in scope of test obj") + this.end() +}) + +// test setTimeout, just a trivial example. +test("setTimeout", function (t) { + var start = Date.now() + setTimeout(function () { + t.ok(Date.now() >= start + 50, "timeout fired after delay") + t.end() + }, 50) +}) + +// another way to do the same, using a plan. +// this is more robust, but annoying when you have a long list +// of tests for something. For async stuff, it's generally better, +// since there's a higher risk of the control flowing off to lala land. +test("setTimeout planned", function (t) { + t.plan(1) + var start = Date.now() + setTimeout(function () { + t.ok(Date.now() >= start + 50, "timeout fired after delay") + }, 50) +}) + +// plans also are good for cases where things may fire in a non-deterministic +// order, since it won't be as obvious when everything is done. +test("setTimeout parallel", function (t) { + t.plan(2) + var start = Date.now() + setTimeout(function A () { + t.ok(Date.now() >= start + 50, "timeout A fired after delay") + }, 50) + setTimeout(function B () { + t.ok(Date.now() >= start + 50, "timeout B fired after delay") + }, 50) +}) + +// something slightly less hello worldy +test("async test", function (t) { + t.plan(4) + var fs = require("fs") + t.ok(fs, "fs library should load") + var rs = fs.createReadStream(__filename) + t.ok(rs, "read stream should start fine.") + rs.on("open", function (fd) { + t.type(fd, "number", "file descriptor should be a number") + t.equal(fd, rs.fd, "fd should match stream fd") + }) +}) + +// you can bail out of the entire everything if something is just +// Not Right (db not installed, etc.) +test("tarp", function (parent) { + if (7 === 5) { + parent.bailout("math is broken") + } + // bailout bubbles up a bit like "error" events + // if unhandled, then the parent will bail, as well. + parent.test("child bailouts", function (child) { + child.on("bailout", function (s) { + parent.fail("children shouldn't bail.") + }) + child.bailout("try to bail out, but instead just fail a test") + }) + + parent.test("child bailout 2", function (child) { + child.bailout("this one will bail out") + }) +}) + +// tests marked "todo" can fail without counting against the overall score +// never ever ever write tests to "verify" incorrect behavior! +test("unfinished test", function (t) { + t.equal(math.cos(math.PI), -1, "cos(PI)") + t.equal(math.sin(math.PI), 0, "sin(PI)") + t.equal(math.face, "your face", "math.face should be your face # TODO") + t.end() +}) + +// tests can have children. +test("http server", function (t) { + // one test plus 4 children. + t.plan(5) + + var http = require("http") + , PORT = 12346 + + t.ok(http, "http module should load") + var server + + t.test("set up server", function (t) { + t.plan(2) + server = http.createServer(function (req, res) { + t.comment("Request: "+req.url) + res.writeHead(200, {}) + res.end(req.method + " " + req.url) + }) + t.ok(server, "createServer should create a server") + server.listen(PORT, t.cb("listen should fire callback")) + }) + + // set the "parallel" flag on this one. + // That signals the harness to proceed immediately to the next test, + // and run them in parallel. + // Default behavior is to wait for each test to complete before proceeding + // to the next one. + // The first not-parallel test encountered will cause it to wait for that + // test, as well as all the parallel tests before it. + // A, B', C', D', E (where ' means "parallel") + // Runs A, and then B, C, and D in parallel, and then E. + t.test("testing POST", {parallel: true}, function (t) { + t.plan(1) + http.request("POST", { method: "POST" + , host: "localhost" + , path: "/foo" + , port: PORT }).on("response", function (res) { + t.bufferStream(res, function (s) { t.equal(s, "POST /foo") }) + }).end() + }) + + t.test("testing GET", {parallel: true}, function (t) { + t.plan(1) + http.request("POST", { method: "GET" + , host: "localhost" + , path: "/foo" + , port: PORT }).on("response", function (res) { + t.bufferStream(res, function (s) { t.equal(s, "GET /foo") }) + }).end() + }) + + // wrap in a test so that if this throws, it'll log as a failed test. + t.test("teardown", function (t) { + server.close() + t.end() + }) +}) + +// yo dawg! +test("meta-tests", function (t) { + t.plan(5) + + // t.fails() wraps a child test and succeeds if it fails. + t.fails(t.test("this should fail", function (t) { + t.ok(false, "assert false") + t.end() + })) + + // t.timesOut() wraps a child test and succeeds if it times out. + // if t.end() is called, or if a plan is completed, then it fails. + // set the timeout really low so that it will not take forever. + t.timesOut(t.test("this should timeout", { timeout: 1 }, function (t) { + t.ok(true, "assert true") + // t.end() never called. + })) + + // t.incomplete() wraps a child test and succeeds if it ends before + // the plan is finished. + t.incomplete(t.test("this should be incomplete", function (t) { + t.plan(100) + t.ok(true, "assert true") + // calling end prematurely. + t.end() + })) + + // t.bailsOut() wraps a child test and succeeds if it calls bailout() + t.bailsOut(t.test("this should bailout", function (t) { + t.bailout("oh noes, bailing out!") + })) + + // low-level analysis of subtests + t.test("verifying test success/failure expectations", function (t) { + t.once("end", function () { + var res = t.results + , is = t.equal + // hijack! + t.clear() + is(res.ok, false, "ok") + + is(res.bailedOut, false, "bailed out") + + is(res.skip, 2, "skips") + is(res.skipPass, 1, "skip that passed") + is(res.skipFail, 1, "skip that failed") + + is(res.todo, 2, "todos") + is(res.todoPass, 1, "todo that passed") + is(res.todoFail, 1, "todo that failed") + + is(res.failTotal, 3, "failures total") + is(res.fail, 1, "relevant failure") + + is(res.passTotal, 3, "passes total") + is(res.pass, 1, "relevant pass") + + is(res.testsTotal, 6, "total tests") + is(res.tests, 2, "should be 2 relevant tests") + + t.end() + }) + + // run the metatest. + // *this* is the actual SUT in this case. + t.ok(false, "failing todo #todo") + // can also set #todo or #skip explicitly + t.ok(true, "succeeding todo", {todo: true}) + t.ok(false, "failing skip #skip", {skip: true}) + t.ok(true, "suceeding skip #skip") + t.ok(false, "failing test") + t.ok(true, "succeeding test") + t.end() + }) +}) diff --git a/node_modules/tap/lib/main.js b/node_modules/tap/lib/main.js new file mode 100644 index 0000000..a9a520a --- /dev/null +++ b/node_modules/tap/lib/main.js @@ -0,0 +1,16 @@ + +var GlobalHarness = require("./tap-global-harness") + +// this lets you do stuff like: +// var test = require("tap").test +// test(...) +// to run stuff in the global harness. +exports = module.exports = new GlobalHarness() + +exports.createProducer = exports.Producer = require("./tap-producer") +exports.createConsumer = exports.Consumer = require("./tap-consumer") +exports.yamlish = require("yamlish") +exports.createTest = exports.Test = require("./tap-test") +exports.createHarness = exports.Harness = require("./tap-harness") +exports.createRunner = exports.Runner = require("./tap-runner") +exports.assert = require("./tap-assert") diff --git a/node_modules/tap/lib/tap-assert.js b/node_modules/tap/lib/tap-assert.js new file mode 100644 index 0000000..bde5f11 --- /dev/null +++ b/node_modules/tap/lib/tap-assert.js @@ -0,0 +1,442 @@ +// an assert module that returns tappable data for each assertion. +var difflet = require('difflet') + , deepEqual = require('deep-equal') + , bufferEqual = require('buffer-equal') + +module.exports = assert + +var syns = {} + , id = 1 + +function assert (ok, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + + //console.error("assert %j", [ok, message, extra]) + //if (extra && extra.skip) return assert.skip(message, extra) + //console.error("assert", [ok, message, extra]) + ok = !!ok + var res = { id : id ++, ok: ok } + + var caller = getCaller(extra && extra.error) + if (extra && extra.error) { + res.type = extra.error.name + res.message = extra.error.message + res.code = extra.error.code + || extra.error.type + res.errno = extra.error.errno + delete extra.error + } + if (caller.file) { + res.file = caller.file + res.line = +caller.line + res.column = +caller.column + } + res.stack = caller.stack + + res.name = message || "(unnamed assert)" + + if (extra) Object.keys(extra).forEach(function (k) { + if (!res.hasOwnProperty(k)) res[k] = extra[k] + }) + + // strings and objects are hard to diff by eye + if (!ok && + res.hasOwnProperty("found") && + res.hasOwnProperty("wanted") && + res.found !== res.wanted) { + if (typeof res.wanted !== typeof res.found || + typeof res.wanted === "object" && (!res.found || !res.wanted)) { + res.type = { found: typeof found + , wanted: typeof wanted } + } else if (typeof res.wanted === "string") { + res.diff = diffString(res.found, res.wanted) + } else if (typeof res.wanted === "object") { + res.diff = diffObject(res.found, res.wanted) + } + } + + //console.error("assert return", res) + + return res +} +assert.ok = assert +syns.ok = [ "true", "assert" ] + + +function notOk (ok, message, extra) { + return assert(!ok, message, extra) +} +assert.notOk = notOk +syns.notOk = [ "false", "notok" ] + +function error (er, message, extra) { + if (!er) { + // just like notOk(er) + return assert(!er, message, extra) + } + message = message || er.message + extra = extra || {} + extra.error = er + return assert.fail(message, extra) +} +assert.error = error +syns.error = [ "ifError", "ifErr", "iferror" ] + + +function pass (message, extra) { + return assert(true, message, extra) +} +assert.pass = pass + +function fail (message, extra) { + //console.error("assert.fail", [message, extra]) + //if (extra && extra.skip) return assert.skip(message, extra) + return assert(false, message, extra) +} +assert.fail = fail + +function skip (message, extra) { + //console.error("assert.skip", message, extra) + if (!extra) extra = {} + return { id: id ++, skip: true, name: message || "" } +} +assert.skip = skip + +function throws (fn, wanted, message, extra) { + if (typeof wanted === "string") { + extra = message + message = wanted + wanted = null + } + + if (extra && extra.skip) return assert.skip(message, extra) + + var found = null + try { + fn() + } catch (e) { + found = { name: e.name, message: e.message } + } + + extra = extra || {} + + extra.found = found + if (wanted) { + wanted = { name: wanted.name, message: wanted.message } + extra.wanted = wanted + } + + if (!message) { + message = "Expected to throw" + if (wanted) message += ": "+wanted.name + " " + wanted.message + } + + return (wanted) ? assert.similar(found, wanted, message, extra) + : assert.ok(found, message, extra) +} +assert.throws = throws + + +function doesNotThrow (fn, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + var found = null + try { + fn() + } catch (e) { + found = {name: e.name, message: e.message} + } + message = message || "Should not throw" + + return assert.equal(found, null, message, extra) +} +assert.doesNotThrow = doesNotThrow + + +function equal (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + extra = extra || {} + message = message || "should be equal" + extra.found = a + extra.wanted = b + return assert(a === b, message, extra) +} +assert.equal = equal +syns.equal = ["equals" + ,"isEqual" + ,"is" + ,"strictEqual" + ,"strictEquals"] + + +function equivalent (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + var extra = extra || {} + message = message || "should be equivalent" + extra.found = a + extra.wanted = b + + if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { + return assert(bufferEqual(a, b), message, extra) + } else { + return assert(deepEqual(a, b), message, extra) + } +} +assert.equivalent = equivalent +syns.equivalent = ["isEquivalent" + ,"looseEqual" + ,"looseEquals" + ,"isDeeply" + ,"same" + ,"deepEqual" + ,"deepEquals"] + + +function inequal (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + extra = extra || {} + message = message || "should not be equal" + extra.found = a + extra.doNotWant = b + return assert(a !== b, message, extra) +} +assert.inequal = inequal +syns.inequal = ["notEqual" + ,"notEquals" + ,"isNotEqual" + ,"isNot" + ,"not" + ,"doesNotEqual" + ,"isInequal"] + + +function inequivalent (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + extra = extra || {} + message = message || "should not be equivalent" + extra.found = a + extra.doNotWant = b + + if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { + return assert(!bufferEqual(a, b), message, extra) + } else { + return assert(!deepEqual(a, b), message, extra) + } +} +assert.inequivalent = inequivalent +syns.inequivalent = ["notEquivalent" + ,"notDeepEqual" + ,"notDeeply" + ,"notSame" + ,"isNotDeepEqual" + ,"isNotDeeply" + ,"isNotEquivalent" + ,"isInequivalent"] + +function similar (a, b, message, extra, flip) { + if (extra && extra.skip) return assert.skip(message, extra) + // test that a has all the fields in b + message = message || "should be similar" + + if (typeof a === "string" && + (Object.prototype.toString.call(b) === "[object RegExp]")) { + extra = extra || {} + extra.pattern = b + extra.string = a + var ok = a.match(b) + extra.match = ok + if (flip) ok = !ok + return assert.ok(ok, message, extra) + } + + var isObj = assert(a && typeof a === "object", message, extra) + if (!isObj.ok) { + // not an object + if (a == b) isObj.ok = true + if (flip) isObj.ok = !isObj.ok + return isObj + } + + var eq = flip ? inequivalent : equivalent + return eq(selectFields(a, b), b, message, extra) +} +assert.similar = similar +syns.similar = ["isSimilar" + ,"has" + ,"hasFields" + ,"like" + ,"isLike"] + +function dissimilar (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + message = message || "should be dissimilar" + return similar(a, b, message, extra, true) +} +assert.dissimilar = dissimilar +syns.dissimilar = ["unsimilar" + ,"notSimilar" + ,"unlike" + ,"isUnlike" + ,"notLike" + ,"isNotLike" + ,"doesNotHave" + ,"isNotSimilar" + ,"isDissimilar"] + +function type (thing, t, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + var name = t + if (typeof name === "function") name = name.name || "(anonymous ctor)" + //console.error("name=%s", name) + message = message || "type is "+name + var type = typeof thing + //console.error("type=%s", type) + if (!thing && type === "object") type = "null" + if (type === "object" && t !== "object") { + if (typeof t === "function") { + //console.error("it is a function!") + extra = extra || {} + extra.found = Object.getPrototypeOf(thing).constructor.name + extra.wanted = name + //console.error(thing instanceof t, name) + return assert.ok(thing instanceof t, message, extra) + } + + //console.error("check prototype chain") + // check against classnames or objects in prototype chain, as well. + // type(new Error("asdf"), "Error") + // type(Object.create(foo), foo) + var p = thing + while (p = Object.getPrototypeOf(p)) { + if (p === t || p.constructor && p.constructor.name === t) { + type = name + break + } + } + } + //console.error(type, name, type === name) + return assert.equal(type, name, message, extra) +} +assert.type = type +syns.type = ["isa"] + +// synonyms are helpful. +Object.keys(syns).forEach(function (c) { + syns[c].forEach(function (s) { + Object.defineProperty(assert, s, { value: assert[c], enumerable: false }) + }) +}) + +// helpers below + +function selectFields (a, b) { + // get the values in A of the fields in B + var ret = Array.isArray(b) ? [] : {} + Object.keys(b).forEach(function (k) { + if (!a.hasOwnProperty(k)) return + var v = b[k] + , av = a[k] + if (v && av && typeof v === "object" && typeof av === "object" + && !(v instanceof Date) + && !(v instanceof RegExp) + && !(v instanceof String) + && !(v instanceof Boolean) + && !(v instanceof Number) + && !(Array.isArray(v))) { + ret[k] = selectFields(av, v) + } else ret[k] = av + }) + return ret +} + +function sortObject (obj) { + if (typeof obj !== 'object' || Array.isArray(obj) || obj === null) { + return obj + } + + return Object.keys(obj).sort().reduce(function (acc, key) { + acc[key] = sortObject(obj[key]) + return acc + }, {}) +} + +function stringify (a) { + return JSON.stringify(sortObject(a), (function () { + var seen = [] + , keys = [] + return function (key, val) { + var s = seen.indexOf(val) + if (s !== -1) { + return "[Circular: "+keys[s]+"]" + } + if (val && typeof val === "object" || typeof val === "function") { + seen.push(val) + keys.push(val["!"] || val.name || key || "") + if (typeof val === "function") { + return val.toString().split(/\n/)[0] + } else if (typeof val.toUTCString === "function") { + return val.toUTCString() + } + } + return val + }})()) +} + +function diffString (f, w) { + if (w === f) return null + var p = 0 + , l = w.length + while (p < l && w.charAt(p) === f.charAt(p)) p ++ + w = stringify(w).substr(1).replace(/"$/, "") + f = stringify(f).substr(1).replace(/"$/, "") + return diff(f, w, p) +} + +function diffObject (f, w) { + return difflet({ indent : 2, comment : true }).compare(w, f) +} + +function diff (f, w, p) { + if (w === f) return null + var i = p || 0 // it's going to be at least p. JSON can only be bigger. + , l = w.length + while (i < l && w.charAt(i) === f.charAt(i)) i ++ + var pos = Math.max(0, i - 20) + w = w.substr(pos, 40) + f = f.substr(pos, 40) + var pointer = i - pos + return "FOUND: "+f+"\n" + + "WANTED: "+w+"\n" + + (new Array(pointer + 9).join(" ")) + + "^ (at position = "+p+")" +} + +function getCaller (er) { + // get the first file/line that isn't this file. + if (!er) er = new Error + var stack = er.stack || "" + stack = stack.split(/\n/) + for (var i = 1, l = stack.length; i < l; i ++) { + var s = stack[i].match(/\(([^):]+):([0-9]+):([0-9]+)\)$/) + if (!s) continue + var file = s[1] + , line = +s[2] + , col = +s[3] + if (file.indexOf(__dirname) === 0) continue + if (file.match(/tap-test\/test.js$/)) continue + else break + } + var res = {} + if (file && file !== __filename && !file.match(/tap-test\/test.js$/)) { + res.file = file + res.line = line + res.column = col + } + + res.stack = stack.slice(1).map(function (s) { + return s.replace(/^\s*at\s*/, "") + }) + + return res +} + + diff --git a/node_modules/tap/lib/tap-browser-harness.js b/node_modules/tap/lib/tap-browser-harness.js new file mode 100644 index 0000000..6e6cda7 --- /dev/null +++ b/node_modules/tap/lib/tap-browser-harness.js @@ -0,0 +1,63 @@ +// this is just a harness that pipes to stdout. +// It's the default one. +module.exports = BrowserHarness + +var BrowserHarness = global.TAP_Browser_Harness + , inherits = require("inherits") + , Results = require("./tap-results") + , Harness = require("./tap-harness") + , Test = require("./tap-test") + +inherits(BrowserHarness, Harness) +function BrowserHarness (outPipe) { + //console.error("calling BrowserHarness") + if (browserHarness) return browserHarness + if (!(this instanceof BrowserHarness)) { + return browserHarness = new BrowserHarness + } + browserHarness = global.TAP_Browser_Harness = this + BrowserHarness.super.call(this, Test) + + if (outPipe) this.output.pipe(outPipe) + + this.test = this.test.bind(this) + + this.plan = this.plan.bind(this) + + var output = this.output + this.on("childEnd", function (child) { + //console.error("childEnd in global harness") + //console.error(child.results) + // write out the stuff for this child. + //console.error("child.conf", child.conf) + output.write(child.conf.name || "(unnamed test)") + // maybe write some other stuff about the number of tests in this + // thing, etc. I dunno. + //console.error("child results", child.results) + this.results.list.forEach(function (res) { + //delete res.error + //console.error("child resuilt", res) + output.write(res) + }) + //console.error("wrote child results") + this.results.list.length = 0 + }) + + var streamEnded = false + this.on("end", function () { + //console.error("global ending the stream") + if (!streamEnded) { + this.results.list.forEach(function (res) { + output.write(res) + }) + this.results.list.length = 0 + output.end() + streamEnded = true + } + }) + + // TODO: handle global errors + // process.on("unhandledException", function (e) { + // this.bailout("unhandled exception: " + e.message) + // }) +} diff --git a/node_modules/tap/lib/tap-consumer.js b/node_modules/tap/lib/tap-consumer.js new file mode 100644 index 0000000..3fd8fea --- /dev/null +++ b/node_modules/tap/lib/tap-consumer.js @@ -0,0 +1,243 @@ +module.exports = TapConsumer + +// pipe a stream into this that's emitting tap-formatted data, +// and it'll emit "data" events with test objects or comment strings +// and an "end" event with the final results. + +var yamlish = require("yamlish") + , Results = require("./tap-results") + , inherits = require("inherits") + +TapConsumer.decode = TapConsumer.parse = function (str) { + var tc = new TapConsumer + , list = [] + tc.on("data", function (res) { + list.push(res) + }) + tc.end(str) + tc.results.list = list + return tc.results +} + +inherits(TapConsumer, require("stream").Stream) +function TapConsumer () { + if (!(this instanceof TapConsumer)) { + return new TapConsumer + } + + TapConsumer.super.call(this) + this.results = new Results + this.readable = this.writable = true + + this.on("data", function (res) { + if (typeof res === "object") this.results.add(res) + }) + + this._plan = null + this._buffer = "" + this._indent = [] + this._current = null + this._actualCount = 0 + this._passed = [] + this._failed = [] + //console.error("TapConsumer ctor done") +} + +TapConsumer.prototype.bailedOut = false + +TapConsumer.prototype.write = function (chunk) { + if (!this.writable) this.emit("error", new Error("not writable")) + if (this.bailedOut) return true + + this._buffer = this._buffer + chunk + // split it up into lines. + var lines = this._buffer.split(/\r?\n/) + // ignore the last line, since it might be incomplete. + this._buffer = lines.pop() + + for (var i = 0, l = lines.length; i < l; i ++) { + //console.error([i, lines[i]]) + // see if it's indented. + var line = lines[i] + , spaces = (this._indent.length && !line.trim()) + || line.match(/^\s/) + // at this level, only interested in fully undented stuff. + if (spaces) { + var c = i + while (c < l && (!lines[c].trim() || lines[c].match(/^\s/))) { + this._indent.push(lines[c++]) + } + //console.error(c-i, "indented", this._indent, this._current) + i = c - 1 + continue + } + // some kind of line. summary, ok, notok, comment, or garbage. + // this also finishes parsing any of the indented lines from before + this._parseLine(line) + } + return true +} + +TapConsumer.prototype.end = function () { + // finish up any hanging indented sections or final buffer + if (this._buffer.match(/^\s/)) this._indent.push(this.buffer) + else this._parseLine(this._buffer) + + if (!this.bailedOut && + this._plan !== null && + this.results.testsTotal !== this._plan) { + while (this._actualCount < this._plan) { + this.emit("data", {ok: false, name:"MISSING TEST", + id:this._actualCount ++ }) + } + } + + this._parseLine("") + this._buffer = "" + this.writable = false + this.emit("end", null, this._actualCount, this._passed) +} + +TapConsumer.prototype._parseLine = function (line) { + if (this.bailedOut) return + //console.error("_parseLine", [line]) + // if there are any indented lines, and there is a + // current object already, then they belong to it. + // if there is not a current object, then they're garbage. + if (this._current && this._indent.length) { + this._parseIndented() + } + this._indent.length = 0 + if (this._current) { + if (this._current.ok) this._passed.push(this._current.id) + else this._failed.push(this._current.id) + this.emit("data", this._current) + } + this._current = null + line = line.trim() + if (!line) return + // try to see what kind of line this is. + + var bo + if (bo = line.match(/^bail out!\s*(.*)$/i)) { + this.bailedOut = true + // this.emit("error", new Error(line)) + this.emit("bailout", bo[1]) + return + } + + if (line.match(/^#/)) { // just a comment + line = line.replace(/^#+/, "").trim() + // console.error("outputting comment", [line]) + if (line) this.emit("data", line) + return + } + + var plan = line.match(/^([0-9]+)\.\.([0-9]+)(?:\s+#(.*))?$/) + if (plan) { + var start = +(plan[1]) + , end = +(plan[2]) + , comment = plan[3] + + // TODO: maybe do something else with this? + // it might be something like: "1..0 #Skip because of reasons" + this._plan = end + this.emit("plan", end, comment) + // plan must come before or after all tests. + if (this._actualCount !== 0) { + this._sawPlan = true + } + return + } + + if (line.match(/^(not )?ok(?:\s+([0-9]+))?/)) { + this._parseResultLine(line) + return + } + + // garbage. emit as a comment. + //console.error("emitting", [line.trim()]) + if (line.trim()) this.emit("data", line.trim()) +} + +TapConsumer.prototype._parseDirective = function (line) { + line = line.trim() + if (line.match(/^TODO\b/i)) { + return { todo:true, explanation: line.replace(/^TODO\s*/i, "") } + } else if (line.match(/^SKIP\b/i)) { + return { skip:true, explanation: line.replace(/^SKIP\s*/i, "") } + } +} + +TapConsumer.prototype._parseResultLine = function (line) { + this._actualCount ++ + if (this._sawPlan) { + this.emit("data", {ok: false, name:"plan in the middle of tests" + ,id:this._actualCount ++}) + } + var parsed = line.match(/^(not )?ok(?: ([0-9]+))?(?:(?: - )?(.*))?$/) + , ok = !parsed[1] + , id = +(parsed[2] || this._actualCount) + , rest = parsed[3] || "" + , name + , res = { id:id, ok:ok } + + // split on un-escaped # characters + + //console.log("# "+JSON.stringify([name, rest])) + rest = rest.replace(/([^\\])((?:\\\\)*)#/g, "$1\n$2").split("\n") + name = rest.shift() + rest = rest.filter(function (r) { return r.trim() }).join("#") + //console.log("# "+JSON.stringify([name, rest])) + + // now, let's see if there's a directive in there. + var dir = this._parseDirective(rest.trim()) + if (!dir) name += rest ? "#" + rest : "" + else { + res.ok = true + if (dir.skip) res.skip = true + else if (dir.todo) res.todo = true + if (dir.explanation) res.explanation = dir.explanation + } + res.name = name + + //console.error(line, [ok, id, name]) + this._current = res +} + +TapConsumer.prototype._parseIndented = function () { + // pull yamlish block out + var ind = this._indent + , ys + , ye + , yind + , diag + //console.error(ind, this._indent) + for (var i = 0, l = ind.length; i < l; i ++) { + var line = ind[i] + , lt = line.trim() + if (!ys) { + ys = line.match(/^(\s*)---(.*)$/) + if (ys) { + yind = ys[1] + diag = [ys[2]] + //console.error([line,ys, diag]) + continue + } else if (lt) this.emit("data", lt) + } else if (ys && !ye) { + if (line === yind + "...") ye = true + else { + diag.push(line.substr(yind.length)) + } + } else if (ys && ye && lt) this.emit("data", lt) + } + if (diag) { + //console.error('about to parse', diag) + diag = yamlish.decode(diag.join("\n")) + //console.error('parsed', diag) + Object.keys(diag).forEach(function (k) { + //console.error(this._current, k) + if (!this._current.hasOwnProperty(k)) this._current[k] = diag[k] + }, this) + } +} diff --git a/node_modules/tap/lib/tap-cov-html.js b/node_modules/tap/lib/tap-cov-html.js new file mode 100644 index 0000000..3c1c192 --- /dev/null +++ b/node_modules/tap/lib/tap-cov-html.js @@ -0,0 +1,78 @@ +var fs = require('fs'), + path = require('path'), + asyncMap = require("slide").asyncMap, + util = require('util'); + +var CovHtml = module.exports = function(cov_stats, cov_dir, cb) { + var index = []; + + asyncMap( + Object.keys(cov_stats), + function(f, cb) { + var st = cov_stats[f], + missing_lines = st.missing.map(function(l) { + return l.number; + }), + out = '\n\n\n ' + + '\n ' + + + f + ' (' + st.loc + ')\n' + + '\n' + + '\n\n' + + '

' + f + ' (' + st.loc + ')' + '

' + + '

Run: ' + (st.missing.length ? st.loc - st.missing.length : st.loc) + ', Missing: ' + + st.missing.length + ', Percentage: ' + st.percentage + '

' + + '

Source:

\n' + + '
    \n' + + st.lines.map(function(line) { + var number = line.number, + color = (missing_lines.indexOf(number) !== -1) ? '#fcc' : '#cfc'; + return '
  1. ' + line.source.replace(/'; + }).join('\n') + + '
\n' + + '

Data

\n'+ + '
' + util.inspect(st, true, Infinity, false).replace(/\n';
+
+      fs.writeFile(
+        cov_dir + '/' + 
+        f.replace(process.cwd() + '/', '').replace(/\//g, '+') + '.html',
+        out,
+        'utf8',
+        function(err) {
+          if (err) {
+            throw err;
+          }
+          index.push(f);
+          cb();
+        });
+    },
+    function(err) {
+      if (err) {
+        throw err;
+      }
+      var out = '\n\n\n  ' +
+          '\n  Coverage Index\n\n' +
+          '\n

Code Coverage Information

\n
    ' + + index.map(function(fname) { + return '
  • ' + fname + '
  • '; + }).join('\n') + '
\n\n'; + + fs.writeFile(cov_dir + '/index.html', out, 'utf8', function(err) { + if (err) { + throw err; + } + cb(); + }); + } + ); +}; + + diff --git a/node_modules/tap/lib/tap-global-harness.js b/node_modules/tap/lib/tap-global-harness.js new file mode 100644 index 0000000..0bcb3a4 --- /dev/null +++ b/node_modules/tap/lib/tap-global-harness.js @@ -0,0 +1,68 @@ +// this is just a harness that pipes to stdout. +// It's the default one. +module.exports = GlobalHarness + +var globalHarness = global.TAP_Global_Harness + , inherits = require("inherits") + , Results = require("./tap-results") + , Harness = require("./tap-harness") + , Test = require("./tap-test") + +inherits(GlobalHarness, Harness) +function GlobalHarness () { + //console.error("calling GlobalHarness") + if (globalHarness) return globalHarness + if (!(this instanceof GlobalHarness)) { + return globalHarness = new GlobalHarness + } + + globalHarness = global.TAP_Global_Harness = this + GlobalHarness.super.call(this, Test) + + this.output.pipe(process.stdout) + //this.output.on("data", function () { + // process.nextTick(process.stdout.flush.bind(process.stdout)) + //}) + + this.test = this.test.bind(this) + + this.plan = this.plan.bind(this) + + var output = this.output + this.on("childEnd", function (child) { + //console.error("childEnd in global harness") + //console.error(child.results) + // write out the stuff for this child. + //console.error("child.conf", child.conf) + output.write(child.conf.name || "(unnamed test)") + // maybe write some other stuff about the number of tests in this + // thing, etc. I dunno. + //console.error("child results", child.results) + this.results.list.forEach(function (res) { + //delete res.error + //console.error("child resuilt", res) + output.write(res) + }) + //console.error("wrote child results") + this.results.list.length = 0 + }) + + var streamEnded = false + this.on("end", function () { + //console.error("global ending the stream") + if (!streamEnded) { + this.results.list.forEach(function (res) { + output.write(res) + }) + this.results.list.length = 0 + output.end() + streamEnded = true + } + }) + + //this.on("end", this.output.end.bind(this.output)) + + process.on("unhandledException", function (e) { + this.bailout("unhandled exception: " + e.message) + }) +} diff --git a/node_modules/tap/lib/tap-harness.js b/node_modules/tap/lib/tap-harness.js new file mode 100644 index 0000000..7aa6cd6 --- /dev/null +++ b/node_modules/tap/lib/tap-harness.js @@ -0,0 +1,219 @@ +// a thing that runs tests. +// Every "test" is also a harness. If they do not have a harness, +// then they are attached to the defaut "global harness", +// which writes its results to stdout. + + +// TODO: +// - Bailout should stop running any tests. +// - "skip" in the test config obj should skip it. + +module.exports = Harness +require("inherits")(Harness, require("events").EventEmitter) + +var Results = require("./tap-results") + , TapProducer = require("./tap-producer") + , assert = require("./tap-assert") + +function Harness (Test) { + if (!(this instanceof Harness)) return new Harness(Test) + + //console.error("Test in "+this.constructor.name, Test) + + this._Test = Test + this._plan = null + this._children = [] + this._started = false + + this._testCount = 0 + this._planSum = 0 + + this.results = new Results() + // emit result events on the harness. + //this.results.on("result", function (res) { + // console.error("proxying result ev from res to harness") + // this.emit("result", res) + //}.bind(this)) + var me = this + this.results.on("result", this.emit.bind(this, "result")) + + var p = this.process.bind(this) + this.process = function () { + this._started = true + process.nextTick(p) + } + + this.output = new TapProducer() + Harness.super.call(this) +} + +// this function actually only gets called bound to +// the Harness object, and on process.nextTick. Even if +// passed as an event handler, everything *else* will +// happen before it gets called. +Harness.prototype.process = function () { + //console.error("harness process") + // "end" can emit multiple times, so only actually move on + // to the next test if the current one is actually over. + // TODO: multiple in-process tests, if all are marked "async" + if (this._current) { + if (!this._current._ended) return + // handle the current one before moving onto the next. + this.childEnd(this._current) + } + var skip = true + while (skip) { + //console.error("checking for skips") + var current = this._current = this._children.shift() + if (current) { + skip = current.conf.skip + if (skip) { + //console.error("add a failure for the skipping") + this.results.add(assert.fail(current.conf.name + ,{skip:true, diag:false})) + } + } else skip = false + } + + // keep processing through skipped tests, instead of running them. + if (current && this._bailedOut) { + return this.process() + } + + //console.error("got current?", !!current) + if (current) { + current.on("end", this.process) + current.emit("ready") + //console.error("emitted ready") + //console.error("_plan", this._plan, this.constructor.name) + } else { + //console.error("Harness process: no more left. ending") + if (this._endNice) { + this._endNice() + } else { + this.end() + } + } +} + +Harness.prototype.end = function () { + if (this._children.length) { + return this.process() + } + //console.error("harness end", this.constructor.name) + if (this._bailedOut) return + + // can't call .end() more than once. + if (this._ended) { + //console.error("adding failure for end calling") + this.results.add(assert.fail("end called more than once")) + } + + // see if the plan is completed properly, if there was one. + if (this._plan !== null) { + var total = this._testCount + if (total !== this._plan) { + this.results.add(assert.equal(total, this._plan, "test count != plan")) + } + this._plan = total + } + + //console.error("setting ended true", this.constructor.name) + this._ended = true + this.emit("end") +} + +Harness.prototype.plan = function (p) { + //console.error("setting plan", new Error().stack) + if (this._plan !== null) { + //console.error("about to add failure for calling plan") + return this.results.add(assert.fail("plan set multiple times")) + } + this._plan = p + if (p === 0 || this.results.testsTotal) { + this.end() + } +} + +Harness.prototype.childEnd = function (child) { + //console.error("childEnd") + this._testCount ++ + this._planSum += child._plan + //console.error("adding set of child.results") + this.results.addSet(child.results) + this.emit("childEnd", child) + // was this planned? + if (this._plan === this._testCount) { + //console.error("plan", [this._plan, this._testCount]) + return this.end() + } +} + +function copyObj(o) { + var copied = {} + Object.keys(o).forEach(function (k) { copied[k] = o[k] }) + return copied +} + +Harness.prototype.test = function test (name, conf, cb) { + if (this._bailedOut) return + + if (typeof conf === "function") cb = conf, conf = null + if (typeof name === "object") conf = name, name = null + if (typeof name === "function") cb = name, name = null + + conf = (conf ? copyObj(conf) : {}) + name = name || "" + + //console.error("making test", [name, conf, cb]) + + // timeout: value in milliseconds. Defaults to 30s + // Set to Infinity to have no timeout. + if (isNaN(conf.timeout)) conf.timeout = 30000 + var t = new this._Test(this, name, conf) + var self = this + if (cb) { + //console.error("attaching cb to ready event") + t.on("ready", function () { + if (!isNaN(conf.timeout) && isFinite(conf.timeout)) { + var timer = setTimeout(this.timeout.bind(this), conf.timeout) + var clear = clearTimeout.bind(null, timer) + t.on("end", clear) + t.on("bailout", function (message) { + self.bailout(message) + clear() + }) + } + }) + t.on("ready", cb.bind(t, t)) + // proxy the child results to this object. + //t.on("result", function (res) { + // console.error("in harness, proxying result up") + // t.results.add(res) + //}) + } + return t +} + +Harness.prototype.bailout = function (message) { + // console.error("Harness bailout", this.constructor.name) + message = message || "" + //console.error("adding bailout message result") + this.results.add({bailout: message}) + // console.error(">>> results after bailout" , this.results) + this._bailedOut = true + this.emit("bailout", message) + this.output.end({bailout: message}) +} + +Harness.prototype.add = function (child) { + //console.error("adding child") + this._children.push(child) + if (!this._started) this.process() +} + +// the tearDown function is *always* guaranteed to happen. +// Even if there's a bailout. +Harness.prototype.tearDown = function (fn) { + this.on("end", fn) +} diff --git a/node_modules/tap/lib/tap-producer.js b/node_modules/tap/lib/tap-producer.js new file mode 100644 index 0000000..c6593a9 --- /dev/null +++ b/node_modules/tap/lib/tap-producer.js @@ -0,0 +1,130 @@ +module.exports = TapProducer + +var Results = require("./tap-results") + , inherits = require("inherits") + , yamlish = require("yamlish") + +TapProducer.encode = function (result, diag) { + var tp = new TapProducer(diag) + , out = "" + tp.on("data", function (c) { out += c }) + if (Array.isArray(result)) { + result.forEach(tp.write, tp) + } else tp.write(result) + tp.end() + return out +} + +inherits(TapProducer, require("stream").Stream) +function TapProducer (diag) { + TapProducer.super.call(this) + this.diag = diag + this.count = 0 + this.readable = this.writable = true + this.results = new Results +} + +TapProducer.prototype.trailer = true + +TapProducer.prototype.write = function (res) { + // console.error("TapProducer.write", res) + if (typeof res === "function") throw new Error("wtf?") + if (!this.writable) this.emit("error", new Error("not writable")) + + if (!this._didHead) { + this.emit("data", "TAP version 13\n") + this._didHead = true + } + + var diag = res.diag + if (diag === undefined) diag = this.diag + + this.emit("data", encodeResult(res, this.count + 1, diag)) + + if (typeof res === "string") return true + + if (res.bailout) { + var bo = "bail out!" + if (typeof res.bailout === "string") bo += " " + res.bailout + this.emit("data", bo) + return + } + this.results.add(res, false) + + this.count ++ +} + +TapProducer.prototype.end = function (res) { + if (res) this.write(res) + // console.error("TapProducer end", res, this.results) + this.emit("data", "\n1.."+this.results.testsTotal+"\n") + if (this.trailer && typeof this.trailer !== "string") { + // summary trailer. + var trailer = "tests "+this.results.testsTotal + "\n" + if (this.results.pass) { + trailer += "pass " + this.results.pass + "\n" + } + if (this.results.fail) { + trailer += "fail " + this.results.fail + "\n" + } + if (this.results.skip) { + trailer += "skip "+this.results.skip + "\n" + } + if (this.results.todo) { + trailer += "todo "+this.results.todo + "\n" + } + if (this.results.bailedOut) { + trailer += "bailed out" + "\n" + } + + if (this.results.testsTotal === this.results.pass) { + trailer += "\nok\n" + } + this.trailer = trailer + } + if (this.trailer) this.write(this.trailer) + this.writable = false + this.emit("end", null, this.count, this.ok) +} + +function encodeResult (res, count, diag) { + // console.error(res, count, diag) + if (typeof res === "string") { + res = res.split(/\r?\n/).map(function (l) { + if (!l.trim()) return l.trim() + return "# " + l + }).join("\n") + if (res.substr(-1) !== "\n") res += "\n" + return res + } + + if (res.bailout) return "" + + + if (!!process.env.TAP_NODIAG) diag = false + else if (!!process.env.TAP_DIAG) diag = true + else if (diag === undefined) diag = !res.ok + + var output = "" + res.name = res.name && ("" + res.name).trim() + output += ( !res.ok ? "not " : "") + "ok " + count + + ( !res.name ? "" + : " " + res.name.replace(/[\r\n]/g, " ") ) + + ( res.skip ? " # SKIP" + : res.todo ? " # TODO" + : "" ) + + "\n" + + if (!diag) return output + var d = {} + , dc = 0 + Object.keys(res).filter(function (k) { + return k !== "ok" && k !== "name" && k !== "id" + }).forEach(function (k) { + dc ++ + d[k] = res[k] + }) + //console.error(d, "about to encode") + if (dc > 0) output += " ---"+yamlish.encode(d)+"\n ...\n" + return output +} diff --git a/node_modules/tap/lib/tap-results.js b/node_modules/tap/lib/tap-results.js new file mode 100644 index 0000000..6fe90e8 --- /dev/null +++ b/node_modules/tap/lib/tap-results.js @@ -0,0 +1,71 @@ +// A class for counting up results in a test harness. + +module.exports = Results + +var inherits = require("inherits") + , EventEmitter = require("events").EventEmitter + +inherits(Results, EventEmitter) + +function Results (r) { + //console.error("result constructor", r) + this.ok = true + this.addSet(r) +} + +Results.prototype.addSet = function (r) { + //console.error("add set of results", r) + r = r || {ok: true} + ; [ "todo" + , "todoPass" + , "todoFail" + , "skip" + , "skipPass" + , "skipFail" + , "pass" + , "passTotal" + , "fail" + , "failTotal" + , "tests" + , "testsTotal" ].forEach(function (k) { + this[k] = (this[k] || 0) + (r[k] || 0) + //console.error([k, this[k]]) + }, this) + + this.ok = this.ok && r.ok && true + this.bailedOut = this.bailedOut || r.bailedOut || false + this.list = (this.list || []).concat(r.list || []) + this.emit("set", this.list) + //console.error("after addSet", this) +} + +Results.prototype.add = function (r, addToList) { + //console.error("add result", r) + var pf = r.ok ? "pass" : "fail" + , PF = r.ok ? "Pass" : "Fail" + + this.testsTotal ++ + this[pf + "Total"] ++ + + if (r.skip) { + this["skip" + PF] ++ + this.skip ++ + } else if (r.todo) { + this["todo" + PF] ++ + this.todo ++ + } else { + this.tests ++ + this[pf] ++ + } + + if (r.bailout || typeof r.bailout === "string") { + // console.error("Bailing out in result") + this.bailedOut = true + } + this.ok = !!(this.ok && r.ok) + + if (addToList === false) return + this.list = this.list || [] + this.list.push(r) + this.emit("result", r) +} diff --git a/node_modules/tap/lib/tap-runner.js b/node_modules/tap/lib/tap-runner.js new file mode 100644 index 0000000..4f3f117 --- /dev/null +++ b/node_modules/tap/lib/tap-runner.js @@ -0,0 +1,434 @@ +var fs = require("fs") + , child_process = require("child_process") + , path = require("path") + , chain = require("slide").chain + , asyncMap = require("slide").asyncMap + , TapProducer = require("./tap-producer.js") + , TapConsumer = require("./tap-consumer.js") + , assert = require("./tap-assert.js") + , inherits = require("inherits") + , util = require("util") + , CovHtml = require("./tap-cov-html.js") + + // XXX Clean up the coverage options + , doCoverage = process.env.TAP_COV + || process.env.npm_package_config_coverage + || process.env.npm_config_coverage + +module.exports = Runner + +inherits(Runner, TapProducer) + +function Runner (options, cb) { + this.options = options + + var diag = this.options.diag + var dir = this.options.argv.remain + Runner.super.call(this, diag) + + this.doCoverage = doCoverage + // An array of full paths to files to obtain coverage + this.coverageFiles = [] + // The source of these files + this.coverageFilesSource = {} + // Where to write coverage information + this.coverageOutDir = this.options["coverage-dir"] + // Temporary test files bunkerified we'll remove later + this.f2delete = [] + // Raw coverage stats, as read from JSON files + this.rawCovStats = [] + // Processed coverage information, per file to cover: + this.covStats = {} + + if (dir) { + var filesToCover = this.options.cover + + if (doCoverage) { + var mkdirp = require("mkdirp") + this.coverageOutDir = path.resolve(this.coverageOutDir) + this.getFilesToCover(filesToCover) + var self = this + return mkdirp(this.coverageOutDir, 0755, function (er) { + if (er) return self.emit("error", er) + self.run(dir, cb) + }) + } + + this.run(dir, cb) + } +} + + +Runner.prototype.run = function() { + var self = this + , args = Array.prototype.slice.call(arguments) + , cb = args.pop() || finish + + function finish (er) { + if (er) { + self.emit("error", er) + } + + if (!doCoverage) return self.end() + + // Cleanup temporary test files with coverage: + self.f2delete.forEach(function(f) { + fs.unlinkSync(f) + }) + self.getFilesToCoverSource(function(err, data) { + if (err) { + self.emit("error", err) + } + self.getPerFileCovInfo(function(err, data) { + if (err) { + self.emit("error", err) + } + self.mergeCovStats(function(err, data) { + if (err) { + self.emit("error", err) + } + CovHtml(self.covStats, self.coverageOutDir, function() { + self.end() + }) + }) + }) + }) + } + + if (Array.isArray(args[0])) { + args = args[0] + } + self.runFiles(args, "", cb) +} + +Runner.prototype.runDir = function (dir, cb) { + var self = this + fs.readdir(dir, function (er, files) { + if (er) { + self.write(assert.fail("failed to readdir " + dir, { error: er })) + self.end() + return + } + files = files.sort(function(a, b) { + return a > b ? 1 : -1 + }) + files = files.filter(function(f) { + return !f.match(/^\./) + }) + files = files.map(path.resolve.bind(path, dir)) + + self.runFiles(files, path.resolve(dir), cb) + }) +} + + +Runner.prototype.runFiles = function (files, dir, cb) { + + var self = this + chain(files.map(function(f) { + return function (cb) { + if (self._bailedOut) return + var relDir = dir || path.dirname(f) + , fileName = relDir === "." ? f : f.substr(relDir.length + 1) + + self.write(fileName) + fs.lstat(f, function(er, st) { + if (er) { + self.write(assert.fail("failed to stat " + f, {error: er})) + return cb() + } + + var cmd = f, args = [], env = {} + + if (path.extname(f) === ".js") { + cmd = "node" + args = [fileName] + } else if (path.extname(f) === ".coffee") { + cmd = "coffee" + args = [fileName] + } + + if (st.isDirectory()) { + return self.runDir(f, cb) + } + + if (doCoverage && path.extname(f) === ".js") { + var foriginal = fs.readFileSync(f, "utf8") + , fcontents = self.coverHeader() + foriginal + self.coverFooter() + , tmpBaseName = path.basename(f, path.extname(f)) + + ".with-coverage." + process.pid + path.extname(f) + , tmpFname = path.resolve(path.dirname(f), tmpBaseName) + , i + + fs.writeFileSync(tmpFname, fcontents, "utf8") + args = [tmpFname] + } + + for (i in process.env) { + env[i] = process.env[i] + } + env.TAP = 1 + + var cp = child_process.spawn(cmd, args, { env: env, cwd: relDir }) + , out = "" + , err = "" + , tc = new TapConsumer() + , childTests = [f] + + var timeout = setTimeout(function () { + if (!cp._ended) { + cp._timedOut = true + cp.kill() + } + }, self.options.timeout * 1000) + + tc.on("data", function(c) { + self.emit("result", c) + self.write(c) + }) + + tc.on("bailout", function (message) { + clearTimeout(timeout) + console.log("# " + f.substr(process.cwd().length + 1)) + process.stderr.write(err) + process.stdout.write(out + "\n") + self._bailedOut = true + cp._ended = true + cp.kill() + }) + + cp.stdout.pipe(tc) + cp.stdout.on("data", function (c) { out += c }) + cp.stderr.on("data", function (c) { + if (self.options.stderr) process.stderr.write(c) + err += c + }) + + cp.on("exit", function (code) { + if (cp._ended) return + cp._ended = true + var ok = !cp._timedOut && !code + clearTimeout(timeout) + //childTests.forEach(function (c) { self.write(c) }) + var res = { name: path.dirname(f).replace(process.cwd() + "/", "") + + "/" + fileName + , ok: ok + , timedOut: cp._timedOut + , exit: code } + + if (err) { + res.stderr = err + if (tc.results.ok && + tc.results.tests === 0 && + !self.options.stderr) { + // perhaps a compilation error or something else failed. + // no need if stderr is set, since it will have been + // output already anyway. + console.error(err) + } + } + + // tc.results.ok = tc.results.ok && ok + tc.results.add(res) + res.command = [cmd].concat(args).map(JSON.stringify).join(" ") + self.emit("result", res) + self.emit("file", f, res, tc.results) + self.write(res) + self.write("\n") + if (doCoverage) { + self.f2delete.push(tmpFname) + } + cb() + }) + }) + } + }), cb) + + return self +} + + +// Get an array of full paths to files we are interested into obtain +// code coverage. +Runner.prototype.getFilesToCover = function(filesToCover) { + var self = this + filesToCover = filesToCover.split(",").map(function(f) { + return path.resolve(f) + }).filter(function(f) { + return path.existsSync(f) + }) + + function recursive(f) { + if (path.extname(f) === "") { + // Is a directory: + fs.readdirSync(f).forEach(function(p) { + recursive(f + "/" + p) + }) + } else { + self.coverageFiles.push(f) + } + } + filesToCover.forEach(function(f) { + recursive(f) + }) +} + +// Prepend to every test file to run. Note tap.test at the very top due it +// "plays" with include paths. +Runner.prototype.coverHeader = function() { + // semi here since we're injecting it before the first line, + // and don't want to mess up line numbers in the test files. + return "var ___TAP_COVERAGE = require(" + + JSON.stringify(require.resolve("runforcover")) + + ").cover(/.*/g);" +} + +// Append at the end of every test file to run. Actually, the stuff which gets +// the coverage information. +// Maybe it would be better to move into a separate file template so editing +// could be easier. +Runner.prototype.coverFooter = function() { + var self = this + // This needs to be a string with proper interpolations: + return [ "" + , "var ___TAP = require(" + JSON.stringify(require.resolve("./main.js")) + ")" + , "if (typeof ___TAP._plan === 'number') ___TAP._plan ++" + , "___TAP.test(" + JSON.stringify("___coverage") + ", function(t) {" + , " var covFiles = " + JSON.stringify(self.coverageFiles) + , " , covDir = " + JSON.stringify(self.coverageOutDir) + , " , path = require('path')" + , " , fs = require('fs')" + , " , testFnBase = path.basename(__filename, '.js') + '.json'" + , " , testFn = path.resolve(covDir, testFnBase)" + , "" + , " function asyncForEach(arr, fn, callback) {" + , " if (!arr.length) {" + , " return callback()" + , " }" + , " var completed = 0" + , " arr.forEach(function(i) {" + , " fn(i, function (err) {" + , " if (err) {" + , " callback(err)" + , " callback = function () {}" + , " } else {" + , " completed += 1" + , " if (completed === arr.length) {" + , " callback()" + , " }" + , " }" + , " })" + , " })" + , " }" + , "" + , " ___TAP_COVERAGE(function(coverageData) {" + , " var outObj = {}" + , " asyncForEach(covFiles, function(f, cb) {" + , " if (coverageData[f]) {" + , " var stats = coverageData[f].stats()" + , " , stObj = stats" + , " stObj.lines = stats.lines.map(function (l) {" + , " return { number: l.lineno, source: l.source() }" + , " })" + , " outObj[f] = stObj" + , " }" + , " cb()" + , " }, function(err) {" + , " ___TAP_COVERAGE.release()" + , " fs.writeFileSync(testFn, JSON.stringify(outObj))" + , " t.end()" + , " })" + , " })" + , "})" ].join("\n") +} + + +Runner.prototype.getFilesToCoverSource = function(cb) { + var self = this + asyncMap(self.coverageFiles, function(f, cb) { + fs.readFile(f, "utf8", function(err, data) { + var lc = 0 + if (err) { + cb(err) + } + self.coverageFilesSource[f] = data.split("\n").map(function(l) { + lc += 1 + return { number: lc, source: l } + }) + cb() + }) + }, cb) +} + +Runner.prototype.getPerFileCovInfo = function(cb) { + var self = this + , covPath = path.resolve(self.coverageOutDir) + + fs.readdir(covPath, function(err, files) { + if (err) { + self.emit("error", err) + } + var covFiles = files.filter(function(f) { + return path.extname(f) === ".json" + }) + asyncMap(covFiles, function(f, cb) { + fs.readFile(path.resolve(covPath, f), "utf8", function(err, data) { + if (err) { + cb(err) + } + self.rawCovStats.push(JSON.parse(data)) + cb() + }) + }, function(f, cb) { + fs.unlink(path.resolve(covPath, f), cb) + }, cb) + }) +} + +Runner.prototype.mergeCovStats = function(cb) { + var self = this + self.rawCovStats.forEach(function(st) { + Object.keys(st).forEach(function(i) { + // If this is the first time we reach this file, just add the info: + if (!self.covStats[i]) { + self.covStats[i] = { + missing: st[i].lines + } + } else { + // If we already added info for this file before, we need to remove + // from self.covStats any line not duplicated again (since it has + // run on such case) + self.covStats[i].missing = self.covStats[i].missing.filter( + function(l) { + return (st[i].lines.indexOf(l)) + }) + } + }) + }) + + // This is due to a bug into + // chrisdickinson/node-bunker/blob/feature/add-coverage-interface + // which is using array indexes for line numbers instead of the right number + Object.keys(self.covStats).forEach(function(f) { + self.covStats[f].missing = self.covStats[f].missing.map(function(line) { + return { number: line.number, source: line.source } + }) + }) + + Object.keys(self.coverageFilesSource).forEach(function(f) { + if (!self.covStats[f]) { + self.covStats[f] = { missing: self.coverageFilesSource[f] + , percentage: 0 + } + } + self.covStats[f].lines = self.coverageFilesSource[f] + self.covStats[f].loc = self.coverageFilesSource[f].length + + if (!self.covStats[f].percentage) { + self.covStats[f].percentage = + 1 - (self.covStats[f].missing.length / self.covStats[f].loc) + } + + }) + cb() +} diff --git a/node_modules/tap/lib/tap-test.js b/node_modules/tap/lib/tap-test.js new file mode 100644 index 0000000..3c8f138 --- /dev/null +++ b/node_modules/tap/lib/tap-test.js @@ -0,0 +1,109 @@ +// This is a very simple test framework that leverages the tap framework +// to run tests and output tap-parseable results. + +module.exports = Test + +var assert = require("./tap-assert") + , inherits = require("inherits") + , Results = require("./tap-results") + +// tests are also test harnesses +inherits(Test, require("./tap-harness")) + +function Test (harness, name, conf) { + //console.error("test ctor") + if (!(this instanceof Test)) return new Test(harness, name, conf) + + Test.super.call(this, Test) + + conf.name = name || conf.name || "(anonymous)" + this.conf = conf + + this.harness = harness + this.harness.add(this) +} + +// it's taking too long! +Test.prototype.timeout = function () { + // detect false alarms + if (this._ended) return + this.fail("Timeout!") + this.end() +} + +Test.prototype.clear = function () { + this._started = false + this._ended = false + this._plan = null + this._bailedOut = false + this._testCount = 0 + this.results = new Results() +} + +// this gets called if a test throws ever +Test.prototype.threw = function (ex) { + //console.error("threw!", ex.stack) + this.fail(ex.name + ": " + ex.message, { error: ex, thrown: true }) + // may emit further failing tests if the plan is not completed + //console.error("end, because it threw") + this.end() +} + +Test.prototype.comment = function (m) { + if (typeof m !== "string") { + return this.fail("Test.comment argument must be a string") + } + this.result("\n" + m.trim()) +} + +Test.prototype.result = function (res) { + this.results.add(res) + this._testCount ++ + this.emit("result", res) + if (this._plan === this._testCount) { + process.nextTick(this._endNice.bind(this)) + } +} + +Test.prototype._endNice = function () { + if (!this._ended) this.end() +} + +// parasitic +// Who says you can't do multiple inheritance in js? +Object.getOwnPropertyNames(assert).forEach(function (k) { + if (k === "prototype" || k === "name") return + var d = Object.getOwnPropertyDescriptor(assert, k) + , v = d.value + if (!v) return + d.value = assertParasite(v) + Object.defineProperty(Test.prototype, k, d) +}) + +function assertParasite (fn) { return function _testAssert () { + //console.error("_testAssert", fn.name, arguments) + if (this._bailedOut) return + var res = fn.apply(assert, arguments) + this.result(res) + return res +}} + +// a few tweaks on the EE emit function, because +// we want to catch all thrown errors and bubble up "bailout" +Test.prototype.emit = (function (em) { return function (t) { + // bailouts bubble until handled + if (t === "bailout" && + this.listeners(t).length === 0 && + this.harness) { + return this.harness.bailout(arguments[1]) + } + + if (t === "error") return em.apply(this, arguments) + try { + em.apply(this, arguments) + } catch (ex) { + // any exceptions in a test are a failure + //console.error("caught!", ex.stack) + this.threw(ex) + } +}})(Test.super.prototype.emit) diff --git a/node_modules/tap/node_modules/inherits/LICENSE b/node_modules/tap/node_modules/inherits/LICENSE new file mode 100644 index 0000000..5a8e332 --- /dev/null +++ b/node_modules/tap/node_modules/inherits/LICENSE @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/node_modules/tap/node_modules/inherits/README.md b/node_modules/tap/node_modules/inherits/README.md new file mode 100644 index 0000000..b2beaed --- /dev/null +++ b/node_modules/tap/node_modules/inherits/README.md @@ -0,0 +1,51 @@ +A dead simple way to do inheritance in JS. + + var inherits = require("inherits") + + function Animal () { + this.alive = true + } + Animal.prototype.say = function (what) { + console.log(what) + } + + inherits(Dog, Animal) + function Dog () { + Dog.super.apply(this) + } + Dog.prototype.sniff = function () { + this.say("sniff sniff") + } + Dog.prototype.bark = function () { + this.say("woof woof") + } + + inherits(Chihuahua, Dog) + function Chihuahua () { + Chihuahua.super.apply(this) + } + Chihuahua.prototype.bark = function () { + this.say("yip yip") + } + + // also works + function Cat () { + Cat.super.apply(this) + } + Cat.prototype.hiss = function () { + this.say("CHSKKSS!!") + } + inherits(Cat, Animal, { + meow: function () { this.say("miao miao") } + }) + Cat.prototype.purr = function () { + this.say("purr purr") + } + + + var c = new Chihuahua + assert(c instanceof Chihuahua) + assert(c instanceof Dog) + assert(c instanceof Animal) + +The actual function is laughably small. 10-lines small. diff --git a/node_modules/tap/node_modules/inherits/inherits-old.js b/node_modules/tap/node_modules/inherits/inherits-old.js new file mode 100644 index 0000000..ef39252 --- /dev/null +++ b/node_modules/tap/node_modules/inherits/inherits-old.js @@ -0,0 +1,40 @@ +// This is a less perfect implementation of the inherits function, +// designed to work in cases where ES5 is not available. +// +// Note that it is a bit longer, and doesn't properly deal with +// getter/setters or property descriptor flags (enumerable, etc.) + +module.exports = inheritsOld + +function inheritsOld (c, p, proto) { + function F () { this.constructor = c } + F.prototype = p.prototype + var e = {} + for (var i in c.prototype) if (c.prototype.hasOwnProperty(i)) { + e[i] = c.prototype[i] + } + if (proto) for (var i in proto) if (proto.hasOwnProperty(i)) { + e[i] = proto[i] + } + c.prototype = new F() + for (var i in e) if (e.hasOwnProperty(i)) { + c.prototype[i] = e[i] + } + c.super = p +} + +// function Child () { +// Child.super.call(this) +// console.error([this +// ,this.constructor +// ,this.constructor === Child +// ,this.constructor.super === Parent +// ,Object.getPrototypeOf(this) === Child.prototype +// ,Object.getPrototypeOf(Object.getPrototypeOf(this)) +// === Parent.prototype +// ,this instanceof Child +// ,this instanceof Parent]) +// } +// function Parent () {} +// inheritsOld(Child, Parent) +// new Child diff --git a/node_modules/tap/node_modules/inherits/inherits.js b/node_modules/tap/node_modules/inherits/inherits.js new file mode 100644 index 0000000..061b396 --- /dev/null +++ b/node_modules/tap/node_modules/inherits/inherits.js @@ -0,0 +1,29 @@ +module.exports = inherits + +function inherits (c, p, proto) { + proto = proto || {} + var e = {} + ;[c.prototype, proto].forEach(function (s) { + Object.getOwnPropertyNames(s).forEach(function (k) { + e[k] = Object.getOwnPropertyDescriptor(s, k) + }) + }) + c.prototype = Object.create(p.prototype, e) + c.super = p +} + +//function Child () { +// Child.super.call(this) +// console.error([this +// ,this.constructor +// ,this.constructor === Child +// ,this.constructor.super === Parent +// ,Object.getPrototypeOf(this) === Child.prototype +// ,Object.getPrototypeOf(Object.getPrototypeOf(this)) +// === Parent.prototype +// ,this instanceof Child +// ,this instanceof Parent]) +//} +//function Parent () {} +//inherits(Child, Parent) +//new Child diff --git a/node_modules/tap/node_modules/inherits/package.json b/node_modules/tap/node_modules/inherits/package.json new file mode 100644 index 0000000..487b6fa --- /dev/null +++ b/node_modules/tap/node_modules/inherits/package.json @@ -0,0 +1,8 @@ +{ "name" : "inherits" +, "description": "A tiny simple way to do classic inheritance in js" +, "version" : "1.0.0" +, "keywords" : ["inheritance", "class", "klass", "oop", "object-oriented"] +, "main" : "./inherits.js" +, "repository" : "https://github.com/isaacs/inherits" +, "license": { "type": "WTFPL2" } +, "author" : "Isaac Z. Schlueter (http://blog.izs.me/)" } diff --git a/node_modules/tap/node_modules/yamlish/LICENSE b/node_modules/tap/node_modules/yamlish/LICENSE new file mode 100644 index 0000000..187e8db --- /dev/null +++ b/node_modules/tap/node_modules/yamlish/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Isaac Z. Schlueter + +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. diff --git a/node_modules/tap/node_modules/yamlish/README.md b/node_modules/tap/node_modules/yamlish/README.md new file mode 100644 index 0000000..954d063 --- /dev/null +++ b/node_modules/tap/node_modules/yamlish/README.md @@ -0,0 +1,20 @@ +This is a thingie to parse the "yamlish" format used to serialize +objects in the TAP format. + +It's like yaml, but just a tiny little bit smaller. + +Usage: + + var yamlish = require("yamlish") + // returns a string like: + /* + some: + object: + - full + - of + pretty: things + */ + yamlish.encode({some:{object:["full", "of"]}, pretty:"things"}) + + // returns the object + yamlish.decode(someYamlishString) diff --git a/node_modules/tap/node_modules/yamlish/package.json b/node_modules/tap/node_modules/yamlish/package.json new file mode 100644 index 0000000..359300d --- /dev/null +++ b/node_modules/tap/node_modules/yamlish/package.json @@ -0,0 +1,9 @@ +{ "name" : "yamlish" +, "description" : "Parser/encoder for the yamlish format" +, "repository":"https://github.com/isaacs/yamlish" +, "version" : "0.0.5" +, "main" : "yamlish.js" +, "keywords" : [ "yaml", "yamlish", "test", "anything", "protocol", "tap"] +, "license" : { "type" : "MIT" + , "url" : "http://github.com/isaacs/yamlish/raw/master/LICENSE" } +, "author" : "Isaac Z. Schlueter (http://blog.izs.me/)" } diff --git a/node_modules/tap/node_modules/yamlish/yamlish.js b/node_modules/tap/node_modules/yamlish/yamlish.js new file mode 100644 index 0000000..dd8c370 --- /dev/null +++ b/node_modules/tap/node_modules/yamlish/yamlish.js @@ -0,0 +1,260 @@ +exports.encode = encode +exports.decode = decode + +var seen = [] +function encode (obj, indent) { + var deep = arguments[2] + if (!indent) indent = " " + + if (obj instanceof String || + Object.prototype.toString.call(obj) === "[object String]") { + obj = obj.toString() + } + + if (obj instanceof Number || + Object.prototype.toString.call(obj) === "[object Number]") { + obj = obj.valueOf() + } + + // take out the easy ones. + switch (typeof obj) { + case "string": + obj = obj.trim() + if (obj.indexOf("\n") !== -1) { + return "|\n" + indent + obj.split(/\r?\n/).join("\n"+indent) + } else { + return (obj) + } + + case "number": + return obj.toString(10) + + case "function": + return encode(obj.toString(), indent, true) + + case "boolean": + return obj.toString() + + case "undefined": + // fallthrough + case "object": + // at this point we know it types as an object + if (!obj) return "~" + + if (obj instanceof Date || + Object.prototype.toString.call(obj) === "[object Date]") { + return JSON.stringify("[Date " + obj.toISOString() + "]") + } + + if (obj instanceof RegExp || + Object.prototype.toString.call(obj) === "[object RegExp]") { + return JSON.stringify(obj.toString()) + } + + if (obj instanceof Boolean || + Object.prototype.toString.call(obj) === "[object Boolean]") { + return obj.toString() + } + + if (seen.indexOf(obj) !== -1) { + return "[Circular]" + } + seen.push(obj) + + if (typeof Buffer === "function" && + typeof Buffer.isBuffer === "function" && + Buffer.isBuffer(obj)) return obj.inspect() + + if (obj instanceof Error) { + var o = { name: obj.name + , message: obj.message + , type: obj.type } + + if (obj.code) o.code = obj.code + if (obj.errno) o.errno = obj.errno + if (obj.type) o.type = obj.type + obj = o + } + + var out = "" + + if (Array.isArray(obj)) { + var out = "\n" + indent + "- " +obj.map(function (item) { + return encode(item, indent + " ", true) + }).join("\n"+indent + "- ") + break + } + + // an actual object + var keys = Object.keys(obj) + , niceKeys = keys.map(function (k) { + return (k.match(/^[a-zA-Z0-9_]+$/) ? k : JSON.stringify(k)) + ": " + }) + //console.error(keys, niceKeys, obj) + var maxLength = Math.max.apply(Math, niceKeys.map(function (k) { + return k.length + }).concat(0)) + //console.error(niceKeys, maxLength) + + var spaces = new Array(maxLength + 1).join(" ") + + if (!deep) indent += " " + out = "\n" + indent + keys.map(function (k, i) { + var niceKey = niceKeys[i] + return niceKey + spaces.substr(niceKey.length) + + encode(obj[k], indent + " ", true) + }).join("\n" + indent) + break + + default: return "" + } + if (!deep) seen.length = 0 + return out +} + +function decode (str) { + var v = str.trim() + , d + , dateRe = /^\[Date ([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}(?::[0-9]{2})?(?:\.[0-9]{3})?(?:[A-Z]+)?)\]$/ + + if (v === "~") return null + + try { + var jp = JSON.parse(str) + } catch (e) { + var jp = "" + } + + if (jp && + typeof jp === "string" && + (d = jp.match(dateRe)) && + (d = Date.parse(d[1]))) { + return new Date(d) + } + + if (typeof jp === "boolean") return jp + if (v && !isNaN(v)) return parseInt(v, 10) + + // something interesting. + var lines = str.split(/\r?\n/) + // check if it's some kind of string or something. + // if the first line is > or | then it's a wrapping indented string. + // if the first line is blank, and there are many lines, + // then it's an array or object. + // otherwise, it's just "" + var first = lines.shift().trim() + if (lines.length) lines = undent(lines) + switch (first) { + case "|": + return lines.join("\n") + case ">": + return lines.join("\n").split(/\n{2,}/).map(function (l) { + return l.split(/\n/).join(" ") + }).join("\n") + default: + if (!lines.length) return first + // array or object. + // the first line will be either "- value" or "key: value" + return lines[0].charAt(0) === "-" ? decodeArr(lines) : decodeObj(lines) + } +} + +function decodeArr (lines) { + var out = [] + , key = 0 + , val = [] + for (var i = 0, l = lines.length; i < l; i ++) { + // if it starts with a -, then it's a new thing + var line = lines[i] + if (line.charAt(0) === "-") { + if (val.length) { + out[key ++] = decode(val.join("\n")) + val.length = 0 + } + val.push(line.substr(1).trim()) + } else if (line.charAt(0) === " ") { + val.push(line) + } else return [] + } + if (val.length) { + out[key ++] = decode(val.join("\n")) + } + return out +} + +function decodeObj (lines) { + var out = {} + , val = [] + , key = null + + for (var i = 0, l = lines.length; i < l; i ++) { + var line = lines[i] + if (line.charAt(0) === " ") { + val.push(line) + continue + } + // some key:val + if (val.length) { + out[key] = decode(val.join("\n")) + val.length = 0 + } + // parse out the quoted key + var first + if (line.charAt(0) === "\"") { + for (var ii = 1, ll = line.length, esc = false; ii < ll; ii ++) { + var c = line.charAt(ii) + if (c === "\\") { + esc = !esc + } else if (c === "\"" && !esc) { + break + } + } + key = JSON.parse(line.substr(0, ii + 1)) + line = line.substr(ii + 1) + first = line.substr(line.indexOf(":") + 1).trim() + } else { + var kv = line.split(":") + key = kv.shift() + first = kv.join(":").trim() + } + // now we've set a key, and "first" has the first line of the value. + val.push(first.trim()) + } + if (val.length) out[key] = decode(val.join("\n")) + return out +} + +function undent (lines) { + var i = lines[0].match(/^\s*/)[0].length + return lines.map(function (line) { + return line.substr(i) + }) +} + + +// XXX Turn this into proper tests. +if (require.main === module) { +var obj = [{"bigstring":new Error().stack} + ,{ar:[{list:"of"},{some:"objects"}]} + ,{date:new Date()} + ,{"super huge string":new Error().stack} + ] + +Date.prototype.toJSON = function (k, val) { + console.error(k, val, this) + return this.toISOString() + " (it's a date)" +} + +var enc = encode(obj) + , dec = decode(enc) + , encDec = encode(dec) + +console.error(JSON.stringify({ obj : obj + , enc : enc.split(/\n/) + , dec : dec }, null, 2), encDec === enc) + +var num = 100 + , encNum = encode(num) + , decEncNum = decode(encNum) +console.error([num, encNum, decEncNum]) +} diff --git a/node_modules/tap/package.json b/node_modules/tap/package.json new file mode 100644 index 0000000..a8a3357 --- /dev/null +++ b/node_modules/tap/package.json @@ -0,0 +1,41 @@ +{ + "name": "tap", + "version": "0.2.6", + "author": "Isaac Z. Schlueter (http://blog.izs.me)", + "description": "A Test-Anything-Protocol library", + "bin": "bin/tap.js", + "main": "lib/main.js", + "dependencies": { + "inherits": "*", + "yamlish": "*", + "slide": "*", + "runforcover": "~0.0.2", + "nopt": "~2", + "mkdirp": "~0.3", + "difflet": "~0.2.0", + "deep-equal": "~0.0.0", + "buffer-equal": "~0.0.0" + }, + "bundledDependencies": [ + "inherits", + "tap-consumer", + "yamlish" + ], + "keywords": [ + "assert", + "test", + "tap" + ], + "contributors": [ + "Isaac Z. Schlueter (http://blog.izs.me)", + "baudehlo " + ], + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/node-tap/raw/master/LICENSE" + }, + "repository": "git://github.com/isaacs/node-tap.git", + "scripts": { + "test": "bin/tap.js test" + } +} diff --git a/node_modules/tap/test-disabled/bailout.js b/node_modules/tap/test-disabled/bailout.js new file mode 100644 index 0000000..498035c --- /dev/null +++ b/node_modules/tap/test-disabled/bailout.js @@ -0,0 +1,36 @@ +var tap = require("tap") + , test = tap.test + +test("bailout test", { skip: false }, function (t) { + + // t.once("bailout", function () { + // console.error("bailout event")//, t) + // t.clear() + // }) + + // t.once("end", function () { + // console.error("end event") + // }) + + // simulate three tests where the second bails out. + t.test("first", function (t) { + t.pass("this is ok") + t.end() + }) + + t.test("bailout", function (t) { + console.error("bailout test") + t.pass("pass") + t.bailout("bail out message") + t.fail("fail") + t.end() + }) + + t.test("second (should not happen)", function (t) { + t.fail("this should not happen") + t.end() + }) + + t.end() + +}) diff --git a/node_modules/tap/test-disabled/foo.js b/node_modules/tap/test-disabled/foo.js new file mode 100644 index 0000000..6360156 --- /dev/null +++ b/node_modules/tap/test-disabled/foo.js @@ -0,0 +1 @@ +process.stdin diff --git a/node_modules/tap/test-disabled/t.js b/node_modules/tap/test-disabled/t.js new file mode 100644 index 0000000..581d24b --- /dev/null +++ b/node_modules/tap/test-disabled/t.js @@ -0,0 +1,16 @@ +var test = require('tap').test; + +function foo() { + throw new Error('one'); +} + +test('demonstrate bug in t.throws', function (t) { + t.throws( + function () { + foo(); + }, + new Error('two')), + // "this should throw", + // {}); // not 'one'! + t.end(); +}); diff --git a/node_modules/tap/test/buffer_compare.js b/node_modules/tap/test/buffer_compare.js new file mode 100644 index 0000000..b1e1505 --- /dev/null +++ b/node_modules/tap/test/buffer_compare.js @@ -0,0 +1,11 @@ +var test = require("../").test + +test("same buffers", function (t) { + t.same(new Buffer([3,4,243]), new Buffer([3,4,243])) + t.end() +}) + +test("not same buffers", function (t) { + t.notSame(new Buffer([3,5,243]), new Buffer([3,4,243])) + t.end() +}) diff --git a/node_modules/tap/test/common.js b/node_modules/tap/test/common.js new file mode 100644 index 0000000..7cc43c1 --- /dev/null +++ b/node_modules/tap/test/common.js @@ -0,0 +1,32 @@ +exports.taps = ["Tests for the foo module" + ,{ok:true, name:"test that the foo is fooish" + ,file:"foo.js", line:8, name:"fooish test" + ,stack:new Error("fooish").stack} + ,{ok:false, name:"a test that the bar is barish" + ,file:"bar.js", line:25 + ,expected:"bar\nbar\nbaz", actual:"rab\nrib\nzib" + ,hash:{more:"\nstuff\nhere\n",regexp:/asdf/}} + ,"Quux module tests" + ,"This is a longer comment" + ,{ok:true, name:"an easy one."} + ,{ok:false, name:"bloooooo" + ,expected:"blerggeyyy" + ,actual:"blorggeyy"} + ,{ok:false, name:"array test" + ,expected:[{ok:true},{ok:true},{stack:new Error().stack}] + ,actual:[1234567890,123456789,{error:new Error("yikes")}]} + ,{ok:true, name:"nulltest" + ,expected:undefined, actual:null} + ,{ok:true, name:"weird key test" + ,expected:"weird key" + ,actual:"weird key" + ,"this object":{"has a ":"weird key" + ,"and a looooooooonnnnnnnnnggg":"jacket"}} + ,{ok:true, name:"regexp test" + ,regexp:/asdf/,function:function (a,b) { return a + b }} + ] + +if (require.main === module) { + console.log("1..1") + console.log("ok 1 - just setup, nothing relevant") +} diff --git a/node_modules/tap/test/deep.js b/node_modules/tap/test/deep.js new file mode 100644 index 0000000..52b6110 --- /dev/null +++ b/node_modules/tap/test/deep.js @@ -0,0 +1,43 @@ +var tap = require("../") + , test = tap.test + +test("deepEquals shouldn't care about key order", function (t) { + t.deepEqual({ a : 1, b : 2 }, { b : 2, a : 1 }) + t.end() +}) + +test("deepEquals shouldn't care about key order recursively", function (t) { + t.deepEqual( + { x : { a : 1, b : 2 }, y : { c : 3, d : 4 } }, + { y : { d : 4, c : 3 }, x : { b : 2, a : 1 } } + ) + t.end() +}) + +test("deepEquals shoudn't care about key order but still might", function (t) { + t.deepEqual( + [ { foo: + { z: 100 + , y: 200 + , x: 300 } } + , "bar" + , 11 + , { baz: + { d : 4 + , a: 1 + , b: 2 + , c: 3 } } ] + , [ { foo : + { z: 100 + , y: 200 + , x: 300 } } + , "bar" + , 11 + , { baz: + { a: 1 + , b: 2 + , c: 3 + , d: 4 } } ] + ) + t.end() +}); diff --git a/node_modules/tap/test/independent-timeouts.js b/node_modules/tap/test/independent-timeouts.js new file mode 100644 index 0000000..5a35e61 --- /dev/null +++ b/node_modules/tap/test/independent-timeouts.js @@ -0,0 +1,16 @@ +// https://github.com/isaacs/node-tap/issues/23 + +var tap = require("../") + , test = tap.test + +test("finishes in time", {timeout: 500}, function(t) { + setTimeout(function () { + t.end(); + }, 300); +}) +test("finishes in time too", {timeout: 500}, function(t) { + setTimeout(function () { + t.end(); + }, 300); +}) + diff --git a/node_modules/tap/test/isolated-conf-test.js b/node_modules/tap/test/isolated-conf-test.js new file mode 100644 index 0000000..d8bfae6 --- /dev/null +++ b/node_modules/tap/test/isolated-conf-test.js @@ -0,0 +1,16 @@ +// https://github.com/isaacs/node-tap/issues/24 + +var tap = require("../") + , test = tap.test + +var config = {foo: "bar"} +test("one", config, function(t) { + t.equal(t.conf.foo, "bar") + t.equal(t.conf.name, "one") // before fix this would be "two" + t.end() +}) +test("two", config, function(t) { + t.equal(t.conf.foo, "bar") + t.equal(t.conf.name, "two") + t.end() +}) diff --git a/node_modules/tap/test/meta-test.js b/node_modules/tap/test/meta-test.js new file mode 100644 index 0000000..8f56f26 --- /dev/null +++ b/node_modules/tap/test/meta-test.js @@ -0,0 +1,73 @@ +var tap = require("../") + , test = tap.test + +test("meta test", { skip: false }, function (t) { + + function thr0w() { throw new Error('raburt') } + function noop () {} + + // this also tests the ok/notOk functions + t.once("end", section2) + t.ok(true, "true is ok") + t.ok(noop, "function is ok") + t.ok({}, "object is ok") + t.ok(t, "t is ok") + t.ok(100, "number is ok") + t.ok("asdf", "string is ok") + t.notOk(false, "false is notOk") + t.notOk(0, "0 is notOk") + t.notOk(null, "null is notOk") + t.notOk(undefined, "undefined is notOk") + t.notOk(NaN, "NaN is notOk") + t.notOk("", "empty string is notOk") + t.throws(thr0w, "Thrower throws"); + t.doesNotThrow(noop, "noop does not throw"); + t.similar({foo:"bar", bar:"foo"}, {foo:"bar"}, "similar objects are ok"); + t.dissimilar({}, {mandatory:"value"}, "dissimilar objects are ok"); + t.dissimilar(null, {}, "null is dissimilar from an object, even with no keys"); + + // a few failures. + t.ifError(new Error("this is an error")) + t.ifError({ message: "this is a custom error" }) + t.ok(false, "false is not ok") + t.notOk(true, "true is not not ok") + t.similar(null, {}, "Null is not similar to an object, even with no keys"); + t.throws(noop, "noop does not throw"); + t.throws(noop, new Error("Whoops!"), "noop does not throw an Error"); + t.throws(noop, {name:"MyError", message:"Whoops!"}, "noop does not throw a MyError"); + t.doesNotThrow(thr0w, "thrower does throw"); + + // things that are like other things + t.like("asdf", "asdf") + t.like("asdf", /^a.*f$/) + t.like(100, 100) + t.like(100, '100') + t.like(100, 100.0) + t.unlike("asdf", "fdsa") + t.unlike("asdf", /^you jelly, bro?/) + t.unlike(100, 100.1) + t.like(true, 1) + t.like(null, undefined) + t.like(true, [1]) + t.like(false, []) + t.like('', []) + t.end() + + function section2 () { + var results = t.results + t.clear() + t.ok(true, "sanity check") + t.notOk(results.ok, "not ok") + t.equal(results.tests, 39, "total test count") + t.equal(results.passTotal, 30, "tests passed") + t.equal(results.fail, 9, "tests failed") + t.type(results.ok, "boolean", "ok is boolean") + t.type(results.skip, "number", "skip is number") + t.type(results, "Results", "results isa Results") + t.type(t, "Test", "test isa Test") + t.type(t, "Harness", "test isa Harness") + t.end() + } +}) + + diff --git a/node_modules/tap/test/nested-test.js b/node_modules/tap/test/nested-test.js new file mode 100644 index 0000000..493f13a --- /dev/null +++ b/node_modules/tap/test/nested-test.js @@ -0,0 +1,23 @@ +var tap = require("../"), + test = tap.test, + util = require('util'); + +test("parent", function (t) { + // TODO: Make grandchildren tests count? + t.plan(3); + t.ok(true, 'p test'); + t.test("subtest", function (t) { + t.ok(true, 'ch test'); + t.test('nested subtest', function(t) { + t.ok(true, 'grch test'); + t.end(); + }); + t.end(); + }); + t.test('another subtest', function(t) { + t.ok(true, 'ch test 2'); + t.end(); + }); + t.end(); +}) + diff --git a/node_modules/tap/test/non-tap-output.js b/node_modules/tap/test/non-tap-output.js new file mode 100644 index 0000000..929e9aa --- /dev/null +++ b/node_modules/tap/test/non-tap-output.js @@ -0,0 +1,12 @@ +console.log("everything is fine\n" + +"there are no errors\n" + +"this output is not haiku.\n\n" + +"is 8 ok?\n" + +"ok, 8 can stay.\n" + +"ok 100 might be confusing\n" + +" but: nevertheless, here we are\n" + +" this: is indented\n" + +" and: it\n" + +" might: ~\n" + +" be: yaml?\n" + +"ok done now, exiting") diff --git a/node_modules/tap/test/result-trap.js b/node_modules/tap/test/result-trap.js new file mode 100644 index 0000000..1ac600f --- /dev/null +++ b/node_modules/tap/test/result-trap.js @@ -0,0 +1,25 @@ +var tap = require("../") + +tap.test("trap result #TODO", function (t0) { + + console.log("not ok 1 result event trapping #TODO") + return t0.end() + + t0.plan(3) + + var t1 = new(tap.Harness)(tap.Test).test() + + t1.plan(1) + + t1.on("result", function (res) { + if (res.wanted === 4) { + t0.equal(res.found, 3) + t0.equal(res.wanted, 4) + + t0.end() + t1.end() + } + }) + + t1.equal(1 + 2, 4) +}) diff --git a/node_modules/tap/test/simple-harness-test-with-plan.js b/node_modules/tap/test/simple-harness-test-with-plan.js new file mode 100644 index 0000000..813c4cf --- /dev/null +++ b/node_modules/tap/test/simple-harness-test-with-plan.js @@ -0,0 +1,16 @@ +var tap = require("../") + , test = tap.test + , plan = tap.plan + +plan(2) + +test("trivial success", function (t) { + t.ok(true, "it works") + t.end() +}) + +test("two tests", function (t) { + t.equal(255, 0xFF, "math should work") + t.notOk(false, "false should not be ok") + t.end() +}) diff --git a/node_modules/tap/test/simple-harness-test.js b/node_modules/tap/test/simple-harness-test.js new file mode 100644 index 0000000..64451ae --- /dev/null +++ b/node_modules/tap/test/simple-harness-test.js @@ -0,0 +1,13 @@ +var tap = require("../") + , test = tap.test + +test("trivial success", function (t) { + t.ok(true, "it works") + t.end() +}) + +test("two tests", function (t) { + t.equal(255, 0xFF, "math should work") + t.notOk(false, "false should not be ok") + t.end() +}) diff --git a/node_modules/tap/test/test-test.js b/node_modules/tap/test/test-test.js new file mode 100644 index 0000000..f383941 --- /dev/null +++ b/node_modules/tap/test/test-test.js @@ -0,0 +1,91 @@ +var tap = require("../") + , test = tap.test + , Test = require("../lib/tap-test") + , Harness = require("../lib/tap-harness") + +test("testing the test object", function (t) { + + t.isa(t, Test, "test object should be instanceof Test") + t.isa(t, Harness, "test object should be instanceof Harness") + t.is(t._Test, Test, "test._Test should be the Test class") + + // now test all the methods. + ; [ "isNotDeepEqual" + , "equals" + , "inequivalent" + , "threw" + , "strictEqual" + , "emit" + , "fail" + , "strictEquals" + , "notLike" + , "dissimilar" + , "true" + , "assert" + , "is" + , "ok" + , "isEqual" + , "isDeeply" + , "deepEqual" + , "deepEquals" + , "pass" + , "length" + , "skip" + , "isNotEqual" + , "looseEquals" + , "false" + , "notDeeply" + , "ifErr" + , "hasFields" + , "isNotDeeply" + , "like" + , "similar" + , "notOk" + , "isDissimilar" + , "isEquivalent" + , "doesNotEqual" + , "isSimilar" + , "notDeepEqual" + , "type" + , "notok" + , "isInequivalent" + , "isNot" + , "same" + , "isInequal" + , "_endNice" + , "ifError" + , "iferror" + , "clear" + , "has" + , "not" + , "timeout" + , "notSimilar" + , "isUnlike" + , "notEquals" + , "unsimilar" + , "result" + , "doesNotThrow" + , "error" + , "constructor" + , "notEqual" + , "throws" + , "isLike" + , "isNotSimilar" + , "isNotEquivalent" + , "inequal" + , "notEquivalent" + , "isNotLike" + , "equivalent" + , "looseEqual" + , "equal" + , "unlike" + , "doesNotHave" + , "comment" + , "isa" + ].forEach(function (method) { + t.ok(t[method], "should have "+method+" method") + t.isa(t[method], "function", method+" method should be a function") + }) + t.end() +}) + diff --git a/node_modules/tap/test/timeout.js b/node_modules/tap/test/timeout.js new file mode 100644 index 0000000..4ee409c --- /dev/null +++ b/node_modules/tap/test/timeout.js @@ -0,0 +1,33 @@ +var tap = require("../") + +tap.test("timeout test with plan only", function (t) { + console.error("timeout test") + t.plan(2) + console.error("t.plan="+t._plan) + setTimeout(function () { + console.error("a assert") + t.ok(true, "a") + }, 1000) + setTimeout(function () { + console.error("b assert") + t.ok(true, "b") + }, 1000) +}) + +tap.test("timeout test with plan and end", function (t) { + console.error("timeout test") + t.plan(2) + + var tc = 2 + console.error("t.plan="+t._plan) + setTimeout(function () { + console.error("a assert") + t.ok(true, "a") + if (-- tc === 0) t.end() + }, 1000) + setTimeout(function () { + console.error("b assert") + t.ok(true, "b") + if (-- tc === 0) t.end() + }, 1000) +}) diff --git a/node_modules/tap/test/trivial-success.js b/node_modules/tap/test/trivial-success.js new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/traverse/.eslintrc b/node_modules/traverse/.eslintrc new file mode 100644 index 0000000..1fc98be --- /dev/null +++ b/node_modules/traverse/.eslintrc @@ -0,0 +1,33 @@ +{ + "root": true, + + "extends": "@ljharb/eslint-config/node/0.4", + + "rules": { + "array-bracket-newline": 0, + "array-callback-return": 0, + "array-element-newline": 0, + "complexity": 0, + "func-style": [2, "declaration"], + "global-require": 1, + "max-lines-per-function": 0, + "max-statements-per-line": 1, + "multiline-comment-style": 0, + "no-proto": 0, + "no-sparse-arrays": 1, + "no-underscore-dangle": 0, + "no-invalid-this": 0, + "object-curly-newline": 0, + "sort-keys": 0, + }, + + "overrides": [ + { + "files": "examples/**", + "rules": { + "no-console": 0, + "no-plusplus": 0, + }, + }, + ], +} diff --git a/node_modules/traverse/.github/FUNDING.yml b/node_modules/traverse/.github/FUNDING.yml new file mode 100644 index 0000000..e7dd4fa --- /dev/null +++ b/node_modules/traverse/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [ljharb] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: npm/traverse +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with a single custom sponsorship URL diff --git a/node_modules/traverse/CHANGELOG.md b/node_modules/traverse/CHANGELOG.md new file mode 100644 index 0000000..82c6f63 --- /dev/null +++ b/node_modules/traverse/CHANGELOG.md @@ -0,0 +1,432 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v0.6.7](https://github.com/ljharb/js-traverse/compare/v0.6.6...v0.6.7) - 2022-10-12 + +### Commits + +- [eslint] fix indentation and whitespace [`89fc65c`](https://github.com/ljharb/js-traverse/commit/89fc65c5c9f2778cb63d583b1fcd83a31ca104f4) +- [eslint] cleanup [`1921966`](https://github.com/ljharb/js-traverse/commit/1921966fff1933e086d413acc44c2cf43a130fae) +- [meta] add `auto-changelog` [`c291ed2`](https://github.com/ljharb/js-traverse/commit/c291ed225c7b5257372a3d30951eaefc186107e7) +- [actions] add reusable workflows [`9a8fd34`](https://github.com/ljharb/js-traverse/commit/9a8fd34a6111f3f6dff43a7f22d272c46243d68f) +- [Dev Deps] update `tape` [`afd6a95`](https://github.com/ljharb/js-traverse/commit/afd6a95c5ab6b8ed2e29d044b5ff8724ed992c4d) +- [eslint] add eslint [`559372e`](https://github.com/ljharb/js-traverse/commit/559372ec96b460c45953c4c00f931f7fee36dce7) +- [readme] rename, add badges [`0e613fd`](https://github.com/ljharb/js-traverse/commit/0e613fdf7d3712e9b18a678d45cadd639233c79e) +- [meta] create FUNDING.yml; add `funding` in package.json [`26a9ae3`](https://github.com/ljharb/js-traverse/commit/26a9ae3a2e6ff06a3af9f1301ec4ef08ceb99bec) +- [meta] use `npmignore` to autogenerate an npmignore file [`0e09fe6`](https://github.com/ljharb/js-traverse/commit/0e09fe6105466f5e11ff4e1d12fa5cb77848b900) +- Only apps should have lockfiles [`e1ac253`](https://github.com/ljharb/js-traverse/commit/e1ac253acfa4917617c01b7d76d80741cbe379ce) +- [meta] update URLs [`035e2c0`](https://github.com/ljharb/js-traverse/commit/035e2c05c52acde26d5c13599748a901d1bbf237) +- [meta] add `safe-publish-latest` [`c2797ac`](https://github.com/ljharb/js-traverse/commit/c2797ac1218e9c8da1a9dd3863ecf3698e57878f) +- [Tests] add `aud` in `posttest` [`ff93f53`](https://github.com/ljharb/js-traverse/commit/ff93f5380201ccbd0bf22188ed4943b739174589) + +## [v0.6.6](https://github.com/ljharb/js-traverse/compare/v0.6.5...v0.6.6) - 2013-09-23 + +### Commits + +- remove tap as a dep to get around the cyclic library issues [`85e1b23`](https://github.com/ljharb/js-traverse/commit/85e1b23ea360b4e6918f998c95ef84d8a0d9a1d2) +- guard for the presence of getTime [`98f278a`](https://github.com/ljharb/js-traverse/commit/98f278a34a957134688e147ec65b1b1115244234) +- use getTime() for firefox browser support [`ee928ca`](https://github.com/ljharb/js-traverse/commit/ee928ca5c2b6a3b19cecd01a743d38d3cddaccf5) + +## [v0.6.5](https://github.com/ljharb/js-traverse/compare/v0.6.4...v0.6.5) - 2013-08-30 + +### Commits + +- merge the null fix [`c405df2`](https://github.com/ljharb/js-traverse/commit/c405df2c8a8d49321ac8081b928b4e5df5f80237) +- fix for Cannot convert null to object at hasOwnProperty (native) when node is null [`d9f52fa`](https://github.com/ljharb/js-traverse/commit/d9f52fa400c53f5bf1b5e388c0dd457c4dc651e3) + +## [v0.6.4](https://github.com/ljharb/js-traverse/compare/v0.6.3...v0.6.4) - 2012-12-17 + +### Commits + +- upgraded readme [`c45db75`](https://github.com/ljharb/js-traverse/commit/c45db75c4a606b724156e50b14688b503e146cf3) +- using tape [`5c8e966`](https://github.com/ljharb/js-traverse/commit/5c8e966e8636fdab2c55cac0e4e0958f06f7ca1f) +- using testling-ci [`73f3061`](https://github.com/ljharb/js-traverse/commit/73f306146afa8ccc884cb0d43788338e294320cc) +- hasOwnProperty stub [`c889666`](https://github.com/ljharb/js-traverse/commit/c889666d81d79cbfd99372bea641e6938bd5531c) +- add a comma [`3f8d778`](https://github.com/ljharb/js-traverse/commit/3f8d778dbc0b070c972839fd1ac23b253a99cce2) + +## [v0.6.3](https://github.com/ljharb/js-traverse/compare/v0.6.2...v0.6.3) - 2012-06-18 + +### Commits + +- 0.6.3, fixes bugs when the replacement for an object is not an object [`09f560c`](https://github.com/ljharb/js-traverse/commit/09f560c0f910a9ac76fa0fc507655627cda6dd6f) +- fixed merge conflicts [`576832a`](https://github.com/ljharb/js-traverse/commit/576832a2e4d91197b88a002dec643310fa9b3b26) +- Update state with the current node before recursing [`3857dca`](https://github.com/ljharb/js-traverse/commit/3857dcaeaceca9a739300b0b846c1094ddf3b26f) +- Add test for replacing objects with strings and vice-versa [`28d5fb6`](https://github.com/ljharb/js-traverse/commit/28d5fb64e44237e21c01904d6e46b34626d66d33) +- s/Object_keys/objectKeys/g [`ef3694f`](https://github.com/ljharb/js-traverse/commit/ef3694f1fcfe948c39a5caaded33480bcbdafdfa) +- Only set state.keys when necessary [`ee66cd1`](https://github.com/ljharb/js-traverse/commit/ee66cd1c71db7701769323548916ce860f442d03) +- Fix crash when node is a string and this.update is called with an object. [`5c6f161`](https://github.com/ljharb/js-traverse/commit/5c6f161f2006df87f231317f3413bc38ad799b7d) + +## [v0.6.2](https://github.com/ljharb/js-traverse/compare/v0.6.1...v0.6.2) - 2012-06-16 + +### Commits + +- using tap [`4f4a3e5`](https://github.com/ljharb/js-traverse/commit/4f4a3e504e702bffa88ea15b687a3712b56938dd) +- re-generate the package.json [`99a0a15`](https://github.com/ljharb/js-traverse/commit/99a0a159b28d8175c159a208e276256a0240c056) +- fix to reconstruct prototypes in browsers without Object.create() [`0cb3f34`](https://github.com/ljharb/js-traverse/commit/0cb3f349e381109287c9fac1391472796b7fc0bd) +- using travis [`57e7ccd`](https://github.com/ljharb/js-traverse/commit/57e7ccd6b10e92e737ef41b332172b38b4d5cc2e) +- s/^js-// [`1c2bae3`](https://github.com/ljharb/js-traverse/commit/1c2bae3a286b38c5f7cd22ffe4bbcc165bab7245) +- drop 0.4 [`2331189`](https://github.com/ljharb/js-traverse/commit/2331189e047b94fc95edc6f6fce11cb0cfcbb435) + +## [v0.6.1](https://github.com/ljharb/js-traverse/compare/v0.6.0...v0.6.1) - 2012-04-06 + +### Commits + +- check builtins using the toString.call trick [`459378b`](https://github.com/ljharb/js-traverse/commit/459378b6dd18ea95e9a012fd96a5d0d30ce83d64) +- support for traversing an Error object. [`642dd51`](https://github.com/ljharb/js-traverse/commit/642dd51c41ca7e41774bbde948913d9a7996633e) +- fixed the tests for how typeof a regex is now "object" [`9250084`](https://github.com/ljharb/js-traverse/commit/925008491725beec15216147329f3df907285975) +- less annoying constructor [`2c5f693`](https://github.com/ljharb/js-traverse/commit/2c5f693b60daa8b0f2cc9566fa62ec6b733d6a84) +- bump for error fixes [`6b78600`](https://github.com/ljharb/js-traverse/commit/6b78600f53284b324e733f836b9fd3b47fa5b28d) + +## [v0.6.0](https://github.com/ljharb/js-traverse/compare/v0.5.2...v0.6.0) - 2012-02-20 + +### Commits + +- has() with tests, documented get() and set() too [`aeebf14`](https://github.com/ljharb/js-traverse/commit/aeebf1466c2b7b5660545cc4365b0a66bc54a765) + +## [v0.5.2](https://github.com/ljharb/js-traverse/compare/v0.5.1...v0.5.2) - 2011-10-16 + +### Commits + +- Should be able to stop traversing when removing or deleting [`4aa61ef`](https://github.com/ljharb/js-traverse/commit/4aa61ef874d81a633aec4b72c3b2bc5ede64947f) +- relative requires for the tests [`9d4d4c5`](https://github.com/ljharb/js-traverse/commit/9d4d4c5d4c3abb9ef38c6f878a7ee8c61f0264c1) +- Added documentation for stopHere-flag on remove and delete [`2bb8018`](https://github.com/ljharb/js-traverse/commit/2bb80186f15d860cd5e17934c270bd0814236004) +- bump for stopHere on delete and remove [`a23839a`](https://github.com/ljharb/js-traverse/commit/a23839a473d0e91814911210f01d2ec4a95d1098) + +## [v0.5.1](https://github.com/ljharb/js-traverse/compare/v0.5.0...v0.5.1) - 2011-08-23 + +### Commits + +- fix for brokenness in IE with using the wrong variable name for the prototype checking [`4cb7bcb`](https://github.com/ljharb/js-traverse/commit/4cb7bcbd155df29268c8b8fc249f0f838aaa94f3) + +## [v0.5.0](https://github.com/ljharb/js-traverse/compare/v0.4.6...v0.5.0) - 2011-08-23 + +### Commits + +- spun off deepEqual into a utility library [`9d5148a`](https://github.com/ljharb/js-traverse/commit/9d5148a22dbe1484286c216959625168275457db) +- traverse now works with all the IEs [`96d9e25`](https://github.com/ljharb/js-traverse/commit/96d9e2564fc0f1413a7a1371cfd9cc5600896771) +- tests all updated for the removal of deepEqual from the main lib [`9ebde92`](https://github.com/ljharb/js-traverse/commit/9ebde9226720231d4390ebdaea04a0c4652caf21) +- stubs for non-es5 browsers, didn't break any unit tests [`559a6f1`](https://github.com/ljharb/js-traverse/commit/559a6f18873d48a97b293c058cc2a8f334dfd535) + +## [v0.4.6](https://github.com/ljharb/js-traverse/compare/v0.4.5...v0.4.6) - 2011-07-27 + +### Commits + +- some minor adjustments to expose keys for sibling calculations [`a936bea`](https://github.com/ljharb/js-traverse/commit/a936bea1e4d164ab33459352234eaea9a1d84a38) + +## [v0.4.5](https://github.com/ljharb/js-traverse/compare/v0.4.4...v0.4.5) - 2011-07-24 + +### Commits + +- include circular ref example in the readme, Traverse => traverse [`4a6285f`](https://github.com/ljharb/js-traverse/commit/4a6285f71f4220550d4587090fd832ec9fcb10b7) +- scrub example [`ec1fb18`](https://github.com/ljharb/js-traverse/commit/ec1fb18b494f1bcb6b1ce4a2a86dce6560ae746d) +- bump for exposing parents [`5cb4ecb`](https://github.com/ljharb/js-traverse/commit/5cb4ecb37b2af64367f466cd1994d18c45def070) +- export 'parents' to context [`5af2f8d`](https://github.com/ljharb/js-traverse/commit/5af2f8d24e2e9dce5c43ae5abbe2ff23384610fc) + +## [v0.4.4](https://github.com/ljharb/js-traverse/compare/v0.4.3...v0.4.4) - 2011-07-20 + +### Commits + +- allow setting of keys (ordering) in before modifier [`9fb8e2c`](https://github.com/ljharb/js-traverse/commit/9fb8e2c126e5bcec59e382b59e040ae764ea9045) +- note about this.keys, bump [`1148bc7`](https://github.com/ljharb/js-traverse/commit/1148bc7603411c423b41a5cb396b27ab6ca2c565) + +## [v0.4.3](https://github.com/ljharb/js-traverse/compare/v0.4.2...v0.4.3) - 2011-06-14 + +### Commits + +- bump to 0.4.3 for guybrush's IE fixes [`c74a7ea`](https://github.com/ljharb/js-traverse/commit/c74a7eaa83edb86e20b2427bbd2068339b385aa8) +- another fix for IE [`ed86376`](https://github.com/ljharb/js-traverse/commit/ed86376b826284a858d040f8d0a40532a8d4d919) +- fix for IE [`35949ef`](https://github.com/ljharb/js-traverse/commit/35949ef979662e6a9118beca80d0f6a080828ddc) + +## [v0.4.2](https://github.com/ljharb/js-traverse/compare/v0.4.1...v0.4.2) - 2011-06-11 + +### Commits + +- bump to 0.4.2 for this.block() with a passing test [`d945818`](https://github.com/ljharb/js-traverse/commit/d945818e0e489d9ffe2dd25ea64c598085139c69) +- note about stopHere for update() in the readme [`18f3e27`](https://github.com/ljharb/js-traverse/commit/18f3e273c7ec22b7121438d517eaeb7832f18d99) + +## [v0.4.1](https://github.com/ljharb/js-traverse/compare/v0.4.0...v0.4.1) - 2011-06-10 + +### Commits + +- moved stop behavior in updates into a second keepGoing argument [`1d31897`](https://github.com/ljharb/js-traverse/commit/1d318974255df34a821da53cb3d573153a0682b2) + +## [v0.4.0](https://github.com/ljharb/js-traverse/compare/v0.3.8...v0.4.0) - 2011-06-10 + +### Commits + +- an amazing number of test descriptions were getting ignored [`1d043f0`](https://github.com/ljharb/js-traverse/commit/1d043f09e6eb6ecf8456295efdbe4e7298f7c3c8) +- better failing super deep test [`01d35ce`](https://github.com/ljharb/js-traverse/commit/01d35ce70d514243d1854bd4c50eb0fa5321ef2b) +- stop() passes its test [`79d615f`](https://github.com/ljharb/js-traverse/commit/79d615f8dc60dc491da82d80f0fdab1a53974d3d) +- passing test for deep reduce and this.stop() [`9aea0a1`](https://github.com/ljharb/js-traverse/commit/9aea0a10cdd48f23ef40aeaee54f2d50053d77ff) +- subexpr test passes by checking if update() happened [`44e731b`](https://github.com/ljharb/js-traverse/commit/44e731b972b864b1de1ef315bf1ce4dbba3a7d67) +- passing new tests yay [`3d5057a`](https://github.com/ljharb/js-traverse/commit/3d5057a832c14f51d07ddb7f3331769c37f6192d) +- failing test for this.stop() [`090c3d4`](https://github.com/ljharb/js-traverse/commit/090c3d4d2de99586ad89a8b51ab8ea5664747e3e) +- subexpressions from update()s shouldn't be traversed, failing test [`be2b574`](https://github.com/ljharb/js-traverse/commit/be2b5746670b213d1c57c8f1f6d59a78e8ff88e6) +- passing test for stop map too hooray [`0ee24cc`](https://github.com/ljharb/js-traverse/commit/0ee24cc01673ea3dfd63e854b70bcd7b36b9884d) +- test for arity shows more bugs [`da698d6`](https://github.com/ljharb/js-traverse/commit/da698d6c7f5b712c9d89b3fa42a00b9cf2b42b4c) + +## [v0.3.8](https://github.com/ljharb/js-traverse/compare/v0.3.7...v0.3.8) - 2011-06-06 + +### Commits + +- tests for some bugs in deepEqual [`2b15a41`](https://github.com/ljharb/js-traverse/commit/2b15a410f723f0ed5b3bdc019803deff7d70b7c0) +- deep equal tests now pass, delete map tests fail though [`bfdc40e`](https://github.com/ljharb/js-traverse/commit/bfdc40e35f7a3ec3acf96f7f8599602747ef999d) +- delete map redux test also passes for deleted element construction syntax [,,,] etc [`56553ff`](https://github.com/ljharb/js-traverse/commit/56553ff7753e21480023caa488791a4d88f36673) +- now passing all the equality tests again [`6721461`](https://github.com/ljharb/js-traverse/commit/6721461c4fc1323c5784f16ee5efcd7a18d77122) +- tests for remove() and delete() [`f5d429a`](https://github.com/ljharb/js-traverse/commit/f5d429a15a77e2a7ce33c2485a2b3ee43f41d341) +- remove tests [`7010fe2`](https://github.com/ljharb/js-traverse/commit/7010fe2bdc568f59576da576c09b5a7c90291b89) +- better failing levels test for deepEqual [`73efbe5`](https://github.com/ljharb/js-traverse/commit/73efbe5ea5f2c61c8c3f6e4cd6fbc2d290e33188) +- failing deepEqual comparison with undefined throws [`0a6d27d`](https://github.com/ljharb/js-traverse/commit/0a6d27d139baefbd2a19411a6a4805b2bbd5d664) +- remove unused seq devDependency, bump expresso version [`0c1e021`](https://github.com/ljharb/js-traverse/commit/0c1e0218a991fa6fd71468ee54cdd364cab5d1b5) + +## [v0.3.7](https://github.com/ljharb/js-traverse/compare/v0.3.6...v0.3.7) - 2011-06-05 + +### Commits + +- now with syntax-highlightable markdown snippets [`d4a7710`](https://github.com/ljharb/js-traverse/commit/d4a771015d6483859784a585912a816bd4d82484) +- failing circular map scrub test [`9f36635`](https://github.com/ljharb/js-traverse/commit/9f3663533d34d4280c6dd49387a8516b40ae67c4) +- fix for immutable removal, bump to 0.3.7 [`9528471`](https://github.com/ljharb/js-traverse/commit/9528471cad4bbe810d7b10133f53ea0937e6667d) + +## [v0.3.6](https://github.com/ljharb/js-traverse/compare/v0.3.5...v0.3.6) - 2011-06-03 + +### Commits + +- tests for not-yet-written deepEqual() [`5267ae1`](https://github.com/ljharb/js-traverse/commit/5267ae183ac44d82438da0c3665a31c456e27fdb) +- deepEqual now passes several tests [`6fe06a5`](https://github.com/ljharb/js-traverse/commit/6fe06a5a7e7d76e4cdeaae148fbd40964a8bd478) +- dox for deepEqual [`5eab662`](https://github.com/ljharb/js-traverse/commit/5eab662f486e423e8d1d4bde65c47f99243aa1fe) +- untested get and set [`7fa7247`](https://github.com/ljharb/js-traverse/commit/7fa7247dcfe2b2ddcc0ea9ecd2c7329a1e034151) +- missing comma fixed the regexp test and also an implementation for typeof "function" [`fc23e4f`](https://github.com/ljharb/js-traverse/commit/fc23e4fb50e8adf0891c416c994390b02545a197) +- a passing test for the other case of structural deep circular reference checking [`04e5492`](https://github.com/ljharb/js-traverse/commit/04e54928da73b2d02a4430bfa79e2505af51068a) +- some tests were wrong, regexp test rightly still fails [`b9d1110`](https://github.com/ljharb/js-traverse/commit/b9d11107f62367453eaf707b2cb29df1533043ea) +- circular test for topological circular equality passes [`b423996`](https://github.com/ljharb/js-traverse/commit/b4239962ab0312d660a7895b74fda36368d057f9) +- and another test just in case for non-root circular ref checks [`a914717`](https://github.com/ljharb/js-traverse/commit/a9147171961cbf7ae8a9a45fb73cd3c0591da33b) +- actually check function equality, all tests now passing [`cb7c1b0`](https://github.com/ljharb/js-traverse/commit/cb7c1b04cb7b4b1037419349000e96b13d824ab7) + +## [v0.3.5](https://github.com/ljharb/js-traverse/compare/v0.3.4...v0.3.5) - 2011-05-28 + +### Commits + +- took out up-front cloning, only fails date test [`718d01b`](https://github.com/ljharb/js-traverse/commit/718d01b06cdb9f9c948d1ac5886a7a3fc17d1008) +- cleaned up root handling, fails circDubMap still [`9ed99f3`](https://github.com/ljharb/js-traverse/commit/9ed99f3dd74123c17eb2787bfac6207c643d39d6) +- updated tests for expresso updates ages ago [`f95bf5e`](https://github.com/ljharb/js-traverse/commit/f95bf5e0eb7300832d326960289ec7f395630bfd) +- passes all its tests again [`d0dac52`](https://github.com/ljharb/js-traverse/commit/d0dac529201dc8b3e6a7dba3d853d839b746ffbf) + +## [v0.3.4](https://github.com/ljharb/js-traverse/compare/v0.3.3...v0.3.4) - 2011-04-16 + +### Commits + +- updated readme for this.delete() and this.remove() [`e4cea30`](https://github.com/ljharb/js-traverse/commit/e4cea309a1f035400c8f4e9ebd55e6e0cecf8a35) +- quote the delete keyword [`42d0460`](https://github.com/ljharb/js-traverse/commit/42d0460fc6624a38775bd65a4788cfa8b3f08825) + +## [v0.3.3](https://github.com/ljharb/js-traverse/compare/v0.3.2...v0.3.3) - 2011-04-15 + +### Commits + +- this.remove() and this.delete() with passing tests [`d603771`](https://github.com/ljharb/js-traverse/commit/d603771e1381e0d62c70bc1f47736c8eaa6cfa6f) + +## [v0.3.2](https://github.com/ljharb/js-traverse/compare/v0.3.1...v0.3.2) - 2011-04-10 + +### Commits + +- now traverses over dates correctly and should work for other builtins [`bb8d1b5`](https://github.com/ljharb/js-traverse/commit/bb8d1b567489a94507941f4a6bda2224ed2d9692) +- failing date map test [`a504425`](https://github.com/ljharb/js-traverse/commit/a504425aa3021371f67498b27d4a98e6f7a4283f) +- forgot the console.dir [`fb2c472`](https://github.com/ljharb/js-traverse/commit/fb2c4729ac1a7824358ee04ea840a35ac3ea17af) + +## [v0.3.1](https://github.com/ljharb/js-traverse/compare/v0.3.0...v0.3.1) - 2011-02-18 + +### Commits + +- updated readme and examples for the new interface changes [`aa2d4f3`](https://github.com/ljharb/js-traverse/commit/aa2d4f3f1cc88a230cdb8fae3b1b416773860ef4) +- mutability tests all pass [`36df874`](https://github.com/ljharb/js-traverse/commit/36df874ae431b0e31dc809c0b949073774f624b4) +- updated tests to not use sys anymore [`7a0969f`](https://github.com/ljharb/js-traverse/commit/7a0969fbb39a7a66f4bd46ca8172edef15b675ea) +- simpler clone implementation [`6a6cb49`](https://github.com/ljharb/js-traverse/commit/6a6cb49f2da571470a6b024b1e8db5ef2080b946) +- double circular ref test failing, not aggressive enough [`d190897`](https://github.com/ljharb/js-traverse/commit/d190897a9763549e2a077c01378520d519b402f7) +- reduce() now too [`c89ae4b`](https://github.com/ljharb/js-traverse/commit/c89ae4be025534494422cc1265f50595828398b3) +- fix for isRoot, check path.length, not node === root [`423066e`](https://github.com/ljharb/js-traverse/commit/423066e821070ffb8f8a29022175b08f4bfc5d99) +- passing circular ref update forEach test but failing for likewise with map [`d411695`](https://github.com/ljharb/js-traverse/commit/d4116955a4fbc00a2fd716e3885e334b9664d670) +- trade some space savings for less agressive circular reference algorithm (the same as console.dir it seems) [`ee52d80`](https://github.com/ljharb/js-traverse/commit/ee52d80d2b18ea069f38039b210f68b00aa29d4b) +- failing test for circular ref updates [`42b6b84`](https://github.com/ljharb/js-traverse/commit/42b6b84917f34f80729339127360c36bd62fa9bd) + +## [v0.3.0](https://github.com/ljharb/js-traverse/compare/v0.2.4...v0.3.0) - 2011-02-18 + +### Commits + +- completely rewrote Traverse, deleted hash.js and web.js [`414c726`](https://github.com/ljharb/js-traverse/commit/414c72637807c0e6e86f38f66146d729d0bbf3f2) +- tests pass again with the rewrite [`f0f76cc`](https://github.com/ljharb/js-traverse/commit/f0f76cc6b08849644a79a828e249be2d8896797a) + +## [v0.2.4](https://github.com/ljharb/js-traverse/compare/v0.2.3...v0.2.4) - 2011-02-03 + +### Commits + +- for some silly reason I was requiring sys [`95712d9`](https://github.com/ljharb/js-traverse/commit/95712d9de9e6182860418754690bb98c40462d62) + +## [v0.2.3](https://github.com/ljharb/js-traverse/compare/v0.2.2...v0.2.3) - 2010-11-19 + +### Commits + +- a hash exclude test and a package bump [`536b93d`](https://github.com/ljharb/js-traverse/commit/536b93dc0474a27a0f5c3f53b8a80cf3eb32e4e4) +- exclude to remove keys [`752f64f`](https://github.com/ljharb/js-traverse/commit/752f64f66da9fb424a4f78fc2d4ad0ef096ba65d) + +## [v0.2.2](https://github.com/ljharb/js-traverse/compare/v0.2.1...v0.2.2) - 2010-10-25 + +### Commits + +- detect test, package bump [`04b1d50`](https://github.com/ljharb/js-traverse/commit/04b1d50e73870026fd21ab9ccea609c3f1351080) +- detect like in ruby [`441f3b4`](https://github.com/ljharb/js-traverse/commit/441f3b4bef547cb4b07b10e139fa68ec1b9b4a95) + +## [v0.2.1](https://github.com/ljharb/js-traverse/compare/v0.2.0...v0.2.1) - 2010-09-11 + +### Commits + +- better compatability fallbacks for ff, maybe ie [`33577aa`](https://github.com/ljharb/js-traverse/commit/33577aae0ccdc441e40fab0a945d831805cc8148) +- compact and size for Hash (can't do .length since the function prototype has that) [`b9e6db5`](https://github.com/ljharb/js-traverse/commit/b9e6db57addbcc67a1cfec0ab9a380573d0cab8e) +- more correct string behavior in stringify example [`b9750ff`](https://github.com/ljharb/js-traverse/commit/b9750ff32be6ad76892bdf01a533bd13907d92f7) + +## [v0.2.0](https://github.com/ljharb/js-traverse/compare/v0.1.4...v0.2.0) - 2010-09-08 + +### Commits + +- deepEquals to make the tests simpler [`a962ed8`](https://github.com/ljharb/js-traverse/commit/a962ed8d0e5e3baf8279e5b3bf2476e5d2c7dbb8) +- top-level Hash functions more closely mirror Hash() functions [`35298be`](https://github.com/ljharb/js-traverse/commit/35298be61b782681f6d0a555a0ab8db673419293) +- .has with tests [`02727cf`](https://github.com/ljharb/js-traverse/commit/02727cfe1d86cf6c36daa700513861fe1f4a8066) +- test for valuesAt and now takes a single non-array key too [`3487771`](https://github.com/ljharb/js-traverse/commit/348777160fe2008186d5089fddd8e5686d0c1c3a) +- take out memoization since it breaks if the hash gets modified outside the fluent interface [`67b6d3d`](https://github.com/ljharb/js-traverse/commit/67b6d3d5ea7d8ed7127f7f9129660510f9292716) +- zip and zip constructor [`616514e`](https://github.com/ljharb/js-traverse/commit/616514ebd72a9c8a4e4b59763ee0462dcae89de0) +- zip test passes [`0226636`](https://github.com/ljharb/js-traverse/commit/0226636db7b8d3a49c2a7cbb26d18f7eeba061c1) + +## [v0.1.4](https://github.com/ljharb/js-traverse/compare/v0.1.3...v0.1.4) - 2010-09-08 + +### Commits + +- test for compact passes [`ec171ba`](https://github.com/ljharb/js-traverse/commit/ec171bab4d2b2339752cbab00c0d4b65652de0f0) +- compact like in ruby, but for hashes [`0d8e1e6`](https://github.com/ljharb/js-traverse/commit/0d8e1e624005b58aecd6a6dddaefc20da33cdf4a) + +## [v0.1.3](https://github.com/ljharb/js-traverse/compare/v0.1.2...v0.1.3) - 2010-09-04 + +### Commits + +- add stringify to examples [`6683529`](https://github.com/ljharb/js-traverse/commit/668352964878c1f896b3f57b69a989717c0fae5c) +- now isArray and instanceof works for arrays [`fa2d72b`](https://github.com/ljharb/js-traverse/commit/fa2d72b33705adccc74bf12e94e4e68d7261469c) + +## [v0.1.2](https://github.com/ljharb/js-traverse/compare/v0.1.1...v0.1.2) - 2010-09-04 + +### Commits + +- pushed walk() out of map [`e7ec7de`](https://github.com/ljharb/js-traverse/commit/e7ec7dee4b33968b0b380e54202d5d01af5e9a80) +- modifiers seem to work [`f0ee567`](https://github.com/ljharb/js-traverse/commit/f0ee567968c4b218ae729d76520ab2f3fe2c372f) +- stringify test for new modifiers [`6de18e5`](https://github.com/ljharb/js-traverse/commit/6de18e5012578b4a71faf442962ce999fc72624c) +- before, after, and between callbacks to fancier traversing [`5662b6f`](https://github.com/ljharb/js-traverse/commit/5662b6f5265bfec32dccb999b9749cf2569e7d9f) +- updated readme and negative example with new style [`5aa3f84`](https://github.com/ljharb/js-traverse/commit/5aa3f84584fb1a74652485e3cf809f5982a4cb88) +- deprecated .get() in favor of .value [`a8d1645`](https://github.com/ljharb/js-traverse/commit/a8d1645665ebb832ff82eca3317e61bf62ca83ed) +- non-coerced root test fixes an odd bug with array traversal [`f22580a`](https://github.com/ljharb/js-traverse/commit/f22580aacec7b2eb60c38ba8ba1b89324ed3e209) + +## [v0.1.1](https://github.com/ljharb/js-traverse/compare/v0.1.0...v0.1.1) - 2010-09-04 + +### Commits + +- only update when this.update is still around, tests for Traverse.functions [`cc59d56`](https://github.com/ljharb/js-traverse/commit/cc59d56b994759f6acd9efd70d9063ea40f45fbf) +- deprecate modify in favor of map [`f018025`](https://github.com/ljharb/js-traverse/commit/f018025989afdd6c9474d9e9095331500826d553) +- fix nodes and paths [`78edd30`](https://github.com/ljharb/js-traverse/commit/78edd30685e1d47deac4edd7bdd1e1b360a0244f) +- use return values to auto-update [`bc68fa5`](https://github.com/ljharb/js-traverse/commit/bc68fa5426363872835f1b4b73b8abf7920c9bfc) + +## [v0.1.0](https://github.com/ljharb/js-traverse/compare/v0.0.9...v0.1.0) - 2010-09-03 + +### Commits + +- circular refs don't crash it now [`2cdd854`](https://github.com/ljharb/js-traverse/commit/2cdd85460054f91e3130b269a6020e20cb59d7c0) +- new top-level map forEach paths and nodes [`e508823`](https://github.com/ljharb/js-traverse/commit/e5088233c9e09221f2ac766bd95c0ea55e7d0761) +- package bump to 0.1.0 and should work in IE better now too [`4400d88`](https://github.com/ljharb/js-traverse/commit/4400d886d7e33dd811121e7cd5ac5a31a0ca25b0) + +## [v0.0.9](https://github.com/ljharb/js-traverse/compare/v0.0.8...v0.0.9) - 2010-08-27 + +### Commits + +- broke up test into separate exports [`92046a4`](https://github.com/ljharb/js-traverse/commit/92046a4e0622d0db9502a2d6090041935d1bede6) +- forgot the return in ('traverse/web').source() [`188ee17`](https://github.com/ljharb/js-traverse/commit/188ee170de8b087a6bbec6dad92b39a0f1ffc67e) + +## [v0.0.8](https://github.com/ljharb/js-traverse/compare/v0.0.7...v0.0.8) - 2010-08-26 + +### Commits + +- memoization for keys, values, length [`9cffe15`](https://github.com/ljharb/js-traverse/commit/9cffe158a70f4945a6bf000dace4eddf4ca2c344) +- merge, update, and tap [`df5b737`](https://github.com/ljharb/js-traverse/commit/df5b737a7b82711261be325b7f9aa0e7aedc6804) +- length, clone, and copy [`249ec0f`](https://github.com/ljharb/js-traverse/commit/249ec0fcd2b62c6701488c17083433049060ae15) +- updated readme and f.call(self) [`03f6f1e`](https://github.com/ljharb/js-traverse/commit/03f6f1e03c9ccc2a6afb0525393acde13d2b009f) +- more explicit about the licensing (MIT/X11) [`c452103`](https://github.com/ljharb/js-traverse/commit/c4521038e845878ebb20984204f1db7520df9cad) +- oh right and this example file [`d98c125`](https://github.com/ljharb/js-traverse/commit/d98c125d9f9f17ca08260ed57ede2b1fac26da11) +- updated readme for hash traversal [`a56b629`](https://github.com/ljharb/js-traverse/commit/a56b629aae33e6bfe45bc3ec72b65bc84536f57b) +- tests for update, concat, and merge all pass [`7fc4eca`](https://github.com/ljharb/js-traverse/commit/7fc4ecaf203924becd9c88d800216ddad7ecbd4b) +- updated readme for hash stuff [`094ab55`](https://github.com/ljharb/js-traverse/commit/094ab556f795e554e8227016d8fd6acc36f0257c) +- more tests, all pass [`2d9f7a2`](https://github.com/ljharb/js-traverse/commit/2d9f7a245ac6793e8e58ba4c751e551650cfbaac) +- key and value getters [`459def9`](https://github.com/ljharb/js-traverse/commit/459def9529e381d38909f75b182b330e20d3f2f9) +- stupid markdown parens [`0bd932b`](https://github.com/ljharb/js-traverse/commit/0bd932bc6517d08f02ab3aac8cc551425072ead7) +- new valuesAt and extract functions [`883f015`](https://github.com/ljharb/js-traverse/commit/883f015c79ea79acc188a98be3bfa7ad54186266) +- tests for valuesAt and extract pass [`86d71a9`](https://github.com/ljharb/js-traverse/commit/86d71a97241ff84b071a0ff4aed68a99919014ff) +- hash example, some() [`c7a133c`](https://github.com/ljharb/js-traverse/commit/c7a133cbb59d5fa9aedfe3958b9a0898fc5dea4c) +- key and value tests [`92212e5`](https://github.com/ljharb/js-traverse/commit/92212e55cfb1f16f68c14885d644125a83951589) +- copy instead of clone for merge [`4fcece2`](https://github.com/ljharb/js-traverse/commit/4fcece2de64fbe90ef0250f31f4f399a103ec7ed) + +## [v0.0.7](https://github.com/ljharb/js-traverse/compare/v0.0.6...v0.0.7) - 2010-08-26 + +### Commits + +- new hash lib and clone sugar [`586124c`](https://github.com/ljharb/js-traverse/commit/586124cebb2b613ee63d0c76a0d636058c5c9213) +- hash test for map [`393444a`](https://github.com/ljharb/js-traverse/commit/393444a2add24b9dba4f68385518b96a3900de33) +- a test for instances [`1adf75a`](https://github.com/ljharb/js-traverse/commit/1adf75a9cdc13b094b660f17bc496a94fd9576fd) +- new modules format for package.json, boost to 0.0.7 [`0f11600`](https://github.com/ljharb/js-traverse/commit/0f11600d5cfb67b50fb4f4f79dda522d17c9df4f) +- __proto__ trick to make instanceof work on cloned objects [`130a833`](https://github.com/ljharb/js-traverse/commit/130a833014477b7463cb8fbf4de246fd93f990a5) + +## [v0.0.6](https://github.com/ljharb/js-traverse/compare/v0.0.5...v0.0.6) - 2010-08-01 + +### Commits + +- magical webified version of traverse with require('dnode/web').source() [`0043cd6`](https://github.com/ljharb/js-traverse/commit/0043cd6b57327a0d1962b7378e9f6897d963e3c0) +- directories.lib, I forgot. Also scrub requires for later [`2a1f530`](https://github.com/ljharb/js-traverse/commit/2a1f5301601984b09a1746bd0b1699fb88a18264) + +## [v0.0.5](https://github.com/ljharb/js-traverse/compare/v0.0.4...v0.0.5) - 2010-07-28 + +### Commits + +- test for stupid .constructor() bug [`6b9d85d`](https://github.com/ljharb/js-traverse/commit/6b9d85dac5eedd3e043c63fe2cff4881c25f9f98) +- stupid traversal bug, version bump [`4cf36f3`](https://github.com/ljharb/js-traverse/commit/4cf36f3f987a71704064dd6ab6b695ddce0cac47) + +## [v0.0.4](https://github.com/ljharb/js-traverse/compare/v0.0.3...v0.0.4) - 2010-07-27 + +### Commits + +- now using expresso for test suite, json test written [`7d448da`](https://github.com/ljharb/js-traverse/commit/7d448daa7c93444b302095da394f8f47bf3fb61f) +- leaves and negative tests to go with the example, also s/tests/test/ [`13e19bf`](https://github.com/ljharb/js-traverse/commit/13e19bf5441abc903a270eb5abfc985d75a7507b) +- clone in the constructor so updates don't mess up the root object's refs [`fc5903b`](https://github.com/ljharb/js-traverse/commit/fc5903b3b008377d7f06e83ad3bce84957900c8c) +- readme updates for expresso tests and version bump to 0.0.4 [`6993515`](https://github.com/ljharb/js-traverse/commit/69935153c1b54afaee42c58c8e33f15d21f55efe) + +## [v0.0.3](https://github.com/ljharb/js-traverse/compare/v0.0.2...v0.0.3) - 2010-07-21 + +### Commits + +- backwards compatible update for var Traverse = require('traverse') style [`d0f50e9`](https://github.com/ljharb/js-traverse/commit/d0f50e9a6f428b68fc51e1c582148196deb9e209) + +## [v0.0.2](https://github.com/ljharb/js-traverse/compare/v0.0.1...v0.0.2) - 2010-07-14 + +### Commits + +- special check for null, for which typeof(null) == 'object' [`a4128c0`](https://github.com/ljharb/js-traverse/commit/a4128c01a666132b40c69d57d9176a33a1f5046c) +- installation in readme [`a6fc0d6`](https://github.com/ljharb/js-traverse/commit/a6fc0d641970984fefab29773a930f22c925eb91) +- add output to negative example [`590045e`](https://github.com/ljharb/js-traverse/commit/590045e3bc9daf8dbb884f59b3579bf57a7dc42d) +- license file [`519fd1f`](https://github.com/ljharb/js-traverse/commit/519fd1ff6d225d2465899d102519e93ef5334bba) +- s/127/128/ [`5fcb3f5`](https://github.com/ljharb/js-traverse/commit/5fcb3f5256207e392e9500db720aa2aeb3f85304) + +## v0.0.1 - 2010-07-08 + +### Commits + +- initial commit with forEach, modify, get, paths, nodes [`e73bba8`](https://github.com/ljharb/js-traverse/commit/e73bba81dbc8630a0ef6003fa3c12ceaafc4188d) +- more examples [`16bf66e`](https://github.com/ljharb/js-traverse/commit/16bf66e5cf5c537441a98001eae9368d4bae7317) +- readme with json example [`fa8265b`](https://github.com/ljharb/js-traverse/commit/fa8265badad1dfe3df5d1aa6e561a3698e4b1338) +- json example [`607de69`](https://github.com/ljharb/js-traverse/commit/607de691cd1bdeb0ced603d5177e3f855dc20417) +- leaf example [`23ccea5`](https://github.com/ljharb/js-traverse/commit/23ccea575ce9b6984fcd8bb64ccd7f9ee765c258) +- package.json file for version 0.0.1 [`c3266e0`](https://github.com/ljharb/js-traverse/commit/c3266e060d8b5ebfb6472385dba323c7e951fd14) +- npm doesn't like newlines in package.json strings [`6840d4e`](https://github.com/ljharb/js-traverse/commit/6840d4e7c75aaafeca6778a48600759641dfa7f1) diff --git a/node_modules/traverse/LICENSE b/node_modules/traverse/LICENSE new file mode 100644 index 0000000..7b75500 --- /dev/null +++ b/node_modules/traverse/LICENSE @@ -0,0 +1,24 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: +http://www.opensource.org/licenses/mit-license.php + +Copyright 2010 James Halliday (mail@substack.net) + +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. diff --git a/node_modules/traverse/README.md b/node_modules/traverse/README.md new file mode 100644 index 0000000..0bce518 --- /dev/null +++ b/node_modules/traverse/README.md @@ -0,0 +1,228 @@ +# traverse [![Version Badge][npm-version-svg]][package-url] + +[![github actions][actions-image]][actions-url] +[![coverage][codecov-image]][codecov-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] + +[![npm badge][npm-badge-png]][package-url] + +Traverse and transform objects by visiting every node on a recursive walk. + +# examples + +## transform negative numbers in-place + +negative.js + +````javascript +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); +```` + +Output: + + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ] + +## collect leaf nodes + +leaves.js + +````javascript +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); +```` + +Output: + + [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +## scrub circular references + +scrub.js: + +````javascript +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); +```` + +output: + + { a: 1, b: 2, c: [ 3, 4 ] } + +# methods + +Each method that takes an `fn` uses the context documented below in the context +section. + +## .map(fn) + +Execute `fn` for each node in the object and return a new object with the +results of the walk. To update nodes in the result use `this.update(value)`. + +## .forEach(fn) + +Execute `fn` for each node in the object but unlike `.map()`, when +`this.update()` is called it updates the object in-place. + +## .reduce(fn, acc) + +For each node in the object, perform a +[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function)) +with the return value of `fn(acc, node)`. + +If `acc` isn't specified, `acc` is set to the root object for the first step +and the root element is skipped. + +## .paths() + +Return an `Array` of every possible non-cyclic path in the object. +Paths are `Array`s of string keys. + +## .nodes() + +Return an `Array` of every node in the object. + +## .clone() + +Create a deep clone of the object. + +## .get(path) + +Get the element at the array `path`. + +## .set(path, value) + +Set the element at the array `path` to `value`. + +## .has(path) + +Return whether the element at the array `path` exists. + +# context + +Each method that takes a callback has a context (its `this` object) with these +attributes: + +## this.node + +The present node on the recursive walk + +## this.path + +An array of string keys from the root to the present node + +## this.parent + +The context of the node's parent. +This is `undefined` for the root node. + +## this.key + +The name of the key of the present node in its parent. +This is `undefined` for the root node. + +## this.isRoot, this.notRoot + +Whether the present node is the root node + +## this.isLeaf, this.notLeaf + +Whether or not the present node is a leaf node (has no children) + +## this.level + +Depth of the node within the traversal + +## this.circular + +If the node equals one of its parents, the `circular` attribute is set to the +context of that parent and the traversal progresses no deeper. + +## this.update(value, stopHere=false) + +Set a new value for the present node. + +All the elements in `value` will be recursively traversed unless `stopHere` is +true. + +## this.remove(stopHere=false) + +Remove the current element from the output. If the node is in an Array it will +be spliced off. Otherwise it will be deleted from its parent. + +## this.delete(stopHere=false) + +Delete the current element from its parent in the output. Calls `delete` even on +Arrays. + +## this.before(fn) + +Call this function before any of the children are traversed. + +You can assign into `this.keys` here to traverse in a custom order. + +## this.after(fn) + +Call this function after any of the children are traversed. + +## this.pre(fn) + +Call this function before each of the children are traversed. + +## this.post(fn) + +Call this function after each of the children are traversed. + + +# install + +Using [npm](http://npmjs.org) do: + + $ npm install traverse + +# license + +MIT + +[package-url]: https://npmjs.org/package/traverse +[npm-version-svg]: https://versionbadg.es/ljharb/traverse.svg +[deps-svg]: https://david-dm.org/ljharb/traverse.svg +[deps-url]: https://david-dm.org/ljharb/traverse +[dev-deps-svg]: https://david-dm.org/ljharb/traverse/dev-status.svg +[dev-deps-url]: https://david-dm.org/ljharb/traverse#info=devDependencies +[npm-badge-png]: https://nodei.co/npm/traverse.png?downloads=true&stars=true +[license-image]: https://img.shields.io/npm/l/traverse.svg +[license-url]: LICENSE +[downloads-image]: https://img.shields.io/npm/dm/traverse.svg +[downloads-url]: https://npm-stat.com/charts.html?package=traverse +[codecov-image]: https://codecov.io/gh/ljharb/traverse/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/ljharb/traverse/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/traverse +[actions-url]: https://github.com/ljharb/traverse/actions diff --git a/node_modules/traverse/examples/json.js b/node_modules/traverse/examples/json.js new file mode 100755 index 0000000..af71883 --- /dev/null +++ b/node_modules/traverse/examples/json.js @@ -0,0 +1,18 @@ +'use strict'; + +var traverse = require('traverse'); + +var id = 54; +var callbacks = {}; +var obj = { moo: function () {}, foo: [2, 3, 4, function () {}] }; + +var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id: id, f: x, path: this.path }; + this.update('[Function]'); + id++; + } +}); + +console.dir(scrubbed); +console.dir(callbacks); diff --git a/node_modules/traverse/examples/leaves.js b/node_modules/traverse/examples/leaves.js new file mode 100755 index 0000000..0bbd67a --- /dev/null +++ b/node_modules/traverse/examples/leaves.js @@ -0,0 +1,17 @@ +'use strict'; + +var traverse = require('traverse'); + +var obj = { + a: [1, 2, 3], + b: 4, + c: [5, 6], + d: { e: [7, 8], f: 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) { acc.push(x); } + return acc; +}, []); + +console.dir(leaves); diff --git a/node_modules/traverse/examples/negative.js b/node_modules/traverse/examples/negative.js new file mode 100755 index 0000000..9224fac --- /dev/null +++ b/node_modules/traverse/examples/negative.js @@ -0,0 +1,10 @@ +'use strict'; + +var traverse = require('traverse'); +var obj = [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; + +traverse(obj).forEach(function (x) { + if (x < 0) { this.update(x + 128); } +}); + +console.dir(obj); diff --git a/node_modules/traverse/examples/scrub.js b/node_modules/traverse/examples/scrub.js new file mode 100755 index 0000000..7a8d1e2 --- /dev/null +++ b/node_modules/traverse/examples/scrub.js @@ -0,0 +1,12 @@ +'use strict'; + +// scrub out circular references +var traverse = require('traverse'); + +var obj = { a: 1, b: 2, c: [3, 4] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function () { + if (this.circular) { this.remove(); } +}); +console.dir(scrubbed); diff --git a/node_modules/traverse/examples/stringify.js b/node_modules/traverse/examples/stringify.js new file mode 100755 index 0000000..2f6e14a --- /dev/null +++ b/node_modules/traverse/examples/stringify.js @@ -0,0 +1,37 @@ +#!/usr/bin/env node + +'use strict'; + +var traverse = require('traverse'); + +var obj = ['five', 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; + +var s = ''; +traverse(obj).forEach(function toS(node) { + if (Array.isArray(node)) { + this.before(function () { s += '['; }); + this.post(function (child) { + if (!child.isLast) { s += ','; } + }); + this.after(function () { s += ']'; }); + } else if (typeof node === 'object') { + this.before(function () { s += '{'; }); + this.pre(function (x, key) { + toS(key); + s += ':'; + }); + this.post(function (child) { + if (!child.isLast) { s += ','; } + }); + this.after(function () { s += '}'; }); + } else if (typeof node === 'string') { + s += '"' + node.toString().replace(/"/g, '\\"') + '"'; + } else if (typeof node === 'function') { + s += 'null'; + } else { + s += node.toString(); + } +}); + +console.log('JSON.stringify: ' + JSON.stringify(obj)); +console.log('this stringify: ' + s); diff --git a/node_modules/traverse/index.js b/node_modules/traverse/index.js new file mode 100644 index 0000000..032d0c5 --- /dev/null +++ b/node_modules/traverse/index.js @@ -0,0 +1,311 @@ +'use strict'; + +// TODO: use call-bind, is-date, is-regex, is-string, is-boolean-object, is-number-object +function toS(obj) { return Object.prototype.toString.call(obj); } +function isDate(obj) { return toS(obj) === '[object Date]'; } +function isRegExp(obj) { return toS(obj) === '[object RegExp]'; } +function isError(obj) { return toS(obj) === '[object Error]'; } +function isBoolean(obj) { return toS(obj) === '[object Boolean]'; } +function isNumber(obj) { return toS(obj) === '[object Number]'; } +function isString(obj) { return toS(obj) === '[object String]'; } + +// TODO: use isarray +var isArray = Array.isArray || function isArray(xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +// TODO: use for-each? +function forEach(xs, fn) { + if (xs.forEach) { return xs.forEach(fn); } + for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } + return void undefined; +} + +// TODO: use object-keys +var objectKeys = Object.keys || function keys(obj) { + var res = []; + for (var key in obj) { res.push(key); } // eslint-disable-line no-restricted-syntax + return res; +}; + +// TODO: use object.hasown +var hasOwnProperty = Object.prototype.hasOwnProperty || function (obj, key) { + return key in obj; +}; + +function copy(src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (isArray(src)) { + dst = []; + } else if (isDate(src)) { + dst = new Date(src.getTime ? src.getTime() : src); + } else if (isRegExp(src)) { + dst = new RegExp(src); + } else if (isError(src)) { + dst = { message: src.message }; + } else if (isBoolean(src) || isNumber(src) || isString(src)) { + dst = Object(src); + } else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } else if (src.constructor === Object) { + dst = {}; + } else { + var proto = (src.constructor && src.constructor.prototype) + || src.__proto__ + || {}; + var T = function T() {}; // eslint-disable-line func-style, func-name-matching + T.prototype = proto; + dst = new T(); + } + + forEach(objectKeys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + return src; +} + +function walk(root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker(node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node: node, + node_: node_, + path: [].concat(path), + parent: parents[parents.length - 1], + parents: parents, + key: path[path.length - 1], + isRoot: path.length === 0, + level: path.length, + circular: null, + update: function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) { keepGoing = false; } + }, + delete: function (stopHere) { + delete state.parent.node[state.key]; + if (stopHere) { keepGoing = false; } + }, + remove: function (stopHere) { + if (isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } else { + delete state.parent.node[state.key]; + } + if (stopHere) { keepGoing = false; } + }, + keys: null, + before: function (f) { modifiers.before = f; }, + after: function (f) { modifiers.after = f; }, + pre: function (f) { modifiers.pre = f; }, + post: function (f) { modifiers.post = f; }, + stop: function () { alive = false; }, + block: function () { keepGoing = false; }, + }; + + if (!alive) { return state; } + + function updateState() { + if (typeof state.node === 'object' && state.node !== null) { + if (!state.keys || state.node_ !== state.node) { + state.keys = objectKeys(state.node); + } + + state.isLeaf = state.keys.length === 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; // eslint-disable-line no-restricted-syntax + } + } + } else { + state.isLeaf = true; + state.keys = null; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + } + + updateState(); + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) { state.update(ret); } + + if (modifiers.before) { modifiers.before.call(state, state.node); } + + if (!keepGoing) { return state; } + + if ( + typeof state.node === 'object' + && state.node !== null + && !state.circular + ) { + parents.push(state); + + updateState(); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) { modifiers.pre.call(state, state.node[key], key); } + + var child = walker(state.node[key]); + if (immutable && hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i === state.keys.length - 1; + child.isFirst = i === 0; + + if (modifiers.post) { modifiers.post.call(state, child); } + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) { modifiers.after.call(state, state.node); } + + return state; + }(root)).node; +} + +function Traverse(obj) { + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i++) { + var key = ps[i]; + if (!node || !hasOwnProperty.call(node, key)) { + return void undefined; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.has = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i++) { + var key = ps[i]; + if (!node || !hasOwnProperty.call(node, key)) { + return false; + } + node = node[key]; + } + return true; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i++) { + var key = ps[i]; + if (!hasOwnProperty.call(node, key)) { node[key] = {}; } + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function () { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function () { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = []; + var nodes = []; + + return (function clone(src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(objectKeys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + + return src; + + }(this.value)); +}; + +function traverse(obj) { + return new Traverse(obj); +} + +// TODO: replace with object.assign? +forEach(objectKeys(Traverse.prototype), function (key) { + traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = new Traverse(obj); + return t[key].apply(t, args); + }; +}); + +module.exports = traverse; diff --git a/node_modules/traverse/package.json b/node_modules/traverse/package.json new file mode 100644 index 0000000..bba353b --- /dev/null +++ b/node_modules/traverse/package.json @@ -0,0 +1,93 @@ +{ + "name": "traverse", + "version": "0.6.7", + "description": "traverse and transform objects by visiting every node on a recursive walk", + "main": "index.js", + "directories": { + "example": "example", + "test": "test" + }, + "devDependencies": { + "@ljharb/eslint-config": "^21.0.0", + "aud": "^2.0.1", + "auto-changelog": "^2.4.0", + "eslint": "=8.8.0", + "in-publish": "^2.0.1", + "npmignore": "^0.3.0", + "safe-publish-latest": "^2.0.0", + "tape": "^5.6.1" + }, + "scripts": { + "prepack": "npmignore --auto --commentLines=autogenerated", + "prepublishOnly": "safe-publish-latest", + "prepublish": "not-in-publish || npm run prepublishOnly", + "lint": "eslint --ext=js,mjs .", + "pretest": "npm run lint", + "tests-only": "tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "aud --production", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" + }, + "testling": { + "files": "test/*.js", + "browsers": { + "iexplore": [ + "6.0", + "7.0", + "8.0", + "9.0" + ], + "chrome": [ + "10.0", + "20.0" + ], + "firefox": [ + "10.0", + "15.0" + ], + "safari": [ + "5.1" + ], + "opera": [ + "12.0" + ] + } + }, + "repository": { + "type": "git", + "url": "git://github.com/ljharb/js-traverse.git" + }, + "homepage": "https://github.com/ljharb/js-traverse", + "keywords": [ + "traverse", + "walk", + "recursive", + "map", + "forEach", + "deep", + "clone" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "license": "MIT", + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + }, + "publishConfig": { + "ignore": [ + ".github/workflows" + ] + } +} diff --git a/node_modules/traverse/test/circular.js b/node_modules/traverse/test/circular.js new file mode 100644 index 0000000..89743cd --- /dev/null +++ b/node_modules/traverse/test/circular.js @@ -0,0 +1,118 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); +var util = require('util'); + +test('circular', function (t) { + t.plan(1); + + var obj = { x: 3 }; + obj.y = obj; + traverse(obj).forEach(function () { + if (this.path.join('') === 'y') { + t.equal( + util.inspect(this.circular.node), + util.inspect(obj) + ); + } + }); +}); + +test('deepCirc', function (t) { + t.plan(2); + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + + traverse(obj).forEach(function () { + if (this.circular) { + t.deepEqual(this.circular.path, []); + t.deepEqual(this.path, ['y', '2']); + } + }); +}); + +test('doubleCirc', function (t) { + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var circs = []; + traverse(obj).forEach(function (x) { + if (this.circular) { + circs.push({ circ: this.circular, self: this, node: x }); + } + }); + + t.deepEqual(circs[0].self.path, ['x', '3', '2']); + t.deepEqual(circs[0].circ.path, []); + + t.deepEqual(circs[1].self.path, ['y', '2']); + t.deepEqual(circs[1].circ.path, []); + + t.deepEqual(circs.length, 2); + t.end(); +}); + +test('circDubForEach', function (t) { + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + traverse(obj).forEach(function () { + if (this.circular) { this.update('...'); } + }); + + t.same(obj, { x: [1, 2, 3, [4, 5, '...']], y: [4, 5, '...'] }); + t.end(); +}); + +test('circDubMap', function (t) { + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var c = traverse(obj).map(function () { + if (this.circular) { + this.update('...'); + } + }); + + t.same(c, { x: [1, 2, 3, [4, 5, '...']], y: [4, 5, '...'] }); + t.end(); +}); + +test('circClone', function (t) { + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var clone = traverse.clone(obj); + t.ok(obj !== clone); + + t.ok(clone.y[2] === clone); + t.ok(clone.y[2] !== obj); + t.ok(clone.x[3][2] === clone); + t.ok(clone.x[3][2] !== obj); + t.same(clone.x.slice(0, 3), [1, 2, 3]); + t.same(clone.y.slice(0, 2), [4, 5]); + t.end(); +}); + +test('circMapScrub', function (t) { + var obj = { a: 1, b: 2 }; + obj.c = obj; + + var scrubbed = traverse(obj).map(function () { + if (this.circular) { this.remove(); } + }); + t.same( + Object.keys(scrubbed).sort(), + ['a', 'b'] + ); + t.ok(deepEqual(scrubbed, { a: 1, b: 2 })); + + t.equal(obj.c, obj); + t.end(); +}); diff --git a/node_modules/traverse/test/date.js b/node_modules/traverse/test/date.js new file mode 100644 index 0000000..2df5a5f --- /dev/null +++ b/node_modules/traverse/test/date.js @@ -0,0 +1,39 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('dateEach', function (t) { + var obj = { x: new Date(), y: 10, z: 5 }; + + var counts = {}; + + traverse(obj).forEach(function (node) { + var type = (node instanceof Date && 'Date') || typeof node; + counts[type] = (counts[type] || 0) + 1; + }); + + t.same(counts, { + object: 1, + Date: 1, + number: 2, + }); + t.end(); +}); + +test('dateMap', function (t) { + var obj = { x: new Date(), y: 10, z: 5 }; + + var res = traverse(obj).map(function (node) { + if (typeof node === 'number') { this.update(node + 100); } + }); + + t.ok(obj.x !== res.x); + t.same(res, { + x: obj.x, + y: 110, + z: 105, + }); + t.end(); +}); + diff --git a/node_modules/traverse/test/equal.js b/node_modules/traverse/test/equal.js new file mode 100644 index 0000000..3413143 --- /dev/null +++ b/node_modules/traverse/test/equal.js @@ -0,0 +1,238 @@ +'use strict'; + +var test = require('tape'); +var deepEqual = require('./lib/deep_equal'); + +test('deepDates', function (t) { + t.plan(2); + + t.ok( + deepEqual( + { d: new Date(), x: [1, 2, 3] }, + { d: new Date(), x: [1, 2, 3] } + ), + 'dates should be equal' + ); + + var d0 = new Date(); + setTimeout(function () { + t.ok( + !deepEqual( + { d: d0, x: [1, 2, 3] }, + { d: new Date(), x: [1, 2, 3] } + ), + 'microseconds should count in date equality' + ); + }, 5); +}); + +test('deepCircular', function (t) { + var a = [1]; + a.push(a); // a = [ 1, *a ] + + var b = [1]; + b.push(a); // b = [ 1, [ 1, *a ] ] + + t.ok( + !deepEqual(a, b), + 'circular ref mount points count towards equality' + ); + + var c = [1]; + c.push(c); // c = [ 1, *c ] + t.ok( + deepEqual(a, c), + 'circular refs are structurally the same here' + ); + + var d = [1]; + d.push(a); // c = [ 1, [ 1, *d ] ] + t.ok( + deepEqual(b, d), + 'non-root circular ref structural comparison' + ); + + t.end(); +}); + +test('deepInstances', function (t) { + t.ok( + !deepEqual([Object(false)], [false]), + 'boolean instances are not real booleans' + ); + + t.ok( + !deepEqual([Object('x')], ['x']), + 'string instances are not real strings' + ); + + t.ok( + !deepEqual([Object(4)], [4]), + 'number instances are not real numbers' + ); + + t.ok( + deepEqual([new RegExp('x')], [/x/]), + 'regexp instances are real regexps' + ); + + t.ok( + !deepEqual([new RegExp(/./)], [/../]), + 'these regexps aren\'t the same' + ); + + t.ok( + !deepEqual( + [function (x) { return x * 2; }], + [function (x) { return x * 2; }] + ), + 'functions with the same .toString() aren\'t necessarily the same' + ); + + function f(x) { return x * 2; } + t.ok( + deepEqual([f], [f]), + 'these functions are actually equal' + ); + + t.end(); +}); + +test('deepEqual', function (t) { + t.ok( + !deepEqual([1, 2, 3], { 0: 1, 1: 2, 2: 3 }), + 'arrays are not objects' + ); + t.end(); +}); + +test('falsy', function (t) { + t.ok( + !deepEqual([undefined], [null]), + 'null is not undefined!' + ); + + t.ok( + !deepEqual([null], [undefined]), + 'undefined is not null!' + ); + + t.ok( + !deepEqual( + { a: 1, b: 2, c: [3, undefined, 5] }, + { a: 1, b: 2, c: [3, null, 5] } + ), + 'undefined is not null, however deeply!' + ); + + t.ok( + !deepEqual( + { a: 1, b: 2, c: [3, undefined, 5] }, + { a: 1, b: 2, c: [3, null, 5] } + ), + 'null is not undefined, however deeply!' + ); + + t.ok( + !deepEqual( + { a: 1, b: 2, c: [3, undefined, 5] }, + { a: 1, b: 2, c: [3, null, 5] } + ), + 'null is not undefined, however deeply!' + ); + + t.end(); +}); + +test('deletedArrayEqual', function (t) { + var xs = [1, 2, 3, 4]; + delete xs[2]; + + var ys = Object.create(Array.prototype); + ys[0] = 1; + ys[1] = 2; + ys[3] = 4; + + t.ok( + deepEqual(xs, ys), + 'arrays with deleted elements are only equal to arrays with similarly deleted elements' + ); + + t.ok( + !deepEqual(xs, [1, 2, undefined, 4]), + 'deleted array elements cannot be undefined' + ); + + t.ok( + !deepEqual(xs, [1, 2, null, 4]), + 'deleted array elements cannot be null' + ); + + t.end(); +}); + +test('deletedObjectEqual', function (t) { + var obj = { a: 1, b: 2, c: 3 }; + delete obj.c; + + t.ok( + deepEqual(obj, { a: 1, b: 2 }), + 'deleted object elements should not show up' + ); + + t.ok( + !deepEqual(obj, { a: 1, b: 2, c: undefined }), + 'deleted object elements are not undefined' + ); + + t.ok( + !deepEqual(obj, { a: 1, b: 2, c: null }), + 'deleted object elements are not null' + ); + + t.end(); +}); + +test('emptyKeyEqual', function (t) { + t.ok(!deepEqual({ a: 1 }, { a: 1, '': 55 })); + + t.end(); +}); + +test('deepArguments', function (t) { + t.ok( + !deepEqual( + [4, 5, 6], + (function () { return arguments; }(4, 5, 6)) + ), + 'arguments are not arrays' + ); + + t.ok( + deepEqual( + (function () { return arguments; }(4, 5, 6)), + (function () { return arguments; }(4, 5, 6)) + ), + 'arguments should equal' + ); + + t.end(); +}); + +test('deepUn', function (t) { + t.ok(!deepEqual({ a: 1, b: 2 }, undefined)); + t.ok(!deepEqual({ a: 1, b: 2 }, {})); + t.ok(!deepEqual(undefined, { a: 1, b: 2 })); + t.ok(!deepEqual({}, { a: 1, b: 2 })); + t.ok(deepEqual(undefined, undefined)); + t.ok(deepEqual(null, null)); + t.ok(!deepEqual(undefined, null)); + + t.end(); +}); + +test('deepLevels', function (t) { + var xs = [1, 2, [3, 4, [5, 6]]]; + t.ok(!deepEqual(xs, [])); + t.end(); +}); diff --git a/node_modules/traverse/test/error.js b/node_modules/traverse/test/error.js new file mode 100644 index 0000000..8c4aca1 --- /dev/null +++ b/node_modules/traverse/test/error.js @@ -0,0 +1,13 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('traverse an Error', function (t) { + var obj = new Error('test'); + var results = traverse(obj).map(function () {}); + t.same(results, { message: 'test' }); + + t.end(); +}); + diff --git a/node_modules/traverse/test/has.js b/node_modules/traverse/test/has.js new file mode 100644 index 0000000..e29fb51 --- /dev/null +++ b/node_modules/traverse/test/has.js @@ -0,0 +1,17 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('has', function (t) { + var obj = { a: 2, b: [4, 5, { c: 6 }] }; + + t.equal(traverse(obj).has(['b', 2, 'c']), true); + t.equal(traverse(obj).has(['b', 2, 'c', 0]), false); + t.equal(traverse(obj).has(['b', 2, 'd']), false); + t.equal(traverse(obj).has([]), true); + t.equal(traverse(obj).has(['a']), true); + t.equal(traverse(obj).has(['a', 2]), false); + + t.end(); +}); diff --git a/node_modules/traverse/test/instance.js b/node_modules/traverse/test/instance.js new file mode 100644 index 0000000..b181b26 --- /dev/null +++ b/node_modules/traverse/test/instance.js @@ -0,0 +1,17 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); +var EventEmitter = require('events').EventEmitter; + +test('check instanceof on node elems', function (t) { + var counts = { emitter: 0 }; + + traverse([new EventEmitter(), 3, 4, { ev: new EventEmitter() }]) + .forEach(function (node) { + if (node instanceof EventEmitter) { counts.emitter += 1; } + }); + t.equal(counts.emitter, 2); + + t.end(); +}); diff --git a/node_modules/traverse/test/interface.js b/node_modules/traverse/test/interface.js new file mode 100644 index 0000000..02735b9 --- /dev/null +++ b/node_modules/traverse/test/interface.js @@ -0,0 +1,46 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('interface map', function (t) { + var obj = { a: [5, 6, 7], b: { c: [8] } }; + + t.same( + traverse.paths(obj) + .sort() + .map(function (path) { return path.join('/'); }) + .slice(1) + .join(' ') + , + 'a a/0 a/1 a/2 b b/c b/c/0' + ); + + t.same( + traverse.nodes(obj), + [ + { a: [5, 6, 7], b: { c: [8] } }, + [5, 6, 7], 5, 6, 7, + { c: [8] }, [8], 8, + ] + ); + + t.same( + traverse.map(obj, function (node) { + if (typeof node === 'number') { + return node + 1000; + } + if (Array.isArray(node)) { + return node.join(' '); + } + return void undefined; + }), + { a: '5 6 7', b: { c: '8' } } + ); + + var nodes = 0; + traverse.forEach(obj, function () { nodes += 1; }); + t.equal(nodes, 8); + + t.end(); +}); diff --git a/node_modules/traverse/test/json.js b/node_modules/traverse/test/json.js new file mode 100644 index 0000000..244a444 --- /dev/null +++ b/node_modules/traverse/test/json.js @@ -0,0 +1,55 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('json test', function (t) { + var id = 54; + var callbacks = {}; + var obj = { moo: function () {}, foo: [2, 3, 4, function () {}] }; + + var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id: id, f: x, path: this.path }; + this.update('[Function]'); + id += 1; + } + }); + + t.equal( + scrubbed.moo, + '[Function]', + 'obj.moo replaced with "[Function]"' + ); + + t.equal( + scrubbed.foo[3], + '[Function]', + 'obj.foo[3] replaced with "[Function]"' + ); + + t.same(scrubbed, { + moo: '[Function]', + foo: [2, 3, 4, '[Function]'], + }, 'Full JSON string matches'); + + t.same( + typeof obj.moo, + 'function', + 'Original obj.moo still a function' + ); + + t.same( + typeof obj.foo[3], + 'function', + 'Original obj.foo[3] still a function' + ); + + t.same(callbacks, { + 54: { id: 54, f: obj.moo, path: ['moo'] }, + 55: { id: 55, f: obj.foo[3], path: ['foo', '3'] }, + }, 'Check the generated callbacks list'); + + t.end(); +}); + diff --git a/node_modules/traverse/test/keys.js b/node_modules/traverse/test/keys.js new file mode 100644 index 0000000..6544eb9 --- /dev/null +++ b/node_modules/traverse/test/keys.js @@ -0,0 +1,33 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('sort test', function (t) { + var acc = []; + traverse({ + a: 30, + b: 22, + id: 9, + }).forEach(function (node) { + if (!Array.isArray(node) && typeof node === 'object') { + this.before(function (beforeNode) { + this.keys = Object.keys(beforeNode); + this.keys.sort(function (a, b) { + var aA = [a === 'id' ? 0 : 1, a]; + var bA = [b === 'id' ? 0 : 1, b]; + return aA < bA ? -1 : aA > bA ? 1 : 0; + }); + }); + } + if (this.isLeaf) { acc.push(node); } + }); + + t.equal( + acc.join(' '), + '9 30 22', + 'Traversal in a custom order' + ); + + t.end(); +}); diff --git a/node_modules/traverse/test/leaves.js b/node_modules/traverse/test/leaves.js new file mode 100644 index 0000000..d598499 --- /dev/null +++ b/node_modules/traverse/test/leaves.js @@ -0,0 +1,24 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('leaves test', function (t) { + var acc = []; + traverse({ + a: [1, 2, 3], + b: 4, + c: [5, 6], + d: { e: [7, 8], f: 9 }, + }).forEach(function (x) { + if (this.isLeaf) { acc.push(x); } + }); + + t.equal( + acc.join(' '), + '1 2 3 4 5 6 7 8 9', + 'Traversal in the right(?) order' + ); + + t.end(); +}); diff --git a/node_modules/traverse/test/lib/deep_equal.js b/node_modules/traverse/test/lib/deep_equal.js new file mode 100644 index 0000000..46d5af0 --- /dev/null +++ b/node_modules/traverse/test/lib/deep_equal.js @@ -0,0 +1,87 @@ +'use strict'; + +var traverse = require('../../'); + +function toS(o) { + return Object.prototype.toString.call(o); +} + +module.exports = function (a, b) { + if (arguments.length !== 2) { + throw new Error('deepEqual requires exactly two objects to compare against'); + } + + var equal = true; + function notEqual() { + equal = false; + // this.stop(); + return undefined; + } + + var node = b; + + traverse(a).forEach(function (y) { // eslint-disable-line consistent-return + + // if (node === undefined || node === null) return notEqual(); + + if (!this.isRoot) { + /* + if (!Object.hasOwnProperty.call(node, this.key)) { + return notEqual(); + } + */ + if (typeof node !== 'object') { return notEqual(); } + node = node[this.key]; + } + + var x = node; + + this.post(function () { + node = x; + }); + + if (this.circular) { + if (traverse(b).get(this.circular.path) !== x) { notEqual(); } + } else if (typeof x !== typeof y) { + notEqual(); + } else if (x === null || y === null || x === undefined || y === undefined) { + if (x !== y) { notEqual(); } + } else if (x.__proto__ !== y.__proto__) { + notEqual(); + } else if (x === y) { + // nop + } else if (typeof x === 'function') { + if (x instanceof RegExp) { + // both regexps on account of the __proto__ check + if (String(x) !== String(y)) { notEqual(); } + } else if (x !== y) { notEqual(); } + } else if (typeof x === 'object') { + if (toS(y) === '[object Arguments]' + || toS(x) === '[object Arguments]') { + if (toS(x) !== toS(y)) { + notEqual(); + } + } else if (toS(y) === '[object RegExp]' + || toS(x) === '[object RegExp]') { + if (!x || !y || x.toString() !== y.toString()) { notEqual(); } + } else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) + || x.getTime() !== y.getTime()) { + notEqual(); + } + } else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) { return notEqual(); } + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + + return equal; +}; diff --git a/node_modules/traverse/test/mutability.js b/node_modules/traverse/test/mutability.js new file mode 100644 index 0000000..dc5d6f4 --- /dev/null +++ b/node_modules/traverse/test/mutability.js @@ -0,0 +1,276 @@ +'use strict'; + +var test = require('tape'); +var assert = require('assert'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +test('mutate', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, res); + t.same(obj, { a: 1, b: 20, c: [3, 40] }); + t.end(); +}); + +test('mutateT', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse.forEach(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, res); + t.same(obj, { a: 1, b: 20, c: [3, 40] }); + t.end(); +}); + +test('map', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).map(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, { a: 1, b: 20, c: [3, 40] }); + t.end(); +}); + +test('mapT', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse.map(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, { a: 1, b: 20, c: [3, 40] }); + t.end(); +}); + +test('clone', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).clone(); + t.same(obj, res); + t.ok(obj !== res); + obj.a += 1; + t.same(res.a, 1); + obj.c.push(5); + t.same(res.c, [3, 4]); + t.end(); +}); + +test('cloneT', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse.clone(obj); + t.same(obj, res); + t.ok(obj !== res); + obj.a += 1; + t.same(res.a, 1); + obj.c.push(5); + t.same(res.c, [3, 4]); + t.end(); +}); + +test('reduce', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) { acc.push(x); } + return acc; + }, []); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, [1, 2, 3, 4]); + t.end(); +}); + +test('reduceInit', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).reduce(function (acc) { + if (this.isRoot) { assert.fail('got root'); } + return acc; + }); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, obj); + t.end(); +}); + +test('remove', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 === 0) { this.remove(); } + }); + + t.same(obj, { a: 1, c: [3] }); + t.end(); +}); + +test('removeNoStop', function (t) { + var obj = { a: 1, b: 2, c: { d: 3, e: 4 }, f: 5 }; + + var keys = []; + traverse(obj).forEach(function () { + keys.push(this.key); + if (this.key === 'c') { this.remove(); } + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f']); + t.end(); +}); + +test('removeStop', function (t) { + var obj = { a: 1, b: 2, c: { d: 3, e: 4 }, f: 5 }; + + var keys = []; + traverse(obj).forEach(function () { + keys.push(this.key); + if (this.key === 'c') { this.remove(true); } + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'f']); + t.end(); +}); + +test('removeMap', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 === 0) { this.remove(); } + }); + + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, { a: 1, c: [3] }); + t.end(); +}); + +test('delete', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 === 0) { this.delete(); } + }); + + t.ok(!deepEqual(obj, { a: 1, c: [3, undefined] })); + + t.ok(deepEqual(obj, { a: 1, c: [3] })); + + t.ok(!deepEqual(obj, { a: 1, c: [3, null] })); + t.end(); +}); + +test('deleteNoStop', function (t) { + var obj = { a: 1, b: 2, c: { d: 3, e: 4 } }; + + var keys = []; + traverse(obj).forEach(function () { + keys.push(this.key); + if (this.key === 'c') { this.delete(); } + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e']); + t.end(); +}); + +test('deleteStop', function (t) { + var obj = { a: 1, b: 2, c: { d: 3, e: 4 } }; + + var keys = []; + traverse(obj).forEach(function () { + keys.push(this.key); + if (this.key === 'c') { this.delete(true); } + }); + + t.same(keys, [undefined, 'a', 'b', 'c']); + t.end(); +}); + +test('deleteRedux', function (t) { + var obj = { a: 1, b: 2, c: [3, 4, 5] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 === 0) { this.delete(); } + }); + + t.ok(!deepEqual(obj, { a: 1, c: [3, undefined, 5] })); + + t.ok(deepEqual(obj, { a: 1, c: [3,, 5] })); + + t.ok(!deepEqual(obj, { a: 1, c: [3, null, 5] })); + + t.ok(!deepEqual(obj, { a: 1, c: [3, 5] })); + + t.end(); +}); + +test('deleteMap', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 === 0) { this.delete(); } + }); + + t.ok(deepEqual( + obj, + { a: 1, b: 2, c: [3, 4] } + )); + + var xs = [3, 4]; + delete xs[1]; + + t.ok(deepEqual(res, { a: 1, c: xs })); + + t.ok(deepEqual(res, { a: 1, c: [3,,] })); // eslint-disable-line comma-spacing + + t.ok(deepEqual(res, { a: 1, c: [3] })); + + t.end(); +}); + +test('deleteMapRedux', function (t) { + var obj = { a: 1, b: 2, c: [3, 4, 5] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 === 0) { this.delete(); } + }); + + t.ok(deepEqual( + obj, + { a: 1, b: 2, c: [3, 4, 5] } + )); + + var xs = [3, 4, 5]; + delete xs[1]; + + t.ok(deepEqual(res, { a: 1, c: xs })); + + t.ok(!deepEqual(res, { a: 1, c: [3, 5] })); + + t.ok(deepEqual(res, { a: 1, c: [3,, 5] })); + + t.end(); +}); + +test('objectToString', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'object' && !this.isRoot) { + this.update(JSON.stringify(x)); + } + }); + t.same(obj, res); + t.same(obj, { a: 1, b: 2, c: '[3,4]' }); + t.end(); +}); + +test('stringToObject', function (t) { + var obj = { a: 1, b: 2, c: '[3,4]' }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'string') { + this.update(JSON.parse(x)); + } else if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.deepEqual(obj, res); + t.deepEqual(obj, { a: 1, b: 20, c: [3, 40] }); + t.end(); +}); diff --git a/node_modules/traverse/test/negative.js b/node_modules/traverse/test/negative.js new file mode 100644 index 0000000..b3806c4 --- /dev/null +++ b/node_modules/traverse/test/negative.js @@ -0,0 +1,25 @@ +'use strict'; + +var traverse = require('../'); +var test = require('tape'); + +test('negative update test', function (t) { + var obj = [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; + var fixed = traverse.map(obj, function (x) { + if (x < 0) { this.update(x + 128); } + }); + + t.same( + fixed, + [5, 6, 125, [7, 8, 126, 1], { f: 10, g: 115 }], + 'Negative values += 128' + ); + + t.same( + obj, + [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }], + 'Original references not modified' + ); + + t.end(); +}); diff --git a/node_modules/traverse/test/obj.js b/node_modules/traverse/test/obj.js new file mode 100644 index 0000000..fa3daea --- /dev/null +++ b/node_modules/traverse/test/obj.js @@ -0,0 +1,13 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('traverse an object with nested functions', function (t) { + t.plan(1); + + function Cons(x) { + t.equal(x, 10); + } + traverse(new Cons(10)); +}); diff --git a/node_modules/traverse/test/siblings.js b/node_modules/traverse/test/siblings.js new file mode 100644 index 0000000..049632e --- /dev/null +++ b/node_modules/traverse/test/siblings.js @@ -0,0 +1,39 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('siblings', function (t) { + var obj = { a: 1, b: 2, c: [4, 5, 6] }; + + var res = traverse(obj).reduce(function (acc) { + /* eslint no-param-reassign: 0 */ + var p = '/' + this.path.join('/'); + if (this.parent) { + acc[p] = { + siblings: this.parent.keys, + key: this.key, + index: this.parent.keys.indexOf(this.key), + }; + } else { + acc[p] = { + siblings: [], + key: this.key, + index: -1, + }; + } + return acc; + }, {}); + + t.same(res, { + '/': { siblings: [], key: undefined, index: -1 }, + '/a': { siblings: ['a', 'b', 'c'], key: 'a', index: 0 }, + '/b': { siblings: ['a', 'b', 'c'], key: 'b', index: 1 }, + '/c': { siblings: ['a', 'b', 'c'], key: 'c', index: 2 }, + '/c/0': { siblings: ['0', '1', '2'], key: '0', index: 0 }, + '/c/1': { siblings: ['0', '1', '2'], key: '1', index: 1 }, + '/c/2': { siblings: ['0', '1', '2'], key: '2', index: 2 }, + }); + + t.end(); +}); diff --git a/node_modules/traverse/test/stop.js b/node_modules/traverse/test/stop.js new file mode 100644 index 0000000..86fc128 --- /dev/null +++ b/node_modules/traverse/test/stop.js @@ -0,0 +1,46 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('stop', function (t) { + var visits = 0; + traverse('abcdefghij'.split('')).forEach(function (node) { + if (typeof node === 'string') { + visits += 1; + if (node === 'e') { this.stop(); } + } + }); + + t.equal(visits, 5); + t.end(); +}); + +test('stopMap', function (t) { + var s = traverse('abcdefghij'.split('')).map(function (node) { + if (typeof node === 'string') { + if (node === 'e') { this.stop(); } + return node.toUpperCase(); + } + return void undefined; + }).join(''); + + t.equal(s, 'ABCDEfghij'); + t.end(); +}); + +test('stopReduce', function (t) { + var obj = { + a: [4, 5], + b: [6, [7, 8, 9]], + }; + var xs = traverse(obj).reduce(function (acc, node) { + if (this.isLeaf) { + if (node === 7) { this.stop(); } else { acc.push(node); } + } + return acc; + }, []); + + t.same(xs, [4, 5, 6]); + t.end(); +}); diff --git a/node_modules/traverse/test/stringify.js b/node_modules/traverse/test/stringify.js new file mode 100644 index 0000000..e7bf65d --- /dev/null +++ b/node_modules/traverse/test/stringify.js @@ -0,0 +1,35 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('stringify', function (t) { + var obj = [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; + + var s = ''; + traverse(obj).forEach(function (node) { + if (Array.isArray(node)) { + this.before(function () { s += '['; }); + this.post(function (child) { + if (!child.isLast) { s += ','; } + }); + this.after(function () { s += ']'; }); + } else if (typeof node === 'object') { + this.before(function () { s += '{'; }); + this.pre(function (x, key) { + s += '"' + key + '":'; + }); + this.post(function (child) { + if (!child.isLast) { s += ','; } + }); + this.after(function () { s += '}'; }); + } else if (typeof node === 'function') { + s += 'null'; + } else { + s += node.toString(); + } + }); + + t.equal(s, JSON.stringify(obj)); + t.end(); +}); diff --git a/node_modules/traverse/test/subexpr.js b/node_modules/traverse/test/subexpr.js new file mode 100644 index 0000000..6aeba05 --- /dev/null +++ b/node_modules/traverse/test/subexpr.js @@ -0,0 +1,41 @@ +'use strict'; + +var traverse = require('../'); +var test = require('tape'); + +test('subexpr', function (t) { + var obj = ['a', 4, 'b', 5, 'c', 6]; + var r = traverse(obj).map(function (x) { + if (typeof x === 'number') { + this.update([x - 0.1, x, x + 0.1], true); + } + }); + + t.same(obj, ['a', 4, 'b', 5, 'c', 6]); + t.same(r, [ + 'a', [3.9, 4, 4.1], + 'b', [4.9, 5, 5.1], + 'c', [5.9, 6, 6.1], + ]); + t.end(); +}); + +test('block', function (t) { + var obj = [[1], [2], [3]]; + var r = traverse(obj).map(function (x) { + if (Array.isArray(x) && !this.isRoot) { + if (x[0] === 5) { + this.block(); + } else { + this.update([[x[0] + 1]]); + } + } + }); + + t.same(r, [ + [[[[[5]]]]], + [[[[5]]]], + [[[5]]], + ]); + t.end(); +}); diff --git a/node_modules/traverse/test/super_deep.js b/node_modules/traverse/test/super_deep.js new file mode 100644 index 0000000..f7fd971 --- /dev/null +++ b/node_modules/traverse/test/super_deep.js @@ -0,0 +1,56 @@ +'use strict'; + +var test = require('tape'); +var deepEqual = require('./lib/deep_equal'); + +function make() { + var a = { self: 'a' }; + var b = { self: 'b' }; + var c = { self: 'c' }; + var d = { self: 'd' }; + var e = { self: 'e' }; + + a.a = a; + a.b = b; + a.c = c; + + b.a = a; + b.b = b; + b.c = c; + + c.a = a; + c.b = b; + c.c = c; + c.d = d; + + d.a = a; + d.b = b; + d.c = c; + d.d = d; + d.e = e; + + e.a = a; + e.b = b; + e.c = c; + e.d = d; + e.e = e; + + return a; +} + +test('super_deep', function (t) { + var a0 = make(); + var a1 = make(); + t.ok(deepEqual(a0, a1)); + + a0.c.d.moo = true; + t.ok(!deepEqual(a0, a1)); + + a1.c.d.moo = true; + t.ok(deepEqual(a0, a1)); + + // TODO: this one + // a0.c.a = a1; + // t.ok(!deepEqual(a0, a1)); + t.end(); +}); diff --git a/node_modules/uglify-js/.npmignore b/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..d97eaa0 --- /dev/null +++ b/node_modules/uglify-js/.npmignore @@ -0,0 +1,4 @@ +.DS_Store +.tmp*~ +*.local.* +.pinf-* \ No newline at end of file diff --git a/node_modules/uglify-js/README.html b/node_modules/uglify-js/README.html new file mode 100644 index 0000000..8f5223f --- /dev/null +++ b/node_modules/uglify-js/README.html @@ -0,0 +1,1026 @@ + + + + +UglifyJS -- a JavaScript parser/compressor/beautifier + + + + + + + + + + + + +
+ +

UglifyJS – a JavaScript parser/compressor/beautifier

+ + + + +
+

1 UglifyJS — a JavaScript parser/compressor/beautifier

+
+ + +

+This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on NodeJS, but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the exports.* lines from UglifyJS sources). +

+

+The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in parse-js.js and it's a +port to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke. +

+

+( See cl-uglify-js if you're looking for the Common Lisp version of +UglifyJS. ) +

+

+The second part of this package, implemented in process.js, inspects and +manipulates the AST generated by the parser to provide the following: +

+
    +
  • +ability to re-generate JavaScript code from the AST. Optionally +indented—you can use this if you want to “beautify” a program that has +been compressed, so that you can inspect the source. But you can also run +our code generator to print out an AST without any whitespace, so you +achieve compression as well. + +
  • +
  • +shorten variable names (usually to single characters). Our mangler will +analyze the code and generate proper variable names, depending on scope +and usage, and is smart enough to deal with globals defined elsewhere, or +with eval() calls or with{} statements. In short, if eval() or +with{} are used in some scope, then all variables in that scope and any +variables in the parent scopes will remain unmangled, and any references +to such variables remain unmangled as well. + +
  • +
  • +various small optimizations that may lead to faster code but certainly +lead to smaller code. Where possible, we do the following: + +
      +
    • +foo["bar"] ==> foo.bar + +
    • +
    • +remove block brackets {} + +
    • +
    • +join consecutive var declarations: +var a = 10; var b = 20; ==> var a=10,b=20; + +
    • +
    • +resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the +replacement if the result occupies less bytes; for example 1/3 would +translate to 0.333333333333, so in this case we don't replace it. + +
    • +
    • +consecutive statements in blocks are merged into a sequence; in many +cases, this leaves blocks with a single statement, so then we can remove +the block brackets. + +
    • +
    • +various optimizations for IF statements: + +
        +
      • +if (foo) bar(); else baz(); ==> foo?bar():baz(); +
      • +
      • +if (!foo) bar(); else baz(); ==> foo?baz():bar(); +
      • +
      • +if (foo) bar(); ==> foo&&bar(); +
      • +
      • +if (!foo) bar(); ==> foo||bar(); +
      • +
      • +if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); +
      • +
      • +if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + +
      • +
      +
    • +
    • +remove some unreachable code and warn about it (code that follows a +return, throw, break or continue statement, except +function/variable declarations). + +
    • +
    • +act a limited version of a pre-processor (c.f. the pre-processor of +C/C++) to allow you to safely replace selected global symbols with +specified values. When combined with the optimisations above this can +make UglifyJS operate slightly more like a compilation process, in +that when certain symbols are replaced by constant values, entire code +blocks may be optimised away as unreachable. +
    • +
    +
  • +
+ + + +
+ +
+

1.1 Unsafe transformations

+
+ + +

+The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +--unsafe flag. +

+ +
+ +
+

1.1.1 Calls involving the global Array constructor

+
+ + +

+The following transformations occur: +

+ + + +
new Array(1, 2, 3, 4)  => [1,2,3,4]
+Array(a, b, c)         => [a,b,c]
+new Array(5)           => Array(5)
+new Array(a)           => Array(a)
+
+ + + +

+These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. +

+

+UglifyJS does handle the case where Array is redefined locally, or even +globally but with a function or var declaration. Therefore, in the +following cases UglifyJS doesn't touch calls or instantiations of Array: +

+ + + +
// case 1.  globally declared variable
+  var Array;
+  new Array(1, 2, 3);
+  Array(a, b);
+
+  // or (can be declared later)
+  new Array(1, 2, 3);
+  var Array;
+
+  // or (can be a function)
+  new Array(1, 2, 3);
+  function Array() { ... }
+
+// case 2.  declared in a function
+  (function(){
+    a = new Array(1, 2, 3);
+    b = Array(5, 6);
+    var Array;
+  })();
+
+  // or
+  (function(Array){
+    return Array(5, 6, 7);
+  })();
+
+  // or
+  (function(){
+    return new Array(1, 2, 3, 4);
+    function Array() { ... }
+  })();
+
+  // etc.
+
+ + + +
+ +
+ +
+

1.1.2 obj.toString() ==> obj+“”

+
+ + +
+
+ +
+ +
+

1.2 Install (NPM)

+
+ + +

+UglifyJS is now available through NPM — npm install uglify-js should do +the job. +

+
+ +
+ +
+

1.3 Install latest code from GitHub

+
+ + + + + +
## clone the repository
+mkdir -p /where/you/wanna/put/it
+cd /where/you/wanna/put/it
+git clone git://github.com/mishoo/UglifyJS.git
+
+## make the module available to Node
+mkdir -p ~/.node_libraries/
+cd ~/.node_libraries/
+ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js
+
+## and if you want the CLI script too:
+mkdir -p ~/bin
+cd ~/bin
+ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs
+  # (then add ~/bin to your $PATH if it's not there already)
+
+ + + +
+ +
+ +
+

1.4 Usage

+
+ + +

+There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: +

+ + + +
uglifyjs [ options... ] [ filename ]
+
+ + + +

+filename should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. +

+

+Supported options: +

+
    +
  • +-b or --beautify — output indented code; when passed, additional +options control the beautifier: + +
      +
    • +-i N or --indent N — indentation level (number of spaces) + +
    • +
    • +-q or --quote-keys — quote keys in literal objects (by default, +only keys that cannot be identifier names will be quotes). + +
    • +
    +
  • +
  • +--ascii — pass this argument to encode non-ASCII characters as +\uXXXX sequences. By default UglifyJS won't bother to do it and will +output Unicode characters instead. (the output is always encoded in UTF8, +but if you pass this option you'll only get ASCII). + +
  • +
  • +-nm or --no-mangle — don't mangle variable names + +
  • +
  • +-ns or --no-squeeze — don't call ast_squeeze() (which does various +optimizations that result in smaller, less readable code). + +
  • +
  • +-mt or --mangle-toplevel — mangle names in the toplevel scope too +(by default we don't do this). + +
  • +
  • +--no-seqs — when ast_squeeze() is called (thus, unless you pass +--no-squeeze) it will reduce consecutive statements in blocks into a +sequence. For example, "a = 10; b = 20; foo();" will be written as +"a=10,b=20,foo();". In various occasions, this allows us to discard the +block brackets (since the block becomes a single statement). This is ON +by default because it seems safe and saves a few hundred bytes on some +libs that I tested it on, but pass --no-seqs to disable it. + +
  • +
  • +--no-dead-code — by default, UglifyJS will remove code that is +obviously unreachable (code that follows a return, throw, break or +continue statement and is not a function/variable declaration). Pass +this option to disable this optimization. + +
  • +
  • +-nc or --no-copyright — by default, uglifyjs will keep the initial +comment tokens in the generated code (assumed to be copyright information +etc.). If you pass this it will discard it. + +
  • +
  • +-o filename or --output filename — put the result in filename. If +this isn't given, the result goes to standard output (or see next one). + +
  • +
  • +--overwrite — if the code is read from a file (not from STDIN) and you +pass --overwrite then the output will be written in the same file. + +
  • +
  • +--ast — pass this if you want to get the Abstract Syntax Tree instead +of JavaScript as output. Useful for debugging or learning more about the +internals. + +
  • +
  • +-v or --verbose — output some notes on STDERR (for now just how long +each operation takes). + +
  • +
  • +-d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace +all instances of the specified symbol where used as an identifier +(except where symbol has properly declared by a var declaration or +use as function parameter or similar) with the specified value. This +argument may be specified multiple times to define multiple +symbols - if no value is specified the symbol will be replaced with +the value true, or you can specify a numeric value (such as +1024), a quoted string value (such as ="object"= or +='https://github.com'), or the name of another symbol or keyword (such as =null or document). +This allows you, for example, to assign meaningful names to key +constant values but discard the symbolic names in the uglified +version for brevity/efficiency, or when used wth care, allows +UglifyJS to operate as a form of conditional compilation +whereby defining appropriate values may, by dint of the constant +folding and dead code removal features above, remove entire +superfluous code blocks (e.g. completely remove instrumentation or +trace code for production use). +Where string values are being defined, the handling of quotes are +likely to be subject to the specifics of your command shell +environment, so you may need to experiment with quoting styles +depending on your platform, or you may find the option +--define-from-module more suitable for use. + +
  • +
  • +-define-from-module SOMEMODULE — will load the named module (as +per the NodeJS require() function) and iterate all the exported +properties of the module defining them as symbol names to be defined +(as if by the --define option) per the name of each property +(i.e. without the module name prefix) and given the value of the +property. This is a much easier way to handle and document groups of +symbols to be defined rather than a large number of --define +options. + +
  • +
  • +--unsafe — enable other additional optimizations that are known to be +unsafe in some contrived situations, but could still be generally useful. +For now only these: + +
      +
    • +foo.toString() ==> foo+"" +
    • +
    • +new Array(x,…) ==> [x,…] +
    • +
    • +new Array(x) ==> Array(x) + +
    • +
    +
  • +
  • +--max-line-len (default 32K characters) — add a newline after around +32K characters. I've seen both FF and Chrome croak when all the code was +on a single line of around 670K. Pass –max-line-len 0 to disable this +safety feature. + +
  • +
  • +--reserved-names — some libraries rely on certain names to be used, as +pointed out in issue #92 and #81, so this option allow you to exclude such +names from the mangler. For example, to keep names require and $super +intact you'd specify –reserved-names "require,$super". + +
  • +
  • +--inline-script – when you want to include the output literally in an +HTML <script> tag you can use this option to prevent </script from +showing up in the output. + +
  • +
  • +--lift-vars – when you pass this, UglifyJS will apply the following +transformations (see the notes in API, ast_lift_variables): + +
      +
    • +put all var declarations at the start of the scope +
    • +
    • +make sure a variable is declared only once +
    • +
    • +discard unused function arguments +
    • +
    • +discard unused inner (named) functions +
    • +
    • +finally, try to merge assignments into that one var declaration, if +possible. +
    • +
    +
  • +
+ + + +
+ +
+

1.4.1 API

+
+ + +

+To use the library from JavaScript, you'd do the following (example for +NodeJS): +

+ + + +
var jsp = require("uglify-js").parser;
+var pro = require("uglify-js").uglify;
+
+var orig_code = "... JS code here";
+var ast = jsp.parse(orig_code); // parse code and get the initial AST
+ast = pro.ast_mangle(ast); // get a new AST with mangled names
+ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
+var final_code = pro.gen_code(ast); // compressed code here
+
+ + + +

+The above performs the full compression that is possible right now. As you +can see, there are a sequence of steps which you can apply. For example if +you want compressed output but for some reason you don't want to mangle +variable names, you would simply skip the line that calls +pro.ast_mangle(ast). +

+

+Some of these functions take optional arguments. Here's a description: +

+
    +
  • +jsp.parse(code, strict_semicolons) – parses JS code and returns an AST. +strict_semicolons is optional and defaults to false. If you pass +true then the parser will throw an error when it expects a semicolon and +it doesn't find it. For most JS code you don't want that, but it's useful +if you want to strictly sanitize your code. + +
  • +
  • +pro.ast_lift_variables(ast) – merge and move var declarations to the +scop of the scope; discard unused function arguments or variables; discard +unused (named) inner functions. It also tries to merge assignments +following the var declaration into it. + +

    +If your code is very hand-optimized concerning var declarations, this +lifting variable declarations might actually increase size. For me it +helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also +note that (since it's not enabled by default) this operation isn't yet +heavily tested (please report if you find issues!). +

    +

    +Note that although it might increase the image size (on jQuery it gains +865 bytes, 243 after gzip) it's technically more correct: in certain +situations, dead code removal might drop variable declarations, which +would not happen if the variables are lifted in advance. +

    +

    +Here's an example of what it does: +

    +
  • +
+ + + + +
function f(a, b, c, d, e) {
+    var q;
+    var w;
+    w = 10;
+    q = 20;
+    for (var i = 1; i < 10; ++i) {
+        var boo = foo(a);
+    }
+    for (var i = 0; i < 1; ++i) {
+        var boo = bar(c);
+    }
+    function foo(){ ... }
+    function bar(){ ... }
+    function baz(){ ... }
+}
+
+// transforms into ==>
+
+function f(a, b, c) {
+    var i, boo, w = 10, q = 20;
+    for (i = 1; i < 10; ++i) {
+        boo = foo(a);
+    }
+    for (i = 0; i < 1; ++i) {
+        boo = bar(c);
+    }
+    function foo() { ... }
+    function bar() { ... }
+}
+
+ + + +
    +
  • +pro.ast_mangle(ast, options) – generates a new AST containing mangled +(compressed) variable and function names. It supports the following +options: + +
      +
    • +toplevel – mangle toplevel names (by default we don't touch them). +
    • +
    • +except – an array of names to exclude from compression. +
    • +
    • +defines – an object with properties named after symbols to +replace (see the --define option for the script) and the values +representing the AST replacement value. + +
    • +
    +
  • +
  • +pro.ast_squeeze(ast, options) – employs further optimizations designed +to reduce the size of the code that gen_code would generate from the +AST. Returns a new AST. options can be a hash; the supported options +are: + +
      +
    • +make_seqs (default true) which will cause consecutive statements in a +block to be merged using the "sequence" (comma) operator + +
    • +
    • +dead_code (default true) which will remove unreachable code. + +
    • +
    +
  • +
  • +pro.gen_code(ast, options) – generates JS code from the AST. By +default it's minified, but using the options argument you can get nicely +formatted output. options is, well, optional :-) and if you pass it it +must be an object and supports the following properties (below you can see +the default values): + +
      +
    • +beautify: false – pass true if you want indented output +
    • +
    • +indent_start: 0 (only applies when beautify is true) – initial +indentation in spaces +
    • +
    • +indent_level: 4 (only applies when beautify is true) -- +indentation level, in spaces (pass an even number) +
    • +
    • +quote_keys: false – if you pass true it will quote all keys in +literal objects +
    • +
    • +space_colon: false (only applies when beautify is true) – wether +to put a space before the colon in object literals +
    • +
    • +ascii_only: false – pass true if you want to encode non-ASCII +characters as \uXXXX. +
    • +
    • +inline_script: false – pass true to escape occurrences of +</script in strings +
    • +
    +
  • +
+ + +
+ +
+ +
+

1.4.2 Beautifier shortcoming – no more comments

+
+ + +

+The beautifier can be used as a general purpose indentation tool. It's +useful when you want to make a minified file readable. One limitation, +though, is that it discards all comments, so you don't really want to use it +to reformat your code, unless you don't have, or don't care about, comments. +

+

+In fact it's not the beautifier who discards comments — they are dumped at +the parsing stage, when we build the initial AST. Comments don't really +make sense in the AST, and while we could add nodes for them, it would be +inconvenient because we'd have to add special rules to ignore them at all +the processing stages. +

+
+ +
+ +
+

1.4.3 Use as a code pre-processor

+
+ + +

+The --define option can be used, particularly when combined with the +constant folding logic, as a form of pre-processor to enable or remove +particular constructions, such as might be used for instrumenting +development code, or to produce variations aimed at a specific +platform. +

+

+The code below illustrates the way this can be done, and how the +symbol replacement is performed. +

+ + + +
CLAUSE1: if (typeof DEVMODE === 'undefined') {
+    DEVMODE = true;
+}
+
+CLAUSE2: function init() {
+    if (DEVMODE) {
+        console.log("init() called");
+    }
+    ....
+    DEVMODE &amp;&amp; console.log("init() complete");
+}
+
+CLAUSE3: function reportDeviceStatus(device) {
+    var DEVMODE = device.mode, DEVNAME = device.name;
+    if (DEVMODE === 'open') {
+        ....
+    }
+}
+
+ + + +

+When the above code is normally executed, the undeclared global +variable DEVMODE will be assigned the value true (see CLAUSE1) +and so the init() function (CLAUSE2) will write messages to the +console log when executed, but in CLAUSE3 a locally declared +variable will mask access to the DEVMODE global symbol. +

+

+If the above code is processed by UglifyJS with an argument of +--define DEVMODE=false then UglifyJS will replace DEVMODE with the +boolean constant value false within CLAUSE1 and CLAUSE2, but it +will leave CLAUSE3 as it stands because there DEVMODE resolves to +a validly declared variable. +

+

+And more so, the constant-folding features of UglifyJS will recognise +that the if condition of CLAUSE1 is thus always false, and so will +remove the test and body of CLAUSE1 altogether (including the +otherwise slightly problematical statement false = true; which it +will have formed by replacing DEVMODE in the body). Similarly, +within CLAUSE2 both calls to console.log() will be removed +altogether. +

+

+In this way you can mimic, to a limited degree, the functionality of +the C/C++ pre-processor to enable or completely remove blocks +depending on how certain symbols are defined - perhaps using UglifyJS +to generate different versions of source aimed at different +environments +

+

+It is recommmended (but not made mandatory) that symbols designed for +this purpose are given names consisting of UPPER_CASE_LETTERS to +distinguish them from other (normal) symbols and avoid the sort of +clash that CLAUSE3 above illustrates. +

+
+
+ +
+ +
+

1.5 Compression – how good is it?

+
+ + +

+Here are updated statistics. (I also updated my Google Closure and YUI +installations). +

+

+We're still a lot better than YUI in terms of compression, though slightly +slower. We're still a lot faster than Closure, and compression after gzip +is comparable. +

+ + ++ + + + + + + + + + +
FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
+ + +
+ +
+ +
+

1.6 Bugs?

+
+ + +

+Unfortunately, for the time being there is no automated test suite. But I +ran the compressor manually on non-trivial code, and then I tested that the +generated code works as expected. A few hundred times. +

+

+DynarchLIB was started in times when there was no good JS minifier. +Therefore I was quite religious about trying to write short code manually, +and as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a += 10 : b = 20”, though the more readable version would clearly be to use +“if/else”. +

+

+Since the parser/compressor runs fine on DL and jQuery, I'm quite confident +that it's solid enough for production use. If you can identify any bugs, +I'd love to hear about them (use the Google Group or email me directly). +

+
+ +
+ +
+

1.7 Links

+
+ + + + + +
+ +
+ +
+

1.8 License

+
+ + +

+UglifyJS is released under the BSD license: +

+ + + +
Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
+Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+    * Redistributions of source code must retain the above
+      copyright notice, this list of conditions and the following
+      disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+ + + + +
+
+
+
+

Footnotes:

+
+

1 I even reported a few bugs and suggested some fixes in the original +parse-js library, and Marijn pushed fixes literally in minutes. +

+
+
+
+

Author: Mihai Bazon +

+

Date: 2011-08-29 19:17:55 EEST

+

HTML generated by org-mode 7.01trans in emacs 23

+
+
+ + diff --git a/node_modules/uglify-js/README.org b/node_modules/uglify-js/README.org new file mode 100644 index 0000000..50c9c27 --- /dev/null +++ b/node_modules/uglify-js/README.org @@ -0,0 +1,571 @@ +#+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier +#+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier +#+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript +#+STYLE: +#+AUTHOR: Mihai Bazon +#+EMAIL: mihai.bazon@gmail.com + +* UglifyJS --- a JavaScript parser/compressor/beautifier + +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the =exports.*= lines from UglifyJS sources). + +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a +port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn +Haverbeke]]. + +( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of +UglifyJS. ) + +The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and +manipulates the AST generated by the parser to provide the following: + +- ability to re-generate JavaScript code from the AST. Optionally + indented---you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +- shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with =eval()= calls or =with{}= statements. In short, if =eval()= or + =with{}= are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +- various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + + - foo["bar"] ==> foo.bar + + - remove block brackets ={}= + + - join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + + - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + + - consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + + - various optimizations for IF statements: + + - if (foo) bar(); else baz(); ==> foo?bar():baz(); + - if (!foo) bar(); else baz(); ==> foo?baz():bar(); + - if (foo) bar(); ==> foo&&bar(); + - if (!foo) bar(); ==> foo||bar(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + + - remove some unreachable code and warn about it (code that follows a + =return=, =throw=, =break= or =continue= statement, except + function/variable declarations). + + - act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. + +** <> + +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +=--unsafe= flag. + +*** Calls involving the global Array constructor + +The following transformations occur: + +#+BEGIN_SRC js +new Array(1, 2, 3, 4) => [1,2,3,4] +Array(a, b, c) => [a,b,c] +new Array(5) => Array(5) +new Array(a) => Array(a) +#+END_SRC + +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. + +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a =function= or =var= declaration. Therefore, in the +following cases UglifyJS *doesn't touch* calls or instantiations of Array: + +#+BEGIN_SRC js +// case 1. globally declared variable + var Array; + new Array(1, 2, 3); + Array(a, b); + + // or (can be declared later) + new Array(1, 2, 3); + var Array; + + // or (can be a function) + new Array(1, 2, 3); + function Array() { ... } + +// case 2. declared in a function + (function(){ + a = new Array(1, 2, 3); + b = Array(5, 6); + var Array; + })(); + + // or + (function(Array){ + return Array(5, 6, 7); + })(); + + // or + (function(){ + return new Array(1, 2, 3, 4); + function Array() { ... } + })(); + + // etc. +#+END_SRC + +*** =obj.toString()= ==> =obj+“”= + +** Install (NPM) + +UglifyJS is now available through NPM --- =npm install uglify-js= should do +the job. + +** Install latest code from GitHub + +#+BEGIN_SRC sh +## clone the repository +mkdir -p /where/you/wanna/put/it +cd /where/you/wanna/put/it +git clone git://github.com/mishoo/UglifyJS.git + +## make the module available to Node +mkdir -p ~/.node_libraries/ +cd ~/.node_libraries/ +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js + +## and if you want the CLI script too: +mkdir -p ~/bin +cd ~/bin +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs + # (then add ~/bin to your $PATH if it's not there already) +#+END_SRC + +** Usage + +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: + +#+BEGIN_SRC sh +uglifyjs [ options... ] [ filename ] +#+END_SRC + +=filename= should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. + +Supported options: + +- =-b= or =--beautify= --- output indented code; when passed, additional + options control the beautifier: + + - =-i N= or =--indent N= --- indentation level (number of spaces) + + - =-q= or =--quote-keys= --- quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +- =--ascii= --- pass this argument to encode non-ASCII characters as + =\uXXXX= sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +- =-nm= or =--no-mangle= --- don't mangle variable names + +- =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various + optimizations that result in smaller, less readable code). + +- =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too + (by default we don't do this). + +- =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass + =--no-squeeze=) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass =--no-seqs= to disable it. + +- =--no-dead-code= --- by default, UglifyJS will remove code that is + obviously unreachable (code that follows a =return=, =throw=, =break= or + =continue= statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +- =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +- =-o filename= or =--output filename= --- put the result in =filename=. If + this isn't given, the result goes to standard output (or see next one). + +- =--overwrite= --- if the code is read from a file (not from STDIN) and you + pass =--overwrite= then the output will be written in the same file. + +- =--ast= --- pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +- =-v= or =--verbose= --- output some notes on STDERR (for now just how long + each operation takes). + +- =-d SYMBOL[=VALUE]= or =--define SYMBOL[=VALUE]= --- will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value =true=, or you can specify a numeric value (such as + =1024=), a quoted string value (such as ="object"= or + ='https://github.com'=), or the name of another symbol or keyword + (such as =null= or =document=). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of *conditional compilation* + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + =--define-from-module= more suitable for use. + +- =-define-from-module SOMEMODULE= --- will load the named module (as + per the NodeJS =require()= function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the =--define= option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of =--define= + options. + +- =--unsafe= --- enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + + - foo.toString() ==> foo+"" + - new Array(x,...) ==> [x,...] + - new Array(x) ==> Array(x) + +- =--max-line-len= (default 32K characters) --- add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass --max-line-len 0 to disable this + safety feature. + +- =--reserved-names= --- some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names =require= and =$super= + intact you'd specify --reserved-names "require,$super". + +- =--inline-script= -- when you want to include the output literally in an + HTML = + + + + diff --git a/websockets.js b/websockets.js new file mode 100644 index 0000000..205f065 --- /dev/null +++ b/websockets.js @@ -0,0 +1,16 @@ + +async function go() { + const LNSocket = await lnsocket_init() + const ln = LNSocket() + + ln.genkey() + //const their_init = await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "cln.jb55.com:443") + await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "ws://24.84.152.187:8324") + + const rune = "APaeUhcGPAMQwgV1Kn-hRRs5Bi4-D1nrfsHfCoTLl749MTAmbWV0aG9kPWdldGluZm8=" + const res = await ln.rpc({ method: "getinfo", rune }) + + document.body.innerHTML = `
${JSON.stringify(res.result, undefined, 2)}
` +} + +go()