@lvce-editor/server 0.116.12 → 0.116.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@ This project incorporates components from the projects listed below, that may ha
2
2
  differing from this project:
3
3
 
4
4
 
5
- 1) License Notice for static/0517e85/icons (from https://github.com/microsoft/vscode-codicons)
5
+ 1) License Notice for static/e271222/icons (from https://github.com/microsoft/vscode-codicons)
6
6
  ---------------------------------------
7
7
 
8
8
  Attribution 4.0 International
@@ -402,7 +402,7 @@ public licenses.
402
402
  Creative Commons may be contacted at creativecommons.org.
403
403
 
404
404
 
405
- 2) License Notice for static/0517e85/fonts/FiraCode-VariableFont.ttf (from https://github.com/tonsky/FiraCode)
405
+ 2) License Notice for static/e271222/fonts/FiraCode-VariableFont.ttf (from https://github.com/tonsky/FiraCode)
406
406
  ---------------------------------------
407
407
 
408
408
  Copyright (c) 2014, The Fira Code Project Authors (https://github.com/tonsky/FiraCode)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/server",
3
- "version": "0.116.12",
3
+ "version": "0.116.14",
4
4
  "description": "Run LVCE Editor as a server.",
5
5
  "main": "index.js",
6
6
  "bin": "bin/server.js",
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@lvce-editor/jsonc-parser": "^1.5.2",
24
- "@lvce-editor/shared-process": "0.116.12",
25
- "@lvce-editor/static-server": "0.116.12"
24
+ "@lvce-editor/shared-process": "0.116.14",
25
+ "@lvce-editor/static-server": "0.116.14"
26
26
  }
27
27
  }
@@ -0,0 +1,16 @@
1
+ export const sendSocket = (childProcess, message, socket) => {
2
+ socket.pause()
3
+ const handle = socket._handle
4
+ if (handle) {
5
+ // pause() stops stream delivery, but can leave the native read active.
6
+ // send() discards reads on the parent's handle until the child acknowledges
7
+ // the transfer, so stop that read before the peer can send its first frame.
8
+ const status = handle.readStop()
9
+ if (status !== 0) {
10
+ socket.destroy()
11
+ throw new Error(`Unable to stop socket reads before transfer (${status})`)
12
+ }
13
+ handle.reading = false
14
+ }
15
+ childProcess.send(message, socket, { keepOpen: false })
16
+ }
package/src/server.js CHANGED
@@ -7,6 +7,7 @@ import { fileURLToPath } from 'node:url'
7
7
  import { Worker } from 'node:worker_threads'
8
8
  import * as ArgvConfig from './argvConfig.js'
9
9
  import { getRemoteSshOptions, isAuthenticatedRemoteRequest } from './remoteSshOptions.js'
10
+ import { sendSocket } from './sendSocket.js'
10
11
 
11
12
  const __dirname = dirname(fileURLToPath(import.meta.url))
12
13
  const ROOT = resolve(__dirname, '../')
@@ -77,7 +78,7 @@ const isStatic = (url) => {
77
78
  if (url === '/index.html' || url.startsWith('/index.html?')) {
78
79
  return !hasLinkedExtensions
79
80
  }
80
- if (url.startsWith('/0517e85')) {
81
+ if (url.startsWith('/e271222')) {
81
82
  return true
82
83
  }
83
84
  if (url.startsWith('/favicon.ico')) {
@@ -284,16 +285,14 @@ const sendHandleSharedProcess = async (request, socket, method, ...params) => {
284
285
  }
285
286
  socket.on('error', handleSocketError)
286
287
  const sharedProcess = await getOrCreateSharedProcess()
287
- sharedProcess.send(
288
+ sendSocket(
289
+ sharedProcess,
288
290
  {
289
291
  jsonrpc: '2.0',
290
292
  method,
291
293
  params: [getHandleMessage(request), ...params],
292
294
  },
293
295
  socket,
294
- {
295
- keepOpen: false,
296
- },
297
296
  )
298
297
  }
299
298
 
@@ -0,0 +1,25 @@
1
+ // Delay the handoff acknowledgement so the sender still owns a native handle
2
+ // when the peer sends its first request.
3
+ const send = process._send
4
+ process._send = function (message, ...args) {
5
+ if (message?.cmd === 'NODE_HANDLE_ACK') {
6
+ setTimeout(() => send.call(this, message, ...args), 200)
7
+ return true
8
+ }
9
+ return send.call(this, message, ...args)
10
+ }
11
+
12
+ process.on('message', (_message, socket) => {
13
+ socket.pause()
14
+ socket._handle.readStop()
15
+ socket._handle.reading = false
16
+ socket.write('ready\n')
17
+ // Keep the receiver from winning the competing read while the sender's
18
+ // handle is waiting for its acknowledgement.
19
+ setTimeout(() => {
20
+ socket.on('data', (data) => socket.end(data))
21
+ socket._handle.readStart()
22
+ socket._handle.reading = true
23
+ socket.resume()
24
+ }, 100)
25
+ })
@@ -0,0 +1,23 @@
1
+ import assert from 'node:assert/strict'
2
+ import { fork } from 'node:child_process'
3
+ import { once } from 'node:events'
4
+ import { createConnection, createServer } from 'node:net'
5
+ import test from 'node:test'
6
+ import { sendSocket } from '../src/sendSocket.js'
7
+
8
+ test('preserves the first request while the child has not acknowledged the socket handoff', { timeout: 10000 }, async (context) => {
9
+ const child = fork(new URL('./fixtures/socket-transfer-child.js', import.meta.url))
10
+ context.after(() => child.kill())
11
+ const server = createServer((socket) => sendSocket(child, { type: 'socket' }, socket))
12
+ context.after(() => server.close())
13
+ server.listen(0, '127.0.0.1')
14
+ await once(server, 'listening')
15
+ const client = createConnection(server.address().port, '127.0.0.1')
16
+ context.after(() => client.destroy())
17
+ const [ready] = await once(client, 'data')
18
+ assert.equal(ready.toString(), 'ready\n')
19
+ const response = once(client, 'data', { signal: AbortSignal.timeout(5000) })
20
+ client.write('first request')
21
+ const [data] = await response
22
+ assert.equal(data.toString(), 'first request')
23
+ })