waterbang / android-deno-runtime-example

bfs base runtime app for modern os
Apache License 2.0
1 stars 0 forks source link

## Plaoc(BFS) #1

Open waterbang opened 2 years ago

waterbang commented 2 years ago

Plaoc(BFS)

赋能给 ts/js 的一个 runtime

对标 nodejs( tcp/udp)/deno(http1/2) appliction

操作系统级别 D:/ /user/root

底层网络是 bnrtc(golang=webrtc+udp)->websocket->js-controller

文件系统:(未定)/sys/ /user/address

GUI/TUI: (Webview=>http/https) => DWebview

nodejs

import { http } from "http";
http.createServer(staticDir("./www")).listen(8080);
import { Webview } from "@microsoft/webview2";
new Webview("http://localhost:8080");

v8 nodejs deno https://deno.land/x@0.0.1

bfs

import { bnrtc } from "node:bnrtc";
import { DWebServer } from "@bnrtc/dweb";
const dwebserver = new DWebServer({ publicKey, privateKey }).listen("dport");

import { Webview } from "@microsoft/webview2";
import { Webview } from "@android/webiew";
new Webview(dwebserver.resolveUrl()); // http://haahshsahashshshahssa.localhost:128920/

class AppRuntime {
  constructor(app_root: string) {
    const worker = new Worker("");
    worker.module_loader = {
      linker(spe) {
        if (spe === "node:bnrtc") {
          return new ScriptModule(code, "node:bnrtc");
        }
        if (spe.startsWith("./")) {
          return new FileModule(new URL(spe, app_root));
        }
        if (spe === "dwebview") {
          return DWebviewModule;
        }
      },
    };
    worker.injectFFI({
      op_fs_read: (path) => {
        fs.read(new URL(path, app_root));
      },
    });
  }
}

const app = new AppRuntime();
app.import("./myapp.js");

bfs-gui-application bfs-cmd-application

app_manifest.json
index.bfs.js // 主程序入口

assets
    index.html
    main.js
import { DWebview } from "@bfs/dwebview";
import { writePicture, openUserPictureLib } from "@bfs/media";
const dwebview = new DWebview();
dwebview.url = new URL("./assets/index.html", import.meta.url);
dwebview.statubar.bgcolor = 'transparent'
dwebview.statubar.ftcolor = 'dark'
dwebview.on("request",(req,res)=>{
    if(req.url==='/statubar/bgcolor/set'){
        dwebview.statubar.bgcolor = 'transparent'
        res.end('{success:true}')
    }
    if(req.url==='/picture/pick'){
        openUserPictureLib()
        res.end('{success:true}')
    }
    if(req.url === 'index.html'){
        res.wirte(render(<a>))
    }
});

// 区块链地址 address 就是域名
//
// dweb:localhost.xx
// url重定向 dweb:localhost.xx => http://localhost:98092
// https://app-id.dweb.bfchain.org/ 分享出去的
// https://app-id.bfchain.dweb/ 应用内部的
dwebview.acitive();

openBrl(other_app_id);

// android

java/kotlin -> webview -(java_interface)-> html/js obj-c/swift -> webview -(jsCore-api)-> html/js

deno <-(java_interface)-> java/kotlin -> webview -> html/js '----(http/ws-server)-------> html/js

开发第一里程碑目标

  1. 只支持 Android 开发
  2. 支持 DWebview 运行
    1. 以现有的 “碳链” 做 demo
      • cordova: statusbar/相册读写/权限管理(最好是对开发者屏蔽掉)/通知/启动屏(配置)/二维码扫描/deeplink
      • 保持单页应用(多页引用)
  3. bfs-app 是一个侧重于后端开发的环境
  4. 不开放后端开发,提供默认的 webcomponent

tudo

[] statusbar

[] read/write picture

[] authority management

[] navigation

[] notification

[] Startup screen

[] Qr code scanning

webcompont

shuibang.bfs-app.js

<script src="./shuibang-dweb-sdk.js"/>
<script>
await shuibangDwebSdk.setStatubarBgColor('transaparent')
</script>

