dsh-ris-ide 0.0.0-stage → 1.6.8
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.
- package/LICENSE +21 -0
- package/README.md +123 -2
- package/bin/run-with-log.ps1 +173 -0
- package/bin/run-with-log.sh +136 -0
- package/cordis.patch.yml +25 -0
- package/lib/client-codemirror.js +29822 -0
- package/lib/client.js +10772 -0
- package/lib/debug/engine.js +537 -0
- package/lib/debug/vendor/LICENSE +21 -0
- package/lib/debug/vendor/README.md +36 -0
- package/lib/debug/vendor/UPSTREAM_COMMIT +1 -0
- package/lib/debug/vendor/jdwp/client.js +1104 -0
- package/lib/debug/vendor/jdwp/constants.js +309 -0
- package/lib/debug/vendor/jdwp/protocol.js +253 -0
- package/lib/debug/vendor/src/jdwp/client.ts +1368 -0
- package/lib/debug/vendor/src/jdwp/constants.ts +310 -0
- package/lib/debug/vendor/src/jdwp/protocol.ts +326 -0
- package/lib/index.js +6112 -0
- package/lib/standalone/vendor/react-dom.js +267 -0
- package/lib/standalone/vendor/react.js +31 -0
- package/lib/standalone/window.html +248 -0
- package/package.json +96 -4
- package/skills/dsh-ris-ide-debug/SKILL.md +158 -0
- package/test/client-viewer.test.mjs +3557 -0
- package/test/debug-engine.test.mjs +351 -0
- package/test/harness.test.mjs +93 -0
- package/test/host-nogit.test.mjs +48 -0
- package/test/host-tail.test.mjs +2846 -0
- package/test/host-window.test.mjs +119 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The standalone window routes: one self-contained page that does NOT boot the
|
|
3
|
+
* DSH frontend. The page loads this plugin's OWN browser half plus a vendored
|
|
4
|
+
* React, so the window carries no session, no conversation and no other plugin
|
|
5
|
+
* bundle — the whole point of keeping it open all day.
|
|
6
|
+
*
|
|
7
|
+
* Same harness style as host-tail.test.mjs: a real node:http listener over
|
|
8
|
+
* `handleRequest`, so the browser's actual requests are what is asserted.
|
|
9
|
+
*/
|
|
10
|
+
import { test } from 'node:test'
|
|
11
|
+
import assert from 'node:assert/strict'
|
|
12
|
+
import { createServer, request as httpRequest } from 'node:http'
|
|
13
|
+
|
|
14
|
+
import { __test } from '../lib/index.js'
|
|
15
|
+
|
|
16
|
+
const { handleRequest, WINDOW_PAGE_PATH, WINDOW_APP_PATH, WINDOW_VENDOR_PREFIX } = __test
|
|
17
|
+
|
|
18
|
+
/** Serve `handleRequest` on a loopback port and return its base URL. */
|
|
19
|
+
async function startHost() {
|
|
20
|
+
const server = createServer((req, res) => {
|
|
21
|
+
handleRequest({}, req, res, {})
|
|
22
|
+
})
|
|
23
|
+
await new Promise((done) => server.listen(0, '127.0.0.1', done))
|
|
24
|
+
const address = server.address()
|
|
25
|
+
return {
|
|
26
|
+
base: `http://127.0.0.1:${address.port}`,
|
|
27
|
+
close: () => new Promise((done) => server.close(done)),
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** One request; resolves with status, headers and the body as a string. */
|
|
32
|
+
function request(base, path, options = {}) {
|
|
33
|
+
return new Promise((done, fail) => {
|
|
34
|
+
const req = httpRequest(`${base}${path}`, { method: options.method ?? 'GET' }, (res) => {
|
|
35
|
+
const chunks = []
|
|
36
|
+
res.on('data', (chunk) => chunks.push(chunk))
|
|
37
|
+
res.on('end', () => done({
|
|
38
|
+
status: res.statusCode,
|
|
39
|
+
headers: res.headers,
|
|
40
|
+
body: Buffer.concat(chunks).toString('utf8'),
|
|
41
|
+
}))
|
|
42
|
+
})
|
|
43
|
+
req.on('error', fail)
|
|
44
|
+
req.end()
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
test('the standalone window page is a self-contained HTML document', async () => {
|
|
49
|
+
const host = await startHost()
|
|
50
|
+
try {
|
|
51
|
+
const page = await request(host.base, WINDOW_PAGE_PATH)
|
|
52
|
+
assert.equal(page.status, 200)
|
|
53
|
+
assert.match(page.headers['content-type'], /text\/html/)
|
|
54
|
+
// Root base: every `/dsh-ris-ide/*` fetch from the panel then lands on the
|
|
55
|
+
// same origin/port the DSH page uses (same cookie, no proxy, no new server).
|
|
56
|
+
assert.match(page.body, /<base href="\/"/)
|
|
57
|
+
// Vendored React first, then the plugin's own browser half, then the boot.
|
|
58
|
+
const vendorAt = page.body.indexOf('window/vendor/react.js')
|
|
59
|
+
const appAt = page.body.indexOf('window/app.js')
|
|
60
|
+
assert.ok(vendorAt > 0, 'the page loads the vendored React')
|
|
61
|
+
assert.ok(appAt > vendorAt, 'the browser half loads after React')
|
|
62
|
+
assert.match(page.body, /__ModuleLoader__/, 'the page shims the module loader')
|
|
63
|
+
assert.match(page.body, /mountStandalone/, 'and calls the standalone mount entry')
|
|
64
|
+
// Script-opened windows may size themselves: the page fills the work area so
|
|
65
|
+
// the IDE opens "maximized" even when the opener size is clamped.
|
|
66
|
+
assert.match(page.body, /window\.moveTo\(0, 0\)/, 'the page repositions itself to the screen origin')
|
|
67
|
+
assert.match(page.body, /window\.resizeTo\(window\.screen\.availWidth, window\.screen\.availHeight\)/, 'and fills the work area')
|
|
68
|
+
} finally {
|
|
69
|
+
await host.close()
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('the window app route serves the same hand-written client half', async () => {
|
|
74
|
+
const host = await startHost()
|
|
75
|
+
try {
|
|
76
|
+
const app = await request(host.base, WINDOW_APP_PATH)
|
|
77
|
+
assert.equal(app.status, 200)
|
|
78
|
+
assert.match(app.headers['content-type'], /text\/javascript/)
|
|
79
|
+
assert.match(app.headers['cache-control'], /no-cache/)
|
|
80
|
+
assert.match(app.body, /window\.__ModuleLoader__\.load/)
|
|
81
|
+
assert.match(app.body, /exports\.mountStandalone = /, 'the mount entry ships in the bundle')
|
|
82
|
+
} finally {
|
|
83
|
+
await host.close()
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('the vendored React UMD files are served under the vendor prefix', async () => {
|
|
88
|
+
const host = await startHost()
|
|
89
|
+
try {
|
|
90
|
+
const react = await request(host.base, `${WINDOW_VENDOR_PREFIX}react.js`)
|
|
91
|
+
assert.equal(react.status, 200)
|
|
92
|
+
assert.match(react.headers['content-type'], /text\/javascript/)
|
|
93
|
+
assert.ok(react.body.length > 5000, 'the real UMD build, not a stub')
|
|
94
|
+
assert.match(react.body, /createElement/)
|
|
95
|
+
|
|
96
|
+
const reactDom = await request(host.base, `${WINDOW_VENDOR_PREFIX}react-dom.js`)
|
|
97
|
+
assert.equal(reactDom.status, 200)
|
|
98
|
+
assert.ok(reactDom.body.length > 100000, 'react-dom UMD with the client entry')
|
|
99
|
+
assert.match(reactDom.body, /createRoot/)
|
|
100
|
+
} finally {
|
|
101
|
+
await host.close()
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
test('unknown vendor assets and non-GET window requests are refused', async () => {
|
|
106
|
+
const host = await startHost()
|
|
107
|
+
try {
|
|
108
|
+
const unknown = await request(host.base, `${WINDOW_VENDOR_PREFIX}../client.js`)
|
|
109
|
+
assert.equal(unknown.status, 404, 'only the two mapped names are servable')
|
|
110
|
+
|
|
111
|
+
const missing = await request(host.base, `${WINDOW_VENDOR_PREFIX}lodash.js`)
|
|
112
|
+
assert.equal(missing.status, 404)
|
|
113
|
+
|
|
114
|
+
const post = await request(host.base, WINDOW_PAGE_PATH, { method: 'POST' })
|
|
115
|
+
assert.equal(post.status, 405)
|
|
116
|
+
} finally {
|
|
117
|
+
await host.close()
|
|
118
|
+
}
|
|
119
|
+
})
|