esnext.string.to-well-formed.js 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  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. var $toWellFormed = ''.toWellFormed;
  13. var REPLACEMENT_CHARACTER = '\uFFFD';
  14. // Safari bug
  15. var TO_STRING_CONVERSION_BUG = $toWellFormed && fails(function () {
  16. return call($toWellFormed, 1) !== '1';
  17. });
  18. // `String.prototype.toWellFormed` method
  19. // https://github.com/tc39/proposal-is-usv-string
  20. $({ target: 'String', proto: true, forced: TO_STRING_CONVERSION_BUG }, {
  21. toWellFormed: function toWellFormed() {
  22. var S = toString(requireObjectCoercible(this));
  23. if (TO_STRING_CONVERSION_BUG) return call($toWellFormed, S);
  24. var length = S.length;
  25. var result = $Array(length);
  26. for (var i = 0; i < length; i++) {
  27. var charCode = charCodeAt(S, i);
  28. // single UTF-16 code unit
  29. if ((charCode & 0xF800) != 0xD800) result[i] = charAt(S, i);
  30. // unpaired surrogate
  31. else if (charCode >= 0xDC00 || i + 1 >= length || (charCodeAt(S, i + 1) & 0xFC00) != 0xDC00) result[i] = REPLACEMENT_CHARACTER;
  32. // surrogate pair
  33. else {
  34. result[i] = charAt(S, i);
  35. result[++i] = charAt(S, i);
  36. }
  37. } return join(result, '');
  38. }
  39. });