diff --git a/AUTHORS b/AUTHORS index 5aed48f68b996..6c35c1c0b38fd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -601,3 +601,4 @@ a license to everyone to use it as detailed in LICENSE.) * Artur Gatin (copyright owned by Teladoc Health, Inc.) * Christian Lloyd (copyright owned by Teladoc Health, Inc.) * Sean Morris +* Pt. Prashant Tripathi diff --git a/site/source/docs/tools_reference/settings_reference.rst b/site/source/docs/tools_reference/settings_reference.rst index d3df18d195513..e116f4b6ad72a 100644 --- a/site/source/docs/tools_reference/settings_reference.rst +++ b/site/source/docs/tools_reference/settings_reference.rst @@ -2700,6 +2700,18 @@ of ENVIRONMENT since TextDecoder is not available in those environments). Default value: 1 +.. _textencoder: + +TEXTENCODER +=========== + +The default value of 1 means the generated code will use TextEncoder if +available and fall back to custom encoding code when it is not available. +If set to 2, we assume TextEncoder is always present and usable, and no +fallback JS code will be emitted. + +Default value: 1 + .. _embind_std_string_is_utf8: EMBIND_STD_STRING_IS_UTF8 diff --git a/src/lib/libstrings.js b/src/lib/libstrings.js index 9ae73bf6f9f7a..745a8e0b32309 100644 --- a/src/lib/libstrings.js +++ b/src/lib/libstrings.js @@ -8,6 +8,10 @@ #error "TEXTDECODER must be either 1 or 2" #endif +#if TEXTENCODER != 1 && TEXTENCODER != 2 +#error "TEXTENCODER must be either 1 or 2" +#endif + addToLibrary({ // TextDecoder constructor defaults to UTF-8 #if TEXTDECODER == 2 @@ -16,6 +20,13 @@ addToLibrary({ $UTF8Decoder: "typeof TextDecoder != 'undefined' ? new TextDecoder() : undefined", #endif + // TextEncoder constructor defaults to UTF-8 +#if TEXTENCODER == 2 + $UTF8Encoder: "new TextEncoder()", +#else + $UTF8Encoder: "typeof TextEncoder != 'undefined' ? new TextEncoder() : undefined", +#endif + $findStringEnd: (heapOrArray, idx, maxBytesToRead, ignoreNul) => { var maxIdx = idx + maxBytesToRead; if (ignoreNul) return maxIdx; @@ -147,9 +158,12 @@ addToLibrary({ * terminator. * @return {number} The number of bytes written, EXCLUDING the null terminator. */ + $stringToUTF8Array__deps: [ + '$UTF8Encoder', #if ASSERTIONS - $stringToUTF8Array__deps: ['$warnOnce'], + '$warnOnce', #endif + ], $stringToUTF8Array: (str, heap, outIdx, maxBytesToWrite) => { #if CAN_ADDRESS_2GB outIdx >>>= 0; @@ -162,6 +176,28 @@ addToLibrary({ if (!(maxBytesToWrite > 0)) return 0; +#if TEXTENCODER == 2 + // Always use TextEncoder when TEXTENCODER == 2 + var encoded = UTF8Encoder.encode(str); + var bytesToWrite = Math.min(encoded.length, maxBytesToWrite - 1); // -1 for null terminator + for (var i = 0; i < bytesToWrite; ++i) { + heap[outIdx + i] = encoded[i]; + } + heap[outIdx + bytesToWrite] = 0; + return bytesToWrite; +#else + // When using conditional TextEncoder + if (UTF8Encoder) { + var encoded = UTF8Encoder.encode(str); + var bytesToWrite = Math.min(encoded.length, maxBytesToWrite - 1); // -1 for null terminator + for (var i = 0; i < bytesToWrite; ++i) { + heap[outIdx + i] = encoded[i]; + } + heap[outIdx + bytesToWrite] = 0; + return bytesToWrite; + } + + // Fallback: manual UTF-8 encoding var startIdx = outIdx; var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. for (var i = 0; i < str.length; ++i) { @@ -198,6 +234,7 @@ addToLibrary({ // Null-terminate the pointer to the buffer. heap[outIdx] = 0; return outIdx - startIdx; +#endif // TEXTENCODER == 2 }, /** @@ -224,7 +261,18 @@ addToLibrary({ * @param {string} str - JavaScript string to operator on * @return {number} Length, in bytes, of the UTF8 encoded string. */ + $lengthBytesUTF8__deps: ['$UTF8Encoder'], $lengthBytesUTF8: (str) => { +#if TEXTENCODER == 2 + // Always use TextEncoder when TEXTENCODER == 2 + return UTF8Encoder.encode(str).length; +#else + // When using conditional TextEncoder + if (UTF8Encoder) { + return UTF8Encoder.encode(str).length; + } + + // Fallback: manual calculation var len = 0; for (var i = 0; i < str.length; ++i) { // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code @@ -243,6 +291,7 @@ addToLibrary({ } } return len; +#endif // TEXTENCODER == 2 }, $intArrayFromString__docs: '/** @type {function(string, boolean=, number=)} */', diff --git a/src/settings.js b/src/settings.js index 32c6e49d55e89..65bd578107263 100644 --- a/src/settings.js +++ b/src/settings.js @@ -1776,6 +1776,13 @@ var EVAL_CTORS = 0; // [link] var TEXTDECODER = 1; +// The default value of 1 means the generated code will use TextEncoder if +// available and fall back to custom encoding code when it is not available. +// If set to 2, we assume TextEncoder is always present and usable, and no +// fallback JS code will be emitted. +// [link] +var TEXTENCODER = 1; + // Embind specific: If enabled, assume UTF-8 encoded data in std::string binding. // Disable this to support binary data transfer. // [link] diff --git a/test/code_size/test_codesize_cxx_ctors1.json b/test/code_size/test_codesize_cxx_ctors1.json index 312bb3273070a..2510e5350b82f 100644 --- a/test/code_size/test_codesize_cxx_ctors1.json +++ b/test/code_size/test_codesize_cxx_ctors1.json @@ -1,10 +1,10 @@ { - "a.out.js": 19754, - "a.out.js.gz": 8162, - "a.out.nodebug.wasm": 129509, - "a.out.nodebug.wasm.gz": 49243, - "total": 149263, - "total_gz": 57405, + "a.out.js": 19941, + "a.out.js.gz": 8224, + "a.out.nodebug.wasm": 129513, + "a.out.nodebug.wasm.gz": 49252, + "total": 149454, + "total_gz": 57476, "sent": [ "__cxa_throw", "_abort_js", diff --git a/test/code_size/test_codesize_cxx_ctors2.json b/test/code_size/test_codesize_cxx_ctors2.json index bc5555606d146..39e71d99b421c 100644 --- a/test/code_size/test_codesize_cxx_ctors2.json +++ b/test/code_size/test_codesize_cxx_ctors2.json @@ -1,10 +1,10 @@ { - "a.out.js": 19732, - "a.out.js.gz": 8148, - "a.out.nodebug.wasm": 128936, - "a.out.nodebug.wasm.gz": 48884, - "total": 148668, - "total_gz": 57032, + "a.out.js": 19919, + "a.out.js.gz": 8209, + "a.out.nodebug.wasm": 128940, + "a.out.nodebug.wasm.gz": 48891, + "total": 148859, + "total_gz": 57100, "sent": [ "__cxa_throw", "_abort_js", diff --git a/test/code_size/test_codesize_cxx_except.json b/test/code_size/test_codesize_cxx_except.json index 4e27799b75801..90933f7fa79e6 100644 --- a/test/code_size/test_codesize_cxx_except.json +++ b/test/code_size/test_codesize_cxx_except.json @@ -1,10 +1,10 @@ { - "a.out.js": 23415, - "a.out.js.gz": 9145, - "a.out.nodebug.wasm": 171271, - "a.out.nodebug.wasm.gz": 57338, - "total": 194686, - "total_gz": 66483, + "a.out.js": 23604, + "a.out.js.gz": 9203, + "a.out.nodebug.wasm": 171275, + "a.out.nodebug.wasm.gz": 57346, + "total": 194879, + "total_gz": 66549, "sent": [ "__cxa_begin_catch", "__cxa_end_catch", diff --git a/test/code_size/test_codesize_cxx_except_wasm.json b/test/code_size/test_codesize_cxx_except_wasm.json index 043a53f450876..e2d418cf288a7 100644 --- a/test/code_size/test_codesize_cxx_except_wasm.json +++ b/test/code_size/test_codesize_cxx_except_wasm.json @@ -1,10 +1,10 @@ { - "a.out.js": 19643, - "a.out.js.gz": 8112, - "a.out.nodebug.wasm": 144630, - "a.out.nodebug.wasm.gz": 54894, - "total": 164273, - "total_gz": 63006, + "a.out.js": 19831, + "a.out.js.gz": 8171, + "a.out.nodebug.wasm": 144634, + "a.out.nodebug.wasm.gz": 54899, + "total": 164465, + "total_gz": 63070, "sent": [ "_abort_js", "_tzset_js", diff --git a/test/code_size/test_codesize_cxx_except_wasm_legacy.json b/test/code_size/test_codesize_cxx_except_wasm_legacy.json index 6df2d37780ccf..02a4c5c01ed3a 100644 --- a/test/code_size/test_codesize_cxx_except_wasm_legacy.json +++ b/test/code_size/test_codesize_cxx_except_wasm_legacy.json @@ -1,10 +1,10 @@ { - "a.out.js": 19643, - "a.out.js.gz": 8112, - "a.out.nodebug.wasm": 142219, - "a.out.nodebug.wasm.gz": 54358, - "total": 161862, - "total_gz": 62470, + "a.out.js": 19831, + "a.out.js.gz": 8171, + "a.out.nodebug.wasm": 142223, + "a.out.nodebug.wasm.gz": 54362, + "total": 162054, + "total_gz": 62533, "sent": [ "_abort_js", "_tzset_js", diff --git a/test/code_size/test_codesize_cxx_lto.json b/test/code_size/test_codesize_cxx_lto.json index 8e14251227c11..7935f1f71cc11 100644 --- a/test/code_size/test_codesize_cxx_lto.json +++ b/test/code_size/test_codesize_cxx_lto.json @@ -1,10 +1,10 @@ { - "a.out.js": 19082, - "a.out.js.gz": 7841, - "a.out.nodebug.wasm": 106463, - "a.out.nodebug.wasm.gz": 42596, - "total": 125545, - "total_gz": 50437, + "a.out.js": 18725, + "a.out.js.gz": 7678, + "a.out.nodebug.wasm": 106473, + "a.out.nodebug.wasm.gz": 42629, + "total": 125198, + "total_gz": 50307, "sent": [ "a (emscripten_resize_heap)", "b (_setitimer_js)", diff --git a/test/code_size/test_codesize_cxx_mangle.json b/test/code_size/test_codesize_cxx_mangle.json index 91bf2915957fe..69b6be08e65f5 100644 --- a/test/code_size/test_codesize_cxx_mangle.json +++ b/test/code_size/test_codesize_cxx_mangle.json @@ -1,10 +1,10 @@ { - "a.out.js": 23465, - "a.out.js.gz": 9164, - "a.out.nodebug.wasm": 235312, - "a.out.nodebug.wasm.gz": 78933, - "total": 258777, - "total_gz": 88097, + "a.out.js": 23654, + "a.out.js.gz": 9223, + "a.out.nodebug.wasm": 235316, + "a.out.nodebug.wasm.gz": 78938, + "total": 258970, + "total_gz": 88161, "sent": [ "__cxa_begin_catch", "__cxa_end_catch", diff --git a/test/code_size/test_codesize_cxx_noexcept.json b/test/code_size/test_codesize_cxx_noexcept.json index 09548f3c2b31c..4dc6f0a5de616 100644 --- a/test/code_size/test_codesize_cxx_noexcept.json +++ b/test/code_size/test_codesize_cxx_noexcept.json @@ -1,10 +1,10 @@ { - "a.out.js": 19754, - "a.out.js.gz": 8162, - "a.out.nodebug.wasm": 131926, - "a.out.nodebug.wasm.gz": 50238, - "total": 151680, - "total_gz": 58400, + "a.out.js": 19941, + "a.out.js.gz": 8224, + "a.out.nodebug.wasm": 131930, + "a.out.nodebug.wasm.gz": 50245, + "total": 151871, + "total_gz": 58469, "sent": [ "__cxa_throw", "_abort_js", diff --git a/test/code_size/test_codesize_cxx_wasmfs.json b/test/code_size/test_codesize_cxx_wasmfs.json index f470124928808..3e23978047696 100644 --- a/test/code_size/test_codesize_cxx_wasmfs.json +++ b/test/code_size/test_codesize_cxx_wasmfs.json @@ -1,10 +1,10 @@ { - "a.out.js": 7143, - "a.out.js.gz": 3338, - "a.out.nodebug.wasm": 169797, - "a.out.nodebug.wasm.gz": 63087, - "total": 176940, - "total_gz": 66425, + "a.out.js": 7353, + "a.out.js.gz": 3407, + "a.out.nodebug.wasm": 169801, + "a.out.nodebug.wasm.gz": 63095, + "total": 177154, + "total_gz": 66502, "sent": [ "__cxa_throw", "_abort_js", diff --git a/test/code_size/test_codesize_file_preload.json b/test/code_size/test_codesize_file_preload.json index a7ad8a13b7305..e4bf203447229 100644 --- a/test/code_size/test_codesize_file_preload.json +++ b/test/code_size/test_codesize_file_preload.json @@ -1,10 +1,10 @@ { - "a.out.js": 22684, - "a.out.js.gz": 9375, + "a.out.js": 22869, + "a.out.js.gz": 9431, "a.out.nodebug.wasm": 1681, "a.out.nodebug.wasm.gz": 960, - "total": 24365, - "total_gz": 10335, + "total": 24550, + "total_gz": 10391, "sent": [ "a (fd_write)" ], diff --git a/test/code_size/test_codesize_files_js_fs.json b/test/code_size/test_codesize_files_js_fs.json index 2938b9c5dddf7..8f4dfb3c9dd6f 100644 --- a/test/code_size/test_codesize_files_js_fs.json +++ b/test/code_size/test_codesize_files_js_fs.json @@ -1,10 +1,10 @@ { - "a.out.js": 18357, - "a.out.js.gz": 7470, + "a.out.js": 18536, + "a.out.js.gz": 7528, "a.out.nodebug.wasm": 381, "a.out.nodebug.wasm.gz": 260, - "total": 18738, - "total_gz": 7730, + "total": 18917, + "total_gz": 7788, "sent": [ "a (fd_write)", "b (fd_read)", diff --git a/test/code_size/test_codesize_files_wasmfs.json b/test/code_size/test_codesize_files_wasmfs.json index e3182ff75bc14..d56f7a720176a 100644 --- a/test/code_size/test_codesize_files_wasmfs.json +++ b/test/code_size/test_codesize_files_wasmfs.json @@ -1,10 +1,10 @@ { - "a.out.js": 5549, - "a.out.js.gz": 2591, - "a.out.nodebug.wasm": 50231, + "a.out.js": 5759, + "a.out.js.gz": 2665, + "a.out.nodebug.wasm": 50237, "a.out.nodebug.wasm.gz": 18094, - "total": 55780, - "total_gz": 20685, + "total": 55996, + "total_gz": 20759, "sent": [ "a (emscripten_date_now)", "b (emscripten_err)", diff --git a/test/code_size/test_codesize_hello_O0.json b/test/code_size/test_codesize_hello_O0.json index b46bbc84b434f..228bcbfd469db 100644 --- a/test/code_size/test_codesize_hello_O0.json +++ b/test/code_size/test_codesize_hello_O0.json @@ -1,10 +1,10 @@ { - "a.out.js": 22496, - "a.out.js.gz": 8322, + "a.out.js": 22508, + "a.out.js.gz": 8324, "a.out.nodebug.wasm": 15127, "a.out.nodebug.wasm.gz": 7450, - "total": 37623, - "total_gz": 15772, + "total": 37635, + "total_gz": 15774, "sent": [ "fd_write" ], diff --git a/test/code_size/test_codesize_hello_dylink.json b/test/code_size/test_codesize_hello_dylink.json index bfb800632ec73..acd37f86b9849 100644 --- a/test/code_size/test_codesize_hello_dylink.json +++ b/test/code_size/test_codesize_hello_dylink.json @@ -1,10 +1,10 @@ { - "a.out.js": 26976, - "a.out.js.gz": 11458, + "a.out.js": 27164, + "a.out.js.gz": 11514, "a.out.nodebug.wasm": 18567, "a.out.nodebug.wasm.gz": 9199, - "total": 45543, - "total_gz": 20657, + "total": 45731, + "total_gz": 20713, "sent": [ "__heap_base", "__indirect_function_table", diff --git a/test/code_size/test_codesize_hello_dylink_all.json b/test/code_size/test_codesize_hello_dylink_all.json index 018a103b84bf2..2da96ad4272a8 100644 --- a/test/code_size/test_codesize_hello_dylink_all.json +++ b/test/code_size/test_codesize_hello_dylink_all.json @@ -1,7 +1,7 @@ { - "a.out.js": 246331, - "a.out.nodebug.wasm": 597763, - "total": 844094, + "a.out.js": 246519, + "a.out.nodebug.wasm": 597778, + "total": 844297, "sent": [ "IMG_Init", "IMG_Load", diff --git a/test/code_size/test_codesize_mem_O3.json b/test/code_size/test_codesize_mem_O3.json index f08b2cfa3a937..721c8e88c2910 100644 --- a/test/code_size/test_codesize_mem_O3.json +++ b/test/code_size/test_codesize_mem_O3.json @@ -1,10 +1,10 @@ { - "a.out.js": 4399, - "a.out.js.gz": 2112, - "a.out.nodebug.wasm": 5260, - "a.out.nodebug.wasm.gz": 2418, - "total": 9659, - "total_gz": 4530, + "a.out.js": 4581, + "a.out.js.gz": 2194, + "a.out.nodebug.wasm": 5267, + "a.out.nodebug.wasm.gz": 2422, + "total": 9848, + "total_gz": 4616, "sent": [ "a (emscripten_resize_heap)" ], diff --git a/test/code_size/test_codesize_mem_O3_grow.json b/test/code_size/test_codesize_mem_O3_grow.json index b8308e205b9b6..0f77da37b8bde 100644 --- a/test/code_size/test_codesize_mem_O3_grow.json +++ b/test/code_size/test_codesize_mem_O3_grow.json @@ -1,10 +1,10 @@ { - "a.out.js": 4684, - "a.out.js.gz": 2264, - "a.out.nodebug.wasm": 5261, - "a.out.nodebug.wasm.gz": 2418, - "total": 9945, - "total_gz": 4682, + "a.out.js": 4866, + "a.out.js.gz": 2338, + "a.out.nodebug.wasm": 5268, + "a.out.nodebug.wasm.gz": 2421, + "total": 10134, + "total_gz": 4759, "sent": [ "a (emscripten_resize_heap)" ], diff --git a/test/code_size/test_codesize_mem_O3_grow_standalone.json b/test/code_size/test_codesize_mem_O3_grow_standalone.json index c82d80b717277..5ab7c9db61b1a 100644 --- a/test/code_size/test_codesize_mem_O3_grow_standalone.json +++ b/test/code_size/test_codesize_mem_O3_grow_standalone.json @@ -1,10 +1,10 @@ { "a.out.js": 4125, "a.out.js.gz": 1977, - "a.out.nodebug.wasm": 5547, - "a.out.nodebug.wasm.gz": 2597, - "total": 9672, - "total_gz": 4574, + "a.out.nodebug.wasm": 5554, + "a.out.nodebug.wasm.gz": 2599, + "total": 9679, + "total_gz": 4576, "sent": [ "args_get", "args_sizes_get", diff --git a/test/code_size/test_codesize_mem_O3_standalone.json b/test/code_size/test_codesize_mem_O3_standalone.json index ab9bbcaa8b074..771c7c2a476cd 100644 --- a/test/code_size/test_codesize_mem_O3_standalone.json +++ b/test/code_size/test_codesize_mem_O3_standalone.json @@ -1,10 +1,10 @@ { "a.out.js": 4058, "a.out.js.gz": 1941, - "a.out.nodebug.wasm": 5472, - "a.out.nodebug.wasm.gz": 2538, - "total": 9530, - "total_gz": 4479, + "a.out.nodebug.wasm": 5479, + "a.out.nodebug.wasm.gz": 2542, + "total": 9537, + "total_gz": 4483, "sent": [ "args_get", "args_sizes_get", diff --git a/test/code_size/test_codesize_mem_O3_standalone_lib.json b/test/code_size/test_codesize_mem_O3_standalone_lib.json index d67159acdba3e..aa52e981c46e4 100644 --- a/test/code_size/test_codesize_mem_O3_standalone_lib.json +++ b/test/code_size/test_codesize_mem_O3_standalone_lib.json @@ -1,10 +1,10 @@ { "a.out.js": 3602, "a.out.js.gz": 1699, - "a.out.nodebug.wasm": 5239, - "a.out.nodebug.wasm.gz": 2360, - "total": 8841, - "total_gz": 4059, + "a.out.nodebug.wasm": 5246, + "a.out.nodebug.wasm.gz": 2347, + "total": 8848, + "total_gz": 4046, "sent": [], "imports": [], "exports": [ diff --git a/test/code_size/test_codesize_mem_O3_standalone_narg.json b/test/code_size/test_codesize_mem_O3_standalone_narg.json index 2dd5745326ca0..c47dcf1a48a9d 100644 --- a/test/code_size/test_codesize_mem_O3_standalone_narg.json +++ b/test/code_size/test_codesize_mem_O3_standalone_narg.json @@ -1,10 +1,10 @@ { "a.out.js": 3605, "a.out.js.gz": 1708, - "a.out.nodebug.wasm": 5265, - "a.out.nodebug.wasm.gz": 2397, - "total": 8870, - "total_gz": 4105, + "a.out.nodebug.wasm": 5272, + "a.out.nodebug.wasm.gz": 2381, + "total": 8877, + "total_gz": 4089, "sent": [ "proc_exit" ], diff --git a/test/code_size/test_codesize_mem_O3_standalone_narg_flto.json b/test/code_size/test_codesize_mem_O3_standalone_narg_flto.json index 69e3d9ed7e93a..0e8f8da8a3722 100644 --- a/test/code_size/test_codesize_mem_O3_standalone_narg_flto.json +++ b/test/code_size/test_codesize_mem_O3_standalone_narg_flto.json @@ -1,10 +1,10 @@ { "a.out.js": 3605, "a.out.js.gz": 1708, - "a.out.nodebug.wasm": 4077, - "a.out.nodebug.wasm.gz": 2031, - "total": 7682, - "total_gz": 3739, + "a.out.nodebug.wasm": 4085, + "a.out.nodebug.wasm.gz": 2024, + "total": 7690, + "total_gz": 3732, "sent": [ "proc_exit" ], diff --git a/test/code_size/test_codesize_minimal_O0.json b/test/code_size/test_codesize_minimal_O0.json index 31c8077ad2f0f..0874b5051db9f 100644 --- a/test/code_size/test_codesize_minimal_O0.json +++ b/test/code_size/test_codesize_minimal_O0.json @@ -1,10 +1,10 @@ { - "a.out.js": 17757, - "a.out.js.gz": 6623, + "a.out.js": 17769, + "a.out.js.gz": 6628, "a.out.nodebug.wasm": 1136, "a.out.nodebug.wasm.gz": 659, - "total": 18893, - "total_gz": 7282, + "total": 18905, + "total_gz": 7287, "sent": [], "imports": [], "exports": [ diff --git a/test/code_size/test_codesize_minimal_pthreads.json b/test/code_size/test_codesize_minimal_pthreads.json index dae747cce1239..f99b6bc4fe9e5 100644 --- a/test/code_size/test_codesize_minimal_pthreads.json +++ b/test/code_size/test_codesize_minimal_pthreads.json @@ -1,10 +1,10 @@ { "a.out.js": 7659, "a.out.js.gz": 3776, - "a.out.nodebug.wasm": 19592, - "a.out.nodebug.wasm.gz": 9060, - "total": 27251, - "total_gz": 12836, + "a.out.nodebug.wasm": 19597, + "a.out.nodebug.wasm.gz": 9042, + "total": 27256, + "total_gz": 12818, "sent": [ "a (memory)", "b (emscripten_get_now)", diff --git a/test/code_size/test_codesize_minimal_pthreads_memgrowth.json b/test/code_size/test_codesize_minimal_pthreads_memgrowth.json index 521a48e365036..6fc13cadd14a1 100644 --- a/test/code_size/test_codesize_minimal_pthreads_memgrowth.json +++ b/test/code_size/test_codesize_minimal_pthreads_memgrowth.json @@ -1,10 +1,10 @@ { "a.out.js": 8086, "a.out.js.gz": 3977, - "a.out.nodebug.wasm": 19593, - "a.out.nodebug.wasm.gz": 9061, - "total": 27679, - "total_gz": 13038, + "a.out.nodebug.wasm": 19598, + "a.out.nodebug.wasm.gz": 9043, + "total": 27684, + "total_gz": 13020, "sent": [ "a (memory)", "b (emscripten_get_now)", diff --git a/test/code_size/test_minimal_runtime_code_size_hello_embind.json b/test/code_size/test_minimal_runtime_code_size_hello_embind.json index 76987a4e0c590..03e88063cfa39 100644 --- a/test/code_size/test_minimal_runtime_code_size_hello_embind.json +++ b/test/code_size/test_minimal_runtime_code_size_hello_embind.json @@ -1,10 +1,10 @@ { "a.html": 552, "a.html.gz": 373, - "a.js": 7255, - "a.js.gz": 3313, + "a.js": 6902, + "a.js.gz": 3188, "a.wasm": 7315, "a.wasm.gz": 3368, - "total": 15122, - "total_gz": 7054 + "total": 14769, + "total_gz": 6929 } diff --git a/test/code_size/test_minimal_runtime_code_size_hello_embind_val.json b/test/code_size/test_minimal_runtime_code_size_hello_embind_val.json index fa7600e4d2db1..e99b99344301b 100644 --- a/test/code_size/test_minimal_runtime_code_size_hello_embind_val.json +++ b/test/code_size/test_minimal_runtime_code_size_hello_embind_val.json @@ -1,10 +1,10 @@ { "a.html": 552, "a.html.gz": 373, - "a.js": 5350, - "a.js.gz": 2527, + "a.js": 4997, + "a.js.gz": 2396, "a.wasm": 5852, "a.wasm.gz": 2743, - "total": 11754, - "total_gz": 5643 + "total": 11401, + "total_gz": 5512 } diff --git a/test/code_size/test_unoptimized_code_size.json b/test/code_size/test_unoptimized_code_size.json index 1eed6617a859a..c91f0ddf18b19 100644 --- a/test/code_size/test_unoptimized_code_size.json +++ b/test/code_size/test_unoptimized_code_size.json @@ -1,16 +1,16 @@ { - "hello_world.js": 53881, - "hello_world.js.gz": 17016, + "hello_world.js": 53898, + "hello_world.js.gz": 17019, "hello_world.wasm": 15127, "hello_world.wasm.gz": 7450, "no_asserts.js": 26352, "no_asserts.js.gz": 8789, "no_asserts.wasm": 12227, "no_asserts.wasm.gz": 6010, - "strict.js": 51919, - "strict.js.gz": 16352, + "strict.js": 51936, + "strict.js.gz": 16357, "strict.wasm": 15127, "strict.wasm.gz": 7447, - "total": 174633, - "total_gz": 63064 + "total": 174667, + "total_gz": 63072 } diff --git a/test/other/codesize/test_codesize_file_preload.expected.js b/test/other/codesize/test_codesize_file_preload.expected.js index f8ec8a8646ec5..0c23607874e61 100644 --- a/test/other/codesize/test_codesize_file_preload.expected.js +++ b/test/other/codesize/test_codesize_file_preload.expected.js @@ -727,7 +727,14 @@ var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => { var FS_stdin_getChar_buffer = []; +var UTF8Encoder = typeof TextEncoder != "undefined" ? new TextEncoder : undefined; + var lengthBytesUTF8 = str => { + // When using conditional TextEncoder + if (UTF8Encoder) { + return UTF8Encoder.encode(str).length; + } + // Fallback: manual calculation var len = 0; for (var i = 0; i < str.length; ++i) { // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code @@ -754,6 +761,18 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { // Parameter maxBytesToWrite is not optional. Negative values, 0, null, // undefined and false each don't write out any bytes. if (!(maxBytesToWrite > 0)) return 0; + // When using conditional TextEncoder + if (UTF8Encoder) { + var encoded = UTF8Encoder.encode(str); + var bytesToWrite = Math.min(encoded.length, maxBytesToWrite - 1); + // -1 for null terminator + for (var i = 0; i < bytesToWrite; ++i) { + heap[outIdx + i] = encoded[i]; + } + heap[outIdx + bytesToWrite] = 0; + return bytesToWrite; + } + // Fallback: manual UTF-8 encoding var startIdx = outIdx; var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. diff --git a/test/other/codesize/test_codesize_minimal_O0.expected.js b/test/other/codesize/test_codesize_minimal_O0.expected.js index da2b6ec3422f0..cc5b72524dad9 100644 --- a/test/other/codesize/test_codesize_minimal_O0.expected.js +++ b/test/other/codesize/test_codesize_minimal_O0.expected.js @@ -1069,6 +1069,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol) 'PATH', 'PATH_FS', 'UTF8Decoder', + 'UTF8Encoder', 'UTF16Decoder', 'JSEvents', 'specialHTMLTargets', diff --git a/tools/link.py b/tools/link.py index 77b90f00d8d63..cc5cef924b948 100644 --- a/tools/link.py +++ b/tools/link.py @@ -674,7 +674,6 @@ def report_incompatible_settings(): ('GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS', 'NO_GL_SUPPORT_SIMPLE_ENABLE_EXTENSIONS', None), ('MODULARIZE', 'NODEJS_CATCH_REJECTION', None), ('MODULARIZE', 'NODEJS_CATCH_EXIT', None), - ('LEGACY_VM_SUPPORT', 'MEMORY64', None), ] for a, b, reason in incompatible_settings: @@ -1069,16 +1068,21 @@ def limit_incoming_module_api(): if 'noExitRuntime' in settings.INCOMING_MODULE_JS_API: settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.append('$noExitRuntime') - # Default to TEXTDECODER=2 (always use TextDecoder to decode UTF-8 strings) - # in -Oz builds, since custom decoder for UTF-8 takes up space. - # When supporting shell environments, do not do this as TextDecoder is not - # widely supported there. - # In Audio Worklets TextDecoder API is intentionally not exposed - # (https://github.com/WebAudio/web-audio-api/issues/2499) so we also need to - # keep the JavaScript-based fallback. + # Default to TEXTDECODER=2 (always use TextDecoder for decoding UTF-8 strings) + # and TEXTENCODER=2 (always use TextEncoder for encoding UTF-8 strings) + # in -Oz builds to minimize code size, as custom UTF-8 encoder/decoder logic + # adds extra code footprint. + # + # Exceptions: + # - Shell environments: TextDecoder and TextEncoder are not consistently + # available, so we must retain the JavaScript-based fallback. + # - Audio Worklets: The TextDecoder API is intentionally not exposed + # (see: https://github.com/WebAudio/web-audio-api/issues/2499), requiring + # the fallback decoder to remain in place. if settings.SHRINK_LEVEL >= 2 and not settings.AUDIO_WORKLET and \ not settings.ENVIRONMENT_MAY_BE_SHELL: default_setting('TEXTDECODER', 2) + default_setting('TEXTENCODER', 2) # If set to 1, we will run the autodebugger (the automatic debugging tool, see # tools/autodebugger). Note that this will disable inclusion of libraries. This