exval

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');
const exval = new Exval();
const obj = {
foo: 'bar',
deep: {
hello: 'world',
},
pow: Math.pow,
};
const output = exval.stringify(obj);
console.log(output);
const obj2 = eval(`(${output})`);
assert(obj2 !== obj);
assert(obj2.deep !== obj.deep);
assert.deepEqual(obj2, obj);
Class Instance
const Exval = require('exval');
const exval = new Exval();
const c1 = (() => {
class Counter {
constructor(init) {
this.counter = init;
}
inc(a) {
this.counter += a;
}
}
return new Counter(100);
}());
assert.equal(typeof Counter, 'undefined');
c1.inc(2);
c1.foo = 'bar';
const output = exval.stringify(c1);
const c2 = eval(`(${output})`);
assert.equal(typeof Counter, 'undefined');
assert.equal(c2.counter, c1.counter);
assert.equal(c2.foo, c1.foo);
c2.inc(1);
assert.equal(c2.counter, 103);
assert.equal(c1.counter, 102);
Multiple References
const Exval = require('exval');
const exval = new Exval();
const a = { name: 'a' };
const obj = {
a1: a,
a2: a,
};
const output = exval.stringify(obj);
console.log(output);
const obj2 = eval(`(${output})`);
assert.deepEqual(obj2, obj);
assert(obj2.a1 === obj2.a2);
Close Loop References
const Exval = require('exval');
const exval = new Exval();
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);
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())
console.log(inc())
console.log(typeof counter)
const output = exval.stringify(inc);
const inc2 = eval(`{$output}`);
inc2();
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`;
}
}
exval.stringify(FooBar);
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.stringify(foo2);
exval.stringify(foo5);
Symbols
Exval currently ignoring object symbols:
const kFoo = Symbol('foo');
const obj = {
[kFoo]: 'Foo!'
};
exval.stringify(obj);
License
MIT License.
Copyright © 2016 Moshe Simantov