Skip to content

Commit 668483f

Browse files
committed
fix: reuse objects when possible; delete test that protects against this (now desired) behaviour
1 parent 2320bef commit 668483f

File tree

5 files changed

+93
-54
lines changed

5 files changed

+93
-54
lines changed

package-lock.json

Lines changed: 17 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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,15 @@
6868
"eslint-plugin-prettier": "^3.1.4",
6969
"eslint-plugin-promise": "^4.2.1",
7070
"eslint-plugin-standard": "^4.0.2",
71+
"json-schema-merge-allof-old": "npm:json-schema-merge-allof@0.6.0",
7172
"json-schema-ref-parser": "^9.0.6",
7273
"json-stringify-safe": "^5.0.1",
7374
"mocha": "^4.0.1",
7475
"npm-run-all": "^4.1.5",
7576
"nyc": "^11.2.1",
7677
"prettier": "^2.1.2",
7778
"sinon": "^4.0.1",
79+
"sizeof": "^1.0.0",
7880
"typescript": "^4.0.3"
7981
}
8082
}

sizecmp.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
'use strict';
2+
3+
const mergeOld = require('json-schema-merge-allof-old');
4+
const mergeNew = require('.');
5+
const { inspect } = require('util');
6+
const { sizeof } = require('sizeof');
7+
const { cloneDeep } = require('lodash');
8+
9+
const schema = {
10+
allOf: [
11+
{
12+
anyOf: [
13+
{ type: 'object', properties: { foo: { type: 'string' } } },
14+
{ type: 'object', properties: { bar: { type: 'string' } } }
15+
]
16+
},
17+
{
18+
allOf: [
19+
{ type: 'object', properties: { one: { type: 'string' } } },
20+
{ type: 'object', properties: { two: { type: 'string' } } }
21+
]
22+
}
23+
]
24+
};
25+
26+
const m = mergeNew(schema);
27+
const n = [m, m, m.anyOf, m.anyOf];
28+
console.log(sizeof(m), sizeof(n), sizeof([mergeNew(schema), mergeNew(schema)]));
29+
const mergedNew = [mergeNew(schema), mergeNew(schema), mergeNew(schema)];
30+
const mergedOld = [
31+
mergeOld(cloneDeep(schema)),
32+
mergeOld(cloneDeep(schema)),
33+
mergeOld(cloneDeep(schema))
34+
];
35+
36+
console.log(inspect(mergedNew));
37+
38+
console.log('Old:', sizeof(mergedOld));
39+
console.log('New:', sizeof(mergedNew));

src/index.ts

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ function cleanupReturnValue(returnObject) {
180180
hasOwnProperty.call(returnObject, prop) &&
181181
isEmptySchema(returnObject[prop])
182182
) {
183-
delete returnObject[prop];
183+
const { [prop]: dummy, ...rest } = returnObject;
184+
returnObject = rest;
184185
}
185186
}
186187
return returnObject;
@@ -212,7 +213,7 @@ function callGroupResolver(
212213
throw new Error('No resolver found for ' + resolverName);
213214
}
214215

