Skip to content

Commit

Permalink
fix: use prototypeless objects for field-to-type mappings (#212)
Browse files Browse the repository at this point in the history
Fixes: #211
  • Loading branch information
addaleax authored Dec 15, 2023
1 parent f4c7aab commit 90f3f8b
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 11 deletions.
14 changes: 7 additions & 7 deletions src/schema-analyzer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

import Reservoir from 'reservoir';
import type {
import {
Document,
ObjectId,
MinKey,
Expand Down Expand Up @@ -310,7 +310,7 @@ function simplifiedSchema(fields: SchemaAnalysisFieldsMap): SimplifiedSchema {
}

function finalizeDocumentFieldSchema(fieldMap: SchemaAnalysisFieldsMap): SimplifiedSchema {
const fieldSchema: SimplifiedSchema = {};
const fieldSchema: SimplifiedSchema = Object.create(null);
Object.values(fieldMap).forEach((field: SchemaAnalysisField) => {
const fieldTypes = finalizeSchemaFieldTypes(field.types);

Expand Down Expand Up @@ -437,7 +437,7 @@ export class SchemaAnalyzer {
options: SchemaParseOptions;
documentsAnalyzed = 0;
schemaAnalysisRoot: SchemaAnalysisRoot = {
fields: {},
fields: Object.create(null),
count: 0
};

Expand All @@ -464,7 +464,7 @@ export class SchemaAnalyzer {
this.semanticTypes = {
...Object.entries(this.semanticTypes)
.filter(([k]) => enabledTypes.includes(k.toLowerCase()))
.reduce((p, [k, v]) => ({ ...p, [k]: v }), {})
.reduce((p, [k, v]) => ({ ...p, [k]: v }), Object.create(null))
};

Object.entries(this.options.semanticTypes)
Expand Down Expand Up @@ -512,13 +512,13 @@ export class SchemaAnalyzer {

if (isArrayType(type)) {
// Recurse into arrays by calling `addToType` for each element.
type.types = type.types ?? {};
type.types = type.types ?? Object.create(null);
type.lengths = type.lengths ?? [];
type.lengths.push((value as BSONValue[]).length);
(value as BSONValue[]).forEach((v: BSONValue) => addToType(path, v, type.types));
} else if (isDocumentType(type)) {
// Recurse into nested documents by calling `addToField` for all sub-fields.
type.fields = type.fields ?? {};
type.fields = type.fields ?? Object.create(null);
Object.entries(value as Document).forEach(
([fieldName, v]) => addToField(fieldName, [...path, fieldName], v, type.fields)
);
Expand All @@ -545,7 +545,7 @@ export class SchemaAnalyzer {
name: fieldName,
path: path,
count: 0,
types: {}
types: Object.create(null)
};
}
const field = schema[fieldName];
Expand Down
7 changes: 5 additions & 2 deletions test/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ describe('using only basic fields', function() {
last_address_longitude: null,
created_at: new Date(),
length: 29,
'name[]': 'Annabeth Frankie'
'name[]': 'Annabeth Frankie',
toString: 42
}
];

Expand All @@ -38,7 +39,8 @@ describe('using only basic fields', function() {
'name',
'stats_friends',
'twitter_username',
'name[]'
'name[]',
'toString'
];
assert.deepEqual(users.fields.map(v => v.name).sort(), fieldNames.sort());
});
Expand All @@ -59,5 +61,6 @@ describe('using only basic fields', function() {
assert.equal(users.fields.find(v => v.name === 'name')?.type, 'String');
assert.equal(users.fields.find(v => v.name === 'stats_friends')?.type, 'Number');
assert.equal(users.fields.find(v => v.name === 'twitter_username')?.type, 'String');
assert.equal(users.fields.find(v => v.name === 'toString')?.type, 'Number');
});
});
5 changes: 3 additions & 2 deletions test/mixed-type-nested.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ describe('mixed types nested', function() {
{
_id: 5,
address: {
valid: true
valid: true,
toString: { value: false }
}
}
];
] as const;

let schema: Schema;
let valid: SchemaField | undefined;
Expand Down

0 comments on commit 90f3f8b

Please sign in to comment.