<a href='./b.html' target="_blank">

<dweb-plugin>
    <dweb-statubar/>
</dweb-plugin>

 <script>
 $("dweb-statubar").ready().then(apis=>{
    apis.
})
</script>
waterbang commented 2 years ago

第一步deno <-(java_interface)-> java/kotlin 流程需要走通。

deno的runtime作为中间桥梁,提供代替cordova的方法(1.采用直接函数回调。2.采用事件注册。3.如果都不行使用ws)。

由deno去操控,kotlin启动webview(Dwebview)。

waterbang commented 2 years ago

image

waterbang commented 2 years ago
  1. deno里的v8 runtime负责起一个server.js,这个runtime(server.js)类似于nodejs的包,我们是可以根据core来进行动态调度的,暴露给用户的是三种形式:(不包含webView里可以直接用js启动的逻辑,比如:启动一个扫码)。

    • import blockInfo from dweb://blockinfo
    • @method/@rule
    • webComponent
  2. 整个bfs里会有一个core模块(js编写),负责一些系统的调度,api网关层面只是负责拦截,真正的逻辑放到core模块里。

waterbang commented 2 years ago

image

waterbang commented 2 years ago

html/js'<----(http/ws-server)-------> deno <-(java_interface)-> java/kotlin -> webview -> html/js ⬆️ webComponent 负责native的样式封装 import 负责native的系统调用 @rule ➡️ 负责权限 我认为逻辑还是得这样走,而不是直接去跟kotlin交互,如果直接去调kotlin,那么组件将无法封装。

Gaubee:倒也不会“无法封装”。 只是说我们要遵循一个可靠的权限管控原则,那么就不该让 html/js 直接通过 WebView-JavascriptInterface 的这种路径去做这些事情。

waterbang commented 2 years ago

https://github.com/ssrlive/rust_on_android_ios, https://github.com/suve/rust-on-android/

waterbang commented 2 years ago

下一阶段目标,webComponent需要有一层下面这个做限制。

    fetch('./get-ws-port', location.href/* dweb://app.id/index.html */)
    new DWebSocket('dweb://app.id/')

      // link import

      // bfs-app.js
     const dwebview = new DWebView()
     dwebview.onRequest((req,res)=>{
       if(req.url ==='get-ws-port') {
     //nodejs & deno
             // tcp/udp
             // websocket-server
      //bfs-app
           const socketBlob = DWebSocket
          //  const socketBlob = new DwebSocket('dweb://app.id/')
           res.send(socketBlob)
        }

      })
      dwebview.onUpgrade(req,socket)
waterbang commented 2 years ago

关于里程碑和环境隔离的选择,现在是在m2.

    import { Console } from 'bfs:console'
    import { createVM, createWorkerVM } from 'bfs:vm'

    async function linker(s) {
      if (s === '@bfs/console') { 
        return { Console }
      }
    }

    new Worker(block module{
      createVM(linker)
    })

    // block module
    import { Console } from 'bfs:console'

    const x = new Console
    new Worker(module {
      const x = new Console
    })

    // bfs-app.js
    import { } from 'xxxx'

    const webview = new Webview();

    const workerApp = new Worker(module{
      const windows = await webview.getWindows()
      windows.document.body = "asfafsa"
      windows.document.body.height
    });

    deno -> html / js
    deno -> android -> html / js

    m1: android -> html / js // spa
    m2: bfs(close) -> android -> html / js // mpa
    m3: bfs(open) -> android -> html / js // ssr // 面向OO角色编程 分布式节点
    m4: bfs(open) -> pc -> (html / js)?
        bfs -> BNRTC/App(GUI:Web+TUI) (WebGPU+WASM)

    await Webview.useable()?
    await camera.useable("env"|"face")?

    @role("user")
    class UserZZZ {

    }
    -> BNRTC ->

    websocket -> comlink-v2 / (googlechromelab/comlink)
    @JavascriptInterface  null / string / number // -1/0/1->bool
    new WebViewMessageChannel()->secriable js-object // map/set/arraybuffer

    // main.js
    comlink.export({ foo(a, b) { return a + b } }, endpoint)

    // worker.js
    const mainModule = comlink.warp(endpoint);
    const res = await mainModule.foo(1, 1) // get foo, call foo, [1,1]

    // comlink-v2->async/sync
    Atomics.wait / notify / load

    const mainModule = comlink.warp(endpoint);
    const res = mainModule.foo(1, 1) // get foo, call foo, [1,1]
