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

exval

v0.2.0

Published

Allows taking snapshot of JavaScript objects including functions and classes and run it on other machine.

Downloads

17

Readme

exval

build npm Join the chat at https://gitter.im/remotelib/exval npm

exval allows uneval JavaScript objects back to source code (including functions and classes!). This allows making shallow copy of an object and recreate it on other machine.

WARNING: This library is under development. Many features may not work, throws exceptions or works partly. If you find a bug, please open an issue or consider contributing to this project.

If you're interested in running JavaScript on a remote machine you should checkout remote-lib as well.

Examples

Object Cloning

const Exval = require('exval'); // require exval
const exval = new Exval(); // create a new exval instance

const obj = {
  foo: 'bar',
  deep: {
    hello: 'world',
  },
  pow: Math.pow,
};

const output = exval.stringify(obj);
console.log(output); // {foo:'bar',deep:{hello:'world'},pow:Math.pow}

const obj2 = eval(`(${output})`);
assert(obj2 !== obj);
assert(obj2.deep !== obj.deep);
assert.deepEqual(obj2, obj);

Class Instance

const Exval = require('exval'); // require exval
const exval = new Exval(); // create a new exval instance

// create a counter instance
const c1 = (() => {
  class Counter {
    constructor(init) {
      this.counter = init;
    }

    inc(a) {
      this.counter += a;
    }
  }
  
  return new Counter(100);
}());

// notice that we didn't define `Counter` class here
assert.equal(typeof Counter, 'undefined');
  
// update the counter and add some custom properties
c1.inc(2);
c1.foo = 'bar';

// generate the counter instance code and run it
const output = exval.stringify(c1);
const c2 = eval(`(${output})`);

// Counter class is still undefined but our counter cloned successfully
assert.equal(typeof Counter, 'undefined');
assert.equal(c2.counter, c1.counter);
assert.equal(c2.foo, c1.foo);

// we can even continue to use it as normal!
c2.inc(1);
assert.equal(c2.counter, 103);

// the original counter stay the same
assert.equal(c1.counter, 102);

Multiple References

const Exval = require('exval'); // require exval
const exval = new Exval(); // create a new exval instance

const a = { name: 'a' };

const obj = {
  a1: a,
  a2: a,
};

const output = exval.stringify(obj);
console.log(output); // function(){var a={name:'a'};return {a1:a,a2:a}}()

const obj2 = eval(`(${output})`);
assert.deepEqual(obj2, obj);
assert(obj2.a1 === obj2.a2);

Close Loop References

const Exval = require('exval'); // require exval
const exval = new Exval(); // create a new exval instance

const obj = { foo: 'bar' };
obj.obj = obj;

const output = exval.stringify(obj);
const obj2 = eval(`(${output})`);
                  
assert(obj2 !== obj); 
assert(obj2.foo === obj.foo);
assert(obj2.obj === obj2);

Limitations

Global Vars

exvar will not copy outer scope variables that has been used in your code (including globals and environment variables). It's your responsibility to make sure that all the globals variables are correctly copied and transferred between your machines.

let glob = 1;
 
function counter() {
  return glob++;
}
 
const output = exval.stringify(counter);

console.log(output); // prints 'function counter() {\nreturn glob++;\n}'
                     // notice that the variable `glob` has been ommited

Closures

exvar can't access variables in your inner closure. Therefore it's your responsibility to regenerate them before you can use the generated code.

const inc = (() => {
  let counter = 0;
  
  return () => counter++;
})();

console.log(inc()) // "0"
console.log(inc()) // "1"
console.log(typeof counter) // "undefined"
 
const output = exval.stringify(inc);
const inc2 = eval(`{$output}`);

inc2(); // Throws "ReferenceError: counter is not defined"

The supper Keyword

It's impossible to know a method parent class outside the class context. Therefore, calling methods that using the super keyword will fail to run, although exvaling the hole class will works!

class Foo {
  getName() {
    return 'Foo';
  }
}
 
class FooBar extends Foo {
  getName() {
    return `${super.getName()}Bar`;
  }
}

// create shallow copy of the hole class will work
exval.stringify(FooBar);

// create shallow copy of the method `getName`
// throws "SyntaxError: 'super' keyword unexpected here"
exval.stringify(FooBar.prototype.getName);

Function .bind

Binding a function will hide it sourcecode so exvar couldn't access the original function sourcecode. Please prefer to use arrow functions instead of .bind.

function foo(a) { return a + 1; }
const foo2 = () => foo(2);
const foo5 = foo.bind(null, 5);

// exval'ing arrow function will work
exval.stringify(foo2); // returns "() => foo(2)"

// exval'ing bind function will not work
// throws ReferenceError: Couldn't encode native code "function () { [native code] }"
exval.stringify(foo5);

Symbols

Exval currently ignoring object symbols:

const kFoo = Symbol('foo');
const obj = {
  [kFoo]: 'Foo!'
};

exval.stringify(obj); // returns "{}"

License

MIT License. Copyright © 2016 Moshe Simantov