Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34.2k
repl: Support for eager evaluation#22875
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
Uh oh!
There was an error while loading. Please reload this page.
Conversation
antsmartian commented Sep 15, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Trott commented Sep 15, 2018
@nodejs/repl |
devsnek commented Sep 15, 2018
any reason this is limited to call expressions? |
antsmartian commented Sep 15, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
@devsnek I need to extend to other expressions as well, but just wanted to post my progress here so that I can get review from the community (mainly on whether or not I'm in right direction). Edit: Or we can first go with call expressions and expand there-after. As always, its all depends on what community says :) |
32d6067 to 047b6e6Compareantsmartian commented Sep 16, 2018
@devsnek Added support for other expressions and as well for |
047b6e6 to 7138252Comparelib/repl.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's no need to check if its a valid expression, or even an expression at all.
antsmartianSep 16, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just thought sending code for every key press for eval might be unnecessary.
Yes we can remove them, anyways the code block is in try catch block, so in worst case that should catch the exception if any.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
v8 will detect invalid code anyway, so there's no need to manually check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@devsnek Ok make sense, if I remove the check, then there would be preview results as necessary. Hence, few test cases will be failing (I could see test-repl-persistent-history.js failing already). Let me work on fixing those test cases and update the PR.
Fishrock123 left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pretty neat but certainly needs more work (as you seem to be aware)!
Some things I noticed:
- Not all edits to the current line cause the eager eval to re-appear.
- The eager eval should probably be colored with grey and the colors of inspect outputs should probably also go though a grey-ing filter.
Uh oh!
There was an error while loading. Please reload this page.
antsmartian commented Sep 17, 2018
@Fishrock123 Yes, you are correct. Not all edits (with valid code) trigger eager eval. I knew that it needs to be worked out. Regarding color will change them. Thanks for taking time to review this! |
danbev commented Sep 19, 2018
antsmartian commented Oct 9, 2018
Just to give an update, I will find some time later this week, afterwhich I will be updating the PR with comments addressed. Sorry for the delay :) |
bcadcce to e005596Compareantsmartian commented Oct 14, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
@devsnek@Fishrock123 Addressed your comments. Now eager eval will work on all lines (when v8 says it has a preview). Also changed the color to grey. Updated the tests. Let me know if anything else is needed. Thanks! |
antsmartian commented Oct 18, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Friendly remainder : @devsnek@Fishrock123 🔉 |
lib/readline.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is there in both the branches, at the end. Perhaps this can be moved out of the if..else.
lib/repl.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its better to expect the specific exceptions and ignore them. Is that possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also if there is an error, will the result object always have result property?
antsmartianOct 27, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes result will always have result even in case of error. Will refactor the variable to previewResult, so that its better readable.
antsmartianOct 27, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And about the exception, it can be syntax issues, side effects etc. Not sure if I can catch them specifically. @devsnek can give some thoughts on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
appendPreview doesn't have a space character after //. Is this intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, it was a miss. Good catch. Will fix them.
antsmartian commented Oct 27, 2018
@thefourtheye I have addressed your comments. @devsnek@jdalton@Fishrock123 Can you please have a look? |
Fishrock123 left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting there... also needs some more tests. :)
I'd really like to see this make it into a release though!
lib/readline.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| this.previewResult=`\u001b[90m //${result}\u001b[39m`; | |
| this.previewResult=`\u001b[90m //${result}\u001b[39m`; |
lib/repl.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be necessary - can you instead add the function on the class but either prefix the function name with _ or, better, put it behind a Symbol? Something like kPreviewResults = new Symbol('Preview Results Fn'), and then you can do this[kPreviewResults]().
lib/repl.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need this wrapping function? Also, it's confusing, since there is a variable with the same name.
lib/repl.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure this is what you think it is?
It currently seems to be printing Objects as Arrays of values:
> process.versions{http_parser: '2.8.0', node: '12.0.0-pre', v8: '7.0.276.38-node.11', uv: '1.24.0', zlib: '1.2.11', ares: '1.15.0', modules: '67', nghttp2: '1.34.0', napi: '3', openssl: '1.1.0i', icu: '63.1', unicode: '11.0', cldr: '34.0', tz: '2018e' } > process.versions //[ '2.8.0', '12.0.0-pre', '7.0.276.38-node.11', '1.24.0', '1.2.11' ] lib/repl.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should avoid the eslint message:
| constpreviewData=previewResults.map((preview)=>preview.value);// eslint-disable-line max-len | |
| constpreviewData=previewResults.map( | |
| (preview)=>preview.value | |
| ); |
lib/repl.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean this?
| },()=>[]); | |
| },()=>{}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| constwrapWithColorCode=(str)=>`\u001b[90m //${str}\u001b[39m`; | |
| constwrapWithColorCode=(str)=>`\u001b[90m //${str}\u001b[39m`; |
antsmartian commented Nov 16, 2018
@Fishrock123 Thanks for your review, will update the thread once I'm done with your review comments. |
e48a315 to 0b0783fCompareantsmartian commented Nov 22, 2018
@Fishrock123 Addressed review comments. I guess few things I need do to:
|
319ea89 to 87b14fcCompareantsmartian commented Nov 28, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
@nodejs/repl PTAL.. Have added test cases and made changes requested by @Fishrock123 |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
antsmartian commented Jan 19, 2019
@BridgeAR will address your comments. |
antsmartian commented Apr 1, 2019
@nodejs/repl @Fishrock123@BridgeAR PTAL.. |
BridgeAR commented Apr 1, 2019
@antsmartian have you seen my comments? They still seem to apply? |
antsmartian commented Apr 2, 2019
@BridgeAR Yes, I have addressed the comments and also added check for color part in the prev commit, may be you can have a look now. Thanks! |
lib/readline.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The maximum color depth is 24. You can also use hasColors() instead of getColorDepth() as it's more intuitive to use.
lib/readline.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not identical to the color part (it does not only strip the colors).
lib/readline.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The length check includes the colors but that should ideally not be the case. Colors are not visible characters and should as such not be calculated towards the total length.
lib/readline.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This adds the color unconditionally. Can you also please elaborate what exactly this does? I am not sure I understand why this part is sliced and replaced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The slice and replace part is mainly for splitting the new lines. Since in output terminal has only limited columns, we need to split them and replace with empty space so that we can show them the content in single line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already use util.inspect() on the preview. We should use options that deactivate the colors for the preview and make sure the output is printed on a single line. That can be done with the compact options set to true in combination with breakLength set to Infinity and colors set to false.
I would then limit the preview only instead of limiting the input as well. Right now we unconditionally slice the input value and that doesn't seem right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BridgeAR: (sorry for a very late reply)
What you are saying is actually a good idea. But I was just trying to play with the options provided by you but still that doesn't seems to be atleast fixing the problem what we have now. For example, if the user types process, we get a long string, so if we apply the options like below:
util.inspect(process,{breakLength: Infinity, compact: true}) still we are getting results like below:
This actually breaks the cursor position as the output is huge. I feel, the only way for us to slice the string to the length of the tty column. May be is there any other way we could achieve it? 🤔
lib/readline.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be possible to add internal functionality in a separate file that would only be loaded internally. That way we do not have to pollute the prototype further. An underscore in a property name would not hinder anyone from using or monkey patching this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I will move them to internal/readline/util.
lib/repl.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
depth: Infinity does not sound like a good default to me. The preview should ideally be short and on the same line. This could cause the terminal to add lots of output.
lib/readline.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This adds colors unconditionally.
lib/readline.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally would keep the preview, even if no colors are supported. The comment should be indication enough.
If we do not want to have a preview in case the colors are deactivated, we should not start the eagerSession in the REPL. That way no code is run unnecessary.
And is it correct that this._prompt is necessary in one case but not in the other?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, I'm planning to send the output to this function and then use util.inspect within the function to customize our output. Do you think that would be a better approach? Because anyways I need to call util.inspect in my REPL session.
lib/readline.js Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already use util.inspect() on the preview. We should use options that deactivate the colors for the preview and make sure the output is printed on a single line. That can be done with the compact options set to true in combination with breakLength set to Infinity and colors set to false.
I would then limit the preview only instead of limiting the input as well. Right now we unconditionally slice the input value and that doesn't seem right.
lundibundi commented Nov 24, 2019
ping @antsmartian, will you be working on this further? |
antsmartian commented Nov 25, 2019
@lundibundi Yes. This is open for long time ( I know :( ), I wanted it to get closed. Will look at it this week. Will update the PR soon. |
163f7fd to 700c94eCompare
lundibundi left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 just a few nits and code refactoring suggestions.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
lib/repl.js Outdated
| // If no exception and we have objectId | ||
| // Run the expression via callFunctionOn | ||
| // And return it from util inspect. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
// If there was no exception and we've got an objectId// stringify it with `util.inspect` via Runtime.callFunctionOn.antsmartian commented Dec 3, 2019
@lundibundi @nodejs/repl PTAL.. 🔉 |
lundibundi left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly LGTM from me, but I'm not that familiar with repl code to put a ✔️. This will have to get approval from @BridgeAR or someone else from @nodejs/repl.
Great work, would love to see preview in the repl.
| returnreadline; | ||
| }; | ||
| const{ cursorTo, clearScreenDown }=lazyReadline(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 can we just const{cursorTo, clearScreenDown } = require('readline') at the top now?
| repl.output.write(s); | ||
| } | ||
| // Move back the cursor to the original position |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
| // Move back the cursor to the original position | |
| // Move back the cursor to the original position. |
| // Appends the preview of the result | ||
| // to the tty. | ||
| functionappendPreview(repl,result,cursorTo,clearScreenDown){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| functionappendPreview(repl,result,cursorTo,clearScreenDown){ | |
| functionappendPreview(repl,preview,cursorTo,clearScreenDown){ |
maybe? To make it a little clearer.
| // Appends the preview of the result | ||
| // to the tty. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I think this will fit on one line.
| // A hack to get the line refreshed if it's needed | ||
| this._moveCursor(0); | ||
| } | ||
| // Emit current line for generating preview |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
| // Emit current line for generating preview | |
| // Emit current line for generating preview. |
| return; | ||
| } | ||
| if(undefined!==previewResult.result.value){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
| if(undefined!==previewResult.result.value){ | |
| if(previewResult.result.value!==undefined){ |
| eagerSession.once('Runtime.executionContextCreated', | ||
| ({params: { context }})=>{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps to avoid big indentation:
eagerSession.once('Runtime.executionContextCreated',({params: { context }})=>{})| repl.output.write(line.length<columns ? | ||
| s : `${s.slice(0,columns-3) | ||
| .replace(/\r?\n|\r/g,'')}...\u001b[39m`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
repl.output.write(line.length<columns ? s : s.slice(0,columns-3).replace(/\r?\n|\r/g,'')+'...\u001b[39m');nodejs-github-bot commented Dec 3, 2019
BridgeAR commented Dec 9, 2019
This got superseded by #30811 |

Address the issue #20977
Well, I would say its "initial" checkins. May be work will be required for handling cursors, additionaledge cases (may be 🤔 ) etc, but I guess this should be a good starting point.Added code for handling cursors and also for line refresh, when necessary.
Thanks for your time on this.
make -j4 test(UNIX), orvcbuild test(Windows) passes