From 7343ed0c01294f84058686b245c6ad36df70aaad Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 25 Sep 2020 13:56:09 +0300 Subject: [PATCH 1/7] feat(loader): use TextDecoder for large strings --- lib/loader/index.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/loader/index.js b/lib/loader/index.js index 85b757be93..3183db4588 100644 --- a/lib/loader/index.js +++ b/lib/loader/index.js @@ -38,23 +38,21 @@ 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 length = U32[ptr + SIZE_OFFSET >>> 2] >>> 1; + const offset = ptr >>> 1; + const data = U16.subarray(offset, offset + length); + if (length <= STRING_DECODE_THRESHOLD) { + return String.fromCharCode.apply(String, data); + } + return decoder.decode(data); } /** Prepares the base module prior to instantiation. */ From 22bc157c9be2513058ffdba4087ecb291c298f70 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 25 Sep 2020 14:02:49 +0300 Subject: [PATCH 2/7] node.js as well --- lib/loader/index.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/loader/index.js b/lib/loader/index.js index 3183db4588..19f0a03c02 100644 --- a/lib/loader/index.js +++ b/lib/loader/index.js @@ -40,7 +40,15 @@ const BIGINT = typeof BigUint64Array !== "undefined"; const THIS = Symbol(); const STRING_DECODE_THRESHOLD = 32; -const decoder = new TextDecoder('utf-16le'); + +let decoder; +if (typeof process !== 'undefined') { + // node.js + decoder = new (require('util').TextDecoder)('utf-16le'); +} else { + // browser + decoder = new TextDecoder('utf-16le'); +} /** Gets a string from an U32 and an U16 view on a memory. */ function getStringImpl(buffer, ptr) { From 7326bc94e8b02fbcc87dc924291828fa174f2ed5 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 25 Sep 2020 14:08:18 +0300 Subject: [PATCH 3/7] fix --- lib/loader/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/loader/index.js b/lib/loader/index.js index 19f0a03c02..f62db3382f 100644 --- a/lib/loader/index.js +++ b/lib/loader/index.js @@ -42,7 +42,7 @@ const THIS = Symbol(); const STRING_DECODE_THRESHOLD = 32; let decoder; -if (typeof process !== 'undefined') { +if (typeof process !== 'undefined' && typeof TextDecoder === 'undefined') { // node.js decoder = new (require('util').TextDecoder)('utf-16le'); } else { From 2a5ddea007f1bff2156553bae337c4788b86eb12 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 25 Sep 2020 14:18:30 +0300 Subject: [PATCH 4/7] revert --- lib/loader/index.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/loader/index.js b/lib/loader/index.js index f62db3382f..3183db4588 100644 --- a/lib/loader/index.js +++ b/lib/loader/index.js @@ -40,15 +40,7 @@ const BIGINT = typeof BigUint64Array !== "undefined"; const THIS = Symbol(); const STRING_DECODE_THRESHOLD = 32; - -let decoder; -if (typeof process !== 'undefined' && typeof TextDecoder === 'undefined') { - // node.js - decoder = new (require('util').TextDecoder)('utf-16le'); -} else { - // browser - decoder = new TextDecoder('utf-16le'); -} +const decoder = new TextDecoder('utf-16le'); /** Gets a string from an U32 and an U16 view on a memory. */ function getStringImpl(buffer, ptr) { From 5be9ad37efed4781fe91f0a048cb19d4b84165b7 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 25 Sep 2020 14:40:23 +0300 Subject: [PATCH 5/7] ' -> " --- lib/loader/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/loader/index.js b/lib/loader/index.js index 3183db4588..a72f1cf43e 100644 --- a/lib/loader/index.js +++ b/lib/loader/index.js @@ -40,7 +40,7 @@ const BIGINT = typeof BigUint64Array !== "undefined"; const THIS = Symbol(); const STRING_DECODE_THRESHOLD = 32; -const decoder = new TextDecoder('utf-16le'); +const decoder = new TextDecoder("utf-16le"); /** Gets a string from an U32 and an U16 view on a memory. */ function getStringImpl(buffer, ptr) { From 7b61d73dcdfbe95e32a6f1bcd868d86e0ef3a205 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 25 Sep 2020 14:47:16 +0300 Subject: [PATCH 6/7] add test --- lib/loader/tests/index.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) 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 +} From 03e3e5e60a410c2bb7702fb2c6cfa0d35da2821f Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 25 Sep 2020 18:14:16 +0300 Subject: [PATCH 7/7] simplify --- lib/loader/index.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/loader/index.js b/lib/loader/index.js index a72f1cf43e..d49733c39a 100644 --- a/lib/loader/index.js +++ b/lib/loader/index.js @@ -44,15 +44,12 @@ 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); - const length = U32[ptr + SIZE_OFFSET >>> 2] >>> 1; - const offset = ptr >>> 1; - const data = U16.subarray(offset, offset + length); - if (length <= STRING_DECODE_THRESHOLD) { - return String.fromCharCode.apply(String, data); + 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(data); + return decoder.decode(arr); } /** Prepares the base module prior to instantiation. */