Reputation: 3814
here is a program I made called example.js
const e = {
test: 'test',
};
console.log('object', e);
console.log('stack', e.stack);
console.log('now add stack trace info');
Error.captureStackTrace(e);
console.log('object', e);
console.log('stack', e.stack);
and when I run it, this is what I get:
pi@raspberrypi:~ $ node example.js
object { test: 'test' }
stack undefined
now add stack trace info
object { test: 'test' }
stack Error
at Object.<anonymous> (/home/pi/example.js:10:7)
at Module._compile (internal/modules/cjs/loader.js:1137:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
at Module.load (internal/modules/cjs/loader.js:985:32)
at Function.Module._load (internal/modules/cjs/loader.js:878:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
pi@raspberrypi:~ $ node --version
v12.18.3
so the stack
property is added, and I can print it out individually, but it is hidden when I print the whole object.
When I console.log(JSON.stringify(e));
, the stack
field is still not visible.
How does that work? Where is that field hidden?
Upvotes: 1
Views: 1959
Reputation: 16875
The stack
property is set to be non-enumerable and so doesn't show up when the object's properties are enumerated as is done when using JSON.stringify
.
Object properties consist of a number of descriptors that control their value and how the system interacts with them. These include:
configurable
true
if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object. Defaults tofalse
.
enumerable
true
if and only if this property shows up during enumeration of the properties on the corresponding object. Defaults tofalse
.
writable
true
if the value associated with the property may be changed with an assignment operator. Defaults tofalse
.
value
- The value associated with the property. Can be any valid JavaScript value (number, object, function, etc). Defaults to
undefined
.
(There are also get
and set
as well as some configuration and behavioral rules but they're not important here. If you're interested, this is described on MDN under Object.defineProperty()
.)
Let's assume you have an object and you then assign to a previously non-existent property on that object:
const someObject = {};
someObject.someProperty = 'someValue';
This is similar to:
const someObject = {};
Object.defineProperty(someObject, 'someProperty', {
configurable: true,
enumerable: true,
writable: true,
value: 'someValue',
});
When Error.captureStackTrace
creates or updates the stack
property on an object, it sets that property's enumerable
descriptor to false
. Because of this, JSON.stringify
doesn't see the property when it enumerates over the object's properties.
After calling Error.captureStackTrace
, update the stack
property's descriptors using Object.defineProperty
, as in:
Object.defineProperty(e, 'stack', { enumerable: true });
This will cause the property to be enumerable so that JSON.stringify
can see it.
Upvotes: 4