-
Notifications
You must be signed in to change notification settings - Fork 30.2k
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
console.log
never finishes on Proxy with getPrototypeOf
pointing to itself
#26231
Comments
That is probably working as expected. Object having itself as prototype usually doesn't make sense and handling it as a special case may not be worth it. Note that there is |
Reduced test case: const util = require('util');
const p = new Proxy({}, {
getPrototypeOf() {
return p;
}
});
util.inspect(p); I'd expect |
The cause is this loop which does not take care of the case when node/lib/internal/util/inspect.js Lines 334 to 345 in e51da1f
|
V8 has the advantage of not triggering the proxy handlers when inspecting the proxy. That is the reason why it works there but not with |
@joyeecheung that would not be sufficient. If we handle that case there, it would cause a maximum call stack size error instead. |
I don't think we should fix this. The only real way to fix proxy inspection is to use some internal V8 magic which does not trigger the proxy handlers. |
Funny enough, adding a memo in the loop reveals another bug(?): const p = new Proxy({}, {
getPrototypeOf() {
return p;
}
});
p instanceof Error; // RangeError: Maximum call stack size exceeded |
Taking care of that case is not enough, as proxy can have cyclic prototype with length more than 1 ( |
Upstream bug in https://bugs.chromium.org/p/v8/issues/detail?id=8884 for #26231 (comment)
Why are we attempting to display the proxy itself instead of doing |
I looked into this a bit last night and found the same issues. The following diff seemed to solve the infinite looping: diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js
index 5246ed89b7..66c7194d1c 100644
--- a/lib/internal/util/inspect.js
+++ b/lib/internal/util/inspect.js
@@ -330,8 +330,9 @@ function getEmptyFormatArray() {
}
function getConstructorName(obj, ctx) {
+ const localSeen = [];
let firstProto;
- while (obj) {
+ while (localSeen.indexOf(obj) === -1) {
const descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor');
if (descriptor !== undefined &&
typeof descriptor.value === 'function' &&
@@ -339,6 +340,7 @@ function getConstructorName(obj, ctx) {
return descriptor.value.name;
}
+ localSeen.push(obj);
obj = Object.getPrototypeOf(obj);
if (firstProto === undefined) {
firstProto = obj;
@@ -349,10 +351,14 @@ function getConstructorName(obj, ctx) {
return null;
}
- return `<${inspect(firstProto, {
+ ctx.seen.push(firstProto);
+ const result = `<${inspect(firstProto, {
...ctx,
customInspect: false
})}>`;
+ ctx.seen.pop();
+
+ return result;
}
function getPrefix(constructor, tag, fallback) { Unfortunately, we call |
I actually found a way to completely resolve all our proxy issues without changing the behavior (no trap is called anymore). The main problem I have with this is just that it does a C++ call on each object. I'll open a PR for it and see what others think about it.
There are different opinions about proxies in general. We even got complains that the repl sets |
I'm a fan of using a |
I opened #26241 to fix general proxy inspection. |
This prevents any proxy traps from being called while inspecting proxy objects. That guarantees a side-effect free way of inspecting proxies. Refs: nodejs#25212 Refs: nodejs#24765 Fixes: nodejs#10731 Fixes: nodejs#26231
Version:
v11.10.0
Platform:
Darwin (MacOS High Sierra)
(This is a pretty rare case: I encountered this when I was playing around with Proxy to build a dummy that always silently do nothing on any function call/value assignment given any name)
Example:
console.log(p)
never finishes running given the following code (potentially in an infinite loop):In comparison, on Chrome 71
console.log
would immediately finishes with outputThe text was updated successfully, but these errors were encountered: