Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

yield/await support in repl/cli #8382

Closed
martinheidegger opened this issue Sep 2, 2016 · 31 comments
Closed

yield/await support in repl/cli #8382

martinheidegger opened this issue Sep 2, 2016 · 31 comments
Labels
feature request Issues that request new features to be added to Node.js. help wanted Issues that need assistance from volunteers or PRs that need help to proceed. repl Issues and PRs related to the REPL subsystem.

Comments

@martinheidegger
Copy link

martinheidegger commented Sep 2, 2016

In the version of node 6.5.0 that I am running, the repl does support quite a few things already - which is awesome. One thing I came to miss when trying things out though is that the yield (as often used before await and/or the await keyword. If yield would be available like with co or await would be available like in the concept then async code would become easy to test in the REPL.

@addaleax addaleax added repl Issues and PRs related to the REPL subsystem. feature request Issues that request new features to be added to Node.js. labels Sep 2, 2016
@Fishrock123
Copy link
Contributor

@martinheidegger It already is if you run a generator function, I'm not 100 sure what you are asking.
Could you provide an example?

@bmeck
Copy link
Member

bmeck commented Sep 2, 2016

@Fishrock123 I think the idea is that the default repl wraps the code being run in a generator/async function so that the following works:

> var x = await Promise.resolve(1); x
1

~=

async () => {
  return eval(`var x = await Promise.resolve(1); x`);
}

await seems reasonable, particularly if modules get it at the top level, but not gonna bite on special casing yield.

@martinheidegger
Copy link
Author

@Fishrock123 @bmeck Explained my request better than me.
@bmeck I am in agreement that await seems more reasonable, the only reason I mentioned yield is because async/await seemed like an unfinished feature at this point.

@martinheidegger
Copy link
Author

My personal example is working with nodegit

> var git = require('nodegit')
undefined
> var repo = await git.getRepo('.')
undefined
> await repo.getCommit(sha)
Commit { repo: Repository {} }

@bmeck
Copy link
Member

bmeck commented Sep 2, 2016

@martinheidegger async/await functions were accepted in July : https://github.com/tc39/proposals/blob/master/finished-proposals.md

@targos
Copy link
Member

targos commented Sep 2, 2016

+1 for such a feature. It would make it much easier to work with Promise-based APIs

@bmeck
Copy link
Member

bmeck commented Sep 2, 2016

blocked on v8 giving us unflagged async/await functions at the very least.

ref: https://bugs.chromium.org/p/v8/issues/detail?id=4483

@bmeck bmeck added the blocked PRs that are blocked by other issues or PRs. label Sep 2, 2016
@Fishrock123
Copy link
Contributor

I wonder if a --require module could appropriately extend the built-in repl?

@bmeck
Copy link
Member

bmeck commented Sep 2, 2016

@Fishrock123 well modules have not fully landed top level await in spec (proposal in september?) so the module parser in v8 won't land the await outside of async functions for a while still.

@Fishrock123
Copy link
Contributor

I mean for yield.

@princejwesley
Copy link
Contributor

This is how I implemented in my electron based REPL.

const awaitMatcher = /^(?:\s*(?:(?:let|var|const)\s)?\s*([^=]+)=\s*|^\s*)(await\s[\s\S]*)/;
const asyncWrapper = (code, binder) => {
  let assign = binder ? `root.${binder} = ` : '';
  return `(function(){ async function _wrap() { return ${assign}${code} } return _wrap();})()`;
};

// match & transform
const match = input.match(awaitMatcher);
if(match) {
  input = `${asyncWrapper(match[2], match[1])}`;
}

@pannous
Copy link

pannous commented Dec 24, 2016

little workaround / hack:

await=promise=>{
  ret = undefined
  promise.then(response=>ret=response)
  while(ret === undefined) {require('deasync').runLoopOnce();}
  return ret
}

or

await=async function(promise){
  result=await promise // result now available via side effect (workaround)
  return result // still PROMISE in return!??! but ok otherwise 
}

or just
await=promise=>promise.then(x=>result=x)

of course the proposed addition of await to the REPL would be way better!

@sibelius
Copy link

sibelius commented Jan 5, 2017

@princejwesley how can I add your implementation to node repl?

I saw this as well: https://github.com/paulserraino/babel-repl

but it does not support await syntax yet

cc @paulserraino

@sibelius
Copy link

sibelius commented Jan 5, 2017

@martinheidegger what is the link for your personal working example of here: #8382 (comment)

@princejwesley
Copy link
Contributor

@sibelius Something like this

@martinheidegger
Copy link
Author

@sibelius Oh: I am afraid this is a misunderstanding: this is an example of how i would love it to work.

@sibelius
Copy link

sibelius commented Jan 5, 2017

@princejwesley it does work tks for the awesome work

@martinheidegger u should try @princejwesley gist

@knilink
Copy link

knilink commented Feb 4, 2017

I was looking for similar solusion as well and I made this after I saw pannous's comment.
Now I'm happy with testing nodegit in REPL.

> syncPromise(require('nodegit')).getRepo('.').o.getCommit(sha).o
Commit { repo: Repository {} }

@joyeecheung joyeecheung removed the blocked PRs that are blocked by other issues or PRs. label Feb 22, 2017
@joyeecheung
Copy link
Member

Removed blocked because unflagged async/await have landed in master.

@martinheidegger
Copy link
Author

@joyecheung It would be nice to reference the commit.

@joyeecheung
Copy link
Member

@martinheidegger Sure, it should be PR #9618 and commit 2739185

@martinheidegger
Copy link
Author

@joyeecheung Awesome! Did you have a chance to test it? Does await work in the Repl?

@TimothyGu TimothyGu added blocked PRs that are blocked by other issues or PRs. and removed blocked PRs that are blocked by other issues or PRs. labels Feb 22, 2017
@TimothyGu
Copy link
Member

@martinheidegger, in v7.6.0 we have updated V8 to 5.5, which makes it possible to use async functions w/o the --harmony flag, so we can actually get started with implementing. The actual ability of using await in the REPL hasn't been implemented yet.

Apologize for the label shuffling. Didn't realize what it was actually blocking on.

@nfcampos
Copy link

I made a small package https://www.npmjs.com/package/await-outside that you can use as

node --require await-outside/repl

or just

await-outside

Hope it helps anyone

@Qard
Copy link
Member

Qard commented Mar 16, 2017

I just had a quick look at implementing this. Naively wrapping each input line with (async function() { return ${line} })() and changing the callback trigger from cb(err, result) to something like Promise.resolve(result).then(res => cb(null, res), cb) works, but breaks assignments. The await-outside module mentioned above uses a regex hack to redirect assignments to globals, but I worry about how reliable that'd be...

@pannous
Copy link

pannous commented Mar 16, 2017

way too hacky if you insert multi line function etc

@nfcampos
Copy link

you might notice that the tests of await-outside do cover multi-line inputs

@motet-a
Copy link

motet-a commented Apr 23, 2017

Hello, I wrote this quick and dirty Babel-based experiment: https://github.com/motet-a/async-repl

It works as described by @Qard, so currently variable declarations are broken. But it’s not a big deal since we could transform variable declarations into global assigments only in the global scope with Babel, skipping declarations inside inner functions. It’s not perfect but it could be pretty reliable.

@Trott Trott added the help wanted Issues that need assistance from volunteers or PRs that need help to proceed. label Aug 2, 2017
@billybonks
Copy link

in the mean time you could stub repl with https://github.com/ef4/async-repl

@TimothyGu
Copy link
Member

BTW there is an open PR for await support at #15566.

@targos
Copy link
Member

targos commented Nov 24, 2017

Top-level await is now supported in the REPL. Closing.

@targos targos closed this as completed Nov 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Issues that request new features to be added to Node.js. help wanted Issues that need assistance from volunteers or PRs that need help to proceed. repl Issues and PRs related to the REPL subsystem.
Projects
None yet
Development

No branches or pull requests