diff --git a/lib/loader/index.js b/lib/loader/index.js index 85b757be93..d49733c39a 100644 --- a/lib/loader/index.js +++ b/lib/loader/index.js @@ -38,23 +38,18 @@ const ARRAY_SIZE = 16; const BIGINT = typeof BigUint64Array !== "undefined"; const THIS = Symbol(); -const CHUNKSIZE = 1024; + +const STRING_DECODE_THRESHOLD = 32; +const decoder = new TextDecoder("utf-16le"); /** Gets a string from an U32 and an U16 view on a memory. */ function getStringImpl(buffer, ptr) { - const U32 = new Uint32Array(buffer); - const U16 = new Uint16Array(buffer); - let length = U32[ptr + SIZE_OFFSET >>> 2] >>> 1; - let offset = ptr >>> 1; - if (length <= CHUNKSIZE) return String.fromCharCode.apply(String, U16.subarray(offset, offset + length)); - let parts = ''; - do { - const last = U16[offset + CHUNKSIZE - 1]; - const size = last >= 0xD800 && last < 0xDC00 ? CHUNKSIZE - 1 : CHUNKSIZE; - parts += String.fromCharCode.apply(String, U16.subarray(offset, offset += size)); - length -= size; - } while (length > CHUNKSIZE); - return parts + String.fromCharCode.apply(String, U16.subarray(offset, offset + length)); + const len = new Uint32Array(buffer)[ptr + SIZE_OFFSET >>> 2] >>> 1; + const arr = new Uint16Array(buffer, ptr, len); + if (len <= STRING_DECODE_THRESHOLD) { + return String.fromCharCode.apply(String, arr); + } + return decoder.decode(arr); } /** Prepares the base module prior to instantiation. */ diff --git a/lib/loader/tests/index.js b/lib/loader/tests/index.js index 72dc1996c6..5ed603e28a 100644 --- a/lib/loader/tests/index.js +++ b/lib/loader/tests/index.js @@ -24,7 +24,7 @@ function test(file) { // should be able to get an exported string assert.strictEqual(exports.__getString(exports.COLOR), "red"); - // should be able to allocate and work with a new string + // should be able to allocate and work with a new small string { let str = "Hello world!𤭢"; let ref = exports.__retain(exports.__allocString(str)); @@ -33,6 +33,21 @@ function test(file) { exports.__release(ref); } + // should be able to allocate and work with a new big string + { + let str = ` + ∀ ∁ ∂ ∃ ∄ ∅ ∆ ∇ ∈ ∉ ∊ ∋ ∌ ∍ ∎ ∏ ∐ ∑ − ∓ ∔ ∕ ∖ ∗ ∘ ∙ √ ∛ + ∜ ∝ ∞ ∟ ∠ ∡ ∢ ∣ ∤ ∥ ∦ ∧ ∨ ∩ ∪ ∫ ∬ ∭ ∮ ∯ ∰ ∱ ∲ ∳ ∴ ∵ ∶ ∷ + ∸ ∹ ∺ ∻ ∼ ∽ ∾ ∿ ≀ ≁ ≂ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≏ ≐ ≑ ≒ ≓ + ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≠ ≡ ≢ ≣ ≤ ≥ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ + ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ + `; + let ref = exports.__retain(exports.__allocString(str)); + assert.strictEqual(exports.__getString(ref), str); + assert.strictEqual(exports.strlen(ref), str.length); + exports.__release(ref); + } + // should be able to allocate a typed array { let arr = [1, 2, 3, 4, 5, 0x80000000 | 0]; @@ -290,4 +305,4 @@ function testInstantiate(file) { assert(instance && instance instanceof WebAssembly.Instance); assert(module && module instanceof WebAssembly.Module); })(); -} \ No newline at end of file +}