npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

jsoid

v1.0.4

Published

Unique Object IDs for NodeJS (io.js at this time, really

Downloads

1

Readme

Table of Contents generated with DocToc

jsoid

jsoid provides unique Object IDs for NodeJS (io.js at this time, really).

Motivation

When comparing classical JavaScript to a language like Python, there are (among many others) two things that JavaScript lacks and for which workarounds are sometimes necessary:

  • Classical JS has no concept of a 'unique Object ID' (OID).
  • Classical JS has no true Maps; you only get objects which accept strings as keys;
  • Classical JS has no Weak Maps, meaning when you have to cache objects, you must always make sure to appropriately clear the cache when objects get out of scope.
  • Because classical JS has only strings as keys, there are quite a few opportunities for key collsions in case you're not careful (i.e. x[ '123' ] shadows x[ 123 ], x[ 'NaN' ] shadows x[ 0 / 0 ]` and so on).
  • Because classical JS has only strings as keys, it is somewhat hard to tack private attributes such as x.__FOOBAR_ID to objects; in the general case, you should make those keys non-iterable in the general case (which has only been possible at all for a few years).
  • Because classical JS has no OIDs, it is hard to efficiently look into a given cache or somesuch collection for the existence of a given object; an easy way to achieve that is to put everything in an array and then query for cache.indexOf( x ), but that isn't bound to scale very well (and is prone to leak memory).

All this has quite recently changed; for NodeJS people, the most obvious change is the release of io.js in January 2015, which out-of-the-box provides ES6 Symbols, Maps, Sets, WeakMaps, generators / yield, you name it.

For a quick-and-easy instruction how to install the latest iojs binary on your machine, have a look at my how-to.

It turns out that Symbols, Maps, Sets, WeakMaps have some amount of overlap in their features that make all of the above tasks a lot easier. jsoid uses ES6 WeakMaps to implement efficient, memory-safe, bijective, non-obstrusive Object IDs that can readily be used as string values for your favorite object collection. Because 'primitive' values (numbers, strings, true, NaN, ...) are supported, you should never have to care about the type of the values when using jsoid.

Usage

Install as npm install --save jsoid.

Be aware that this is not a mature module; i just slapped something together that seems to work with a tiny test (run node --harmony jsoid/index.js or, better still, iojs jsoid/index.js; if you get no output, the tests have passed).

From within your module, use

var jsoid = require( 'jsoid' )();
var d = {};
var e = {};
console.log( jsoid( d ) );
console.log( jsoid( e ) );
console.log( jsoid( 42 ) );
console.log( jsoid( 42 ) );
console.log( jsoid( 'helo' ) );
console.log( jsoid( 'helo!' ) );

to see the generated OIDs; you should get something like:

o#0
o#1
n#42
n#42
t#c6efaf27673d
t#8e95a23efc4e

Basically, that's a running ID for objects, and some kind of stringification for primitive values. Ah yes, and the IDs are all (short) strings, because with the more traditional numerical IDs, it's logically inconceivable to represent both all JS numbers and all the other possible values uniquely; only strings can do that, and only strings can act as object keys, so there's an added value there.

As it stands, each call to require( 'jsoid' )() will return a new instance of a OID-generating function; that function will generated unqiue IDs that are consistent with the IDs of all other instances of the jsoid function, but since a simple counter is used in the case of objects, you must make sure to use only one and the same jsoid function for all your IDs. I'm willing to look into ways to fix that, but that may not be worthwhile: when you can transfer an object from one point of your application to another point, you can also transfer the jsoid function. All other solutions are more cumbersome.

One more point: i arbitrarily chose 12 digits of an sha-1 hash to represent all strings because that method should be available everywhere, be good enough for the purpose, and i think the number of digits should make collisions reasonably unlikely. And i don't want a 1MB text to inadvertently get used as an object key in my code. If you're worried you could ever run into a collsion like jsoid( text1 ) === jsoid( text2 ) with text1 !== text2, read up on the math, do the figures, and complain / praise.

Source

The source is so short it fits into the readme:

@new_jsoid = new_jsoid = ( settings ) ->
  throw new Error "settings not yet supported" if settings?
  last_oid  = -1
  oid_map   = new WeakMap()
  R         = {}

  set = ( value ) ->
    R = "o##{last_oid += +1}"
    oid_map.set value, R
    return R

  R = ( value ) ->
    return 'true'       if value is true
    return 'false'      if value is false
    return 'null'       if value is null
    return 'undefined'  if value is undefined
    if is_number value
      ### `isNan is broken as per
      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN;
      however, we already know that `value` tests `true` for `util.isNumber`, so using `isNan` here should
      be alright. ###
      return 'nan' if isNaN value
      return ( if value > 0 then "+infinity" else "-infinity" ) unless isFinite value
      return "n##{value}"
    return "t##{id_from_text value, 12}" if is_string value
    return R if ( R = oid_map.get value )?
    return set value

  return R