react 0.2.6 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/.npmignore +2 -1
  2. package/README.md +94 -149
  3. package/doc/advanced.md +161 -0
  4. package/doc/color-def.graffle +938 -0
  5. package/doc/color-def.png +0 -0
  6. package/doc/default-simple.dot +19 -0
  7. package/doc/default-simple.dot.png +0 -0
  8. package/examples/default-events1.js +33 -6
  9. package/examples/{fstr1.js → default-log-events.js} +20 -13
  10. package/examples/default-simple.js +45 -0
  11. package/lib/base-task.js +8 -6
  12. package/lib/cb-task.js +14 -1
  13. package/lib/core.js +43 -12
  14. package/lib/dsl.js +14 -6
  15. package/lib/event-collector.js +65 -0
  16. package/lib/event-manager.js +29 -16
  17. package/lib/finalcb-first-task.js +16 -10
  18. package/lib/finalcb-task.js +17 -10
  19. package/lib/input-parser.js +7 -3
  20. package/lib/log-events.js +86 -0
  21. package/lib/parse.js +6 -3
  22. package/lib/promise-resolve.js +35 -0
  23. package/lib/promise-task.js +89 -0
  24. package/lib/ret-task.js +1 -1
  25. package/lib/task.js +32 -23
  26. package/lib/track-tasks.js +60 -0
  27. package/lib/validate.js +3 -3
  28. package/lib/vcon.js +6 -3
  29. package/lib/when-task.js +81 -0
  30. package/package.json +5 -3
  31. package/react.js +33 -5
  32. package/test/core-deferred.test.js +134 -0
  33. package/test/core-promised.test.js +132 -0
  34. package/test/core-when.test.js +84 -0
  35. package/test/core.test.js +108 -60
  36. package/test/dsl.test.js +58 -6
  37. package/test/exec-options.test.js +2 -1
  38. package/test/finalcb-task.test.js +6 -5
  39. package/test/input-parser.test.js +10 -6
  40. package/test/module-use.test.js +16 -199
  41. package/test/promise-auto-resolve.test.js +52 -0
  42. package/test/validate.test.js +4 -2
  43. package/test/vcon.test.js +13 -0
  44. package/Jakefile.js +0 -8
  45. package/examples/chain-events1.js +0 -34
  46. package/examples/chain1.js +0 -19
  47. package/examples/fstr-events1.js +0 -51
  48. package/examples/pcode1.js +0 -22
  49. package/jake-tasks/jake-test.js +0 -64
  50. package/lib/chain.js +0 -148
  51. package/lib/fstr.js +0 -119
  52. package/lib/pcode.js +0 -173
  53. package/oldExamples/analyze.js +0 -29
  54. package/oldExamples/analyze2.js +0 -29
  55. package/oldExamples/example10-dsl.js +0 -63
  56. package/oldExamples/example11.js +0 -62
  57. package/oldExamples/example12.js +0 -63
  58. package/oldExamples/example13.js +0 -63
  59. package/oldExamples/example14.js +0 -63
  60. package/oldExamples/example15.js +0 -75
  61. package/oldExamples/example6-ast.js +0 -47
  62. package/oldExamples/example6-dsl.js +0 -49
  63. package/oldExamples/example8-ast.js +0 -55
  64. package/oldExamples/example8-dsl.js +0 -53
  65. package/oldExamples/example9-ast.js +0 -58
  66. package/oldExamples/example9-dsl.js +0 -57
  67. package/oldExamples/function-str-ex1.js +0 -33
  68. package/oldExamples/function-str-ex2.js +0 -67
  69. package/oldExamples/trait1.js +0 -41
  70. package/oldExamples/trait2.js +0 -44
  71. package/test/chain.test.js +0 -253
  72. package/test/fstr.test.js +0 -300
  73. package/test/pcode.test.js +0 -335
package/lib/task.js CHANGED
@@ -4,16 +4,21 @@ var util = require('util');
4
4
  var sprintf = require('sprintf').sprintf;
