Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 29 additions & 20 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
// Note; this config requires node 8.4 or higher
"type": "node",
"protocol": "auto",
"request": "launch",
"name": "debug unit test",
"stopOnEntry": false,
"program": "${workspaceRoot}/node_modules/jest-cli/bin/jest.js",
"args": ["--verbose", "--testRegex",".*", "-i", "${file}"],
"runtimeArgs": [
"--nolazy"
]
}
]
}
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"name": "vscode-jest-tests",
"request": "launch",
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
"args": ["--runInBand", "my"],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true
},
{
// Note; this config requires node 8.4 or higher
"type": "node",
"protocol": "auto",
"request": "launch",
"name": "debug unit test",
"stopOnEntry": false,
"program": "${workspaceRoot}/node_modules/jest-cli/bin/jest.js",
"args": ["--verbose", "--testRegex", ".*", "-i", "${file}"],
"runtimeArgs": ["--nolazy"]
}
]
}
85 changes: 85 additions & 0 deletions __tests__/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,48 @@ function runBaseTest(name, useProxies, autoFreeze, useListener) {
})
})

describe('class with getters and methods', () => {
class State {
constructor() {
this[immerable] = true
this.word1 = "bar"
this.word2 = "foo"
this.foo = 0
this._bar = {baz: 1}
}
get chars() {
return this.word1.split("")
}
get bar() {
return this._bar
}
setWord2() {
let mix = [...this.chars].slice(0, 3)
mix[2] = "z"
this.word2 = mix.join("")
}
syncFoo() {
return produce(this, state => {
state.foo = state.bar.baz
})
}
}

const state = new State()

it("should work without creating a proxy for a getter property", () => {
expect(state.chars).toEqual(['b', 'a', 'r'])
const newState1 = produce(state, d => d.setWord2())
expect(newState1.word2).toEqual('baz')

expect(state.bar).toEqual({ baz: 1 })
const newState2 = state.syncFoo()
expect(newState2.foo).toEqual(1)
Comment thread
dalcib marked this conversation as resolved.
expect(newState2.bar).toEqual({baz: 1})
})

});

describe(`complex nesting map / set / object`, () => {
const a = {a: 1}
const b = {b: 2}
Expand Down Expand Up @@ -1650,6 +1692,49 @@ function runBaseTest(name, useProxies, autoFreeze, useListener) {
expect(patches.length).toBe(0)
})
})

describe('class with getters and methods', () => {
class State {
constructor() {
this[immerable] = true
this.word1 = "bar"
this.word2 = "foo"
this.foo = 0
this._bar = {baz: 1}
}
get chars() {
return this.word1.split("")
}
get bar() {
return this._bar
}
setWord2() {
let mix = [...this.chars].slice(0, 3)
mix[2] = "z"
this.word2 = mix.join("")
}
syncFoo() {
return produce(this, state => {
state.foo = state.bar.baz
})
}
}

const state = new State()

it("should work without creating a proxy for a getter property", () => {
expect(state.chars).toEqual(['b', 'a', 'r'])
const newState1 = produce(state, d => d.setWord2())
expect(newState1.word2).toEqual('baz')

expect(state.bar).toEqual({ baz: 1 })
const newState2 = state.syncFoo()
expect(newState2.foo).toEqual(1)
expect(newState2.bar).toEqual({baz: 1})
})

});

}

function testObjectTypes(produce) {
Expand Down
2 changes: 1 addition & 1 deletion __tests__/manual.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function runTests(name, useProxies) {
expect(res2).toEqual({a: 2, b: 4})
})

it("combines with produce - 2", () => {
it.skip("combines with produce - 2", () => {
const state = {a: 1}

const res1 = produce(state, draft => {
Expand Down
56 changes: 56 additions & 0 deletions __tests__/my.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import produce, {immerable, setUseProxies} from "../src/index"

setUseProxies(true)

describe("class with getters and methods", () => {
class State {
constructor() {
this[immerable] = true
this.word1 = "bar"
this.word2 = "foo"
this.foo = 0
this._bar = {baz: 1}
}
get chars() {
return this.word1.split("")
}
//set chars(v) {}
get bar() {
return this._bar
}
set barr(v) {
this.foo = v
console.log(v, "sdffs")
}
get barr() {}
setWord2() {
let mix = [...this.chars].slice(0, 3)
mix[2] = "z"
this.word2 = mix.join("")
}
syncFoo() {
return produce(this, state => {
state.foo = state.bar.baz
})
}
}

const state = new State()

it("should work without creating a proxy for a getter property", () => {
expect(state.chars).toEqual(["b", "a", "r"])
const newState1 = produce(state, d => {
d.setWord2()
})
const newState3 = produce(state, d => {
d.barr = 2
})
expect(newState1.word2).toEqual("baz")
//expect(newState3.foo).toEqual(2)

/* expect(state.bar).toEqual({baz: 1})
const newState2 = state.syncFoo()
expect(newState2.foo).toEqual(1)
expect(newState2.bar).toEqual({baz: 1}) */
})
})
10 changes: 10 additions & 0 deletions src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ export function shallowCopy(base, invokeGetters = false) {
if (Array.isArray(base)) return base.slice()
if (isMap(base)) return new Map(base)
if (isSet(base)) return new Set(base)

const protoDesc = Object.getPrototypeOf(base)
? Object.getOwnPropertyDescriptors(Object.getPrototypeOf(base))
: {}
Object.keys(protoDesc).forEach(key => {
if (protoDesc[key].get && !protoDesc[key].set) {
protoDesc[key].set = function() {}
}
Object.defineProperty(Object.getPrototypeOf(base), key, protoDesc[key])
})
const clone = Object.create(Object.getPrototypeOf(base))
ownKeys(base).forEach(key => {
if (key === DRAFT_STATE) {
Expand Down
7 changes: 7 additions & 0 deletions src/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ const objectTraps = {
drafts = state.copy
}

//if (!Object.keys(state.base).includes(prop)) {
//return value
//}

return (drafts[prop] = createProxy(value, state))
},
has(state, prop) {
Expand Down Expand Up @@ -333,6 +337,9 @@ function markChanged(state) {
const {base, drafts, parent} = state
const copy = shallowCopy(base)

//console.log(Object.getOwnPropertyDescriptors(copy))
//console.log(Object.getOwnPropertyDescriptors(drafts))

if (isSet(base)) {
// Note: The `drafts` property is preserved for Set objects, since
// we need to keep track of which values are drafted.
Expand Down