215-
const compacted = uniqWith(
216+
let compacted = uniqWith(
216217
schemas
217218
.map(function (schema) {
218219
return keys.reduce(function (all, key) {
@@ -225,6 +226,7 @@ function callGroupResolver(
225226
.filter(notUndefined),
226227
compare
227228
);
229+
if (isEqual(compacted, schemas)) compacted = schemas;
228230

229231
const related =
230232
resolverName === 'properties' ? propertyRelated : itemsRelated;
@@ -256,7 +258,7 @@ function callGroupResolver(
256258
};
257259
}
258260

259-
const result = resolver(
261+
let result = resolver(
260262
compacted,
261263
parents.concat(resolverName),
262264
mergers,
@@ -267,7 +269,18 @@ function callGroupResolver(
267269
throwIncompatible(compacted, parents.concat(resolverName));
268270
}
269271

270-
return cleanupReturnValue(result);
272+
result = cleanupReturnValue(result);
273+
if (Object.keys(result).length === 1) {
274+
if (
275+
'properties' in result &&
276+
isEqual(result.properties, schemas[0].properties)
277+
) {
278+
return { properties: schemas[0].properties };
279+
} else if ('items' in result && isEqual(result.items, schemas[0].items)) {
280+
return { items: schemas[0].items };
281+
}
282+
}
283+
return result;
271284
}
272285
}
273286

@@ -279,8 +292,7 @@ function mergeSchemaGroup(group, mergeSchemas, source?: JSONSchema[]) {
279292
function (all, key) {
280293
const schemas = extractor(group, key);
281294
const compacted = uniqWith(schemas.filter(notUndefined), compare);
282-
all = setProp(all, key, mergeSchemas(compacted, key));
283-
return all;
295+
return setProp(all, key, mergeSchemas(compacted, key));
284296
},
285297
source ? [] : {}
286298
);
@@ -772,10 +784,13 @@ function merger<T extends JSONSchema>(
772784
);
773785

774786
function addToAllOf(unresolvedSchemas) {
775-
merged = {
776-
...merged,
777-
allOf: mergeWithArray(merged.allOf, unresolvedSchemas)
778-
};
787+
const mergedAllOf = mergeWithArray(merged.allOf, unresolvedSchemas);
788+
if (mergedAllOf !== merged.allOf) {
789+
merged = {
790+
...merged,
791+
allOf: mergeWithArray(merged.allOf, unresolvedSchemas)
792+
};
793+
}
779794
}
780795

781796
return merged;
@@ -792,18 +807,21 @@ merger.options = {
792807
};
793808

794809
function setProp<T>(ob, key, value): T {
795-
if (Array.isArray(ob)) {
796-
ob = [...ob];
797-
ob[key] = value;
798-
return ob;
799-
} else {
800-
return ob[key] === value ? ob : { ...ob, [key]: value };
810+
if (ob[key] !== value) {
811+
if (Array.isArray(ob)) {
812+
ob = ob.slice();
813+
ob[key] = value;
814+
} else {
815+
ob = { ...ob, [key]: value };
816+
}
801817
}
818+
return ob;
802819
}
803820

804821
function setProps<T>(ob, values): T {
805822
for (const k in values) {
806-
ob = setProp(ob, k, values[k]);
823+
const val = values[k];
824+
if (val !== ob[k]) ob = setProp(ob, k, val);
807825
}
808826
return ob;
809827
}

test/specs/index.spec.js

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -80,43 +80,6 @@ describe('module', function() {
8080
})
8181
})
8282

83-
it('does not use any original objects or arrays', () => {
84-
const schema = {
85-
properties: {
86-
arr: {
87-
type: 'array',
88-
items: {
89-
type: 'object'
90-
},
91-
additionalItems: [{
92-
type: 'array'
93-
}]
94-
}
95-
},
96-
allOf: [{
97-
properties: {
98-
test: true
99-
}
100-
}]
101-
}
102-
103-
function innerDeconstruct(schema) {
104-
const allChildObj = Object.entries(schema).map(([key, val]) => {
105-
if (_.isObject(val)) return innerDeconstruct(val)
106-
})
107-
return [schema, ..._.flatten(allChildObj)]
108-
}
109-
110-
const getAllObjects = schema => _(innerDeconstruct(schema)).compact().value()
111-
const inputObjects = getAllObjects(schema)
112-
113-
const result = merger(schema)
114-
const resultObjects = getAllObjects(result)
115-
116-
const commonObjects = _.intersection(inputObjects, resultObjects)
117-
expect(commonObjects).to.have.length(0)
118-
})
119-
12083
it('combines simple usecase', function() {
12184
var result = merger({
12285
allOf: [{

0 commit comments

Comments
 (0)