Giter Club home page Giter Club logo

continuation's People

Contributors

alhimik45 avatar byvoid avatar curimit avatar pimterry avatar reynir avatar shankerwangmiao avatar summivox avatar tomibelan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

continuation's Issues

using 'continue' in for (... in ...)

var console = require('console');

function async (ret) {
  ret(null, [1, 2, 3, 4, 5, 6]);
}

try {
  async(obtain(a));
  for (var i in a)
    if (i % 2 == 0) continue;
    else console.log(a[i]);
} catch (err) {
  console.log(err);
}

The iterator doesn't go forward with continue.

Add example for parallel array processing

I can't seem to work out how to do the equivalent of

async.each https://github.com/caolan/async#eacharr-iterator-callback

or

async.map https://github.com/caolan/async#maparr-iterator-callback

Is there any chance of an example of something like that? These are the only use cases keeping my project dependant on the async library and I would love to remove that dependency if possible as I prefer the simplicity of the syntax when using your library and the robust error trapping.

Move 'use strict' above

function test() {
    'use strict';
    f(obtain());
}

Actual

function test() {
  var _$err;
  'use strict';
  f(function () {
    _$err = arguments[0];
    if (_$err)
      throw _$err;
  });
}

Heuristics for exceptions don't work

function test(ret) {
  throw undefined;
}

try {
  test();
} catch(e) {
  console.log('Exception1: ', e); // prints Exception1: undefined
}

try {
  test(cont(res));
} catch(e) {
  console.log('Excpetion2: ',e); // Never prints!
}

Substituting undefined for 42 will print 42 in both places.

Portable continuations?

Are continuations portable? Specifically, could a continuation be serialized and sent across the network to be resumed elsewhere?

If that were possible you could potentially do some very interesting stuff with breaking down the barrier between client and server. I experimented with this idea a few years ago using Scala (which has a compiler plugin that does something similar to this project), you can learn more about these ideas here: http://swarmframework.org/

The compiler allow non-lvars as argument to cont() etc.

In other words, the compiler does not check whether the arguments to cont() etc.
are assignable. Here is an example:

// Source
async(stuff, cont(err, result+4));
bar(result+1);

// Output
var err;
async(stuff, function () {
  err = arguments[0];
  (result + 4) = arguments[1];
  bar(result + 1);
});
/* Generated by Continuation.js v0.1.3 */

This is always an error. You cannot assign to (result + 4). Actually, you can also
write 4 instead result + 4 and you will get 4 = arguments[1];!

Running compiler from the browser

My project does not use a module loading system such as RequireJS or AMD, so I am a bit of a loss at how to run the compiler from the browser.

Can the continuation compiler be run from the browser? If so, is there an example for that?

`this` get lost in try block

 a={}
  a.b=(cb)->
    console.log this
    try
      console.log this
      this.b cont()
    catch err
      console.error err
  a.b()

the output code is

(function () {
  var a;
  a = {};
  a.b = function (cb) {
    var err;
    console.log(this);
    (function (_$cont) {
      try {
        console.log(this);
        return this.b(function (arguments) {
          try {
            _$cont();
          } catch (_$err) {
            _$cont(_$err);
          }
        }.bind(this, arguments));
      } catch (_$err) {
        _$cont(_$err);
      }
    }(function (_error) {
      if (_error !== undefined) {
        err = _error;
        return console.error(err);
      }
    }));
  };
  a.b();
}.call(this));
/* Generated by Continuation.js v0.1.7 */

Apparently, this get lost in the structure

(function (_$cont) {
  //...
})(function (_error) {
})

ECMAScript 6 is not supported

This project is still alive? Can you please add support for new version JS languege.

Now, if continuation meet token like () => {} it obtain error:

Error: Line 15: Unexpected token => in undefined
at Object.parse (G:\ShepherdProject\cont8doo\node_modules\continuation\lib\parser.js:18:11)
at Object.exports.compile (G:\ShepherdProject\cont8doo\node_modules\continuation\continuation.js:29:20)
at compile (G:\ShepherdProject\cont8doo\node_modules\continuation\lib\cli.js:166:25)

Bizarre behavior when throw exceptions without try in a continuation block

var test = function(callback) {
    console.log('called');
    callback(null);
}

function main() {
    try {
        test(obtain(a));
    } catch (e) {
        console.log('error by obtain', e);
    }
    throw 'a';
}

try {
    main();
} catch (e) {
    console.log('error by main', e);
}

Expected:

called
error by main a

Actual:

called
error by obtain a
error by obtain a
error by main a

Arguments scope bug

js code:

var read = function() {
  var content = 'abc';
  fs.readFile('a.txt', 'utf-8', cont(err, content));
};

will be compiled to

var read;
read = function () {
  var content, err;
  content = 'abc';
  fs.readFile('a.txt', 'utf-8', function (arguments, _$param1, _$param2) {
    err = _$param1;
    content = _$param2;
  }.bind(this, arguments));
};

the variable content is changed.

So, the correct compiled result is that:

