react 0.2.3 → 0.3.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 (61) hide show
  1. package/README.md +15 -13
  2. package/{lib → dsl}/chain.js +5 -3
  3. package/{lib → dsl}/fstr.js +17 -6
  4. package/{lib → dsl}/pcode.js +19 -8
  5. package/examples/chain-events1.js +3 -3
  6. package/examples/chain1.js +2 -2
  7. package/examples/default-events1.js +2 -2
  8. package/examples/fstr-events1.js +4 -3
  9. package/examples/fstr1.js +3 -2
  10. package/examples/pcode1.js +2 -2
  11. package/lib/base-task.js +1 -0
  12. package/lib/cb-task.js +14 -1
  13. package/lib/core.js +36 -12
  14. package/lib/dsl.js +16 -5
  15. package/lib/event-manager.js +16 -4
  16. package/lib/finalcb-first-task.js +9 -6
  17. package/lib/finalcb-task.js +9 -6
  18. package/lib/input-parser.js +7 -3
  19. package/lib/parse.js +6 -3
  20. package/lib/promise-task.js +89 -0
  21. package/lib/ret-task.js +1 -1
  22. package/lib/task.js +23 -19
  23. package/lib/validate.js +14 -5
  24. package/lib/vcon.js +8 -3
  25. package/lib/when-task.js +81 -0
  26. package/package.json +4 -2
  27. package/promise-resolve.js +35 -0
  28. package/react.js +0 -4
  29. package/test/core-deferred.test.js +134 -0
  30. package/test/core-promised.test.js +132 -0
  31. package/test/core-when.test.js +84 -0
  32. package/test/core.test.js +63 -4
  33. package/test/dsl.test.js +70 -5
  34. package/test/{chain.test.js → dsl/chain.test.js} +84 -1
  35. package/test/{fstr.test.js → dsl/fstr.test.js} +13 -1
  36. package/test/{pcode.test.js → dsl/pcode.test.js} +136 -1
  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 +2 -190
  41. package/test/promise-auto-resolve.test.js +51 -0
  42. package/test/validate.test.js +30 -1
  43. package/test/vcon.test.js +13 -0
  44. package/oldExamples/analyze.js +0 -29
  45. package/oldExamples/analyze2.js +0 -29
  46. package/oldExamples/example10-dsl.js +0 -63
  47. package/oldExamples/example11.js +0 -62
  48. package/oldExamples/example12.js +0 -63
  49. package/oldExamples/example13.js +0 -63
  50. package/oldExamples/example14.js +0 -63
  51. package/oldExamples/example15.js +0 -75
  52. package/oldExamples/example6-ast.js +0 -47
  53. package/oldExamples/example6-dsl.js +0 -49
  54. package/oldExamples/example8-ast.js +0 -55
  55. package/oldExamples/example8-dsl.js +0 -53
  56. package/oldExamples/example9-ast.js +0 -58
  57. package/oldExamples/example9-dsl.js +0 -57
  58. package/oldExamples/function-str-ex1.js +0 -33
  59. package/oldExamples/function-str-ex2.js +0 -67
  60. package/oldExamples/trait1.js +0 -41
  61. package/oldExamples/trait2.js +0 -44
package/README.md CHANGED
@@ -40,7 +40,7 @@ It takes inspiration from several projects including:
40
40
  - object instance method calls
41
41
  - class method calls
42
42
  - selectFirst flow where the first task that returns defined, non-null value is used
43
- - (planned) promise style functions - also automatic resolution of promise inputs
43
+ - promise style functions - also automatic resolution of promise inputs (optional require('react/promise-resolve');)
44
44
  - (planned) use of resulting flow function as callback style or promise style (if no callback provided)
45
45
  - (planned) iteration on arrays, streams, sockets
46
46
  - (planned) event emitter integration
