@@ -318,8 +318,8 @@ public struct BridgeJSLink {
318318 /// The wasm32 12-byte Swift `String` layout is a standard-library
319319 /// implementation detail, not a stable ABI. Small strings (`word2 & 0x2000`)
320320 /// store up to 10 UTF-8 bytes inline. Large strings store the UTF-8 count in
321- /// `word0` and a storage pointer in `word1` already biased by `nativeBias`
322- /// (20), so UTF-8 starts at `word1 + 20` . Immortal large strings
321+ /// `word0` and a variant/object pointer in `word1`; UTF-8 starts at
322+ /// `word1 + nativeBias` (20 on 32-bit) . Immortal large strings
323323 /// (`word2 & 0x8000`) are cached by a 53-bit `ptr + len * 2**32` key when
324324 /// `len < 2**21`; longer immortals skip the cache.
325325 private func emitDecodeString( _ printer: CodeFragmentPrinter ) {
@@ -366,103 +366,74 @@ public struct BridgeJSLink {
366366 }
367367 // Match TextDecoder: consume exactly one leading UTF-8 BOM.
368368 if (start === 0 && codePoint === 0xfeff) continue;
369- if (codePoint <= 0xffff) {
370- switch (unitCount++) {
371- case 0:
372- u0 = codePoint;
373- break;
374- case 1:
375- u1 = codePoint;
376- break;
377- case 2:
378- u2 = codePoint;
379- break;
380- case 3:
381- u3 = codePoint;
382- break;
383- case 4:
384- u4 = codePoint;
385- break;
386- case 5:
387- u5 = codePoint;
388- break;
389- case 6:
390- u6 = codePoint;
391- break;
392- case 7:
393- u7 = codePoint;
394- break;
395- case 8:
396- u8 = codePoint;
397- break;
398- case 9:
399- u9 = codePoint;
400- break;
401- }
402- } else {
403- codePoint -= 0x10000;
404- switch (unitCount++) {
405- case 0:
406- u0 = 0xd800 + (codePoint >>> 10);
407- break;
408- case 1:
409- u1 = 0xd800 + (codePoint >>> 10);
410- break;
411- case 2:
412- u2 = 0xd800 + (codePoint >>> 10);
413- break;
414- case 3:
415- u3 = 0xd800 + (codePoint >>> 10);
416- break;
417- case 4:
418- u4 = 0xd800 + (codePoint >>> 10);
419- break;
420- case 5:
421- u5 = 0xd800 + (codePoint >>> 10);
422- break;
423- case 6:
424- u6 = 0xd800 + (codePoint >>> 10);
425- break;
426- case 7:
427- u7 = 0xd800 + (codePoint >>> 10);
428- break;
429- case 8:
430- u8 = 0xd800 + (codePoint >>> 10);
431- break;
432- case 9:
433- u9 = 0xd800 + (codePoint >>> 10);
434- break;
435- }
369+ const supplementary = codePoint > 0xffff;
370+ const codeUnit = supplementary
371+ ? 0xd800 + ((codePoint - 0x10000) >>> 10)
372+ : codePoint;
373+ switch (unitCount++) {
374+ case 0:
375+ u0 = codeUnit;
376+ break;
377+ case 1:
378+ u1 = codeUnit;
379+ break;
380+ case 2:
381+ u2 = codeUnit;
382+ break;
383+ case 3:
384+ u3 = codeUnit;
385+ break;
386+ case 4:
387+ u4 = codeUnit;
388+ break;
389+ case 5:
390+ u5 = codeUnit;
391+ break;
392+ case 6:
393+ u6 = codeUnit;
394+ break;
395+ case 7:
396+ u7 = codeUnit;
397+ break;
398+ case 8:
399+ u8 = codeUnit;
400+ break;
401+ case 9:
402+ u9 = codeUnit;
403+ break;
404+ }
405+ if (supplementary) {
406+ const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023);
436407 switch (unitCount++) {
437408 case 0:
438- u0 = 0xdc00 + (codePoint & 1023) ;
409+ u0 = lowSurrogate ;
439410 break;
440411 case 1:
441- u1 = 0xdc00 + (codePoint & 1023) ;
412+ u1 = lowSurrogate ;
442413 break;
443414 case 2:
444- u2 = 0xdc00 + (codePoint & 1023) ;
415+ u2 = lowSurrogate ;
445416 break;
446417 case 3:
447- u3 = 0xdc00 + (codePoint & 1023) ;
418+ u3 = lowSurrogate ;
448419 break;
449420 case 4:
450- u4 = 0xdc00 + (codePoint & 1023) ;
421+ u4 = lowSurrogate ;
451422 break;
452423 case 5:
453- u5 = 0xdc00 + (codePoint & 1023) ;
424+ u5 = lowSurrogate ;
454425 break;
455426 case 6:
456- u6 = 0xdc00 + (codePoint & 1023) ;
427+ u6 = lowSurrogate ;
457428 break;
458429 case 7:
459- u7 = 0xdc00 + (codePoint & 1023) ;
430+ u7 = lowSurrogate ;
460431 break;
461432 case 8:
462- u8 = 0xdc00 + (codePoint & 1023) ;
433+ u8 = lowSurrogate ;
463434 break;
464435 case 9:
465- u9 = 0xdc00 + (codePoint & 1023) ;
436+ u9 = lowSurrogate ;
466437 break;
467438 }
468439 }
@@ -506,7 +477,8 @@ public struct BridgeJSLink {
506477 case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff);
507478 case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff);
508479 case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24);
509- default: return decodeSmallUTF8(word0, word1, word2, count);
480+ case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff);
481+ case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff);
510482 }
511483 };
512484 return (word0, word1, word2) => {
0 commit comments