GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — repl: allow `await` in REPL · Issue #13209 · nodejs/node

repl: allow await in REPL #13209

New issue
Copy link
New issue
Copy link
Closed
Closed
repl: allow await in REPL#13209
Copy link
Assignees
TimothyGu
Labels
cliIssues and PRs related to the Node.js command-line interface.Issues and PRs related to the Node.js command-line interface.feature requestIssues requesting new Node.js features.Issues requesting new Node.js features.promisesIssues and PRs related to ECMAScript promises.Issues and PRs related to ECMAScript promises.replIssues and PRs related to the REPL subsystem.Issues and PRs related to the REPL subsystem.

Description

@benjamingr
benjamingr
opened on May 24, 2017
Issue body actions

I've seen this requested a few times in StackOverflow now:

People have code that is asynchronous and would like to use values from it in the REPL:

// how do I access in the REPL? returns promise
Transaction.where('reference', '1').fetch().then((res) => { return res }); 

A common workaround is to store a global reference in the REPL, which is a little hacky and relies on timing, but can work for simple cases:

> Transaction.where('reference', '1').fetch().then((res) => out = res)
[Object Promise]
> out
   /* response available here*/

This works, but has timing issues and generally isn't great. We could however run the REPL in the context of an async function potentially - which would allow awaiting values in the REPL:

let res = await Transaction.where('reference', '1').fetch(); 

I think it could be an interesting enhancement but would like more feedback on the idea. @nodejs/collaborators

Reacted by Teddy Katz, Refael Ackermann, Alexander Frisch, Sindre Sorhus, Bergi, no, Ivo Todorov, ebraminio, Tomas Della Vedova, pannous and 124 more
Reacted by Sergey Rubanov and Luis Eduardo Brito
Reacted by pannous, Adrien Becchis, Kothique Félixx, Luis Eduardo Brito, Ahmad Said, ExE Boss and Joe Lust
Reacted by juno suárez, Radon Rosborough, Gabriele Tomberli, Casu, Adrien Becchis, Motoi Washida, Alexander Ivanov, Kothique Félixx, Luis Eduardo Brito, A Flores and 4 more
Reacted by ExE Boss
Reacted by Antonio Ferrándiz and Hydrophobefireman

Activity

