Skip to content

Commit bbd4da1

Browse files
authored
Merge pull request #83 from richmolj/dup
Ensure #dup() works correctly
2 parents 05dbf75 + 97ac360 commit bbd4da1

File tree

4 files changed

+46
-1
lines changed

4 files changed

+46
-1
lines changed

src/model.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { refreshJWT } from "./util/refresh-jwt"
55
import relationshipIdentifiersFor from "./util/relationship-identifiers"
66
import { Request, RequestVerbs, JsonapiResponse } from "./request"
77
import { WritePayload } from "./util/write-payload"
8+
import { flipEnumerable, getNonEnumerables } from "./util/enumerables"
89
import {
910
CredentialStorage,
1011
NullStorageBackend,
@@ -616,7 +617,12 @@ export class JSORMBase {
616617
}
617618

618619
dup(): this {
619-
return cloneDeep(this)
620+
let nonEnums = getNonEnumerables(this)
621+
flipEnumerable(this, nonEnums, true)
622+
let cloned = cloneDeep(this)
623+
flipEnumerable(this, nonEnums, false)
624+
flipEnumerable(cloned, nonEnums, false)
625+
return cloned
620626
}
621627

622628
/*

src/util/decorators.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const nonenumerable = (target: any, key: string) => {
1010
Object.defineProperty(this, key, {
1111
value: val,
1212
writable: true,
13+
configurable: true,
1314
enumerable: false
1415
})
1516
},

src/util/enumerables.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export function flipEnumerable(instance: any, props: string[], to: boolean) : void {
2+
props.forEach((propName) => {
3+
let descriptor = Object.getOwnPropertyDescriptor(instance, propName)
4+
descriptor.enumerable = to
5+
Object.defineProperty(instance, propName, descriptor)
6+
})
7+
}
8+
9+
export function getNonEnumerables(instance: any) : string[] {
10+
let nonEnums = [] as string[]
11+
Object.getOwnPropertyNames(instance).forEach((propName) => {
12+
let descriptor = Object.getOwnPropertyDescriptor(instance, propName)
13+
if (!descriptor.enumerable) {
14+
nonEnums.push(propName)
15+
}
16+
})
17+
return nonEnums
18+
}

test/unit/model.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,26 @@ describe("Model", () => {
13251325
})
13261326
})
13271327

1328+
describe("#dup()", () => {
1329+
it("returns a new instance of the same object", () => {
1330+
let author = new Author({ firstName: "Stephen" })
1331+
let duped = author.dup()
1332+
duped.firstName = "updated"
1333+
expect(author.firstName).to.eq("Stephen")
1334+
expect(duped.firstName).to.eq("updated")
1335+
})
1336+
1337+
it("does not recast nonenumerables to enumerable", () => {
1338+
let author = new Author({ firstName: "Stephen" })
1339+
let duped = author.dup()
1340+
1341+
let descriptor = Object.getOwnPropertyDescriptor(author, 'relationships')
1342+
expect(descriptor.enumerable).to.eq(false)
1343+
descriptor = Object.getOwnPropertyDescriptor(duped, 'relationships')
1344+
expect(descriptor.enumerable).to.eq(false)
1345+
})
1346+
})
1347+
13281348
describe("#fetchOptions", () => {
13291349
context("jwt is set", () => {
13301350
beforeEach(() => {

0 commit comments

Comments
 (0)