esnext.json.raw-json.js 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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 push = uncurryThis([].push);
  25. var MARK = uid();
  26. var MARK_LENGTH = MARK.length;
  27. var ERROR_MESSAGE = 'Unacceptable as raw JSON';
  28. var isWhitespace = function (it) {
  29. return it === ' ' || it === '\t' || it === '\n' || it === '\r';
  30. };
  31. // `JSON.parse` method
  32. // https://tc39.es/proposal-json-parse-with-source/#sec-json.israwjson
  33. // https://github.com/tc39/proposal-json-parse-with-source
  34. $({ target: 'JSON', stat: true, forced: !NATIVE_RAW_JSON }, {
  35. rawJSON: function rawJSON(text) {
  36. var jsonString = toString(text);
  37. if (jsonString === '' || isWhitespace(at(jsonString, 0)) || isWhitespace(at(jsonString, jsonString.length - 1))) {
  38. throw new $SyntaxError(ERROR_MESSAGE);
  39. }
  40. var parsed = parse(jsonString);
  41. if (typeof parsed == 'object' && parsed !== null) throw new $SyntaxError(ERROR_MESSAGE);
  42. var obj = create(null);
  43. setInternalState(obj, { type: 'RawJSON' });
  44. createProperty(obj, 'rawJSON', jsonString);
  45. return FREEZING ? freeze(obj) : obj;
  46. }
  47. });
  48. // `JSON.stringify` method
  49. // https://tc39.es/ecma262/#sec-json.stringify
  50. // https://github.com/tc39/proposal-json-parse-with-source
  51. if ($stringify) $({ target: 'JSON', stat: true, arity: 3, forced: !NATIVE_RAW_JSON }, {
  52. stringify: function stringify(text, replacer, space) {
  53. var replacerFunction = getReplacerFunction(replacer);
  54. var rawStrings = [];
  55. var json = $stringify(text, function (key, value) {
  56. // some old implementations (like WebKit) could pass numbers as keys
  57. var v = isCallable(replacerFunction) ? call(replacerFunction, this, $String(key), value) : value;
  58. return isRawJSON(v) ? MARK + (push(rawStrings, v.rawJSON) - 1) : v;
  59. }, space);
  60. if (typeof json != 'string') return json;
  61. var result = '';
  62. var length = json.length;
  63. for (var i = 0; i < length; i++) {
  64. var chr = at(json, i);
  65. if (chr === '"') {
  66. var end = parseJSONString(json, ++i).end - 1;
  67. var string = slice(json, i, end);
  68. result += slice(string, 0, MARK_LENGTH) === MARK
  69. ? rawStrings[slice(string, MARK_LENGTH)]
  70. : '"' + string + '"';
  71. i = end;
  72. } else result += chr;
  73. }
  74. return result;
  75. }
  76. });