@@ -1445,18 +1445,51 @@ impl<'a> Context<'a> {
1445
1445
self . expose_text_encoder ( ) ;
1446
1446
self . expose_uint8_memory ( ) ;
1447
1447
1448
+ // A fast path that directly writes char codes into WASM memory as long
1449
+ // as it finds only ASCII characters.
1450
+ //
1451
+ // This is much faster for common ASCII strings because it can avoid
1452
+ // calling out into C++ TextEncoder code.
1453
+ //
1454
+ // This might be not very intuitive, but such calls are usually more
1455
+ // expensive in mainstream engines than staying in the JS, and
1456
+ // charCodeAt on ASCII strings is usually optimised to raw bytes.
1457
+ let start_encoding_as_ascii = format ! (
1458
+ "
1459
+ {}
1460
+ let size = arg.length;
1461
+ let ptr = wasm.__wbindgen_malloc(size);
1462
+ let offset = 0;
1463
+ {{
1464
+ const mem = getUint8Memory();
1465
+ for (; offset < arg.length; offset++) {{
1466
+ const code = arg.charCodeAt(offset);
1467
+ if (code > 0x7F) {{
1468
+ arg = arg.slice(offset);
1469
+ break;
1470
+ }}
1471
+ mem[ptr + offset] = code;
1472
+ }}
1473
+ }}
1474
+ " ,
1475
+ debug
1476
+ ) ;
1477
+
1448
1478
// The first implementation we have for this is to use
1449
1479
// `TextEncoder#encode` which has been around for quite some time.
1450
1480
let use_encode = format ! (
1451
1481
"
1452
1482
{}
1453
- const buf = cachedTextEncoder.encode(arg);
1454
- const ptr = wasm.__wbindgen_malloc(buf.length);
1455
- getUint8Memory().set(buf, ptr);
1456
- WASM_VECTOR_LEN = buf.length;
1483
+ if (offset !== arg.length) {{
1484
+ const buf = cachedTextEncoder.encode(arg);
1485
+ ptr = wasm.__wbindgen_realloc(ptr, size, size += buf.length);
1486
+ getUint8Memory().set(buf, ptr + offset);
1487
+ offset += buf.length;
1488
+ }}
1489
+ WASM_VECTOR_LEN = offset;
1457
1490
return ptr;
1458
1491
" ,
1459
- debug
1492
+ start_encoding_as_ascii
1460
1493
) ;
1461
1494
1462
1495
// Another possibility is to use `TextEncoder#encodeInto` which is much
@@ -1465,23 +1498,15 @@ impl<'a> Context<'a> {
1465
1498
let use_encode_into = format ! (
1466
1499
"
1467
1500
{}
1468
- let size = arg.length;
1469
- let ptr = wasm.__wbindgen_malloc(size);
1470
- let writeOffset = 0;
1471
- while (true) {{
1472
- const view = getUint8Memory().subarray(ptr + writeOffset, ptr + size);
1473
- const {{ read, written }} = cachedTextEncoder.encodeInto(arg, view);
1474
- writeOffset += written;
1475
- if (read === arg.length) {{
1476
- break;
1477
- }}
1478
- arg = arg.substring(read);
1501
+ if (offset !== arg.length) {{
1479
1502
ptr = wasm.__wbindgen_realloc(ptr, size, size += arg.length * 3);
1503
+ const view = getUint8Memory().subarray(ptr + offset, ptr + size);
1504
+ offset += cachedTextEncoder.encodeInto(arg, view).written;
1480
1505
}}
1481
- WASM_VECTOR_LEN = writeOffset ;
1506
+ WASM_VECTOR_LEN = offset ;
1482
1507
return ptr;
1483
1508
" ,
1484
- debug
1509
+ start_encoding_as_ascii
1485
1510
) ;
1486
1511
1487
1512
// Looks like `encodeInto` doesn't currently work when the memory passed
0 commit comments