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

fix(core): Log customInspect implementation errors #9095

Merged
merged 5 commits into from
Jan 14, 2021

Conversation

Soremwar
Copy link
Contributor

@Soremwar Soremwar commented Jan 11, 2021

Right now, the customInspect function in core swallows all errors that are thrown in user defined inspection functions. I don't think there is a reason for this behavior to be inforced (in my particular use case this is swallowing Permission errors).

With this PR, a warning will be appended to the inspected item showing the error thrown in the the inspect function

@nayeemrmn
Copy link
Collaborator

nayeemrmn commented Jan 12, 2021

This was introduced in #3226. It can be troublesome if a broken customInspect prevents logging the object or any object that contains it. Instead, the string should indicate that it threw:

> console.log(headers);
[Custom inspect: Error: message] Headers {}

Logging should be throw-safe.

@Soremwar
Copy link
Contributor Author

Soremwar commented Jan 12, 2021

> ReadableStream.prototype
[Custom inspect: TypeError: Invalid ReadableStream.]
ReadableStream {
  [Symbol(Deno.customInspect)]: [Function: [Deno.customInspect]],
  [Symbol(Symbol.asyncIterator)]: [Function: [Symbol.asyncIterator]]
}

Is this a desirable output?

@nayeemrmn
Copy link
Collaborator

I'd omit the line break before the fallback output, it looks better for a nested property.

@Soremwar
Copy link
Contributor Author

Hmm I discovered something interesting while messing around with this.

Turns out you can skip the inspect error pass by defining Deno.customInspect with a getter

Is this desired behavior based on what we just discussed?

const x = {}

Object.defineProperty(x, Deno.customInspect, {
  enumerable: false,
  configurable: false,
  get: function(){
    return Deno.env.toObject();
  }
})

console.log(x)

@nayeemrmn

This comment has been minimized.

@Soremwar
Copy link
Contributor Author

Mmm gotcha. I didn't know you could assign something other than a function to customInspect. This might cover my use case after all

@ghost

This comment has been minimized.

@Soremwar
Copy link
Contributor Author

Doesn't look so great on variables. I think I'm gonna leave the line break there

[Custom inspect: PermissionDenied: access to environment variables, run again with the --allow-env flag] [Function: x]

@Soremwar
Copy link
Contributor Author

Soremwar commented Jan 12, 2021

@00ff0000red You are right. However it can be polyfilled easily with Symbol.for("Deno.customInspect") instead of Deno.customInspect, so any Deno bundler like Bundler can make this code usable just as well in any environment

@ghost
Copy link

ghost commented Jan 12, 2021

Actually, what I said was irrelevant anyway, since, in a browser, you wouldn't exactly have Deno.customInspect in the first place.

@Soremwar Soremwar changed the title fix(core): Remove passes for customInspect fix(core): Log customInspect errors Jan 13, 2021
@Soremwar Soremwar changed the title fix(core): Log customInspect errors fix(core): Log customInspect implementation errors Jan 13, 2021
@Soremwar
Copy link
Contributor Author

Ready for review

@ry
Copy link
Member

ry commented Jan 14, 2021

What's the behavior in Node for this?

It seems like we should just throw the exception rather than trying to log it. I agree silently swallowing the error is not great. But why try to catch it at all?

@caspervonb
Copy link
Contributor

caspervonb commented Jan 14, 2021

Node throws

const util = require("util");

const foo = {
  [util.inspect.custom]() {
      console.log("before");
      throw new Error("error");
      console.log("after");
   },
 };
 
util.inspect(foo);
console.log("done");
before
/home/caspervonb/test.js:6
    throw new Error("error");
    ^

Error: error
    at Object.[nodejs.util.inspect.custom] (/home/caspervonb/test.js:6:11)
    at formatValue (node:internal/util/inspect:735:19)
    at Object.inspect (node:internal/util/inspect:309:10)
    at Object.<anonymous> (/home/caspervonb/test.js:11:6)
    at Module._compile (node:internal/modules/cjs/loader:1108:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
    at Module.load (node:internal/modules/cjs/loader:973:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
    at node:internal/main/run_main_module:17:47

I don't get why we'd do anything special here at all really.
I'd prefer to let this fail loud and clear.

@Soremwar
Copy link
Contributor Author

Soremwar commented Jan 14, 2021

Yeah I'm not crazy about this swallowing errors either (customInspect is an user implementation after all, it's not out of their control to fix the error).

I'll revert to the original commit and look for customInspect implementations in Deno code that require manual error handling (like Headers)

@Soremwar
Copy link
Contributor Author

I'll look for customInspect implementations in Deno code that require manual error handling (like Headers)

On second though since errors like trying to read ReadableStream.prototype are really debug only there is no reason to change this implementations.

@nayeemrmn
Copy link
Collaborator

It surprises me that Node throws for this, because it doesn't when evaluating getters with getters: true. I don't see what the difference would be. I agree with @kevinkassimo's original PR to make logging (as an exception) throw safe.

Copy link
Member

@ry ry left a comment

Choose a reason for hiding this comment

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

LGTM - this is more explicit, easier to debug. Thanks @Soremwar

@ry ry merged commit 2d12085 into denoland:master Jan 14, 2021
@Soremwar Soremwar deleted the inspect_fix branch April 19, 2021 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants