
Security News
Feross on the 10 Minutes or Less Podcast: Nobody Reads the Code
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.
Loot is a bunch of useful functions in the (gasp!) global scope, prefixed with $. Dont like that? you can inject them into some namespace, but that would be lame. Like chaining things? Too bad don't have tons of that. Dont like using new Blah()? Me either :-)
This is an experimental bag of tricks that is starting to look like a microframework.
Just load up the js file/s and call the global methods. Init process will protect existing globals by making backups under loot.oldValues.
This is experimental and minimally tested code, it also changes frequently. Docs may not be 100% up to date, check the tests and benchmarks for more usage examples.
see underscore.js
Most of this code is derived from the excellent async.js https://github.com/caolan/async, changes include different signatures with more information being passed around and support for objects in addition to arrays, (crazy right?) the multi-signature $parallel and $series functions are versitile enough that they are all you need to use.
$async.each(collection, iterator, callback) iteration happens as soon as possible (in parallel), completing in unknown order, fires the callback once all the done functions have been called. The first argument provided to the iterator function is a done function which accepts an error (anything that is non-falsey) which will cause the callback to be fired with the error. Arguments: collection = array or object, iterator = function(done, val, key, collection), callback = function(err, collection)
$async.eachLimit(collection, limit, iterator, callback) same as above except the added limit argument (number) defines the maximum number of parallel tasks that will happen at the same time
$async.eachSeries(collection, iterator, callback) same as $async.each but iteration happens one after the other (in series), completing in given order. Arguments: same as $async.each
$async.map(collection, iterator, callback) simmilar to $async.each, iteration happens in parallel, completing in unknown order, instead of a done function the iterator is provided a push function where the second argument gets pushed into a results array. Results are available to both iterator and callback functions. Arguments: collection = array or object, iterator = function(push, val, key, results, collection), callback = function(err, results, collection)
$async.mapSeries(collection, iterator, callback) same as $async.map but iteration happens in series, completing in given order;
$async.tasks(tasks, callback) works like a map function calling each function in the tasks array/object, the first argument to each function must be called when the function is complete and can be used to pass along an error or push a value into results. Arguments: tasks = array of functions with the signature function(push, key, results), callback = function(err, results, tasks)
$async.tasksSeries(tasks, callback) same as $async.parallelTasks but tasks are executed in series, one after the other. Alternately if results is not used push can be called "next" omitting the second argument when calling it.
$parallel a multi-signature async swiss army knife, iteration happens in parallel, completing in unknown order.
finishOrder = 0;
var asyncFunction1 = function(push, key, results) {
// lets do something that is async (requires a callback)
setTimeout(function() {
var err = null; // amazing no errors!
push(err, "index: " + key + " Finish Order: " + finishOrder);
finishOrder++;
}, 100 * Math.random());
};
$parallel([asyncFunction1, asyncFunction1, asyncFunction1], function(err, results) {
if(err) {
alert("oh nohs!");
} else {
alert("functions finish out of order but values are inserted into corrcect locations:\n" + results.toString().replace(/,/g, "\n"));
}
});
var pages = {
google: "http://www.googl.com",
cnn: "http://www.cnn.com",
apple: "http://www.apple.com",
techCrunch: "http://www.techcrunch.com",
theVerge: "http://www.theverge.com"
};
var urlHasETest = function(push, url, name, results) {
var args = arguments;
setTimeout(function() {
push(null, !!url.match("e"));
}, 100*Math.random());
};
// collection can be objects or arrays
$parallel(pages, urlHasETest, function(err, results) {
if(err) {
alert("oh nohs!");
} else {
var winners = $keys($reject(results, function(val) {return !val}));
console.log(results, winners);
alert("finished!\n" + winners.toString().replace(/,/g, "\n"));
}
});
$series a multi-signature async swiss army knife, iteration happens in series, completing in given order.
$series(func1, func2, ...) each argument is a function(push, index, results), each function is called in sequence one after the other as push functions are called, alternately if "results" is not used "push" can be called "next" omitting the second argument when calling it.
// call each function one after the other
$series(
// this fires first
function(next) {
// someAsyncFunction accepts a callback that it fires when complete
someAsyncFunction(function() {
next();
});
},
// this fires once the above function calls next
function(next) {
// someOtherAsyncFunction accepts a callback that it fires when complete
someOtherAsyncFunction(function() {
next();
});
},
// this fires once the above function calls next
function() {
// no need to call next, this is fired last
someOtherFunction();
},
);
$series(tasks, callback) an alias for $async.tasksSeries
$series(collection, iterator, callback) an alias for $async.eachSeries
This dude is optimized to perform insanely well, compared to other frameworks with a noop it can be upto 50x faster! That said, add in some work and most cross-frameowrk event system performance differences quickly diminsh to the point of being almost meaningless. Oh well. There is no priority, I've never found a use for it yet, just don't go mutiating the message all over the place when its getting sent around to multiple handlers. See item 2 for more details http://freshbrewedcode.com/jimcowart/tag/pubsub/
// create new speaker
var agent = $speak();
agent.name = "Mulder";
// subscribe to an event and alert the message
agent.listen("spookyEvent", function(msg) {
alert(msg);
});
// now tell the event
agent.tell("spookyEvent", "I want to believe.");
// alerts "I want to believe."
var partner = {
name: "Scully"
}
// add pub sub functionality to an existing object
$speak(partner);
// alternatively you can combine object creation and the speak call
var partner = $speak({
name: "Scully"
});
// now lets forward all messages from agent to partner
// there are two ways to do this, the folloing two calls are equivalent
agent.talksTo(partner);
// or
partner.listensTo(agent);
// lets use a catch-all to fire our handler on all events
partner.listen("*", function(msg, type, originalSpeaker) {
// the reciever of the function is bound to "this"
alert(originalSpeaker.name + ' said: "' + msg + '" to ' + this.name + ' in a ' + type);
});
agent.tell("random comment", "The truth is out there!");
// alerts 'Mulder said: "The truth is out there!" to Scully in a random comment'
// define a schema
$define("person", {
defaults: {
first: "John",
last: "Doe",
fullName: function() {
return this.first + " " + this.last;
}
}
});
// to delete a schema
$schema("person").drop();
// referencing the person schema we defined above, we create a new intance setting some properties up front.
var jim = $model("person", {
first: "Jim",
last: "Hipster"
});
// lets listen for a change in jim's age and alert that
var alertAgeChange = function(changes, topic, originalSpeaker) {
if ("age" in changes) {
// lets grab all the values from the model
var values = originalSpeaker.get();
alert(values.first + "'s age set to " + changes.age);
}
};
jim.listen("change", alertAgeChange);
// all model instances talk to their schema so we can also listen for changes that happen to any person model by
adding a change listener like so...
$schema("person").listen("change", alertAgeChange);
// the following will alert twice "Jim's age set to 25", firing first from the model then from the schema
jim.set({
first: "Jim",
last: "Hipster",
age: 25,
height: "5'8\""
});
var dom = $el("div.myDiv", "this is my div!");
// by default $el outputs dom nodes
console.log(dom, dom.toString());
//prints: <div id="message">...</div>, [object HTMLDivElement]
$doc.useRealDom(false);
var items = [ 1, 2, 3, 4];
var div2 = $el('div#message', [
$el('a.biglink', {href: 'http://www.google.com'}, 'A link to Google'),
$el('ul', $map(items, function(item) {
return $el('li.item', item + '. Item');
})
)
]);
// with useRealDom == false, toString will output the html
console.log(div2, div2.toString());
//prints: Object, <div id="message"><a href="http://www.google.com" class="biglink">A link to Google</a><ul><li class="item">1. Item</li><li class="item">2. Item</li><li class="item">3. Item</li><li class="item">4. Item</li></ul></div>
$dom(domSyntaxArray) build dom structures or html using a simplified json syntax of nested arrays with selectors defining dom nodes, followed by an optional attributes object then an aray of children or a string of inner html. Makes use of $el so will output dom nodes or html strings depending on $doc.useRealDom(bool), Syntax guide follows:
dom instruction syntax:
dom instruction patterns:
var newsItem = {
title: "Life discovered on Mars!",
content: "Lorem ipsum dolor sit amet."
};
var dom = $dom([
"div.newsItem", [
"h3", newsItem.title,
"p", newsItem.content
]
]);
// with useRealDom == false, toString will output the html
console.log(dom.toString());
// prints <div class="newsItem"><h3>Life discovered on Mars!</h3><p>Lorem ipsum dolor sit amet.</p></div>
// first lets define a partial
$part("todoItem", function(data) {
return $dom([
"div", {className: "todo " + data.done ? "done" : ""},[
"div.display", [
"input.check", {type: "checkbox", checked: data.done},
"label.todo-content", data.content,
"span.todo-destroy"
],
"div.edit", [
"input.todo-input", {type: "text", value: data.content}
]
]
]);
});
var todoItems = [{
content: "walk dog",
done: false
}, {
content: "get milk",
done: true
},{
content: "find better things to do than make yet another todo application",
done: false
}];
var todoListDom = $dom([
"ul.todos", $map(todoItems, $part("todoItem"))
]);
// with useRealDom == false, toString will output the html
console.log(todoListDom.toString());
// prints: <ul class="todos"><div class="done"><div class="display"><input type="checkbox" checked="false" class="check"/><label class="todo-content">walk dog</label><span class="todo-destroy"></span></div><div class="edit"><input type="text" value="walk dog" class="todo-input"/></div></div><div class="done"><div class="display"><input type="checkbox" checked="checked" class="check"/><label class="todo-content">get milk</label><span class="todo-destroy"></span></div><div class="edit"><input type="text" value="get milk" class="todo-input"/></div></div><div class="done"><div class="display"><input type="checkbox" checked="false" class="check"/><label class="todo-content">find better things to do than make yet another todo application</label><span class="todo-destroy"></span></div><div class="edit"><input type="text" value="find better things to do than make yet another todo application" class="todo-input"/></div></div></ul>
// first lets define a partial
$partial("newsItem", function(data) {
return $dom([
"div.newsItem", [
"h3", data.title,
"p", data.content
]
]);
});
//now lets build our news list dom using map and our new partial as the iterator
var dom = $map(newsItems, $partials("newsItems"));
$isSelector(string) returns true if the provided string is a valid selector in the above dom syntax. leading tag must be of the following set.
validTags = "a abbr acronym address applet area article aside audio b base basefont bdi bdo big blockquote body br button canvas caption center cite code col colgroup command datalist dd del details dfn dir div dl dt em embed fieldset figcaption figure font footer form frame frameset h1 head header hgroup hr html i iframe img input ins keygen kbd label legend li link map mark menu meta meter nav noframes noscript object ol optgroup option output p param pre progress q rp rt ruby s samp script section select small source span strike strong style sub summary sup table tbody td textarea tfoot th thead time title tr track tt u ul var video wbr";
tags list derived from http://www.w3schools.com/html5/html5_reference.asp
$isSelector.addTag(string) The tag you wnt to use not in the list above? Add it to the list with this function.
warning: views are poorly defined and tested, avoid for now.
Why use this? It is an experimental performance enhancement, ideally an object pool will limit the total ammount of work performed, memory used and garbage produced. Tests and benchmarks yet to be written, memory use and GC analysis yet to be performed.
FAQs
a bunch of js functions i like to use as globals starting with $
The npm package loot receives a total of 9 weekly downloads. As such, loot popularity was classified as not popular.
We found that loot demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.

Research
/Security News
Campaign of 108 extensions harvests identities, steals sessions, and adds backdoors to browsers, all tied to the same C2 infrastructure.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.