esnext.json.raw-json.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. 'use strict';
  2. var $ = require('../internals/export');
  3. var FREEZING = require('../internals/freezing');
  4. var NATIVE_RAW_JSON = require('../internals/native-raw-json');
  5. var getBuiltIn = require('../internals/get-built-in');
  6. var call = require('../internals/function-call');
  7. var uncurryThis = require('../internals/function-uncurry-this');
  8. var isCallable = require('../internals/is-callable');
  9. var isRawJSON = require('../internals/is-raw-json');
  10. var toString = require('../internals/to-string');
  11. var createProperty = require('../internals/create-property');
  12. var parseJSONString = require('../internals/parse-json-string');
  13. var getReplacerFunction = require('../internals/get-json-replacer-function');
  14. var uid = require('../internals/uid');
  15. var setInternalState = require('../internals/internal-state').set;
  16. var $String = String;
  17. var $SyntaxError = SyntaxError;
  18. var parse = getBuiltIn('JSON', 'parse');
  19. var $stringify = getBuiltIn('JSON', 'stringify');
  20. var create = getBuiltIn('Object', 'create');
  21. var freeze = getBuiltIn('Object', 'freeze');
  22. var at = uncurryThis(''.charAt);
  23. var slice = uncurryThis(''.slice);
  24. var exec = uncurryThis(/./.exec);
  25. var push = uncurryThis([].push);
  26. var MARK = uid();
  27. var MARK_LENGTH = MARK.length;
  28. var ERROR_MESSAGE = 'Unacceptable as raw JSON';
  29. var IS_WHITESPACE = /^[\t\n\r ]$/;
  30. // `JSON.parse` method
  31. // https://tc39.es/proposal-json-parse-with-source/#sec-json.israwjson
  32. // https://github.com/tc39/proposal-json-parse-with-source
  33. $({ target: 'JSON', stat: true, forced: !NATIVE_RAW_JSON }, {
  34. rawJSON: function rawJSON(text) {
  35. var jsonString = toString(text);
  36. if (jsonString === '' || exec(IS_WHITESPACE, at(jsonString, 0)) || exec(IS_WHITESPACE, at(jsonString, jsonString.length - 1))) {
  37. throw new $SyntaxError(ERROR_MESSAGE);
  38. }
  39. var parsed = parse(jsonString);
  40. if (typeof parsed == 'object' && parsed !== null) throw new $SyntaxError(ERROR_MESSAGE);
  41. var obj = create(null);
  42. setInternalState(obj, { type: 'RawJSON' });
  43. createProperty(obj, 'rawJSON', jsonString);
  44. return FREEZING ? freeze(obj) : obj;
  45. }
  46. });
  47. // `JSON.stringify` method
  48. // https://tc39.es/ecma262/#sec-json.stringify
  49. // https://github.com/tc39/proposal-json-parse-with-source
  50. if ($stringify) $({ target: 'JSON', stat: true, arity: 3, forced: !NATIVE_RAW_JSON }, {
  51. stringify: function stringify(text, replacer, space) {
  52. var replacerFunction = getReplacerFunction(replacer);
  53. var rawStrings = [];
  54. var json = $stringify(text, function (key, value) {
  55. // some old implementations (like WebKit) could pass numbers as keys
  56. var v = isCallable(replacerFunction) ? call(replacerFunction, this, $String(key), value) : value;
  57. return isRawJSON(v) ? MARK + (push(rawStrings, v.rawJSON) - 1) : v;
  58. }, space);
  59. if (typeof json != 'string') return json;
  60. var result = '';
  61. var length = json.length;
  62. for (var i = 0; i < length; i++) {
  63. var chr = at(json, i);
  64. if (chr === '"') {
  65. var end = parseJSONString(json, ++i).end - 1;
  66. var string = slice(json, i, end);
  67. result += slice(string, 0, MARK_LENGTH) === MARK
  68. ? rawStrings[slice(string, MARK_LENGTH)]
  69. : '"' + string + '"';
  70. i = end;
  71. } else result += chr;
  72. }
  73. return result;
  74. }
  75. });