Object not found in heapdump comparison - javascript

I've installed heapdump nodejs module in order to dump the heap object.
Using this code (nodejs6.9.1),
'use strict'
const heapdump = require('heapdump')
heapdump.writeSnapshot()
const obj = {
test: 2,
foo: 6.4,
wow: true,
a: { }
}
heapdump.writeSnapshot()
console.log(obj) // <-- make sure obj lives until here
I've printed two heap dumps.
Importing both of them into chrome dev tools and switching to the comparison mode, I'm aspecting to see the obj object at least (with some other values).
Instead, I see only those values:
(compiled code)
(array)
(system)
(concatenated
(string)
Why?
EDIT:
moving the code into a setTimeout, the dump diff shows the two Objects correctly
setTimeout(() => {
heapdump.writeSnapshot()
const obj = {
test: 2,
foo: 6.4,
wow: true,
a: { }
}
heapdump.writeSnapshot()
console.log(obj)
}, 1000)
NB: test and foo property is not in dump diff.

This code illustrates my comment for this question
heapdump.writeSnapshot()
const obj = {
test: 2,
foo: 6.4,
wow: true,
a: { }
}
heapdump.writeSnapshot(function(err, filename) { // this is the callback
console.log(obj);
})

Related

Compare response in jest unit test case

I'm new to jest unit test case scenario, I have a scenario where in the response from the service that I called is of the below format
Artifact {
name: 'detection-v1.zip',
file_path: 'artifact\\bn-ds-anomalydetection-v1.zip',
is_tenant: false,
metadata: [
Registerfact {
name: 'ad',
_meta: [Object],
line_meta: [Object]
},
Registerfact {
name: 'ad-generic',
_meta: [Object],
line_meta: [Object]
}
]
}
how can i compare the above response in the jest service , I was trying to create a object but the Artifact name before the object is confusing how should i proceed
The test case is
test('test processArtifact method', async()=>{
const mockGetRestClient = jest.fn();
try{
const response = await factService.processfact(artifact)
console.log("response---",response)
// expect(response).toEqual()
}
catch(e){ }
})
I know its silly question ,but i'm confused hence posted it.
How should i create the static object to be put in .toEqual() ?
You can declare a global/static var with your response object on top of file. Or better declare it in some constants file and import here.
For Comparison:
Usually, if you have a simple object, you can use JSON.stringify. However, it may give error due to different order of object keys.
You should use assert for the deep comparison. There is method assert.deepEqual() which does deep comparison of objects.
an example for using assert from official docs
import assert from 'node:assert';
const obj1 = {
a: {
b: 1
}
};
const obj2 = {
a: {
b: 2
}
};
const obj3 = {
a: {
b: 1
}
};
const obj4 = Object.create(obj1);
assert.deepEqual(obj1, obj1);
// OK
// Values of b are different:
assert.deepEqual(obj1, obj2);
// AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } }
assert.deepEqual(obj1, obj3);
// OK
// Prototypes are ignored:
assert.deepEqual(obj1, obj4);
// AssertionError: { a: { b: 1 } } deepEqual {}
Hope this helps, let me know if you have any questions.
You can use JSON.stringify in order to convert your object into a string and then compare this result to the one you expect.
console.log(JSON.stringify({
name: 'detection-v1.zip',
file_path: 'artifact\\bn-ds-anomalydetection-v1.zip',
is_tenant: false,
metadata: [
{Registerfact: {
name: 'ad',
_meta: {},
line_meta: {}
}},
{Registerfact: {
name: 'ad-generic',
_meta: {},
line_meta: {}
}}
]
}));

New object created with the help of spread operator behaving like it is a deep copy, even though it has a nested object

Image of the code
So i created a new object from one object using spread operator and used another object to modify is property values.
But i am not sure, why it behaves as it is a deep copy instead of a shallow copy.
Cause as much as i remember, the way that i have done it, it should create shallow copy only in javascript (Node 12 or 14 version).
const modifier = {
policyName: "Asa1",
test: {
a: "As1",
bc : [
{
a: 1
}
]
}
}
const memberDetails = {
policyName: 'policyName',
test: {
a: "As",
bc : [
{
a: 0
}
]
}
};
const generatedMemberDetails = {...memberDetails, ...modifier};
generatedMemberDetails.test.a = "newAs";
generatedMemberDetails.test.bc[0].a = "new0";
console.log(JSON.stringify(memberDetails) );
console.log(JSON.stringify(generatedMemberDetails));
Output:
{"policyName":"policyName","test":{"a":"As","bc":[{"a":0}]}}
{"policyName":"Asa1","test":{"a":"newAs","bc":[{"a":"new0"}]}}

spread operator issues with property accessors (getters)

I'm having a hard time understanding why there are some issues with the following code https://jsfiddle.net/q4w6e3n3/3/
Note: All examples are tested in chrome version 52.0.2743.116 just in case this helps
const model = {
someVal: 'some val',
};
const obs = {
...model,
get accessor() {
return this.someVal;
},
}
// Expected: '>>> some val'
// Actual: '>>> undefined'
console.log('>>>', obs.accessor);
But the following similar snippet works https://jsfiddle.net/q4w6e3n3/5/
const model = {
someVal: 'some val',
};
const obs = {
get accessor() {
return this.someVal;
},
...model,
}
// Expected: '>>> some val'
// Actual: '>>> some val'
console.log('>>>', obs.accessor);
using the babel REPL I was able to see that Object.assign is used if available in the transpiled code
When I used it directly instead of the object spread I get the same issue, and also works if put the model
variable to the end instead of at the beginning.
Is this a bug? or is it intended behavior?
Also why does the following snippet work as well?:
const model = {
someVal: 'some val',
};
const obs = {
someVal: model.someVal,
get accessor() {
return this.someVal;
},
}
// Expected: '>>> some val'
// Actual: '>>> some val'
console.log('>>>', obs.accessor);
https://jsfiddle.net/q4w6e3n3/6/
I would expect it to have the same issues but works as a charm are getters this keyword somehow bound to the object they were added to?
Object.assign won't copy accessors. So when your splat is before your getter babel and its various voodoos uses Object.assign and the accessor isn't copied onto the first object from the second, well kind of, voodoo again. When your splat is after the getter, then it assigns the splatted properties onto the object with the getter, and the getter is preserved.
See here: MDN - Object.assign
Relevant code excerpt:
**Copying Accessors**
var obj = {
foo: 1,
get bar() {
return 2;
}
};
var copy = Object.assign({}, obj);
console.log(copy);
// { foo: 1, bar: 2 }, the value of copy.bar is obj.bar's getter's return value.
// This is an assign function that copies full descriptors
function completeAssign(target, ...sources) {
sources.forEach(source => {
let descriptors = Object.keys(source).reduce((descriptors, key) => {
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
return descriptors;
}, {});
// by default, Object.assign copies enumerable Symbols too
Object.getOwnPropertySymbols(source).forEach(sym => {
let descriptor = Object.getOwnPropertyDescriptor(source, sym);
if (descriptor.enumerable) {
descriptors[sym] = descriptor;
}
});
Object.defineProperties(target, descriptors);
});
return target;
}
var copy = completeAssign({}, obj);
console.log(copy);
// { foo:1, get bar() { return 2 } }

Javascript compare objects having functions using lodash isEqual

how to compare two objects for equality if they have functions? lodash's isEqual works really well until functions are thrown in:
_.isEqual({
a: 1,
b: 2
}, {
b: 2,
a: 1
});
// -> true
_.isEqual({
a: 1,
b: 2,
c: function () {
return 1;
}
}, {
a: 1,
b: 2,
c: function () {
return 1;
}
});
// -> false
This is what I tried:
_.isEqual(o1, o2, function(val1, val2) {
if(_.isFunction(val1) && _.isFunction(val2)) {
return val1.toString() === val2.toString();
}
})
Lodash supports a customizer function which allows you to write your own equality checks. This seems to be a good enough test to see if the functions are character by character the same.
Are you sure you want to compare functions? If you only care about comparing every property that isn't a function, this is easy to do with lodash:
var o1 = { a: 1, b: 2, c: function() { return 1; } },
o2 = { a: 1, b: 2, c: function() { return 1; } };
_.isEqual(o1, o2)
// → false
_.isEqual(_.omit(o1, _.functions(o1)), _.omit(o2, _.functions(o2)));
// → true
The functions() function returns a list of function properties, and using omit(), you can get rid of them.
Try isEqualWith instead:
import { isEqualWith, isFunction } from 'lodash-es'
const o1 = { fn() {} }
const o2 = { fn() {} }
const equal = isEqualWith(o1, o2, (v1, v2) =>
// if `customizer` returns `undefined`, comparisons are handled by the method instead
isFunction(v1) && isFunction(v2) ? `${v1}` === `${v2}` : undefined,
)
console.log({ equal }) // { equal: true }
As the lodash documentation states:
Functions and DOM nodes are not supported.
https://lodash.com/docs#isEqual

underscore _.each not adding property to object element

This is kind of a newb question as there are still some small things about javascript that baffle me.
I have the following code:
db.units.find({}, { _id: 1, type: 1, name: 1 }).sort({ type: 1, name: 1}).exec(function(err, units) {
if(err) return next(err);
_.each(units, function(u, i) {
this[i]["available"] = !_.contains(_.pluck(_.pluck(req.workorder.units, 'unit'), 'name'), u.name);
console.log(this[i].available);
console.log(this[i]);
console.log(_.extend(this[i],{available:this[i].available}));
}, units);
return res.render('workorder/show', {
workorder: req.workorder,
invoices: db.invoices.find({ workorders: req.params.id }),
units: units
});
});
and here is the result:
true
{ _id: 513bd489b0e7e2634b60dc47,
name: 'Visual Sump Inspection UST-22C NC',
type: 'Service' }
its is logging the available property but not in the object alone, why is this?
The problem is related to how mongoose treats objects. the object can only be modified with the usage of document.toObject()
http://mongoosejs.com/docs/api.html#document_Document-toObject
Likeso:
_.each(units, function(u, i) {
u = _.extend(u.toObject(), {'available': !_.contains(_.pluck(_.pluck(req.workorder.units, 'unit'), 'name'), u.name)});
});
I suspect that Mongoose is defining the available property in a way that makes it readable but non-enumerable. It could be using a getter, or it could be setting enumerable: false with an Object.defineProperty() or Object.defineProperties call.
For a quick test, try pasting this code into the Chrome console or in your node.js app:
var obj = { a: 1 };
Object.defineProperties( obj, {
b: {
get: function() {
return 2;
}
},
c: {
value: 3,
enumerable: false
}
});
console.log( obj );
console.log( obj.a );
console.log( obj.b );
console.log( obj.c );
In Chrome, the code logs:
Object {a: 1}
1
2
3
So all three properties are showing up when read explicitly, but b and c are not enumerated when the object as a whole is logged.

Categories