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

object-track

v1.0.3

Published

Wrap an object to track assignments and calls for inspection or playback.

Downloads

12

Readme

object-track

Wrap an object to track property assignments and method calls made on the wrapper directly. All such assignments and calls are forwarded to the underlying object, and an array of all such assignments and calls can be retrieved. This array can also be used to playback the same actions on a different object.

Example

If run in a browser

var canvas1 = document.createElement("canvas");
var context1 = canvas1.getContext("2d");

var Tracker = require("object-track");
var trackedContext = Tracker.track(context1);

trackedContext.strokeStyle = "#FF0000";
trackedContext.beginPath();
trackedContext.moveTo(5, 5);
trackedContext.lineTo(10, 10);
trackedContext.stroke();
// Draws a red diagonal line in context1.

var actions = Tracker.getActions(trackedContext); /* actions is [
{key: "strokeStyle", set: "#FF0000"},
{key: "beginPath", arguments: []},
{key: "moveTo", arguments: [5, 5]},
{key: "lineTo", arguments: [10, 10]},
{key: "stroke", arguments: []},
] */

var canvas2 = document.createElement("canvas");
var context2 = canvas2.getContext("2d");
Tracker.play(context2, actions);
// Draws a red diagonal line in context2.

API

var Tracker = require("object-track");

Tracker.track(object)

Returns a wrapper of the object that records all property assignments and method calls before forwarding them. The tracked properties and methods include those found by a for-in loop run on the object at the time this method was called. Extensions to the object are not tracked; see the limitations section for details.

Tracker.getActions(tracker)

Pass a return of Tracker.track. Returns an array of objects representing all property assignments and method calls made on the tracker.

  • Property assignments are recorded with keys key and set, where key is a string naming the property assigned to and set is the value that was assigned.
  • Method calls are recorded with keys key and arguments, where key is a string naming the method called and arguments is an array with all arguments passed (and not an array-like object).

Since all arrays are truey, the easiest way to distinguish between the two kinds of actions is if (action.arguments).

Tracker.play(object, actions)

The second parameter should be a return of Tracker.getActions or any object in that format. The appropriate property assignments and method calls are made on the provided object in order. Returns the object.

Install

With npm installed, run

npm install object-track

Test

With npm installed, run

npm test

To lint with ESLint, run

npm run check

Edge Cases and Limitations

tl;dr: Complex object interactions and dynamic objects are likely to break the tracker. Tracking is best done on objects with no external relationships and a fixed set of properties and methods, like a canvas context.

If a method call is made on the tracker with a context other than the tracker itself, the call is assumed to operate on a different object and is not recorded in the actions list. The call is forwarded as usual, however.

The tracker is intentionally shallow, and only calls made directly on it will be tracked. If the wrapped object has methods that call its other methods, those internal calls are not made on the tracker and will not be recorded. Example:

var Tracker = require("object-track");
var obj = {
  method1: {},
  method2: {
    this.method1();
  },
};
var tracked = Tracker.track(obj);
tracked.method2();
console.log(Tracker.getActions(tracked));
// [{key: "method2", arguments: []}]
// Notice the call to method1 is not recorded.

The environment is assumed not to support proxies or object observation, so the implementation uses nothing more complicated than Object.defineProperty, and a for-in loop is used to detect properties and methods to track. The consequences of this are

  • nonenumerable properties and methods are not in the tracker, and interactions with them as though the original object was being used may fail.
  • delete object[key] operations are not tracked and will result in that key no longer being tracked or forwarded.
  • if the object's properties contain objects themselves, mutations or method calls on them will not be tracked.
  • additions of new properties or methods to the tracked object are not tracked.
  • additions of new properties or methods to the tracker will not be forwarded.

In theory, the nonenumerable properties issue could be fixed by using Object.getOwnPropertyNames and a walk up the prototype chain. This may become an option in a future version.

Finally, objects with a key __TRACKING_DATA__ won't work correctly. (This key is used internally by the tracker.)

License

MIT