mirror of
https://github.com/Permissionless-Software-Foundation/psf-memo-client.git
synced 2026-09-21 16:52:02 -07:00
Fix Set Name Buffer reference for browser
Replace Node-only Buffer.byteLength with a TextEncoder-based UTF-8 byte length helper so the Set Name page and byte counter work in the browser. By specifier.
This commit is contained in:
@@ -12,6 +12,7 @@ import { useNavigate } from 'react-router-dom'
|
||||
// Local libraries
|
||||
import MemoSetName from '../../../services/memo-set-name'
|
||||
import SetNamePage from '../../../services/set-name-page'
|
||||
import { byteLength } from '../../../services/utf8'
|
||||
|
||||
function SetName (props) {
|
||||
const { appData } = props
|
||||
@@ -22,7 +23,7 @@ function SetName (props) {
|
||||
const [err, setErr] = useState('')
|
||||
const [settingName, setSettingName] = useState(false)
|
||||
|
||||
const remaining = maxBytes - Buffer.byteLength(input, 'utf8')
|
||||
const remaining = maxBytes - byteLength(input)
|
||||
|
||||
async function handleSubmit (event) {
|
||||
event.preventDefault()
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
const MemoAction = require('./memo-action')
|
||||
const { byteLength } = require('./utf8')
|
||||
|
||||
const MEMO_SET_NAME_PREFIX = '6d01'
|
||||
const MAX_NAME_BYTES = 77
|
||||
@@ -38,7 +39,7 @@ class MemoSetName extends MemoAction {
|
||||
|
||||
// A name is over-length when it exceeds the byte limit.
|
||||
isTooLong (name) {
|
||||
return Buffer.byteLength(name, 'utf8') > MAX_NAME_BYTES
|
||||
return byteLength(name) > MAX_NAME_BYTES
|
||||
}
|
||||
|
||||
// Compose and broadcast a Memo set-name transaction for the given name.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
const PageController = require('./page-controller')
|
||||
const MemoSetName = require('./memo-set-name')
|
||||
const { byteLength } = require('./utf8')
|
||||
|
||||
const SET_NAME_PATH = '/memo/set-name'
|
||||
const ACCOUNT_PATH = '/account'
|
||||
@@ -30,7 +31,7 @@ class SetNamePage extends PageController {
|
||||
|
||||
// Bytes remaining before the name limit is reached.
|
||||
remainingCount () {
|
||||
return MemoSetName.MAX_NAME_BYTES - Buffer.byteLength(this.input, 'utf8')
|
||||
return MemoSetName.MAX_NAME_BYTES - byteLength(this.input)
|
||||
}
|
||||
|
||||
// Set the in-flight setting-name flag.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
UTF-8 byte-length helper for browser and Node.
|
||||
|
||||
The Node global `Buffer` is not available in the browser, so byte counting
|
||||
(used by the Memo set-name byte counter and length check) must not depend on
|
||||
it. TextEncoder is available in both environments and reports the UTF-8 byte
|
||||
length of a string.
|
||||
*/
|
||||
|
||||
// Return the number of UTF-8 bytes in a string.
|
||||
function byteLength (str) {
|
||||
return new TextEncoder().encode(String(str)).length
|
||||
}
|
||||
|
||||
module.exports = { byteLength }
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Unit tests for the UTF-8 byte-length helper (src/services/utf8.js).
|
||||
|
||||
The helper must report the same UTF-8 byte length as Node's Buffer without
|
||||
depending on the Node-only `Buffer` global, so the browser build (which has
|
||||
no Buffer) can count bytes for the Memo set-name counter and length check.
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert/strict')
|
||||
|
||||
const { byteLength } = require('../../src/services/utf8')
|
||||
|
||||
test('byteLength matches Buffer.byteLength for ASCII text', () => {
|
||||
for (const s of ['', 'trout', 'a longer name with spaces', 'x'.repeat(77)]) {
|
||||
assert.equal(byteLength(s), Buffer.byteLength(s, 'utf8'))
|
||||
}
|
||||
})
|
||||
|
||||
test('byteLength matches Buffer.byteLength for multi-byte characters', () => {
|
||||
for (const s of ['é', 'é'.repeat(38), '😀', '😀'.repeat(20), '日本語']) {
|
||||
assert.equal(byteLength(s), Buffer.byteLength(s, 'utf8'))
|
||||
}
|
||||
})
|
||||
|
||||
test('byteLength counts UTF-8 bytes, not characters', () => {
|
||||
// 'é' is 1 character but 2 UTF-8 bytes; an emoji is 1 character but 4 bytes.
|
||||
assert.equal(byteLength('é'), 2)
|
||||
assert.equal(byteLength('😀'), 4)
|
||||
assert.equal(byteLength('a'), 1)
|
||||
})
|
||||
|
||||
test('byteLength coerces non-string input to a string', () => {
|
||||
assert.equal(byteLength(42), 2)
|
||||
assert.equal(byteLength(null), 4) // String(null) === 'null'
|
||||
})
|
||||
Reference in New Issue
Block a user