5
5
  var array = require('ensure-array');
6
6
  var CbTask = require('./cb-task.js');
7
+ var PromiseTask = require('./promise-task.js');
7
8
  var RetTask = require('./ret-task.js');
9
+ var WhenTask = require('./when-task.js');
8
10
  var FinalCbTask = require('./finalcb-task.js');
9
11
  var FinalCbFirstSuccTask = require('./finalcb-first-task.js');
10
12
  var STATUS = require('./status.js');
11
13
  var error = require('./error.js');
12
14
  var VContext = require('./vcon.js');
15
+ var EventManager = require('./event-manager.js');
13
16
 
14
17
  var TASK_TYPES = {
15
18
  cb: CbTask,
16
- ret: RetTask
19
+ ret: RetTask,
20
+ promise: PromiseTask,
21
+ when: WhenTask
17
22
  };
18
23
  function taskTypeKeys() { return Object.keys(TASK_TYPES); }
19
24
 
@@ -106,7 +111,8 @@ function validateLocalFunctions(inParams, taskDefs, locals) {
106
111
  var mock_args = inParams.map(function (p) { return foo; }); //mock args with fns
107
112
  var vCon = VContext.create(mock_args, inParams, locals);
108
113
  var tasks = taskDefs.map(create);
109
- tasks.forEach(function (t, idx) {
114
+ var tasksWFunctions = tasks.filter(function (t) { return (t.type !== 'when'); }); // non-when tasks need f
115
+ tasksWFunctions.forEach(function (t, idx) {
110
116
  if (!t.functionExists(vCon)) { // error if function doesnt exist AND
111
117
  if (!t.isMethodCall()) errors.push(sprintf(LOCAL_FN_MISSING, t.f, idx)); // not method OR
112
118
  else {
@@ -121,7 +127,9 @@ function validateLocalFunctions(inParams, taskDefs, locals) {
121
127
  }
122
128
 
123
129
  function fName(fn) {
124
- return (typeof(fn) === 'string') ? fn : fn.name;
130
+ return (fn) ?
131
+ ((fn.name) ? fn.name : fn) : // if defined, try name, otherwise toString()
132
+ 'undefined'; // not defined, use undefined
125
133
  }
126
134
 
127
135
  /**
@@ -155,27 +163,28 @@ function create(taskDef) {
155
163
  return new TaskConstructor(taskDef);
156
164
  }
157
165
 
158
- function createOutTask(taskDef, cbFinal, tasks, vCon) {
166
+ function createOutTask(taskDef, cbFunc, tasks, vCon, execOptions, env) {
159
167
  setMissingOutTaskType(taskDef);
160
- var TaskConstructor = OUT_TASK_TYPES[taskDef.type];
161
- return new TaskConstructor(taskDef, cbFinal, tasks, vCon);
162
- }
163
-
164
- function createCallback(task, handleTaskError, vCon, contExec) {
165
- return function (err, arg0, arg1, argn) {
166
- var args = Array.prototype.slice.call(arguments, 1);
167
- if (err) { handleTaskError(task, err); return; } //handle error and return, we are done
168
-
169
- //no error, save callback args to vCon context, then continue execution
170
- vCon.saveResults(task.out, args);
171
- task.complete(args);
172
- contExec();
168
+ var outTaskOptions = {
169
+ taskDef: taskDef,
170
+ cbFunc: cbFunc,
171
+ tasks: tasks,
172
+ vCon: vCon,
173
+ execOptions: execOptions,
174
+ env: env,
175
+ TaskConstructor: OUT_TASK_TYPES[taskDef.type]
173
176
  };
177
+ EventManager.global.emit(EventManager.TYPES.EXEC_OUTTASK_CREATE, outTaskOptions); // hook
178
+ var TaskConstructor = outTaskOptions.TaskConstructor; // hook could have changed
179
+ return new TaskConstructor(outTaskOptions);
174
180
  }
175
-
181
+
176
182
  function createErrorHandler(vCon, outTask) {
177
183
  return function handleError(task, err) {
178
184
  task.status = STATUS.ERRORED;
185
+ task.error = err;
186
+ outTask.env.currentTask = task;
187
+ outTask.env.flowEmitter.emit(EventManager.TYPES.EXEC_TASK_ERRORED, task);
179
188
  var errWithMeta = error.augmentError(err, {task: task, vcon: vCon});
180
189
  outTask.exec(errWithMeta); //call the final callback with the first error hit
181
190
  };
@@ -197,7 +206,7 @@ function execTasks(tasksReady, vCon, handleError, contExec) {
197
206
  case everything is fine. If no tasks are running then
198
207
  call handleError since this will never complete.
199
208
  */
200
- function checkIfTasksRunning(vCon, tasks, handleError) {
209
+ function checkIfTasksRunning(vCon, tasks, handleError, env) {
201
210
  var tasksRunning = tasks.filter(function (t) {
202
211
  return (t.status === STATUS.RUNNING || t.status === STATUS.READY);
203
212
  });
@@ -205,13 +214,14 @@ function checkIfTasksRunning(vCon, tasks, handleError) {
205
214
  var remainingTasks = tasks.filter(function (t) { return (!t.status); });
206
215
  var remainingTNames = remainingTasks.map(function (t) { return t.name; });
207
216
  var errMsg = sprintf(NO_TASKS_RUNNING_WONT_COMPLETE, remainingTNames.join(', '));
208
- handleError({}, new Error(errMsg));
217
+ var emptyTask = { env: env };
218
+ handleError(emptyTask, new Error(errMsg));
209
219
  }
210
220
  }
211
221
 
212
- function findReadyAndExec(vCon, tasks, tasksByName, handleError, contExec) {
222
+ function findReadyAndExec(vCon, tasks, tasksByName, handleError, contExec, env) {
213
223
  var tasksReady = findTasksReady(vCon, tasks, tasksByName);
214
- if (!tasksReady.length) checkIfTasksRunning(vCon, tasks, handleError); // no tasks to run, check if ok
224
+ if (!tasksReady.length) checkIfTasksRunning(vCon, tasks, handleError, env); // no tasks to run, check if ok
215
225
  execTasks(tasksReady, vCon, handleError, contExec);
216
226
  }
217
227
 
@@ -234,6 +244,5 @@ exports.validateLocalFunctions = validateLocalFunctions;
234
244
  exports.nameTasks = nameTasks;
235
245
  exports.create = create;
236
246
  exports.createOutTask = createOutTask;
237
- exports.createCallback = createCallback;
238
247
  exports.createErrorHandler = createErrorHandler;
239
248
  exports.findReadyAndExec = findReadyAndExec;
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ Track the tasks, start, complete, args, results, elapsed time
5
+ Emits events that can be monitored
6
+
7
+ - track start and complete
8
+ - record args each task was called with
9
+ - record results at completion
10
+ - record start, end, and calc elapsed time
11
+ - emits flow.begin with flowEnv
12
+ - emits task.begin with task
13
+ - emits task.complete with task
14
+ - emits flow complete with flowEnv
15
+ - emits flow errored with flowEnv
16
+
17
+ @example
18
+ var react = require('react');
19
+ react.trackTasks(); // enable task and flow tracking
20
+ */
21
+
22
+
23
+ var react = require('../'); // require('react');
24
+
25
+ react.events.on(react.events.TYPES.EXEC_FLOW_START, function (env){
26
+ env.startTime = Date.now();
27
+ env.flowEmitter.emit(react.events.TYPES.FLOW_BEGIN, env); //fire public ev
28
+ });
29
+
30
+ react.events.on(react.events.TYPES.EXEC_TASK_START, function (task) {
31
+ task.startTime = Date.now();
32
+ task.env.flowEmitter.emit(react.events.TYPES.TASK_BEGIN, task); //fire public ev
33
+ });
34
+
35
+ react.events.on(react.events.TYPES.EXEC_TASK_COMPLETE, function (task) {
36
+ task.endTime = Date.now();
37
+ task.elapsedTime = task.endTime - task.startTime;
38
+ task.env.flowEmitter.emit(react.events.TYPES.TASK_COMPLETE, task); // fire public ev
39
+ });
40
+
41
+ react.events.on(react.events.TYPES.EXEC_TASK_ERRORED, function (task) {
42
+ task.endTime = Date.now();
43
+ task.elapsedTime = task.endTime - task.startTime;
44
+ task.env.flowEmitter.emit(react.events.TYPES.TASK_ERRORED, task); // fire public ev
45
+ });
46
+
47
+ react.events.on(react.events.TYPES.EXEC_FLOW_COMPLETE, function (env) {
48
+ env.endTime = Date.now();
49
+ env.elapsedTime = env.endTime - env.startTime;
50
+ env.flowEmitter.emit(react.events.TYPES.FLOW_COMPLETE, env); //fire public ev
51
+ });
52
+
53
+ react.events.on(react.events.TYPES.EXEC_FLOW_ERRORED, function (env) {
54
+ env.endTime = Date.now();
55
+ env.elapsedTime = env.endTime - env.startTime;
56
+ env.flowEmitter.emit(react.events.TYPES.FLOW_ERRORED, env); //fire public ev
57
+ });
58
+
59
+
60
+ module.exports = react; // return react
package/lib/validate.js CHANGED
@@ -13,8 +13,8 @@ var LOCALS_NOTNULL = 'ast.locals should not be null';
13
13
  var DUP_OUTPUTS = 'multiple tasks output the same param, must be unique. param';
14
14
  var MISSING_INPUTS = 'missing or mispelled variable referenced in flow definition: %s';
15
15
 
16
- // match any of our literals true, false, int, float, quoted strings, or is property (has dot)
17
- var LITERAL_OR_PROP_RE = /^(true|false|\-?[0-9\.]+)$|'|"|\./i;
16
+ // match any of our literals true, false, int, float, quoted strings, or is property (has dot), match vcon.js
17
+ var LITERAL_OR_PROP_RE = /^(true|false|this|null|\-?[0-9\.]+)$|'|"|\./i;
18
18
 
19
19
  var validateInParams, validateTasks, validateOutTask, validateTaskNamesUnique;
20
20
  var validateLocals, validateOuputsUnique, validateNoMissingNames;
@@ -153,7 +153,7 @@ function validateNoMissingNames(ast) {
153
153
  if (!isLiteralOrProp(p) && !names[p]) accum.push(sprintf(MISSING_INPUTS, p)); // add error if missing
154
154
  return accum;
155
155
  }, errors);
156
- return errors; //TODO reenable
156
+ return errors;
157
157
  }
158
158
 
159
159
  module.exports = validate;
package/lib/vcon.js CHANGED
@@ -16,6 +16,7 @@ VContext.prototype.getVar = function (name) { //name might be simple or obj.prop
16
16
  // literal checks need to match what is in validate.js
17
17
  if (name === 'true') return true;
18
18
  if (name === 'false') return false;
19
+ if (name === 'null') return null;
19
20
  if (/^-?[0-9]+$/.test(name)) return parseInt(name, 10); //int
20
21
  if (/^-?[0-9.]+$/.test(name)) return parseFloat(name); //float
21
22
  var m = /^("|')([^\1]*)\1$/.exec(name); //check for quoted string " or '
@@ -32,13 +33,13 @@ VContext.prototype.getVar = function (name) { //name might be simple or obj.prop
32
33
  variable :LAST_RESULTS which keeps an array of the last values
33
34
  which can be used for chaining and testing last results, etc.
34
35
  */
35
- VContext.prototype.saveResults = function(paramArr, valuesArr) { // set values for params
36
+ VContext.prototype.saveResults = function (paramArr, valuesArr) { // set values for params
36
37
  var self = this;
37
38
  paramArr.forEach(function (k, idx) { //save values to v context
38
39
  self.setVar(k, (valuesArr[idx] !== undefined) ? valuesArr[idx] : null); //upgrade any undefined to null
39
40
  });
40
41
  this.setLastResults(valuesArr);
41
- }
42
+ };
42
43
 
43
44
  VContext.prototype.setVar = function (name, value) { //name might be simple or obj.prop
44
45
  if (!name) return; // if name is undefined or null, then discard
@@ -61,9 +62,11 @@ VContext.prototype.setVar = function (name, value) { //name might be simple or o
61
62
  Ignore extra arguments passed in. Locals can be
62
63
  passed into seed the VContext otherwise empty {}
63
64
  will be used
65
+ @param self used to pass 'this' context in
64
66
  */
65
- VContext.create = function (args, inParams, locals) {
67
+ VContext.create = function (args, inParams, locals, self) {
66
68
  var initValues = {};
69
+ if (self) initValues['this'] = self;
67
70
  if (locals) Object.keys(locals).forEach(function (k) { initValues[k] = locals[k]; }); // copy over keys
68
71
  var vContext = new VContext();
69
72
  vContext.values = args.reduce(function (vcon, x, idx) { // create vCon start with input args
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ When task which checks if is a promise (has a then method)
5
+ and waits for it to resolve.
6
+
7
+ If argument does not have a then method, it resolves immediately
8
+ */
9
+
10
+ var util = require('util');
11
+ var sprintf = require('sprintf').sprintf;
12
+
13
+ var BaseTask = require('./base-task.js');
14
+
15
+ function format_error(errmsg, obj) {
16
+ return sprintf('%s - %s', errmsg, util.inspect(obj));
17
+ }
18
+
19
+ var REQ = 'whenTask requires a, out';
20
+ var A_REQ = 'whenTask requires a to be an array[1] of string param names';
21
+ var OUT_REQ = 'whenTask requires out to be an array[1] of string param names';
22
+
23
+ function WhenTask(taskDef) {
24
+ var self = this;
25
+ Object.keys(taskDef).forEach(function (k) { self[k] = taskDef[k]; });
26
+ }
27
+
28
+ WhenTask.prototype = new BaseTask();
29
+ WhenTask.prototype.constructor = WhenTask;
30
+
31
+ WhenTask.prototype.f = function when() { // just here to keep validations happy
32
+ }
33
+
34
+ WhenTask.validate = function (taskDef) {
35
+ var errors = [];
36
+ if (!taskDef.a || !taskDef.out) {
37
+ errors.push(format_error(REQ, taskDef));
38
+ } else {
39
+ if (! (Array.isArray(taskDef.a) && taskDef.a.length === 1 &&
40
+ taskDef.a.every(function (x) { return (typeof(x) === 'string'); }))) {
41
+ errors.push(format_error(A_REQ, taskDef));
42
+ }
43
+ if (! (Array.isArray(taskDef.out) && taskDef.out.length <= 1 &&
44
+ taskDef.out.every(function (x) { return (typeof(x) === 'string'); }))) {
45
+ errors.push(format_error(OUT_REQ, taskDef));
46
+ }
47
+ }
48
+ return errors;
49
+ };
50
+
51
+ WhenTask.prototype.prepare = function prepare(handleTaskError, vCon, contExec) {
52
+ var self = this;
53
+ this.nextFn = function (arg) {
54
+ var args = Array.prototype.slice.call(arguments);
55
+ vCon.saveResults(self.out, args);
56
+ self.complete(args);
57
+ contExec();
58
+ };
59
+ this.failFn = function (err) {
60
+ handleTaskError(self, err);
61
+ };
62
+ };
63
+
64
+ WhenTask.prototype.exec = function exec(vCon, handleError, contExec) {
65
+ try {
66
+ var args = this.a.map(function (k) { return vCon.getVar(k); }); //get args from vCon
67
+ //console.error('WhenTask.exec.args=', args);
68
+ //console.error('WhenTask.exec.vCon=', vCon);
69
+ this.start(args); //note the start time, args
70
+ var arg = args[0]; // one value allowed
71
+ if (arg && typeof(arg.then) === 'function') { // is a promise
72
+ arg.then(this.nextFn, this.failFn);
73
+ } else { // not a promise continue immediately
74
+ this.nextFn(arg);
75
+ }
76
+ } catch (err) { //catch and handle the task error, calling final cb
77
+ handleError(this, err);
78
+ }
79
+ };
80
+
81
+ module.exports = WhenTask;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react",
3
- "description": "React is a javascript module to make it easier to work with asynchronous code, by reducing boilerplate code and improving error and exception handling while allowing variable and task dependencies when defining flow.",
4
- "version": "0.2.6",
3
+ "description": "React is a javascript module implementing a lightweight rules engine to make it easier to work with asynchronous code, by reducing boilerplate code and improving error and exception handling while allowing variable and task dependencies when defining flow.",
4
+ "version": "0.5.0",
5
5
  "author": "Jeff Barczewski <jeff.barczewski@gmail.com>",
6
6
  "repository": { "type": "git", "url": "http://github.com/jeffbski/react.git" },
7
7
  "bugs" : { "url": "http://github.com/jeffbski/react/issues" },
@@ -15,7 +15,9 @@
15
15
  },
16
16
  "devDependencies": {
17
17
  "tap" : "~0.1.0",
18
- "tapr" : "~0.1.0"
18
+ "tapr" : "~0.1.0",
19
+ "promised-io" : "~0.3.0",
20
+ "Deferred" : "~0.1.1"
19
21
  },
20
22
  "scripts": {
21
23
  "test": "node_modules/.bin/tapr test"
package/react.js CHANGED
@@ -2,11 +2,39 @@
2
2
 
3
3
  var core = require('./lib/core.js');
4
4
 
5
+ /**
6
+ If called, load the built-in plugin for log events and invoke
7
+
8
+ @param flowFn [function] if not provided uses global react
9
+ @param eventWildcard [string] pattern to log events for
10
+ */
11
+ function logEvents(flowFn, eventWildcard) {
12
+ var logEventsMod = require('./lib/log-events');
13
+ if (!eventWildcard && typeof(flowFn) === 'string') { // only wildcard provided
14
+ eventWildcard = flowFn;
15
+ flowFn = undefined;
16
+ }
17
+ return logEventsMod.logEvents(flowFn, eventWildcard);
18
+ }
19
+
20
+ /**
21
+ Enable detection of promises and resolution
22
+ */
23
+ function resolvePromises() {
24
+ require('./lib/promise-resolve');
25
+ }
26
+
27
+ /**
28
+ Enable tracking of tasks and flow execution, emitting events and
29
+ tracking start, end, elapsed time
30
+ */
31
+ function trackTasks() {
32
+ require('./lib/track-tasks');
33
+ }
34
+
5
35
  module.exports = require('./lib/dsl.js'); // core + default dsl
6
36
  module.exports.options = core.options; // global react options
7
37
  module.exports.events = core.events; // global react event emitter
8
-
9
- // additional interfaces
10
- module.exports.fstrDefine = require('./lib/fstr.js');
11
- module.exports.pcodeDefine = require('./lib/pcode.js');
12
- module.exports.chainDefine = require('./lib/chain.js');
38
+ module.exports.logEvents = logEvents; // enable event logging
39
+ module.exports.resolvePromises = resolvePromises; // enable promise resolution
40
+ module.exports.trackTasks = trackTasks; // enable tracking of tasks
@@ -0,0 +1,134 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ Test core PromiseTasks using Deferred - jquery style promises
5
+ */
6
+
7
+
8
+ var test = require('tap').test;
9
+ var Deferred = require('Deferred');
10
+ //var when = Deferred.when;
11
+
12
+
13
+ var react = require('../'); //require('react');
14
+
15
+ function multiply(x, y) {
16
+ var deferred = new Deferred();
17
+ setTimeout(function () {
18
+ deferred.resolve(x * y);
19
+ }, 10);
20
+ return deferred.promise();
21
+ }
22
+ function add(x, y) {
23
+ var deferred = new Deferred();
24
+ setTimeout(function () {
25
+ deferred.resolve(x + y);
26
+ }, 10);
27
+ return deferred.promise();
28
+ }
29
+
30
+ function badFunc(a, b) {
31
+ throw new Error('badFuncThrow');
32
+ }
33
+
34
+ function badF2(a, b) {
35
+ var deferred = new Deferred();
36
+ setTimeout(function () {
37
+ deferred.reject(new Error('my-error'));
38
+ }, 10);
39
+ return deferred.promise();
40
+ }
41
+
42
+
43
+ test('multi-step', function (t) {
44
+ t.plan(4);
45
+ var fn = react();
46
+ var errors = fn.setAndValidateAST({
47
+ inParams: ['a', 'b'],
48
+ tasks: [
49
+ { f: multiply, a: ['a', 'b'], out: ['c'], type: 'promise' },
50
+ { f: add, a: ['c', 'b'], out: ['d'], type: 'promise' }
51
+ ],
52
+ outTask: { a: ['c', 'd'] }
53
+ });
54
+ t.deepEqual(errors, [], 'no validation errors');
55
+
56
+ fn(2, 3, function (err, c, d) {
57
+ t.equal(err, null);
58
+ t.equal(c, 6);
59
+ t.equal(d, 9);
60
+ t.end();
61
+ });
62
+ });
63
+
64
+ test('using "this" in a cb function', function (t) {
65
+ t.plan(3);
66
+ function getA(cb) {
67
+ /*jshint validthis: true */
68
+ var deferred = new Deferred();
69
+ var self = this;
70
+ setTimeout(function () {
71
+ deferred.resolve(self.a);
72
+ }, 10);
73
+ return deferred.promise();
74
+ }
75
+
76
+ var fn = react();
77
+ var errors = fn.setAndValidateAST({
78
+ inParams: [],
79
+ tasks: [
80
+ { f: getA, a: [], out: ['a'], type: 'promise' }
81
+ ],
82
+ outTask: { a: ['a'] }
83
+ });
84
+ t.deepEqual(errors, [], 'no validation errors');
85
+
86
+ var obj = {
87
+ a: 100
88
+ };
89
+
90
+ fn.apply(obj, [function (err, a) {
91
+ t.equal(err, null);
92
+ t.equal(a, 100);
93
+ t.end();
94
+ }]);
95
+ });
96
+
97
+
98
+ test('throws error', function (t) {
99
+ t.plan(2);
100
+ var fn = react();
101
+ var errors = fn.setAndValidateAST({
102
+ inParams: ['a', 'b'],
103
+ tasks: [
104
+ { f: badFunc, a: ['a', 'b'], out: ['c'], type: 'promise' },
105
+ { f: add, a: ['c', 'b'], out: ['d'], type: 'promise' }
106
+ ],
107
+ outTask: { a: ['c', 'd'] }
108
+ });
109
+ t.deepEqual(errors, [], 'no validation errors');
110
+
111
+ fn(2, 3, function (err, c, d) {
112
+ t.equal(err.message, 'badFuncThrow');
113
+ t.end();
114
+ });
115
+ });
116
+
117
+ test('rejects with error', function (t) {
118
+ t.plan(2);
119
+ var fn = react();
120
+ var errors = fn.setAndValidateAST({
121
+ inParams: ['a', 'b'],
122
+ tasks: [
123
+ { f: badF2, a: ['a', 'b'], out: ['c'], type: 'promise' },
124
+ { f: add, a: ['c', 'b'], out: ['d'], type: 'promise' }
125
+ ],
126
+ outTask: { a: ['c', 'd'] }
127
+ });
128
+ t.deepEqual(errors, [], 'no validation errors');
129
+
130
+ fn(2, 3, function (err, c, d) {
131
+ t.equal(err.message, 'my-error');
132
+ t.end();
133
+ });
134
+ });