New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

krl-stdlib

Package Overview
Dependencies
Maintainers
2
Versions
55
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

krl-stdlib - npm Package Compare versions

Comparing version 0.44.0 to 0.45.0

2

package.json
{
"name": "krl-stdlib",
"version": "0.44.0",
"version": "0.45.0",
"description": "Standard library for KRL",

@@ -5,0 +5,0 @@ "main": "src/index.js",

@@ -37,29 +37,18 @@ var _ = require("lodash");

// some guidelines/suggestions:
// 0. effectively check arguments.length when not fixed by the grammar (and consider null versus omitted)
// 1. convert NaN's/void 0's when needed (i.e. use cleanNulls)
// 2. don't mutate arguments (array/map)
// 3. where strings/numbers/arrays are expected, convert to them when reasonable (don't coerce arrays to maps)
// 4. prioritize errors on val's type (if applicable), then argument values/types/0. from left to right
// 5. try to return the logical noop value (e.g. false, [], val (unchanged by 3.)) for missing or unrecoverably wrongly typed arguments
// 6. don't worry about call stack limits when processing deep objects - Lodash is incorrect there too
// 7. the wiki's docs take precedence over the above
var stdlib = {};
//Infix operators///////////////////////////////////////////////////////////////
var ltEqGt = function(left, right){
if(types.typeOf(left) !== types.typeOf(right)){
return NaN; // unlike -1/0/1, all comparisons with 0 are false
var a = types.toNumberOrNull(left);
var b = types.toNumberOrNull(right);
if(a === null || b === null){
// if both are not numbers, fall back on string comparison
a = types.toString(left);
b = types.toString(right);
}
left = types.cleanNulls(left);
right = types.cleanNulls(right);
if(_.isEqual(left, right)){
return 0;
}
if(types.isArrayOrMap(left)){
return NaN; // don't compare unequal arrays or maps
}
return (left > right) ? 1 : -1;
// at this point a and b are both numbers or both strings
return a === b ? 0 : (a > b ? 1 : -1);
};
var stdlib = {};
//Infix operators///////////////////////////////////////////////////////////////
stdlib["<"] = function(ctx, left, right){

@@ -96,3 +85,3 @@ return ltEqGt(left, right) < 0;

stdlib["-"] = function(ctx, left, right){
var leftNumber = types.numericCast(left);
var leftNumber = types.toNumberOrNull(left);
if(arguments.length < 3){

@@ -104,3 +93,3 @@ if(leftNumber === null){

}
var rightNumber = types.numericCast(right);
var rightNumber = types.toNumberOrNull(right);
if(leftNumber === null || rightNumber === null){

@@ -112,4 +101,4 @@ throw new TypeError(types.toString(right) + " cannot be subtracted from " + types.toString(left));

stdlib["*"] = function(ctx, left, right){
var leftNumber = types.numericCast(left);
var rightNumber = types.numericCast(right);
var leftNumber = types.toNumberOrNull(left);
var rightNumber = types.toNumberOrNull(right);
if(leftNumber === null || rightNumber === null){

@@ -121,4 +110,4 @@ throw new TypeError(types.toString(left) + " cannot be multiplied by " + types.toString(right));

stdlib["/"] = function(ctx, left, right){
var leftNumber = types.numericCast(left);
var rightNumber = types.numericCast(right);
var leftNumber = types.toNumberOrNull(left);
var rightNumber = types.toNumberOrNull(right);
if(leftNumber === null || rightNumber === null){

@@ -128,3 +117,4 @@ throw new TypeError(types.toString(left) + " cannot be divided by " + types.toString(right));

if(rightNumber === 0){
throw new RangeError(leftNumber + " / 0 is not a number");
ctx.emit("debug", "[DIVISION BY ZERO] " + leftNumber + " / 0");
return 0;
}

@@ -134,4 +124,4 @@ return leftNumber / rightNumber;

stdlib["%"] = function(ctx, left, right){
var leftNumber = types.numericCast(left);
var rightNumber = types.numericCast(right);
var leftNumber = types.toNumberOrNull(left);
var rightNumber = types.toNumberOrNull(right);
if(leftNumber === null || rightNumber === null){

@@ -166,17 +156,8 @@ throw new TypeError("Cannot calculate " + types.toString(left) + " modulo " + types.toString(right));

stdlib["<=>"] = function(ctx, left, right){
var leftNumber = types.numericCast(left);
var rightNumber = types.numericCast(right);
if(leftNumber !== null && rightNumber !== null){
return ltEqGt(leftNumber, rightNumber);
}
var result = ltEqGt(left, right);
if(_.isNaN(result)){
throw new TypeError("The <=> operator will not compare " + types.toString(left) + " with " + types.toString(right));
}
return result;
return ltEqGt(left, right);
};
stdlib.cmp = function(ctx, left, right){
var leftStr = types.toString(left);
var rightStr = types.toString(right);
return ltEqGt(leftStr, rightStr);
left = types.toString(left);
right = types.toString(right);
return left === right ? 0 : (left > right ? 1 : -1);
};

@@ -213,13 +194,3 @@

if(type === "Number"){
if(val_type === "Null"){
return 0;
}else if(val_type === "Boolean"){
return val ? 1 : 0;
}else if(val_type === "String"){
var n = parseFloat(val);
return types.isNumber(n)
? n
: null;
}
return null;
return types.toNumberOrNull(val);
}

@@ -289,3 +260,3 @@ if(type === "RegExp"){

stdlib.chr = function(ctx, val){
var code = types.numericCast(val);
var code = types.toNumberOrNull(val);
if(code === null){

@@ -297,6 +268,9 @@ return null;

stdlib.range = function(ctx, val, end){
var startNumber = types.numericCast(val);
var endNumber = types.numericCast(end);
if(arguments.length < 3){
return [];
}
var startNumber = types.toNumberOrNull(val);
var endNumber = types.toNumberOrNull(end);
if(startNumber === null || endNumber === null){
return []; // we could return [number] if one of them is a number
return [];
}

@@ -375,11 +349,11 @@ if(startNumber < endNumber){

stdlib.substr = function(ctx, val, start, len){
start = types.numericCast(start);
val = types.toString(val);
start = types.toNumberOrNull(start);
len = types.toNumberOrNull(len);
if(start === null){
return val;
}
val = types.toString(val);
if(start > val.length){
return null;
return "";
}
len = types.numericCast(len);
var end;

@@ -519,3 +493,2 @@ if(len === null){

};
//works for maps for weak typing purposes
stdlib.length = function(ctx, val){

@@ -525,3 +498,3 @@ if(types.isArrayOrMap(val) || types.isString(val)){

}
return 0; // we could check function.prototype.length
return 0;
};

@@ -624,4 +597,3 @@ stdlib.map = function*(ctx, val, iter){

}else if(val.length === 0){
ctx.emit("error", new Error("Cannot .slice() an empty array"));
return null;
return [];
}

@@ -631,3 +603,3 @@ if(arguments.length === 2){

}
var firstIndex = types.numericCast(start);
var firstIndex = types.toNumberOrNull(start);
if(firstIndex === null){

@@ -638,8 +610,7 @@ throw new TypeError("The .slice() operator cannot use " + types.toString(start) + " as an index");

if(firstIndex > val.length){
ctx.emit("error", new RangeError("Cannot .slice() an array of length " + val.length + " from 0 to " + firstIndex));
return null;
return [];
}
return _.slice(val, 0, firstIndex + 1);
}
var secondIndex = types.numericCast(end);
var secondIndex = types.toNumberOrNull(end);
if(secondIndex === null){

@@ -656,33 +627,25 @@ throw new TypeError("The .slice() operator cannot use " + types.toString(end) + " as the other index");

}
ctx.emit("error", new RangeError("Cannot .slice() an array of length " + val.length + " from " + firstIndex + " to " + secondIndex));
return null;
return [];
};
stdlib.splice = function(ctx, val, start, n_elms, value){
stdlib.splice = function(ctx, val, start, nElements, value){
if(!types.isArray(val)){
val = [val];
}else if(val.length === 0){
throw new Error("Cannot .splice() an empty array");
return [];
}
if(arguments.length < 4){
throw new Error("The .splice() operator needs more than one argument");
}
var startIndex = types.numericCast(start);
var startIndex = types.toNumberOrNull(start);
if(startIndex === null){
throw new TypeError("The .splice() operator cannot use " + types.toString(start) + "as an index");
}
if(startIndex < 0){
throw new RangeError("Cannot start .splice() starting at index " + startIndex);
startIndex = Math.min(Math.max(startIndex, 0), val.length - 1);
var n_elm = types.toNumberOrNull(nElements);
if(n_elm === null){
throw new TypeError("The .splice() operator cannot use " + types.toString(nElements) + "as a number of elements");
}
if(startIndex >= val.length){
throw new RangeError("Cannot .splice() an array of length " + val.length + " starting at index " + startIndex);
if(n_elm < 0 || startIndex + n_elm > val.length){
n_elm = val.length - startIndex;
}
var n_elms_number = types.numericCast(n_elms);
if(n_elms_number === null){
throw new TypeError("The .splice() operator cannot use " + types.toString(n_elms) + "as a number of elements");
}
if(n_elms_number < 0 || startIndex + n_elms_number > val.length){
n_elms_number = val.length - startIndex;
}
var part1 = _.slice(val, 0, startIndex);
var part2 = _.slice(val, startIndex + n_elms);
var part2 = _.slice(val, startIndex + n_elm);
if(arguments.length < 5){

@@ -689,0 +652,0 @@ return _.concat(part1, part2);

@@ -61,2 +61,6 @@ var _ = require("lodash");

if(!message){
message = "testing stdlib[\"" + fn + "\"]";
}
if(useStrict(expected)){

@@ -78,12 +82,2 @@ strictDeepEquals(t, stdlib[fn].apply(null, [emitCTX].concat(args)), expected, message);

var tfMatrix = function(tf, args, exp){
var i;
for(i=0; i < exp.length; i++){
var j;
for(j=0; j < args.length; j++){
tf(exp[i][0], args[j], exp[i][j+1]);
}
}
};
var ytfMatrix = function*(ytf, obj, args, exp){

@@ -164,4 +158,4 @@ var i;

tfe("-", ["zero"], "TypeError");
tfe("-", [[0]], "TypeError");
tfe("-", [{}], "TypeError");
tf("-", [[0]], -1);
tf("-", [{}], 0);

@@ -173,3 +167,4 @@ tf("-", [1, 3], -2);

tfe("-", ["two", 1], "TypeError");
tfe("-", [[], "-1"], "TypeError");
tf("-", [[], "-1"], 1);
tf("-", [{a:1,b:1,c:1}, [1]], 2, "map.length() - array.length()");

@@ -186,32 +181,19 @@ tf("==", [null, NaN], true);

tf("==", [true, 1], false);
tf("==", [{a: ["b"]}, {a: ["b"]}], true);
tf("==", [{a: ["b"]}, {a: ["c"]}], false);
tfMatrix(tf, [
[2, 10], // 1
[6, 6], // 2
[10, 2], // 3
["2", "10"], // 4
["6", "6"], // 5
["10", "2"], // 6
[NaN, null], // 7
[["a", 0], ["a", 0]], // 8
[{"a": 0}, {"a": 0}], // 9
[["a", 0], ["b", 1]], // 10
[{"a": 1}, {"b": 0}], // 11
], [ // 1 2 3 4 5 6 7 8 9 10 11
["<", true, false, false, false, false, true, false, false, false, false, false],
[">", false, false, true, true, false, false, false, false, false, false, false],
["<=", true, true, false, false, true, true, true, true, true, false, false],
[">=", false, true, true, true, true, false, true, true, true, false, false],
["==", false, true, false, false, true, false, true, true, true, false, false],
["!=", true, false, true, true, false, true, false, false, false, true, true],
]);
tf("*", [5, 2], 10);
tfe("*", ["two", 1], "TypeError");
tfe("*", [[], "-1"], "TypeError");
tfe("*", [1, _.noop], "TypeError");
tf("/", [4, 2], 2);
tfe("/", ["two", 1], "TypeError");
tfe("/", [[], "-1"], "TypeError");
tfe("/", ["1", "0"], "RangeError");
tf("/", ["2", 1], 2);
tfe("/", [1, _.noop], "TypeError");
t.equals(stdlib["/"]({
emit: function(kind, err){
t.equals(kind + err, "debug[DIVISION BY ZERO] 9 / 0");
}
}, 9, 0), 0);

@@ -221,3 +203,4 @@ tf("%", [4, 2], 0);

tfe("%", [1, "two"], "TypeError");
tfe("%", [[], "-1"], "TypeError");
tf("%", [[1,2,3,4], [1,2]], 0, ".length() % .length()");
tfe("%", [_.noop, 1], "TypeError");

@@ -232,11 +215,38 @@ tf("like", ["wat", /a/], true);

tf("<=>", ["10", 5], 1);
tf("<=>", [{" ":-.5}, {" ":-.5}], 0);
tf("<=>", [NaN, void 0], 0);
tfe("<=>", [null, 0], "TypeError");
tfe("<=>", [[0, 1], [1, 1]], "TypeError");
tf("<=>", [null, 0], 0);
tf("<=>", [null, false], 0);
tf("<=>", [true, 1], 0);
tf("<=>", [true, false], 1);
tf("<=>", [[0, 1], [1, 1]], 0);
tf("<=>", [20, 3], 1);
tf("<=>", ["20", 3], 1);
tf("<=>", [20, "3"], 1);
tf("<=>", ["20", "3"], 1, "parse numbers then compare");
tf("<=>", [".2", .02], 1, "parse numbers then compare");
tf("<=>", [["a", "b"], 2], 0, ".length() of arrays");
tf("<=>", [{" ":-.5}, 1], 0, ".length() of maps");
tf("<=>", [[1,2,3], {a:"b",z:"y",c:"d"}], 0, "compare the .length() of each");
tf("<=>", [_.noop, "[Function]"], 0, "Functions drop down to string compare");
tf("<=>", [action, "[Action]"], 0, "Actions drop down to string compare");
tf("<=>", [/good/, "re#good#"], 0, "RegExp drop down to string compare");
tf("<=>", [1, "a"], -1, "if both can't be numbers, then string compare");
tf("<=>", ["to", true], -1, "if both can't be numbers, then string compare");
// <, >, <=, >= all use <=> under the hood
tf("<", ["3", "20"], true);
tf(">", ["a", "b"], false);
tf("<=", ["a", "a"], true);
tf("<=", ["a", "b"], true);
tf("<=", ["b", "a"], false);
tf(">=", ["a", "a"], true);
tf(">=", ["a", "b"], false);
tf(">=", ["b", "a"], true);
tf("cmp", ["aab", "abb"], -1);
tf("cmp", ["aab", "aab"], 0);
tf("cmp", ["abb", "aab"], 1);
tf("cmp", [void 0, NaN], 0);
tf("cmp", [void 0, NaN], 0, "\"null\" === \"null\"");
tf("cmp", ["5", "10"], 1);

@@ -248,2 +258,3 @@ tf("cmp", [5, "5"], 0);

tf("cmp", [null, 0], 1);
tf("cmp", [20, 3], -1, "cmp always converts to string then compares");

@@ -282,4 +293,5 @@ t.end();

tf("as", ["foo", "Number"], null);
tf("as", [[1,2], "Number"], null);
tf("as", [arguments, "Number"], null);
tf("as", [{}, "Number"], 0);
tf("as", [[1,2], "Number"], 2);
tf("as", [{a:"b",z:"y",c:"d"}, "Number"], 3);

@@ -352,4 +364,5 @@ t.equals(stdlib.as(defaultCTX, "^a.*z$", "RegExp").source, /^a.*z$/.source);

tf("range", [-4], []);
tf("range", [null, 0], []);
tf("range", [0, []], []);
tf("range", [-4, _.noop], []);
tf("range", [null, 0], [0], "range auto convert null -> 0");
tf("range", [0, [1,2,3]], [0, 1, 2, 3], "0.range(.length())");

@@ -431,5 +444,5 @@ tf("sprintf", [.25], "");

tf("substr", ["This is a string", 16, -1], "g");
tf("substr", ["This is a string", 25], null);
tf("substr", [["Not a string", void 0]], ["Not a string", void 0]);
tf("substr", [void 0, "Not an index", 2], void 0);
tf("substr", ["This is a string", 25], "");
tf("substr", [["Not a string", void 0]], "[Array]");
tf("substr", [void 0, "Not an index", 2], "null");

@@ -536,3 +549,3 @@ tf("uc", ["loWer"], "LOWER");

});
yield ytf("collect", [null, collectFn], {"y": [null]});
yield ytf("collect", [null, collectFn], {"x": [null]});
yield ytf("collect", [[], fnDontCall], {});

@@ -644,9 +657,10 @@ yield ytf("collect", [[7]], {});

tf("slice", [veggies, 0, 0], ["corn"]);
tf("slice", [veggies, null, NaN], ["corn"]);
tf("slice", [[], 0, 0], []);
tf("slice", [{"0": "0"}, 0, 0], [{"0": "0"}]);
tf("slice", [[], _.noop], null, "error", "Error");
tfe("slice", [veggies, _.noop], "TypeError");
tfe("slice", [veggies, 1, _.noop], "TypeError");
tfe("slice", [veggies, -1, _.noop], "TypeError");
tf("slice", [veggies, 14], null, "error", "RangeError");
tf("slice", [veggies, 2, -1], null, "error", "RangeError");
tf("slice", [veggies, 14], []);
tf("slice", [veggies, 2, -1], []);
t.deepEquals(veggies, ["corn","tomato","tomato","tomato","sprouts","lettuce","sprouts"], "should not be mutated");

@@ -661,8 +675,14 @@

tf("splice", [veggies, 1, 10, []], ["corn"]);
tfe("splice", [[], NaN], "Error");
tfe("splice", [void 0, NaN, []], "TypeError");
tfe("splice", [void 0, -1, []], "RangeError");
tfe("splice", [veggies, 7, []], "RangeError");
tfe("splice", [veggies, 6, []], "TypeError");
tf("splice", [void 0, 0, 0, []], [void 0]);
tf("splice", [[], 0, 1], []);
tf("splice", [[], NaN], []);
tfe("splice", [veggies, _.noop, 1] , "TypeError");
tfe("splice", [veggies, 0, _.noop] , "TypeError");
tf("splice", [veggies, 0, 0], veggies);
tf("splice", [veggies, 0, veggies.length], []);
tf("splice", [veggies, 0, 999], []);
tf("splice", [veggies, 0, -1], []);
tf("splice", [veggies, 0, -999], []);
tf("splice", [veggies, -1, 0], veggies);
tf("splice", [veggies, -999, 0], veggies);
tf("splice", [void 0, 0, 0], [void 0]);
t.deepEquals(veggies, ["corn","tomato","tomato","tomato","sprouts","lettuce","sprouts"], "should not be mutated");

@@ -669,0 +689,0 @@

@@ -97,14 +97,22 @@ var _ = require("lodash");

types.numericCast = function(val, round){
var roundFn = round ? _.round : _.identity;
if(types.isNumber(val)){
return roundFn(val);
types.toNumberOrNull = function(val){
switch(types.typeOf(val)){
case "Null":
return 0;
case "Boolean":
return val ? 1 : 0;
case "String":
var n = parseFloat(val);
return types.isNumber(n) ? n : null;
case "Number":
return val;
case "Array":
case "Map":
return _.size(val);
case "RegExp":
case "Function":
case "Action":
}
if(!types.isString(val)){
return null;
}
var n = parseFloat(val);
return types.isNumber(n)
? roundFn(n)
: null;
return null;
};

@@ -111,0 +119,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