Wang1rrr opened a new issue, #4774:
URL: https://github.com/apache/rocketmq-dashboard/issues/4774

   ### Before Creating the Bug Report
   
   - [x] I searched open and closed issues/PRs and believe this is not a 
duplicate.
   - [x] This concerns RocketMQ Studio, not another RocketMQ repository.
   - [x] The exact inspected version and reproduction scope are stated below.
   
   ### Studio Version
   
   - Branch: `rocketmq-studio`
   - Commit: `4c697f07acde460e2344375cb1f82669f5b270fd`
   - Reproduction: source-function probe, not a deployed Studio instance.
   
   ### Runtime Environment
   
   Windows, Node.js `v22.23.2`. The probe executes the checked-in formatter and 
download
   handler, with Node's real `Blob` and an in-memory replacement for 
`downloadBlob`.
   No browser or MySQL instance was involved.
   
   ### Connected RocketMQ Cluster
   
   None. A synthetic `MessageRecord.body` string is sufficient to reproduce this
   client-side transformation; no broker or customer data is needed.
   
   ### Describe the Bug
   
   The ordinary message-page download handler runs `record.body` through 
`formatBody`
   before creating the JSON Blob. That formatter calls `JSON.parse` followed by
   `JSON.stringify`, so JSON integers outside JavaScript's safe integer range 
can be
   silently changed in the downloaded content.
   
   For example, the incoming body string `{"orderId":9007199254740993}` 
produces a
   download containing `9007199254740992`. The incoming field is already a 
string;
   this particular precision loss happens inside the UI formatter, not while 
decoding
   the outer HTTP response.
   
   ### Steps to Reproduce
   
   From a checkout of the commit above, save this as a temporary `.mjs` file 
and run
   it with Node.js 22.23.2, using the repository root as the working directory:
   
   ```js
   import assert from 'node:assert/strict';
   import { readFileSync } from 'node:fs';
   import { stripTypeScriptTypes } from 'node:module';
   import vm from 'node:vm';
   
   const source = readFileSync('web/src/pages/instance/message.tsx', 'utf8');
   const formatter = source.match(
     /^const formatBody = \(body: string\): string => \{[\s\S]*?^\};/m,
   )?.[0];
   const handler = source.match(
     /^  const handleDownload = \(record: MessageRecord\) => \{[\s\S]*?^  \};/m,
   )?.[0];
   assert.ok(formatter && handler, 'Source changed: inspect the two functions 
first');
   let captured;
   const context = vm.createContext({
     Blob,
     downloadBlob: (blob) => { captured = blob; },
     message: { success: () => {} },
     t: (key) => key,
   });
   vm.runInContext(stripTypeScriptTypes(
     `${formatter}\n${handler}\nglobalThis.download = handleDownload;`,
   ), context, { timeout: 1000 });
   
   const record = { msgId: 'precision-repro', body: 
'{"orderId":9007199254740993}' };
   context.download(record);
   const actual = await captured.text();
   console.log('Incoming:', record.body);
   console.log('Downloaded:', actual);
   assert.ok(actual.includes('9007199254740992'), 'Expected current rounding 
bug');
   ```
   
   This extracts the original functions and only removes their TypeScript 
types. The
   assertion deliberately checks the current defect; it is not a passing fix 
test.
   The row's button wiring was inspected statically, not clicked in a browser.
   
   ### What Did You Expect to See?
   
   Downloading the available `record.body` should preserve its content, 
including
   numeric tokens. Presentation formatting should not silently rewrite message 
data.
   This does not imply recovery of bytes already truncated or encoded by the 
backend.
   
   ### What Did You See Instead?
   
   ```text
   Incoming: {"orderId":9007199254740993}
   Downloaded: {
     "orderId": 9007199254740992
   }
   ```
   
   Additional source-function controls:
   
   | Body value | Value in downloaded body |
   | --- | --- |
   | `9223372036854775807` | `9223372036854776000` |
   | `9007199254740991` | unchanged |
   | `"9007199254740993"` (JSON string) | unchanged |
   | Plain text, not JSON | unchanged |
   
   ### Additional Context
   
   - 
[Formatter](https://github.com/apache/rocketmq-dashboard/blob/4c697f07acde460e2344375cb1f82669f5b270fd/web/src/pages/instance/message.tsx#L140-L146)
   - [Download 
handler](https://github.com/apache/rocketmq-dashboard/blob/4c697f07acde460e2344375cb1f82669f5b270fd/web/src/pages/instance/message.tsx#L730-L734)
   - [Row 
action](https://github.com/apache/rocketmq-dashboard/blob/4c697f07acde460e2344375cb1f82669f5b270fd/web/src/pages/instance/message.tsx#L838)
   - The [copyable detail 
view](https://github.com/apache/rocketmq-dashboard/blob/4c697f07acde460e2344375cb1f82669f5b270fd/web/src/pages/instance/message.tsx#L945-L959)
     uses the same formatter. This is the same root cause, not a separate 
feature request;
     the actual clipboard interaction has not been tested.
   
   #4759 / #4760 concern Go CLI passthrough precision, whereas this path is the 
normal
   message-page download. #4735 / #4737 concern AI redelivery, which is not 
involved
   here. Any proposed fix should account for the related body 
encoding/truncation
   concerns discussed in #2501 / #2571.
   
   A small proposed direction is to preserve the available body string for 
downloads
   and copying, and agree on the presentation policy before changing the 
display.
   A component regression should click download and inspect the Blob, with 
unsafe
   integers, safe integers, quoted IDs, and plain text as controls.
   
   This report was prepared with AI assistance and independently checked by 
rerunning
   the source-function probe. No production code was changed, and no browser 
E2E,
   Vitest suite, backend test, or full-stack validation is claimed.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to