Skip to content

Commit 125865a

Browse files
authored
feat(loader): Use TextDecoder for large strings (#1471)
1 parent 9948f41 commit 125865a

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

Diff for: lib/loader/index.js

+9-14
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,18 @@ const ARRAY_SIZE = 16;
3838

3939
const BIGINT = typeof BigUint64Array !== "undefined";
4040
const THIS = Symbol();
41-
const CHUNKSIZE = 1024;
41+
42+
const STRING_DECODE_THRESHOLD = 32;
43+
const decoder = new TextDecoder("utf-16le");
4244

4345
/** Gets a string from an U32 and an U16 view on a memory. */
4446
function getStringImpl(buffer, ptr) {
45-
const U32 = new Uint32Array(buffer);
46-
const U16 = new Uint16Array(buffer);
47-
let length = U32[ptr + SIZE_OFFSET >>> 2] >>> 1;
48-
let offset = ptr >>> 1;
49-
if (length <= CHUNKSIZE) return String.fromCharCode.apply(String, U16.subarray(offset, offset + length));
50-
let parts = '';
51-
do {
52-
const last = U16[offset + CHUNKSIZE - 1];
53-
const size = last >= 0xD800 && last < 0xDC00 ? CHUNKSIZE - 1 : CHUNKSIZE;
54-
parts += String.fromCharCode.apply(String, U16.subarray(offset, offset += size));
55-
length -= size;
56-
} while (length > CHUNKSIZE);
57-
return parts + String.fromCharCode.apply(String, U16.subarray(offset, offset + length));
47+
const len = new Uint32Array(buffer)[ptr + SIZE_OFFSET >>> 2] >>> 1;
48+
const arr = new Uint16Array(buffer, ptr, len);
49+
if (len <= STRING_DECODE_THRESHOLD) {
50+
return String.fromCharCode.apply(String, arr);
51+
}
52+
return decoder.decode(arr);
5853
}
5954

6055
/** Prepares the base module prior to instantiation. */

Diff for: lib/loader/tests/index.js

+17-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function test(file) {
2424
// should be able to get an exported string
2525
assert.strictEqual(exports.__getString(exports.COLOR), "red");
2626

27-
// should be able to allocate and work with a new string
27+
// should be able to allocate and work with a new small string
2828
{
2929
let str = "Hello world!𤭢";
3030
let ref = exports.__retain(exports.__allocString(str));
@@ -33,6 +33,21 @@ function test(file) {
3333
exports.__release(ref);
3434
}
3535

36+
// should be able to allocate and work with a new big string
37+
{
38+
let str = `
39+
∀ ∁ ∂ ∃ ∄ ∅ ∆ ∇ ∈ ∉ ∊ ∋ ∌ ∍ ∎ ∏ ∐ ∑ − ∓ ∔ ∕ ∖ ∗ ∘ ∙ √ ∛
40+
∜ ∝ ∞ ∟ ∠ ∡ ∢ ∣ ∤ ∥ ∦ ∧ ∨ ∩ ∪ ∫ ∬ ∭ ∮ ∯ ∰ ∱ ∲ ∳ ∴ ∵ ∶ ∷
41+
∸ ∹ ∺ ∻ ∼ ∽ ∾ ∿ ≀ ≁ ≂ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≏ ≐ ≑ ≒ ≓
42+
≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≠ ≡ ≢ ≣ ≤ ≥ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯
43+
≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿
44+
`;
45+
let ref = exports.__retain(exports.__allocString(str));
46+
assert.strictEqual(exports.__getString(ref), str);
47+
assert.strictEqual(exports.strlen(ref), str.length);
48+
exports.__release(ref);
49+
}
50+
3651
// should be able to allocate a typed array
3752
{
3853
let arr = [1, 2, 3, 4, 5, 0x80000000 | 0];
@@ -290,4 +305,4 @@ function testInstantiate(file) {
290305
assert(instance && instance instanceof WebAssembly.Instance);
291306
assert(module && module instanceof WebAssembly.Module);
292307
})();
293-
}
308+
}

0 commit comments

Comments
 (0)