Skip to content

Commit

Permalink
Merge pull request #119 from drborges/fix-method-binding-mechanism
Browse files Browse the repository at this point in the history
Isolate method bindings to each node instance
  • Loading branch information
drborges authored Jun 17, 2024
2 parents 13f6366 + a835a94 commit 475d870
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 19 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
6 changes: 3 additions & 3 deletions packages/arbor-plugins/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@arborjs/plugins",
"version": "0.0.1-alpha.87",
"version": "0.0.1-alpha.88",
"sideEffects": false,
"description": "Community driven plugins for @arborjs/store.",
"keywords": [
Expand Down Expand Up @@ -46,7 +46,7 @@
"access": "public"
},
"devDependencies": {
"@arborjs/store": "0.0.1-alpha.87",
"@arborjs/store": "0.0.1-alpha.88",
"@types/jest": "^29.5.1",
"esbuild": "^0.17.19",
"eslint": "^8.40.0",
Expand All @@ -57,7 +57,7 @@
"typescript": "^5.0.4"
},
"peerDependencies": {
"@arborjs/store": "0.0.1-alpha.87"
"@arborjs/store": "0.0.1-alpha.88"
},
"scripts": {
"prettier": "prettier -w . ",
Expand Down
6 changes: 3 additions & 3 deletions packages/arbor-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@arborjs/react",
"version": "0.0.1-alpha.87",
"version": "0.0.1-alpha.88",
"sideEffects": false,
"description": "A fully typed, minimalistic proxy-based state tree library with very little boilerplate for React apps.",
"keywords": [
Expand Down Expand Up @@ -45,7 +45,7 @@
"access": "public"
},
"devDependencies": {
"@arborjs/store": "0.0.1-alpha.87",
"@arborjs/store": "0.0.1-alpha.88",
"@testing-library/react": "14.0.0",
"@types/jest": "^29.5.1",
"@types/react": "18.2.31",
Expand All @@ -71,7 +71,7 @@
"build:dev": "yarn clean && NODE_ENV=development node ../../tools/build.js && yarn tsc"
},
"peerDependencies": {
"@arborjs/store": "0.0.1-alpha.87",
"@arborjs/store": "0.0.1-alpha.88",
"react": "18.2.0",
"react-dom": "18.2.14"
}
Expand Down
4 changes: 2 additions & 2 deletions packages/arbor-rxjs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@arborjs/rxjs",
"version": "0.0.1-alpha.87",
"version": "0.0.1-alpha.88",
"sideEffects": false,
"description": "rxjs binding for @arborjs/store",
"keywords": [
Expand Down Expand Up @@ -55,7 +55,7 @@
"typescript": "^5.0.4"
},
"peerDependencies": {
"@arborjs/store": "0.0.1-alpha.87",
"@arborjs/store": "0.0.1-alpha.88",
"rxjs": "*"
},
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/arbor-store/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@arborjs/store",
"sideEffects": false,
"version": "0.0.1-alpha.87",
"version": "0.0.1-alpha.88",
"description": "A fully typed, minimalistic proxy-based state tree library with very little boilerplate.",
"keywords": [
"arbor",
Expand Down
30 changes: 30 additions & 0 deletions packages/arbor-store/src/Arbor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2581,4 +2581,34 @@ describe("Arbor", () => {
expect(subscriber.mock.calls[1][0].metadata.operation).toEqual("set")
expect(subscriber.mock.calls[2][0].metadata.operation).toEqual("push")
})

it("binds methods to the instance of the node they belong to", () => {
@proxiable
class Todo {
constructor(public text = "", public done = false) {}

toggle() {
this.done = !this.done
}
}

@proxiable
class TodoApp {
todos: Todo[] = []
}

const store = new TrackedArbor(new Arbor(new TodoApp()))
const subscriber = jest.fn()

store.subscribe(subscriber)

const state = store.state
state.todos = [new Todo("Do the dishes"), new Todo("Clean the house")]

state.todos[0].toggle()
state.todos[1].toggle()

expect(state.todos[0].done).toBe(true)
expect(state.todos[1].done).toBe(true)
})
})
13 changes: 9 additions & 4 deletions packages/arbor-store/src/TrackedArbor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function isArborNodeTracked<T extends object>(
}