@@ -157,7 +157,7 @@ fn('foo', 'pre-', '-post', function cb(err, lres) {
157
157
  ### Example using Function String DSL interface
158
158
 
159
159
  ```javascript
160
- var react = require('react');
160
+ var fstrDefine = require('react/dsl/fstr');
161
161
 
162
162
  function loadUser(uid, cb){ setTimeout(cb, 100, null, "User"+uid); }
163
163
  function loadFile(filename, cb){ setTimeout(cb, 100, null, 'Filedata'+filename); }
@@ -176,7 +176,7 @@ function useHtml(err, html, user, bytesWritten) {
176
176
  console.log('final result: %s, user: %s, written:%s', html, user, bytesWritten);
177
177
  }
178
178
 
179
- var loadAndSave = react.fstrDefine('filename, uid, outDirname, cb', [ // input params
179
+ var loadAndSave = fstrDefine('filename, uid, outDirname, cb', [ // input params
180
180
  loadUser, 'uid -> err, user', // calling async fn loadUser with uid, callback is called with err and user
181
181
  loadFile, 'filename -> err, filedata',
182
182
  markdown, 'filedata -> returns html', // using a sync function
@@ -195,7 +195,7 @@ loadAndSave('file.md', 100, '/tmp/foo', useHtml); // executing the flow
195
195
  ### Example using pseudocode DSL interface
196
196
 
197
197
  ```javascript
198
- var react = require('react');
198
+ var pcodeDefine = require('react/dsl/pcode');
199
199
 
200
200
  function multiply(a, b, cb) { cb(null, a * b); }
201
201
  function add(a, b) { return a + b; }
@@ -204,7 +204,7 @@ var locals = { // since pcodeDefine uses strings, need references to functions
204
204
  add: add
205
205
  };
206
206
 
207
- var fn = react.pcodeDefine('a, b, cb', [ // input params
207
+ var fn = pcodeDefine('a, b, cb', [ // input params
208
208
  'm := multiply(a, b)', // using a callback function, use :=
209
209
  's = add(m, a)', // using a sync function, use =
210
210
  'cb(err, m, s)' // output params for final callback
@@ -221,12 +221,12 @@ fn(2, 3, function (err, m, s) {
221
221
  ### Example using jquery-like chaining DSL interface
222
222
 
223
223
  ```javascript
224
- var react = require('react');
224
+ var chainDefine = require('react/dsl/chain');
225
225
 
226
226
  function multiply(a, b, cb) { cb(null, a * b); }
227
227
  function add(a, b) { return a + b; }
228
228
 
229
- var fn = react.chainDefine()
229
+ var fn = chainDefine()
230
230
  .in('a', 'b', 'cb') // input params
231
231
  .out('err', 'm', 's') // final callback output params
232
232
  .async(multiply).in('a', 'b', 'cb').out('err', 'm') // task def - async fn, in params, callback out params
@@ -242,6 +242,8 @@ fn(2, 3, function (err, m, s) {
242
242
 
243
243
  ## Status
244
244
 
245
+ - 2012-01-13 - Add promise tasks, promise resolution, refactor alternate DSL interfaces as optional requires (v0.3.0)
246
+ - 2012-01-11 - Provide warning/error when name is skipped in default DSL, literal check in validate (v0.2.5)
245
247
  - 2012-01-10 - Create default DSL for react(), create error for missing variables, list remaining tasks when flow won't complete
246
248
  - 2011-12-21 - Refactor from ground up with tests, changes to the interfaces
247
249
  - 2011-10-26 - React is in active development and interface may change frequently in these early stages. Current code is functional but does not perform validation yet. Additional interfaces are planned to make it easy to define flows in a variety of ways. Documentation and examples forthcoming.
@@ -251,23 +253,23 @@ fn(2, 3, function (err, m, s) {
251
253
  ```bash
252
254
  ok ast.test.js .................... 10/10
253
255
  ok cb-task.test.js ................ 31/31
254
- ok chain.test.js .................. 56/56
256
+ ok chain.test.js .................. 59/59
255
257
  ok core.test.js ................... 98/98
256
- ok dsl.test.js .................... 58/58
258
+ ok dsl.test.js .................... 63/63
257
259
  ok event-manager.test.js .......... 13/13
258
260
  ok exec-options.test.js ............. 3/3
259
261
  ok finalcb-task.test.js ............. 5/5
260
- ok fstr.test.js ................... 64/64
262
+ ok fstr.test.js ................... 67/67
261
263
  ok input-parser.test.js ........... 15/15
262
264
  ok module-use.test.js ............. 64/64
263
- ok pcode.test.js .................. 65/65
265
+ ok pcode.test.js .................. 68/68
264
266
  ok ret-task.test.js ............... 31/31
265
267
  ok task.test.js ..................... 1/1
266
268
  ok validate-cb-task.test.js ......... 6/6
267
269
  ok validate-ret-task.test.js ........ 7/7
268
- ok validate.test.js ............... 26/26
270
+ ok validate.test.js ............... 31/31
269
271
  ok vcon.test.js ................... 42/42
270
- total ........................... 613/613
272
+ total ........................... 632/632
271
273
 
272
274
  ok
273
275
  ```
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var sprintf = require('sprintf').sprintf;
4
- var core = require('./core.js');
5
- var tutil = require('./task.js');
4
+ var core = require('../lib/core.js');
5
+ var tutil = require('../lib/task.js');
6
6
 
7
7
  // err for task type cb is implied and thus optional, but allow for clarity.
8
8
  var ERROR_NAMES_RE = /^err$/i; // first out param matching this is skipped as being the err object
@@ -145,4 +145,6 @@ FlowBuilder.prototype.end = function end() {
145
145
  return reactFn;
146
146
  };
147
147
 
148
- module.exports = chainDefine;
148
+ module.exports = chainDefine;
149
+ module.exports.options = core.options;
150
+ module.exports.events = core.events;
@@ -1,23 +1,32 @@
1
1
  'use strict';
2
+ /*jshint regexp: false */
2
3
 
3
4
  var sprintf = require('sprintf').sprintf;
4
- var core = require('./core.js');
5
- var parse = require('./parse.js');
6
- var tutil = require('./task.js');
5
+ var core = require('../lib/core.js');
6
+ var parse = require('../lib/parse.js');
7
+ var tutil = require('../lib/task.js');
7
8
 
8
9
  var INPARAMS_NO_MATCH = 'input params in wrong format, wanted "foo, bar" - found: %s';
9
10
  var OUTPARAMS_NO_MATCH = 'output params in wrong format, wanted "foo, bar" - found: %s';
10
11
  var INOUT_PARAMS_NO_MATCH = 'task params in wrong format, wanted "foo, bar -> err, baz" - found: %s';
11
12
  var EXTRA_TASKARG = 'extra unmatched task arg: %s';
12
13
 
14
+ var ERR_NAMES_RE = /^err$/i; // err, ERR, Err, ...
15
+
16
+ function filterOutLeadingErrParam(args) { // if leading err param, filter it out
17
+ if (args.length && args[0].match(ERR_NAMES_RE)) args.shift();
18
+ return args;
19
+ }
20
+
21
+
13
22
  var inOutDefParse = {
14
- regex: /^([^-]*)(->)?\s*(er{0,2}\s*,|returns?\s+)?(.*)$/i,
23
+ regex: /^([^\-]*)(->)?\s*(returns?\s+)?(.*)$/i, //TODO this will not work if literal has dash
15
24
  fn: function (m) {
16
25
  var reMatchReturns = /returns?/i;
17
26
  return {
18
27
  type: (m[3] && m[3].match(reMatchReturns)) ? 'ret' : 'cb',
19
28
  inDef: parse.splitTrimFilterArgs(m[1]),
20
- outDef: parse.splitTrimFilterArgs(m[4])
29
+ outDef: filterOutLeadingErrParam(parse.splitTrimFilterArgs(m[4]))
21
30
  };
22
31
  }
23
32
  };
@@ -107,4 +116,6 @@ function selectFirst(inParamStr, taskDefArr, outParamStr, options) {
107
116
  }
108
117
 
109
118
  module.exports = fstrDefine;
110
- module.exports.selectFirst = selectFirst;
119
+ module.exports.selectFirst = selectFirst;
120
+ module.exports.options = core.options;
121
+ module.exports.events = core.events;
@@ -1,15 +1,24 @@
1
1
  'use strict';
2
+ /*jshint regexp: false */
2
3
 
3
4
  var sprintf = require('sprintf').sprintf;
4
- var core = require('./core.js');
5
- var parse = require('./parse.js');
6
- var tutil = require('./task.js');
5
+ var core = require('../lib/core.js');
6
+ var parse = require('../lib/parse.js');
7
+ var tutil = require('../lib/task.js');
7
8
 
8
9
  var INPARAMS_NO_MATCH = 'input params in wrong format, wanted "foo, bar, cb" - found: %s';
9
10
  var OUTPARAMS_NO_MATCH = 'output params in wrong format, wanted "cb(err, foo)" - found: %s';
10
11
  var INOUT_PARAMS_NO_MATCH = 'task params in wrong format, wanted "foo, bar := func(baz, cat, cb) " - found: %s';
11
12
  var EXTRA_TASKARG = 'extra unmatched task arg: %s';
12
13
 
14
+ var ERR_NAMES_RE = /^err$/i; // err, ERR, Err, ...
15
+
16
+ function filterOutLeadingErrParam(args) { // if leading err param, filter it out
17
+ if (args.length && args[0].match(ERR_NAMES_RE)) args.shift();
18
+ return args;
19
+ }
20
+
21
+
13
22
  /**
14
23
  Examples:
15
24
  var react = require('react');
@@ -54,7 +63,7 @@ var inParse = {
54
63
  };
55
64
 
56
65
  var cbParse = {
57
- regex: /^\s*(var\s+)?([^:]*)\s*:=\s*([a-zA-Z0-9_\.-]+)\s*\(\s*([^)]*)\)\s*(when\s+([^;]+))?;?\s*$/,
66
+ regex: /^\s*(var\s+)?([^:]*)\s*:=\s*([a-zA-Z0-9_\.\-]+)\s*\(\s*([^)]*)\)\s*(when\s+([^;]+))?;?\s*$/,
58
67
  fn: function (m) {
59
68
  var taskDef = {
60
69
  type: 'cb',
@@ -68,7 +77,7 @@ var cbParse = {
68
77
  };
69
78
 
70
79
  var retParse = {
71
- regex: /^\s*(var\s+)?([^:]*)\s*=\s*([a-zA-Z0-9_\.-]+)\s*\(\s*([^)]*)\)\s*(when\s+([^;]+))?;?\s*$/,
80
+ regex: /^\s*(var\s+)?([^:]*)\s*=\s*([a-zA-Z0-9_\.\-]+)\s*\(\s*([^)]*)\)\s*(when\s+([^;]+))?;?\s*$/,
72
81
  fn: function (m) {
73
82
  var taskDef = {
74
83
  type: 'ret',
@@ -82,10 +91,10 @@ var retParse = {
82
91
  };
83
92
 
84
93
  var finalCbParse = {
85
- regex: /^\s*(cb|callback)\s*\((er{0,2}\s*,\s*)?([^)]*)\)\s*;?$/i,
94
+ regex: /^\s*(cb|callback)\s*\(([^)]*)\)\s*;?$/i,
86
95
  fn: function (m) {
87
96
  return {
88
- outDef: (m[3]) ? parse.splitTrimFilterArgs(m[3]) : []
97
+ outDef: (m[2]) ? filterOutLeadingErrParam(parse.splitTrimFilterArgs(m[2])) : []
89
98
  };
90
99
  }
91
100
  };
@@ -161,4 +170,6 @@ function selectFirst(inParamStr, taskStrArr, locals, options) {
161
170
  }
162
171
 
163
172
  module.exports = pcodeDefine;
164
- module.exports.selectFirst = selectFirst;
173
+ module.exports.selectFirst = selectFirst;
174
+ module.exports.options = core.options;
175
+ module.exports.events = core.events;
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var react = require('../'); // require('react');
3
+ var chainDefine = require('../dsl/chain'); // require('react/dsl/chain');
4
4
 
5
5
  //output events as tasks start and complete
6
- react.events.on('*', function (obj) {
6
+ chainDefine.events.on('task.*', function (obj) {
7
7
  var time = new Date();
8
8
  time.setTime(obj.time);
9
9
  var eventTimeStr = time.toISOString();
@@ -20,7 +20,7 @@ react.events.on('*', function (obj) {
20
20
  function multiply(a, b, cb) { cb(null, a * b); }
21
21
  function add(a, b) { return a + b; }
22
22
 
23
- var fn = react.chainDefine()
23
+ var fn = chainDefine()
24
24
  .in('a', 'b', 'cb') // input params
25
25
  .out('err', 'm', 's') // final callback output params
26
26
  .async(multiply).in('a', 'b', 'cb').out('err', 'm') // task def - async fn, in params, callback out params
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var react = require('../'); // require('react');
3
+ var chainDefine = require('../dsl/chain'); // require('react/dsl/chain');
4
4
 
5
5
  function multiply(a, b, cb) { cb(null, a * b); }
6
6
  function add(a, b) { return a + b; }
7
7
 
8
- var fn = react.chainDefine()
8
+ var fn = chainDefine()
9
9
  .in('a', 'b', 'cb') // input params
10
10
  .out('err', 'm', 's') // final callback output params
11
11
  .async(multiply).in('a', 'b', 'cb').out('err', 'm') // task def - async fn, in params, callback out params
@@ -4,7 +4,7 @@
4
4
  var react = require('../'); // require('react');
5
5
 
6
6
  //output events as tasks start and complete
7
- react.events.on('*', function (obj) {
7
+ react.events.on('task.*', function (obj) {
8
8
  var time = new Date();
9
9
  time.setTime(obj.time);
10
10
  var eventTimeStr = time.toISOString();
@@ -43,7 +43,7 @@ var loadAndSave = react('loadAndSave', 'filename, uid, outDirname, cb -> err, ht
43
43
  writeOutput, 'html, user, cb -> err, bytesWritten', { after: prepareDirectory }, // only after prepareDirectory done
44
44
  loadEmailTemplate, 'cb -> err, emailmd',
45
45
  markdown, 'emailmd -> emailHtml', // using a sync function
46
- customizeEmail, 'user, emailHtml -> err, custEmailHtml', // sync fn
46
+ customizeEmail, 'user, emailHtml -> custEmailHtml', // sync fn
47
47
  deliverEmail, 'custEmailHtml, cb -> err, deliveredEmail', { after: writeOutput } // only after writeOutput is done
48
48
  );
49
49
 
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
+ /*jshint white: false */
2
3
 
3
- var react = require('../'); // require('react');
4
+ var fstr = require('../dsl/fstr'); // require('react/dsl/fstr');
4
5
 
5
6
  //output events as tasks start and complete
6
- react.events.on('*', function (obj) {
7
+ fstr.events.on('task.*', function (obj) {
7
8
  var time = new Date();
8
9
  time.setTime(obj.time);
9
10
  var eventTimeStr = time.toISOString();
@@ -34,7 +35,7 @@ function useHtml(err, html, user, bytesWritten) {
34
35
  console.log('final result: %s, user: %s, written:%s', html, user, bytesWritten);
35
36
  }
36
37
 
37
- var loadAndSave = react.fstrDefine('filename, uid, outDirname, cb', [ // input params
38
+ var loadAndSave = fstr('filename, uid, outDirname, cb', [ // input params
38
39
  loadUser, 'uid -> err, user', // calling async fn loadUser with uid, callback is called with err and user
39
40
  loadFile, 'filename -> err, filedata',
40
41
  markdown, 'filedata -> returns html', // using a sync function
package/examples/fstr1.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
+ /*jshint white: false */
2
3
 
3
- var react = require('../'); // require('react');
4
+ var fstr = require('../dsl/fstr'); // require('react/dsl/fstr');
4
5
 
5
6
  function loadUser(uid, cb){ setTimeout(cb, 100, null, "User"+uid); }
6
7
  function loadFile(filename, cb){ setTimeout(cb, 100, null, 'Filedata'+filename); }
@@ -19,7 +20,7 @@ function useHtml(err, html, user, bytesWritten) {
19
20
  console.log('final result: %s, user: %s, written:%s', html, user, bytesWritten);
20
21
  }
21
22
 
22
- var loadAndSave = react.fstrDefine('filename, uid, outDirname, cb', [ // input params
23
+ var loadAndSave = fstr('filename, uid, outDirname, cb', [ // input params
23
24
  loadUser, 'uid -> err, user', // calling async fn loadUser with uid, callback is called with err and user
24
25
  loadFile, 'filename -> err, filedata',
25
26
  markdown, 'filedata -> returns html', // using a sync function
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var react = require('../'); // require('react');
3
+ var pcodeDefine = require('../dsl/pcode'); // require('react/dsl/pcode');
4
4
 
5
5
  function multiply(a, b, cb) { cb(null, a * b); }
6
6
  function add(a, b) { return a + b; }
@@ -9,7 +9,7 @@ var locals = { // since pcodeDefine uses strings, need references to functions
9
9
  add: add
10
10
  };
11
11
 
12
- var fn = react.pcodeDefine('a, b, cb', [ // input params
12
+ var fn = pcodeDefine('a, b, cb', [ // input params
13
13
  'm := multiply(a, b)', // using a callback function, use :=
14
14
  's = add(m, a)', // using a sync function, use =
15
15
  'cb(err, m, s)' // output params for final callback
package/lib/base-task.js CHANGED
@@ -96,6 +96,7 @@ BaseTask.prototype.isReady = function (vCon, tasksByName) {
96
96
  };
97
97
 
98
98
  BaseTask.prototype.isMethodCall = function () {
99
+ /*jshint regexp: false */
99
100
  return (typeof(this.f) === 'string' && /^.*\..*$/.test(this.f)); //str contains .
100
101
  };
101
102
 
package/lib/cb-task.js CHANGED
@@ -43,6 +43,19 @@ CbTask.validate = function (taskDef) {
43
43
  return errors;
44
44
  };
45
45
 
46
+ CbTask.prototype.prepare = function prepare(handleTaskError, vCon, contExec) {
47
+ var self = this;
48
+ this.cbFun = function (err, arg0, arg1, argn) {
49
+ var args = Array.prototype.slice.call(arguments, 1);
50
+ if (err) { handleTaskError(self, err); return; } //handle error and return, we are done
51
+
52
+ //no error, save callback args to vCon context, then continue execution
53
+ vCon.saveResults(self.out, args);
54
+ self.complete(args);
55
+ contExec();
56
+ };
57
+ };
58
+
46
59
  CbTask.prototype.exec = function exec(vCon, handleError, contExec) {
47
60
  try {
48
61
  var args = this.a.map(function (k) { return vCon.getVar(k); }); //get args from vCon
@@ -51,7 +64,7 @@ CbTask.prototype.exec = function exec(vCon, handleError, contExec) {
51
64
  this.start(args); //note the start time, args
52
65
  args.push(this.cbFun); // push callback fn on end
53
66
  var func = this.f;
54
- var bindObj = null; //global space
67
+ var bindObj = vCon.getVar('this'); //global space or the original this
55
68
  if (this.isMethodCall()) { //if method call then reset func and bindObj
56
69
  func = vCon.getVar(this.f);
57
70
  bindObj = this.getMethodObj(vCon);
package/lib/core.js CHANGED
@@ -7,16 +7,25 @@ var validate = require('./validate.js');
7
7
  var tskutil = require('./task.js');
8
8
  var STATUS = require('./status.js');
9
9
  var VContext = require('./vcon.js');
10
- var FinalCbTask = require('./finalcb-task.js');
11
10
  var EventManager = require('./event-manager.js');
12
11
  var inputParser = require('./input-parser.js');
13
12
  var idGenerator = require('./id.js');
14
13
 
15
14
  var reactOptions = {
16
- stackTraceLimitMin: 30
15
+ stackTraceLimitMin: 30
17
16
  };
18
17
 
19
- var reactEmitter = EventManager.create(); // the top emitter
18
+ var reactEmitter = EventManager.global; // the top emitter
19
+
20
+ /**
21
+ merge global react options with parsed options
22
+ */
23
+ function mergeOptions(parsedOptions) {
24
+ return Object.keys(reactOptions).reduce(function (accum, k) {
25
+ if (!accum[k]) accum[k] = reactOptions[k];
26
+ return accum;
27
+ }, parsedOptions);
28
+ }
20
29
 
21
30
  /**
22
31
  Creates react function which the AST can be manipulated and then
@@ -39,7 +48,7 @@ var reactEmitter = EventManager.create(); // the top emitter
39
48
  */
40
49
  function reactFactory() {
41
50
  if (arguments.length) throw new Error('react() takes no args, check API');
42
-
51
+
43
52
  error.ensureStackTraceLimitSet(reactOptions.stackTraceLimitMin);
44
53
  var flowEmitter = EventManager.create();
45
54
  flowEmitter.parent = reactEmitter;
@@ -56,18 +65,32 @@ function reactFactory() {
56
65
  Object.keys(newAST).forEach(function (k) { ast[k] = newAST[k]; }); // copy all properties
57
66
  var errors = validate(ast);
58
67
  if (!errors.length) tskutil.nameTasks(ast.tasks); //run this so names can be checked in ast
68
+ if (Object.freeze) { //lets freeze the AST so plugin writers don't accidentally manip the ast
69
+ Object.keys(newAST).forEach(function (k) {
70
+ if (typeof(newAST[k]) === 'object') Object.freeze(newAST[k]);
71
+ });
72
+ Object.freeze(newAST);
73
+ }
59
74
  return errors;
60
75
  }
61
76
 
62
77
  function exec(arg1, arg2, argN, cb) { // called to execute the flow
78
+ /*jshint validthis: true */
63
79
  var parsedInput = inputParser(Array.prototype.slice.call(arguments), ast);
64
- var args = parsedInput.args;
65
- var cbFinal = parsedInput.cb;
66
- var extraArgs = parsedInput.extraArgs; // we'll have these if we need them
67
- var vCon = VContext.create(args, ast.inParams, ast.locals); // create var ctx with in args & locals
68
- var tasks = ast.tasks.map(tskutil.create);
80
+ var vCon = VContext.create(parsedInput.args, ast.inParams, ast.locals, this); // create var ctx with in args & locals
81
+
82
+ var taskEnv = { // collect taskEnv for hook
83
+ parsedInput: parsedInput,
84
+ vCon: vCon,
85
+ ast: ast, // for reference, will not be used further
86
+ taskDefs: ast.tasks.slice(), // create copy
87
+ outTaskDef: ast.outTask
88
+ };
89
+ reactEmitter.emit(EventManager.TYPES.EXEC_TASKS_PRECREATE, taskEnv); // hook
90
+
91
+ var tasks = taskEnv.taskDefs.map(tskutil.create);
69
92
  var tasksByName = tskutil.nameTasks(tasks); // map names to working tasks
70
- var outTask = tskutil.createOutTask(ast.outTask, cbFinal, tasks, vCon);
93
+ var outTask = tskutil.createOutTask(taskEnv.outTaskDef, parsedInput.cb, tasks, vCon, mergeOptions(parsedInput.options));
71
94
  var handleError = tskutil.createErrorHandler(vCon, outTask);
72
95
 
73
96
  function contExec() {
@@ -75,13 +98,14 @@ function reactFactory() {
75
98
  if (outTask.isReady()) return outTask.exec(); // all tasks done, exec cb, return
76
99
  tskutil.findReadyAndExec(vCon, tasks, tasksByName, handleError, contExec); //exec tasks that ready to run
77
100
  }
78
-
101
+
79
102
  tasks.forEach(function (t) {
80
103
  t.id = idGenerator.createUniqueId();
81
104
  t.flowEmitter = flowEmitter;
82
- if (t.type === 'cb') t.cbFun = tskutil.createCallback(t, handleError, vCon, contExec, flowEmitter);
105
+ if (t.prepare) t.prepare(handleError, vCon, contExec, flowEmitter);
83
106
  }); // create callbacks
84
107
  contExec(); // start things off
108
+ return outTask.retValue; // could return promise
85
109
  }
86
110
 
87
111
  var reactFn = exec; // make the exec() the function returned