Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

reactive-function

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

reactive-function - npm Package Compare versions

Comparing version 0.11.0 to 0.12.0

9

index.js

@@ -124,3 +124,2 @@ var ReactiveProperty = require("reactive-property");

ReactiveFunction.digest = function (){
graph

@@ -185,2 +184,10 @@ .topologicalSort(Object.keys(changed), false)

ReactiveFunction.link = function (propertyA, propertyB){
return ReactiveFunction({
inputs: [propertyA],
output: propertyB,
callback: function (x){ return x; }
});
}
module.exports = ReactiveFunction;

2

package.json
{
"name": "reactive-function",
"version": "0.11.0",
"version": "0.12.0",
"description": "A library for managing data flows and changing state.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -14,3 +14,3 @@ # reactive-function

<br>
This library is built on top of <a href="https://github.com/datavis-tech/reactive-property">reactive-property</a> and <a href="https://github.com/datavis-tech/graph-data-structure">graph-data-structure</a>
This library is built on top of <a href="https://github.com/datavis-tech/reactive-property">reactive-property</a> and <a href="https://github.com/datavis-tech/graph-data-structure">graph-data-structure</a>.
</p>

@@ -24,2 +24,3 @@

* [Tricky Case](#tricky-case)
* [Ohm's Law](#ohms-law)
* [Installing](#installing)

@@ -144,2 +145,43 @@ * [API Reference](#api-reference)

### Ohm's Law
[Ohm's Law](https://en.wikipedia.org/wiki/Ohm%27s_law) is a mathematical relationship between 3 quantities in electrical circuits:
* V, voltage. V = IR
* I, current. I = V/R
* R, resistance. R = V/I
Given any two of these values, one can calculate the third. Here's an example where if any two of the values are set, the third will automatically be calculated.
<p align="center">
<img src="https://cloud.githubusercontent.com/assets/68416/15575699/db091b10-2371-11e6-9b0e-8c77878039f5.png">
<br>
The data flow graph for Ohm's Law.
</p>
```javascript
var I = ReactiveProperty();
var V = ReactiveProperty();
var R = ReactiveProperty();
ReactiveFunction({ output: V, inputs: [I, R], callback: function (i, r){ return i * r; } });
ReactiveFunction({ output: I, inputs: [V, R], callback: function (v, r){ return v / r; } });
ReactiveFunction({ output: R, inputs: [V, I], callback: function (v, i){ return v / i; } });
V(9)
I(2)
ReactiveFunction.digest();
console.log(R()); // Prints 4.5
R(6)
I(2)
ReactiveFunction.digest();
console.log(V()); // Prints 12
V(9);
R(18);
ReactiveFunction.digest();
console.log(I()); // Prints 0.5
```
For more detailed example code, have a look at the [tests](https://github.com/datavis-tech/reactive-function/blob/master/test.js).

@@ -210,2 +252,31 @@

<a name="link" href="#link">#</a> <i>ReactiveFunction</i>.<b>link</b>(<i>propertyA</i>, <i>propertyB</i>)
Sets up one-way data binding from *propertyA* to *propertyB*. Returns an instance of **[ReactiveFunction](#constructor)**.
Arguments:
* *propertyA* - A [reactive-property](https://github.com/datavis-tech/reactive-property).
* *propertyB* - A [reactive-property](https://github.com/datavis-tech/reactive-property) that will be set to the value of *propertyA* and updated whenever *propertyA* changes.
Example:
```javascript
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var link = ReactiveFunction.link(a, b);
```
This is equivalent to:
```javascript
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var link = ReactiveFunction({
inputs: [a],
output: b,
callback: function (a){ return a; }
});
```
### Data Flow Execution

@@ -229,8 +300,13 @@

Data flow graphs can be serialized to JSON, then visualized using [graph-diagrams](https://github.com/datavis-tech/graph-diagrams/).
<a name="serialize" href="#serialize">#</a> ReactiveFunction.<b>serializeGraph</b>()
Returns a serialized form of the graph. Node names are derived from `property.propertyName` for each property. If `propertyName` is not specified, then the automaticelly generated node id (an integer) is used as the node name.
Serializes the data flow graph. Returns an object with the following properties.
* `nodes` An array of objects, each with the following properties.
* `id` The node identifier string.
* `propertyName` The property name for this node, derived from `property.propertyName` for each property.
* `links` An array of objects representing edges, each with the following properties.
* `source` The node identifier string of the source node (**u**).
* `target` The node identifier string of the target node (**v**).
Example:

@@ -263,9 +339,9 @@

"nodes": [
{ "id": "fullName" },
{ "id": "firstName" },
{ "id": "lastName" }
{ "id": "95", "propertyName": "fullName" },
{ "id": "96", "propertyName": "firstName" },
{ "id": "97", "propertyName": "lastName" }
],
"links": [
{ "source": "firstName", "target": "fullName" },
{ "source": "lastName", "target": "fullName" }
{ "source": "96", "target": "95" },
{ "source": "97", "target": "95" }
]

@@ -275,4 +351,7 @@ }

See also <a href="https://github.com/datavis-tech/graph-data-structure#serialize"><i>graph</i>.<b>serialize</b>()</a>.
See also:
* <a href="https://github.com/datavis-tech/graph-data-structure#serialize"><i>graph</i>.<b>serialize</b>()</a>
* [graph-diagrams](https://github.com/datavis-tech/graph-diagrams/)
## Related Work

@@ -279,0 +358,0 @@

@@ -13,3 +13,3 @@ // Unit tests for reactive-function.

// If true, writes graph files to ../graph-diagrams for visualization.
outputGraphs: true,
outputGraphs: false,
project: "reactive-function"

@@ -24,651 +24,638 @@ });

it("Should depend on two reactive properties.", function () {
describe("Core Functionality", function() {
it("Should depend on two reactive properties.", function () {
var firstName = ReactiveProperty("Jane");
var lastName = ReactiveProperty("Smith");
var firstName = ReactiveProperty("Jane");
var lastName = ReactiveProperty("Smith");
var fullName = ReactiveProperty();
var fullName = ReactiveProperty();
var reactiveFunction = ReactiveFunction({
inputs: [firstName, lastName],
output: fullName,
callback: function (first, last){
return first + " " + last;
}
});
var reactiveFunction = ReactiveFunction({
inputs: [firstName, lastName],
output: fullName,
callback: function (first, last){
return first + " " + last;
}
});
ReactiveFunction.digest();
assert.equal(fullName(), "Jane Smith");
ReactiveFunction.digest();
assert.equal(fullName(), "Jane Smith");
firstName("John");
ReactiveFunction.digest();
assert.equal(fullName(), "John Smith");
firstName("John");
ReactiveFunction.digest();
assert.equal(fullName(), "John Smith");
lastName("Lennon");
ReactiveFunction.digest();
assert.equal(fullName(), "John Lennon");
lastName("Lennon");
ReactiveFunction.digest();
assert.equal(fullName(), "John Lennon");
// For serialization.
firstName.propertyName = "firstName";
lastName.propertyName = "lastName";
fullName.propertyName = "fullName";
output("full-name");
// For serialization.
firstName.propertyName = "firstName";
lastName.propertyName = "lastName";
fullName.propertyName = "fullName";
output("full-name");
reactiveFunction.destroy();
});
it("Should depend on any number of reactive properties.", function () {
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty(15);
var d = ReactiveProperty();
var e = ReactiveProperty();
var rf1 = ReactiveFunction({
inputs: [a],
output: d,
callback: function (a){
return a * 2;
}
reactiveFunction.destroy();
});
var rf2 = ReactiveFunction({
inputs: [a, b, c],
output: e,
callback: function (a, b, c){
return a + b + c;
}
});
it("Should depend on any number of reactive properties.", function () {
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty(15);
ReactiveFunction.digest();
var d = ReactiveProperty();
var e = ReactiveProperty();
assert.equal(d(), 10);
assert.equal(e(), 30);
var rf1 = ReactiveFunction({
inputs: [a],
output: d,
callback: function (a){
return a * 2;
}
});
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
c.propertyName = "c";
d.propertyName = "d";
e.propertyName = "e";
output("any-number");
var rf2 = ReactiveFunction({
inputs: [a, b, c],
output: e,
callback: function (a, b, c){
return a + b + c;
}
});
rf1.destroy();
rf2.destroy();
});
ReactiveFunction.digest();
it("Should depend on a reactive function output.", function () {
assert.equal(d(), 10);
assert.equal(e(), 30);
var a = ReactiveProperty(5);
var b = ReactiveProperty();
var c = ReactiveProperty();
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
c.propertyName = "c";
d.propertyName = "d";
e.propertyName = "e";
output("any-number");
var rf1 = ReactiveFunction({
inputs: [a],
output: b,
callback: function (a){
return a * 2;
}
rf1.destroy();
rf2.destroy();
});
var rf2 = ReactiveFunction({
inputs: [b],
output: c,
callback: function (b){
return b / 2;
}
});
it("Should depend on a reactive function output.", function () {
ReactiveFunction.digest();
assert.equal(c(), 5);
var a = ReactiveProperty(5);
var b = ReactiveProperty();
var c = ReactiveProperty();
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
c.propertyName = "c";
output("abc");
var rf1 = ReactiveFunction({
inputs: [a],
output: b,
callback: function (a){
return a * 2;
}
});
rf1.destroy();
rf2.destroy();
});
var rf2 = ReactiveFunction({
inputs: [b],
output: c,
callback: function (b){
return b / 2;
}
});
it("Should depend on a property and a reactive function output.", function () {
ReactiveFunction.digest();
assert.equal(c(), 5);
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
c.propertyName = "c";
output("abc");
var c = ReactiveProperty();
var d = ReactiveProperty();
var rf1 = ReactiveFunction({
inputs: [a],
output: c,
callback: function (a){
return a * 2;
}
rf1.destroy();
rf2.destroy();
});
var rf2 = ReactiveFunction({
inputs: [b, c],
output: d,
callback: function (b, c){
return b + c;
}
});
it("Should depend on a property and a reactive function output.", function () {
ReactiveFunction.digest();
assert.equal(d(), 20);
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
c.propertyName = "c";
d.propertyName = "d";
output("abcd");
var c = ReactiveProperty();
var d = ReactiveProperty();
rf1.destroy();
rf2.destroy();
});
var rf1 = ReactiveFunction({
inputs: [a],
output: c,
callback: function (a){
return a * 2;
}
});
it("Should handle tricky case.", function () {
var rf2 = ReactiveFunction({
inputs: [b, c],
output: d,
callback: function (b, c){
return b + c;
}
});
// This is the case where model-js failed (https://github.com/curran/model),
// which cropped up as flashes of inconstistent states in Chiasm visualizations.
// For example, it happens when you change the X column in this example
// "Magic Heat Map" http://bl.ocks.org/curran/a54fc3a6578efcdc19f4
// This flaw in model-js is the main inspiration for making this library and using topological sort.
//
// a
// / \
// b |
// | d
// c |
// \ /
// e
//
var a = ReactiveProperty(5);
var b = ReactiveProperty();
var c = ReactiveProperty();
var d = ReactiveProperty();
var e = ReactiveProperty();
ReactiveFunction.digest();
assert.equal(d(), 20);
var rfs = [
ReactiveFunction({ inputs: [a], output: b, callback: function (a){ return a * 2; } }),
ReactiveFunction({ inputs: [b], output: c, callback: function (b){ return b + 5; } }),
ReactiveFunction({ inputs: [a], output: d, callback: function (a){ return a * 3; } }),
ReactiveFunction({ inputs: [c, d], output: e, callback: function (c, d){ return c + d; } })
];
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
c.propertyName = "c";
d.propertyName = "d";
output("abcd");
ReactiveFunction.digest();
assert.equal(e(), ((a() * 2) + 5) + (a() * 3));
rf1.destroy();
rf2.destroy();
});
a(10);
ReactiveFunction.digest();
assert.equal(e(), ((a() * 2) + 5) + (a() * 3));
it("Should handle tricky case.", function () {
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
c.propertyName = "c";
d.propertyName = "d";
e.propertyName = "e";
output("tricky-case");
// This is the case where model-js failed (https://github.com/curran/model),
// which cropped up as flashes of inconstistent states in Chiasm visualizations.
// For example, it happens when you change the X column in this example
// "Magic Heat Map" http://bl.ocks.org/curran/a54fc3a6578efcdc19f4
// This flaw in model-js is the main inspiration for making this library and using topological sort.
//
// a
// / \
// b |
// | d
// c |
// \ /
// e
//
var a = ReactiveProperty(5);
var b = ReactiveProperty();
var c = ReactiveProperty();
var d = ReactiveProperty();
var e = ReactiveProperty();
rfs.forEach(function (reactiveFunction){
reactiveFunction.destroy();
});
});
var rfs = [
ReactiveFunction({ inputs: [a], output: b, callback: function (a){ return a * 2; } }),
ReactiveFunction({ inputs: [b], output: c, callback: function (b){ return b + 5; } }),
ReactiveFunction({ inputs: [a], output: d, callback: function (a){ return a * 3; } }),
ReactiveFunction({ inputs: [c, d], output: e, callback: function (c, d){ return c + d; } })
];
it("Should clear changed nodes on digest.", function () {
var numInvocations = 0;
var a = ReactiveProperty(5);
var b = ReactiveProperty();
ReactiveFunction.digest();
assert.equal(e(), ((a() * 2) + 5) + (a() * 3));
var reactiveFunction = ReactiveFunction({
inputs: [a],
output: b,
callback: function (a){
numInvocations++;
return a * 2;
}
});
a(10);
ReactiveFunction.digest();
assert.equal(e(), ((a() * 2) + 5) + (a() * 3));
ReactiveFunction.digest();
ReactiveFunction.digest();
assert.equal(numInvocations, 1);
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
c.propertyName = "c";
d.propertyName = "d";
e.propertyName = "e";
output("tricky-case");
reactiveFunction.destroy();
});
it("Should automatically digest on next tick.", function (done) {
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
var reactiveFunction = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
return a + b;
}
rfs.forEach(function (reactiveFunction){
reactiveFunction.destroy();
});
});
ReactiveFunction.nextFrame(function (){
assert.equal(c(), 15);
reactiveFunction.destroy();
done();
}, 0);
it("Should automatically digest on next tick.", function (done) {
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
});
var reactiveFunction = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
return a + b;
}
});
it("Should remove listeners on destroy.", function (done){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
ReactiveFunction.nextFrame(function (){
assert.equal(c(), 15);
reactiveFunction.destroy();
done();
}, 0);
var rf = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
return a + b;
}
});
// Wait until after the first auto-digest.
ReactiveFunction.nextFrame(function (){
it("Should not invoke if an input is undefined.", function (){
var numInvocations = 0;
var a = ReactiveProperty();
var b = ReactiveProperty(10);
var c = ReactiveProperty();
rf.destroy();
var reactiveFunction = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
numInvocations++;
return a + b;
}
});
// Without the call to destroy(), this would trigger a digest.
a(20);
ReactiveFunction.digest();
assert.equal(numInvocations, 0);
// Give time for an auto-digest to occur.
ReactiveFunction.nextFrame(function (){
reactiveFunction.destroy();
});
// Confirm that a digest did not occur.
assert.equal(c(), 15);
it("Should invoke if an input is null.", function (){
var numInvocations = 0;
var a = ReactiveProperty(null);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
done();
}, 0);
}, 0);
});
var reactiveFunction = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
numInvocations++;
return a + b;
}
});
it("Should remove edges on destroy.", function (){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
ReactiveFunction.digest();
assert.equal(numInvocations, 1);
var rf = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
return a + b;
}
reactiveFunction.destroy();
});
ReactiveFunction.digest();
it("Should invoke if a single input is null.", function (){
var numInvocations = 0;
var a = ReactiveProperty(null);
assert.equal(c(), 15);
var reactiveFunction = ReactiveFunction({
inputs: [a],
callback: function (a, b){
numInvocations++;
}
});
rf.destroy();
ReactiveFunction.digest();
assert.equal(numInvocations, 1);
a(20);
reactiveFunction.destroy();
});
ReactiveFunction.digest();
assert.equal(c(), 15);
});
it("Should not invoke if an input is undefined.", function (){
var numInvocations = 0;
var a = ReactiveProperty();
var b = ReactiveProperty(10);
var c = ReactiveProperty();
var reactiveFunction = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
numInvocations++;
return a + b;
}
it("Should work without any output specified.", function (){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var sideEffect = 0;
var rf = ReactiveFunction({
inputs: [a, b],
callback: function (a, b){ sideEffect++; }
});
ReactiveFunction.digest();
assert(sideEffect);
rf.destroy();
});
ReactiveFunction.digest();
assert.equal(numInvocations, 0);
it("Should work asynchronously.", function (done){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
reactiveFunction.destroy();
});
var rf = ReactiveFunction({
inputs: [a, b],
callback: function (a, b) {
setTimeout(function(){
c(a + b);
}, 10);
}
});
it("Should invoke if an input is null.", function (){
var numInvocations = 0;
var a = ReactiveProperty(null);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
var reactiveFunction = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
numInvocations++;
return a + b;
}
c.on(function(value){
assert.equal(value, 15);
rf.destroy();
done();
});
});
ReactiveFunction.digest();
assert.equal(numInvocations, 1);
it("Should be able to implement unidirectional data binding.", function (){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var reactiveFunction = ReactiveFunction({
inputs: [a],
output: b,
callback: function (a){
return a;
}
});
reactiveFunction.destroy();
});
ReactiveFunction.digest();
assert.equal(b(), 5);
it("Should invoke if a single input is null.", function (){
var numInvocations = 0;
var a = ReactiveProperty(null);
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
output("ab");
var reactiveFunction = ReactiveFunction({
inputs: [a],
callback: function (a, b){
numInvocations++;
}
reactiveFunction.destroy();
});
ReactiveFunction.digest();
assert.equal(numInvocations, 1);
it("Should support unidirectional data binding via link().", function (){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
reactiveFunction.destroy();
});
var link = ReactiveFunction.link(a, b);
it("Should be able to implement unidirectional data binding.", function (){
ReactiveFunction.digest();
assert.equal(b(), 5);
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var reactiveFunction = ReactiveFunction({
inputs: [a],
output: b,
callback: function (a){
return a;
}
link.destroy();
});
ReactiveFunction.digest();
it("Should compute Ohm's Law.", function (){
assert.equal(b(), 5);
// These symbols are used in the definition of Ohm's law.
// See https://en.wikipedia.org/wiki/Ohm%27s_law
var I = ReactiveProperty();
var V = ReactiveProperty();
var R = ReactiveProperty();
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
output("ab");
var rfs = [
reactiveFunction.destroy();
});
// I = V / R
ReactiveFunction({
inputs: [V, R],
output: I,
callback: function (v, r){ return v / r; }
}),
it("Should be able to implement bidirectional data binding.", function (){
// V = I * R
ReactiveFunction({
inputs: [I, R],
output: V,
callback: function (i, r){ return i * r; }
}),
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
// R = V / I
ReactiveFunction({
inputs: [V, I],
output: R,
callback: function (v, i){ return v / i; }
})
];
function identity(x){ return x; }
V(9)
I(2)
ReactiveFunction.digest();
assert.equal(R(), 4.5);
var rf1 = ReactiveFunction({ inputs: [a], output: b, callback: identity });
var rf2 = ReactiveFunction({ inputs: [b], output: a, callback: identity });
R(6)
I(2)
ReactiveFunction.digest();
assert.equal(V(), 12);
ReactiveFunction.digest();
V(9);
R(18);
ReactiveFunction.digest();
assert.equal(I(), 0.5);
// The most recently added edge takes precedence.
assert.equal(b(), 10);
V(9)
I(2)
ReactiveFunction.digest();
assert.equal(R(), 4.5);
a(50);
ReactiveFunction.digest();
assert.equal(b(), 50);
// For serialization.
V.propertyName = "V";
I.propertyName = "I";
R.propertyName = "R";
output("ohms-law");
b(100);
ReactiveFunction.digest();
assert.equal(a(), 100);
rfs.forEach(function (reactiveFunction){
reactiveFunction.destroy();
});
});
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
output("data-binding");
rf1.destroy();
rf2.destroy();
});
it("Should compute Ohm's Law.", function (){
describe("Cleanup", function (){
// These symbols are used in the definition of Ohm's law.
// See https://en.wikipedia.org/wiki/Ohm%27s_law
var I = ReactiveProperty();
var V = ReactiveProperty();
var R = ReactiveProperty();
it("Should clear changed nodes on digest.", function () {
var numInvocations = 0;
var a = ReactiveProperty(5);
var b = ReactiveProperty();
var rfs = [
var reactiveFunction = ReactiveFunction({
inputs: [a],
output: b,
callback: function (a){
numInvocations++;
return a * 2;
}
});
// I = V / R
ReactiveFunction({
inputs: [V, R],
output: I,
callback: function (v, r){ return v / r; }
}),
ReactiveFunction.digest();
ReactiveFunction.digest();
assert.equal(numInvocations, 1);
// V = I * R
ReactiveFunction({
inputs: [I, R],
output: V,
callback: function (i, r){ return i * r; }
}),
reactiveFunction.destroy();
});
// R = V / I
ReactiveFunction({
inputs: [V, I],
output: R,
callback: function (v, i){ return v / i; }
})
];
it("Should remove listeners on destroy.", function (done){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
V(9)
I(2)
ReactiveFunction.digest();
assert.equal(R(), 4.5);
var rf = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
return a + b;
}
});
R(6)
I(2)
ReactiveFunction.digest();
assert.equal(V(), 12);
// Wait until after the first auto-digest.
ReactiveFunction.nextFrame(function (){
V(9);
R(18);
ReactiveFunction.digest();
assert.equal(I(), 0.5);
rf.destroy();
V(9)
I(2)
ReactiveFunction.digest();
assert.equal(R(), 4.5);
// Without the call to destroy(), this would trigger a digest.
a(20);
// For serialization.
V.propertyName = "V";
I.propertyName = "I";
R.propertyName = "R";
output("ohms-law");
// Give time for an auto-digest to occur.
ReactiveFunction.nextFrame(function (){
rfs.forEach(function (reactiveFunction){
reactiveFunction.destroy();
// Confirm that a digest did not occur.
assert.equal(c(), 15);
done();
}, 0);
}, 0);
});
});
it("Should remove the 'evaluate' function from the output on destroy.", function (){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
it("Should remove edges on destroy.", function (){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
var rf = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
return a + b;
}
});
var rf = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
return a + b;
}
});
assert.equal(typeof c.evaluate, "function");
ReactiveFunction.digest();
rf.destroy();
assert.equal(typeof c.evaluate, "undefined");
});
assert.equal(c(), 15);
it("Should work without any output specified.", function (){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var sideEffect = 0;
rf.destroy();
var rf = ReactiveFunction({
inputs: [a, b],
callback: function (a, b){
sideEffect++;
}
a(20);
ReactiveFunction.digest();
assert.equal(c(), 15);
});
ReactiveFunction.digest();
assert(sideEffect);
rf.destroy();
});
it("Should remove the 'evaluate' function from the output on destroy.", function (){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
it("Should work asynchronously.", function (done){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var c = ReactiveProperty();
var rf = ReactiveFunction({
inputs: [a, b],
output: c,
callback: function (a, b){
return a + b;
}
});
var rf = ReactiveFunction({
inputs: [a, b],
callback: function (a, b) {
setTimeout(function(){
c(a + b);
}, 10);
}
});
assert.equal(typeof c.evaluate, "function");
c.on(function(value){
assert.equal(value, 15);
rf.destroy();
done();
assert.equal(typeof c.evaluate, "undefined");
});
});
describe("Serialization", function() {
it("Should serialize the data flow graph.", function (){
// These tests may easily break if upstream tests are modified.
// Fix by changing the value of initialId.
var initialId = 56;
var firstName = ReactiveProperty("Jane");
var lastName = ReactiveProperty("Smith");
var fullName = ReactiveProperty();
it("Should serialize the data flow graph.", function (){
// For serialization.
firstName.propertyName = "firstName";
lastName.propertyName = "lastName";
fullName.propertyName = "fullName";
var firstName = ReactiveProperty("Jane");
var lastName = ReactiveProperty("Smith");
var fullName = ReactiveProperty();
var rf = ReactiveFunction({
inputs: [firstName, lastName],
output: fullName,
callback: function (first, last){
return first + " " + last;
}
});
// For serialization.
firstName.propertyName = "firstName";
lastName.propertyName = "lastName";
fullName.propertyName = "fullName";
var serialized = ReactiveFunction.serializeGraph();
var rf = ReactiveFunction({
inputs: [firstName, lastName],
output: fullName,
callback: function (first, last){
return first + " " + last;
}
});
//console.log(JSON.stringify(serialized, null, 2));
var serialized = ReactiveFunction.serializeGraph();
assert.equal(serialized.nodes.length, 3);
assert.equal(serialized.links.length, 2);
//console.log(JSON.stringify(serialized, null, 2));
assert.equal(serialized.nodes[0].id, "56");
assert.equal(serialized.nodes[1].id, "57");
assert.equal(serialized.nodes[2].id, "58");
assert.equal(serialized.nodes.length, 3);
assert.equal(serialized.links.length, 2);
assert.equal(serialized.nodes[0].propertyName, "fullName");
assert.equal(serialized.nodes[1].propertyName, "firstName");
assert.equal(serialized.nodes[2].propertyName, "lastName");
var idStart = initialId;
assert.equal(serialized.links[0].source, "57");
assert.equal(serialized.links[0].target, "56");
assert.equal(serialized.links[1].source, "58");
assert.equal(serialized.links[1].target, "56");
assert.equal(serialized.nodes[0].id, String(idStart));
assert.equal(serialized.nodes[1].id, String(idStart + 1));
assert.equal(serialized.nodes[2].id, String(idStart + 2));
rf.destroy();
});
assert.equal(serialized.nodes[0].propertyName, "fullName");
assert.equal(serialized.nodes[1].propertyName, "firstName");
assert.equal(serialized.nodes[2].propertyName, "lastName");
it("Should serialize the data flow graph and omit property names if they are not present.", function (){
var firstName = ReactiveProperty("Jane");
var lastName = ReactiveProperty("Smith");
var fullName = ReactiveProperty();
var rf = ReactiveFunction({
inputs: [firstName, lastName],
output: fullName,
callback: function (first, last){
return first + " " + last;
}
assert.equal(serialized.links[0].source, String(idStart + 1));
assert.equal(serialized.links[0].target, String(idStart));
assert.equal(serialized.links[1].source, String(idStart + 2));
assert.equal(serialized.links[1].target, String(idStart));
rf.destroy();
});
var serialized = ReactiveFunction.serializeGraph();
it("Should serialize the data flow graph and omit property names if they are not present.", function (){
assert.equal(serialized.nodes.length, 3);
assert.equal(serialized.links.length, 2);
var firstName = ReactiveProperty("Jane");
var lastName = ReactiveProperty("Smith");
var fullName = ReactiveProperty();
var rf = ReactiveFunction({
inputs: [firstName, lastName],
output: fullName,
callback: function (first, last){
return first + " " + last;
}
});
// These tests may easily break if earlier tests are modified.
// Fix by copying values from:
//console.log(JSON.stringify(serialized, null, 2));
var serialized = ReactiveFunction.serializeGraph();
assert.equal(serialized.nodes[0].id, "59");
assert.equal(serialized.nodes[1].id, "60");
assert.equal(serialized.nodes[2].id, "61");
assert.equal(serialized.nodes.length, 3);
assert.equal(serialized.links.length, 2);
assert.equal(typeof serialized.nodes[0].propertyName, "undefined");
var idStart = initialId + 3;
assert.equal(serialized.links[0].source, "60");
assert.equal(serialized.links[0].target, "59");
assert.equal(serialized.links[1].source, "61");
assert.equal(serialized.links[1].target, "59");
assert.equal(serialized.nodes[0].id, String(idStart));
assert.equal(serialized.nodes[1].id, String(idStart + 1));
assert.equal(serialized.nodes[2].id, String(idStart + 2));
rf.destroy();
});
assert.equal(typeof serialized.nodes[0].propertyName, "undefined");
it("Should serialize case without any output specified and use empty string as property name.", function (){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var sideEffect = 0;
assert.equal(serialized.links[0].source, String(idStart + 1));
assert.equal(serialized.links[0].target, String(idStart));
assert.equal(serialized.links[1].source, String(idStart + 2));
assert.equal(serialized.links[1].target, String(idStart));
var rf = ReactiveFunction({
inputs: [a, b],
callback: function (a, b){
sideEffect++;
}
rf.destroy();
});
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
var serialized = ReactiveFunction.serializeGraph();
it("Should serialize case without any output specified and use empty string as property name.", function (){
var a = ReactiveProperty(5);
var b = ReactiveProperty(10);
var sideEffect = 0;
assert.equal(serialized.nodes.length, 3);
assert.equal(serialized.links.length, 2);
var rf = ReactiveFunction({
inputs: [a, b],
callback: function (a, b){
sideEffect++;
}
});
//console.log(JSON.stringify(serialized, null, 2));
// For serialization.
a.propertyName = "a";
b.propertyName = "b";
var serialized = ReactiveFunction.serializeGraph();
assert.equal(serialized.nodes[0].id, "62");
assert.equal(serialized.nodes[1].id, "63");
assert.equal(serialized.nodes[2].id, "64");
assert.equal(serialized.nodes.length, 3);
assert.equal(serialized.links.length, 2);
assert.equal(serialized.nodes[0].propertyName, "");
assert.equal(serialized.nodes[1].propertyName, "a");
assert.equal(serialized.nodes[2].propertyName, "b");
//console.log(JSON.stringify(serialized, null, 2));
assert.equal(serialized.links[0].source, "63");
assert.equal(serialized.links[0].target, "62");
assert.equal(serialized.links[1].source, "64");
assert.equal(serialized.links[1].target, "62");
rf.destroy();
var idStart = initialId + 6;
assert.equal(serialized.nodes[0].id, String(idStart));
assert.equal(serialized.nodes[1].id, String(idStart + 1));
assert.equal(serialized.nodes[2].id, String(idStart + 2));
assert.equal(serialized.nodes[0].propertyName, "");
assert.equal(serialized.nodes[1].propertyName, "a");
assert.equal(serialized.nodes[2].propertyName, "b");
assert.equal(serialized.links[0].source, String(idStart + 1));
assert.equal(serialized.links[0].target, String(idStart));
assert.equal(serialized.links[1].source, String(idStart + 2));
assert.equal(serialized.links[1].target, String(idStart));
rf.destroy();
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc