@nxtedition/lib 28.0.1 → 28.0.3
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/app.d.ts +2 -0
- package/app.js +42 -10
- package/logger.js +21 -14
- package/memory.js +43 -0
- package/package.json +4 -2
- package/serializers.js +4 -0
- package/slice.js +278 -0
package/app.d.ts
CHANGED
package/app.js
CHANGED
|
@@ -41,6 +41,7 @@ import { isTimeBetween } from './time.js'
|
|
|
41
41
|
import makeUnderPressure from './under-pressure.js'
|
|
42
42
|
import { nice } from '@nxtedition/sched'
|
|
43
43
|
import { setAffinity } from './numa.js'
|
|
44
|
+
import { getContainerMemoryLimit, getContainerMemoryUsage } from './memory.js'
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
47
|
* @param {object} appConfig
|
|
@@ -670,6 +671,8 @@ export function makeApp(appConfig, onTerminateOrMeta, metaOrNull) {
|
|
|
670
671
|
heapUsed: mem.heapUsed,
|
|
671
672
|
external: mem.external,
|
|
672
673
|
arrayBuffers: mem.arrayBuffers,
|
|
674
|
+
containerLimit: getContainerMemoryLimit(),
|
|
675
|
+
containerUsage: getContainerMemoryUsage(),
|
|
673
676
|
totalHeapTotal: 0,
|
|
674
677
|
totalHeapUsed: 0,
|
|
675
678
|
totalExternal: 0,
|
|
@@ -776,16 +779,45 @@ export function makeApp(appConfig, onTerminateOrMeta, metaOrNull) {
|
|
|
776
779
|
rx.repeatWhen((complete$) => complete$.pipe(rx.delay(10e3))),
|
|
777
780
|
),
|
|
778
781
|
stats$.pipe(
|
|
779
|
-
rx.map(({ undici
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
782
|
+
rx.map(({ memory, heap, utilization, undici }) => {
|
|
783
|
+
const messages = []
|
|
784
|
+
|
|
785
|
+
if (memory?.containerLimit) {
|
|
786
|
+
const usagePercent = (memory.containerUsage / memory.containerLimit) * 100
|
|
787
|
+
messages.push({
|
|
788
|
+
id: 'app:container_memory_usage',
|
|
789
|
+
level: usagePercent > 90 ? 50 : usagePercent > 70 ? 40 : 30,
|
|
790
|
+
msg: `Memory Usage: ${usagePercent.toFixed(2)}%`,
|
|
791
|
+
})
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
if (heap) {
|
|
795
|
+
const usagePercent = (heap.used_heap_size / heap.heap_size_limit) * 100
|
|
796
|
+
messages.push({
|
|
797
|
+
id: 'app:heap_memory_usage',
|
|
798
|
+
level: usagePercent > 90 ? 50 : usagePercent > 70 ? 40 : 30,
|
|
799
|
+
msg: `Heap Usage: ${usagePercent.toFixed(2)}%`,
|
|
800
|
+
})
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
if (utilization) {
|
|
804
|
+
const elp = utilization.utilization * 100
|
|
805
|
+
messages.push({
|
|
806
|
+
id: 'app:event_loop_utilization',
|
|
807
|
+
level: elp > 95 ? 50 : elp > 80 ? 40 : 30,
|
|
808
|
+
msg: `Event Loop Utilization: ${elp.toFixed(2)}%`,
|
|
809
|
+
})
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
if (undici) {
|
|
813
|
+
messages.push({
|
|
814
|
+
id: 'app:undici_upstream_sockets',
|
|
815
|
+
level: undici.sockets > 8192 ? 50 : undici.sockets > 4096 ? 40 : 30,
|
|
816
|
+
msg: `Undici: ${undici.sockets} upstream connected`,
|
|
817
|
+
})
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
return messages
|
|
789
821
|
}),
|
|
790
822
|
),
|
|
791
823
|
toobusy?.appLag$.pipe(
|
package/logger.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
1
|
import { isMainThread } from 'node:worker_threads'
|
|
3
2
|
import serializers from './serializers.js'
|
|
4
3
|
import pino from 'pino'
|
|
5
4
|
|
|
6
5
|
const isProduction = process.env.NODE_ENV === 'production'
|
|
7
6
|
|
|
8
|
-
export function createLogger(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
export function createLogger({
|
|
8
|
+
level = isProduction ? 'debug' : 'trace',
|
|
9
|
+
flushInterval = 1e3,
|
|
10
|
+
stream,
|
|
11
|
+
...options
|
|
12
|
+
} = {}) {
|
|
14
13
|
if (!stream) {
|
|
15
14
|
if (
|
|
16
15
|
process.stdout.write !== process.stdout.constructor.prototype.write ||
|
|
@@ -23,15 +22,24 @@ export function createLogger(
|
|
|
23
22
|
if (stream) {
|
|
24
23
|
// Do nothing...
|
|
25
24
|
} else if (!isProduction) {
|
|
26
|
-
stream = pino.destination({ fd: process.stdout.fd ?? 1, sync: true })
|
|
25
|
+
stream = pino.destination({ fd: process.stdout.fd ?? 1, sync: true, fsync: false })
|
|
27
26
|
} else if (!isMainThread) {
|
|
28
27
|
// TODO (perf): Async mode doesn't work super well in workers.
|
|
29
|
-
stream = pino.destination({ fd: 1, sync: true })
|
|
28
|
+
stream = pino.destination({ fd: 1, sync: true, fsync: false })
|
|
30
29
|
} else {
|
|
31
|
-
stream = pino.destination({
|
|
30
|
+
stream = pino.destination({
|
|
31
|
+
sync: false,
|
|
32
|
+
fsync: false,
|
|
33
|
+
minLength: 4 * 1024,
|
|
34
|
+
maxWrite: 32 * 1024,
|
|
35
|
+
})
|
|
32
36
|
|
|
33
37
|
let flushing = 0
|
|
34
|
-
|
|
38
|
+
const onFlush = () => {
|
|
39
|
+
flushing--
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const flushTimeout = setInterval(() => {
|
|
35
43
|
if (flushing >= 10) {
|
|
36
44
|
try {
|
|
37
45
|
logger.warn('logger is flushing too slow')
|
|
@@ -41,10 +49,9 @@ export function createLogger(
|
|
|
41
49
|
}
|
|
42
50
|
} else {
|
|
43
51
|
flushing++
|
|
44
|
-
stream.flush(
|
|
45
|
-
flushing--
|
|
46
|
-
})
|
|
52
|
+
stream.flush(onFlush)
|
|
47
53
|
}
|
|
54
|
+
flushTimeout.refresh()
|
|
48
55
|
}, flushInterval).unref()
|
|
49
56
|
}
|
|
50
57
|
|
package/memory.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
function readFile(path) {
|
|
4
|
+
try {
|
|
5
|
+
return readFileSync(path, 'utf8').trim()
|
|
6
|
+
} catch {
|
|
7
|
+
return null
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function getContainerMemoryLimit() {
|
|
12
|
+
// cgroups v2
|
|
13
|
+
const v2Limit = readFile('/sys/fs/cgroup/memory.max')
|
|
14
|
+
if (v2Limit) {
|
|
15
|
+
return v2Limit === 'max' ? null : Number(v2Limit)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// cgroups v1
|
|
19
|
+
const v1Limit = readFile('/sys/fs/cgroup/memory/memory.limit_in_bytes')
|
|
20
|
+
if (v1Limit) {
|
|
21
|
+
const limit = Number(v1Limit)
|
|
22
|
+
// Very large number usually means "no limit"
|
|
23
|
+
return limit > 1e15 ? null : limit
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getContainerMemoryUsage() {
|
|
30
|
+
// cgroups v2
|
|
31
|
+
const v2Usage = readFile('/sys/fs/cgroup/memory.current')
|
|
32
|
+
if (v2Usage) {
|
|
33
|
+
return Number(v2Usage)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// cgroups v1
|
|
37
|
+
const v1Usage = readFile('/sys/fs/cgroup/memory/memory.usage_in_bytes')
|
|
38
|
+
if (v1Usage) {
|
|
39
|
+
return Number(v1Usage)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return undefined
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/lib",
|
|
3
|
-
"version": "28.0.
|
|
3
|
+
"version": "28.0.3",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"author": "Robert Nagy <robert.nagy@boffins.se>",
|
|
6
6
|
"type": "module",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"shared.js",
|
|
25
25
|
"logger.js",
|
|
26
26
|
"logger.d.ts",
|
|
27
|
+
"memory.js",
|
|
27
28
|
"mime.js",
|
|
28
29
|
"numa.js",
|
|
29
30
|
"proxy.js",
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
"errors.js",
|
|
37
38
|
"errors.d.ts",
|
|
38
39
|
"worker.js",
|
|
40
|
+
"slice.js",
|
|
39
41
|
"stream.js",
|
|
40
42
|
"transcript.js",
|
|
41
43
|
"docker-secrets.js",
|
|
@@ -90,5 +92,5 @@
|
|
|
90
92
|
"pino": ">=7.0.0",
|
|
91
93
|
"rxjs": "^7.0.0"
|
|
92
94
|
},
|
|
93
|
-
"gitHead": "
|
|
95
|
+
"gitHead": "15f4fd00f86a558ae56672b1efa3e909b23feb3f"
|
|
94
96
|
}
|
package/serializers.js
CHANGED
|
@@ -118,6 +118,7 @@ export default {
|
|
|
118
118
|
req: (req) =>
|
|
119
119
|
req && {
|
|
120
120
|
id: req.id || getHeader(req, 'request-id'),
|
|
121
|
+
httpVersion: req.httpVersion,
|
|
121
122
|
method: req.method,
|
|
122
123
|
target: getTarget(req),
|
|
123
124
|
url: getUrl(req),
|
|
@@ -138,6 +139,7 @@ export default {
|
|
|
138
139
|
ureq: (ureq) =>
|
|
139
140
|
ureq && {
|
|
140
141
|
id: ureq.id || getHeader(ureq, 'request-id'),
|
|
142
|
+
httpVersion: ureq.httpVersion,
|
|
141
143
|
method: ureq.method,
|
|
142
144
|
target: getTarget(ureq),
|
|
143
145
|
url: getUrl(ureq),
|
|
@@ -154,6 +156,7 @@ export default {
|
|
|
154
156
|
res: (res) =>
|
|
155
157
|
res && {
|
|
156
158
|
id: res.id || getHeader(res, 'request-id') || getHeader(res.req, 'request-id'),
|
|
159
|
+
httpVersion: res.httpVersion,
|
|
157
160
|
headers: getHeaders(res),
|
|
158
161
|
statusCode: res.statusCode || res.status,
|
|
159
162
|
timing: res.timing,
|
|
@@ -171,6 +174,7 @@ export default {
|
|
|
171
174
|
ures: (ures) =>
|
|
172
175
|
ures && {
|
|
173
176
|
id: ures.id || getHeader(ures, 'request-id') || getHeader(ures.req, 'request-id'),
|
|
177
|
+
httpVersion: ures.httpVersion,
|
|
174
178
|
headers: getHeaders(ures),
|
|
175
179
|
statusCode: ures.statusCode ?? ures.status,
|
|
176
180
|
timing: ures.timing,
|
package/slice.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import util from 'node:util'
|
|
2
|
+
|
|
3
|
+
const EMPTY_BUF = Buffer.alloc(0)
|
|
4
|
+
const POOL = []
|
|
5
|
+
|
|
6
|
+
export class Slice {
|
|
7
|
+
buffer
|
|
8
|
+
byteOffset = 0
|
|
9
|
+
byteLength = 0
|
|
10
|
+
maxByteLength = 0
|
|
11
|
+
|
|
12
|
+
static EMPTY_BUF = EMPTY_BUF
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @param {Buffer} [buffer]
|
|
17
|
+
* @param {number} [byteOffset]
|
|
18
|
+
* @param {number} [byteLength]
|
|
19
|
+
* @param {number} [maxByteLength]
|
|
20
|
+
*/
|
|
21
|
+
constructor(
|
|
22
|
+
buffer = Slice.EMPTY_BUF,
|
|
23
|
+
byteOffset = 0,
|
|
24
|
+
byteLength = buffer.byteLength,
|
|
25
|
+
maxByteLength = byteLength,
|
|
26
|
+
) {
|
|
27
|
+
if (byteOffset < 0 || !Number.isInteger(byteOffset)) {
|
|
28
|
+
throw new RangeError(`Invalid byteOffset: ${byteOffset}`)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (byteLength < 0 || !Number.isInteger(byteLength)) {
|
|
32
|
+
throw new RangeError(`Invalid byteLength: ${byteLength}`)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (
|
|
36
|
+
maxByteLength < byteLength ||
|
|
37
|
+
maxByteLength > buffer.byteLength ||
|
|
38
|
+
!Number.isInteger(maxByteLength)
|
|
39
|
+
) {
|
|
40
|
+
throw new RangeError(`Invalid maxByteLength: ${maxByteLength}`)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
this.buffer = buffer
|
|
44
|
+
this.byteOffset = byteOffset
|
|
45
|
+
this.byteLength = byteLength
|
|
46
|
+
this.maxByteLength = maxByteLength
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static create(buffer, byteOffset, byteLength, maxByteLength) {
|
|
50
|
+
if (buffer === undefined) {
|
|
51
|
+
buffer = Slice.EMPTY_BUF
|
|
52
|
+
}
|
|
53
|
+
if (byteOffset === undefined) {
|
|
54
|
+
byteOffset = 0
|
|
55
|
+
}
|
|
56
|
+
if (byteLength === undefined) {
|
|
57
|
+
byteLength = buffer.byteLength
|
|
58
|
+
}
|
|
59
|
+
if (maxByteLength === undefined) {
|
|
60
|
+
maxByteLength = byteLength
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const slice = POOL.pop()
|
|
64
|
+
|
|
65
|
+
if (slice) {
|
|
66
|
+
slice.buffer = buffer
|
|
67
|
+
slice.byteOffset = byteOffset
|
|
68
|
+
slice.byteLength = byteLength
|
|
69
|
+
slice.maxByteLength = maxByteLength
|
|
70
|
+
return slice
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return new Slice(buffer, byteOffset, byteLength, maxByteLength)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static free(slice) {
|
|
77
|
+
if (slice == null) {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
slice.reset()
|
|
82
|
+
|
|
83
|
+
if (POOL.length < 16 * 1024) {
|
|
84
|
+
POOL.push(slice)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
reset() {
|
|
89
|
+
this.buffer = Slice.EMPTY_BUF
|
|
90
|
+
this.byteOffset = 0
|
|
91
|
+
this.byteLength = 0
|
|
92
|
+
this.maxByteLength = 0
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get length() {
|
|
96
|
+
return this.byteLength
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {Buffer|Slice} target
|
|
101
|
+
* @param {number} [targetStart = 0]
|
|
102
|
+
* @param {number} [sourceStart = 0]
|
|
103
|
+
* @param {number} [sourceEnd = this.byteOffset]
|
|
104
|
+
* @returns {number} Number of bytes written.
|
|
105
|
+
*/
|
|
106
|
+
copy(target, targetStart, sourceStart, sourceEnd) {
|
|
107
|
+
if (target instanceof Slice) {
|
|
108
|
+
if (targetStart === undefined) {
|
|
109
|
+
targetStart = target.byteOffset
|
|
110
|
+
} else {
|
|
111
|
+
targetStart += target.byteOffset
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
target = target.buffer
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (sourceStart === undefined) {
|
|
118
|
+
sourceStart = this.byteOffset
|
|
119
|
+
} else {
|
|
120
|
+
sourceStart += this.byteOffset
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (sourceEnd === undefined) {
|
|
124
|
+
sourceEnd = this.byteLength + this.byteOffset
|
|
125
|
+
} else {
|
|
126
|
+
sourceEnd += this.byteOffset
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return this.buffer.copy(target, targetStart, sourceStart, sourceEnd)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @param {Buffer|Slice} target
|
|
134
|
+
* @param {number} [targetStart = 0]
|
|
135
|
+
* @param {number} [targetEnd = target.byteOffset]
|
|
136
|
+
* @param {number} [sourceStart = 0]
|
|
137
|
+
* @param {number} [sourceEnd = this.byteOffset]
|
|
138
|
+
* @returns
|
|
139
|
+
*/
|
|
140
|
+
compare(target, targetStart, targetEnd, sourceStart, sourceEnd) {
|
|
141
|
+
if (target instanceof Slice) {
|
|
142
|
+
if (targetStart === undefined) {
|
|
143
|
+
targetStart = target.byteOffset
|
|
144
|
+
} else {
|
|
145
|
+
targetStart += target.byteOffset
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (targetEnd === undefined) {
|
|
149
|
+
targetEnd = target.byteLength + target.byteOffset
|
|
150
|
+
} else {
|
|
151
|
+
targetEnd += target.byteOffset
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
target = target.buffer
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (sourceStart === undefined) {
|
|
158
|
+
sourceStart = this.byteOffset
|
|
159
|
+
} else {
|
|
160
|
+
sourceStart += this.byteOffset
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (sourceEnd === undefined) {
|
|
164
|
+
sourceEnd = this.byteLength + this.byteOffset
|
|
165
|
+
} else {
|
|
166
|
+
sourceEnd += this.byteOffset
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return this.buffer.compare(target, targetStart, targetEnd, sourceStart, sourceEnd)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
*
|
|
174
|
+
* @param {string} string
|
|
175
|
+
* @param {number} [offset=0]
|
|
176
|
+
* @param {number} [length=this.byteLength - offset]
|
|
177
|
+
* @param {NodeJS.BufferEncoding} [encoding='utf8']
|
|
178
|
+
* @returns {number} Number of bytes written.
|
|
179
|
+
*/
|
|
180
|
+
write(string, offset, length, encoding) {
|
|
181
|
+
if (offset === undefined) {
|
|
182
|
+
offset = this.byteOffset
|
|
183
|
+
} else {
|
|
184
|
+
offset += this.byteOffset
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (length === undefined) {
|
|
188
|
+
length = this.byteLength + this.byteOffset - offset
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return this.buffer.write(string, offset, length, encoding)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
set(array, offset) {
|
|
195
|
+
if (array == null) {
|
|
196
|
+
return
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (offset === undefined) {
|
|
200
|
+
offset = this.byteOffset
|
|
201
|
+
} else {
|
|
202
|
+
offset += this.byteOffset
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
array?.copy(this.buffer, offset)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
at(index) {
|
|
209
|
+
return index >= 0
|
|
210
|
+
? this.buffer[this.byteOffset + index]
|
|
211
|
+
: this.buffer[this.byteOffset + this.byteLength + index]
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
test(expr) {
|
|
215
|
+
return expr.test(this.buffer, this.byteOffset, this.byteLength)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
readBigUInt64BE(offset = 0) {
|
|
219
|
+
if (offset === undefined) {
|
|
220
|
+
offset = this.byteOffset
|
|
221
|
+
} else {
|
|
222
|
+
offset += this.byteOffset
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return this.buffer.readBigUInt64BE(offset)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
*
|
|
230
|
+
* @param {BufferEncoding} [encoding='utf8']
|
|
231
|
+
* @param {number} [start=0]
|
|
232
|
+
* @param {number} [end=this.byteLength]
|
|
233
|
+
* @returns {string}
|
|
234
|
+
*/
|
|
235
|
+
toString(encoding, start, end) {
|
|
236
|
+
if (start === undefined) {
|
|
237
|
+
start = this.byteOffset
|
|
238
|
+
} else {
|
|
239
|
+
start += this.byteOffset
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (end === undefined) {
|
|
243
|
+
end = this.byteLength + this.byteOffset
|
|
244
|
+
} else {
|
|
245
|
+
end += this.byteOffset
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return this.buffer.toString(encoding, start, end)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
toBuffer(start, end) {
|
|
252
|
+
if (start === undefined) {
|
|
253
|
+
start = this.byteOffset
|
|
254
|
+
} else {
|
|
255
|
+
start += this.byteOffset
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (end === undefined) {
|
|
259
|
+
end = this.byteLength + this.byteOffset
|
|
260
|
+
} else {
|
|
261
|
+
end += this.byteOffset
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return this.buffer.subarray(start, end)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
[Symbol.toStringTag]() {
|
|
268
|
+
return this.toString()
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
[util.inspect.custom](depth, options, inspect) {
|
|
272
|
+
const bytes = []
|
|
273
|
+
for (let i = 0; i < this.byteLength; i++) {
|
|
274
|
+
bytes.push(this.buffer[this.byteOffset + i].toString(16).padStart(2, '0'))
|
|
275
|
+
}
|
|
276
|
+
return `Slice: "${this.toString()}" <${bytes.join(' ')}>`
|
|
277
|
+
}
|
|
278
|
+
}
|