Skip to content

Commit

Permalink
feat: js <=> libuv
Browse files Browse the repository at this point in the history
  • Loading branch information
QinZhen001 committed Apr 4, 2024
1 parent 290c79d commit 0b1b09c
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/pages/node/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ import { CommonPageRouter } from "../main"
import { lazy } from "react"

const Eventloop = lazy(() => import("./event-loop"))
const JSLibuv = lazy(() => import("./js-libuv"))

export const children = [
{
path: "eventloop",
element: <Eventloop></Eventloop>,
title: "简单版Eventloop",
},
{
path: "js-libuv",
element: <JSLibuv></JSLibuv>,
title: "js和libuv通信",
},
]

const NodePage = () => {
Expand Down
15 changes: 15 additions & 0 deletions src/pages/node/js-libuv/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { testJsTcpOperate } from "./src"

const JSLibuv = () => {
const onClick = () => {
testJsTcpOperate()
}

return (
<div>
<button onClick={onClick}>testJsTcpOperate</button>
</div>
)
}

export default JSLibuv
119 changes: 119 additions & 0 deletions src/pages/node/js-libuv/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,122 @@
// JS 和 C、C++ 层的通信,Node.js 很多功能都是由 C、C++ 实现,然后暴露到 JS 层使用的,
// 所以当我们调用 JS 代码时,就会进入 C++ 层,接着 C++ 层会进入 Libuv 的 C 层,
// 等到 Libuv 完成操作后就会回调 C++ 代码,最终 C++ 代码再回调 JS 层。

// 操作系统
let fd = 0
function socket() {
return ++fd
}
function connect(fd, addr, port, req) {
return new Promise((resolve) => {
// 模拟
setTimeout(() => {
resolve(0)
}, 3000)
})
}

// Libuv层 (C)
async function uv_tcp_connect(req, handle, addr, port, cb) {
console.log("Libuv: uv_tcp_connect", req, handle, addr, port, cb)
handle.fd = socket()
req.handle = handle
req.cb = cb
const status = await connect(handle.fd, addr, port)
req.cb(req, status)
}

// C++层
class ConnectWrap {
uv_connect_t = {}

constructor(object) {
console.log("C++: ConnectWrap constructor", object)
object[0] = this
this.object = object
}

Dispatch(fn, ...args) {
this.uv_connect_t.data = this
fn(this.uv_connect_t, ...args)
}

MakeCallback(key, ...args) {
this.object[key](...args)
}
}

class TCPWrap {
uv_tcp_t = {}

constructor() {
this.uv_tcp_t.data = this
}

static Connect(req, addr, port) {
const tcpWrap = this[0]
const connectWrap = new ConnectWrap(req)
connectWrap.Dispatch(uv_tcp_connect, tcpWrap.uv_tcp_t, addr, port, (req, status) => {
console.log("C++: connect callback", req, status)
const connectWrap = req.data
const tcpWrap = req.handle.data
connectWrap.MakeCallback("oncomplete", tcpWrap, connectWrap, status)
})
}
}

function FunctionTemplate(cb) {
const map = {}

function Tmp() {
Object.assign(this, map)
cb && cb(this)
}

return {
PrototypeTemplate() {
return {
set(k, v) {
Tmp.prototype[k] = v
},
}
},
InstanceTemplate() {
return {
set(k, v) {
map[k] = v
},
}
},
GetFunction() {
return Tmp
},
}
}

const TCPFunctionTemplate = FunctionTemplate((target) => {
target[0] = new TCPWrap()
})
TCPFunctionTemplate.PrototypeTemplate().set("connect", TCPWrap.Connect)
TCPFunctionTemplate.InstanceTemplate().set("name", "hi")
const TCP = TCPFunctionTemplate.GetFunction()

const TCPConnectWrapFunctionTemplate = FunctionTemplate()
const TCPConnectWrap = TCPConnectWrapFunctionTemplate.GetFunction()

// JS层
export const testJsTcpOperate = () => {
// 模拟
const tcp = new TCP()
const req = new TCPConnectWrap()
console.log("tcp", tcp)
console.log("req", req)
const address = "127.0.0.1"
const port = 80
req.oncomplete = () => {
console.log("js: tcp connect success")
}
req.address = address
req.port = port
tcp.connect(req, address, port)
}

0 comments on commit 0b1b09c

Please sign in to comment.