Skip to content

Commit

Permalink
fix: change OrmUtils.mergeDeep to not merge RegExp objects
Browse files Browse the repository at this point in the history
Before entity column values are transformed, changes are deeply merged using OrmUtils.mergeDeep. This mergeDeep function attempts to merge objects, but wrongly attempted to merge RegExp objects. This merging of RegExp objects breaks the object, rendering them unusable. This commit changes mergeDeep to not merge RegExp objects but overwrite them instead.

Closes typeorm#3534
  • Loading branch information
tobyhinloopen committed Dec 5, 2019
1 parent 04b4f3e commit 7dcd3c9
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 14 deletions.
26 changes: 12 additions & 14 deletions src/util/OrmUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,23 +73,21 @@ export class OrmUtils {

if (this.isObject(target) && this.isObject(source)) {
for (const key in source) {
let propertyKey = key;
if (source[key] instanceof Promise)
const value = source[key];
if (value instanceof Promise)
continue;

// if (source[key] instanceof Promise) {
// propertyKey = "__" + key + "__";
// }

if (this.isObject(source[propertyKey])
&& !(source[propertyKey] instanceof Map)
&& !(source[propertyKey] instanceof Set)
&& !(source[propertyKey] instanceof Date)
&& !(source[propertyKey] instanceof Buffer)) {
if (!target[key]) Object.assign(target, { [key]: Object.create(Object.getPrototypeOf(source[propertyKey])) });
this.mergeDeep(target[key], source[propertyKey]);
if (this.isObject(value)
&& !(value instanceof Map)
&& !(value instanceof Set)
&& !(value instanceof Date)
&& !(value instanceof Buffer)
&& !(value instanceof RegExp)) {
if (!target[key])
Object.assign(target, { [key]: Object.create(Object.getPrototypeOf(value)) });
this.mergeDeep(target[key], value);
} else {
Object.assign(target, { [key]: source[propertyKey] });
Object.assign(target, { [key]: value });
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions test/github-issues/3534/entity/Foo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {Column} from "../../../../src/decorator/columns/Column";
import {Entity} from "../../../../src/decorator/entity/Entity";
import { RegExpStringTransformer } from './RegExpStringTransformer';
import { PrimaryGeneratedColumn } from '../../../../src';

@Entity()
export class Foo {
@PrimaryGeneratedColumn()
id: number;

@Column({ type: String, transformer: RegExpStringTransformer })
bar: RegExp;
}
15 changes: 15 additions & 0 deletions test/github-issues/3534/entity/RegExpStringTransformer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export namespace RegExpStringTransformer {
export function to(value: RegExp): string {
return value.toString();
}

export function from(value: string): RegExp {
const match = value.match(/^\/(.*)\/(.*)$/);
if (match) {
const [, pattern, flags] = match;
return new RegExp(pattern, flags);
} else {
throw new Error(`"${value}" is not a regular expression`);
}
}
}
32 changes: 32 additions & 0 deletions test/github-issues/3534/issue-3534.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import "reflect-metadata";
import {expect} from "chai";
import { Connection, PromiseUtils } from "../../../src";
import { Foo } from "./entity/Foo";
import { closeTestingConnections, createTestingConnections } from '../../utils/test-utils';

describe("github issues > #3534: store regexp", () => {
let connections: Connection[];
before(async () => {
connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
enabledDrivers: ["postgres"],
dropSchema: true,
});
});
after(() => closeTestingConnections(connections));

it("allows entities with regexp columns", () => PromiseUtils.runInSequence(connections, async connection => {
await connection.synchronize();
const repository = connection.getRepository(Foo);

const foo = new Foo();
foo.bar = /foo/i;
const savedFoo = await repository.save(foo);
expect(savedFoo.bar).to.instanceOf(RegExp);
expect(savedFoo.bar.toString()).to.eq(/foo/i.toString());
const storedFoo = await repository.findOneOrFail(foo.id);
expect(storedFoo.bar).to.instanceOf(RegExp);
expect(storedFoo.bar.toString()).to.eq(/foo/i.toString());
}));

});

0 comments on commit 7dcd3c9

Please sign in to comment.