Skip to content

Commit

Permalink
Merge pull request #84 from omochi/hook-obj
Browse files Browse the repository at this point in the history
InstanceはHook wrapperではなくHook objectを持つ
  • Loading branch information
omochi authored Apr 24, 2024
2 parents 637eff7 + adcaeeb commit c00fbbb
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 48 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ targets += [

let package = Package(
name: "swift-react",
platforms: [.macOS(.v14)],
platforms: [.macOS(.v14), .iOS(.v17)],
products: [
.library(name: "React", targets: ["React"]),
],
Expand Down
17 changes: 6 additions & 11 deletions Sources/React/Hooks/Context/Context.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import SRTCore

@propertyWrapper
public struct Context<Value: ContextValue>: _AnyContextHook {
public struct Context<Value: ContextValue>: _AnyHookWrapper {
public init() {}

public var wrappedValue: Value {
Expand All @@ -16,16 +16,10 @@ public struct Context<Value: ContextValue>: _AnyContextHook {
_object.value = object ?? Object()
}

var valueType: any ContextValue.Type { Value.self }

func setHolder(_ holder: ContextValueHolder?, disposable: (any Disposable)?) {
object.holder = holder
object.disposable = disposable
}

final class Object {
final class Object: _AnyContextHookObject {
init() {}

var valueType: any ContextValue.Type { Value.self }
var disposable: (any Disposable)?
weak var holder: ContextValueHolder?

Expand All @@ -39,7 +33,8 @@ public struct Context<Value: ContextValue>: _AnyContextHook {
}
}

protocol _AnyContextHook: _AnyHookWrapper {
protocol _AnyContextHookObject: AnyObject {
var valueType: any ContextValue.Type { get }
func setHolder(_ holder: ContextValueHolder?, disposable: (any Disposable)?)
var holder: ContextValueHolder? { get set }
var disposable: (any Disposable)? { get set }
}
6 changes: 1 addition & 5 deletions Sources/React/Hooks/Effect.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import SRTCore

@propertyWrapper
public struct Effect: _AnyEffectHook {
public struct Effect: _AnyHookWrapper {
public typealias Setup = () -> Cleanup?
public typealias Cleanup = () -> Void

Expand Down Expand Up @@ -89,7 +89,3 @@ public struct Effect: _AnyEffectHook {
}
}
}

protocol _AnyEffectHook: _AnyHookWrapper {
var effectObject: Effect.Object { get }
}
4 changes: 2 additions & 2 deletions Sources/React/Hooks/Hook.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ public protocol Hook {
}

protocol _AnyHookWrapper: Hook {
associatedtype Object
associatedtype Object: AnyObject

var object: Object { get }
func prepare(object: Object?)
}

extension _AnyHookWrapper {
func _prepareAny(object: Any?) {
func _prepareAny(object: AnyObject?) {
prepare(object: object.map { $0 as! Object })
}
}
5 changes: 1 addition & 4 deletions Sources/React/Hooks/Ref.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import SRTCore

@propertyWrapper
public struct Ref<Value>: _AnyRef {
public struct Ref<Value>: _AnyHookWrapper {
public init() {}

typealias Object = RefObject<Value>
Expand Down Expand Up @@ -31,9 +31,6 @@ public struct Ref<Value>: _AnyRef {
}
}

protocol _AnyRef: _AnyHookWrapper {
}

public final class RefObject<Value>: IdentityHashable {
public init() {}

Expand Down
13 changes: 5 additions & 8 deletions Sources/React/Hooks/State.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import SRTCore

@propertyWrapper
public struct State<Value: Equatable>: _AnyStateHook {
public struct State<Value: Equatable>: _AnyHookWrapper {
public init(wrappedValue: Value) {
self.initialValue = wrappedValue
}
Expand All @@ -21,16 +21,13 @@ public struct State<Value: Equatable>: _AnyStateHook {
_object.value = object ?? Object(value: initialValue)
}

func setDidChange(_ newValue: (() -> Void)?) {
object.didChange = newValue
}

final class Object {
final class Object: _AnyStateHookObject {
init(value: Value) {
self.value = value
}

private var value: Value

var didChange: (() -> Void)?

func getValue() -> Value { value }
Expand All @@ -50,6 +47,6 @@ extension State where Value: ExpressibleByNilLiteral {
}
}

protocol _AnyStateHook: _AnyHookWrapper {
func setDidChange(_ newValue: (() -> Void)?)
protocol _AnyStateHookObject: AnyObject {
var didChange: (() -> Void)? { get set }
}
15 changes: 7 additions & 8 deletions Sources/React/Renderer/Instance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ package final class Instance {
}

weak var owner: VNode?
var hooks: [any _AnyHookWrapper] = []
var hooks: [AnyObject] = []
public var dom: JSNode?
var attributes: Attributes = [:]
var listeners: [String: ListenerBridge] = [:]
var contextValueHolder: ContextValueHolder?
var isDirty: Bool = false

var contextHooks: [any _AnyContextHook] {
hooks.compactMap { $0 as? any _AnyContextHook }
var contextHooks: [any _AnyContextHookObject] {
hooks.compactMap { $0 as? any _AnyContextHookObject }
}

var stateHooks: [any _AnyStateHook] {
hooks.compactMap { $0 as? any _AnyStateHook }
var stateHooks: [any _AnyStateHookObject] {
hooks.compactMap { $0 as? any _AnyStateHookObject }
}

var effectHooks: [any _AnyEffectHook] {
hooks.compactMap { $0 as? any _AnyEffectHook }
var effectHooks: [Effect.Object] {
hooks.compactMap { $0 as? Effect.Object }
}

func renderDOMAttributes(
Expand Down Expand Up @@ -58,7 +58,6 @@ package final class Instance {
) throws {
let dom = try (self.dom?.asHTMLElement()).unwrap("dom.asHTMLElement")

// コピー必要なんだっけ?
for (type, bridge) in Array(self.listeners) {
if bridge.swift != newListeners[type] {
if let js = bridge.js {
Expand Down
19 changes: 10 additions & 9 deletions Sources/React/Renderer/ReactRoot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,12 @@ public final class ReactRoot {
hook._prepareAny(object: nil)
}
} else {
for (new, old) in zip(hooks, instance.hooks) {
new._prepareAny(object: old.object)
for (hook, object) in zip(hooks, instance.hooks) {
hook._prepareAny(object: object)
}
}

instance.hooks = hooks
instance.hooks = hooks.map { $0.object }
}

private func subscribeHooks(instance: Instance) {
Expand All @@ -284,15 +284,16 @@ public final class ReactRoot {

for context in instance.contextHooks {
if let holder = contextValueHolders[ObjectIdentifier(context.valueType)] {
let dsp = holder.emitter.on(handler: updater)
context.setHolder(holder, disposable: dsp)
context.holder = holder
context.disposable = holder.emitter.on(handler: updater)
} else {
context.setHolder(nil, disposable: nil)
context.holder = nil
context.disposable = nil
}
}

for state in instance.stateHooks {
state.setDidChange(updater)
state.didChange = updater
}
}

Expand All @@ -304,7 +305,7 @@ public final class ReactRoot {

private func postRender(instance: Instance) throws {
for effect in instance.effectHooks {
if let task = effect.effectObject.taskIfShouldExecute() {
if let task = effect.taskIfShouldExecute() {
scheduleEffect(task)
}
}
Expand All @@ -314,7 +315,7 @@ public final class ReactRoot {
try instance.dom?.remove()

for effect in instance.effectHooks {
if let task = effect.effectObject.cleanupTask() {
if let task = effect.cleanupTask() {
scheduleEffect(task)
}
}
Expand Down

0 comments on commit c00fbbb

Please sign in to comment.