UNPKG

luhn-generator

Version:

A generator of numbers that passes the validation of Luhn algorithm or Luhn formula, also known as the 'modulus 10' or 'mod 10' algorithm

249 lines (210 loc) 6.83 kB
"use strict"; const evaluate = require("babel-helper-evaluate-path"); function isPureAndUndefined(rval, { tdz, scope = { hasBinding: () => false } } = {}) { if (rval.isIdentifier() && rval.node.name === "undefined") { // deopt right away if undefined is a local binding if (scope.hasBinding(rval.node.name, true /* no globals */ )) { return false; } return true; } if (!rval.isPure()) { return false; } const evaluation = evaluate(rval, { tdz }); return evaluation.confident === true && evaluation.value === undefined; } function getLoopParent(path, scopeParent) { const parent = path.findParent(p => p.isLoop() || p === scopeParent); // don't traverse higher than the function the var is defined in. return parent === scopeParent ? null : parent; } function getFunctionParent(path, scopeParent) { const parent = path.findParent(p => p.isFunction()); // don't traverse higher than the function the var is defined in. return parent === scopeParent ? null : parent; } function getFunctionReferences(path, scopeParent, references = new Set()) { for (let func = getFunctionParent(path, scopeParent); func; func = getFunctionParent(func, scopeParent)) { const id = func.node.id; const binding = id && func.scope.getBinding(id.name); if (!binding) { continue; } binding.referencePaths.forEach(path => { if (!references.has(path)) { references.add(path); getFunctionReferences(path, scopeParent, references); } }); } return references; } function hasViolation(declarator, scope, start) { const binding = scope.getBinding(declarator.node.id.name); if (!binding) { return true; } const scopeParent = declarator.getFunctionParent(); const violation = binding.constantViolations.some(v => { // https://github.com/babel/minify/issues/630 if (!v.node) { return false; } // return 'true' if we cannot guarantee the violation references // the initialized identifier after const violationStart = v.node.start; if (violationStart === undefined || violationStart < start) { return true; } const references = getFunctionReferences(v, scopeParent); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = references[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { const ref = _step.value; if (ref.node.start === undefined || ref.node.start < start) { return true; } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } for (let loop = getLoopParent(declarator, scopeParent); loop; loop = getLoopParent(loop, scopeParent)) { if (loop.node.end === undefined || loop.node.end > violationStart) { return true; } } }); return violation; } module.exports = function () { return { name: "transform-remove-undefined", visitor: { SequenceExpression(path, { opts: { tdz } = {} }) { const expressions = path.get("expressions"); for (let i = 0; i < expressions.length; i++) { const expr = expressions[i]; if (!isPureAndUndefined(expr, { tdz, scope: path.scope })) continue; // last value if (i === expressions.length - 1) { if (path.parentPath.isExpressionStatement()) { expr.remove(); } } else { expr.remove(); } } }, ReturnStatement(path, { opts: { tdz } = {} }) { if (path.node.argument !== null) { if (isPureAndUndefined(path.get("argument"), { tdz, scope: path.scope })) { path.node.argument = null; } } }, VariableDeclaration(path, { opts: { tdz } = {} }) { switch (path.node.kind) { case "const": break; case "let": var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = path.get("declarations")[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { const declarator = _step2.value; if (isPureAndUndefined(declarator.get("init"), { tdz })) { declarator.node.init = null; } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return != null) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } break; case "var": const start = path.node.start; if (start === undefined) { // This is common for plugin-generated nodes break; } const scope = path.scope; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = path.get("declarations")[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { const declarator = _step3.value; if (isPureAndUndefined(declarator.get("init")) && !hasViolation(declarator, scope, start)) { declarator.node.init = null; } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return != null) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } break; } } } }; };