waterbang commented 2 years ago

Gaubee: 经过测试,dweb:// 这种customScheme不能很好地支持fetch。 尝试用blob来替代,效果也不好。 最终只能回归到http(s)的协议上来。

那么只能回归常规的 域名方案来做兼容。

使用dweb作为顶级域名 比如: https://appname.address.dweb/

new DWebView({id/name:"xxx"})
waterbang commented 2 years ago

Gaubee: 双工方案:

  1. 这个wc上面,增加dispatchStringMessage与dispatchBinaryMessage。
  2. fetch CHANNEL_ID.dwebhost/polling ,会将 dwebview.isWaitingData 设置为true,该fetch返回ok信号代表信号传递成功。
  3. 如果 isWatingData 为 true,或者 变成true,deno会通过ffi,让kotlin去执行evaljs 来将数据包通过dweb-plugin的dispatch接口发送数据。

优点: 该方案存在简单的反压机制,只有isWaitingData为true的时候才会发送数据,这样deno可以根据web自身的状况发送必要的包,可以减少数据包的发送,节省不必要的CPU开支

  1. 不依赖websocket接口,更加安全
  2. 等待响应时,不会阻塞渲染进程
  3. 数据包可以进一步切片发送来提升js的碎片时间使用
document.querySelector('dweb-plugin').createChannel('channelid') 
 .postMessage()
 .onMessage 
 .onClose
// 消息不断往返封装为异步迭代器的形式
.[Symbol.asyncIterator]
const justjavac = {
  [Symbol.asyncIterator]: () => {
    const items = [`j`, `u`, `s`, `t`, `j`, `a`, `v`, `a`, `c`];
    return {
      next: () => Promise.resolve({
        done: items.length === 0,
        value: items.shift()
      })
    }
  }
}

组件销毁,自动执行onClose isWaitingData :true 本质上 等于 数字 1. 如果有特殊需求,可以将之设置为 number 类型,这样可以节省消息通讯的次数 要考虑不断往返的情况,onMessagepostMessage

反压:最高水位阈值(hightWaterMark)

https://bmr9vohvtvbvwrs3p4bwgzsmolhtphsvvj.dweb/open https://bmr9vohvtvbvwrs3p4bwgzsmolhtphsvvj.dweb/poll https://bmr9vohvtvbvwrs3p4bwgzsmolhtphsvvj.dweb/channelId

waterbang commented 2 years ago

### 暂时在deno-js 起一个http端口 因为rust_v8 的 v8动态链接库(aarch64-linux-android)在 deno:v1.21.1已经停止编译。 但是 deno_ffistatic function 参数却是在deno:v.1.23.2才更新,因此能力有限无法编译deno_ffifunction参数。 也就导致了流程dwebview-js --fetch--> kotlin --ffi--> rust --ffi--> deno-js 临时改变为 dwebview-js --fetch--> kotlin --http--> deno-js 回来的逻辑是一样的:deno-js --ffi--> kotlin --evaljs--> dwebview-js(dispashByte,dispashString)

https://github.com/denoland/rusty_v8/issues/1043 https://stackoverflow.com/questions/73151160/how-to-learn-writing-a-v8-dynamic-link-library-for-rust-v8

需要自己构建二进制函数接口(ABI)具体如下问题: https://github.com/denoland/rusty_v8/issues/1045

planB: Rust调用C++代码,C++代码调用暴露出来的JavaScript回调方法.

因为在同一内存使用deno.core.opSync,实现零拷贝?