es.string.to-well-formed.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. 'use strict';
  2. var $ = require('../internals/export');
  3. var call = require('../internals/function-call');
  4. var uncurryThis = require('../internals/function-uncurry-this');
  5. var requireObjectCoercible = require('../internals/require-object-coercible');
  6. var toString = require('../internals/to-string');
  7. var fails = require('../internals/fails');
  8. var $Array = Array;
  9. var charAt = uncurryThis(''.charAt);
  10. var charCodeAt = uncurryThis(''.charCodeAt);
  11. var join = uncurryThis([].join);
  12. // eslint-disable-next-line es/no-string-prototype-iswellformed-towellformed -- safe
  13. var $toWellFormed = ''.toWellFormed;
  14. var REPLACEMENT_CHARACTER = '\uFFFD';
  15. // Safari bug
  16. var TO_STRING_CONVERSION_BUG = $toWellFormed && fails(function () {
  17. return call($toWellFormed, 1) !== '1';
  18. });
  19. // `String.prototype.toWellFormed` method
  20. // https://github.com/tc39/proposal-is-usv-string
  21. $({ target: 'String', proto: true, forced: TO_STRING_CONVERSION_BUG }, {
  22. toWellFormed: function toWellFormed() {
  23. var S = toString(requireObjectCoercible(this));
  24. if (TO_STRING_CONVERSION_BUG) return call($toWellFormed, S);
  25. var length = S.length;
  26. var result = $Array(length);
  27. for (var i = 0; i < length; i++) {
  28. var charCode = charCodeAt(S, i);
  29. // single UTF-16 code unit
  30. if ((charCode & 0xF800) !== 0xD800) result[i] = charAt(S, i);
  31. // unpaired surrogate
  32. else if (charCode >= 0xDC00 || i + 1 >= length || (charCodeAt(S, i + 1) & 0xFC00) !== 0xDC00) result[i] = REPLACEMENT_CHARACTER;
  33. // surrogate pair
  34. else {
  35. result[i] = charAt(S, i);
  36. result[++i] = charAt(S, i);
  37. }
  38. } return join(result, '');
  39. }
  40. });