插件树就是 effect 树

子插件是父 fiber 的一个 effect;服务内部创建的资源,归属被改写到调用方名下

插件树就是 effect 树 子插件是父 fiber 的一个 effect;服务内部创建的资源,归属被改写到调用方名下 root Context · 四个内置服务,引导完就清空自己的 disposer · Architecture component · 不可卸载 root Context 四个内置服务,引导完就清空自己的 disposer 不可卸载 某个 Service · 被 A 注入,比如 ctx.timer · Architecture component · provide 注册 某个 Service 被 A 注入,比如 ctx.timer provide 注册 插件 A 的 Fiber · disposer 列表:监听器 · 定时器 · 子插件 · Architecture component · ctx.plugin() 插件 A 的 Fiber disposer 列表:监听器 · 定时器 · 子插件 ctx.plugin() 服务里建出来的资源 · setInterval · 事件监听 · Architecture component · this.ctx.effect() 服务里建出来的资源 setInterval · 事件监听 this.ctx.effect() 插件 B 的 Fiber · 在 A 的上下文里装的子插件 · Architecture component · A 的一个 effect 插件 B 的 Fiber 在 A 的上下文里装的子插件 A 的一个 effect 装插件 子插件即父 fiber 的一项 effect ctx.timer.interval() 归属改写到调用方 Legend Fiber 服务内部创建的资源 服务 根上下文

一棵树,不是两棵

  • • 子插件的整个生命周期,注册成父 fiber 上的一个 effect
  • • 父 fiber 卸载时逆序跑完 disposer,子插件跟着倒下
  • • 所以没有单独一段遍历插件树做卸载的代码

归属由代理决定

  • • 插件 A 拿到的服务是一层代理,代理把服务里的 this.ctx 换成 A 的上下文
  • • 于是服务内部建的定时器和监听器,记在 A 名下,A 卸载就一起清
  • • 服务因此不需要提供 unregister,也不需要知道谁调了它

空间上的三层可变

  • • 上下文靠原型链继承,扩展一层只是 Object.create 加几个属性
  • • 隔离用 symbol 给服务名分命名空间,两个域各自提供同名服务,互相看不见
  • • 拦截配置沿同一条链向下合并,任意一层都能改写下游服务的行为