Next
  1. benjamingr
    added
    feature requestIssues requesting new Node.js features.Issues requesting new Node.js features.
    promisesIssues and PRs related to ECMAScript promises.Issues and PRs related to ECMAScript promises.
    replIssues and PRs related to the REPL subsystem.Issues and PRs related to the REPL subsystem.
    on May 24, 2017
  2. not-an-aardvark commented on May 24, 2017

    @not-an-aardvark
    not-an-aardvark
    on May 24, 2017
    Contributor
    More actions

    👍

    I looked into implementing this when Node 7.6.0 came out and async functions were originally added. At first glance it seemed like it would be a bit difficult because the REPL currently doesn't run in a function context at all. However, there might be a better solution that I'm not aware of.

    Reacted by Benjamin Gruenbaum
  3. refack commented on May 24, 2017

    @refack
    refack
    on May 24, 2017
    Contributor
    More actions

    I'm +1.
    But there are userland solutions, quick googling found https://github.com/skyrising/await-repl, https://github.com/StreetStrider/repl.js, and I'm sure there are more

  4. not-an-aardvark commented on May 24, 2017

    @not-an-aardvark
    not-an-aardvark
    on May 24, 2017
    Contributor
    More actions

    await-repl seems to only await a promise if the line starts with "await ", which is probably insufficient (e.g. it doesn't allow foo = await bar().

    repl.js seems to auto-await all Promises that are returned from an eval, but that also probably isn't what we want (and it doesn't allow for nested await either).

  5. refack commented on May 24, 2017

    @refack
    refack
    on May 24, 2017
    Contributor
    More actions

    I'm not arguing that this is a beneficial feature. But IMHO the REPL is an exploratory tool, so those tools at least enable easier exploration 🤷‍♂️
    On the other hand the cli -e option, again IMHO, is a more "important" feature to enable easy await usage for.
    node -e "await new Promise.resolve(4)"

  6. vkurchatkin commented on May 24, 2017

    @vkurchatkin
    vkurchatkin
    on May 24, 2017
    Contributor
    More actions

    The question is, is it really possible? It seems like it's not

    Reacted by Sergey Rubanov and Den Rupp
  7. refack
    added
    cliIssues and PRs related to the Node.js command-line interface.Issues and PRs related to the Node.js command-line interface.
    on May 24, 2017
  8. not-an-aardvark commented on May 24, 2017

    @not-an-aardvark
    not-an-aardvark
    on May 24, 2017
    Contributor
    More actions

    It would definitely be possible in theory by reimplementing await semantics and parsing, but that seems like a lot of work. Ideally there would be some --allow-top-level-await flag in V8 that we can use.

  9. joyeecheung commented on May 25, 2017

    @joyeecheung
    joyeecheung
    on May 25, 2017
    Member
    More actions

    There was a feature request issue for this and there are some solutions proposed there: #8382 although it seems most of them are somewhat hacky

  10. benjamingr commented on May 25, 2017

    @benjamingr
    benjamingr
    on May 25, 2017
    MemberAuthor
    More actions

    @vkurchatkin

    The question is, is it really possible? It seems like it's not

    Why can't we just wrap the content with an async function?

  11. ChALkeR commented on May 25, 2017

    @ChALkeR
    ChALkeR
    on May 25, 2017
    Member
    More actions

    @benjamingr, that will change the semantics of repl. We need to detect it somehow, or use a flag, or force this as a semver-major change for everyone.

  12. benjamingr commented on May 25, 2017

    @benjamingr
    benjamingr
    on May 25, 2017
    MemberAuthor
    More actions

    @ChALkeR what semantics would it change? I figured that since the REPL is not synchronous anyway (being user input and all) the microtick of wrapping it in an async function - unwrapping it and giving the user back the result wouldn't be too bad.

    Am I missing anything?

  13. targos commented on May 25, 2017

    @targos
    targos
    on May 25, 2017
    Member
    More actions

    @benjamingr do you have ideas about how to make this work:

    > const a = Promise.resolve(42);
    undefined
    > const b = await a;
    undefined
    > b
    42

    If we wrapped the code in an async function, b would be local to this function. How to unwrap it?

    Reacted by Benjamin Gruenbaum, Andy Edwards and Mourad Kejji
  14. 83 remaining items

  15. filips123 commented on Jul 1, 2019

    @filips123
    filips123
    on Jul 1, 2019
    More actions

    Is there any specific reason why is await under an experimental flag? Why is it not enabled by default?

    Reacted by Chris Talman and Sablier Bot
  16. devsnek commented on Jul 1, 2019

    @devsnek
    devsnek
    on Jul 1, 2019
    Member
    More actions

    @filips123 when await is enabled we run input through a separate parser which doesn't necessarily match the way node normally parses code, so there could be incompatibilities. In the long run, a combination of top-level-await and a standardized repl parse goal should fix this.

    https://github.com/tc39/proposal-top-level-await
    https://github.com/bmeck/js-repl-goal

  17. FossPrime commented on Jul 19, 2019

    @FossPrime
    FossPrime
    on Jul 19, 2019
    More actions

    Summary, it works with an experimental flag. use something like the following to load some js and drop you into a repl after the variables are set, kind of like bashrc.

    #!/bin/bash
    node  --experimental-repl-await -i -e "$(< scripts/repl.js)"`
    

    With enough run commands, it might be possible to replace bash with node lol
    https://stackoverflow.com/questions/33850903/use-node-js-as-shell

    Reacted by Ray Foss, hadroncfy and Jure Triglav
  18. nahtnam commented on Sep 5, 2019

    @nahtnam
    nahtnam
    on Sep 5, 2019
    More actions

    Has anyone figured out how to get the experimental flag to work in a REPL that is spawned with .start()? The following snippet doesn't work.

    process.env.NODE_OPTIONS = '--experimental-repl-await';
    const local = repl.start({ prompt: '> ' });
    
    Reacted by Filip Štamcar, Sam Yau, anna herlihy and Philippe Serhal
  19. aherlihy commented on Oct 3, 2019

    @aherlihy
    aherlihy
    on Oct 3, 2019
    More actions

    Having the same issue as @nahtnam with trying to get await mode turned on from repl.start. Any suggestions?

  20. bapti commented on Dec 1, 2019

    @bapti
    bapti
    on Dec 1, 2019
    More actions

    I did this and it worked

    "scripts": {
        "repl": "node --experimental-repl-await ./repl.js"
    }

    And in repl.js

    const { readFileToArray } = require("./utils");
    const repl = require("repl");
    
    repl.start("> ").context.readFileToArray = readFileToArray;

    When I run it it works fine and I can await on my function readFileToArray

    Reacted by Iddan Aaronsohn, Ryan Wersal, Guillaume Massé (马赛卫), Alex Yang, Yang-Hsing Lin and Jerry Baba
  21. tomasgvivo commented on Mar 27, 2020

    @tomasgvivo
    tomasgvivo
    on Mar 27, 2020
    More actions

    Top level await is now supported in V8 (https://v8.dev/features/top-level-await)
    Is it possible to add something like vm.runAsyncInContext to avoid using a different parser for code containing async in repl?

    Also, I could really use vm.runAsyncInContext for a jupyter-notebook-like node project.

  22. devsnek commented on Mar 28, 2020

    @devsnek
    devsnek
    on Mar 28, 2020
    Member
    More actions

    @tomasgvivo TLA is part of modules. Once we land support for it (#30370), you can use it in a vm.SourceTextModule instance.

    There is another thing V8 is working on called "repl mode" which might help with await in the repl though: https://docs.google.com/document/d/1bIKMRrLVObsAfmMAQ-tmsWkQZu1cFg87RRrPpiwTL2M/edit

    Reacted by ExE Boss and Tomas Gonzalez Vivo
  23. cyrus-and commented on Apr 26, 2020

    @cyrus-and
    cyrus-and
    on Apr 26, 2020
    More actions

    When the adding the command line --experimental-repl-await is not an option, one could use this hack to always await promises on a custom REPL:

    const defaultEval = myRepl.eval;
    myRepl.eval = (cmd, context, filename, callback) => {
        defaultEval(cmd, context, filename, async (err, result) => {
            if (err) {
                // propagate errors from the eval
                callback(err);
            } else {
                // awaits the promise and either return result or error
                try {
                    callback(null, await Promise.resolve(result));
                } catch (err) {
                    callback(err);
                }
            }
        });
    };

    It is not a general solution but worked well for my use case.

    Reacted by Sean Dunford
    Reacted by Aaryamann Challani
  24. YoraiLevi commented on Jun 3, 2020

    @YoraiLevi
    YoraiLevi
    on Jun 3, 2020
    More actions

    When the adding the command line --experimental-repl-await is not an option, one could use this hack to always await promises on a custom REPL:

    const defaultEval = myRepl.eval;
    myRepl.eval = (cmd, context, filename, callback) => {
        defaultEval(cmd, context, filename, async (err, result) => {
            if (err) {
                // propagate errors from the eval
                callback(err);
            } else {
                // awaits the promise and either return result or error
                try {
                    callback(null, await Promise.resolve(result));
                } catch (err) {
                    callback(err);
                }
            }
        });
    };

    It is not a general solution but worked well for my use case.

    // index.js
    const repl = require("repl");
    const myRepl = repl.start();
    
    const defaultEval = myRepl.eval;
    myRepl.eval = (cmd, context, filename, callback) => {
      defaultEval(cmd, context, filename, async (err, result) => {
        if (err) {
          // propagate errors from the eval
          callback(err);
        } else {
          // awaits the promise and either return result or error
          try {
            callback(null, await Promise.resolve(result));
          } catch (err) {
            callback(err);
          }
        }
      });
    };

    usage node index.js
    type:

    function delayPromise(delay){
        //async delay function
        return new Promise(resolve => setTimeout(() => resolve(), delay))
    }
    delayPromise(3000)
    undefined
    //wait 3 seconds until can proceed typing
    Reacted by Sean Dunford
    Reacted by Jimmie Tyrrell
  25. pstaender
    added a commit that references this issue on Jun 26, 2020

    Adds await support to strapis REPL console

    b5f0a5d
  26. andyvanee commented on Oct 20, 2020

    @andyvanee
    andyvanee
    on Oct 20, 2020
    More actions

    I'm not sure why, but using --experimental-repl-await affects how util.inspect.defaultOptions are interpreted. In normal code you could adjust the output of console.log using the following:

    import util from "util"
    util.inspect.defaultOptions.getters = true
    util.inspect.defaultOptions.depth = 4
    util.inspect.defaultOptions.maxStringLength = 80

    But when using --experimental-repl-await it needs to be changed to this:

    import util from "util"
    util.inspect.replDefaults.getters = true
    util.inspect.replDefaults.depth = 4
    util.inspect.replDefaults.maxStringLength = 80

    The docs seem to suggest that the replDefaults should mirror defaultOptions, but this doesn't seem to be the case when using the async version of the REPL.

  27. kawamataryo
    added 2 commits that reference this issue on Sep 12, 2021

    [from now] 2021/09/12 20:25:28

    db8ecb0

    [from now] 2021/09/12 20:33:11

    d6b595b
  28. sjarmak
    added a commit that references this issue on Jul 27, 2026

    repl: support top-level await

    eeab7bc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @TimothyGu
    TimothyGu

Labels

cliIssues and PRs related to the Node.js command-line interface.Issues and PRs related to the Node.js command-line interface.feature requestIssues requesting new Node.js features.Issues requesting new Node.js features.promisesIssues and PRs related to ECMAScript promises.Issues and PRs related to ECMAScript promises.replIssues and PRs related to the REPL subsystem.Issues and PRs related to the REPL subsystem.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.