Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

functionality

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

functionality - npm Package Compare versions

Comparing version 1.3.2 to 2.0.0

test/bugs.js

8

lib/Context.js

@@ -11,3 +11,3 @@ module.exports = Context;

this.handlers = [];
this.overloads = [];
this.matched = false;

@@ -18,5 +18,7 @@ this.result = Context.noResult;

Context.prototype.retry = function() {
if(arguments.length)
this.args = Array.prototype.slice.call(arguments);
this.matched = false;
this.result = Context.noResult;
this.handlers = this.overload.handlers.on.slice(0);
this.overloads = this.overload.handlers.on.slice();
return Context.noResult;

@@ -28,3 +30,3 @@ };

if(this.result !== undefined) return;
if(this.matched || !this.handlers.length) this.result = value;
if(this.matched || !this.overloads.length) this.result = value;
};

@@ -22,23 +22,23 @@ var Masquerade = require('./Masquerade.js'),

Functionality.prototype.any = function() {
return new Masquerade(function(value) {
return value !== undefined && value !== null;
});
Functionality.prototype.mask = function(name, handler) {
return new Masquerade(name, handler);
};
Functionality.prototype.mask = function(handler) {
return new Masquerade(handler);
};
Functionality.prototype.any = function(masks) {
var args = Array.prototype.slice.call(arguments);
return new Masquerade(function(value) {
Functionality.prototype.any = function() {
var args = Array.prototype.slice.call(arguments).map(Masquerade.type);
return new Masquerade("Any", function(value) {
if(args.length === 0) return value !== undefined && value !== null;
return _.any(args, function(mask) { return Masquerade.match(mask, value) });
}).withToString(function() {
if(args.length) return "Any " + args.join(' or ');
return "Any";
});
};
Functionality.prototype.not = function(masks) {
var args = Array.prototype.slice.call(arguments);
return new Masquerade(function(value) {
return value !== undefined && !_.any(args, function(mask) { return Masquerade.match(mask, value) });
Functionality.prototype.not = function() {
var args = Array.prototype.slice.call(arguments).map(Masquerade.type);
return new Masquerade("Not", function(value) {
return value !== undefined && !_.any(args, function(mask) { return Masquerade.match([mask], [value]); });
}).withToString(function() {
return "Not " + args.join(' or ');
});

@@ -48,12 +48,15 @@ };

Functionality.prototype.opt = function(mask) {
return new Masquerade(function(value, next) {
return new Masquerade("Optional", function(value, next) {
if(value === undefined || value === null) return next();
return Masquerade.match([mask], [value]) && next();
if(Masquerade.match([mask], [value])) return next();
return next(true);
}).withToString(function() {
return "Optional " + Masquerade.type(mask);
});
};
Functionality.prototype.gobble = function() {
return new Masquerade(function(value, next) {
return true;
Functionality.prototype.gobble = function(type) {
return new Masquerade("Gobble", function(value, next) {
if(type === undefined || Masquerade.match([type], [value])) return next(true);
});
};

@@ -5,79 +5,96 @@ var _ = require('lodash');

function Masquerade(handler) {
function Masquerade(name, handler) {
this.name = name;
this.handler = handler;
}
Masquerade.prototype.match = function(value, next) {
if(this.handler.length <= 1) return this.handler(value) && next();
return this.handler(value, next);
Masquerade.prototype.match = function(state) {
if(this.handler.length <= 1) {
var result = this.handler(state.value);
state.next();
return result;
} else
return this.handler(state.value, state.next);
};
Masquerade.match = function(mask, args) {
if(!Array.isArray(mask)) {
mask = [mask];
Masquerade.prototype.toString = function() {
return this.name;
};
Masquerade.prototype.withToString = function(formatter) {
this.toString = formatter.bind(this);
return this;
};
Masquerade.match = function(masks, args, defaultFreeze) {
if(!Array.isArray(masks)) {
masks = [masks];
args = [args];
} else {
mask = mask.slice(0);
args = args.slice(0);
}
// Normalize masks
mask = _.map(mask, function(m) {
if(m instanceof Masquerade) return m;
masks = _.map(masks, function(m) {
return Masquerade.type(m);
});
var next = function() {
if(!mask.length) return !args.length;
var m = mask.shift(), arg = args.shift();
return m.match(arg, next);
};
var maskIndex = 0;
var argIndex = 0;
var state = {
mask: masks[0],
value: args[0],
next: function(freeze) {
if(freeze === undefined) freeze = defaultFreeze;
if(!freeze) maskIndex++;
argIndex++;
return next();
};
state.mask = masks.length > maskIndex ? masks[maskIndex] : false;
state.value = args.length > argIndex ? args[argIndex] : undefined;
Masquerade.type = function(mask) {
return new Masquerade(function(value) {
// /regex/ => "a regex string"
if(mask instanceof RegExp) return mask.test(value || '');
if(freeze && argIndex >= args.length) state.mask = false;
// String => "string"
if(mask === String) return typeof value == 'string';
// Boolean => true
if(mask === Boolean) return typeof value == 'boolean';
// Number => 1
if(mask === Number) return typeof value == 'number';
return true;
}.bind(state)
};
// Function => function() { }
if(mask === Function) return _.isFunction(value);
while(state.mask) {
var mask = state.mask;
if(!mask.match(state))
return false;
}
return true;
};
// Object => {}, new Object(), new String(), "" ...
if(mask === Object) return _.isPlainObject(value);
Masquerade.types = [
[String, new Masquerade("String", function(value) { return typeof value == 'string'; })],
[Boolean, new Masquerade("Boolean", function(value) { return typeof value == 'boolean'; })],
[Number, new Masquerade("Number", function(value) { return typeof value == 'number'; })],
[Function, new Masquerade("Function", function(value) { return _.isFunction(value); })],
[Object, new Masquerade("Object", function(value) { return _.isPlainObject(value); })],
[RegExp, new Masquerade("RegExp", function(value) { return _.isRegExp(value); })],
[Date, new Masquerade("Date", function(value) { return _.isDate(value); })],
[Array, new Masquerade("Array", function(value) { return _.isArray(value); })]
];
// RegExp => /regex/
if(mask === RegExp) return _.isRegExp(value);
Masquerade.type = function(mask) {
if(mask instanceof Masquerade) return mask;
if(mask === null) return new Masquerade("null", function(value) { return value === null; });
if(mask === undefined) return new Masquerade("undefined", function(value) { return value === undefined; });
if(mask instanceof RegExp) return new Masquerade(mask.toString(), mask.test.bind(mask));
// Date => new Date()
if(mask === Date) return _.isDate(value);
for(var i = 0; i < Masquerade.types.length; i++)
if(mask === Masquerade.types[i][0]) return Masquerade.types[i][1];
// null => null
if(mask === null) return value === null;
if(Array.isArray(mask) && mask.length === 1) return new Masquerade("[" + mask[0].name + "]", function(value) {
if(!Array.isArray(value)) return false;
if(!(mask[0] instanceof Masquerade)) mask = Masquerade.type(mask[0]);
return Masquerade.match([mask], value, true);
});
// undefined => undefined
if(mask === undefined) return value === undefined;
// Array => [...]
if(mask === Array) return _.isArray(value);
// [Number] => [1, 2, 3, 4]
if(Array.isArray(mask) && mask.length == 1)
return Array.isArray(value) && Masquerade.match(_.map(value, function() { return mask[0]; }), value);
if(_.isPlainObject(mask)) return new Masquerade("Deep Object", function(value) {
// { a: Number } => { a: 1 }
if(_.isObject(mask))
return _.isObject(value) && _.every(mask, function(m, key) { return Masquerade.match(m, value[key]); });
return _.isObject(value) && _.every(mask, function(m, key) { return Masquerade.match(m, value[key]); });
});
return new Masquerade("InstanceOf", function(value) {
// Masquerade => new Masquerade()

@@ -84,0 +101,0 @@ return value instanceof mask;

@@ -9,7 +9,11 @@ var Context = require('./Context.js'),

this.__frozen = false;
this.handlers = {
var handlers = this.handlers = {
first: null,
on: [],
or: function() {
throw new Error("No overload for this method accepts the arguments " + JSON.stringify(this.args));
var error = "No overload for this method accepts the arguments (" + this.args.map(JSON.stringify).join(',') + ")\n";
error += "Available Overloads:\n";
for(var i = 0; i < handlers.on.length; i++)
error += '(' + handlers.on[i].masks.join(', ') + ')\n';
throw new Error(error);
},

@@ -51,8 +55,7 @@ then: function() {

handler = masks.pop();
masks = masks.map(Masquerade.type);
this.handlers.on.unshift(function() {
if(Masquerade.match(masks, this.args)) {
this.matched = true;
return handler.apply(this, this.args);
}
this.handlers.on.unshift({
masks: masks,
handler: handler
});

@@ -76,11 +79,13 @@ return this;

var ctx = new Context(context, this, args);
ctx.handlers = this.handlers.on.slice(0);
ctx.overloads = this.handlers.on.slice();
if(this.handlers.first) this.handlers.first.call(ctx);
while(ctx.handlers.length && !ctx.matched) {
var handler = ctx.handlers.shift();
while(ctx.overloads.length && !ctx.matched) {
var overload = ctx.overloads.shift();
if(typeof handler == 'function')
ctx.return(handler.call(ctx));
if(Masquerade.match(overload.masks, ctx.args)) {
ctx.matched = true;
ctx.return(overload.handler.apply(ctx, ctx.args));
}
}

@@ -87,0 +92,0 @@

{
"name": "functionality",
"version": "1.3.2",
"version": "2.0.0",
"description": "Simple function overloading for JavaScript",

@@ -5,0 +5,0 @@ "author": "Sierra Softworks",

@@ -178,3 +178,3 @@ # Functionality

### fn.mask(handler)
### fn.mask(name, handler)
**Creates a new mask option for use in your functions**

@@ -187,11 +187,11 @@

```javascript
var between1and10 = fn.mask(function(value) {
var between1and10 = fn.mask("Between1And10", function(value) {
return typeof value == 'number' && value > 1 && value < 10;
});
var isEmpty = fn.mask(function(value, next) {
var isEmpty = fn.mask("isEmpty", function(value, next) {
return typeof value == 'string' && !value.length && next();
})
var startsWith1 = fn.mask(function(value, next) {
var startsWith1 = fn.mask("Starts With", function(value, next) {
return value === 1;

@@ -198,0 +198,0 @@ });

@@ -18,4 +18,3 @@ var fn = require('../');

var f = fn.on(fn.not(String), function(o) {
this.args[0] = JSON.stringify(o);
return this.retry();
return this.retry(JSON.stringify(o));
}).on(String, function(s) {

@@ -27,2 +26,3 @@ return s;

f(1).should.equal('1');
f({ a: 1 }).should.equal('{"a":1}');
});

@@ -29,0 +29,0 @@

@@ -30,3 +30,3 @@ var Masquerade = require('../lib/Masquerade.js');

var optional = function(type) {
return new Masquerade(function(value) {
return new Masquerade("optional", function(value) {
return value === undefined || Masquerade.match([type], [value]);

@@ -132,3 +132,3 @@ });

it('should work correctly with basic validators', function() {
var validator = new Masquerade(function(value) {
var validator = new Masquerade("between 10 and 100", function(value) {
return typeof value == 'number' && value >= 10 && value <= 100;

@@ -144,4 +144,4 @@ });

it('should work correctly with greedy validators', function() {
var gobble = new Masquerade(function(value, next) {
return true;
var gobble = new Masquerade("gobble", function(value, next) {
return next(true);
});

@@ -148,0 +148,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc