react 0.2.4 → 0.3.4

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 (65) hide show
  1. package/README.md +146 -94
  2. package/doc/alternate-dsls.md +103 -0
  3. package/{lib → dsl}/chain.js +5 -3
  4. package/{lib → dsl}/fstr.js +17 -6
  5. package/{lib → dsl}/pcode.js +19 -8
  6. package/examples/chain-events1.js +28 -7
  7. package/examples/chain1.js +2 -2
  8. package/examples/default-events1.js +33 -6
  9. package/examples/default-log-events.js +43 -0
  10. package/examples/fstr-events1.js +4 -17
  11. package/examples/fstr1.js +3 -2
  12. package/examples/pcode1.js +2 -2
  13. package/lib/base-task.js +8 -6
  14. package/lib/cb-task.js +14 -1
  15. package/lib/core.js +46 -15
  16. package/lib/dsl.js +14 -6
  17. package/lib/event-manager.js +29 -15
  18. package/lib/finalcb-first-task.js +16 -10
  19. package/lib/finalcb-task.js +17 -10
  20. package/lib/input-parser.js +7 -3
  21. package/lib/log-events.js +71 -0
  22. package/lib/parse.js +6 -3
  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 +117 -0
  27. package/lib/validate.js +14 -5
  28. package/lib/vcon.js +8 -3
  29. package/lib/when-task.js +81 -0
  30. package/package.json +4 -2
  31. package/promise-resolve.js +35 -0
  32. package/react.js +0 -4
  33. package/test/core-deferred.test.js +134 -0
  34. package/test/core-promised.test.js +132 -0
  35. package/test/core-when.test.js +84 -0
  36. package/test/core.test.js +108 -60
  37. package/test/dsl.test.js +58 -6
  38. package/test/{chain.test.js → dsl/chain.test.js} +85 -1
  39. package/test/{fstr.test.js → dsl/fstr.test.js} +13 -1
  40. package/test/{pcode.test.js → dsl/pcode.test.js} +128 -1
  41. package/test/exec-options.test.js +2 -1
  42. package/test/finalcb-task.test.js +6 -5
  43. package/test/input-parser.test.js +10 -6
  44. package/test/module-use.test.js +13 -199
  45. package/test/promise-auto-resolve.test.js +51 -0
  46. package/test/validate.test.js +30 -1
  47. package/test/vcon.test.js +13 -0
  48. package/oldExamples/analyze.js +0 -29
  49. package/oldExamples/analyze2.js +0 -29
  50. package/oldExamples/example10-dsl.js +0 -63
  51. package/oldExamples/example11.js +0 -62
  52. package/oldExamples/example12.js +0 -63
  53. package/oldExamples/example13.js +0 -63
  54. package/oldExamples/example14.js +0 -63
  55. package/oldExamples/example15.js +0 -75
  56. package/oldExamples/example6-ast.js +0 -47
  57. package/oldExamples/example6-dsl.js +0 -49
  58. package/oldExamples/example8-ast.js +0 -55
  59. package/oldExamples/example8-dsl.js +0 -53
  60. package/oldExamples/example9-ast.js +0 -58
  61. package/oldExamples/example9-dsl.js +0 -57
  62. package/oldExamples/function-str-ex1.js +0 -33
  63. package/oldExamples/function-str-ex2.js +0 -67
  64. package/oldExamples/trait1.js +0 -41
  65. package/oldExamples/trait2.js +0 -44
package/lib/dsl.js CHANGED
@@ -6,8 +6,10 @@ var core = require('./core.js');
6
6
  var parse = require('./parse.js');
7
7
  var tutil = require('./task.js');
8
8
 
9
- var MISSING_NAME = 'param[0] should be the flow name, instead found in/out def: %s';
10
- var INOUT_PARAMS_NO_MATCH = 'params in wrong format, wanted "foo, bar cb -> err, baz" - found: %s';
9
+ var MISSING_NAME = 'first flow parameter should be the flow name, but found in/out def: %s';
10
+ var INOUT_PARAMS_NO_MATCH = 'params in wrong format, wanted "foo, bar, cb -> err, baz" - found: %s';
11
+ var MISSING_ERR = 'callback specified, but first out param was not "err", use for clarity. Found in/out def: %s';
12
+ var MISSING_CB = 'found err param, but cb/callback is not specified, is this cb-style async or sync function? Found in/out def: %s';
11
13
  var EXTRA_TASKARG = 'extra unmatched task arg: %s';
12
14
 
13
15
  var INOUT_RE = /\->/; // used to detect missing name, in/out as first arg
@@ -25,12 +27,18 @@ function filterOutLeadingErrParam(args) { // if leading err param, filter it out
25
27
  }
26
28
 
27
29
  var inOutDefParse = {
28
- regex: /^([^\-]*)(->\s*(.*))?$/i,
29
- fn: function (m) {
30
- var inParams = parse.splitTrimFilterArgs(m[1]);
30
+ splitStr: '->',
31
+ fn: function (m, origStr) {
32
+ var inParams = parse.splitTrimFilterArgs(m[0]);
31
33
  var lastParam = inParams[inParams.length - 1];
32
34
  var type = (lastParam && CB_NAMES_RE.test(lastParam)) ? 'cb' : 'ret';
33
- var outParams = parse.splitTrimFilterArgs(m[3]);
35
+ var outParams = parse.splitTrimFilterArgs(m[1]);
36
+ var firstOutParam = outParams[0];
37
+ if (type === 'cb' && (!firstOutParam || !ERR_NAMES_RE.test(firstOutParam))) {
38
+ throw new Error(sprintf(MISSING_ERR, origStr)); // found cb, but no err param
39
+ } else if (type === 'ret' && firstOutParam && ERR_NAMES_RE.test(firstOutParam)) {
40
+ throw new Error(sprintf(MISSING_CB, origStr)); // found err but not cb param
41
+ }
34
42
  return {
35
43
  type: type,
36
44
  inDef: filterOutTrailingCbParam(inParams),
@@ -3,12 +3,30 @@
3
3
  var EventEmitter2 = require('eventemitter2').EventEmitter2;
4
4
 
5
5
  var EVENT_EMITTER2_CONFIG = {
6
- wildcard: true
6
+ wildcard: true, // should the event emitter use wildcards.
7
+ delimiter: '.', // the delimiter used to segment namespaces, defaults to `.`.
8
+ maxListeners: 30 // the max number of listeners that can be assigned to an event, defaults to 10.
7
9
  };
8
10
 
9
11
  var TYPES = {
10
- TASK_BEGIN: 'task.begin',
11
- TASK_COMPLETE: 'task.complete'
12
+ // Flow monitoring events and their params
13
+ FLOW_BEGIN: 'flow.begin', // env
14
+ TASK_BEGIN: 'task.begin', // task
15
+ TASK_COMPLETE: 'task.complete', // task
16
+ TASK_ERRORED: 'task.errored', // task
17
+ FLOW_COMPLETE: 'flow.complete', // env
18
+ FLOW_ERRORED: 'flow.errored', // env
19
+
20
+ // Internal Hooks
21
+ EXEC_FLOW_START: 'exec.flow.start', // env
22
+ EXEC_INPUT_PREPROCESS: 'exec.input.preprocess', // parsedInput
23
+ EXEC_TASKS_PRECREATE: 'exec.tasks.precreate', // env
24
+ EXEC_OUTTASK_CREATE: 'exec.outTask.create', // outTaskOptions
25
+ EXEC_TASK_START: 'exec.task.start', // task
26
+ EXEC_TASK_COMPLETE: 'exec.task.complete', // task
27
+ EXEC_TASK_ERRORED: 'exec.task.errored', // task
28
+ EXEC_FLOW_COMPLETE: 'exec.flow.complete', // env
29
+ EXEC_FLOW_ERRORED: 'exec.flow.errored' // env
12
30
  };
13
31
 
14
32
  /**
@@ -21,6 +39,9 @@ function EventManager() {
21
39
 
22
40
  EventManager.create = function () { return new EventManager(); };
23
41
 
42
+ EventManager.TYPES = TYPES;
43
+ EventManager.prototype.TYPES = TYPES;
44
+
24
45
  EventManager.prototype.isEnabled = function () { // if has listener or an ancestor has listener
25
46
  return (this.emitter || (this.parent && this.parent.isEnabled()));
26
47
  };
@@ -36,22 +57,15 @@ EventManager.prototype.on = function (event, listener) {
36
57
  };
37
58
 
38
59
  EventManager.prototype.emit = function (event, arg1, arg2, argN) {
60
+ if (event === undefined) throw new Error('event is undefined');
39
61
  if (this.emitter) this.emitter.emit.apply(this.emitter, arguments);
40
62
  if (this.parent && this.parent.isEnabled()) this.parent.emit.apply(this.parent, arguments);
41
63
  };
42
64
 
43
- /**
44
- Emit an object augmented with standard fields.
45
- Copies object and adds standard fields:
46
- event: event type
47
- time: current time
48
- */
49
- EventManager.prototype.emitObject = function (event, object) {
50
- var evObj = Object.create(object); // create inherited copy version so origin is untouched
51
- evObj.event = event; // augment with the event type
52
- evObj.time = Date.now(); // augument with the time of the event
53
- this.emit(event, evObj);
65
+ EventManager.prototype.removeListener = function (event, listener) {
66
+ if (this.emitter) this.emitter.removeListener.apply(this.emitter, arguments);
54
67
  };
55
68
 
69
+
56
70
  module.exports = EventManager;
57
- module.exports.TYPES = TYPES;
71
+ module.exports.global = EventManager.create(); // create one top level emitter
@@ -5,15 +5,22 @@ var util = require('util');
5
5
 
6
6
  var STATUS = require('./status.js');
7
7
  var VContext = require('./vcon.js');
8
+ var EventManager = require('./event-manager.js');
8
9
 
9
10
  var OUTTASK_A_REQ = 'ast.outTask.a should be an array of string param names';
10
11
 
11
- function FinalCbFirstSuccTask(taskDef, cbFunc, tasks, vCon) {
12
+ function FinalCbFirstSuccTask(outTaskOptions) {
13
+ var taskDef = outTaskOptions.taskDef;
14
+ if (typeof(outTaskOptions.cbFunc) !== 'function') throw new Error('callback is not a function');
12
15
  var self = this;
13
- Object.keys(taskDef).forEach(function (k) { self[k] = taskDef[k]; });
14
- this.f = cbFunc;
15
- this.tasks = tasks;
16
- this.vCon = vCon;
16
+ for (var k in taskDef) {
17
+ if (true) self[k] = taskDef[k]; // if to make jshint happy
18
+ }
19
+ this.f = outTaskOptions.cbFunc;
20
+ this.tasks = outTaskOptions.tasks;
21
+ this.vCon = outTaskOptions.vCon;
22
+ this.retValue = outTaskOptions.retValue;
23
+ this.env = outTaskOptions.env;
17
24
  }
18
25
 
19
26
  function format_error(errmsg, obj) {
@@ -27,11 +34,6 @@ FinalCbFirstSuccTask.validate = function (taskDef) {
27
34
  errors.push(format_error(OUTTASK_A_REQ, taskDef));
28
35
  }
29
36
  return errors;
30
- }
31
-
32
- FinalCbFirstSuccTask.create = function (taskDef, cbFunc, tasks, vCon) {
33
- if (!(cbFunc && cbFunc instanceof Function)) throw new Error('callback is not a function');
34
- return new FinalCbFirstSuccTask(taskDef, cbFunc, tasks, vCon);
35
37
  };
36
38
 
37
39
  /**
@@ -46,11 +48,15 @@ FinalCbFirstSuccTask.prototype.isReady = function () {
46
48
  FinalCbFirstSuccTask.prototype.exec = function (err) {
47
49
  if (!this.f) return; //must have already been called
48
50
  if (err) {
51
+ this.env.error = err;
52
+ this.env.flowEmitter.emit(EventManager.TYPES.EXEC_FLOW_ERRORED, this.env);
49
53
  this.f.call(null, err); //call the final callback with the first error hit
50
54
  } else { // no error, call with args
51
55
  var vCon = this.vCon;
52
56
  var finalArgs = this.a.map(function (k) { return vCon.getVar(k); });
53
57
  finalArgs.unshift(null); //unshift err=null to front
58
+ this.env.results = finalArgs;
59
+ this.env.flowEmitter.emit(EventManager.TYPES.EXEC_FLOW_COMPLETE, this.env);
54
60
  this.f.apply(null, finalArgs);
55
61
  }
56
62
  this.f = null; // prevent multiple calls
@@ -4,15 +4,23 @@ var sprintf = require('sprintf').sprintf;
4
4
  var util = require('util');
5
5
 
6
6
  var STATUS = require('./status.js');
7
+ var EventManager = require('./event-manager.js');
7
8
 
8
9
  var OUTTASK_A_REQ = 'ast.outTask.a should be an array of string param names';
9
10
 
10
- function FinalCbTask(taskDef, cbFunc, tasks, vCon) {
11
+ function FinalCbTask(outTaskOptions) {
12
+ var taskDef = outTaskOptions.taskDef;
13
+ if (typeof(outTaskOptions.cbFunc) !== 'function') throw new Error('callback is not a function');
11
14
  var self = this;
12
- Object.keys(taskDef).forEach(function (k) { self[k] = taskDef[k]; });
13
- this.f = cbFunc;
14
- this.tasks = tasks;
15
- this.vCon = vCon;
15
+ for (var k in taskDef) {
16
+ if (true) self[k] = taskDef[k]; // if to make jshint happy
17
+ }
18
+ this.f = outTaskOptions.cbFunc;
19
+ this.tasks = outTaskOptions.tasks;
20
+ this.vCon = outTaskOptions.vCon;
21
+ this.retValue = outTaskOptions.retValue;
22
+ this.execOptions = outTaskOptions.execOptions;
23
+ this.env = outTaskOptions.env;
16
24
  }
17
25
 
18
26
  function format_error(errmsg, obj) {
@@ -29,11 +37,6 @@ FinalCbTask.validate = function (taskDef) {
29
37
  return errors;
30
38
  };
31
39
 
32
- FinalCbTask.create = function (taskDef, cbFunc, tasks, vCon) {
33
- if (!(cbFunc && cbFunc instanceof Function)) throw new Error('callback is not a function');
34
- return new FinalCbTask(taskDef, cbFunc, tasks, vCon);
35
- };
36
-
37
40
  FinalCbTask.prototype.isReady = function () {
38
41
  return (this.tasks.every(function (t) { return (t.status === STATUS.COMPLETE); }));
39
42
  };
@@ -41,11 +44,15 @@ FinalCbTask.prototype.isReady = function () {
41
44
  FinalCbTask.prototype.exec = function (err) {
42
45
  if (!this.f) return; //must have already been called
43
46
  if (err) {
47
+ this.env.error = err;
48
+ this.env.flowEmitter.emit(EventManager.TYPES.EXEC_FLOW_ERRORED, this.env);
44
49
  this.f.call(null, err); //call the final callback with the first error hit
45
50
  } else { // no error, call with args
46
51
  var vCon = this.vCon;
47
52
  var finalArgs = this.a.map(function (k) { return vCon.getVar(k); });
48
53
  finalArgs.unshift(null); //unshift err=null to front
54
+ this.env.results = finalArgs;
55
+ this.env.flowEmitter.emit(EventManager.TYPES.EXEC_FLOW_COMPLETE, this.env);
49
56
  this.f.apply(null, finalArgs);
50
57
  }
51
58
  this.f = null; // prevent multiple calls
@@ -1,12 +1,14 @@
1
1
  'use strict';
2
2
 
3
+ var EventManager = require('./event-manager.js');
4
+
3
5
  var defaultExecOptions = {
4
6
  reactExecOptions: true,
5
- outputStyle: 'callback',
7
+ outputStyle: 'cb',
6
8
  };
7
9
 
8
10
  var OUTPUT_STYLES = {
9
- CALLBACK: 'callback',
11
+ CALLBACK: 'cb',
10
12
  NONE: 'none'
11
13
  };
12
14
 
@@ -36,7 +38,9 @@ function inputParser(inputArgs, ast) {
36
38
  var splitResult = splitArgs(args, ast.inParams, parsedInput.options.outputStyle);
37
39
  parsedInput.args = splitResult.args;
38
40
  parsedInput.cb = splitResult.cb;
39
- if (splitResult.extra) parsedInput.extraArgs = splitResult.extra;
41
+ if (splitResult.outputStyle) parsedInput.options.outputStyle = splitResult.outputStyle;
42
+ if (splitResult.extra) parsedInput.extraArgs = splitResult.extra;
43
+ EventManager.global.emit(EventManager.TYPES.EXEC_INPUT_PREPROCESS, parsedInput); // hook
40
44
  return parsedInput;
41
45
  }
42
46
 
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ Log events to console.error
5
+
6
+ @example
7
+ var react = require('react');
8
+ require('react/lib/log-events').logEvent(react);
9
+ */
10
+
11
+ var react = require('../lib/track-tasks'); // require('react/lib/track-tasks'); // turn on tracking
12
+
13
+ var ALL_FLOW_EVENTS = 'flow.*';
14
+ var ALL_TASK_EVENTS = 'task.*';
15
+
16
+ function flowLog(obj) {
17
+ /*jshint validthis: true */
18
+ var time = new Date();
19
+ time.setTime(obj.time);
20
+ var argsNoCb = obj.args.filter(function (a) { return (typeof(a) !== 'function'); });
21
+ var eventTimeStr = time.toISOString();
22
+ if (this.event === 'flow.complete') {
23
+ var env = obj;
24
+ console.error('%s: %s \tmsecs:(%s) \n\targs:(%s) \n\tresults:(%s)\n',
25
+ this.event, env.name, env.elapsedTime, argsNoCb, env.results);
26
+ } else {
27
+ var name = obj.name;
28
+ var args = obj.args;
29
+ console.error('%s: %s \n\targs:(%s)\n', this.event, name, argsNoCb);
30
+ }
31
+ }
32
+
33
+ function taskLog(obj) {
34
+ /*jshint validthis: true */
35
+ var time = new Date();
36
+ time.setTime(obj.time);
37
+ var argsNoCb = obj.args.filter(function (a) { return (typeof(a) !== 'function'); });
38
+ var eventTimeStr = time.toISOString();
39
+ if (this.event === 'task.complete') {
40
+ var task = obj;
41
+ console.error('%s: %s \tmsecs:(%s) \n\targs:(%s) \n\tresults:(%s)\n',
42
+ this.event, task.name, task.elapsedTime, argsNoCb, task.results);
43
+ } else {
44
+ var name = obj.name;
45
+ var args = obj.args;
46
+ console.error('%s: %s \n\targs:(%s)\n', this.event, name, argsNoCb);
47
+ }
48
+
49
+ }
50
+
51
+ /**
52
+ Log flow and task events for a flowFn or all of react.
53
+ If called multiple times, remove previous listener (if any) before
54
+ adding.
55
+
56
+ @example
57
+ var react = require('react');
58
+ require('react/lib/log-events').logEvents(flowFn); // pass flowFn or react
59
+
60
+ @param flowFn Flow function or global react object
61
+ */
62
+ function logEvents(flowFn) {
63
+ //output events as tasks start and complete
64
+ flowFn.events.removeListener(ALL_FLOW_EVENTS, flowLog);
65
+ flowFn.events.on(ALL_FLOW_EVENTS, flowLog);
66
+ flowFn.events.removeListener(ALL_TASK_EVENTS, taskLog);
67
+ flowFn.events.on(ALL_TASK_EVENTS, taskLog);
68
+ }
69
+
70
+ module.exports = react;
71
+ module.exports.logEvents = logEvents;
package/lib/parse.js CHANGED
@@ -9,10 +9,13 @@ function splitTrimFilterArgs(commaSepArgs) { //parse 'one, two' into ['one', 'tw
9
9
  .filter(function (s) { return (s); }); //filter out empty strings
10
10
  }
11
11
 
12
- function parseReduce(accum, regexFn) {
12
+ /**
13
+ @param patternFn regex + fn or splitStr + fn
14
+ */
15
+ function parseReduce(accum, patternFn) {
13
16
  if (typeof(accum) !== 'string') return accum; // already matched
14
- var m = regexFn.regex.exec(accum);
15
- if (m) return regexFn.fn(m); // return result obj
17
+ var m = (patternFn.regex) ? patternFn.regex.exec(accum) : accum.split(patternFn.splitStr);
18
+ if (m) return patternFn.fn(m, accum); // pass in matches and origStr, return result obj
16
19
  return accum; // no match, return str, will try next matcher
17
20
  }
18
21
 
@@ -0,0 +1,89 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ PromiseTask is a task which executes a fn that returns a promise
5
+ and when it completes it sets the values in vCon
6
+ */
7
+
8
+ var util = require('util');
9
+ var sprintf = require('sprintf').sprintf;
10
+
11
+ var BaseTask = require('./base-task.js');
12
+
13
+ function format_error(errmsg, obj) {
14
+ return sprintf('%s - %s', errmsg, util.inspect(obj));
15
+ }
16
+
17
+ var REQ = 'promiseTask requires f, a, out';
18
+ var FN_REQ = 'promiseTask requires f to be a function or string';
19
+ var A_REQ = 'promiseTask requires a to be an array of string param names';
20
+ var OUT_REQ = 'promiseTask requires out to be an array[1] of string param names';
21
+
22
+ function PromiseTask(taskDef) {
23
+ var self = this;
24
+ Object.keys(taskDef).forEach(function (k) { self[k] = taskDef[k]; });
25
+ }
26
+
27
+ PromiseTask.prototype = new BaseTask();
28
+ PromiseTask.prototype.constructor = PromiseTask;
29
+
30
+ PromiseTask.validate = function (taskDef) {
31
+ var errors = [];
32
+ if (!taskDef.f || !taskDef.a || !taskDef.out) {
33
+ errors.push(format_error(REQ, taskDef));
34
+ } else {
35
+ var ftype = typeof(taskDef.f);
36
+ if (! ((taskDef.f instanceof Function) || (ftype === 'string'))) {
37
+ errors.push(format_error(FN_REQ, taskDef));
38
+ }
39
+ if (! (Array.isArray(taskDef.a) &&
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
+ PromiseTask.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
+ PromiseTask.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('PromiseTask.exec.args=', args);
68
+ //console.error('PromiseTask.exec.vCon=', vCon);
69
+ this.start(args); //note the start time, args
70
+ var func = this.f;
71
+ var bindObj = vCon.getVar('this'); //global space or the original this
72
+ if (this.isMethodCall()) { //if method call then reset func and bindObj
73
+ func = vCon.getVar(this.f);
74
+ bindObj = this.getMethodObj(vCon);
75
+ } else if (typeof(func) === 'string') {
76
+ func = vCon.getVar(func); // we want the actual fn from this string
77
+ }
78
+ var retValue = func.apply(bindObj, args);
79
+ if (retValue && typeof(retValue.then) === 'function') { // is a promise
80
+ retValue.then(this.nextFn, this.failFn);
81
+ } else { // just a value, proceed now
82
+ this.nextFn(retValue);
83
+ }
84
+ } catch (err) { //catch and handle the task error, calling final cb
85
+ handleError(this, err);
86
+ }
87
+ };
88
+
89
+ module.exports = PromiseTask;
package/lib/ret-task.js CHANGED
@@ -50,7 +50,7 @@ RetTask.prototype.exec = function exec(vCon, handleError, contExec) {
50
50
  var args = this.a.map(function (k) { return vCon.getVar(k); }); //get args from vCon
51
51
  this.start(args); //note the start time, args
52
52
  var func = this.f;
53
- var bindObj = null; //global space
53
+ var bindObj = vCon.getVar('this'); //global space or the original this
54
54
  if (this.isMethodCall()) { //if method call then reset func and bindObj
55
55
  func = vCon.getVar(this.f);
56
56
  bindObj = this.getMethodObj(vCon);
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;