From f609d4857289851e92682510003e932986ccb8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ad=C3=A1mek?= Date: Sat, 11 Dec 2021 23:11:48 +0100 Subject: [PATCH] perf: rework defining of get/set props for change detection 2 --- packages/core/src/entity/EntityHelper.ts | 26 +++++++++++++++++++- packages/core/src/unit-of-work/UnitOfWork.ts | 5 ---- tests/EntityHelper.mongo.test.ts | 5 ++-- tests/features/auto-flush.postgre.test.ts | 2 +- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/packages/core/src/entity/EntityHelper.ts b/packages/core/src/entity/EntityHelper.ts index d8f1584814b0..e4ba61a18885 100644 --- a/packages/core/src/entity/EntityHelper.ts +++ b/packages/core/src/entity/EntityHelper.ts @@ -89,7 +89,7 @@ export class EntityHelper { */ private static defineProperties>(meta: EntityMetadata): void { Object - .values(meta.properties) + .values(meta.properties) .filter(prop => [ReferenceType.ONE_TO_ONE, ReferenceType.MANY_TO_ONE].includes(prop.reference) && (prop.inversedBy || prop.mappedBy) && !prop.mapToPk) .forEach(prop => { Object.defineProperty(meta.prototype, prop.name, { @@ -100,6 +100,30 @@ export class EntityHelper { }); }); + Object + .values(meta.properties) + .filter(prop => !(prop.inherited || prop.primary || prop.persist === false)) + .filter(prop => !([ReferenceType.ONE_TO_ONE, ReferenceType.MANY_TO_ONE].includes(prop.reference) && (prop.inversedBy || prop.mappedBy) && !prop.mapToPk)) + .forEach(prop => { + Object.defineProperty(meta.prototype, prop.name, { + set(val) { + Object.defineProperty(this, prop.name, { + get() { + return this.__helper.__data[prop.name]; + }, + set(val) { + this.__helper.__data[prop.name] = val; + this.__helper.__touched = true; + }, + enumerable: true, + configurable: true, + }); + this.__helper.__data[prop.name] = val; + this.__helper.__touched = true; + }, + }); + }); + /* istanbul ignore else */ if (!meta.prototype[inspect.custom]) { meta.prototype[inspect.custom] = function (depth: number) { diff --git a/packages/core/src/unit-of-work/UnitOfWork.ts b/packages/core/src/unit-of-work/UnitOfWork.ts index e906fca31260..d91fda9c9561 100644 --- a/packages/core/src/unit-of-work/UnitOfWork.ts +++ b/packages/core/src/unit-of-work/UnitOfWork.ts @@ -86,11 +86,6 @@ export class UnitOfWork { Object.keys(data).forEach(key => entity.__helper!.__loadedProperties.add(key)); this.queuedActions.delete(helper.__meta.className); helper.__touched = false; - - if (!(entity as Dictionary).__gettersDefined) { - helper.__data = { ...entity }; - Object.defineProperties(entity, helper.__meta.definedProperties); - } } return entity; diff --git a/tests/EntityHelper.mongo.test.ts b/tests/EntityHelper.mongo.test.ts index 6b9760d16a01..b4c1e8d03f38 100644 --- a/tests/EntityHelper.mongo.test.ts +++ b/tests/EntityHelper.mongo.test.ts @@ -80,9 +80,8 @@ describe('EntityHelperMongo', () => { test('BaseEntity methods', async () => { const god = new Author('God', 'hello@heaven.god'); expect(wrap(god, true).__populated).toBeUndefined(); - // not managed entities do not track changes (before being flushed) - expect(wrap(god, true).__touched).toBe(false); - expect(god.isTouched()).toBe(false); + expect(wrap(god, true).__touched).toBe(true); + expect(god.isTouched()).toBe(true); god.populated(); expect(wrap(god, true).__populated).toBe(true); expect(wrap(god, true).__platform).toBe(orm.em.getDriver().getPlatform()); diff --git a/tests/features/auto-flush.postgre.test.ts b/tests/features/auto-flush.postgre.test.ts index e1988e260041..ee4c89ee76a0 100644 --- a/tests/features/auto-flush.postgre.test.ts +++ b/tests/features/auto-flush.postgre.test.ts @@ -65,7 +65,7 @@ describe('automatic flushing when querying for overlapping entities via em.find/ god.favouriteAuthor.age = 21; god.age = 999; - expect(wrap(god, true).__touched).toBe(false); + expect(wrap(god, true).__touched).toBe(true); await orm.em.persistAndFlush(god); expect(wrap(god, true).__touched).toBe(false);