├── giron-wasm ├── .cargo-ok ├── tests │ └── web.rs ├── src │ ├── utils.rs │ └── lib.rs ├── README.md ├── .gitignore ├── LICENSE_MIT ├── Cargo.toml ├── .travis.yml └── LICENSE_APACHE ├── giron-node └── README.md ├── giron ├── src │ ├── estree │ │ └── mod.rs │ ├── span │ │ ├── mod.rs │ │ └── span.rs │ ├── codepoint │ │ ├── mod.rs │ │ └── codepoint.rs │ ├── errors │ │ ├── mod.rs │ │ ├── result.rs │ │ └── errors.rs │ ├── parser │ │ ├── mod.rs │ │ ├── test_static_semantics.rs │ │ └── syntax.rs │ ├── scanner │ │ ├── mod.rs │ │ └── reader.rs │ ├── token │ │ ├── mod.rs │ │ ├── token.rs │ │ ├── value.rs │ │ └── punctuators.rs │ └── lib.rs ├── tests │ ├── snippets │ │ ├── isEven.txt │ │ ├── isNull.txt │ │ ├── isOdd.txt │ │ ├── unary.txt │ │ ├── drop.txt │ │ ├── initial.txt │ │ ├── all.txt │ │ ├── any.txt │ │ ├── byteSize.txt │ │ ├── compact.txt │ │ ├── isObject.txt │ │ ├── take.txt │ │ ├── currentURL.txt │ │ ├── filterFalsy.txt │ │ ├── isPrimitive.txt │ │ ├── isString.txt │ │ ├── isSymbol.txt │ │ ├── isUndefined.txt │ │ ├── negate.txt │ │ ├── none.txt │ │ ├── nthArg.txt │ │ ├── splitLines.txt │ │ ├── ary.txt │ │ ├── collectInto.txt │ │ ├── defer.txt │ │ ├── dropRight.txt │ │ ├── findLast.txt │ │ ├── flip.txt │ │ ├── isAfterDate.txt │ │ ├── isBoolean.txt │ │ ├── isFunction.txt │ │ ├── isNil.txt │ │ ├── maxDate.txt │ │ ├── minDate.txt │ │ ├── shallowClone.txt │ │ ├── spreadOver.txt │ │ ├── tail.txt │ │ ├── union.txt │ │ ├── uniqueElements.txt │ │ ├── allEqual.txt │ │ ├── call.txt │ │ ├── degreesToRads.txt │ │ ├── digitize.txt │ │ ├── functionName.txt │ │ ├── head.txt │ │ ├── isBeforeDate.txt │ │ ├── isLowerCase.txt │ │ ├── isPowerOfTwo.txt │ │ ├── isUpperCase.txt │ │ ├── nodeListToArray.txt │ │ ├── radsToDegrees.txt │ │ ├── atob.txt │ │ ├── btoa.txt │ │ ├── castArray.txt │ │ ├── delay.txt │ │ ├── isBrowserTabFocused.txt │ │ ├── isNumber.txt │ │ ├── reverseString.txt │ │ ├── sample.txt │ │ ├── show.txt │ │ ├── sleep.txt │ │ ├── stripHTMLTags.txt │ │ ├── sum.txt │ │ ├── toDecimalMark.txt │ │ ├── when.txt │ │ ├── checkProp.txt │ │ ├── coalesceFactory.txt │ │ ├── compactWhitespace.txt │ │ ├── distance.txt │ │ ├── getStyle.txt │ │ ├── hasClass.txt │ │ ├── hide.txt │ │ ├── isAbsoluteURL.txt │ │ ├── last.txt │ │ ├── maxN.txt │ │ ├── minN.txt │ │ ├── over.txt │ │ ├── removeNonASCII.txt │ │ ├── setStyle.txt │ │ ├── without.txt │ │ ├── cloneRegExp.txt │ │ ├── escapeRegExp.txt │ │ ├── everyNth.txt │ │ ├── includesAll.txt │ │ ├── includesAny.txt │ │ ├── is.txt │ │ ├── isDivisible.txt │ │ ├── isEmpty.txt │ │ ├── isNegativeZero.txt │ │ ├── isObjectLike.txt │ │ ├── isTravisCI.txt │ │ ├── midpoint.txt │ │ ├── objectToPairs.txt │ │ ├── partial.txt │ │ ├── rearg.txt │ │ ├── reject.txt │ │ ├── similarity.txt │ │ ├── takeRight.txt │ │ ├── toggleClass.txt │ │ ├── coalesce.txt │ │ ├── compose.txt │ │ ├── off.txt │ │ ├── offset.txt │ │ ├── words.txt │ │ ├── xProd.txt │ │ ├── average.txt │ │ ├── defaults.txt │ │ ├── findKey.txt │ │ ├── forOwn.txt │ │ ├── getColonTimeFromDate.txt │ │ ├── isBrowser.txt │ │ ├── isSameDate.txt │ │ ├── isWeekday.txt │ │ ├── isWeekend.txt │ │ ├── partialRight.txt │ │ ├── untildify.txt │ │ ├── RGBToHex.txt │ │ ├── composeRight.txt │ │ ├── deepGet.txt │ │ ├── initializeArrayWithValues.txt │ │ ├── insertAfter.txt │ │ ├── isArrayLike.txt │ │ ├── longestItem.txt │ │ ├── mask.txt │ │ ├── nthElement.txt │ │ ├── pipeFunctions.txt │ │ ├── powerset.txt │ │ ├── randomNumberInRange.txt │ │ ├── round.txt │ │ ├── validateNumber.txt │ │ ├── approximatelyEqual.txt │ │ ├── clampNumber.txt │ │ ├── elementContains.txt │ │ ├── filterNonUnique.txt │ │ ├── insertBefore.txt │ │ ├── maxBy.txt │ │ ├── minBy.txt │ │ ├── objectFromPairs.txt │ │ ├── bind.txt │ │ ├── capitalizeEveryWord.txt │ │ ├── converge.txt │ │ ├── countOccurrences.txt │ │ ├── deepFlatten.txt │ │ ├── hammingDistance.txt │ │ ├── indentString.txt │ │ ├── indexOfAll.txt │ │ ├── intersectionWith.txt │ │ ├── isPlainObject.txt │ │ ├── isStream.txt │ │ ├── overArgs.txt │ │ ├── transform.txt │ │ ├── truthCheckCollection.txt │ │ ├── differenceWith.txt │ │ ├── randomIntegerInRange.txt │ │ ├── runPromisesInSeries.txt │ │ ├── serializeCookie.txt │ │ ├── sortCharactersInString.txt │ │ ├── difference.txt │ │ ├── intersection.txt │ │ ├── pad.txt │ │ ├── pick.txt │ │ ├── pipeAsyncFunctions.txt │ │ ├── yesNo.txt │ │ ├── dayOfYear.txt │ │ ├── getType.txt │ │ ├── triggerEvent.txt │ │ ├── bindKey.txt │ │ ├── forEachRight.txt │ │ ├── mapString.txt │ │ ├── redirect.txt │ │ ├── takeRightWhile.txt │ │ ├── truncateString.txt │ │ ├── zipObject.txt │ │ ├── bifurcate.txt │ │ ├── bifurcateBy.txt │ │ ├── findLastKey.txt │ │ ├── hasFlags.txt │ │ ├── matches.txt │ │ ├── reduceWhich.txt │ │ ├── sumBy.txt │ │ ├── unionWith.txt │ │ ├── curry.txt │ │ ├── dropWhile.txt │ │ ├── filterNonUniqueBy.txt │ │ ├── forOwnRight.txt │ │ ├── frequencies.txt │ │ ├── getDaysDiffBetweenDates.txt │ │ ├── intersectionBy.txt │ │ ├── smoothScroll.txt │ │ ├── times.txt │ │ ├── toSafeInteger.txt │ │ ├── createDirIfNotExists.txt │ │ ├── differenceBy.txt │ │ ├── flatten.txt │ │ ├── gcd.txt │ │ ├── mapNumRange.txt │ │ ├── serializeForm.txt │ │ ├── tomorrow.txt │ │ ├── JSONToFile.txt │ │ ├── initialize2DArray.txt │ │ ├── palindrome.txt │ │ ├── percentile.txt │ │ ├── yesterday.txt │ │ ├── httpsRedirect.txt │ │ ├── takeWhile.txt │ │ ├── averageBy.txt │ │ ├── capitalize.txt │ │ ├── chunk.txt │ │ ├── mapKeys.txt │ │ ├── mapValues.txt │ │ ├── omit.txt │ │ ├── omitBy.txt │ │ ├── pickBy.txt │ │ ├── randomHexColorCode.txt │ │ ├── reduceSuccessive.txt │ │ ├── unionBy.txt │ │ ├── createElement.txt │ │ ├── decapitalize.txt │ │ ├── randomIntArrayInRange.txt │ │ ├── timeTaken.txt │ │ ├── toCurrency.txt │ │ ├── fibonacci.txt │ │ ├── findLastIndex.txt │ │ ├── isPromiseLike.txt │ │ ├── isValidJSON.txt │ │ ├── lowercaseKeys.txt │ │ ├── mapObject.txt │ │ ├── promisify.txt │ │ ├── readFileLines.txt │ │ ├── uniqueSymmetricDifference.txt │ │ ├── attempt.txt │ │ ├── shank.txt │ │ ├── unfold.txt │ │ ├── uniqueElementsBy.txt │ │ ├── arrayToCSV.txt │ │ ├── extendHex.txt │ │ ├── detectDeviceType.txt │ │ ├── initializeArrayWithRange.txt │ │ ├── nest.txt │ │ ├── sumPower.txt │ │ ├── inRange.txt │ │ ├── isPrime.txt │ │ ├── toHash.txt │ │ ├── uniqueElementsByRight.txt │ │ ├── bottomVisible.txt │ │ ├── dropRightWhile.txt │ │ ├── initializeNDArray.txt │ │ ├── lcm.txt │ │ ├── countBy.txt │ │ ├── once.txt │ │ ├── reducedFilter.txt │ │ ├── symmetricDifference.txt │ │ ├── formToObject.txt │ │ ├── hz.txt │ │ ├── toKebabCase.txt │ │ ├── toSnakeCase.txt │ │ ├── CSVToArray.txt │ │ ├── arrayToHtmlList.txt │ │ ├── deepFreeze.txt │ │ ├── partition.txt │ │ ├── bindAll.txt │ │ ├── debounce.txt │ │ ├── geometricProgression.txt │ │ ├── getScrollPosition.txt │ │ ├── getURLParameters.txt │ │ ├── groupBy.txt │ │ ├── median.txt │ │ ├── renameKeys.txt │ │ ├── stableSort.txt │ │ ├── symmetricDifferenceWith.txt │ │ ├── toTitleCase.txt │ │ ├── factorial.txt │ │ ├── haveSameContents.txt │ │ ├── UUIDGeneratorBrowser.txt │ │ ├── shuffle.txt │ │ ├── unzip.txt │ │ ├── fromCamelCase.txt │ │ ├── getImages.txt │ │ ├── pull.txt │ │ ├── UUIDGeneratorNode.txt │ │ ├── functions.txt │ │ ├── isReadableStream.txt │ │ ├── isWritableStream.txt │ │ ├── matchesWith.txt │ │ ├── mostFrequent.txt │ │ ├── remove.txt │ │ ├── sortedIndex.txt │ │ ├── chainAsync.txt │ │ ├── initializeArrayWithRangeRight.txt │ │ ├── isContainedIn.txt │ │ ├── scrollToTop.txt │ │ ├── symmetricDifferenceBy.txt │ │ ├── uncurry.txt │ │ ├── invertKeyValues.txt │ │ ├── sampleSize.txt │ │ ├── sdbm.txt │ │ ├── zip.txt │ │ ├── dig.txt │ │ ├── get.txt │ │ ├── size.txt │ │ ├── sortedLastIndex.txt │ │ ├── getMeridiemSuffixOfInteger.txt │ │ ├── parseCookie.txt │ │ ├── on.txt │ │ ├── escapeHTML.txt │ │ ├── hasKey.txt │ │ ├── memoize.txt │ │ ├── URLJoin.txt │ │ ├── httpGet.txt │ │ ├── isAnagram.txt │ │ ├── merge.txt │ │ ├── sortedIndexBy.txt │ │ ├── vectorDistance.txt │ │ ├── join.txt │ │ ├── zipWith.txt │ │ ├── unzipWith.txt │ │ ├── unescapeHTML.txt │ │ ├── flattenObject.txt │ │ ├── mostPerformant.txt │ │ ├── pullAtIndex.txt │ │ ├── weightedSample.txt │ │ ├── JSONtoCSV.txt │ │ ├── pluralize.txt │ │ ├── isDuplexStream.txt │ │ ├── pullAtValue.txt │ │ ├── hashNode.txt │ │ ├── primes.txt │ │ ├── toCamelCase.txt │ │ ├── standardDeviation.txt │ │ ├── isSorted.txt │ │ ├── permutations.txt │ │ ├── sortedLastIndexBy.txt │ │ ├── luhnCheck.txt │ │ ├── hashBrowser.txt │ │ ├── orderBy.txt │ │ ├── stringPermutations.txt │ │ ├── httpPost.txt │ │ ├── CSVToJSON.txt │ │ ├── binomialCoefficient.txt │ │ ├── objectToQueryString.txt │ │ ├── prefix.txt │ │ ├── toOrdinalSuffix.txt │ │ ├── pullBy.txt │ │ ├── deepMapKeys.txt │ │ ├── deepClone.txt │ │ ├── equals.txt │ │ ├── runAsync.txt │ │ ├── elementIsVisibleInViewport.txt │ │ ├── formatDuration.txt │ │ ├── prettyBytes.txt │ │ ├── counter.txt │ │ ├── unflattenObject.txt │ │ ├── recordAnimationFrames.txt │ │ ├── observeMutations.txt │ │ ├── createEventHub.txt │ │ ├── onUserInputChange.txt │ │ ├── hexToRGB.txt │ │ ├── throttle.txt │ │ ├── copyToClipboard.txt │ │ ├── elo.txt │ │ └── colorize.txt │ └── test_parser.rs ├── Cargo.toml ├── LICENSE_MIT ├── README.md └── LICENSE_APACHE ├── Cargo.toml ├── .travis.yml ├── README.md ├── LICENSE_MIT ├── .gitignore └── LICENSE_APACHE /giron-wasm/.cargo-ok: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /giron-node/README.md: -------------------------------------------------------------------------------- 1 | Work In Progress 2 | -------------------------------------------------------------------------------- /giron/src/estree/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod estree; 2 | -------------------------------------------------------------------------------- /giron/src/span/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod span; 2 | -------------------------------------------------------------------------------- /giron/src/codepoint/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod codepoint; 2 | -------------------------------------------------------------------------------- /giron/src/errors/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod errors; 2 | pub mod result; 3 | -------------------------------------------------------------------------------- /giron/src/parser/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod parser; 2 | pub mod syntax; 3 | -------------------------------------------------------------------------------- /giron/src/scanner/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod reader; 2 | pub mod scanner; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isEven.txt: -------------------------------------------------------------------------------- 1 | 2 | const isEven = num => num % 2 === 0; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isNull.txt: -------------------------------------------------------------------------------- 1 | 2 | const isNull = val => val === null; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isOdd.txt: -------------------------------------------------------------------------------- 1 | 2 | const isOdd = num => num % 2 === 1; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/unary.txt: -------------------------------------------------------------------------------- 1 | 2 | const unary = fn => val => fn(val); 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "giron-wasm", 4 | "giron", 5 | ] -------------------------------------------------------------------------------- /giron/tests/snippets/drop.txt: -------------------------------------------------------------------------------- 1 | 2 | const drop = (arr, n = 1) => arr.slice(n); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/initial.txt: -------------------------------------------------------------------------------- 1 | 2 | const initial = arr => arr.slice(0, -1); 3 | -------------------------------------------------------------------------------- /giron/src/token/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod punctuators; 2 | pub mod token; 3 | pub mod value; 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/all.txt: -------------------------------------------------------------------------------- 1 | 2 | const all = (arr, fn = Boolean) => arr.every(fn); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/any.txt: -------------------------------------------------------------------------------- 1 | 2 | const any = (arr, fn = Boolean) => arr.some(fn); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/byteSize.txt: -------------------------------------------------------------------------------- 1 | 2 | const byteSize = str => new Blob([str]).size; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/compact.txt: -------------------------------------------------------------------------------- 1 | 2 | const compact = arr => arr.filter(Boolean); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isObject.txt: -------------------------------------------------------------------------------- 1 | 2 | const isObject = obj => obj === Object(obj); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/take.txt: -------------------------------------------------------------------------------- 1 | 2 | const take = (arr, n = 1) => arr.slice(0, n); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/currentURL.txt: -------------------------------------------------------------------------------- 1 | 2 | const currentURL = () => window.location.href; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/filterFalsy.txt: -------------------------------------------------------------------------------- 1 | 2 | const filterFalsy = arr => arr.filter(Boolean); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isPrimitive.txt: -------------------------------------------------------------------------------- 1 | 2 | const isPrimitive = val => Object(val) !== val; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isString.txt: -------------------------------------------------------------------------------- 1 | 2 | const isString = val => typeof val === 'string'; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isSymbol.txt: -------------------------------------------------------------------------------- 1 | 2 | const isSymbol = val => typeof val === 'symbol'; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isUndefined.txt: -------------------------------------------------------------------------------- 1 | 2 | const isUndefined = val => val === undefined; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/negate.txt: -------------------------------------------------------------------------------- 1 | 2 | const negate = func => (...args) => !func(...args); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/none.txt: -------------------------------------------------------------------------------- 1 | 2 | const none = (arr, fn = Boolean) => !arr.some(fn); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/nthArg.txt: -------------------------------------------------------------------------------- 1 | 2 | const nthArg = n => (...args) => args.slice(n)[0]; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/splitLines.txt: -------------------------------------------------------------------------------- 1 | 2 | const splitLines = str => str.split(/\r?\n/); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/ary.txt: -------------------------------------------------------------------------------- 1 | 2 | const ary = (fn, n) => (...args) => fn(...args.slice(0, n)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/collectInto.txt: -------------------------------------------------------------------------------- 1 | 2 | const collectInto = fn => (...args) => fn(args); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/defer.txt: -------------------------------------------------------------------------------- 1 | 2 | const defer = (fn, ...args) => setTimeout(fn, 1, ...args); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/dropRight.txt: -------------------------------------------------------------------------------- 1 | 2 | const dropRight = (arr, n = 1) => arr.slice(0, -n); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/findLast.txt: -------------------------------------------------------------------------------- 1 | 2 | const findLast = (arr, fn) => arr.filter(fn).pop(); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/flip.txt: -------------------------------------------------------------------------------- 1 | 2 | const flip = fn => (first, ...rest) => fn(...rest, first); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isAfterDate.txt: -------------------------------------------------------------------------------- 1 | 2 | const isAfterDate = (dateA, dateB) => dateA > dateB; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isBoolean.txt: -------------------------------------------------------------------------------- 1 | 2 | const isBoolean = val => typeof val === 'boolean'; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isFunction.txt: -------------------------------------------------------------------------------- 1 | 2 | const isFunction = val => typeof val === 'function'; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isNil.txt: -------------------------------------------------------------------------------- 1 | 2 | const isNil = val => val === undefined || val === null; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/maxDate.txt: -------------------------------------------------------------------------------- 1 | 2 | const maxDate = dates => new Date(Math.max(...dates)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/minDate.txt: -------------------------------------------------------------------------------- 1 | 2 | const minDate = dates => new Date(Math.min(...dates)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/shallowClone.txt: -------------------------------------------------------------------------------- 1 | 2 | const shallowClone = obj => Object.assign({}, obj); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/spreadOver.txt: -------------------------------------------------------------------------------- 1 | 2 | const spreadOver = fn => argsArr => fn(...argsArr); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/tail.txt: -------------------------------------------------------------------------------- 1 | 2 | const tail = arr => (arr.length > 1 ? arr.slice(1) : arr); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/union.txt: -------------------------------------------------------------------------------- 1 | 2 | const union = (a, b) => Array.from(new Set([...a, ...b])); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/uniqueElements.txt: -------------------------------------------------------------------------------- 1 | 2 | const uniqueElements = arr => [...new Set(arr)]; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/allEqual.txt: -------------------------------------------------------------------------------- 1 | 2 | const allEqual = arr => arr.every(val => val === arr[0]); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/call.txt: -------------------------------------------------------------------------------- 1 | 2 | const call = (key, ...args) => context => context[key](...args); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/degreesToRads.txt: -------------------------------------------------------------------------------- 1 | 2 | const degreesToRads = deg => (deg * Math.PI) / 180.0; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/digitize.txt: -------------------------------------------------------------------------------- 1 | 2 | const digitize = n => [...`${n}`].map(i => parseInt(i)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/functionName.txt: -------------------------------------------------------------------------------- 1 | 2 | const functionName = fn => (console.debug(fn.name), fn); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/head.txt: -------------------------------------------------------------------------------- 1 | 2 | const head = arr => (arr && arr.length ? arr[0] : undefined); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isBeforeDate.txt: -------------------------------------------------------------------------------- 1 | 2 | const isBeforeDate = (dateA, dateB) => dateA < dateB; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isLowerCase.txt: -------------------------------------------------------------------------------- 1 | 2 | const isLowerCase = str => str === str.toLowerCase(); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isPowerOfTwo.txt: -------------------------------------------------------------------------------- 1 | 2 | const isPowerOfTwo = n => !!n && (n & (n - 1)) == 0; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isUpperCase.txt: -------------------------------------------------------------------------------- 1 | 2 | const isUpperCase = str => str === str.toUpperCase(); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/nodeListToArray.txt: -------------------------------------------------------------------------------- 1 | 2 | const nodeListToArray = nodeList => [...nodeList]; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/radsToDegrees.txt: -------------------------------------------------------------------------------- 1 | 2 | const radsToDegrees = rad => (rad * 180.0) / Math.PI; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/atob.txt: -------------------------------------------------------------------------------- 1 | 2 | const atob = str => Buffer.from(str, 'base64').toString('binary'); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/btoa.txt: -------------------------------------------------------------------------------- 1 | 2 | const btoa = str => Buffer.from(str, 'binary').toString('base64'); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/castArray.txt: -------------------------------------------------------------------------------- 1 | 2 | const castArray = val => (Array.isArray(val) ? val : [val]); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/delay.txt: -------------------------------------------------------------------------------- 1 | 2 | const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isBrowserTabFocused.txt: -------------------------------------------------------------------------------- 1 | 2 | const isBrowserTabFocused = () => !document.hidden; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isNumber.txt: -------------------------------------------------------------------------------- 1 | 2 | const isNumber = val => typeof val === 'number' && val === val; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/reverseString.txt: -------------------------------------------------------------------------------- 1 | 2 | const reverseString = str => [...str].reverse().join(''); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/sample.txt: -------------------------------------------------------------------------------- 1 | 2 | const sample = arr => arr[Math.floor(Math.random() * arr.length)]; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/show.txt: -------------------------------------------------------------------------------- 1 | 2 | const show = (...el) => [...el].forEach(e => (e.style.display = '')); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/sleep.txt: -------------------------------------------------------------------------------- 1 | 2 | const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/stripHTMLTags.txt: -------------------------------------------------------------------------------- 1 | 2 | const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/sum.txt: -------------------------------------------------------------------------------- 1 | 2 | const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/toDecimalMark.txt: -------------------------------------------------------------------------------- 1 | 2 | const toDecimalMark = num => num.toLocaleString('en-US'); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/when.txt: -------------------------------------------------------------------------------- 1 | 2 | const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/checkProp.txt: -------------------------------------------------------------------------------- 1 | 2 | const checkProp = (predicate, prop) => obj => !!predicate(obj[prop]); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/coalesceFactory.txt: -------------------------------------------------------------------------------- 1 | 2 | const coalesceFactory = valid => (...args) => args.find(valid); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/compactWhitespace.txt: -------------------------------------------------------------------------------- 1 | 2 | const compactWhitespace = str => str.replace(/\s{2,}/g, ' '); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/distance.txt: -------------------------------------------------------------------------------- 1 | 2 | const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/getStyle.txt: -------------------------------------------------------------------------------- 1 | 2 | const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/hasClass.txt: -------------------------------------------------------------------------------- 1 | 2 | const hasClass = (el, className) => el.classList.contains(className); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/hide.txt: -------------------------------------------------------------------------------- 1 | 2 | const hide = (...el) => [...el].forEach(e => (e.style.display = 'none')); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isAbsoluteURL.txt: -------------------------------------------------------------------------------- 1 | 2 | const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/last.txt: -------------------------------------------------------------------------------- 1 | 2 | const last = arr => (arr && arr.length ? arr[arr.length - 1] : undefined); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/maxN.txt: -------------------------------------------------------------------------------- 1 | 2 | const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/minN.txt: -------------------------------------------------------------------------------- 1 | 2 | const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/over.txt: -------------------------------------------------------------------------------- 1 | 2 | const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/removeNonASCII.txt: -------------------------------------------------------------------------------- 1 | 2 | const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/setStyle.txt: -------------------------------------------------------------------------------- 1 | 2 | const setStyle = (el, ruleName, val) => (el.style[ruleName] = val); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/without.txt: -------------------------------------------------------------------------------- 1 | 2 | const without = (arr, ...args) => arr.filter(v => !args.includes(v)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/cloneRegExp.txt: -------------------------------------------------------------------------------- 1 | 2 | const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/escapeRegExp.txt: -------------------------------------------------------------------------------- 1 | 2 | const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/everyNth.txt: -------------------------------------------------------------------------------- 1 | 2 | const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/includesAll.txt: -------------------------------------------------------------------------------- 1 | 2 | const includesAll = (arr, values) => values.every(v => arr.includes(v)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/includesAny.txt: -------------------------------------------------------------------------------- 1 | 2 | const includesAny = (arr, values) => values.some(v => arr.includes(v)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/is.txt: -------------------------------------------------------------------------------- 1 | 2 | const is = (type, val) => ![, null].includes(val) && val.constructor === type; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isDivisible.txt: -------------------------------------------------------------------------------- 1 | 2 | const isDivisible = (dividend, divisor) => dividend % divisor === 0; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isEmpty.txt: -------------------------------------------------------------------------------- 1 | 2 | const isEmpty = val => val == null || !(Object.keys(val) || val).length; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isNegativeZero.txt: -------------------------------------------------------------------------------- 1 | 2 | const isNegativeZero = val => val === 0 && 1 / val === -Infinity; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isObjectLike.txt: -------------------------------------------------------------------------------- 1 | 2 | const isObjectLike = val => val !== null && typeof val === 'object'; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isTravisCI.txt: -------------------------------------------------------------------------------- 1 | 2 | const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/midpoint.txt: -------------------------------------------------------------------------------- 1 | 2 | const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2]; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/objectToPairs.txt: -------------------------------------------------------------------------------- 1 | 2 | const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/partial.txt: -------------------------------------------------------------------------------- 1 | 2 | const partial = (fn, ...partials) => (...args) => fn(...partials, ...args); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/rearg.txt: -------------------------------------------------------------------------------- 1 | 2 | const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i])); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/reject.txt: -------------------------------------------------------------------------------- 1 | 2 | const reject = (pred, array) => array.filter((...args) => !pred(...args)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/similarity.txt: -------------------------------------------------------------------------------- 1 | 2 | const similarity = (arr, values) => arr.filter(v => values.includes(v)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/takeRight.txt: -------------------------------------------------------------------------------- 1 | 2 | const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/toggleClass.txt: -------------------------------------------------------------------------------- 1 | 2 | const toggleClass = (el, className) => el.classList.toggle(className); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/coalesce.txt: -------------------------------------------------------------------------------- 1 | 2 | const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/compose.txt: -------------------------------------------------------------------------------- 1 | 2 | const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args))); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/off.txt: -------------------------------------------------------------------------------- 1 | 2 | const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/offset.txt: -------------------------------------------------------------------------------- 1 | 2 | const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/words.txt: -------------------------------------------------------------------------------- 1 | 2 | const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/xProd.txt: -------------------------------------------------------------------------------- 1 | 2 | const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []); 3 | -------------------------------------------------------------------------------- /giron/src/errors/result.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::errors::Error; 2 | 3 | pub type Result = std::result::Result; 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/average.txt: -------------------------------------------------------------------------------- 1 | 2 | const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/defaults.txt: -------------------------------------------------------------------------------- 1 | 2 | const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/findKey.txt: -------------------------------------------------------------------------------- 1 | 2 | const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/forOwn.txt: -------------------------------------------------------------------------------- 1 | 2 | const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/getColonTimeFromDate.txt: -------------------------------------------------------------------------------- 1 | 2 | const getColonTimeFromDate = date => date.toTimeString().slice(0, 8); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isBrowser.txt: -------------------------------------------------------------------------------- 1 | 2 | const isBrowser = () => ![typeof window, typeof document].includes('undefined'); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isSameDate.txt: -------------------------------------------------------------------------------- 1 | 2 | const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString(); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isWeekday.txt: -------------------------------------------------------------------------------- 1 | 2 | const isWeekday = (t = new Date()) => { 3 | return t.getDay() % 6 !== 0; 4 | }; 5 | -------------------------------------------------------------------------------- /giron/tests/snippets/isWeekend.txt: -------------------------------------------------------------------------------- 1 | 2 | const isWeekend = (t = new Date()) => { 3 | return t.getDay() % 6 === 0; 4 | }; 5 | -------------------------------------------------------------------------------- /giron/tests/snippets/partialRight.txt: -------------------------------------------------------------------------------- 1 | 2 | const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/untildify.txt: -------------------------------------------------------------------------------- 1 | 2 | const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/RGBToHex.txt: -------------------------------------------------------------------------------- 1 | 2 | const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/composeRight.txt: -------------------------------------------------------------------------------- 1 | 2 | const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/deepGet.txt: -------------------------------------------------------------------------------- 1 | 2 | const deepGet = (obj, keys) => keys.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), obj); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/initializeArrayWithValues.txt: -------------------------------------------------------------------------------- 1 | 2 | const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/insertAfter.txt: -------------------------------------------------------------------------------- 1 | 2 | const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isArrayLike.txt: -------------------------------------------------------------------------------- 1 | 2 | const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/longestItem.txt: -------------------------------------------------------------------------------- 1 | 2 | const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/mask.txt: -------------------------------------------------------------------------------- 1 | 2 | const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/nthElement.txt: -------------------------------------------------------------------------------- 1 | 2 | const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0]; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/pipeFunctions.txt: -------------------------------------------------------------------------------- 1 | 2 | const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/powerset.txt: -------------------------------------------------------------------------------- 1 | 2 | const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/randomNumberInRange.txt: -------------------------------------------------------------------------------- 1 | 2 | const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/round.txt: -------------------------------------------------------------------------------- 1 | 2 | const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/validateNumber.txt: -------------------------------------------------------------------------------- 1 | 2 | const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/approximatelyEqual.txt: -------------------------------------------------------------------------------- 1 | 2 | const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/clampNumber.txt: -------------------------------------------------------------------------------- 1 | 2 | const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/elementContains.txt: -------------------------------------------------------------------------------- 1 | 2 | const elementContains = (parent, child) => parent !== child && parent.contains(child); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/filterNonUnique.txt: -------------------------------------------------------------------------------- 1 | 2 | const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/insertBefore.txt: -------------------------------------------------------------------------------- 1 | 2 | const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/maxBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/minBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/objectFromPairs.txt: -------------------------------------------------------------------------------- 1 | 2 | const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {}); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/bind.txt: -------------------------------------------------------------------------------- 1 | 2 | const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/capitalizeEveryWord.txt: -------------------------------------------------------------------------------- 1 | 2 | const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/converge.txt: -------------------------------------------------------------------------------- 1 | 2 | const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args))); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/countOccurrences.txt: -------------------------------------------------------------------------------- 1 | 2 | const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/deepFlatten.txt: -------------------------------------------------------------------------------- 1 | 2 | const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v))); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/hammingDistance.txt: -------------------------------------------------------------------------------- 1 | 2 | const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/indentString.txt: -------------------------------------------------------------------------------- 1 | 2 | const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/indexOfAll.txt: -------------------------------------------------------------------------------- 1 | 2 | const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/intersectionWith.txt: -------------------------------------------------------------------------------- 1 | 2 | const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isPlainObject.txt: -------------------------------------------------------------------------------- 1 | 2 | const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/isStream.txt: -------------------------------------------------------------------------------- 1 | 2 | const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function'; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/overArgs.txt: -------------------------------------------------------------------------------- 1 | 2 | const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val))); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/transform.txt: -------------------------------------------------------------------------------- 1 | 2 | const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/truthCheckCollection.txt: -------------------------------------------------------------------------------- 1 | 2 | const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/differenceWith.txt: -------------------------------------------------------------------------------- 1 | 2 | const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/randomIntegerInRange.txt: -------------------------------------------------------------------------------- 1 | 2 | const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/runPromisesInSeries.txt: -------------------------------------------------------------------------------- 1 | 2 | const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/serializeCookie.txt: -------------------------------------------------------------------------------- 1 | 2 | const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`; 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/sortCharactersInString.txt: -------------------------------------------------------------------------------- 1 | 2 | const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join(''); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/difference.txt: -------------------------------------------------------------------------------- 1 | 2 | const difference = (a, b) => { 3 | const s = new Set(b); 4 | return a.filter(x => !s.has(x)); 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/intersection.txt: -------------------------------------------------------------------------------- 1 | 2 | const intersection = (a, b) => { 3 | const s = new Set(b); 4 | return a.filter(x => s.has(x)); 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/pad.txt: -------------------------------------------------------------------------------- 1 | 2 | const pad = (str, length, char = ' ') => 3 | str.padStart((str.length + length) / 2, char).padEnd(length, char); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/pick.txt: -------------------------------------------------------------------------------- 1 | 2 | const pick = (obj, arr) => 3 | arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/pipeAsyncFunctions.txt: -------------------------------------------------------------------------------- 1 | 2 | const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); 3 | -------------------------------------------------------------------------------- /giron/tests/snippets/yesNo.txt: -------------------------------------------------------------------------------- 1 | 2 | const yesNo = (val, def = false) => 3 | /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def; 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/dayOfYear.txt: -------------------------------------------------------------------------------- 1 | 2 | const dayOfYear = date => 3 | Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/getType.txt: -------------------------------------------------------------------------------- 1 | 2 | const getType = v => 3 | v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/triggerEvent.txt: -------------------------------------------------------------------------------- 1 | 2 | const triggerEvent = (el, eventType, detail) => 3 | el.dispatchEvent(new CustomEvent(eventType, { detail })); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/bindKey.txt: -------------------------------------------------------------------------------- 1 | 2 | const bindKey = (context, fn, ...boundArgs) => (...args) => 3 | context[fn].apply(context, [...boundArgs, ...args]); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/forEachRight.txt: -------------------------------------------------------------------------------- 1 | 2 | const forEachRight = (arr, callback) => 3 | arr 4 | .slice(0) 5 | .reverse() 6 | .forEach(callback); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/mapString.txt: -------------------------------------------------------------------------------- 1 | 2 | const mapString = (str, fn) => 3 | str 4 | .split('') 5 | .map((c, i) => fn(c, i, str)) 6 | .join(''); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/redirect.txt: -------------------------------------------------------------------------------- 1 | 2 | const redirect = (url, asLink = true) => 3 | asLink ? (window.location.href = url) : window.location.replace(url); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/takeRightWhile.txt: -------------------------------------------------------------------------------- 1 | 2 | const takeRightWhile = (arr, func) => 3 | arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/truncateString.txt: -------------------------------------------------------------------------------- 1 | 2 | const truncateString = (str, num) => 3 | str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/zipObject.txt: -------------------------------------------------------------------------------- 1 | 2 | const zipObject = (props, values) => 3 | props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {}); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/bifurcate.txt: -------------------------------------------------------------------------------- 1 | 2 | const bifurcate = (arr, filter) => 3 | arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/bifurcateBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const bifurcateBy = (arr, fn) => 3 | arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/findLastKey.txt: -------------------------------------------------------------------------------- 1 | 2 | const findLastKey = (obj, fn) => 3 | Object.keys(obj) 4 | .reverse() 5 | .find(key => fn(obj[key], key, obj)); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/hasFlags.txt: -------------------------------------------------------------------------------- 1 | 2 | const hasFlags = (...flags) => 3 | flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag)); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/matches.txt: -------------------------------------------------------------------------------- 1 | 2 | const matches = (obj, source) => 3 | Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/reduceWhich.txt: -------------------------------------------------------------------------------- 1 | 2 | const reduceWhich = (arr, comparator = (a, b) => a - b) => 3 | arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/sumBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const sumBy = (arr, fn) => 3 | arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/unionWith.txt: -------------------------------------------------------------------------------- 1 | 2 | const unionWith = (a, b, comp) => 3 | Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)])); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/curry.txt: -------------------------------------------------------------------------------- 1 | 2 | const curry = (fn, arity = fn.length, ...args) => 3 | arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/dropWhile.txt: -------------------------------------------------------------------------------- 1 | 2 | const dropWhile = (arr, func) => { 3 | while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); 4 | return arr; 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/filterNonUniqueBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const filterNonUniqueBy = (arr, fn) => 3 | arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j))); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/forOwnRight.txt: -------------------------------------------------------------------------------- 1 | 2 | const forOwnRight = (obj, fn) => 3 | Object.keys(obj) 4 | .reverse() 5 | .forEach(key => fn(obj[key], key, obj)); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/frequencies.txt: -------------------------------------------------------------------------------- 1 | 2 | const frequencies = arr => 3 | arr.reduce((a, v) => { 4 | a[v] = a[v] ? a[v] + 1 : 1; 5 | return a; 6 | }, {}); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/getDaysDiffBetweenDates.txt: -------------------------------------------------------------------------------- 1 | 2 | const getDaysDiffBetweenDates = (dateInitial, dateFinal) => 3 | (dateFinal - dateInitial) / (1000 * 3600 * 24); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/intersectionBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const intersectionBy = (a, b, fn) => { 3 | const s = new Set(b.map(fn)); 4 | return a.filter(x => s.has(fn(x))); 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/smoothScroll.txt: -------------------------------------------------------------------------------- 1 | 2 | const smoothScroll = element => 3 | document.querySelector(element).scrollIntoView({ 4 | behavior: 'smooth' 5 | }); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/times.txt: -------------------------------------------------------------------------------- 1 | 2 | const times = (n, fn, context = undefined) => { 3 | let i = 0; 4 | while (fn.call(context, i) !== false && ++i < n) {} 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/toSafeInteger.txt: -------------------------------------------------------------------------------- 1 | 2 | const toSafeInteger = num => 3 | Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER)); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/createDirIfNotExists.txt: -------------------------------------------------------------------------------- 1 | 2 | const fs = require('fs'); 3 | const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/differenceBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const differenceBy = (a, b, fn) => { 3 | const s = new Set(b.map(fn)); 4 | return a.map(fn).filter(el => !s.has(el)); 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/flatten.txt: -------------------------------------------------------------------------------- 1 | 2 | const flatten = (arr, depth = 1) => 3 | arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/gcd.txt: -------------------------------------------------------------------------------- 1 | 2 | const gcd = (...arr) => { 3 | const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); 4 | return [...arr].reduce((a, b) => _gcd(a, b)); 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/mapNumRange.txt: -------------------------------------------------------------------------------- 1 | 2 | const mapNumRange = (num, inMin, inMax, outMin, outMax) => 3 | ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin; 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/serializeForm.txt: -------------------------------------------------------------------------------- 1 | 2 | const serializeForm = form => 3 | Array.from(new FormData(form), field => field.map(encodeURIComponent).join('=')).join('&'); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/tomorrow.txt: -------------------------------------------------------------------------------- 1 | 2 | const tomorrow = () => { 3 | let t = new Date(); 4 | t.setDate(t.getDate() + 1); 5 | return t.toISOString().split('T')[0]; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/JSONToFile.txt: -------------------------------------------------------------------------------- 1 | 2 | const fs = require('fs'); 3 | const JSONToFile = (obj, filename) => 4 | fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); 5 | -------------------------------------------------------------------------------- /giron/tests/snippets/initialize2DArray.txt: -------------------------------------------------------------------------------- 1 | 2 | const initialize2DArray = (w, h, val = null) => 3 | Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val)); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/palindrome.txt: -------------------------------------------------------------------------------- 1 | 2 | const palindrome = str => { 3 | const s = str.toLowerCase().replace(/[\W_]/g, ''); 4 | return s === [...s].reverse().join(''); 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/percentile.txt: -------------------------------------------------------------------------------- 1 | 2 | const percentile = (arr, val) => 3 | (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length; 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/yesterday.txt: -------------------------------------------------------------------------------- 1 | 2 | const yesterday = () => { 3 | let t = new Date(); 4 | t.setDate(t.getDate() - 1); 5 | return t.toISOString().split('T')[0]; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/httpsRedirect.txt: -------------------------------------------------------------------------------- 1 | 2 | const httpsRedirect = () => { 3 | if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]); 4 | }; 5 | -------------------------------------------------------------------------------- /giron/tests/snippets/takeWhile.txt: -------------------------------------------------------------------------------- 1 | 2 | const takeWhile = (arr, func) => { 3 | for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i); 4 | return arr; 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/averageBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const averageBy = (arr, fn) => 3 | arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / 4 | arr.length; 5 | -------------------------------------------------------------------------------- /giron/tests/snippets/capitalize.txt: -------------------------------------------------------------------------------- 1 | 2 | const capitalize = ([first, ...rest], lowerRest = false) => 3 | first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join('')); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/chunk.txt: -------------------------------------------------------------------------------- 1 | 2 | const chunk = (arr, size) => 3 | Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => 4 | arr.slice(i * size, i * size + size) 5 | ); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/mapKeys.txt: -------------------------------------------------------------------------------- 1 | 2 | const mapKeys = (obj, fn) => 3 | Object.keys(obj).reduce((acc, k) => { 4 | acc[fn(obj[k], k, obj)] = obj[k]; 5 | return acc; 6 | }, {}); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/mapValues.txt: -------------------------------------------------------------------------------- 1 | 2 | const mapValues = (obj, fn) => 3 | Object.keys(obj).reduce((acc, k) => { 4 | acc[k] = fn(obj[k], k, obj); 5 | return acc; 6 | }, {}); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/omit.txt: -------------------------------------------------------------------------------- 1 | 2 | const omit = (obj, arr) => 3 | Object.keys(obj) 4 | .filter(k => !arr.includes(k)) 5 | .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/omitBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const omitBy = (obj, fn) => 3 | Object.keys(obj) 4 | .filter(k => !fn(obj[k], k)) 5 | .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/pickBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const pickBy = (obj, fn) => 3 | Object.keys(obj) 4 | .filter(k => fn(obj[k], k)) 5 | .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/randomHexColorCode.txt: -------------------------------------------------------------------------------- 1 | 2 | const randomHexColorCode = () => { 3 | let n = (Math.random() * 0xfffff * 1000000).toString(16); 4 | return '#' + n.slice(0, 6); 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/reduceSuccessive.txt: -------------------------------------------------------------------------------- 1 | 2 | const reduceSuccessive = (arr, fn, acc) => 3 | arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/unionBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const unionBy = (a, b, fn) => { 3 | const s = new Set(a.map(fn)); 4 | return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))])); 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/createElement.txt: -------------------------------------------------------------------------------- 1 | 2 | const createElement = str => { 3 | const el = document.createElement('div'); 4 | el.innerHTML = str; 5 | return el.firstElementChild; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/decapitalize.txt: -------------------------------------------------------------------------------- 1 | 2 | const decapitalize = ([first, ...rest], upperRest = false) => 3 | first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join('')); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/randomIntArrayInRange.txt: -------------------------------------------------------------------------------- 1 | 2 | const randomIntArrayInRange = (min, max, n = 1) => 3 | Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/timeTaken.txt: -------------------------------------------------------------------------------- 1 | 2 | const timeTaken = callback => { 3 | console.time('timeTaken'); 4 | const r = callback(); 5 | console.timeEnd('timeTaken'); 6 | return r; 7 | }; 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/toCurrency.txt: -------------------------------------------------------------------------------- 1 | 2 | const toCurrency = (n, curr, LanguageFormat = undefined) => 3 | Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/fibonacci.txt: -------------------------------------------------------------------------------- 1 | 2 | const fibonacci = n => 3 | Array.from({ length: n }).reduce( 4 | (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), 5 | [] 6 | ); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/findLastIndex.txt: -------------------------------------------------------------------------------- 1 | 2 | const findLastIndex = (arr, fn) => 3 | (arr 4 | .map((val, i) => [i, val]) 5 | .filter(([i, val]) => fn(val, i, arr)) 6 | .pop() || [-1])[0]; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/isPromiseLike.txt: -------------------------------------------------------------------------------- 1 | 2 | const isPromiseLike = obj => 3 | obj !== null && 4 | (typeof obj === 'object' || typeof obj === 'function') && 5 | typeof obj.then === 'function'; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/isValidJSON.txt: -------------------------------------------------------------------------------- 1 | 2 | const isValidJSON = str => { 3 | try { 4 | JSON.parse(str); 5 | return true; 6 | } catch (e) { 7 | return false; 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/lowercaseKeys.txt: -------------------------------------------------------------------------------- 1 | 2 | const lowercaseKeys = obj => 3 | Object.keys(obj).reduce((acc, key) => { 4 | acc[key.toLowerCase()] = obj[key]; 5 | return acc; 6 | }, {}); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/mapObject.txt: -------------------------------------------------------------------------------- 1 | 2 | const mapObject = (arr, fn) => 3 | (a => ( 4 | (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) 5 | ))(); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/promisify.txt: -------------------------------------------------------------------------------- 1 | const promisify = func => (...args) => 2 | new Promise((resolve, reject) => 3 | func(...args, (err, result) => (err ? reject(err) : resolve(result))) 4 | ); 5 | -------------------------------------------------------------------------------- /giron/tests/snippets/readFileLines.txt: -------------------------------------------------------------------------------- 1 | 2 | const fs = require('fs'); 3 | const readFileLines = filename => 4 | fs 5 | .readFileSync(filename) 6 | .toString('UTF8') 7 | .split('\n'); 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/uniqueSymmetricDifference.txt: -------------------------------------------------------------------------------- 1 | 2 | const uniqueSymmetricDifference = (a, b) => [ 3 | ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))]) 4 | ]; 5 | -------------------------------------------------------------------------------- /giron/tests/snippets/attempt.txt: -------------------------------------------------------------------------------- 1 | 2 | const attempt = (fn, ...args) => { 3 | try { 4 | return fn(...args); 5 | } catch (e) { 6 | return e instanceof Error ? e : new Error(e); 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/shank.txt: -------------------------------------------------------------------------------- 1 | 2 | const shank = (arr, index = 0, delCount = 0, ...elements) => 3 | arr 4 | .slice(0, index) 5 | .concat(elements) 6 | .concat(arr.slice(index + delCount)); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/unfold.txt: -------------------------------------------------------------------------------- 1 | 2 | const unfold = (fn, seed) => { 3 | let result = [], 4 | val = [null, seed]; 5 | while ((val = fn(val[1]))) result.push(val[0]); 6 | return result; 7 | }; 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/uniqueElementsBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const uniqueElementsBy = (arr, fn) => 3 | arr.reduce((acc, v) => { 4 | if (!acc.some(x => fn(v, x))) acc.push(v); 5 | return acc; 6 | }, []); 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - stable 4 | - beta 5 | jobs: 6 | fast_finish: true 7 | cache: cargo 8 | script: 9 | - cargo build --verbose --all 10 | - cargo test --verbose --all 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/arrayToCSV.txt: -------------------------------------------------------------------------------- 1 | 2 | const arrayToCSV = (arr, delimiter = ',') => 3 | arr 4 | .map(v => v.map(x => (isNaN(x) ? `"${x.replace(/"/g, '""')}"` : x)).join(delimiter)) 5 | .join('\n'); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/extendHex.txt: -------------------------------------------------------------------------------- 1 | 2 | const extendHex = shortHex => 3 | '#' + 4 | shortHex 5 | .slice(shortHex.startsWith('#') ? 1 : 0) 6 | .split('') 7 | .map(x => x + x) 8 | .join(''); 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/detectDeviceType.txt: -------------------------------------------------------------------------------- 1 | 2 | const detectDeviceType = () => 3 | /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) 4 | ? 'Mobile' 5 | : 'Desktop'; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/initializeArrayWithRange.txt: -------------------------------------------------------------------------------- 1 | 2 | const initializeArrayWithRange = (end, start = 0, step = 1) => 3 | Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start); 4 | -------------------------------------------------------------------------------- /giron/tests/snippets/nest.txt: -------------------------------------------------------------------------------- 1 | 2 | const nest = (items, id = null, link = 'parent_id') => 3 | items 4 | .filter(item => item[link] === id) 5 | .map(item => ({ ...item, children: nest(items, item.id) })); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/sumPower.txt: -------------------------------------------------------------------------------- 1 | 2 | const sumPower = (end, power = 2, start = 1) => 3 | Array(end + 1 - start) 4 | .fill(0) 5 | .map((x, i) => (i + start) ** power) 6 | .reduce((a, b) => a + b, 0); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/inRange.txt: -------------------------------------------------------------------------------- 1 | 2 | const inRange = (n, start, end = null) => { 3 | if (end && start > end) [end, start] = [start, end]; 4 | return end == null ? n >= 0 && n < start : n >= start && n < end; 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/isPrime.txt: -------------------------------------------------------------------------------- 1 | 2 | const isPrime = num => { 3 | const boundary = Math.floor(Math.sqrt(num)); 4 | for (var i = 2; i <= boundary; i++) if (num % i === 0) return false; 5 | return num >= 2; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/toHash.txt: -------------------------------------------------------------------------------- 1 | 2 | const toHash = (object, key) => 3 | Array.prototype.reduce.call( 4 | object, 5 | (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc), 6 | {} 7 | ); 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/uniqueElementsByRight.txt: -------------------------------------------------------------------------------- 1 | 2 | const uniqueElementsByRight = (arr, fn) => 3 | arr.reduceRight((acc, v) => { 4 | if (!acc.some(x => fn(v, x))) acc.push(v); 5 | return acc; 6 | }, []); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/bottomVisible.txt: -------------------------------------------------------------------------------- 1 | 2 | const bottomVisible = () => 3 | document.documentElement.clientHeight + window.scrollY >= 4 | (document.documentElement.scrollHeight || document.documentElement.clientHeight); 5 | -------------------------------------------------------------------------------- /giron/tests/snippets/dropRightWhile.txt: -------------------------------------------------------------------------------- 1 | 2 | const dropRightWhile = (arr, func) => { 3 | let rightIndex = arr.length; 4 | while (rightIndex-- && !func(arr[rightIndex])); 5 | return arr.slice(0, rightIndex + 1); 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/initializeNDArray.txt: -------------------------------------------------------------------------------- 1 | 2 | const initializeNDArray = (val, ...args) => 3 | args.length === 0 4 | ? val 5 | : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/lcm.txt: -------------------------------------------------------------------------------- 1 | 2 | const lcm = (...arr) => { 3 | const gcd = (x, y) => (!y ? x : gcd(y, x % y)); 4 | const _lcm = (x, y) => (x * y) / gcd(x, y); 5 | return [...arr].reduce((a, b) => _lcm(a, b)); 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/countBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const countBy = (arr, fn) => 3 | arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => { 4 | acc[val] = (acc[val] || 0) + 1; 5 | return acc; 6 | }, {}); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/once.txt: -------------------------------------------------------------------------------- 1 | 2 | const once = fn => { 3 | let called = false; 4 | return function(...args) { 5 | if (called) return; 6 | called = true; 7 | return fn.apply(this, args); 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/reducedFilter.txt: -------------------------------------------------------------------------------- 1 | 2 | const reducedFilter = (data, keys, fn) => 3 | data.filter(fn).map(el => 4 | keys.reduce((acc, key) => { 5 | acc[key] = el[key]; 6 | return acc; 7 | }, {}) 8 | ); 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/symmetricDifference.txt: -------------------------------------------------------------------------------- 1 | 2 | const symmetricDifference = (a, b) => { 3 | const sA = new Set(a), 4 | sB = new Set(b); 5 | return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/formToObject.txt: -------------------------------------------------------------------------------- 1 | 2 | const formToObject = form => 3 | Array.from(new FormData(form)).reduce( 4 | (acc, [key, value]) => ({ 5 | ...acc, 6 | [key]: value 7 | }), 8 | {} 9 | ); 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/hz.txt: -------------------------------------------------------------------------------- 1 | 2 | const hz = (fn, iterations = 100) => { 3 | const before = performance.now(); 4 | for (let i = 0; i < iterations; i++) fn(); 5 | return (1000 * iterations) / (performance.now() - before); 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/toKebabCase.txt: -------------------------------------------------------------------------------- 1 | 2 | const toKebabCase = str => 3 | str && 4 | str 5 | .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) 6 | .map(x => x.toLowerCase()) 7 | .join('-'); 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/toSnakeCase.txt: -------------------------------------------------------------------------------- 1 | 2 | const toSnakeCase = str => 3 | str && 4 | str 5 | .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) 6 | .map(x => x.toLowerCase()) 7 | .join('_'); 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/CSVToArray.txt: -------------------------------------------------------------------------------- 1 | 2 | const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => 3 | data 4 | .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) 5 | .split('\n') 6 | .map(v => v.split(delimiter)); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/arrayToHtmlList.txt: -------------------------------------------------------------------------------- 1 | 2 | const arrayToHtmlList = (arr, listID) => 3 | (el => ( 4 | (el = document.querySelector('#' + listID)), 5 | (el.innerHTML += arr.map(item => `
  • ${item}
  • `).join('')) 6 | ))(); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/deepFreeze.txt: -------------------------------------------------------------------------------- 1 | 2 | const deepFreeze = obj => 3 | Object.keys(obj).forEach(prop => 4 | !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop]) 5 | ) || Object.freeze(obj); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/partition.txt: -------------------------------------------------------------------------------- 1 | 2 | const partition = (arr, fn) => 3 | arr.reduce( 4 | (acc, val, i, arr) => { 5 | acc[fn(val, i, arr) ? 0 : 1].push(val); 6 | return acc; 7 | }, 8 | [[], []] 9 | ); 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/bindAll.txt: -------------------------------------------------------------------------------- 1 | 2 | const bindAll = (obj, ...fns) => 3 | fns.forEach( 4 | fn => ( 5 | (f = obj[fn]), 6 | (obj[fn] = function() { 7 | return f.apply(obj); 8 | }) 9 | ) 10 | ); 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/debounce.txt: -------------------------------------------------------------------------------- 1 | 2 | const debounce = (fn, ms = 0) => { 3 | let timeoutId; 4 | return function(...args) { 5 | clearTimeout(timeoutId); 6 | timeoutId = setTimeout(() => fn.apply(this, args), ms); 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/geometricProgression.txt: -------------------------------------------------------------------------------- 1 | 2 | const geometricProgression = (end, start = 1, step = 2) => 3 | Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map( 4 | (v, i) => start * step ** i 5 | ); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/getScrollPosition.txt: -------------------------------------------------------------------------------- 1 | 2 | const getScrollPosition = (el = window) => ({ 3 | x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, 4 | y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop 5 | }); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/getURLParameters.txt: -------------------------------------------------------------------------------- 1 | 2 | const getURLParameters = url => 3 | (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( 4 | (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), 5 | {} 6 | ); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/groupBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const groupBy = (arr, fn) => 3 | arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => { 4 | acc[val] = (acc[val] || []).concat(arr[i]); 5 | return acc; 6 | }, {}); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/median.txt: -------------------------------------------------------------------------------- 1 | 2 | const median = arr => { 3 | const mid = Math.floor(arr.length / 2), 4 | nums = [...arr].sort((a, b) => a - b); 5 | return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/renameKeys.txt: -------------------------------------------------------------------------------- 1 | 2 | const renameKeys = (keysMap, obj) => 3 | Object.keys(obj).reduce( 4 | (acc, key) => ({ 5 | ...acc, 6 | ...{ [keysMap[key] || key]: obj[key] } 7 | }), 8 | {} 9 | ); 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/stableSort.txt: -------------------------------------------------------------------------------- 1 | 2 | const stableSort = (arr, compare) => 3 | arr 4 | .map((item, index) => ({ item, index })) 5 | .sort((a, b) => compare(a.item, b.item) || a.index - b.index) 6 | .map(({ item }) => item); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/symmetricDifferenceWith.txt: -------------------------------------------------------------------------------- 1 | 2 | const symmetricDifferenceWith = (arr, val, comp) => [ 3 | ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), 4 | ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1) 5 | ]; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/toTitleCase.txt: -------------------------------------------------------------------------------- 1 | 2 | const toTitleCase = str => 3 | str 4 | .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) 5 | .map(x => x.charAt(0).toUpperCase() + x.slice(1)) 6 | .join(' '); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/factorial.txt: -------------------------------------------------------------------------------- 1 | 2 | const factorial = n => 3 | n < 0 4 | ? (() => { 5 | throw new TypeError('Negative numbers are not allowed!'); 6 | })() 7 | : n <= 1 8 | ? 1 9 | : n * factorial(n - 1); 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/haveSameContents.txt: -------------------------------------------------------------------------------- 1 | 2 | const haveSameContents = (a, b) => { 3 | for (const v of new Set([...a, ...b])) 4 | if (a.filter(e => e === v).length !== b.filter(e => e === v).length) return false; 5 | return true; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/UUIDGeneratorBrowser.txt: -------------------------------------------------------------------------------- 1 | 2 | const UUIDGeneratorBrowser = () => 3 | ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => 4 | (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) 5 | ); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/shuffle.txt: -------------------------------------------------------------------------------- 1 | 2 | const shuffle = ([...arr]) => { 3 | let m = arr.length; 4 | while (m) { 5 | const i = Math.floor(Math.random() * m--); 6 | [arr[m], arr[i]] = [arr[i], arr[m]]; 7 | } 8 | return arr; 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/unzip.txt: -------------------------------------------------------------------------------- 1 | 2 | const unzip = arr => 3 | arr.reduce( 4 | (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), 5 | Array.from({ 6 | length: Math.max(...arr.map(x => x.length)) 7 | }).map(x => []) 8 | ); 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/fromCamelCase.txt: -------------------------------------------------------------------------------- 1 | 2 | const fromCamelCase = (str, separator = '_') => 3 | str 4 | .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') 5 | .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2') 6 | .toLowerCase(); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/getImages.txt: -------------------------------------------------------------------------------- 1 | 2 | const getImages = (el, includeDuplicates = false) => { 3 | const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src')); 4 | return includeDuplicates ? images : [...new Set(images)]; 5 | }; 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/pull.txt: -------------------------------------------------------------------------------- 1 | 2 | const pull = (arr, ...args) => { 3 | let argState = Array.isArray(args[0]) ? args[0] : args; 4 | let pulled = arr.filter(v => !argState.includes(v)); 5 | arr.length = 0; 6 | pulled.forEach(v => arr.push(v)); 7 | }; 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/UUIDGeneratorNode.txt: -------------------------------------------------------------------------------- 1 | 2 | const crypto = require('crypto'); 3 | const UUIDGeneratorNode = () => 4 | ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => 5 | (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) 6 | ); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/functions.txt: -------------------------------------------------------------------------------- 1 | 2 | const functions = (obj, inherited = false) => 3 | (inherited 4 | ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))] 5 | : Object.keys(obj) 6 | ).filter(key => typeof obj[key] === 'function'); 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/isReadableStream.txt: -------------------------------------------------------------------------------- 1 | 2 | const isReadableStream = val => 3 | val !== null && 4 | typeof val === 'object' && 5 | typeof val.pipe === 'function' && 6 | typeof val._read === 'function' && 7 | typeof val._readableState === 'object'; 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/isWritableStream.txt: -------------------------------------------------------------------------------- 1 | 2 | const isWritableStream = val => 3 | val !== null && 4 | typeof val === 'object' && 5 | typeof val.pipe === 'function' && 6 | typeof val._write === 'function' && 7 | typeof val._writableState === 'object'; 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/matchesWith.txt: -------------------------------------------------------------------------------- 1 | 2 | const matchesWith = (obj, source, fn) => 3 | Object.keys(source).every(key => 4 | obj.hasOwnProperty(key) && fn 5 | ? fn(obj[key], source[key], key, obj, source) 6 | : obj[key] == source[key] 7 | ); 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/mostFrequent.txt: -------------------------------------------------------------------------------- 1 | 2 | const mostFrequent = arr => 3 | Object.entries( 4 | arr.reduce((a, v) => { 5 | a[v] = a[v] ? a[v] + 1 : 1; 6 | return a; 7 | }, {}) 8 | ).reduce((a, v) => (v[1] >= a[1] ? v : a), [null, 0])[0]; 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/remove.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | const remove = (arr, func) => 4 | Array.isArray(arr) 5 | ? arr.filter(func).reduce((acc, val) => { 6 | arr.splice(arr.indexOf(val), 1); 7 | return acc.concat(val); 8 | }, []) 9 | : []; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/sortedIndex.txt: -------------------------------------------------------------------------------- 1 | 2 | const sortedIndex = (arr, n) => { 3 | const isDescending = arr[0] > arr[arr.length - 1]; 4 | const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); 5 | return index === -1 ? arr.length : index; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/chainAsync.txt: -------------------------------------------------------------------------------- 1 | 2 | const chainAsync = fns => { 3 | let curr = 0; 4 | const last = fns[fns.length - 1]; 5 | const next = () => { 6 | const fn = fns[curr++]; 7 | fn === last ? fn() : fn(next); 8 | }; 9 | next(); 10 | }; 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/initializeArrayWithRangeRight.txt: -------------------------------------------------------------------------------- 1 | 2 | const initializeArrayWithRangeRight = (end, start = 0, step = 1) => 3 | Array.from({ length: Math.ceil((end + 1 - start) / step) }).map( 4 | (v, i, arr) => (arr.length - i - 1) * step + start 5 | ); 6 | -------------------------------------------------------------------------------- /giron/tests/snippets/isContainedIn.txt: -------------------------------------------------------------------------------- 1 | 2 | const isContainedIn = (a, b) => { 3 | for (const v of new Set(a)) { 4 | if (!b.some(e => e === v) || a.filter(e => e === v).length > b.filter(e => e === v).length) 5 | return false; 6 | } 7 | return true; 8 | }; 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/scrollToTop.txt: -------------------------------------------------------------------------------- 1 | 2 | const scrollToTop = () => { 3 | const c = document.documentElement.scrollTop || document.body.scrollTop; 4 | if (c > 0) { 5 | window.requestAnimationFrame(scrollToTop); 6 | window.scrollTo(0, c - c / 8); 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/symmetricDifferenceBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const symmetricDifferenceBy = (a, b, fn) => { 3 | const sA = new Set(a.map(v => fn(v))), 4 | sB = new Set(b.map(v => fn(v))); 5 | return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/uncurry.txt: -------------------------------------------------------------------------------- 1 | 2 | const uncurry = (fn, n = 1) => (...args) => { 3 | const next = acc => args => args.reduce((x, y) => x(y), acc); 4 | if (n > args.length) throw new RangeError('Arguments too few!'); 5 | return next(fn)(args.slice(0, n)); 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/invertKeyValues.txt: -------------------------------------------------------------------------------- 1 | 2 | const invertKeyValues = (obj, fn) => 3 | Object.keys(obj).reduce((acc, key) => { 4 | const val = fn ? fn(obj[key]) : obj[key]; 5 | acc[val] = acc[val] || []; 6 | acc[val].push(key); 7 | return acc; 8 | }, {}); 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/sampleSize.txt: -------------------------------------------------------------------------------- 1 | 2 | const sampleSize = ([...arr], n = 1) => { 3 | let m = arr.length; 4 | while (m) { 5 | const i = Math.floor(Math.random() * m--); 6 | [arr[m], arr[i]] = [arr[i], arr[m]]; 7 | } 8 | return arr.slice(0, n); 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/sdbm.txt: -------------------------------------------------------------------------------- 1 | 2 | const sdbm = str => { 3 | let arr = str.split(''); 4 | return arr.reduce( 5 | (hashCode, currentVal) => 6 | (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode), 7 | 0 8 | ); 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/zip.txt: -------------------------------------------------------------------------------- 1 | 2 | const zip = (...arrays) => { 3 | const maxLength = Math.max(...arrays.map(x => x.length)); 4 | return Array.from({ length: maxLength }).map((_, i) => { 5 | return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/dig.txt: -------------------------------------------------------------------------------- 1 | 2 | const dig = (obj, target) => 3 | target in obj 4 | ? obj[target] 5 | : Object.values(obj).reduce((acc, val) => { 6 | if (acc !== undefined) return acc; 7 | if (typeof val === 'object') return dig(val, target); 8 | }, undefined); 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/get.txt: -------------------------------------------------------------------------------- 1 | 2 | const get = (from, ...selectors) => 3 | [...selectors].map(s => 4 | s 5 | .replace(/\[([^\[\]]*)\]/g, '.$1.') 6 | .split('.') 7 | .filter(t => t !== '') 8 | .reduce((prev, cur) => prev && prev[cur], from) 9 | ); 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/size.txt: -------------------------------------------------------------------------------- 1 | 2 | const size = val => 3 | Array.isArray(val) 4 | ? val.length 5 | : val && typeof val === 'object' 6 | ? val.size || val.length || Object.keys(val).length 7 | : typeof val === 'string' 8 | ? new Blob([val]).size 9 | : 0; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/sortedLastIndex.txt: -------------------------------------------------------------------------------- 1 | 2 | const sortedLastIndex = (arr, n) => { 3 | const isDescending = arr[0] > arr[arr.length - 1]; 4 | const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el)); 5 | return index === -1 ? 0 : arr.length - index; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/getMeridiemSuffixOfInteger.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | const getMeridiemSuffixOfInteger = num => 4 | num === 0 || num === 24 5 | ? 12 + 'am' 6 | : num === 12 7 | ? 12 + 'pm' 8 | : num < 12 9 | ? (num % 12) + 'am' 10 | : (num % 12) + 'pm'; 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/parseCookie.txt: -------------------------------------------------------------------------------- 1 | 2 | const parseCookie = str => 3 | str 4 | .split(';') 5 | .map(v => v.split('=')) 6 | .reduce((acc, v) => { 7 | acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); 8 | return acc; 9 | }, {}); 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/on.txt: -------------------------------------------------------------------------------- 1 | 2 | const on = (el, evt, fn, opts = {}) => { 3 | const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e); 4 | el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); 5 | if (opts.target) return delegatorFn; 6 | }; 7 | -------------------------------------------------------------------------------- /giron/tests/snippets/escapeHTML.txt: -------------------------------------------------------------------------------- 1 | 2 | const escapeHTML = str => 3 | str.replace( 4 | /[&<>'"]/g, 5 | tag => 6 | ({ 7 | '&': '&', 8 | '<': '<', 9 | '>': '>', 10 | "'": ''', 11 | '"': '"' 12 | }[tag] || tag) 13 | ); 14 | -------------------------------------------------------------------------------- /giron/tests/snippets/hasKey.txt: -------------------------------------------------------------------------------- 1 | 2 | const hasKey = (obj, keys) => { 3 | return ( 4 | keys.length > 0 && 5 | keys.every(key => { 6 | if (typeof obj !== 'object' || !obj.hasOwnProperty(key)) return false; 7 | obj = obj[key]; 8 | return true; 9 | }) 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/memoize.txt: -------------------------------------------------------------------------------- 1 | 2 | const memoize = fn => { 3 | const cache = new Map(); 4 | const cached = function(val) { 5 | return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val); 6 | }; 7 | cached.cache = cache; 8 | return cached; 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/URLJoin.txt: -------------------------------------------------------------------------------- 1 | 2 | const URLJoin = (...args) => 3 | args 4 | .join('/') 5 | .replace(/[\/]+/g, '/') 6 | .replace(/^(.+):\//, '$1://') 7 | .replace(/^file:/, 'file:/') 8 | .replace(/\/(\?|&|#[^!])/g, '$1') 9 | .replace(/\?/g, '&') 10 | .replace('&', '?'); 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/httpGet.txt: -------------------------------------------------------------------------------- 1 | 2 | const httpGet = (url, callback, err = console.error) => { 3 | const request = new XMLHttpRequest(); 4 | request.open('GET', url, true); 5 | request.onload = () => callback(request.responseText); 6 | request.onerror = () => err(request); 7 | request.send(); 8 | }; 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/isAnagram.txt: -------------------------------------------------------------------------------- 1 | 2 | const isAnagram = (str1, str2) => { 3 | const normalize = str => 4 | str 5 | .toLowerCase() 6 | .replace(/[^a-z0-9]/gi, '') 7 | .split('') 8 | .sort() 9 | .join(''); 10 | return normalize(str1) === normalize(str2); 11 | }; 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/merge.txt: -------------------------------------------------------------------------------- 1 | 2 | const merge = (...objs) => 3 | [...objs].reduce( 4 | (acc, obj) => 5 | Object.keys(obj).reduce((a, k) => { 6 | acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k]; 7 | return acc; 8 | }, {}), 9 | {} 10 | ); 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/sortedIndexBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const sortedIndexBy = (arr, n, fn) => { 3 | const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); 4 | const val = fn(n); 5 | const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); 6 | return index === -1 ? arr.length : index; 7 | }; 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/vectorDistance.txt: -------------------------------------------------------------------------------- 1 | 2 | const vectorDistance = (...coords) => { 3 | let pointLength = Math.trunc(coords.length / 2); 4 | let sum = coords 5 | .slice(0, pointLength) 6 | .reduce((acc, val, i) => acc + Math.pow(val - coords[pointLength + i], 2), 0); 7 | return Math.sqrt(sum); 8 | }; 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/join.txt: -------------------------------------------------------------------------------- 1 | 2 | const join = (arr, separator = ',', end = separator) => 3 | arr.reduce( 4 | (acc, val, i) => 5 | i === arr.length - 2 6 | ? acc + val + end 7 | : i === arr.length - 1 8 | ? acc + val 9 | : acc + val + separator, 10 | '' 11 | ); 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/zipWith.txt: -------------------------------------------------------------------------------- 1 | 2 | const zipWith = (...array) => { 3 | const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined; 4 | return Array.from({ length: Math.max(...array.map(a => a.length)) }, (_, i) => 5 | fn ? fn(...array.map(a => a[i])) : array.map(a => a[i]) 6 | ); 7 | }; 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/unzipWith.txt: -------------------------------------------------------------------------------- 1 | 2 | const unzipWith = (arr, fn) => 3 | arr 4 | .reduce( 5 | (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), 6 | Array.from({ 7 | length: Math.max(...arr.map(x => x.length)) 8 | }).map(x => []) 9 | ) 10 | .map(val => fn(...val)); 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/unescapeHTML.txt: -------------------------------------------------------------------------------- 1 | 2 | const unescapeHTML = str => 3 | str.replace( 4 | /&|<|>|'|"/g, 5 | tag => 6 | ({ 7 | '&': '&', 8 | '<': '<', 9 | '>': '>', 10 | ''': "'", 11 | '"': '"' 12 | }[tag] || tag) 13 | ); 14 | -------------------------------------------------------------------------------- /giron-wasm/tests/web.rs: -------------------------------------------------------------------------------- 1 | //! Test suite for the Web and headless browsers. 2 | 3 | #![cfg(target_arch = "wasm32")] 4 | 5 | extern crate wasm_bindgen_test; 6 | use wasm_bindgen_test::*; 7 | 8 | wasm_bindgen_test_configure!(run_in_browser); 9 | 10 | #[wasm_bindgen_test] 11 | fn pass() { 12 | assert_eq!(1 + 1, 2); 13 | } 14 | -------------------------------------------------------------------------------- /giron/tests/snippets/flattenObject.txt: -------------------------------------------------------------------------------- 1 | 2 | const flattenObject = (obj, prefix = '') => 3 | Object.keys(obj).reduce((acc, k) => { 4 | const pre = prefix.length ? prefix + '.' : ''; 5 | if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k)); 6 | else acc[pre + k] = obj[k]; 7 | return acc; 8 | }, {}); 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/mostPerformant.txt: -------------------------------------------------------------------------------- 1 | 2 | const mostPerformant = (fns, iterations = 10000) => { 3 | const times = fns.map(fn => { 4 | const before = performance.now(); 5 | for (let i = 0; i < iterations; i++) fn(); 6 | return performance.now() - before; 7 | }); 8 | return times.indexOf(Math.min(...times)); 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/pullAtIndex.txt: -------------------------------------------------------------------------------- 1 | 2 | const pullAtIndex = (arr, pullArr) => { 3 | let removed = []; 4 | let pulled = arr 5 | .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v)) 6 | .filter((v, i) => !pullArr.includes(i)); 7 | arr.length = 0; 8 | pulled.forEach(v => arr.push(v)); 9 | return removed; 10 | }; 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/weightedSample.txt: -------------------------------------------------------------------------------- 1 | 2 | const weightedSample = (arr, weights) => { 3 | let roll = Math.random(); 4 | return arr[ 5 | weights 6 | .reduce((acc, w, i) => (i === 0 ? [w] : [...acc, acc[acc.length - 1] + w]), []) 7 | .findIndex((v, i, s) => roll >= (i === 0 ? 0 : s[i - 1]) && roll < v) 8 | ]; 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/JSONtoCSV.txt: -------------------------------------------------------------------------------- 1 | 2 | const JSONtoCSV = (arr, columns, delimiter = ',') => 3 | [ 4 | columns.join(delimiter), 5 | ...arr.map(obj => 6 | columns.reduce( 7 | (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, 8 | '' 9 | ) 10 | ) 11 | ].join('\n'); 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/pluralize.txt: -------------------------------------------------------------------------------- 1 | 2 | const pluralize = (val, word, plural = word + 's') => { 3 | const _pluralize = (num, word, plural = word + 's') => 4 | [1, -1].includes(Number(num)) ? word : plural; 5 | if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]); 6 | return _pluralize(val, word, plural); 7 | }; 8 | -------------------------------------------------------------------------------- /giron/tests/snippets/isDuplexStream.txt: -------------------------------------------------------------------------------- 1 | 2 | const isDuplexStream = val => 3 | val !== null && 4 | typeof val === 'object' && 5 | typeof val.pipe === 'function' && 6 | typeof val._read === 'function' && 7 | typeof val._readableState === 'object' && 8 | typeof val._write === 'function' && 9 | typeof val._writableState === 'object'; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/pullAtValue.txt: -------------------------------------------------------------------------------- 1 | 2 | const pullAtValue = (arr, pullArr) => { 3 | let removed = [], 4 | pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)), 5 | mutateTo = arr.filter((v, i) => !pullArr.includes(v)); 6 | arr.length = 0; 7 | mutateTo.forEach(v => arr.push(v)); 8 | return removed; 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/hashNode.txt: -------------------------------------------------------------------------------- 1 | 2 | const crypto = require('crypto'); 3 | const hashNode = val => 4 | new Promise(resolve => 5 | setTimeout( 6 | () => 7 | resolve( 8 | crypto 9 | .createHash('sha256') 10 | .update(val) 11 | .digest('hex') 12 | ), 13 | 0 14 | ) 15 | ); 16 | -------------------------------------------------------------------------------- /giron/tests/snippets/primes.txt: -------------------------------------------------------------------------------- 1 | 2 | const primes = num => { 3 | let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2), 4 | sqroot = Math.floor(Math.sqrt(num)), 5 | numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2); 6 | numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x))); 7 | return arr; 8 | }; 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/toCamelCase.txt: -------------------------------------------------------------------------------- 1 | 2 | const toCamelCase = str => { 3 | let s = 4 | str && 5 | str 6 | .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) 7 | .map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase()) 8 | .join(''); 9 | return s.slice(0, 1).toLowerCase() + s.slice(1); 10 | }; 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/standardDeviation.txt: -------------------------------------------------------------------------------- 1 | 2 | const standardDeviation = (arr, usePopulation = false) => { 3 | const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; 4 | return Math.sqrt( 5 | arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) / 6 | (arr.length - (usePopulation ? 0 : 1)) 7 | ); 8 | }; 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/isSorted.txt: -------------------------------------------------------------------------------- 1 | 2 | const isSorted = arr => { 3 | let direction = -(arr[0] - arr[1]); 4 | for (let [i, val] of arr.entries()) { 5 | direction = !direction ? -(arr[i - 1] - arr[i]) : direction; 6 | if (i === arr.length - 1) return !direction ? 0 : direction; 7 | else if ((val - arr[i + 1]) * direction > 0) return 0; 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/permutations.txt: -------------------------------------------------------------------------------- 1 | 2 | const permutations = arr => { 3 | if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr; 4 | return arr.reduce( 5 | (acc, item, i) => 6 | acc.concat( 7 | permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [item, ...val]) 8 | ), 9 | [] 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/sortedLastIndexBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const sortedLastIndexBy = (arr, n, fn) => { 3 | const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); 4 | const val = fn(n); 5 | const index = arr 6 | .map(fn) 7 | .reverse() 8 | .findIndex(el => (isDescending ? val <= el : val >= el)); 9 | return index === -1 ? 0 : arr.length - index; 10 | }; 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/luhnCheck.txt: -------------------------------------------------------------------------------- 1 | 2 | const luhnCheck = num => { 3 | let arr = (num + '') 4 | .split('') 5 | .reverse() 6 | .map(x => parseInt(x)); 7 | let lastDigit = arr.splice(0, 1)[0]; 8 | let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0); 9 | sum += lastDigit; 10 | return sum % 10 === 0; 11 | }; 12 | -------------------------------------------------------------------------------- /giron/src/span/span.rs: -------------------------------------------------------------------------------- 1 | use serde::Serialize; 2 | 3 | #[derive(Serialize, Debug, Clone)] 4 | #[serde(tag = "type")] 5 | pub struct Marker { 6 | pub line: usize, 7 | pub col: usize, 8 | pub idx: usize, 9 | } 10 | 11 | #[derive(Serialize, Debug, Clone)] 12 | #[serde(tag = "type")] 13 | pub struct Span { 14 | pub start: Marker, 15 | pub end: Marker, 16 | } 17 | -------------------------------------------------------------------------------- /giron/tests/snippets/hashBrowser.txt: -------------------------------------------------------------------------------- 1 | 2 | const hashBrowser = val => 3 | crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => { 4 | let hexes = [], 5 | view = new DataView(h); 6 | for (let i = 0; i < view.byteLength; i += 4) 7 | hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8)); 8 | return hexes.join(''); 9 | }); 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/orderBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const orderBy = (arr, props, orders) => 3 | [...arr].sort((a, b) => 4 | props.reduce((acc, prop, i) => { 5 | if (acc === 0) { 6 | const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]]; 7 | acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0; 8 | } 9 | return acc; 10 | }, 0) 11 | ); 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/stringPermutations.txt: -------------------------------------------------------------------------------- 1 | 2 | const stringPermutations = str => { 3 | if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; 4 | return str 5 | .split('') 6 | .reduce( 7 | (acc, letter, i) => 8 | acc.concat(stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), 9 | [] 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/httpPost.txt: -------------------------------------------------------------------------------- 1 | 2 | const httpPost = (url, data, callback, err = console.error) => { 3 | const request = new XMLHttpRequest(); 4 | request.open('POST', url, true); 5 | request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); 6 | request.onload = () => callback(request.responseText); 7 | request.onerror = () => err(request); 8 | request.send(data); 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/CSVToJSON.txt: -------------------------------------------------------------------------------- 1 | 2 | const CSVToJSON = (data, delimiter = ',') => { 3 | const titles = data.slice(0, data.indexOf('\n')).split(delimiter); 4 | return data 5 | .slice(data.indexOf('\n') + 1) 6 | .split('\n') 7 | .map(v => { 8 | const values = v.split(delimiter); 9 | return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/binomialCoefficient.txt: -------------------------------------------------------------------------------- 1 | 2 | const binomialCoefficient = (n, k) => { 3 | if (Number.isNaN(n) || Number.isNaN(k)) return NaN; 4 | if (k < 0 || k > n) return 0; 5 | if (k === 0 || k === n) return 1; 6 | if (k === 1 || k === n - 1) return n; 7 | if (n - k < k) k = n - k; 8 | let res = n; 9 | for (let j = 2; j <= k; j++) res *= (n - j + 1) / j; 10 | return Math.round(res); 11 | }; 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/objectToQueryString.txt: -------------------------------------------------------------------------------- 1 | 2 | const objectToQueryString = queryParameters => { 3 | return queryParameters 4 | ? Object.entries(queryParameters).reduce((queryString, [key, val], index) => { 5 | const symbol = queryString.length === 0 ? '?' : '&'; 6 | queryString += typeof val === 'string' ? `${symbol}${key}=${val}` : ''; 7 | return queryString; 8 | }, '') 9 | : ''; 10 | }; 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/prefix.txt: -------------------------------------------------------------------------------- 1 | 2 | const prefix = prop => { 3 | const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1); 4 | const prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 5 | const i = prefixes.findIndex( 6 | prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined' 7 | ); 8 | return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null; 9 | }; 10 | -------------------------------------------------------------------------------- /giron/tests/snippets/toOrdinalSuffix.txt: -------------------------------------------------------------------------------- 1 | 2 | const toOrdinalSuffix = num => { 3 | const int = parseInt(num), 4 | digits = [int % 10, int % 100], 5 | ordinals = ['st', 'nd', 'rd', 'th'], 6 | oPattern = [1, 2, 3, 4], 7 | tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19]; 8 | return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) 9 | ? int + ordinals[digits[0] - 1] 10 | : int + ordinals[3]; 11 | }; 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/pullBy.txt: -------------------------------------------------------------------------------- 1 | 2 | const pullBy = (arr, ...args) => { 3 | const length = args.length; 4 | let fn = length > 1 ? args[length - 1] : undefined; 5 | fn = typeof fn == 'function' ? (args.pop(), fn) : undefined; 6 | let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val)); 7 | let pulled = arr.filter((v, i) => !argState.includes(fn(v))); 8 | arr.length = 0; 9 | pulled.forEach(v => arr.push(v)); 10 | }; 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/deepMapKeys.txt: -------------------------------------------------------------------------------- 1 | 2 | const deepMapKeys = (obj, f) => 3 | Array.isArray(obj) 4 | ? obj.map(val => deepMapKeys(val, f)) 5 | : typeof obj === 'object' 6 | ? Object.keys(obj).reduce((acc, current) => { 7 | const val = obj[current]; 8 | acc[f(current)] = 9 | val !== null && typeof val === 'object' ? deepMapKeys(val, f) : (acc[f(current)] = val); 10 | return acc; 11 | }, {}) 12 | : obj; 13 | -------------------------------------------------------------------------------- /giron/tests/snippets/deepClone.txt: -------------------------------------------------------------------------------- 1 | 2 | const deepClone = obj => { 3 | if (obj === null) return null; 4 | let clone = Object.assign({}, obj); 5 | Object.keys(clone).forEach( 6 | key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) 7 | ); 8 | return Array.isArray(obj) && obj.length 9 | ? (clone.length = obj.length) && Array.from(clone) 10 | : Array.isArray(obj) 11 | ? Array.from(obj) 12 | : clone; 13 | }; 14 | -------------------------------------------------------------------------------- /giron/tests/snippets/equals.txt: -------------------------------------------------------------------------------- 1 | 2 | const equals = (a, b) => { 3 | if (a === b) return true; 4 | if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); 5 | if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b; 6 | if (a.prototype !== b.prototype) return false; 7 | let keys = Object.keys(a); 8 | if (keys.length !== Object.keys(b).length) return false; 9 | return keys.every(k => equals(a[k], b[k])); 10 | }; 11 | -------------------------------------------------------------------------------- /giron/tests/snippets/runAsync.txt: -------------------------------------------------------------------------------- 1 | 2 | const runAsync = fn => { 3 | const worker = new Worker( 4 | URL.createObjectURL(new Blob([`postMessage((${fn})());`]), { 5 | type: 'application/javascript; charset=utf-8' 6 | }) 7 | ); 8 | return new Promise((res, rej) => { 9 | worker.onmessage = ({ data }) => { 10 | res(data), worker.terminate(); 11 | }; 12 | worker.onerror = err => { 13 | rej(err), worker.terminate(); 14 | }; 15 | }); 16 | }; 17 | -------------------------------------------------------------------------------- /giron/tests/snippets/elementIsVisibleInViewport.txt: -------------------------------------------------------------------------------- 1 | const elementIsVisibleInViewport = (el, partiallyVisible = false) => { 2 | const { top, left, bottom, right } = el.getBoundingClientRect(); 3 | const { innerHeight, innerWidth } = window; 4 | return partiallyVisible 5 | ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && 6 | ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) 7 | : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth; 8 | }; 9 | -------------------------------------------------------------------------------- /giron/tests/snippets/formatDuration.txt: -------------------------------------------------------------------------------- 1 | 2 | const formatDuration = ms => { 3 | if (ms < 0) ms = -ms; 4 | const time = { 5 | day: Math.floor(ms / 86400000), 6 | hour: Math.floor(ms / 3600000) % 24, 7 | minute: Math.floor(ms / 60000) % 60, 8 | second: Math.floor(ms / 1000) % 60, 9 | millisecond: Math.floor(ms) % 1000 10 | }; 11 | return Object.entries(time) 12 | .filter(val => val[1] !== 0) 13 | .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) 14 | .join(', '); 15 | }; 16 | -------------------------------------------------------------------------------- /giron/tests/snippets/prettyBytes.txt: -------------------------------------------------------------------------------- 1 | 2 | const prettyBytes = (num, precision = 3, addSpace = true) => { 3 | const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; 4 | if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0]; 5 | const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1); 6 | const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision)); 7 | return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent]; 8 | }; 9 | -------------------------------------------------------------------------------- /giron-wasm/src/utils.rs: -------------------------------------------------------------------------------- 1 | #[allow(dead_code)] 2 | pub fn set_panic_hook() { 3 | // When the `console_error_panic_hook` feature is enabled, we can call the 4 | // `set_panic_hook` function at least once during initialization, and then 5 | // we will get better error messages if our code ever panics. 6 | // 7 | // For more details see 8 | // https://github.com/rustwasm/console_error_panic_hook#readme 9 | #[cfg(feature = "console_error_panic_hook")] 10 | console_error_panic_hook::set_once(); 11 | } 12 | -------------------------------------------------------------------------------- /giron/tests/snippets/counter.txt: -------------------------------------------------------------------------------- 1 | 2 | const counter = (selector, start, end, step = 1, duration = 2000) => { 3 | let current = start, 4 | _step = (end - start) * step < 0 ? -step : step, 5 | timer = setInterval(() => { 6 | current += _step; 7 | document.querySelector(selector).innerHTML = current; 8 | if (current >= end) document.querySelector(selector).innerHTML = end; 9 | if (current >= end) clearInterval(timer); 10 | }, Math.abs(Math.floor(duration / (end - start)))); 11 | return timer; 12 | }; 13 | -------------------------------------------------------------------------------- /giron/tests/snippets/unflattenObject.txt: -------------------------------------------------------------------------------- 1 | 2 | const unflattenObject = obj => 3 | Object.keys(obj).reduce((acc, k) => { 4 | if (k.indexOf('.') !== -1) { 5 | const keys = k.split('.'); 6 | Object.assign( 7 | acc, 8 | JSON.parse( 9 | '{' + 10 | keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') + 11 | obj[k] + 12 | '}'.repeat(keys.length) 13 | ) 14 | ); 15 | } else acc[k] = obj[k]; 16 | return acc; 17 | }, {}); 18 | -------------------------------------------------------------------------------- /giron/tests/snippets/recordAnimationFrames.txt: -------------------------------------------------------------------------------- 1 | 2 | const recordAnimationFrames = (callback, autoStart = true) => { 3 | let running = true, 4 | raf; 5 | const stop = () => { 6 | running = false; 7 | cancelAnimationFrame(raf); 8 | }; 9 | const start = () => { 10 | running = true; 11 | run(); 12 | }; 13 | const run = () => { 14 | raf = requestAnimationFrame(() => { 15 | callback(); 16 | if (running) run(); 17 | }); 18 | }; 19 | if (autoStart) start(); 20 | return { start, stop }; 21 | }; 22 | -------------------------------------------------------------------------------- /giron/tests/snippets/observeMutations.txt: -------------------------------------------------------------------------------- 1 | 2 | const observeMutations = (element, callback, options) => { 3 | const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m))); 4 | observer.observe( 5 | element, 6 | Object.assign( 7 | { 8 | childList: true, 9 | attributes: true, 10 | attributeOldValue: true, 11 | characterData: true, 12 | characterDataOldValue: true, 13 | subtree: true 14 | }, 15 | options 16 | ) 17 | ); 18 | return observer; 19 | }; 20 | -------------------------------------------------------------------------------- /giron/tests/snippets/createEventHub.txt: -------------------------------------------------------------------------------- 1 | 2 | const createEventHub = () => ({ 3 | hub: Object.create(null), 4 | emit(event, data) { 5 | (this.hub[event] || []).forEach(handler => handler(data)); 6 | }, 7 | on(event, handler) { 8 | if (!this.hub[event]) this.hub[event] = []; 9 | this.hub[event].push(handler); 10 | }, 11 | off(event, handler) { 12 | const i = (this.hub[event] || []).findIndex(h => h === handler); 13 | if (i > -1) this.hub[event].splice(i, 1); 14 | if (this.hub[event].length === 0) delete this.hub[event]; 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /giron/tests/snippets/onUserInputChange.txt: -------------------------------------------------------------------------------- 1 | 2 | const onUserInputChange = callback => { 3 | let type = 'mouse', 4 | lastTime = 0; 5 | const mousemoveHandler = () => { 6 | const now = performance.now(); 7 | if (now - lastTime < 20) 8 | (type = 'mouse'), callback(type), document.removeEventListener('mousemove', mousemoveHandler); 9 | lastTime = now; 10 | }; 11 | document.addEventListener('touchstart', () => { 12 | if (type === 'touch') return; 13 | (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler); 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /giron/tests/snippets/hexToRGB.txt: -------------------------------------------------------------------------------- 1 | 2 | const hexToRGB = hex => { 3 | let alpha = false, 4 | h = hex.slice(hex.startsWith('#') ? 1 : 0); 5 | if (h.length === 3) h = [...h].map(x => x + x).join(''); 6 | else if (h.length === 8) alpha = true; 7 | h = parseInt(h, 16); 8 | return ( 9 | 'rgb' + 10 | (alpha ? 'a' : '') + 11 | '(' + 12 | (h >>> (alpha ? 24 : 16)) + 13 | ', ' + 14 | ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + 15 | ', ' + 16 | ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + 17 | (alpha ? `, ${h & 0x000000ff}` : '') + 18 | ')' 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /giron/tests/snippets/throttle.txt: -------------------------------------------------------------------------------- 1 | 2 | const throttle = (fn, wait) => { 3 | let inThrottle, lastFn, lastTime; 4 | return function() { 5 | const context = this, 6 | args = arguments; 7 | if (!inThrottle) { 8 | fn.apply(context, args); 9 | lastTime = Date.now(); 10 | inThrottle = true; 11 | } else { 12 | clearTimeout(lastFn); 13 | lastFn = setTimeout(function() { 14 | if (Date.now() - lastTime >= wait) { 15 | fn.apply(context, args); 16 | lastTime = Date.now(); 17 | } 18 | }, Math.max(wait - (Date.now() - lastTime), 0)); 19 | } 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /giron/tests/snippets/copyToClipboard.txt: -------------------------------------------------------------------------------- 1 | 2 | const copyToClipboard = str => { 3 | const el = document.createElement('textarea'); 4 | el.value = str; 5 | el.setAttribute('readonly', ''); 6 | el.style.position = 'absolute'; 7 | el.style.left = '-9999px'; 8 | document.body.appendChild(el); 9 | const selected = 10 | document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; 11 | el.select(); 12 | document.execCommand('copy'); 13 | document.body.removeChild(el); 14 | if (selected) { 15 | document.getSelection().removeAllRanges(); 16 | document.getSelection().addRange(selected); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /giron-wasm/README.md: -------------------------------------------------------------------------------- 1 | # giron-wasm 2 | 3 | A WebAssembly module for parsing Javascript. 4 | 5 | ## Usage 6 | 7 | The easiest way to see how you can use `giron-wasm` is with the wasm-app template. 8 | 9 | Just run `npm init wasm-app` and this will create a boilerplate wasm project for you. 10 | 11 | Now you can install `giron-wasm` and import it like any normal npm package. 12 | 13 | ## API 14 | 15 | `function parseScript(source: string)` - Parses a string as a javascript script. 16 | 17 | `function parseModule(source: string)` - Parses a string as a javascript module. Modules in javascript are parsed as strict mode code and allow import/export declarations. 18 | -------------------------------------------------------------------------------- /giron/tests/snippets/elo.txt: -------------------------------------------------------------------------------- 1 | 2 | const elo = ([...ratings], kFactor = 32, selfRating) => { 3 | const [a, b] = ratings; 4 | const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400)); 5 | const newRating = (rating, i) => 6 | (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a)); 7 | if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)]; 8 | 9 | for (let i = 0, len = ratings.length; i < len; i++) { 10 | let j = i; 11 | while (j < len - 1) { 12 | j++; 13 | [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor); 14 | } 15 | } 16 | return ratings; 17 | }; 18 | -------------------------------------------------------------------------------- /giron/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "giron" 3 | version = "0.1.2" 4 | authors = ["Sanjeet N. Dasharath "] 5 | edition = "2018" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/BlueBlazin/giron" 8 | readme = "README.md" 9 | homepage = "https://github.com/BlueBlazin/giron" 10 | description = "ECMAScript parser which outputs ESTree JSON." 11 | keywords = ["javascript", "ecmascript", "parser", "tokenizer", "js"] 12 | categories = ["parser-implementations"] 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | serde = { version = "1.0", features = ["derive"] } 18 | serde_json = "1.0" 19 | ucd = "0.1.1" 20 | 21 | [dev-dependencies] 22 | glob = "0.3.0" -------------------------------------------------------------------------------- /giron/src/token/token.rs: -------------------------------------------------------------------------------- 1 | use crate::token::value::Value; 2 | use std::char; 3 | 4 | #[derive(Debug, PartialEq, Clone)] 5 | pub enum TokenType { 6 | BooleanLiteral, 7 | Identifier, 8 | Keyword, 9 | NullLiteral, 10 | NumericLiteral, 11 | StringLiteral, 12 | Punctuator, 13 | RegularExpression, 14 | Template, 15 | Eof, 16 | } 17 | 18 | #[derive(Debug, Clone)] 19 | pub struct Token { 20 | pub tokentype: TokenType, 21 | pub value: Value, 22 | pub pattern: Option, 23 | pub flags: Option>, 24 | pub octal: Option, 25 | pub cooked: Option, 26 | pub head: Option, 27 | pub tail: Option, 28 | pub line_num: usize, 29 | pub col: usize, 30 | pub start: usize, 31 | pub end: usize, 32 | } 33 | -------------------------------------------------------------------------------- /giron/tests/snippets/colorize.txt: -------------------------------------------------------------------------------- 1 | 2 | const colorize = (...args) => ({ 3 | black: `\x1b[30m${args.join(' ')}`, 4 | red: `\x1b[31m${args.join(' ')}`, 5 | green: `\x1b[32m${args.join(' ')}`, 6 | yellow: `\x1b[33m${args.join(' ')}`, 7 | blue: `\x1b[34m${args.join(' ')}`, 8 | magenta: `\x1b[35m${args.join(' ')}`, 9 | cyan: `\x1b[36m${args.join(' ')}`, 10 | white: `\x1b[37m${args.join(' ')}`, 11 | bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`, 12 | bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`, 13 | bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`, 14 | bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`, 15 | bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`, 16 | bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`, 17 | bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`, 18 | bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m` 19 | }); 20 | -------------------------------------------------------------------------------- /giron-wasm/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod utils; 2 | 3 | use giron; 4 | use wasm_bindgen::prelude::*; 5 | 6 | // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global 7 | // allocator. 8 | #[cfg(feature = "wee_alloc")] 9 | #[global_allocator] 10 | static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; 11 | 12 | #[wasm_bindgen(js_name = parseScript)] 13 | pub fn parse_script(source: String) -> JsValue { 14 | match giron::parse_script(source) { 15 | Ok(ast) => JsValue::from_serde(&ast).unwrap(), 16 | Err(err) => JsValue::from(format!("{:?}", err)), 17 | } 18 | } 19 | 20 | #[wasm_bindgen(js_name = parseModule)] 21 | pub fn parse_module(source: String) -> JsValue { 22 | match giron::parse_module(source) { 23 | Ok(ast) => JsValue::from_serde(&ast).unwrap(), 24 | Err(err) => JsValue::from(format!("{:?}", err)), 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /giron/src/parser/test_static_semantics.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::result::Result; 2 | use crate::parser::parser::Parser; 3 | use std::str::Chars; 4 | 5 | fn assert_fails(source: &str, f: F) 6 | where 7 | F: Fn(Parser) -> Result, 8 | { 9 | let parser = Parser::new(source.chars()); 10 | if let Ok(_) = f(parser) { 11 | panic!("Expected parse failure."); 12 | } 13 | } 14 | 15 | // 12 Expressions 16 | 17 | // 12.1 Identifiers 18 | #[test] 19 | fn test_identifiers() { 20 | assert_fails("arguments", |mut p| { 21 | p.ctx.strict = true; 22 | p.parse_binding_id() 23 | }); 24 | assert_fails("eval", |mut p| { 25 | p.ctx.strict = true; 26 | p.parse_binding_id() 27 | }); 28 | assert_fails("yield", |mut p| { 29 | p.ctx.strict = true; 30 | p.parse_id_reference() 31 | }); 32 | assert_fails("await", |mut p| { 33 | p.ctx.strict = true; 34 | p.parse_id_reference() 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /giron/src/scanner/reader.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | pub struct Reader { 4 | pub source: I, 5 | pub buf: VecDeque, 6 | } 7 | 8 | impl Reader 9 | where 10 | I: Iterator, 11 | { 12 | pub fn new(source: I) -> Self { 13 | Reader { 14 | source, 15 | buf: VecDeque::with_capacity(3), 16 | } 17 | } 18 | 19 | pub fn lookahead(&mut self, n: usize) -> Option { 20 | for _ in self.buf.len()..(n + 1) { 21 | match self.source.next() { 22 | Some(item) => self.buf.push_back(item), 23 | None => return None, 24 | } 25 | } 26 | 27 | self.buf.get(n).map(|&x| x) 28 | } 29 | } 30 | 31 | impl Iterator for Reader 32 | where 33 | I: Iterator, 34 | { 35 | type Item = char; 36 | 37 | fn next(&mut self) -> Option { 38 | self.buf.pop_front().or_else(|| self.source.next()) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /giron/src/token/value.rs: -------------------------------------------------------------------------------- 1 | use crate::token::punctuators::Punctuator; 2 | use serde::Serialize; 3 | 4 | #[derive(Serialize, Debug, PartialEq, Clone)] 5 | #[serde(untagged)] 6 | pub enum Value { 7 | Str(String), 8 | Num(f64), 9 | Punc(Punctuator), 10 | Null, 11 | } 12 | 13 | impl From<&Value> for String { 14 | fn from(value: &Value) -> Self { 15 | match value { 16 | Value::Str(s) => s.clone(), 17 | Value::Num(x) => x.to_string(), 18 | Value::Punc(p) => p.to_string(), 19 | Value::Null => String::from("null"), 20 | } 21 | } 22 | } 23 | 24 | impl Value { 25 | pub fn string(self) -> Result { 26 | match self { 27 | Value::Str(val) => Ok(val), 28 | _ => Err(()), 29 | } 30 | } 31 | 32 | pub fn punc(self) -> Result { 33 | match self { 34 | Value::Punc(val) => Ok(val), 35 | _ => Err(()), 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # giron-rs 2 | 3 | [![LICENSE](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](LICENSE) 4 | [![Build Status](https://travis-ci.com/BlueBlazin/giron-rs.svg?branch=master)](https://travis-ci.com/BlueBlazin/giron-rs) 5 | [![Active Development](https://img.shields.io/badge/Maintenance%20Level-Actively%20Developed-brightgreen.svg)](https://gist.github.com/cheerfulstoic/d107229326a01ff0f333a1d3476e068d) 6 | 7 | The goal of the giron-rs project is to provide ECMAScript parsing capabalities for Rust and WebAssembly programmers. 8 | The output is an Abstract Syntax Tree (AST) in JSON format using the ESTree specification. ESTree is the most popular output format of open source javascript parsers. 9 | 10 | ## giron 11 | 12 | The giron rust crate is a library for parsing ECMAScript. 13 | 14 | ## giron-wasm 15 | 16 | A WebAssembly based package for parsing ECMAScript on the client side. 17 | 18 | ## giron-node 19 | 20 | A Rust based native node.js package for parsing ECMAScript in node.js. 21 | -------------------------------------------------------------------------------- /giron/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod codepoint; 2 | mod errors; 3 | mod estree; 4 | mod parser; 5 | mod scanner; 6 | mod span; 7 | mod token; 8 | 9 | use crate::errors::errors::{Error, ErrorType}; 10 | use crate::errors::result::Result; 11 | use crate::estree::estree::Node; 12 | use crate::parser::parser::Parser; 13 | 14 | /// GironError 15 | pub type GironError = Error; 16 | 17 | /// GironErrorType 18 | pub type GironErrorType = ErrorType; 19 | 20 | /// EstreeNode 21 | pub type EstreeNode = Node; 22 | 23 | /// Parser a source string as an ECMAScript module. 24 | pub fn parse_module(source: String) -> Result { 25 | let mut parser = Parser::new(source.chars()); 26 | parser.parse_module() 27 | } 28 | 29 | /// Parser a source string as an ECMAScript script. 30 | pub fn parse_script(source: String) -> Result { 31 | let mut parser = Parser::new(source.chars()); 32 | parser.parse_script() 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | #[test] 38 | fn it_works() { 39 | assert_eq!(2 + 2, 4); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /giron-wasm/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | bin/ 5 | pkg/ 6 | wasm-pack.log 7 | 8 | 9 | # Created by https://www.gitignore.io/api/macos,visualstudiocode 10 | # Edit at https://www.gitignore.io/?templates=macos,visualstudiocode 11 | 12 | ### macOS ### 13 | # General 14 | .DS_Store 15 | .AppleDouble 16 | .LSOverride 17 | 18 | # Icon must end with two \r 19 | Icon 20 | 21 | # Thumbnails 22 | ._* 23 | 24 | # Files that might appear in the root of a volume 25 | .DocumentRevisions-V100 26 | .fseventsd 27 | .Spotlight-V100 28 | .TemporaryItems 29 | .Trashes 30 | .VolumeIcon.icns 31 | .com.apple.timemachine.donotpresent 32 | 33 | # Directories potentially created on remote AFP share 34 | .AppleDB 35 | .AppleDesktop 36 | Network Trash Folder 37 | Temporary Items 38 | .apdisk 39 | 40 | ### VisualStudioCode ### 41 | .vscode/* 42 | !.vscode/settings.json 43 | !.vscode/tasks.json 44 | !.vscode/launch.json 45 | !.vscode/extensions.json 46 | 47 | ### VisualStudioCode Patch ### 48 | # Ignore all local history of files 49 | .history 50 | 51 | # End of https://www.gitignore.io/api/macos,visualstudiocode -------------------------------------------------------------------------------- /LICENSE_MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Sanjeet N. Dasharath 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /giron/LICENSE_MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Sanjeet N. Dasharath 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /giron-wasm/LICENSE_MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Sanjeet N. Dasharath 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /giron-wasm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "giron-wasm" 3 | version = "0.2.3" 4 | authors = ["Sanjeet N. Dasharath "] 5 | edition = "2018" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/BlueBlazin/giron" 8 | homepage = "https://github.com/BlueBlazin/giron" 9 | description = "ECMAScript parser which outputs ESTree JSON." 10 | 11 | [lib] 12 | crate-type = ["cdylib", "rlib"] 13 | 14 | [features] 15 | default = ["console_error_panic_hook"] 16 | 17 | [dependencies] 18 | serde = { version = "1.0", features = ["derive"] } 19 | wasm-bindgen = { version = "^0.2", features = ["serde-serialize"] } 20 | giron = "^0.1" 21 | 22 | # The `console_error_panic_hook` crate provides better debugging of panics by 23 | # logging them with `console.error`. This is great for development, but requires 24 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 25 | # code size when deploying. 26 | console_error_panic_hook = { version = "0.1.1", optional = true } 27 | 28 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 29 | # compared to the default allocator's ~10K. It is slower than the default 30 | # allocator, however. 31 | # 32 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 33 | wee_alloc = { version = "0.4.2", optional = true } 34 | 35 | [dev-dependencies] 36 | wasm-bindgen-test = "0.2" 37 | 38 | [profile.release] 39 | # Tell `rustc` to optimize for small code size. 40 | # opt-level = "s" 41 | 42 | # Optimize for speed 43 | opt-level = 3 44 | lto = true -------------------------------------------------------------------------------- /giron/tests/test_parser.rs: -------------------------------------------------------------------------------- 1 | use giron::{parse_module, parse_script}; 2 | use glob::glob; 3 | use std::fs; 4 | 5 | #[test] 6 | fn test_parser() { 7 | // let mut parser = Parser::new("[1, 2, 4]".chars()); 8 | // parser.parse_script().unwrap(); 9 | let res = parse_script(String::from(r#"/[x-\ud800]/u"#)).unwrap(); 10 | println!("{:?}", res); 11 | } 12 | 13 | #[test] 14 | fn test_snippet() { 15 | let source = fs::read_to_string("tests/snippets/all.txt").unwrap(); 16 | match parse_module(source) { 17 | Ok(_) => (), 18 | Err(e) => println!("{}\n{:?}", &e, e), 19 | } 20 | } 21 | 22 | #[test] 23 | fn test_all_snippets() { 24 | // test on js code snippets from 30-seconds-of-code 25 | // https://github.com/30-seconds/30-seconds-of-code 26 | glob("tests/snippets/*.txt").unwrap().for_each(|entry| { 27 | if let Ok(path) = entry { 28 | let source = fs::read_to_string(path.clone()).unwrap(); 29 | // let mut parser = Parser::new(source.chars()); 30 | // match parser.parse_module() { 31 | // Ok(_) => (), 32 | // Err(e) => println!("{}, {}\n{:?}", path.display(), &e, e), 33 | // } 34 | // parser.parse_module().unwrap(); 35 | parse_module(source).unwrap(); 36 | } 37 | }); 38 | } 39 | 40 | #[test] 41 | fn test_react() { 42 | let source = fs::read_to_string("tests/source/react.js").unwrap(); 43 | // let mut parser = Parser::new(source.chars()); 44 | // parser.parse_module().unwrap(); 45 | parse_module(source).unwrap(); 46 | } 47 | 48 | #[test] 49 | fn test_react_dom() { 50 | let source = fs::read_to_string("tests/source/react-dom.js").unwrap(); 51 | // let mut parser = Parser::new(source.chars()); 52 | // parser.parse_module().unwrap(); 53 | parse_module(source).unwrap(); 54 | } 55 | 56 | #[test] 57 | fn test_angular() { 58 | let source = fs::read_to_string("tests/source/angular.js").unwrap(); 59 | // let mut parser = Parser::new(source.chars()); 60 | // parser.parse_module().unwrap(); 61 | parse_module(source).unwrap(); 62 | } 63 | -------------------------------------------------------------------------------- /giron/README.md: -------------------------------------------------------------------------------- 1 | [![LICENSE](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](LICENSE) 2 | [![Build Status](https://travis-ci.com/BlueBlazin/giron-rs.svg?branch=master)](https://travis-ci.com/BlueBlazin/giron-rs) 3 | [![Active Development](https://img.shields.io/badge/Maintenance%20Level-Actively%20Developed-brightgreen.svg)](https://gist.github.com/cheerfulstoic/d107229326a01ff0f333a1d3476e068d) 4 | 5 | # Giron 6 | 7 | ## Table of Contents 8 | 9 | - [Introduction](#introduction) 10 | - [Contribution](#contribution) 11 | - [Installation](#installation) 12 | - [Usage](#usage) 13 | 14 | ## Introduction 15 | 16 | Giron is an ECMAScript parser written in Rust which outputs Rust strucs or JSON in the ESTree specification format. 17 | 18 | The `giron-wasm` provides the compiled .wasm binary and javascript interface for using the giron parser on the web. 19 | 20 | **Note:** giron is a work in progress. 21 | 22 | ## Contribution 23 | 24 | This repository is looking for contributors. There's still a lot of work to be done, but some of the priorities right now are: 25 | 26 | 1. Add more tests, ensure parity with output from esprima and/or acorn. 27 | 2. Update parser and ESTree to be ECMAScript 2020 compliant. 28 | 3. Add all early errors from the ECMAScript specification to the parser. 29 | 4. Refactor the codebase to increase readability and add more documentation. 30 | 5. Improve performance. 31 | 6. Add JSX support. 32 | 33 | ## Installation 34 | 35 | Get from crates.io: https://crates.io/crates/giron 36 | 37 | ## Usage 38 | 39 | Once you add `giron` to your Cargo.toml, 40 | 41 | **Basic Usage:** 42 | 43 | ```rs 44 | use giron::{parse_module, parse_script}; 45 | 46 | fn main() { 47 | let source = String::from("const PI = 3.14;"); 48 | parse_script(source).unwrap(); 49 | } 50 | ``` 51 | 52 | **Giron Errors:** 53 | 54 | ```rs 55 | use giron::{parse_module, parse_script, GironError, EstreeNode}; 56 | 57 | fn analyze_ast() -> Result { 58 | let source = String::from("const PI = 3.14;"); 59 | parse_script(source) 60 | } 61 | ``` 62 | 63 | **Parse contents of a javascript file:** 64 | 65 | ```rs 66 | use giron::{parse_module, parse_script}; 67 | use std::fs; 68 | 69 | fn main() { 70 | let source = fs::read_to_string("example-file.js").unwrap(); 71 | parse_script(source).unwrap(); 72 | } 73 | ``` 74 | -------------------------------------------------------------------------------- /giron-wasm/.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | sudo: false 3 | 4 | cache: cargo 5 | 6 | matrix: 7 | include: 8 | 9 | # Builds with wasm-pack. 10 | - rust: beta 11 | env: RUST_BACKTRACE=1 12 | addons: 13 | firefox: latest 14 | chrome: stable 15 | before_script: 16 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 17 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 18 | - cargo install-update -a 19 | - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f 20 | script: 21 | - cargo generate --git . --name testing 22 | # Having a broken Cargo.toml (in that it has curlies in fields) anywhere 23 | # in any of our parent dirs is problematic. 24 | - mv Cargo.toml Cargo.toml.tmpl 25 | - cd testing 26 | - wasm-pack build 27 | - wasm-pack test --chrome --firefox --headless 28 | 29 | # Builds on nightly. 30 | - rust: nightly 31 | env: RUST_BACKTRACE=1 32 | before_script: 33 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 34 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 35 | - cargo install-update -a 36 | - rustup target add wasm32-unknown-unknown 37 | script: 38 | - cargo generate --git . --name testing 39 | - mv Cargo.toml Cargo.toml.tmpl 40 | - cd testing 41 | - cargo check 42 | - cargo check --target wasm32-unknown-unknown 43 | - cargo check --no-default-features 44 | - cargo check --target wasm32-unknown-unknown --no-default-features 45 | - cargo check --no-default-features --features console_error_panic_hook 46 | - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook 47 | - cargo check --no-default-features --features "console_error_panic_hook wee_alloc" 48 | - cargo check --target wasm32-unknown-unknown --no-default-features --features "console_error_panic_hook wee_alloc" 49 | 50 | # Builds on beta. 51 | - rust: beta 52 | env: RUST_BACKTRACE=1 53 | before_script: 54 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 55 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 56 | - cargo install-update -a 57 | - rustup target add wasm32-unknown-unknown 58 | script: 59 | - cargo generate --git . --name testing 60 | - mv Cargo.toml Cargo.toml.tmpl 61 | - cd testing 62 | - cargo check 63 | - cargo check --target wasm32-unknown-unknown 64 | - cargo check --no-default-features 65 | - cargo check --target wasm32-unknown-unknown --no-default-features 66 | - cargo check --no-default-features --features console_error_panic_hook 67 | - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook 68 | # Note: no enabling the `wee_alloc` feature here because it requires 69 | # nightly for now. 70 | -------------------------------------------------------------------------------- /giron/src/codepoint/codepoint.rs: -------------------------------------------------------------------------------- 1 | use ucd::Codepoint; 2 | 3 | pub trait CodePoint { 4 | fn is_whitespace(self) -> bool; 5 | fn is_line_terminator(self) -> bool; 6 | fn is_identifier_start(self) -> bool; 7 | fn is_identifier_continue(self) -> bool; 8 | fn is_decimal_digit(self) -> bool; 9 | fn is_nonzero_digit(self) -> bool; 10 | fn is_octal_digit(self) -> bool; 11 | fn is_hex_digit(self) -> bool; 12 | fn is_single_escape_char(self) -> bool; 13 | fn unescape(self) -> Self; 14 | fn is_single_char_punctuator(self) -> bool; 15 | } 16 | 17 | impl CodePoint for char { 18 | fn is_whitespace(self) -> bool { 19 | match self { 20 | '\u{0009}' | '\u{000B}' | '\u{000C}' | '\u{0020}' | '\u{00A0}' | '\u{FEFF}' 21 | | '\u{1680}' | '\u{2000}' | '\u{2001}' | '\u{2002}' | '\u{2003}' | '\u{2004}' 22 | | '\u{2005}' | '\u{2006}' | '\u{2007}' | '\u{2008}' | '\u{2009}' | '\u{200A}' 23 | | '\u{202F}' | '\u{205F}' | '\u{3000}' => true, 24 | _ => false, 25 | } 26 | } 27 | 28 | fn is_line_terminator(self) -> bool { 29 | match self { 30 | '\n' | '\r' | '\u{2028}' | '\u{2029}' => true, 31 | _ => false, 32 | } 33 | } 34 | 35 | fn is_identifier_start(self) -> bool { 36 | // $ | _ | \ | A..Z | a..z | other ID_START 37 | match self { 38 | '$' | '_' | 'A'..='Z' | 'a'..='z' => true, 39 | _ => self.is_id_start(), 40 | } 41 | } 42 | 43 | fn is_identifier_continue(self) -> bool { 44 | match self { 45 | '$' | '_' | 'A'..='Z' | 'a'..='z' | '0'..='9' | '\u{005C}' => true, 46 | _ => self.is_id_continue(), 47 | } 48 | } 49 | 50 | fn is_decimal_digit(self) -> bool { 51 | match self { 52 | '0'..='9' => true, 53 | _ => false, 54 | } 55 | } 56 | 57 | fn is_nonzero_digit(self) -> bool { 58 | match self { 59 | '1'..='9' => true, 60 | _ => false, 61 | } 62 | } 63 | 64 | fn is_octal_digit(self) -> bool { 65 | match self { 66 | '0'..='7' => true, 67 | _ => false, 68 | } 69 | } 70 | 71 | fn is_hex_digit(self) -> bool { 72 | match self { 73 | '0'..='9' | 'a'..='f' | 'A'..='F' => true, 74 | _ => false, 75 | } 76 | } 77 | 78 | fn is_single_escape_char(self) -> bool { 79 | match self { 80 | '\'' | '"' | '\\' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' => true, 81 | _ => false, 82 | } 83 | } 84 | 85 | fn unescape(self) -> Self { 86 | match self { 87 | 'b' => '\x08', 88 | 'f' => '\x0C', 89 | 'n' => '\n', 90 | 'r' => '\r', 91 | 't' => '\t', 92 | 'v' => '\x0B', 93 | _ => self, 94 | } 95 | } 96 | 97 | fn is_single_char_punctuator(self) -> bool { 98 | match self { 99 | '{' | '(' | '[' | ';' | ',' | ']' | ':' | '?' | '~' | ')' => true, 100 | _ => false, 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | 5 | 6 | # Created by https://www.gitignore.io/api/node,macos,visualstudiocode 7 | # Edit at https://www.gitignore.io/?templates=node,macos,visualstudiocode 8 | 9 | ### macOS ### 10 | # General 11 | .DS_Store 12 | .AppleDouble 13 | .LSOverride 14 | 15 | # Icon must end with two \r 16 | Icon 17 | 18 | # Thumbnails 19 | ._* 20 | 21 | # Files that might appear in the root of a volume 22 | .DocumentRevisions-V100 23 | .fseventsd 24 | .Spotlight-V100 25 | .TemporaryItems 26 | .Trashes 27 | .VolumeIcon.icns 28 | .com.apple.timemachine.donotpresent 29 | 30 | # Directories potentially created on remote AFP share 31 | .AppleDB 32 | .AppleDesktop 33 | Network Trash Folder 34 | Temporary Items 35 | .apdisk 36 | 37 | ### Node ### 38 | # Logs 39 | logs 40 | *.log 41 | npm-debug.log* 42 | yarn-debug.log* 43 | yarn-error.log* 44 | lerna-debug.log* 45 | 46 | # Diagnostic reports (https://nodejs.org/api/report.html) 47 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 48 | 49 | # Runtime data 50 | pids 51 | *.pid 52 | *.seed 53 | *.pid.lock 54 | 55 | # Directory for instrumented libs generated by jscoverage/JSCover 56 | lib-cov 57 | 58 | # Coverage directory used by tools like istanbul 59 | coverage 60 | *.lcov 61 | 62 | # nyc test coverage 63 | .nyc_output 64 | 65 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 66 | .grunt 67 | 68 | # Bower dependency directory (https://bower.io/) 69 | bower_components 70 | 71 | # node-waf configuration 72 | .lock-wscript 73 | 74 | # Compiled binary addons (https://nodejs.org/api/addons.html) 75 | build/Release 76 | 77 | # Dependency directories 78 | node_modules/ 79 | jspm_packages/ 80 | 81 | # TypeScript v1 declaration files 82 | typings/ 83 | 84 | # TypeScript cache 85 | *.tsbuildinfo 86 | 87 | # Optional npm cache directory 88 | .npm 89 | 90 | # Optional eslint cache 91 | .eslintcache 92 | 93 | # Optional REPL history 94 | .node_repl_history 95 | 96 | # Output of 'npm pack' 97 | *.tgz 98 | 99 | # Yarn Integrity file 100 | .yarn-integrity 101 | 102 | # dotenv environment variables file 103 | .env 104 | .env.test 105 | 106 | # parcel-bundler cache (https://parceljs.org/) 107 | .cache 108 | 109 | # next.js build output 110 | .next 111 | 112 | # nuxt.js build output 113 | .nuxt 114 | 115 | # rollup.js default build output 116 | dist/ 117 | 118 | # Uncomment the public line if your project uses Gatsby 119 | # https://nextjs.org/blog/next-9-1#public-directory-support 120 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav 121 | # public 122 | 123 | # Storybook build outputs 124 | .out 125 | .storybook-out 126 | 127 | # vuepress build output 128 | .vuepress/dist 129 | 130 | # Serverless directories 131 | .serverless/ 132 | 133 | # FuseBox cache 134 | .fusebox/ 135 | 136 | # DynamoDB Local files 137 | .dynamodb/ 138 | 139 | # Temporary folders 140 | tmp/ 141 | temp/ 142 | 143 | ### VisualStudioCode ### 144 | .vscode/* 145 | !.vscode/settings.json 146 | !.vscode/tasks.json 147 | !.vscode/launch.json 148 | !.vscode/extensions.json 149 | 150 | ### VisualStudioCode Patch ### 151 | # Ignore all local history of files 152 | .history 153 | 154 | # End of https://www.gitignore.io/api/node,macos,visualstudiocode -------------------------------------------------------------------------------- /giron/src/parser/syntax.rs: -------------------------------------------------------------------------------- 1 | use crate::token::punctuators::Punctuator; 2 | use crate::token::token::{Token, TokenType}; 3 | use crate::token::value::Value; 4 | 5 | pub trait Syntax { 6 | fn to_keyword(self) -> Self; 7 | fn to_string(self) -> String; 8 | fn to_str(&self) -> &str; 9 | fn matches_str(&self, val: &str) -> bool; 10 | fn matches_punc(&self, val: &str) -> bool; 11 | fn matches_null(&self) -> bool; 12 | fn is_assign_op(&self) -> bool; 13 | fn is_bin_op(&self) -> bool; 14 | fn is_unary_op(&self, has_await: bool) -> bool; 15 | fn is_update_op(&self) -> bool; 16 | fn precedence(&self, has_in: bool) -> usize; 17 | fn is_iteration_kw(&self) -> bool; 18 | fn is_hoistable_dclr_kw(&self) -> bool; 19 | fn is_lexical_dclr_kw(&self) -> bool; 20 | fn is_lexical_dclr_or_var_kw(&self) -> bool; 21 | fn is_dclr_kw(&self) -> bool; 22 | fn is_strict_reserved_kw(&self) -> bool; 23 | } 24 | 25 | impl Syntax for Token { 26 | fn to_keyword(mut self) -> Self { 27 | if self.tokentype == TokenType::Identifier { 28 | self.tokentype = TokenType::Keyword 29 | } 30 | self 31 | } 32 | 33 | fn to_string(self) -> String { 34 | match self.value { 35 | Value::Str(s) => s, 36 | Value::Punc(p) => p.to_string(), 37 | _ => panic!("Not a string value."), 38 | } 39 | } 40 | 41 | fn to_str(&self) -> &str { 42 | match &self.value { 43 | Value::Str(s) => &s[..], 44 | Value::Punc(p) => p.to_str(), 45 | _ => panic!("Not possible to convert value to &str."), 46 | } 47 | } 48 | 49 | fn matches_str(&self, val: &str) -> bool { 50 | match &self.value { 51 | Value::Str(s) if &s[..] == val => true, 52 | _ => false, 53 | } 54 | } 55 | 56 | fn matches_punc(&self, val: &str) -> bool { 57 | match &self.value { 58 | Value::Punc(p) if p == &Punctuator::from(val) => true, 59 | _ => false, 60 | } 61 | } 62 | 63 | fn matches_null(&self) -> bool { 64 | match self.value { 65 | Value::Null => true, 66 | _ => false, 67 | } 68 | } 69 | 70 | fn is_assign_op(&self) -> bool { 71 | match self.value { 72 | Value::Punc(Punctuator::PlusAssign) 73 | | Value::Punc(Punctuator::MinusAssign) 74 | | Value::Punc(Punctuator::StarAssign) 75 | | Value::Punc(Punctuator::ModAssign) 76 | | Value::Punc(Punctuator::PowAssign) 77 | | Value::Punc(Punctuator::LShiftAssign) 78 | | Value::Punc(Punctuator::RShiftAssign) 79 | | Value::Punc(Punctuator::ZRShiftAssign) 80 | | Value::Punc(Punctuator::BitAndAssign) 81 | | Value::Punc(Punctuator::BitOrAssign) 82 | | Value::Punc(Punctuator::BitXorAssign) 83 | | Value::Punc(Punctuator::SlashAssign) => true, 84 | Value::Punc(Punctuator::Equal) => true, 85 | _ => false, 86 | } 87 | } 88 | 89 | fn is_bin_op(&self) -> bool { 90 | match self.tokentype { 91 | TokenType::Punctuator if self.matches_punc("<") => true, 92 | TokenType::Punctuator if self.matches_punc(">") => true, 93 | TokenType::Punctuator if self.matches_punc("<=") => true, 94 | TokenType::Punctuator if self.matches_punc(">=") => true, 95 | TokenType::Punctuator if self.matches_punc("==") => true, 96 | TokenType::Punctuator if self.matches_punc("!=") => true, 97 | TokenType::Punctuator if self.matches_punc("===") => true, 98 | TokenType::Punctuator if self.matches_punc("!==") => true, 99 | TokenType::Punctuator if self.matches_punc("+") => true, 100 | TokenType::Punctuator if self.matches_punc("-") => true, 101 | TokenType::Punctuator if self.matches_punc("*") => true, 102 | TokenType::Punctuator if self.matches_punc("/") => true, 103 | TokenType::Punctuator if self.matches_punc("%") => true, 104 | TokenType::Punctuator if self.matches_punc("<<") => true, 105 | TokenType::Punctuator if self.matches_punc(">>") => true, 106 | TokenType::Punctuator if self.matches_punc(">>>") => true, 107 | TokenType::Punctuator if self.matches_punc("&") => true, 108 | TokenType::Punctuator if self.matches_punc("|") => true, 109 | TokenType::Punctuator if self.matches_punc("^") => true, 110 | TokenType::Punctuator if self.matches_punc("&&") => true, 111 | TokenType::Punctuator if self.matches_punc("||") => true, 112 | TokenType::Keyword if self.matches_str("in") => true, 113 | TokenType::Keyword if self.matches_str("instanceof") => true, 114 | _ => false, 115 | } 116 | } 117 | 118 | fn is_unary_op(&self, has_await: bool) -> bool { 119 | let unary_punc = match self.value { 120 | Value::Punc(Punctuator::Plus) 121 | | Value::Punc(Punctuator::Minus) 122 | | Value::Punc(Punctuator::Tilde) 123 | | Value::Punc(Punctuator::Bang) => true, 124 | _ => false, 125 | }; 126 | let unary_keyword = match self.tokentype { 127 | TokenType::Keyword => match self.to_str() { 128 | "delete" | "void" | "typeof" => true, 129 | "await" if has_await => true, 130 | _ => false, 131 | }, 132 | _ => false, 133 | }; 134 | unary_punc || unary_keyword 135 | } 136 | fn is_update_op(&self) -> bool { 137 | match self.value { 138 | Value::Punc(Punctuator::Inc) | Value::Punc(Punctuator::Dec) => true, 139 | _ => false, 140 | } 141 | } 142 | 143 | fn precedence(&self, has_in: bool) -> usize { 144 | match self.tokentype { 145 | TokenType::Punctuator if self.matches_punc("||") => 1, 146 | TokenType::Punctuator if self.matches_punc("&&") => 2, 147 | TokenType::Punctuator if self.matches_punc("|") => 3, 148 | TokenType::Punctuator if self.matches_punc("^") => 4, 149 | TokenType::Punctuator if self.matches_punc("&") => 5, 150 | TokenType::Punctuator if self.matches_punc("==") => 6, 151 | TokenType::Punctuator if self.matches_punc("!=") => 6, 152 | TokenType::Punctuator if self.matches_punc("===") => 6, 153 | TokenType::Punctuator if self.matches_punc("!==") => 6, 154 | TokenType::Punctuator if self.matches_punc("<") => 7, 155 | TokenType::Punctuator if self.matches_punc(">") => 7, 156 | TokenType::Punctuator if self.matches_punc("<=") => 7, 157 | TokenType::Punctuator if self.matches_punc(">=") => 7, 158 | TokenType::Punctuator if self.matches_punc("<<") => 8, 159 | TokenType::Punctuator if self.matches_punc(">>") => 8, 160 | TokenType::Punctuator if self.matches_punc(">>>") => 8, 161 | TokenType::Punctuator if self.matches_punc("+") => 9, 162 | TokenType::Punctuator if self.matches_punc("-") => 9, 163 | TokenType::Punctuator if self.matches_punc("*") => 10, 164 | TokenType::Punctuator if self.matches_punc("/") => 10, 165 | TokenType::Punctuator if self.matches_punc("%") => 11, 166 | TokenType::Keyword if self.matches_str("instanceof") => 7, 167 | TokenType::Keyword if (self.matches_str("in") && has_in) => 7, 168 | _ => 0, 169 | } 170 | } 171 | 172 | fn is_iteration_kw(&self) -> bool { 173 | match self.tokentype { 174 | TokenType::Keyword => { 175 | self.matches_str("do") | self.matches_str("while") | self.matches_str("for") 176 | } 177 | _ => false, 178 | } 179 | } 180 | 181 | fn is_hoistable_dclr_kw(&self) -> bool { 182 | match self.tokentype { 183 | TokenType::Identifier | TokenType::Keyword => { 184 | self.matches_str("async") | self.matches_str("function") 185 | } 186 | _ => false, 187 | } 188 | } 189 | 190 | fn is_lexical_dclr_kw(&self) -> bool { 191 | match self.tokentype { 192 | TokenType::Identifier | TokenType::Keyword => { 193 | self.matches_str("let") | self.matches_str("const") 194 | } 195 | _ => false, 196 | } 197 | } 198 | 199 | fn is_lexical_dclr_or_var_kw(&self) -> bool { 200 | match self.tokentype { 201 | TokenType::Identifier | TokenType::Keyword => { 202 | self.matches_str("let") | self.matches_str("const") | self.matches_str("var") 203 | } 204 | _ => false, 205 | } 206 | } 207 | 208 | fn is_dclr_kw(&self) -> bool { 209 | if self.is_hoistable_dclr_kw() || self.is_lexical_dclr_kw() { 210 | true 211 | } else { 212 | match self.tokentype { 213 | TokenType::Keyword if self.matches_str("class") => true, 214 | _ => false, 215 | } 216 | } 217 | } 218 | 219 | fn is_strict_reserved_kw(&self) -> bool { 220 | match self.to_str() { 221 | "implements" | "interface" | "package" | "private" | "protected" | "public" => true, 222 | _ => false, 223 | } 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /LICENSE_APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /giron/LICENSE_APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /giron-wasm/LICENSE_APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /giron/src/token/punctuators.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] 4 | #[serde(tag = "type")] 5 | pub enum Punctuator { 6 | LBrace, 7 | LParen, 8 | RParen, 9 | LBracket, 10 | RBracket, 11 | Dot, 12 | Ellipsis, 13 | Semicolon, 14 | Comma, 15 | LAngle, 16 | RAngle, 17 | LEqual, 18 | GEqual, 19 | Equal, 20 | NEqual, 21 | StrictEqual, 22 | StrictNEqual, 23 | Plus, 24 | Minus, 25 | Star, 26 | Mod, 27 | Pow, 28 | Inc, 29 | Dec, 30 | LShift, 31 | RShift, 32 | ZRShift, 33 | BitAnd, 34 | BitOr, 35 | BitXor, 36 | Bang, 37 | Tilde, 38 | LogicalAnd, 39 | LogicalOr, 40 | Question, 41 | Colon, 42 | Assign, 43 | PlusAssign, 44 | MinusAssign, 45 | StarAssign, 46 | ModAssign, 47 | PowAssign, 48 | LShiftAssign, 49 | RShiftAssign, 50 | ZRShiftAssign, 51 | BitAndAssign, 52 | BitOrAssign, 53 | BitXorAssign, 54 | FatArrow, 55 | Slash, 56 | SlashAssign, 57 | RBrace, 58 | Instanceof, 59 | // ES2020 60 | QMarkDot, 61 | DoubleQMark, 62 | } 63 | 64 | impl Punctuator { 65 | // *= /= %= += -= <<= >>= >>>= &= ^= |= **= 66 | pub fn is_assign_op(&self) -> bool { 67 | match self { 68 | Punctuator::PlusAssign 69 | | Punctuator::MinusAssign 70 | | Punctuator::StarAssign 71 | | Punctuator::ModAssign 72 | | Punctuator::PowAssign 73 | | Punctuator::LShiftAssign 74 | | Punctuator::RShiftAssign 75 | | Punctuator::ZRShiftAssign 76 | | Punctuator::BitAndAssign 77 | | Punctuator::BitOrAssign 78 | | Punctuator::BitXorAssign 79 | | Punctuator::SlashAssign => true, 80 | Punctuator::Equal => true, 81 | _ => false, 82 | } 83 | } 84 | 85 | pub fn is_equality_op(&self) -> bool { 86 | match self { 87 | Punctuator::Equal 88 | | Punctuator::StrictEqual 89 | | Punctuator::NEqual 90 | | Punctuator::StrictNEqual => true, 91 | _ => false, 92 | } 93 | } 94 | 95 | pub fn to_str(&self) -> &'static str { 96 | match self { 97 | Punctuator::LBrace => "{", 98 | Punctuator::LParen => "(", 99 | Punctuator::RParen => ")", 100 | Punctuator::LBracket => "[", 101 | Punctuator::RBracket => "]", 102 | Punctuator::Dot => ".", 103 | Punctuator::Ellipsis => "...", 104 | Punctuator::Semicolon => ";", 105 | Punctuator::Comma => ",", 106 | Punctuator::LAngle => "<", 107 | Punctuator::RAngle => ">", 108 | Punctuator::LEqual => "<=", 109 | Punctuator::GEqual => ">=", 110 | Punctuator::Equal => "==", 111 | Punctuator::NEqual => "!=", 112 | Punctuator::StrictEqual => "===", 113 | Punctuator::StrictNEqual => "!==", 114 | Punctuator::Plus => "+", 115 | Punctuator::Minus => "-", 116 | Punctuator::Star => "*", 117 | Punctuator::Mod => "%", 118 | Punctuator::Pow => "**", 119 | Punctuator::Inc => "++", 120 | Punctuator::Dec => "--", 121 | Punctuator::LShift => "<<", 122 | Punctuator::RShift => ">>", 123 | Punctuator::ZRShift => ">>>", 124 | Punctuator::BitAnd => "&", 125 | Punctuator::BitOr => "|", 126 | Punctuator::BitXor => "^", 127 | Punctuator::Bang => "!", 128 | Punctuator::Tilde => "~", 129 | Punctuator::LogicalAnd => "&&", 130 | Punctuator::LogicalOr => "||", 131 | Punctuator::Question => "?", 132 | Punctuator::Colon => ":", 133 | Punctuator::Assign => "=", 134 | Punctuator::PlusAssign => "+=", 135 | Punctuator::MinusAssign => "-=", 136 | Punctuator::StarAssign => "*=", 137 | Punctuator::ModAssign => "%=", 138 | Punctuator::PowAssign => "**=", 139 | Punctuator::LShiftAssign => "<<=", 140 | Punctuator::RShiftAssign => ">>=", 141 | Punctuator::ZRShiftAssign => ">>>=", 142 | Punctuator::BitAndAssign => "&=", 143 | Punctuator::BitOrAssign => "|=", 144 | Punctuator::BitXorAssign => "^=", 145 | Punctuator::FatArrow => "=>", 146 | Punctuator::Slash => "/", 147 | Punctuator::SlashAssign => "/=", 148 | Punctuator::RBrace => "}", 149 | Punctuator::Instanceof => "instanceof", 150 | // ES2020 151 | Punctuator::QMarkDot => "?.", 152 | Punctuator::DoubleQMark => "??", 153 | } 154 | } 155 | 156 | pub fn to_string(&self) -> String { 157 | match self { 158 | Punctuator::LBrace => String::from("{"), 159 | Punctuator::LParen => String::from("("), 160 | Punctuator::RParen => String::from(")"), 161 | Punctuator::LBracket => String::from("["), 162 | Punctuator::RBracket => String::from("]"), 163 | Punctuator::Dot => String::from("."), 164 | Punctuator::Ellipsis => String::from("..."), 165 | Punctuator::Semicolon => String::from(";"), 166 | Punctuator::Comma => String::from(","), 167 | Punctuator::LAngle => String::from("<"), 168 | Punctuator::RAngle => String::from(">"), 169 | Punctuator::LEqual => String::from("<="), 170 | Punctuator::GEqual => String::from(">="), 171 | Punctuator::Equal => String::from("=="), 172 | Punctuator::NEqual => String::from("!="), 173 | Punctuator::StrictEqual => String::from("==="), 174 | Punctuator::StrictNEqual => String::from("!=="), 175 | Punctuator::Plus => String::from("+"), 176 | Punctuator::Minus => String::from("-"), 177 | Punctuator::Star => String::from("*"), 178 | Punctuator::Mod => String::from("%"), 179 | Punctuator::Pow => String::from("**"), 180 | Punctuator::Inc => String::from("++"), 181 | Punctuator::Dec => String::from("--"), 182 | Punctuator::LShift => String::from("<<"), 183 | Punctuator::RShift => String::from(">>"), 184 | Punctuator::ZRShift => String::from(">>>"), 185 | Punctuator::BitAnd => String::from("&"), 186 | Punctuator::BitOr => String::from("|"), 187 | Punctuator::BitXor => String::from("^"), 188 | Punctuator::Bang => String::from("!"), 189 | Punctuator::Tilde => String::from("~"), 190 | Punctuator::LogicalAnd => String::from("&&"), 191 | Punctuator::LogicalOr => String::from("||"), 192 | Punctuator::Question => String::from("?"), 193 | Punctuator::Colon => String::from(":"), 194 | Punctuator::Assign => String::from("="), 195 | Punctuator::PlusAssign => String::from("+="), 196 | Punctuator::MinusAssign => String::from("-="), 197 | Punctuator::StarAssign => String::from("*="), 198 | Punctuator::ModAssign => String::from("%="), 199 | Punctuator::PowAssign => String::from("**="), 200 | Punctuator::LShiftAssign => String::from("<<="), 201 | Punctuator::RShiftAssign => String::from(">>="), 202 | Punctuator::ZRShiftAssign => String::from(">>>="), 203 | Punctuator::BitAndAssign => String::from("&="), 204 | Punctuator::BitOrAssign => String::from("|="), 205 | Punctuator::BitXorAssign => String::from("^="), 206 | Punctuator::FatArrow => String::from("=>"), 207 | Punctuator::Slash => String::from("/"), 208 | Punctuator::SlashAssign => String::from("/="), 209 | Punctuator::RBrace => String::from("}"), 210 | Punctuator::Instanceof => String::from("instanceof"), 211 | // ES2020 212 | Punctuator::QMarkDot => String::from("?."), 213 | Punctuator::DoubleQMark => String::from("??"), 214 | } 215 | } 216 | } 217 | 218 | impl From<&str> for Punctuator { 219 | fn from(s: &str) -> Self { 220 | match s { 221 | "{" => Punctuator::LBrace, 222 | "(" => Punctuator::LParen, 223 | ")" => Punctuator::RParen, 224 | "[" => Punctuator::LBracket, 225 | "]" => Punctuator::RBracket, 226 | "." => Punctuator::Dot, 227 | "..." => Punctuator::Ellipsis, 228 | ";" => Punctuator::Semicolon, 229 | "," => Punctuator::Comma, 230 | "<" => Punctuator::LAngle, 231 | ">" => Punctuator::RAngle, 232 | "<=" => Punctuator::LEqual, 233 | ">=" => Punctuator::GEqual, 234 | "==" => Punctuator::Equal, 235 | "!=" => Punctuator::NEqual, 236 | "===" => Punctuator::StrictEqual, 237 | "!==" => Punctuator::StrictNEqual, 238 | "+" => Punctuator::Plus, 239 | "-" => Punctuator::Minus, 240 | "*" => Punctuator::Star, 241 | "%" => Punctuator::Mod, 242 | "**" => Punctuator::Pow, 243 | "++" => Punctuator::Inc, 244 | "--" => Punctuator::Dec, 245 | "<<" => Punctuator::LShift, 246 | ">>" => Punctuator::RShift, 247 | ">>>" => Punctuator::ZRShift, 248 | "&" => Punctuator::BitAnd, 249 | "|" => Punctuator::BitOr, 250 | "^" => Punctuator::BitXor, 251 | "!" => Punctuator::Bang, 252 | "~" => Punctuator::Tilde, 253 | "&&" => Punctuator::LogicalAnd, 254 | "||" => Punctuator::LogicalOr, 255 | "?" => Punctuator::Question, 256 | ":" => Punctuator::Colon, 257 | "=" => Punctuator::Assign, 258 | "+=" => Punctuator::PlusAssign, 259 | "-=" => Punctuator::MinusAssign, 260 | "*=" => Punctuator::StarAssign, 261 | "%=" => Punctuator::ModAssign, 262 | "**=" => Punctuator::PowAssign, 263 | "<<=" => Punctuator::LShiftAssign, 264 | ">>=" => Punctuator::RShiftAssign, 265 | ">>>=" => Punctuator::ZRShiftAssign, 266 | "&=" => Punctuator::BitAndAssign, 267 | "|=" => Punctuator::BitOrAssign, 268 | "^=" => Punctuator::BitXorAssign, 269 | "=>" => Punctuator::FatArrow, 270 | "/" => Punctuator::Slash, 271 | "/=" => Punctuator::SlashAssign, 272 | "}" => Punctuator::RBrace, 273 | "instanceof" => Punctuator::Instanceof, 274 | // ES2020 275 | "?." => Punctuator::QMarkDot, 276 | "??" => Punctuator::DoubleQMark, 277 | _ => panic!("Invalid punctuator."), 278 | } 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /giron/src/errors/errors.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | // T(AmbiguousExport, "The requested module '%' contains conflicting star exports for name '%'") 4 | // T(BadSetterArity, "Setter must have exactly one formal parameter.") 5 | // T(ConstructorIsAccessor, "Class constructor may not be an accessor") 6 | // T(ConstructorIsGenerator, "Class constructor may not be a generator") 7 | // T(ConstructorIsAsync, "Class constructor may not be an async method") 8 | // T(ConstructorIsPrivate, "Class constructor may not be a private method") 9 | // T(DerivedConstructorReturnedNonObject, "Derived constructors may only return object or undefined") 10 | // T(DuplicateConstructor, "A class may only have one constructor") 11 | // T(DuplicateProto, "Duplicate __proto__ fields are not allowed in object literals") 12 | // T(ForInOfLoopInitializer, "% loop variable declaration may not have an initializer.") 13 | // T(ForOfLet, "The left-hand side of a for-of loop may not start with 'let'.") \ 14 | // T(ForInOfLoopMultiBindings, "Invalid left-hand side in % loop: Must have a single binding.") 15 | // T(AsyncFunctionInSingleStatementContext, "Async functions can only be declared at the top level or inside a block.") 16 | // T(IllegalContinue, "Illegal continue statement: '%' does not denote an iteration statement") 17 | // T(IllegalLanguageModeDirective, "Illegal '%' directive in function with non-simple parameter list") 18 | // T(IntrinsicWithSpread, "Intrinsic calls do not support spread arguments") 19 | // T(InvalidPropertyBindingPattern, "Illegal property in declaration context") 20 | // T(InvalidRestAssignmentPattern, "`...` must be followed by an assignable reference in assignment contexts") 21 | // T(InvalidEscapedReservedWord, "Keyword must not contain escaped characters") 22 | // T(InvalidEscapedMetaProperty, "'%' must not contain escaped characters") 23 | // T(InvalidCoverInitializedName, "Invalid shorthand property initializer") 24 | // T(InvalidRegExpFlags, "Invalid flags supplied to RegExp constructor '%'") 25 | // T(InvalidPrivateFieldResolution, "Private field '%' must be declared in an enclosing class") 26 | // T(InvalidPrivateMemberRead, "Cannot read private member % from an object whose class did not declare it") 27 | // T(InvalidPrivateMemberWrite, "Cannot write private member % to an object whose class did not declare it") 28 | // T(InvalidPrivateMethodWrite, "Private method '%' is not writable") 29 | // T(InvalidPrivateGetterAccess, "'%' was defined without a getter") 30 | // T(InvalidPrivateSetterAccess, "'%' was defined without a setter") 31 | // T(JsonParseUnexpectedToken, "Unexpected token % in JSON at position %") 32 | // T(JsonParseUnexpectedTokenNumber, "Unexpected number in JSON at position %") 33 | // T(JsonParseUnexpectedTokenString, "Unexpected string in JSON at position %") 34 | // T(LabelRedeclaration, "Label '%' has already been declared") 35 | // T(LabelledFunctionDeclaration, "Labelled function declaration not allowed as the body of a control flow structure") 36 | // T(MalformedArrowFunParamList, "Malformed arrow function parameter list") 37 | // T(MalformedRegExp, "Invalid regular expression: /%/: %") 38 | // T(MalformedRegExpFlags, "Invalid regular expression flags") 39 | // T(ModuleExportUndefined, "Export '%' is not defined in module") 40 | // T(HtmlCommentInModule, "HTML comments are not allowed in modules") 41 | // T(NoCatchOrFinally, "Missing catch or finally after try") 42 | // T(FlattenPastSafeLength, "Flattening % elements on an array-like of length % is disallowed, as the total surpasses 2**53-1") 43 | // T(PushPastSafeLength, "Pushing % elements on an array-like of length % is disallowed, as the total surpasses 2**53-1") 44 | // T(ElementAfterRest, "Rest element must be last element") 45 | // T(BadSetterRestParameter, "Setter function argument must not be a rest parameter") 46 | // T(ParamDupe, "Duplicate parameter name not allowed in this context") 47 | // T(ParenthesisInArgString, "Function arg string contains parenthesis") 48 | // T(ArgStringTerminatesParametersEarly, "Arg string terminates parameters early") 49 | // T(UnexpectedEndOfArgString, "Unexpected end of arg string") 50 | // T(RestDefaultInitializer, "Rest parameter may not have a default initializer") 51 | // T(RuntimeWrongNumArgs, "Runtime function given wrong number of arguments") 52 | // T(SuperNotCalled, "Must call super constructor in derived class before accessing 'this' or returning from derived constructor") 53 | // T(SingleFunctionLiteral, "Single function literal required") 54 | // T(SloppyFunction, "In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement.") 55 | // T(SpeciesNotConstructor, "object.constructor[Symbol.species] is not a constructor") 56 | // T(StrictDelete, "Delete of an unqualified identifier in strict mode.") 57 | // T(StrictEvalArguments, "Unexpected eval or arguments in strict mode") 58 | // T(StrictOctalLiteral, "Octal literals are not allowed in strict mode.") 59 | // T(StrictDecimalWithLeadingZero, "Decimals with leading zeros are not allowed in strict mode.") 60 | // T(StrictOctalEscape, "Octal escape sequences are not allowed in strict mode.") 61 | // T(TemplateOctalLiteral, "Octal escape sequences are not allowed in template strings.") 62 | // T(ThisFormalParameter, "'this' is not a valid formal parameter name") 63 | // T(AwaitBindingIdentifier, "'await' is not a valid identifier name in an async function") 64 | // T(TooManyArguments, "Too many arguments in function call (only 65535 allowed)") 65 | // T(TooManyParameters, "Too many parameters in function definition (only 65534 allowed)") 66 | // T(TooManyProperties, "Too many properties to enumerate") 67 | // T(TooManySpreads, "Literal containing too many nested spreads (up to 65534 allowed)") 68 | // T(TooManyVariables, "Too many variables declared (only 4194303 allowed)") 69 | // T(TooManyElementsInPromiseAll, "Too many elements passed to Promise.all") 70 | // T(TypedArrayTooShort, "Derived TypedArray constructor created an array which was too small") 71 | // T(UnexpectedPrivateField, "Unexpected private field") 72 | // T(UnexpectedStrictReserved, "Unexpected strict mode reserved word") 73 | // T(UnexpectedSuper, "'super' keyword unexpected here") 74 | // T(UnexpectedNewTarget, "new.target expression is not allowed here") 75 | // T(UnexpectedTokenIdentifier, "Unexpected identifier") 76 | // T(UnexpectedTokenNumber, "Unexpected number") 77 | // T(UnexpectedTokenString, "Unexpected string") 78 | // T(UnexpectedTokenRegExp, "Unexpected regular expression") 79 | // T(UnexpectedLexicalDeclaration, "Lexical declaration cannot appear in a single-statement context") 80 | // T(UnknownLabel, "Undefined label '%'") 81 | // T(UnresolvableExport, "The requested module '%' does not provide an export named '%'") 82 | // T(UnterminatedArgList, "missing ) after argument list") 83 | // T(UnterminatedRegExp, "Invalid regular expression: missing /") 84 | // T(UnterminatedTemplate, "Unterminated template literal") 85 | // T(UnterminatedTemplateExpr, "Missing } in template expression") 86 | // T(FoundNonCallableHasInstance, "Found non-callable @@hasInstance") 87 | // T(InvalidHexEscapeSequence, "Invalid hexadecimal escape sequence") 88 | // T(UndefinedUnicodeCodePoint, "Undefined Unicode code-point") 89 | 90 | #[derive(Debug, PartialEq)] 91 | pub struct Error { 92 | pub line: usize, 93 | pub col: usize, 94 | pub errortype: ErrorType, 95 | } 96 | 97 | #[derive(Debug, PartialEq)] 98 | pub enum ErrorType { 99 | UnexpectedToken(String), 100 | UnexpectedReserved, 101 | IllegalReturn, 102 | MissingInitializer, 103 | InvalidLhsInFor, 104 | MultipleDefaultsInSwitch, 105 | NoIterationStatement, 106 | IllegalBreak, 107 | StrictWith, 108 | StrictFunction, 109 | NewlineAfterThrow, 110 | GeneratorInSingleStatementContext, 111 | MissingFunctionName, 112 | InvalidLhsInAssignment, 113 | UnexpectedTokenUnaryExponentiation, 114 | InvalidLhsInPostfixOp, 115 | InvalidLhsInPrefixOp, 116 | ParamAfterRest, 117 | InvalidDestructuringTarget, 118 | UnexpectedTemplateString, 119 | YieldInParameter, 120 | AwaitExpressionFormalParameter, 121 | UnexpectedEOS, 122 | InvalidOrUnexpectedToken, 123 | InvalidUnicodeEscapeSequence, 124 | InvalidRestBindingPattern, 125 | UnexpectedStrictReserved, 126 | } 127 | 128 | impl fmt::Display for Error { 129 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 130 | match &self.errortype { 131 | ErrorType::UnexpectedToken(s) => write!(f, "Unexpected token {}", s.clone()), 132 | ErrorType::UnexpectedReserved => write!(f, "Unexpected reserved word"), 133 | ErrorType::IllegalReturn => write!(f, "Illegal return statement"), 134 | ErrorType::MissingInitializer => { 135 | write!(f, "Missing initializer in destructuring declaration") 136 | } 137 | ErrorType::InvalidLhsInFor => write!(f, "Invalid left-hand side in for-loop"), 138 | ErrorType::MultipleDefaultsInSwitch => { 139 | write!(f, "More than one default clause in switch statement") 140 | } 141 | ErrorType::NoIterationStatement => write!( 142 | f, 143 | "Illegal continue statement: no surrounding iteration statement" 144 | ), 145 | ErrorType::IllegalBreak => write!(f, "Illegal break statement"), 146 | ErrorType::StrictWith => write!(f, "Strict mode code may not include a with statement"), 147 | ErrorType::StrictFunction => write!(f, "In strict mode code, functions can only be declared at top level or inside a block."), 148 | ErrorType::NewlineAfterThrow => write!(f, "Illegal newline after throw"), 149 | ErrorType::GeneratorInSingleStatementContext => write!(f, "Generators can only be declared at the top level or inside a block."), 150 | ErrorType::MissingFunctionName => write!(f, "Function statements require a function name"), 151 | ErrorType::InvalidLhsInAssignment => write!(f, "Invalid left-hand side in assignment"), 152 | ErrorType::UnexpectedTokenUnaryExponentiation => write!(f, "Unary operator used immediately before exponentiation expression. Parenthesis must be used to disambiguate operator precedence"), 153 | ErrorType::InvalidLhsInPostfixOp => write!(f, "Invalid left-hand side expression in postfix operation"), 154 | ErrorType::InvalidLhsInPrefixOp => write!(f, "Invalid left-hand side expression in prefix operation"), 155 | ErrorType::ParamAfterRest => write!(f, "Rest parameter must be last formal parameter"), 156 | ErrorType::InvalidDestructuringTarget => write!(f, "Invalid destructuring assignment target"), 157 | ErrorType::UnexpectedTemplateString => write!(f, "Unexpected template string"), 158 | ErrorType::YieldInParameter => write!(f, "Yield expression not allowed in formal parameter"), 159 | ErrorType::AwaitExpressionFormalParameter => write!(f, "Illegal await-expression in formal parameters of async function"), 160 | ErrorType::UnexpectedEOS => write!(f, "Unexpected end of input"), 161 | ErrorType::InvalidOrUnexpectedToken => write!(f, "Invalid or unexpected token"), 162 | ErrorType::InvalidUnicodeEscapeSequence => write!(f, "Invalid Unicode escape sequence"), 163 | ErrorType::InvalidRestBindingPattern => write!(f, "`...` must be followed by an identifier in declaration contexts"), 164 | ErrorType::UnexpectedStrictReserved => write!(f, "Unexpected strict mode reserved word"), 165 | } 166 | } 167 | } 168 | --------------------------------------------------------------------------------