mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00

PR-URL: https://github.com/nodejs/node/pull/59104 Refs: https://github.com/nodejs/node/issues/59090 Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com> Reviewed-By: Kohei Ueno <kohei.ueno119@gmail.com>
181 lines
7.3 KiB
JavaScript
181 lines
7.3 KiB
JavaScript
// Flags: --inspect=0 --experimental-network-inspection
|
|
'use strict';
|
|
const common = require('../common');
|
|
|
|
common.skipIfInspectorDisabled();
|
|
|
|
const { NodeInstance } = require('../common/inspector-helper');
|
|
const test = require('node:test');
|
|
const assert = require('node:assert');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
|
|
const resourceUrl = 'http://localhost:3000/app.js';
|
|
const resourcePath = path.join(__dirname, '../fixtures/inspector-network-resource/app.js.map');
|
|
|
|
const resourceText = fs.readFileSync(resourcePath, 'utf8');
|
|
const embedPath = resourcePath.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
const script = `
|
|
const { NetworkResources } = require('node:inspector');
|
|
const fs = require('fs');
|
|
NetworkResources.put('${resourceUrl}', fs.readFileSync('${embedPath}', 'utf8'));
|
|
console.log('Network resource loaded:', '${resourceUrl}');
|
|
debugger;
|
|
`;
|
|
|
|
async function setupSessionAndPauseAtEvalLastLine(script) {
|
|
const instance = new NodeInstance([
|
|
'--inspect-wait=0',
|
|
'--experimental-inspector-network-resource',
|
|
], script);
|
|
const session = await instance.connectInspectorSession();
|
|
await session.send({ method: 'NodeRuntime.enable' });
|
|
await session.waitForNotification('NodeRuntime.waitingForDebugger');
|
|
await session.send({ method: 'Runtime.enable' });
|
|
await session.send({ method: 'Debugger.enable' });
|
|
await session.send({ method: 'Runtime.runIfWaitingForDebugger' });
|
|
await session.waitForNotification('Debugger.paused');
|
|
return { instance, session };
|
|
}
|
|
|
|
test('should load and stream a static network resource using loadNetworkResource and IO.read', async () => {
|
|
const { session } = await setupSessionAndPauseAtEvalLastLine(script);
|
|
const { resource } = await session.send({
|
|
method: 'Network.loadNetworkResource',
|
|
params: { url: resourceUrl },
|
|
});
|
|
assert(resource.success, 'Resource should be loaded successfully');
|
|
assert(resource.stream, 'Resource should have a stream handle');
|
|
let result = await session.send({ method: 'IO.read', params: { handle: resource.stream } });
|
|
let data = result.data;
|
|
let eof = result.eof;
|
|
let content = '';
|
|
while (!eof) {
|
|
content += data;
|
|
result = await session.send({ method: 'IO.read', params: { handle: resource.stream } });
|
|
data = result.data;
|
|
eof = result.eof;
|
|
}
|
|
content += data;
|
|
assert.strictEqual(content, resourceText);
|
|
await session.send({ method: 'IO.close', params: { handle: resource.stream } });
|
|
await session.send({ method: 'Debugger.resume' });
|
|
await session.waitForDisconnect();
|
|
});
|
|
|
|
test('should return success: false for missing resource', async () => {
|
|
const { session } = await setupSessionAndPauseAtEvalLastLine(script);
|
|
const { resource } = await session.send({
|
|
method: 'Network.loadNetworkResource',
|
|
params: { url: 'http://localhost:3000/does-not-exist.js' },
|
|
});
|
|
assert.strictEqual(resource.success, false);
|
|
assert(!resource.stream, 'No stream should be returned for missing resource');
|
|
await session.send({ method: 'Debugger.resume' });
|
|
await session.waitForDisconnect();
|
|
});
|
|
|
|
test('should error or return empty for wrong stream id', async () => {
|
|
const { session } = await setupSessionAndPauseAtEvalLastLine(script);
|
|
const { resource } = await session.send({
|
|
method: 'Network.loadNetworkResource',
|
|
params: { url: resourceUrl },
|
|
});
|
|
assert(resource.success);
|
|
const bogus = '999999';
|
|
const result = await session.send({ method: 'IO.read', params: { handle: bogus } });
|
|
assert(result.eof, 'Should be eof for bogus stream id');
|
|
assert.strictEqual(result.data, '');
|
|
await session.send({ method: 'IO.close', params: { handle: resource.stream } });
|
|
await session.send({ method: 'Debugger.resume' });
|
|
await session.waitForDisconnect();
|
|
});
|
|
|
|
test('should support IO.read with size and offset', async () => {
|
|
const { session } = await setupSessionAndPauseAtEvalLastLine(script);
|
|
const { resource } = await session.send({
|
|
method: 'Network.loadNetworkResource',
|
|
params: { url: resourceUrl },
|
|
});
|
|
assert(resource.success);
|
|
assert(resource.stream);
|
|
let result = await session.send({ method: 'IO.read', params: { handle: resource.stream, size: 5 } });
|
|
assert.strictEqual(result.data, resourceText.slice(0, 5));
|
|
result = await session.send({ method: 'IO.read', params: { handle: resource.stream, offset: 5, size: 5 } });
|
|
assert.strictEqual(result.data, resourceText.slice(5, 10));
|
|
result = await session.send({ method: 'IO.read', params: { handle: resource.stream, offset: 10 } });
|
|
assert.strictEqual(result.data, resourceText.slice(10));
|
|
await session.send({ method: 'IO.close', params: { handle: resource.stream } });
|
|
await session.send({ method: 'Debugger.resume' });
|
|
await session.waitForDisconnect();
|
|
});
|
|
|
|
test('should load resource put from another thread', async () => {
|
|
const workerScript = `
|
|
console.log('this is worker thread');
|
|
debugger;
|
|
`;
|
|
const script = `
|
|
const { NetworkResources } = require('node:inspector');
|
|
const fs = require('fs');
|
|
NetworkResources.put('${resourceUrl}', fs.readFileSync('${embedPath}', 'utf8'));
|
|
const { Worker } = require('worker_threads');
|
|
const worker = new Worker(\`${workerScript}\`, {eval: true});
|
|
`;
|
|
const instance = new NodeInstance([
|
|
'--experimental-inspector-network-resource',
|
|
'--experimental-worker-inspection',
|
|
'--inspect-brk=0',
|
|
], script);
|
|
const session = await instance.connectInspectorSession();
|
|
await setupInspector(session);
|
|
await session.waitForNotification('Debugger.paused');
|
|
await session.send({ method: 'Debugger.resume' });
|
|
await session.waitForNotification('Target.targetCreated');
|
|
await session.send({ method: 'Target.setAutoAttach', params: { autoAttach: true, waitForDebuggerOnStart: true } });
|
|
let sessionId;
|
|
await session.waitForNotification((notification) => {
|
|
if (notification.method === 'Target.attachedToTarget') {
|
|
sessionId = notification.params.sessionId;
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
});
|
|
await setupInspector(session, sessionId);
|
|
|
|
await session.waitForNotification('Debugger.paused');
|
|
|
|
const { resource } = await session.send({
|
|
method: 'Network.loadNetworkResource',
|
|
params: { url: resourceUrl, sessionId },
|
|
});
|
|
|
|
assert(resource.success, 'Resource should be loaded successfully');
|
|
assert(resource.stream, 'Resource should have a stream handle');
|
|
let result = await session.send({ method: 'IO.read', params: { handle: resource.stream, sessionId } });
|
|
let data = result.data;
|
|
let eof = result.eof;
|
|
let content = '';
|
|
while (!eof) {
|
|
content += data;
|
|
result = await session.send({ method: 'IO.read', params: { handle: resource.stream, sessionId } });
|
|
data = result.data;
|
|
eof = result.eof;
|
|
}
|
|
content += data;
|
|
assert.strictEqual(content, resourceText);
|
|
await session.send({ method: 'IO.close', params: { handle: resource.stream, sessionId } });
|
|
|
|
await session.send({ method: 'Debugger.resume', sessionId });
|
|
|
|
await session.waitForDisconnect();
|
|
|
|
async function setupInspector(session, sessionId) {
|
|
await session.send({ method: 'NodeRuntime.enable', sessionId });
|
|
await session.waitForNotification('NodeRuntime.waitingForDebugger');
|
|
await session.send({ method: 'Runtime.enable', sessionId });
|
|
await session.send({ method: 'Debugger.enable', sessionId });
|
|
await session.send({ method: 'Runtime.runIfWaitingForDebugger', sessionId });
|
|
}
|
|
});
|