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

repl: remove internal frames from runtime errors #15351

Closed
wants to merge 6 commits into from
Closed

repl: remove internal frames from runtime errors #15351

wants to merge 6 commits into from

Conversation

lance
Copy link
Member

@lance lance commented Sep 12, 2017

When a user executes code in the REPLServer which generates an
exception, there is no need to display the REPLServer internal
stack frames.

Based on work by @princejwesley.

Should there be an option to display these stack frames for the purposes of Node.js core development, specifically on the REPL itself?

Ref: #9601

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

repl

@lance lance added the repl Issues and PRs related to the REPL subsystem. label Sep 12, 2017
@nodejs-github-bot nodejs-github-bot added the repl Issues and PRs related to the REPL subsystem. label Sep 12, 2017
Copy link
Member

@bnoordhuis bnoordhuis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an observation but the filtering approach in this PR is somewhat ad hoc.

If we are going to do more of this in the future, then perhaps we should revive parts of #2741: record script ids of builtin scripts and check stack frames against them.

v8::Exception::CreateMessage() (which that PR doesn't use) lets you do that for arbitrary exception objects.

lib/repl.js Outdated
if (err.stack) {
const regex = new RegExp(/\s+repl:/);
const stack = err.stack.split('\n');
const idx = stack.findIndex((frame) => regex.test(frame));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This filters only a single frame. Wouldn't it make more sense to do e.g.

err.stack = err.stack.split('\n').filter((s) => !/ repl:/.test(s)).join('\n');

Copy link
Member Author

@lance lance Sep 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This finds the index of repl: and on line 383 below, the stack is spliced from that point, so all frames after it are removed. If I am reading it correctly, I believe your suggestion would only eliminate lines that begin with repl:, but that's not all that we are looking for. Here is some before/after:

$ node --version
v8.4.0
$ node
> .load test/fixtures/repl-pretty-stack.js
> 'use strict';
'use strict'
> function a() {
...   b();
... }
undefined
> function b() {
...   c();
... }
undefined
> function c() {
...   throw new Error('Whoops!');
... }
undefined
> a();
Error: Whoops!
    at c (repl:2:9)
    at b (repl:2:3)
    at a (repl:2:3)
    at repl:1:1
    at ContextifyScript.Script.runInThisContext (vm.js:44:33)
    at REPLServer.defaultEval (repl.js:239:29)
    at bound (domain.js:301:14)
    at REPLServer.runBound [as eval] (domain.js:314:12)
    at REPLServer.onLine (repl.js:440:10)
    at emitOne (events.js:120:20)
>
$ ./node --version
v9.0.0-pre
$ ./node
> .load test/fixtures/repl-pretty-stack.js
'use strict';
function a() {
  b();
  }
  function b() {
    c();
    }
    function c() {
      throw new Error('Whoops!');
      }
      a();

Error: Whoops!
    at c (repl:9:13)
    at b (repl:6:5)
    at a (repl:3:3)
>

As you can see, it takes care of stack frames including REPLServer, ContextifyScript, etc.

lib/repl.js Outdated
@@ -374,6 +374,17 @@ function REPLServer(prompt,
};
}

function prettifyStackTrace(err) {
if (err.stack) {
const regex = new RegExp(/\s+repl:/);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe new RegExp is unnecessary in recent ES versions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had originally written this inline below as

const idx = stack.findIndex((frame) => /\s+repl:/.test(frame));

Which worked as expected. It just wreaked havoc on my syntax highlighting. 😜 I guess that's not the best reason to use new. But it's all I've got.

lib/repl.js Outdated
@@ -209,9 +209,9 @@ function REPLServer(prompt,
// preserve original error for wrapped command
const error = wrappedErr || e;
if (isRecoverableError(error, code))
err = new Recoverable(error);
err = prettifyStackTrace(new Recoverable(error));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use Error.captureStackTrace()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question. I guess I was just going with something similar to what @princejwesley did in #9601. But perhaps that's not the best approach. I'll try an impl with Error.captureStackTrace() and push it for review.

@lance
Copy link
Member Author

lance commented Sep 12, 2017

@jasnell updated using Error.prepareStackTrace().

@bnoordhuis this change might address some of your concerns, since I'm no longer just parsing text but looking at frame.getFunctionName(). Still, I think this is a little problematic, since all I'm really doing is looking for a null function name starting from the bottom of the stack. This is the frame in which vm.runInContext() executes the user code within the body of REPLServer.defaultEval().

The fragility here is that this breaks if internals change and an anonymous function sneaks in between the time defaultEval() is called and when vm.runIn[This]Context() is called with the user code. I couldn't work out a better way to do it. I tried wrapping the user code in a __replInternalEval() function that I could use to split the stack, but that broke a lot of other tests across the board.

I like the idea of script ids for builtins. It would almost certainly make this implementation a little cleaner.

lib/repl.js Outdated
@@ -374,6 +374,18 @@ function REPLServer(prompt,
};
}

Error.prepareStackTrace = function prepareStackTrace(error, structuredStack) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm... I do not think it is a good idea to be extending Error in this way. Why is the existing Error.captureStackTrace() not adequate?

Copy link
Member Author

@lance lance Sep 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jasnell Error.captureStackTrace() captures the stack at the point where it is called. This would rarely be the stack a user is looking for, since that call would happen in the internals of REPLServer, after a call to vm.runInContext(). I think since it would be after the failed completion of an asynchronous execution, the user stack would be gone.

If I understand the v8 Error API documentation, Error.prepareStackTrace() is the recommended way to accomplish what I am trying to do.

Edit to add the relevant supporting doc

If you assign a different function value to Error.prepareStackTrace that function will be used to format stack traces. It will be passed the error object that it is preparing a stack trace for and a structured representation of the stack. User stack trace formatters are free to format the stack trace however they want and even return non-string values. It is safe to retain references to the structured stack trace object after a call to prepareStackTrace completes so that it is also a valid return value. Note that the custom prepareStackTrace function is only called once the stack property of Error object is accessed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Lemme stew on this a bit more then :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I too had the feeling that doing this is somewhat wrong but by thinking about it further I agree with @lance that this is probably the right thing to do for the repl.

Copy link
Contributor

@princejwesley princejwesley Sep 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lance User may override Error.prepareStackTrace in their code.
I suggest something like 👇

const prepareStackTrace = fn => (error, frames) => { 
	// trim stack frames...
	let trimmedFrames = frames;
	if (fn) {
		// pass trimmed stack frame
                error.stack = <<trimmed stack string>>
		return fn(error, trimmedFrames);
	}

	return trimmedFrames;
};

self.outputStream._write = self.outputStream.write;
self.outputStream.write = (d) => {
	let pstrace = Error.prepareStackTrace;
	Error.prepareStackTrace = prepareStackTrace(pstrace);
	self.outputStream._write(d);
	Error.prepareStackTrace = pstrace;
};

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@princejwesley I thought about that as well but that can be seen as a advantage and as a disadvantage at the same time. Some users might want to know where the repl lines come from (probably only node-core and we could work around it but it is still something to consider). Therefore I did not complain about that.
So do we really want to prevent the user from being able to override the function? If he does that in the first place, the user can also filter the internal lines if he cares to do so.

Copy link
Contributor

@princejwesley princejwesley Sep 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BridgeAR
May be setting process.stdout.write = process.stdout._write would disable the trimming feature(because we are binding the original function(outputstream.write) to same outputstream object instead of keeping it local to context).

Adding comment is sufficient, right?
Advantages:

  • User's choice(like formatting) is preserved.
  • repl stack is not leaked.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BridgeAR we are not preventing user's printStackTrace function, Just decorating it with our printStackTrace which will trim the stack frames and pass it to user defined printStackTrace.

Copy link
Member Author

@lance lance Sep 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@princejwesley @BridgeAR I am a little conflicted about this, and the example here confuses me a little. What happens when self.outputStream._write(d); throws? Wouldn't Error.prepareStackTrace never get restored?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lance wrap it with try/finally block. if self.outputstream._write(d) throws error, we can't use repl at all.

Copy link
Member

@BridgeAR BridgeAR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small nits but otherwise LGTM. I can not think of a better way.

@@ -71,7 +71,7 @@ function clean_up() {
function strict_mode_error_test() {
send_expect([
{ client: client_unix, send: 'ref = 1',
expect: /^ReferenceError:\sref\sis\snot\sdefined\n\s+at\srepl:1:5/ },
expect: /^ReferenceError:\sref\sis\snot\sdefined\n/ },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the new end of the error? If yes, we might mark that in the RegExp and if not, I would just replace it with the new at.


SyntaxError: Unexpected identifier

`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a huge fan of the multi line template string and would rather see \n

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I disagree. Template strings, to my mind, tend to make the test example easier to scan/read quickly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know this was mainly discouraged so far and the code does not have any multi line template strings. I think it is more difficult to see whitespace with this. I do not want to block the PR with this comment though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm definitely not a fan of multi-line template strings and we've avoided them consistently in the past. It's definitely something that we can revisit. Ping @nodejs/tsc ... any feelings on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's possible to align the first line with the others (maybe with a tagged literal that removes the first line terminator), then I'm +1.

@BridgeAR
Copy link
Member

Should this be semver-major though?

@jasnell jasnell added the semver-major PRs that contain breaking changes and should be released in the next major version. label Sep 20, 2017
@jasnell
Copy link
Member

jasnell commented Sep 20, 2017

will mark as major just to be safe. Ping @nodejs/tsc

@lance
Copy link
Member Author

lance commented Sep 27, 2017

@princejwesley @BridgeAR PTAL - updated with a function similar to that suggested. Setting Error.prepareStackTrace just before write as suggested won't work, because by then the stack has already been accessed and it's only ever formatted once. I think interception on the 'error' event probably makes more sense here.

@BridgeAR I can take a look at template strings tomorrow. I'll defer to common wisdom, though I do still stand by my assertion that it's more readable, specifically for test output.

return fn(error, frames);
}
frames.push(error);
return frames.reverse().join('\n at ');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lance return frames.reverse() is sufficient?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@princejwesley Error.prepareStacktrace() is used to format the stack trace. It’s not required to return a string, but that is the behavior of the default implementation, and I think it would be unexpected if users suddenly started getting an array from the Error.stack property.

.replace(/^repl:\d+\r?\n/, '')
.replace(/^\s+at\s.*\n?/gm, '');
.replace(/^repl:\d+\r?\n/, '')
.replace(/^\s+at\s.*\n?/gm, '');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still necessary with the prepareStackTrace function in place? And if yes, cant we just move that part in the prepareStackTrace function as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can poke around on it more - the change in formatting is because that's what I was doing and missed noticing that on my local diff. It's tricky because of the way Error.prepareStackTrace() works. It's only ever called once for a given error, and the return value is by default (and typically in custom impls as well) a string. Because of the way errors are handled in the repl and domain, in the case of a SyntaxError specifically, it's a string before we have an opportunity to filter the stack frames in prepareStackTrace(). So I left it rather than rework more of the overall error handling.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BridgeAR I spent the morning looking into removing this and dealing with it in Error.prepareStackTrace() but the ramifications were wide reaching, especially with regard to how we handle SyntaxError as a Recoverable object so that defaulting into editor mode on multi-line input works as expected. I do think there could be some consolidation and overall improvement of the error handling, but I don't think this is the PR to do that in.

Copy link
Member

@BridgeAR BridgeAR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still LGTM. I do not mind the template string that badly if you feel strongly about it, go ahead.

@lance lance requested a review from a team September 29, 2017 17:57
@lance
Copy link
Member Author

lance commented Sep 29, 2017

Multi-line template strings have been removed, and I think I have addressed all other issues. As semver-major we will need more reviews on this for it to land. /cc @nodejs/tsc

@lance
Copy link
Member Author

lance commented Sep 29, 2017

CI: https://ci.nodejs.org/job/node-test-pull-request/10337/

Edit: CI failures appear to be unrelated

Copy link
Member

@jasnell jasnell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with green CI

@lance
Copy link
Member Author

lance commented Oct 2, 2017

@lance
Copy link
Member Author

lance commented Oct 4, 2017

Do we need another @nodejs/tsc LGTM for this to land?

@lance
Copy link
Member Author

lance commented Oct 9, 2017

Pretty sure CI 2 was green, but didn't comment on it here. Just to be safe, running CI 3.

https://ci.nodejs.org/job/node-test-pull-request/10555/

EDIT
All good except one unrelated failure.

1,pi3-raspbian-jessie
FATAL: remote file operation failed: /home/iojs/build/workspace/node-test-binary-arm@tmp/secretFiles/2eb224a6-31a9-45bd-9b95-2d7b70d88a69 at hudson.remoting.Channel@44c3e069:JNLP4-connect connection from static-n49-176-213-208.sbr2.nsw.optusnet.com.au/49.176.213.208:48902: java.io.IOException: Unable to delete '/home/iojs/build/workspace/node-test-binary-arm@tmp/secretFiles/2eb224a6-31a9-45bd-9b95-2d7b70d88a69/.nfs000000000029f98f00000022'. Tried 3 times (of a maximum of 3) waiting 0.1 sec between attempts.
java.nio.file.FileSystemException: /home/iojs/build/workspace/node-test-binary-arm@tmp/secretFiles/2eb224a6-31a9-45bd-9b95-2d7b70d88a69/.nfs000000000029f98f00000022: Device or resource busy
	at sun.nio.fs.UnixException.translateToIOException(UnixException.java:91)
	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
	at sun.nio.fs.UnixFileSystemProvider.implDelete(UnixFileSystemProvider.java:244)
	at sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(AbstractFileSystemProvider.java:108)
	at java.nio.file.Files.deleteIfExists(Files.java:1165)
	at hudson.Util.tryOnceDeleteFile(Util.java:287)
	at hudson.Util.deleteFile(Util.java:243)
	at hudson.FilePath.deleteRecursive(FilePath.java:1209)
	at hudson.FilePath.deleteContentsRecursive(FilePath.java:1218)
	at hudson.FilePath.deleteRecursive(FilePath.java:1200)
	at hudson.FilePath.access$1000(FilePath.java:195)
	at hudson.FilePath$14.invoke(FilePath.java:1179)
	at hudson.FilePath$14.invoke(FilePath.java:1176)
	at hudson.FilePath$FileCallableWrapper.call(FilePath.java:2731)
	at hudson.remoting.UserRequest.perform(UserRequest.java:153)
	at hudson.remoting.UserRequest.perform(UserRequest.java:50)
	at hudson.remoting.Request$2.run(Request.java:336)
	at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:68)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at hudson.remoting.Engine$1$1.run(Engine.java:94)
	at java.lang.Thread.run(Thread.java:745)
Caused: java.io.IOException: Unable to delete '/home/iojs/build/workspace/node-test-binary-arm@tmp/secretFiles/2eb224a6-31a9-45bd-9b95-2d7b70d88a69/.nfs000000000029f98f00000022'. Tried 3 times (of a maximum of 3) waiting 0.1 sec between attempts.
	at hudson.Util.deleteFile(Util.java:248)
	at hudson.FilePath.deleteRecursive(FilePath.java:1209)
	at hudson.FilePath.deleteContentsRecursive(FilePath.java:1218)
	at hudson.FilePath.deleteRecursive(FilePath.java:1200)
	at hudson.FilePath.access$1000(FilePath.java:195)
	at hudson.FilePath$14.invoke(FilePath.java:1179)
	at hudson.FilePath$14.invoke(FilePath.java:1176)
	at hudson.FilePath$FileCallableWrapper.call(FilePath.java:2731)
	at hudson.remoting.UserRequest.perform(UserRequest.java:153)
	at hudson.remoting.UserRequest.perform(UserRequest.java:50)
	at hudson.remoting.Request$2.run(Request.java:336)
	at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:68)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at hudson.remoting.Engine$1$1.run(Engine.java:94)
	at java.lang.Thread.run(Thread.java:745)
	at ......remote call to JNLP4-connect connection from static-n49-176-213-208.sbr2.nsw.optusnet.com.au/49.176.213.208:48902(Native Method)
	at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1545)
	at hudson.remoting.UserResponse.retrieve(UserRequest.java:253)
	at hudson.remoting.Channel.call(Channel.java:830)
	at hudson.FilePath.act(FilePath.java:985)
Caused: java.io.IOException: remote file operation failed: /home/iojs/build/workspace/node-test-binary-arm@tmp/secretFiles/2eb224a6-31a9-45bd-9b95-2d7b70d88a69 at hudson.remoting.Channel@44c3e069:JNLP4-connect connection from static-n49-176-213-208.sbr2.nsw.optusnet.com.au/49.176.213.208:48902
	at hudson.FilePath.act(FilePath.java:992)
	at hudson.FilePath.act(FilePath.java:974)
	at hudson.FilePath.deleteRecursive(FilePath.java:1176)
	at org.jenkinsci.plugins.credentialsbinding.impl.UnbindableDir$UnbinderImpl.unbind(UnbindableDir.java:84)
	at org.jenkinsci.plugins.credentialsbinding.impl.SecretBuildWrapper$1.tearDown(SecretBuildWrapper.java:113)
	at hudson.model.Build$BuildExecution.doRun(Build.java:174)
	at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:534)
	at hudson.model.Run.execute(Run.java:1728)
	at hudson.matrix.MatrixRun.run(MatrixRun.java:146)
	at hudson.model.ResourceController.execute(ResourceController.java:98)
	at hudson.model.Executor.run(Executor.java:405)

@lance lance self-assigned this Oct 9, 2017
@lance
Copy link
Member Author

lance commented Oct 10, 2017

@jasnell I'd like to land this if possible. Since it's semver-major it needs another @nodejs/tsc approval.

For the record, I'm questioning what makes this a major version bump. What is the scenario where users would be impacted? The only thing I can think of is if the repl module is used programmatically and somewhere in the code there is error handling that is doing manual parsing of a stack trace to achieve some outcome (e.g. report only the relevant information) from the error. Surely that's pretty unlikely don't you think? And in any case, the REPLServer's internal stack frames and structure aren't documented anywhere, and almost certainly changed over time with other non-major releases.

@BridgeAR
Copy link
Member

I am fine to not have it as semver-major. I just thought it would be good to have some other opinions about it. Too bad there was no response from the @nodejs/tsc about that.
I remove it again as I was the person who brought it up in the first place.

@BridgeAR BridgeAR removed the semver-major PRs that contain breaking changes and should be released in the next major version. label Oct 10, 2017
@targos
Copy link
Member

targos commented Oct 10, 2017

I don't think this needs to be semver-major

@Fishrock123
Copy link
Contributor

I'm not certain if any behavior within a repl context can truly be considered semver-major.

@jasnell
Copy link
Member

jasnell commented Oct 10, 2017

I'm good with semver-patch

@lance
Copy link
Member Author

lance commented Oct 10, 2017

Thanks all for the feedback. I will land this in the next day or so modulo work stuff.

@lance
Copy link
Member Author

lance commented Oct 11, 2017

Landed in c5f54b1

@lance lance closed this Oct 11, 2017
lance added a commit that referenced this pull request Oct 11, 2017
When a user executes code in the REPLServer which generates an
exception, there is no need to display the REPLServer internal
stack frames.

PR-URL: #15351
Reviewed-By: Prince John Wesley <princejohnwesley@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>

Refs: #9601
addaleax pushed a commit to addaleax/ayo that referenced this pull request Oct 12, 2017
When a user executes code in the REPLServer which generates an
exception, there is no need to display the REPLServer internal
stack frames.

PR-URL: nodejs/node#15351
Reviewed-By: Prince John Wesley <princejohnwesley@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>

Refs: nodejs/node#9601
@MylesBorins
Copy link
Contributor

This does not land cleanly on v8.x, would someone be willing to backport?

@lance
Copy link
Member Author

lance commented Oct 24, 2017

@MylesBorins I will take care of it.

Edit: PR submitted

@MylesBorins
Copy link
Contributor

Should this be backported to v6.x-staging? If yes please follow the guide and raise a backport PR, if not let me know or add the dont-land-on label.

@lance
Copy link
Member Author

lance commented Nov 16, 2017

@MylesBorins what determines if it should be backported. The backporting guide doesn't give much in the way of guidelines. I'm happy to do it if it should.

gibfahn pushed a commit that referenced this pull request Dec 20, 2017
When a user executes code in the REPLServer which generates an
exception, there is no need to display the REPLServer internal
stack frames.

PR-URL: #15351
Backport-PR-URL: #16457
Reviewed-By: Prince John Wesley <princejohnwesley@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>

Refs: #9601
@gibfahn gibfahn mentioned this pull request Dec 20, 2017
@lance
Copy link
Member Author

lance commented May 3, 2018

@gibfahn @MylesBorins I waited too long and v6.x is in LTS maintenance mode. This, and the fact that the v8 Error API was different enough in 5.1.281 that it makes the backport non-trivial.

The link to the V8 wiki does not adequately describe the behavior I am seeing in my attempts to backport, but it appears that the custom stack formatter is only called if Error.captureStackTrace is also called. I believe it is related to this change to eager capture of the stack.

I am going to remove the backport-requested-v6.x label and add dont-land-on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
repl Issues and PRs related to the REPL subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants