Skip to content

Commit 87e7516

Browse files
authored
fix(deep-object-assign): handle date merging as expected (#1386)
vis-util (used by vis-data, used in turn by vis-timeline) has some cloning/merging logic that works fine with primitives, Arrays, and Objects, but not so well with anything else. Ideally, it'd be nice if there was a generalizable fix for this that worked with arbitrary classes, but dates are common, at least in the vis-timeline case, and with the tests provided, are now guaranteed to work. There's also an unrelated cross-env change that I needed to make the BABEL_ENV thing in package.json work on Windows, but I suppose we can drop that if it's unwanted. This should cover visjs/vis-data#1014 and visjs/vis-timeline#1562 .
1 parent 2661079 commit 87e7516

File tree

4 files changed

+66
-2
lines changed

4 files changed

+66
-2
lines changed

package-lock.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@
3838
"lint-fix": "eslint --fix --ext .js,.ts .",
3939
"prepublishOnly": "npm run build",
4040
"test": "run-s test:unit test:types:check-dts test:types:tsc test:interop",
41-
"test:coverage": "BABEL_ENV=test-cov nyc mocha",
41+
"test:coverage": "cross-env BABEL_ENV=test-cov nyc mocha",
4242
"test:interop": "node interop.js",
4343
"test:interop:debug": "npm run test:interop -- --fail-command \"$SHELL\"",
4444
"test:types:check-dts": "cd test && check-dts",
4545
"test:types:tsc": "tsc --noemit --project tsconfig.check.json",
46-
"test:unit": "BABEL_ENV=test mocha",
46+
"test:unit": "cross-env BABEL_ENV=test mocha",
4747
"type-check": "run-s test:types:*",
4848
"version": "npm run contributors:update && git add package.json",
4949
"contributors:update": "git-authors-cli",
@@ -100,6 +100,7 @@
100100
"assert": "2.1.0",
101101
"check-dts": "0.7.2",
102102
"component-emitter": "1.3.0",
103+
"cross-env": "^7.0.3",
103104
"eslint": "8.50.0",
104105
"git-authors-cli": "1.0.46",
105106
"husky": "8.0.3",

src/deep-object-assign.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ function deepObjectAssignNonentry(...values: readonly any[]): any {
7676
const a = values[0];
7777
const b = values[1];
7878

79+
if (a instanceof Date && b instanceof Date) {
80+
a.setTime(b.getTime());
81+
return a;
82+
}
83+
7984
for (const prop of Reflect.ownKeys(b)) {
8085
if (!Object.prototype.propertyIsEnumerable.call(b, prop)) {
8186
// Ignore nonenumerable props, Object.assign() would do the same.
@@ -108,6 +113,9 @@ function clone(a: any): any {
108113
if (Array.isArray(a)) {
109114
return a.map((value: any): any => clone(value));
110115
} else if (typeof a === "object" && a !== null) {
116+
if (a instanceof Date) {
117+
return new Date(a.getTime());
118+
}
111119
return deepObjectAssignNonentry({}, a);
112120
} else {
113121
return a;

test/deep-object-assign.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,40 @@ test(deepObjectAssign, (): void => {
253253
foo: "bar",
254254
deleteFoo: "foo",
255255
});
256+
257+
const date = new Date(0);
258+
const date2 = new Date(50000);
259+
const date3 = new Date(150000);
260+
261+
// Merge single date into empty object
262+
given(
263+
{},
264+
{
265+
start: date,
266+
}
267+
).expect({
268+
start: date,
269+
});
270+
271+
// Merge single date into non-empty object (no overlap)
272+
given(
273+
{ start: date },
274+
{
275+
end: date2,
276+
}
277+
).expect({
278+
start: date,
279+
end: date2,
280+
});
281+
282+
// Merge single date into non-empty object (overlap)
283+
given(
284+
{ start: date, end: date2 },
285+
{
286+
end: date3,
287+
}
288+
).expect({
289+
start: date,
290+
end: date3,
291+
});
256292
});

0 commit comments

Comments
 (0)