BioforestChain / dweb_browser

BioforestChain Infrastructure
https://docs.dweb-browser.org
MIT License
21 stars 5 forks source link

【讨论】动态内核模块 cmm.browser.dweb+core.std.dweb #222

Open Gaubee opened 2 months ago

Gaubee commented 2 months ago

随着应用内核越发丰富,同时我们又希望 dweb 本身保持简约

  1. 以 jmm 的安装不同,内核模块是无需用户授权,可以静默安装,前提是发行方在可信列表中。默认可信列表中只有 dweb 官方的签名,但允许用户自行配置第三方仓库
    1. cmm 本质上和 npm、cargo、jsr 这类中心化的仓库类似,都属于面向开发者的仓库
    2. 使用 dweb 的去中心特性,开发者可以在本地注册一个专门面向开发者的仓库,比如:dev.***.dweb,然后将这个域名注册成仓库,从而进行开发
  2. cmm 安装的模块不允许 application,但是 cmm 内置了介绍页、设置页面的入口,开发可以通过配置文件自动生成配置界面。用户或者开发者可以在介绍页了解这个模块,在配置页面对模块进行一些设置(类似 vscode 的插件 json 的可视化配置界面)
  3. 与 jmm 类似,内核模块的能力默认不是 native 级别的,而是 sandbox 级别的
    1. 也就是说它目前顶多还是使用 js/wasm + ipc 来做实现
    2. 其它的动态特性,还需要对应模块开放动态编程的能力

      这种统称为 worklet,就是不走 ipc 来做接口编程,因为性能损耗很大,而是直接将脚本发送给对应模块,对应模块在 js-vm 中注入接口,然后运行动态脚本,从而避免 ipc 对通讯损耗。 未来我们会开放 js-vm/wasm-vm 接口,让模块可以自定义自己的 vm

    3. 但在一些特定的平台上,也许可以允许使用 native 级别来实现,比方说 desktop/android 都允许动态链接库。但考虑到跨平台的实现,还是要谨慎考虑和讨论

      未来也许可以通过内置一些 wasi-runtime 来做到动态链接库对 ios 的兼容,wasi 并不能做到 native 的性能,甚至会比 jsCore 的性能还要差,只是说一些编译的需要

  4. 内核模块可以让 dweb 功能越发丰富的同时,保持 dweb 本身的精简高效
  5. 内核模块的关键作用在于为其它模块提供一些共享的能力,比方说“标准库”或者“官方库”,从而减少 jmm 本身的应用体积,同时减少内存的占用

    1. 标准库的使用实例一:使用原始的 ipc 通讯

      /// by fetch
      const hashId = fetch(
      "file://crypto.std.dweb/createHash?type=sha256"
      ).number();
      await fetch(`file://crypto.std.dweb/Hash/update?id=${hashId}`, {
      body: "some data",
      });
      const hex = await fetch(
      `file://crypto.std.dweb/Hash/digest?id=${hashId}&type=hex`
      ).string();
    2. 标准库的使用实例二:使用 js 的 Reflex+Proxy 进行抽象的通讯

      抽象通讯可以不走表面 ipc,可以走 js-sandbox 之间的原生通讯(MessageChannel)来做加速,性能会很好,同时还能做到异步转同步

      /// by atomic+sharedArrayBuffer+messagePort
      import crypto from "https://core.std.dweb/crypto"; // 简化成 dweb:crypto?
      const hash = crypto.createHash("sha256");
      hash.update("some data");
      const hex = hash.digest("hex");
    3. 官方库的使用实例:

      import window from "https://core.std.dweb/window";
      import { Webview } from "https://core.std.dweb/ui";
      import node from "https://core.std.dweb/node";
      console.log(node.versions); // eg: {node:"18.16.3",fs:"1.1.0",buffer:"5.2.6"}
      node.spawn(import.meta.resolve("./server/index.js"));
      node.on("server-ready", async (port, url) => {
      console.log("node server bind to port", port);
      const webview = new Webview({ bootstrapUrl: url });
      await window.mainWindow.add(webview, {
        x: 0,
        y: 0,
        width: "100%",
        height: "100%",
      });
      });
waterbang commented 2 months ago

暴露内核

当前的架构看似模块分离,实则还是一个整体。因为其他kmp应用当前并无法简单的调用我们的模块。 因此我们需要把内核暴露出来,并且让其他kmp应用可以选择性的调用模块。

为了保持足够简单,并且遵循模块标准,用户开发的时候可以直接使用模块功能。

比如:

implementation({ group = "org.dweb", name = "core", version.ref = "std-dns" })
implementation({ group = "org.dweb", name = "core", version.ref = "browser-scan" })
import org.dweb.core.std.dns.nativeFetch

fun scanning() {
    const response = nativeFetch("file://scan.browser.dweb/open")
}
// 当用户这样调用的时候,整个app将是一个模块。

或者采用自定义模块。

import org.dweb.core.module.NativeMicroModule

class TestNMM : NativeMicroModule("test.browser.dweb", "test module") { 
  // 实现dweb能力...
}

// 提供给外部调用
val testNMM =TestNMM().setup()
Gaubee commented 2 months ago

我们还得提供一个默认的window.std.dweb模块的实现,目前我们的window.std.dweb是由desk.browser.dweb来提供。 这是一个多窗口的平台。 而对于第三方应用,它们更多的是用于单个应用,所以不需要多窗口的模式。但不排除一些modal的需求,比如alert、sheet,这部分window.std.dweb中也有相关的定义。