Skip to content

Commit 8464d69

Browse files
author
Brian Vaughn
committed
String table uses TextEncoder/TextDecoder when available
This will support multi-byte characters. Need to profile this to see what the impact is on performance.
1 parent 3746eaf commit 8464d69

File tree

2 files changed

+36
-14
lines changed

2 files changed

+36
-14
lines changed

packages/react-devtools-shared/src/__tests__/setupEnv.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ global.process.env.DARK_MODE_DIMMED_LOG_COLOR = DARK_MODE_DIMMED_LOG_COLOR;
2424
global.process.env.LIGHT_MODE_DIMMED_WARNING_COLOR = LIGHT_MODE_DIMMED_WARNING_COLOR;
2525
global.process.env.LIGHT_MODE_DIMMED_ERROR_COLOR = LIGHT_MODE_DIMMED_ERROR_COLOR;
2626
global.process.env.LIGHT_MODE_DIMMED_LOG_COLOR = LIGHT_MODE_DIMMED_LOG_COLOR;
27+
28+
global.TextEncoder = require('util').TextEncoder;
29+
global.TextDecoder = require('util').TextDecoder;

packages/react-devtools-shared/src/utils.js

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ const cachedDisplayNames: WeakMap<Function, string> = new WeakMap();
5656

5757
// On large trees, encoding takes significant time.
5858
// Try to reuse the already encoded strings.
59-
const encodedStringCache: LRUCache<string, Array<number>> = new LRU({
59+
const encodedStringCache: LRUCache<
60+
string,
61+
Array<number> | Uint8Array,
62+
> = new LRU({
6063
max: 1000,
6164
});
6265

@@ -125,30 +128,46 @@ export function getUID(): number {
125128
return ++uidCounter;
126129
}
127130

131+
const isTextEncoderSupported =
132+
typeof TextDecoder === 'function' && typeof TextEncoder === 'function';
133+
128134
export function utfDecodeString(array: Array<number>): string {
129-
// Avoid spreading the array (e.g. String.fromCodePoint(...array))
130-
// Functions arguments are first placed on the stack before the function is called
131-
// which throws a RangeError for large arrays.
132-
// See github.com/facebook/react/issues/22293
133-
let string = '';
134-
for (let i = 0; i < array.length; i++) {
135-
const char = array[i];
136-
string += String.fromCodePoint(char);
135+
if (isTextEncoderSupported) {
136+
// Handles multi-byte characters; use if available.
137+
return new TextDecoder().decode(new Uint8Array(array));
138+
} else {
139+
// Avoid spreading the array (e.g. String.fromCodePoint(...array))
140+
// Functions arguments are first placed on the stack before the function is called
141+
// which throws a RangeError for large arrays.
142+
// See github.com/facebook/react/issues/22293
143+
let string = '';
144+
for (let i = 0; i < array.length; i++) {
145+
const char = array[i];
146+
string += String.fromCodePoint(char);
147+
}
148+
return string;
137149
}
138-
return string;
139150
}
140151

141-
export function utfEncodeString(string: string): Array<number> {
152+
export function utfEncodeString(string: string): Array<number> | Uint8Array {
142153
const cached = encodedStringCache.get(string);
143154
if (cached !== undefined) {
144155
return cached;
145156
}
146157

147-
const encoded = new Array(string.length);
148-
for (let i = 0; i < string.length; i++) {
149-
encoded[i] = string.codePointAt(i);
158+
let encoded;
159+
if (isTextEncoderSupported) {
160+
// Handles multi-byte characters; use if available.
161+
encoded = new TextEncoder().encode(string);
162+
} else {
163+
encoded = new Array(string.length);
164+
for (let i = 0; i < string.length; i++) {
165+
encoded[i] = string.codePointAt(i);
166+
}
150167
}
168+
151169
encodedStringCache.set(string, encoded);
170+
152171
return encoded;
153172
}
154173

0 commit comments

Comments
 (0)