class Tracker<T extends object> {
private readonly bindings = new WeakMap()
private readonly bindings = new WeakMap<object, WeakMap<object, object>>()
private readonly cache = new WeakMap<ArborNode, Tracked>()
private tracking = new WeakMap<Seed, Set<string>>()

Expand Down Expand Up @@ -127,13 +127,18 @@ class Tracker<T extends object> {
// class methods of Arbor nodes a great option for components event handlers.
const unwrappedTarget = recursivelyUnwrap(target)
const unwrappedChild = Reflect.get(unwrappedTarget, prop, proxy)
if (!bindings.has(unwrappedChild)) {
if (!bindings.has(unwrappedTarget)) {
// Methods are bound to the proxy so that 'this' within the method context
// points back to the proxy itself, allowing it to intercept access to nested objects.
bindings.set(unwrappedChild, child.bind(proxy))
bindings.set(unwrappedTarget, new WeakMap())
}

return bindings.get(unwrappedChild)
const targetBidings = bindings.get(unwrappedTarget)
if (!targetBidings.has(unwrappedChild)) {
targetBidings.set(unwrappedChild, child.bind(proxy))
}

return bindings.get(unwrappedTarget).get(unwrappedChild)
}

return child
Expand Down
12 changes: 6 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@arborjs/plugins@workspace:packages/arbor-plugins"
dependencies:
"@arborjs/store": 0.0.1-alpha.87
"@arborjs/store": 0.0.1-alpha.88
"@types/jest": ^29.5.1
esbuild: ^0.17.19
eslint: ^8.40.0
Expand All @@ -49,15 +49,15 @@ __metadata:
ts-jest: ^29.1.0
typescript: ^5.0.4
peerDependencies:
"@arborjs/store": 0.0.1-alpha.87
"@arborjs/store": 0.0.1-alpha.88
languageName: unknown
linkType: soft

"@arborjs/react@workspace:^, @arborjs/react@workspace:packages/arbor-react":
version: 0.0.0-use.local
resolution: "@arborjs/react@workspace:packages/arbor-react"
dependencies:
"@arborjs/store": 0.0.1-alpha.87
"@arborjs/store": 0.0.1-alpha.88
"@testing-library/react": 14.0.0
"@types/jest": ^29.5.1
"@types/react": 18.2.31
Expand All @@ -73,7 +73,7 @@ __metadata:
ts-jest: ^29.1.0
typescript: ^5.0.4
peerDependencies:
"@arborjs/store": 0.0.1-alpha.87
"@arborjs/store": 0.0.1-alpha.88
react: 18.2.0
react-dom: 18.2.14
languageName: unknown
Expand All @@ -91,7 +91,7 @@ __metadata:
ts-jest: ^29.1.0
typescript: ^5.0.4
peerDependencies:
"@arborjs/store": 0.0.1-alpha.87
"@arborjs/store": 0.0.1-alpha.88
rxjs: "*"
languageName: unknown
linkType: soft
Expand All @@ -105,7 +105,7 @@ __metadata:
languageName: unknown
linkType: soft

"@arborjs/[email protected].87, @arborjs/store@workspace:*, @arborjs/store@workspace:^, @arborjs/store@workspace:packages/arbor-store":
"@arborjs/[email protected].88, @arborjs/store@workspace:*, @arborjs/store@workspace:^, @arborjs/store@workspace:packages/arbor-store":
version: 0.0.0-use.local
resolution: "@arborjs/store@workspace:packages/arbor-store"
dependencies:
Expand Down

0 comments on commit 475d870

Please sign in to comment.