var read;
read = function () {
  var content;
  content = 'abc';
  fs.readFile('a.txt', 'utf-8', function (arguments, _$param1, _$param2) {
    var content, err;
    err = _$param1;
    content = _$param2;
  }.bind(this, arguments));
};

What do you think about it?

Wrong binding of `this` inside `if`/`while/`for`

Sample

this.name = 'outter';

function inner() {
  if (true) {
    setTimeout(cont(), 100);
    console.log(this.name);
  }
};

var o = {
  name: 'inner',
  inner: inner
};

console.log(this.name);
o.inner();

Execution result

The output result shoud be

outter
inner

But we got

outter
undefined

Compiled code

var o;
this.name = 'outter';
function inner() {
  (function (_$cont) {
    if (true) {
      setTimeout(function (arguments) {
        console.log(this.name);
        _$cont();
      }.bind(this, arguments), 100);
    } else {
      _$cont();
    }
  }(function (_$err) {
    if (_$err !== undefined)
      return _$cont(_$err);
  }));
}
o = {
  name: 'inner',
  inner: inner
};
o.inner();
console.log(this.name);
/* Generated by Continuation.js v0.1.4 */

I think the wrong context of function (_$cont) causes this bug, I will fix it soon.

challenging issue

// use continuation to create a function which can synced waiting for 1 second
var stop = function() {
setTimeout(continuation(), 1000);
};
console.log("start");
stop();
console.log("end");

// Readme:
// Due to this, I suggest to consider implement coroutine for javascript.
// we can implement "continuation" by using yield initiatively and resume by callback function.

Nested BlockStatements are improperly normalized

Block statements disappear.

{ x++; }
alert(cont());

is compiled to:

alert(function () {
});
/* Generated by Continuation.js v0.1.1 */

I'm working on a fix (and refactoring). A pull request should be ready soon.

Strange behaviour with hoisted function

The following example:

errorinAsync(null, obtain());

function errorinAsync(options, callback){
    options = options || {};
    setTimeout(function(){
        return callback(new Error("This could be caught"));
    },1000);

}

Does not run, the errorInAsync function is included in the wrong scope in the compiled output:

var _$err;
errorinAsync(null, function () {
  _$err = arguments[0];
  if (_$err)
    throw _$err;
  function errorinAsync(options, callback) {
    options = options || {};
    setTimeout(function () {
      return callback(new Error('This could be caught'));
    }, 1000);
  }
});

continuous return value instead of continuous passsing style?

Hi, great job there,
is it possible to implement a trasformation which makes it possible to pass return values on the left side of the expression?
example:

    var value = async_call(arg1, arg2, obtain);

Do you think it's hard to implement? Any suggestion about that?
Thank you very much!

Compiled code can't get the correct return value

When mix using obtain and return in one function, it seems it can't work properly.
For an example code like

'use continuation'
getElement = (callback) ->
  callback null, 1

checkElement = (number) ->
  getElement obtain standard
  number is standard

console.log checkElement 1
console.log checkElement 2

Which is aimed to check if an element is 1

After just

$ coffee -c a.coffee 

it produce

// Generated by CoffeeScript 1.6.2
(function() {
  'use continuation';
  var checkElement, getElement;

  getElement = function(callback) {
    return callback(null, 1);
  };

  checkElement = function(number) {
    getElement(obtain(standard));
    return number === standard;
  };

  console.log(checkElement(1));

  console.log(checkElement(2));

}).call(this);

The code seems shall work though. However, after using

$ continuation a.coffee -o abc.js

It produce

(function () {
  var checkElement, getElement;
  'use continuation';
  getElement = function (callback) {
    return callback(null, 1);
  };
  checkElement = function (number) {
    var _$err, standard;
    getElement(function () {
      _$err = arguments[0];
      standard = arguments[1];
      if (_$err)
        throw _$err;
      return number === standard;
    });
  };
  console.log(checkElement(1));
  console.log(checkElement(2));
}.call(this));
/* Generated by Continuation.js v0.1.2 */
//@ sourceMappingURL=abc.js.map

Which seems wrong for that return is in the function getElement's callback. Thus checkElement returns nothing.

More, when use

node abc.js

it gives

undefined
undefined

other than expected

true
false

Support source maps

Cool project! I really like how readable the generated code is (especially compared to Streamline, Tame etc). It'd be nice if it also supported source maps. Those are files that map locations in the source to locations in the generated code to make debugging easier.

Escodegen already supports source maps, so most of the hard work should hopefully be already done. But when the parser converts the AST nodes using syntax.factory, their "loc" property is lost. They need to keep it for source maps to work. (As for new nodes that weren't in the original AST, I guess their "loc" should just be null.)

Perhaps that's the only required change (well, plus adding the CLI option itself), but I'm not sure.

Wrong try/catch behavior

The following code doesn't work:

function callme(cb) {
  cb();
}

function main(cb) {
  try {
    callme(cont());
    var result = 0;
    [10, 20, 30].forEach(function (i) {
      result += i;
      throw Error('oh noes');
    });
  }
  catch (e) {
    cb(e);
    return;
  }
  cb(null, result);
}

main(function (e,r) {
  console.log('main() finished with', e, r);
})

Output:

main() finished with [Error: oh noes] undefined
main() finished with [Error: oh noes] undefined
main() finished with [Error: oh noes] undefined
main() finished with null 60

main() "finishes" multiple times (i.e. the console.log callback is called more than one time), which should never happen.

It seems continuation.js messes with the forEach callback and tries to "callback-ize" it even though forEach is always serial (and the function body doesn't contain "cont" nor "obtain"). Perhaps the correct behavior with nested functions is to leave them alone (and transform them separately, depending on whether they use cont) -- though that's just a guess and I'm not sure if that wouldn't break other stuff.

module searching terminates unexpectedly at certain directory

suppose the source tree is

/path/to/root
         |
         +--sub
         |  |
         |  +--main.js
         |
         +--node_modules
            |
            +--aaa
               |
               +--index.js

and main.js is

require('aaa');
console.log('sub/main.js');

while index.js is

console.log("this is aaa");

and below is the issue

% pwd
/path/to/root
% continuation sub/main.js
module.js:340
    throw err;
          ^
Error: Cannot find module 'aaa'
  at Function.Module._resolveFilename (module.js:338:15)
  at Function.Module._load (module.js:280:25)
  at Module.require (module.js:364:17)
  at require (module.js:380:17)
  at Object.<anonymous> (sub/main.js:1:69)
  at Module._compile (module.js:456:26)
  at executeTopModule (/usr/local/lib/node_modules/continuation/lib/cli.js:131:14)
  at Object.exports.main (/usr/local/lib/node_modules/continuation/lib/cli.js:86:7)
  at Object.<anonymous> (/usr/local/lib/node_modules/continuation/bin/continuation:3:5)
  at Module._compile (module.js:456:26)
  at Object.Module._extensions..js (module.js:474:10)
  at Module.load (module.js:356:32)
  at Function.Module._load (module.js:312:12)
  at Function.Module.runMain (module.js:497:10)
  at startup (node.js:119:16)
  at node.js:906:3
% continuation ./sub/main.js
this is aaa
sub/main.js
% continuation --version 
0.1.5
% node -v
v0.10.32

When using `cont()` in `if` block, the context in `if` is correct while the context after `if` is incorrect.

Sample

this.name = 'outter';

function inner() {
  if (true) {
    setTimeout(cont(), 100);
    // Correct context here.
    console.log(this.name);
  }
  // Wrong context here.
  console.log(this.name);
};

var o = {
  name: 'inner',
  inner: inner
};

console.log(this.name);
o.inner();

Which compiles to

var o;
this.name = 'outter';
function inner() {
  (function (_$cont) {
    if (true) {
      setTimeout(function (arguments) {
        console.log(this.name);
        _$cont();
      }.bind(this, arguments), 100);
    } else {
      _$cont();
    }
  }.bind(this)(function (_$err) {
    if (_$err !== undefined)
      return _$cont(_$err);
    console.log(this.name);
  }));
}
o = {
  name: 'inner',
  inner: inner
};
console.log(this.name);
o.inner();
/* Generated by Continuation.js v0.1.5 */

This part of the compiled result got the wrong context:

function (_$err) {
    if (_$err !== undefined)
      return _$cont(_$err);
    console.log(this.name);
  }

cont() and obtain() do not work when instantiating a class

The code in this function:

function t() {
    var csvPath = '/tmp/contacts.csv';
        parser  = new ContactDocParser(csvPath, cont());
}

gets compiled to

function t() {
    var csvPath = '/tmp/contacts.csv';
        parser  = new ContactDocParser(csvPath, cont());
}
/* Generated by Continuation.js v0.1.4 */

It just ignores it.
When I remove the new statement, it does replace the cont()

function declaration should goes to the top level

test();
setTimeout(cont(), 100);
function test() {
  console.log('test');
}

Which compiles to

test();
setTimeout(function (arguments) {
  function test() {
    console.log('test');
  }
}.bind(this, arguments), 100);

This is incorrect.

Wrong context when using `cont()` in switch..case

Sample

this.name = 'outter';

function inner() {
  var a = "a";

  switch (a) {
  case "a":
    setTimeout(cont(), 100);
    // wrong content here
    console.log(this.name);
    break;
  }
};

var o = {
  name: 'inner',
  inner: inner
};

console.log(this.name);
o.inner();

Which compiles to

var o;
this.name = 'outter';
function inner() {
  var a;
  a = 'a';
  (function (_$cont) {
    function case_0(_$cont) {
      setTimeout(function (arguments) {
        console.log(this.name);
        _$cont();
      }.bind(this, arguments), 100);
    }
    switch (a) {
    case 'a':
      return case_0(_$cont);
    }
  }.bind(this)(function () {
  }));
}
o = {
  name: 'inner',
  inner: inner
};
console.log(this.name);
o.inner();
/* Generated by Continuation.js v0.1.5 */

As you can see it we defined a function called case_0 here, but we haven't bind this pointer correctly.
I think we should add case_0 = case_0.bind(this); to make case_0(_$cont); get the correct context.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.