From c18ed1d878250a3d8081c87896ad9a3a44ba29fe Mon Sep 17 00:00:00 2001 From: AmaranthineCodices Date: Sat, 17 Mar 2018 15:16:37 -0400 Subject: [PATCH 1/8] let's try this again --- lib/Change.lua | 23 +++++++++++++++++++ lib/Change.spec.lua | 15 +++++++++++++ lib/Reconciler.lua | 4 +++- lib/SingleEventManager.lua | 45 +++++++++++++++++++++++++++++++++++++- lib/init.lua | 2 ++ lib/init.spec.lua | 1 + 6 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 lib/Change.lua create mode 100644 lib/Change.spec.lua diff --git a/lib/Change.lua b/lib/Change.lua new file mode 100644 index 00000000..a38ac317 --- /dev/null +++ b/lib/Change.lua @@ -0,0 +1,23 @@ +local Change = {} + +local changeMetatable = { + __tostring = function(self) + return ("ChangeListener(%s)"):format(self.name) + end +} + +setmetatable(Change, { + __index = function(self, propertyName) + local changeListener = { + type = "propertyChange", + name = propertyName + } + + setmetatable(changeListener, changeMetatable) + Change[propertyName] = changeListener + + return changeListener + end, +}) + +return Change \ No newline at end of file diff --git a/lib/Change.spec.lua b/lib/Change.spec.lua new file mode 100644 index 00000000..154539a9 --- /dev/null +++ b/lib/Change.spec.lua @@ -0,0 +1,15 @@ +return function() + local Change = require(script.Parent.Change) + + it("should yield change listener objects when indexed", function() + expect(Change.Text).to.be.ok() + expect(Change.Selected).to.be.ok() + end) + + it("should yield the same object when indexed again", function() + local a = Change.Text + local b = Change.Text + + expect(a).to.equal(b) + end) +end \ No newline at end of file diff --git a/lib/Reconciler.lua b/lib/Reconciler.lua index bd816d5c..92044d51 100644 --- a/lib/Reconciler.lua +++ b/lib/Reconciler.lua @@ -512,6 +512,8 @@ function Reconciler._setRbxProp(rbx, key, value, element) if key.type == Event then Reconciler._singleEventManager:connect(rbx, key.name, value) + elseif key.type == "propertyChange" then + Reconciler._singleEventManager:connectProperty(rbx, key.name, value) else local source = element.source or DEFAULT_SOURCE @@ -539,4 +541,4 @@ function Reconciler._setRbxProp(rbx, key, value, element) end end -return Reconciler \ No newline at end of file +return Reconciler diff --git a/lib/SingleEventManager.lua b/lib/SingleEventManager.lua index 83aafd8b..1b8f8bb1 100644 --- a/lib/SingleEventManager.lua +++ b/lib/SingleEventManager.lua @@ -31,6 +31,21 @@ local function createHook(rbx, key, method) return hook end +local function createChangeHook(rbx, key, method) + local hook = { + method = method, + connection = rbx:GetPropertyChangedSignal(key):Connect(function(...) + method(rbx, ...) + end) + } + + return hook +end + +local function formatChangeKey(key) + return ("!PropertyChangeEvent:%s"):format(key) +end + function SingleEventManager.new() local self = {} @@ -64,6 +79,30 @@ function SingleEventManager:connect(rbx, key, method) end end +function SingleEventManager:connectProperty(rbx, key, method) + local rbxHooks = self._hookCache[rbx] + local formattedKey = formatChangeKey(key) + + if rbxHooks then + local existingHook = rbxHooks[formattedKey] + + if existingHook then + if existingHook.method == method then + return + end + + existingHook.connection:Disconnect() + + rbxHooks[formattedKey] = createChangeHook(rbx, key, method) + end + else + rbxHooks = {} + rbxHooks[formattedKey] = createChangeHook(rbx, key, method) + + self._hookCache[rbx] = rbxHooks + end +end + function SingleEventManager:disconnect(rbx, key) local rbxHooks = self._hookCache[rbx] @@ -85,6 +124,10 @@ function SingleEventManager:disconnect(rbx, key) end end +function SingleEventManager:disconnectProperty(rbx, key) + self:disconnect(rbx, formatChangeKey(key)) +end + function SingleEventManager:disconnectAll(rbx) local rbxHooks = self._hookCache[rbx] @@ -99,4 +142,4 @@ function SingleEventManager:disconnectAll(rbx) self._hookCache[rbx] = nil end -return SingleEventManager \ No newline at end of file +return SingleEventManager diff --git a/lib/init.lua b/lib/init.lua index 5afd1693..a5c32ae6 100644 --- a/lib/init.lua +++ b/lib/init.lua @@ -5,6 +5,7 @@ local Component = require(script.Component) local Core = require(script.Core) local Event = require(script.Event) +local Change = require(script.Change) local GlobalConfig = require(script.GlobalConfig) local PureComponent = require(script.PureComponent) local Reconciler = require(script.Reconciler) @@ -37,6 +38,7 @@ apply(Roact, { Component = Component, PureComponent = PureComponent, Event = Event, + Change = Change, }) apply(Roact, { diff --git a/lib/init.spec.lua b/lib/init.spec.lua index 6da40259..ffd698e8 100644 --- a/lib/init.spec.lua +++ b/lib/init.spec.lua @@ -18,6 +18,7 @@ return function() expect(Roact.Portal).to.be.ok() expect(Roact.Children).to.be.ok() expect(Roact.Event).to.be.ok() + expect(Roact.Change).to.be.ok() expect(Roact.Ref).to.be.ok() expect(Roact.None).to.be.ok() end) From 82992d2580318b0b78cb7773be8df21948ba5c31 Mon Sep 17 00:00:00 2001 From: AmaranthineCodices Date: Sat, 17 Mar 2018 15:22:23 -0400 Subject: [PATCH 2/8] update lemur dependency --- modules/lemur | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lemur b/modules/lemur index e4c3f136..a0f18290 160000 --- a/modules/lemur +++ b/modules/lemur @@ -1 +1 @@ -Subproject commit e4c3f1361cbccc6477e7066af650ade8c9aac954 +Subproject commit a0f18290102327c8530b49b3eded39353cea615d From 83cf6b042274577abf2584f53e5e0188735a96a8 Mon Sep 17 00:00:00 2001 From: AmaranthineCodices Date: Sat, 17 Mar 2018 15:48:18 -0400 Subject: [PATCH 3/8] fix an edge case --- lib/SingleEventManager.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/SingleEventManager.lua b/lib/SingleEventManager.lua index 1b8f8bb1..208e885a 100644 --- a/lib/SingleEventManager.lua +++ b/lib/SingleEventManager.lua @@ -92,9 +92,9 @@ function SingleEventManager:connectProperty(rbx, key, method) end existingHook.connection:Disconnect() - - rbxHooks[formattedKey] = createChangeHook(rbx, key, method) end + + rbxHooks[formattedKey] = createChangeHook(rbx, key, method) else rbxHooks = {} rbxHooks[formattedKey] = createChangeHook(rbx, key, method) From fd1c553f2a0f7e9e92fb666c7000184246ab44d3 Mon Sep 17 00:00:00 2001 From: AmaranthineCodices Date: Sat, 17 Mar 2018 15:49:35 -0400 Subject: [PATCH 4/8] test cases! --- lib/SingleEventManager.spec.lua | 86 +++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/lib/SingleEventManager.spec.lua b/lib/SingleEventManager.spec.lua index 5867e405..9b849919 100644 --- a/lib/SingleEventManager.spec.lua +++ b/lib/SingleEventManager.spec.lua @@ -83,6 +83,57 @@ return function() end) end) + describe("connectProperty", function() + it("should connect to property changes", function() + local target = Instance.new("BindableEvent") + local manager = SingleEventManager.new() + + local changeCount = 0 + + manager:connectProperty(target, "Name", function(rbx) + changeCount = changeCount + 1 + end) + + target.Name = "hi" + expect(changeCount).to.equal(1) + end) + + it("should disconnect the existing connection if present", function() + local target = Instance.new("IntValue") + local manager = SingleEventManager.new() + + local changeCountA = 0 + local changeCountB = 0 + + manager:connectProperty(target, "Name", function(rbx) + changeCountA = changeCountA + 1 + end) + + manager:connectProperty(target, "Name", function(rbx) + changeCountB = changeCountB + 1 + end) + + target.Name = "hi" + expect(changeCountA).to.equal(0) + expect(changeCountB).to.equal(1) + end) + + it("should only connect to the property specified", function() + local target = Instance.new("IntValue") + local manager = SingleEventManager.new() + + local changeCount = 0 + + manager:connectProperty(target, "Name", function(rbx) + changeCount = changeCount + 1 + end) + + target.Name = "hi" + target.Value = 0 + expect(changeCount).to.equal(1) + end) + end) + describe("disconnect", function() it("should disconnect handlers on an object", function() local target = Instance.new("BindableEvent") @@ -146,6 +197,33 @@ return function() end) end) + describe("disconnectProperty", function() + it("should disconnect property change handlers on an object", function() + local target = Instance.new("IntValue") + local manager = SingleEventManager.new() + + local changeCount = 0 + + manager:connectProperty(target, "Name", function(rbx) + changeCount = changeCount + 1 + end) + + target.Name = "hi" + expect(changeCount).to.equal(1) + + manager:disconnectProperty(target, "Name") + target.Name = "test" + expect(changeCount).to.equal(1) + end) + + it("should succeed even if no handler is attached", function() + local target = Instance.new("IntValue") + local manager = SingleEventManager.new() + + manager:disconnectProperty(target, "Name") + end) + end) + describe("disconnectAll", function() it("should disconnect all listeners on an object", function() local target = Instance.new("BindableEvent") @@ -153,6 +231,7 @@ return function() local callCountEvent = 0 local callCountChanged = 0 + local changeCount = 0 manager:connect(target, "Event", function(rbx) expect(rbx).to.equal(target) @@ -164,11 +243,17 @@ return function() callCountChanged = callCountChanged + 1 end) + manager:connectProperty(target, "Name", function(rbx) + expect(rbx).to.equal(target) + changeCount = changeCount + 1 + end) + target:Fire() target.Name = "bar" expect(callCountEvent).to.equal(1) expect(callCountChanged).to.equal(1) + expect(changeCount).to.equal(1) manager:disconnectAll(target) @@ -177,6 +262,7 @@ return function() expect(callCountEvent).to.equal(1) expect(callCountChanged).to.equal(1) + expect(changeCount).to.equal(1) end) it("should succeed with no events attached", function() From 9ccf594491c7d0ca6182f86ad3f9d00b99b2854b Mon Sep 17 00:00:00 2001 From: AmaranthineCodices Date: Sun, 18 Mar 2018 08:56:41 -0400 Subject: [PATCH 5/8] switch type to Change --- lib/Change.lua | 2 +- lib/Reconciler.lua | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Change.lua b/lib/Change.lua index a38ac317..bd2e4354 100644 --- a/lib/Change.lua +++ b/lib/Change.lua @@ -9,7 +9,7 @@ local changeMetatable = { setmetatable(Change, { __index = function(self, propertyName) local changeListener = { - type = "propertyChange", + type = Change, name = propertyName } diff --git a/lib/Reconciler.lua b/lib/Reconciler.lua index 92044d51..c0eae7c5 100644 --- a/lib/Reconciler.lua +++ b/lib/Reconciler.lua @@ -24,6 +24,7 @@ local Core = require(script.Parent.Core) local Event = require(script.Parent.Event) +local Change = require(script.Parent.Change) local getDefaultPropertyValue = require(script.Parent.getDefaultPropertyValue) local SingleEventManager = require(script.Parent.SingleEventManager) local Symbol = require(script.Parent.Symbol) @@ -512,7 +513,7 @@ function Reconciler._setRbxProp(rbx, key, value, element) if key.type == Event then Reconciler._singleEventManager:connect(rbx, key.name, value) - elseif key.type == "propertyChange" then + elseif key.type == Change then Reconciler._singleEventManager:connectProperty(rbx, key.name, value) else local source = element.source or DEFAULT_SOURCE From 5984955ec05851d5c1779b0b16fa8143d46a1257 Mon Sep 17 00:00:00 2001 From: AmaranthineCodices Date: Fri, 23 Mar 2018 20:36:58 -0400 Subject: [PATCH 6/8] update lemur --- modules/lemur | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lemur b/modules/lemur index a0f18290..4c292180 160000 --- a/modules/lemur +++ b/modules/lemur @@ -1 +1 @@ -Subproject commit a0f18290102327c8530b49b3eded39353cea615d +Subproject commit 4c29218057ff24d6a8964d798469ebc991a16f4c From 1455e60297eec112e053aa5dd3f3e58cdfe4a62e Mon Sep 17 00:00:00 2001 From: AmaranthineCodices Date: Sat, 24 Mar 2018 19:44:34 -0400 Subject: [PATCH 7/8] will this fix the merge conflict? --- modules/lemur | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lemur b/modules/lemur index 4c292180..67558cbd 160000 --- a/modules/lemur +++ b/modules/lemur @@ -1 +1 @@ -Subproject commit 4c29218057ff24d6a8964d798469ebc991a16f4c +Subproject commit 67558cbd7b06c9b2a1448f160d4b4520b2c0253d From 42e2415d703066c1fa0904ce1a7c1e81fe09f4ee Mon Sep 17 00:00:00 2001 From: AmaranthineCodices Date: Sat, 24 Mar 2018 20:03:55 -0400 Subject: [PATCH 8/8] fix lemur again --- modules/lemur | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lemur b/modules/lemur index 67558cbd..1279dc60 160000 --- a/modules/lemur +++ b/modules/lemur @@ -1 +1 @@ -Subproject commit 67558cbd7b06c9b2a1448f160d4b4520b2c0253d +Subproject commit 1279dc60c676448e021ac12cfb4d95866917b74a