mirror of
https://github.com/hanzoai/core-js.git
synced 2026-09-24 16:58:15 +00:00
move JSON.parse source text access to stable ES
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
### Unreleased
|
||||
- [`JSON.parse` source text access proposal](https://github.com/tc39/proposal-json-parse-with-source) :
|
||||
- Built-ins:
|
||||
- `JSON.isRawJSON`
|
||||
- `JSON.parse`
|
||||
- `JSON.rawJSON`
|
||||
- `JSON.stringify`
|
||||
- Moved to stable ES, November 2025 TC39 meeting
|
||||
- Added `es.` namespace modules, `/es/` and `/stable/` namespaces entries
|
||||
- Reworked `JSON.stringify` internals
|
||||
- [`Iterator` sequencing proposal](https://github.com/tc39/proposal-iterator-sequencing):
|
||||
- Built-ins:
|
||||
- `Iterator.concat`
|
||||
|
||||
@@ -164,6 +164,7 @@ structuredClone(new Set([1, 2, 3])); // => new Set([1, 2, 3])
|
||||
- [`Promise.withResolvers`](#promisewithresolvers)
|
||||
- [`Symbol.asyncIterator` for asynchronous iteration](#symbolasynciterator-for-asynchronous-iteration)
|
||||
- [`Symbol.prototype.description`](#symbolprototypedescription)
|
||||
- [`JSON.parse` source text access](#jsonparse-source-text-access)
|
||||
- [Well-formed `JSON.stringify`](#well-formed-jsonstringify)
|
||||
- [Well-formed unicode strings](#well-formed-unicode-strings)
|
||||
- [New `Set` methods](#new-set-methods)
|
||||
@@ -171,7 +172,6 @@ structuredClone(new Set([1, 2, 3])); // => new Set([1, 2, 3])
|
||||
- [Stage 3 proposals](#stage-3-proposals)
|
||||
- [Joint iteration](#joint-iteration)
|
||||
- [`Map` upsert](#map-upsert)
|
||||
- [`JSON.parse` source text access](#jsonparse-source-text-access)
|
||||
- [`Symbol.metadata` for decorators metadata proposal](#symbolmetadata-for-decorators-metadata-proposal)
|
||||
- [Stage 2.7 proposals](#stage-27-proposals)
|
||||
- [`Iterator` chunking](#iterator-chunking)
|
||||
@@ -2139,23 +2139,47 @@ instance.c; // => 42
|
||||
```
|
||||
|
||||
#### ECMAScript: JSON[⬆](#index)
|
||||
Since `JSON` object is missed only in very old engines like IE7-, `core-js` does not provide a full `JSON` polyfill, however, fix already existing implementations by the current standard, for example, [well-formed `JSON.stringify`](https://github.com/tc39/proposal-well-formed-stringify). `JSON` is also fixed in other modules - for example, `Symbol` polyfill fixes `JSON.stringify` for correct work with symbols.
|
||||
Since `JSON` object is missed only in very old engines like IE7-, `core-js` does not provide a full `JSON.{ parse, stringify }` polyfill, however, fix already existing implementations by the current standard.
|
||||
|
||||
Module [`es.json.to-string-tag`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.to-string-tag.js) and [`es.json.stringify`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.stringify.js).
|
||||
Modules [`es.json.is-raw-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.is-raw-json.js), [`es.json.parse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.parse.js), [`es.json.raw-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.raw-json.js), [`es.json.stringify`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.stringify.js) and [`es.json.to-string-tag`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.to-string-tag.js) .
|
||||
```ts
|
||||
namespace JSON {
|
||||
isRawJSON(O: any): boolean;
|
||||
parse(text: string, reviver?: (this: any, key: string, value: any, context: { source?: string }) => any): any;
|
||||
rawJSON(text: any): RawJSON;
|
||||
stringify(value: any, replacer?: Array<string | number> | (this: any, key: string, value: any) => any, space?: string | number): string | void;
|
||||
@@toStringTag: 'JSON';
|
||||
}
|
||||
```
|
||||
[*CommonJS entry points:*](#commonjs-api)
|
||||
```
|
||||
core-js(-pure)/es|stable|actual|full/json/is-raw-json
|
||||
core-js(-pure)/es|stable|actual|full/json/parse
|
||||
core-js(-pure)/es|stable|actual|full/json/raw-json
|
||||
core-js(-pure)/es|stable|actual|full/json/stringify
|
||||
core-js(-pure)/es|stable|actual|full/json/stringify
|
||||
core-js(-pure)/es|stable|actual|full/json/to-string-tag
|
||||
```
|
||||
[*Examples*](https://is.gd/izZqKn):
|
||||
[*Examples*](https://tinyurl.com/34ctm7cn):
|
||||
```js
|
||||
JSON.stringify({ '𠮷': ['\uDF06\uD834'] }); // => '{"𠮷":["\\udf06\\ud834"]}'
|
||||
|
||||
function digitsToBigInt(key, val, { source }) {
|
||||
return /^\d+$/.test(source) ? BigInt(source) : val;
|
||||
}
|
||||
|
||||
function bigIntToRawJSON(key, val) {
|
||||
return typeof val === 'bigint' ? JSON.rawJSON(String(val)) : val;
|
||||
}
|
||||
|
||||
const tooBigForNumber = BigInt(Number.MAX_SAFE_INTEGER) + 2n;
|
||||
JSON.parse(String(tooBigForNumber), digitsToBigInt) === tooBigForNumber; // true
|
||||
|
||||
const wayTooBig = BigInt(`1${ '0'.repeat(1000) }`);
|
||||
JSON.parse(String(wayTooBig), digitsToBigInt) === wayTooBig; // true
|
||||
|
||||
const embedded = JSON.stringify({ tooBigForNumber }, bigIntToRawJSON);
|
||||
embedded === '{"tooBigForNumber":9007199254740993}'; // true
|
||||
```
|
||||
|
||||
#### ECMAScript: globalThis[⬆](#index)
|
||||
@@ -2649,6 +2673,23 @@ class Symbol {
|
||||
```
|
||||
core-js/proposals/symbol-description
|
||||
```
|
||||
|
||||
##### [`JSON.parse` source text access](https://github.com/tc39/proposal-json-parse-with-source)[⬆](#index)
|
||||
```ts
|
||||
namespace JSON {
|
||||
isRawJSON(O: any): boolean;
|
||||
// patched for source support
|
||||
parse(text: string, reviver?: (this: any, key: string, value: any, context: { source?: string }) => any): any;
|
||||
rawJSON(text: any): RawJSON;
|
||||
// patched for `JSON.rawJSON` support
|
||||
stringify(value: any, replacer?: Array<string | number> | (this: any, key: string, value: any) => any, space?: string | number): string | void;
|
||||
}
|
||||
```
|
||||
[*CommonJS entry points:*](#commonjs-api)
|
||||
```
|
||||
core-js/proposals/json-parse-with-source
|
||||
```
|
||||
|
||||
##### [Well-formed `JSON.stringify`](https://github.com/tc39/proposal-well-formed-stringify)[⬆](#index)
|
||||
```ts
|
||||
namespace JSON {
|
||||
@@ -2792,46 +2833,6 @@ map.getOrInsertComputed('c', key => key); // => 'c'
|
||||
console.log(map); // => Map { 'a': 1, 'b': 3, 'c': 'c' }
|
||||
```
|
||||
|
||||
##### [`JSON.parse` source text access](https://github.com/tc39/proposal-json-parse-with-source)[⬆](#index)
|
||||
Modules [`esnext.json.is-raw-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.json.is-raw-json.js), [`esnext.json.parse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.json.parse.js), [`esnext.json.raw-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.json.raw-json.js).
|
||||
```ts
|
||||
namespace JSON {
|
||||
isRawJSON(O: any): boolean;
|
||||
// patched for source support
|
||||
parse(text: string, reviver?: (this: any, key: string, value: any, context: { source?: string }) => any): any;
|
||||
rawJSON(text: any): RawJSON;
|
||||
// patched for `JSON.rawJSON` support
|
||||
stringify(value: any, replacer?: Array<string | number> | (this: any, key: string, value: any) => any, space?: string | number): string | void;
|
||||
}
|
||||
```
|
||||
[*CommonJS entry points:*](#commonjs-api)
|
||||
```
|
||||
core-js/proposals/json-parse-with-source
|
||||
core-js(-pure)/actual|full/json/is-raw-json
|
||||
core-js(-pure)/actual|full/json/parse
|
||||
core-js(-pure)/actual|full/json/raw-json
|
||||
core-js(-pure)/actual|full/json/stringify
|
||||
```
|
||||
[*Examples*](https://tinyurl.com/22phm569):
|
||||
```js
|
||||
function digitsToBigInt(key, val, { source }) {
|
||||
return /^\d+$/.test(source) ? BigInt(source) : val;
|
||||
}
|
||||
|
||||
function bigIntToRawJSON(key, val) {
|
||||
return typeof val === 'bigint' ? JSON.rawJSON(String(val)) : val;
|
||||
}
|
||||
|
||||
const tooBigForNumber = BigInt(Number.MAX_SAFE_INTEGER) + 2n;
|
||||
JSON.parse(String(tooBigForNumber), digitsToBigInt) === tooBigForNumber; // true
|
||||
|
||||
const wayTooBig = BigInt(`1${ '0'.repeat(1000) }`);
|
||||
JSON.parse(String(wayTooBig), digitsToBigInt) === wayTooBig; // true
|
||||
|
||||
const embedded = JSON.stringify({ tooBigForNumber }, bigIntToRawJSON);
|
||||
embedded === '{"tooBigForNumber":9007199254740993}'; // true
|
||||
```
|
||||
|
||||
##### [`Symbol.metadata` for decorators metadata proposal](https://github.com/tc39/proposal-decorator-metadata)[⬆](#index)
|
||||
Modules [`esnext.symbol.metadata`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.symbol.metadata.js) and [`esnext.function.metadata`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.function.metadata.js).
|
||||
```ts
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
# ECMAScript: JSON
|
||||
Since `JSON` object is missed only in very old engines like IE7-, `core-js` does not provide a full `JSON` polyfill, however, fix already existing implementations by the current standard, for example, [well-formed `JSON.stringify`](https://github.com/tc39/proposal-well-formed-stringify). `JSON` is also fixed in other modules - for example, `Symbol` polyfill fixes `JSON.stringify` for correct work with symbols.
|
||||
Since `JSON` object is missed only in very old engines like IE7-, `core-js` does not provide a full `JSON.{ parse, stringify }` polyfill, however, fix already existing implementations by the current standard.
|
||||
|
||||
## Modules
|
||||
[`es.json.to-string-tag`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.to-string-tag.js) and [`es.json.stringify`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.stringify.js).
|
||||
[`es.json.is-raw-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.is-raw-json.js), [`es.json.parse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.parse.js), [`es.json.raw-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.raw-json.js), [`es.json.stringify`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.stringify.js) and [`es.json.to-string-tag`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.to-string-tag.js).
|
||||
|
||||
## Built-ins signatures
|
||||
```ts
|
||||
namespace JSON {
|
||||
isRawJSON(O: any): boolean;
|
||||
parse(text: string, reviver?: (this: any, key: string, value: any, context: { source?: string }) => any): any;
|
||||
rawJSON(text: any): RawJSON;
|
||||
stringify(value: any, replacer?: Array<string | number> | (this: any, key: string, value: any) => any, space?: string | number): string | void;
|
||||
@@toStringTag: 'JSON';
|
||||
}
|
||||
@@ -14,11 +17,29 @@ namespace JSON {
|
||||
|
||||
## [Entry points]({docs-version}/docs/usage#h-entry-points)
|
||||
```
|
||||
core-js(-pure)/es|stable|actual|full/json/stringify
|
||||
core-js(-pure)/es|stable|actual|full/json/is-raw-json
|
||||
core-js(-pure)/es|stable|actual|full/json/parse
|
||||
core-js(-pure)/es|stable|actual|full/json/raw-json
|
||||
core-js(-pure)/es|stable|actual|full/json/to-string-tag
|
||||
```
|
||||
|
||||
## Examples
|
||||
```js
|
||||
function digitsToBigInt(key, val, { source }) {
|
||||
return /^\d+$/.test(source) ? BigInt(source) : val;
|
||||
}
|
||||
|
||||
function bigIntToRawJSON(key, val) {
|
||||
return typeof val === 'bigint' ? JSON.rawJSON(String(val)) : val;
|
||||
}
|
||||
|
||||
const tooBigForNumber = BigInt(Number.MAX_SAFE_INTEGER) + 2n;
|
||||
JSON.parse(String(tooBigForNumber), digitsToBigInt) === tooBigForNumber; // => true
|
||||
|
||||
const wayTooBig = BigInt(`1${ '0'.repeat(1000) }`);
|
||||
JSON.parse(String(wayTooBig), digitsToBigInt) === wayTooBig; // => true
|
||||
|
||||
JSON.stringify({ tooBigForNumber }, bigIntToRawJSON); // => '{"tooBigForNumber":9007199254740993}'
|
||||
|
||||
JSON.stringify({ '𠮷': ['\uDF06\uD834'] }); // => '{"𠮷":["\\udf06\\ud834"]}'
|
||||
```
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[Proposal repo](https://github.com/tc39/proposal-json-parse-with-source)
|
||||
|
||||
## Modules
|
||||
[`esnext.json.is-raw-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.json.is-raw-json.js), [`esnext.json.parse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.json.parse.js), [`esnext.json.raw-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.json.raw-json.js).
|
||||
[`es.json.is-raw-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.is-raw-json.js), [`es.json.parse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.parse.js), [`es.json.raw-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.json.raw-json.js).
|
||||
|
||||
## Built-ins signatures
|
||||
```ts
|
||||
@@ -20,10 +20,10 @@ namespace JSON {
|
||||
## [Entry points]({docs-version}/docs/usage#h-entry-points)
|
||||
```ts
|
||||
core-js/proposals/json-parse-with-source
|
||||
core-js(-pure)/actual|full/json/is-raw-json
|
||||
core-js(-pure)/actual|full/json/parse
|
||||
core-js(-pure)/actual|full/json/raw-json
|
||||
core-js(-pure)/actual|full/json/stringify
|
||||
core-js(-pure)/es|stable|actual|full/json/is-raw-json
|
||||
core-js(-pure)/es|stable|actual|full/json/parse
|
||||
core-js(-pure)/es|stable|actual|full/json/raw-json
|
||||
core-js(-pure)/es|stable|actual|full/json/stringify
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -221,6 +221,10 @@
|
||||
"title": "Symbol.prototype.description",
|
||||
"url": "{docs-version}/docs/features/proposals/symbol-prototype-description"
|
||||
},
|
||||
{
|
||||
"title": "JSON.parse source text access",
|
||||
"url": "{docs-version}/docs/features/proposals/json-parse-source-text-access"
|
||||
},
|
||||
{
|
||||
"title": "Well-formed JSON.stringify",
|
||||
"url": "{docs-version}/docs/features/proposals/well-formed-jsonstringify"
|
||||
@@ -250,10 +254,6 @@
|
||||
"title": "Map upsert",
|
||||
"url": "{docs-version}/docs/features/proposals/map-upsert"
|
||||
},
|
||||
{
|
||||
"title": "JSON.parse source text access",
|
||||
"url": "{docs-version}/docs/features/proposals/json-parse-source-text-access"
|
||||
},
|
||||
{
|
||||
"title": "Symbol.metadata for decorators metadata proposal",
|
||||
"url": "{docs-version}/docs/features/proposals/symbol-metadata"
|
||||
|
||||
@@ -806,13 +806,35 @@ export const data = {
|
||||
firefox: '131',
|
||||
safari: '18.4',
|
||||
},
|
||||
'es.json.is-raw-json': {
|
||||
bun: '1.1.43',
|
||||
chrome: '114',
|
||||
// enabled in 132 and disabled in 133 because of regression, https://bugzilla.mozilla.org/show_bug.cgi?id=1925334
|
||||
firefox: '135', // '132',
|
||||
safari: '18.4',
|
||||
},
|
||||
'es.json.parse': {
|
||||
bun: '1.1.43',
|
||||
chrome: '114',
|
||||
// enabled in 132 and disabled in 133 because of regression, https://bugzilla.mozilla.org/show_bug.cgi?id=1925334
|
||||
firefox: '135', // '132',
|
||||
safari: '18.4',
|
||||
},
|
||||
'es.json.raw-json': {
|
||||
bun: '1.1.43',
|
||||
chrome: '114',
|
||||
// enabled in 132 and disabled in 133 because of regression, https://bugzilla.mozilla.org/show_bug.cgi?id=1925334
|
||||
firefox: '135', // '132',
|
||||
safari: '18.4',
|
||||
},
|
||||
'es.json.stringify': {
|
||||
chrome: '72',
|
||||
firefox: '64',
|
||||
hermes: '0.13',
|
||||
'react-native': '0.72',
|
||||
rhino: '1.8.0',
|
||||
safari: '12.1',
|
||||
bun: '1.1.43',
|
||||
chrome: '114', // '72',
|
||||
firefox: '135', // '132', '64',
|
||||
// hermes: '0.13',
|
||||
// 'react-native': '0.72',
|
||||
// rhino: '1.8.0',
|
||||
safari: '18.4', // '12.1',
|
||||
},
|
||||
'es.json.to-string-tag': {
|
||||
chrome: '50',
|
||||
@@ -2551,27 +2573,12 @@ export const data = {
|
||||
},
|
||||
'esnext.iterator.zip-keyed': {
|
||||
},
|
||||
'esnext.json.is-raw-json': {
|
||||
bun: '1.1.43',
|
||||
chrome: '114',
|
||||
// enabled in 132 and disabled in 133 because of regression, https://bugzilla.mozilla.org/show_bug.cgi?id=1925334
|
||||
firefox: '135', // '132',
|
||||
safari: '18.4',
|
||||
},
|
||||
'esnext.json.parse': {
|
||||
bun: '1.1.43',
|
||||
chrome: '114',
|
||||
// enabled in 132 and disabled in 133 because of regression, https://bugzilla.mozilla.org/show_bug.cgi?id=1925334
|
||||
firefox: '135', // '132',
|
||||
safari: '18.4',
|
||||
},
|
||||
'esnext.json.raw-json': {
|
||||
bun: '1.1.43',
|
||||
chrome: '114',
|
||||
// enabled in 132 and disabled in 133 because of regression, https://bugzilla.mozilla.org/show_bug.cgi?id=1925334
|
||||
firefox: '135', // '132',
|
||||
safari: '18.4',
|
||||
},
|
||||
// TODO: Remove from `core-js@4`
|
||||
'esnext.json.is-raw-json': null,
|
||||
// TODO: Remove from `core-js@4`
|
||||
'esnext.json.parse': null,
|
||||
// TODO: Remove from `core-js@4`
|
||||
'esnext.json.raw-json': null,
|
||||
'esnext.map.delete-all': {
|
||||
},
|
||||
// TODO: Remove from `core-js@4`
|
||||
@@ -3183,6 +3190,9 @@ export const renamed = new Map([
|
||||
['esnext.iterator.some', 'es.iterator.some'],
|
||||
['esnext.iterator.take', 'es.iterator.take'],
|
||||
['esnext.iterator.to-array', 'es.iterator.to-array'],
|
||||
['esnext.json.is-raw-json', 'es.json.is-raw-json'],
|
||||
['esnext.json.parse', 'es.json.parse'],
|
||||
['esnext.json.raw-json', 'es.json.raw-json'],
|
||||
['esnext.map.group-by', 'es.map.group-by'],
|
||||
['esnext.math.f16round', 'es.math.f16round'],
|
||||
['esnext.math.sum-precise', 'es.math.sum-precise'],
|
||||
|
||||
@@ -313,5 +313,8 @@ export default {
|
||||
],
|
||||
3.47: [
|
||||
'es.iterator.concat',
|
||||
'es.json.is-raw-json',
|
||||
'es.json.parse',
|
||||
'es.json.raw-json',
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
'use strict';
|
||||
var parent = require('../../stable/json');
|
||||
require('../../modules/es.object.create');
|
||||
require('../../modules/es.object.freeze');
|
||||
require('../../modules/es.object.keys');
|
||||
require('../../modules/esnext.json.is-raw-json');
|
||||
require('../../modules/esnext.json.parse');
|
||||
require('../../modules/esnext.json.raw-json');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
var parent = require('../../stable/json/is-raw-json');
|
||||
require('../../modules/esnext.json.is-raw-json');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.JSON.isRawJSON;
|
||||
module.exports = parent;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use strict';
|
||||
require('../../modules/es.object.keys');
|
||||
var parent = require('../../stable/json/parse');
|
||||
require('../../modules/esnext.json.parse');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.JSON.parse;
|
||||
module.exports = parent;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
require('../../modules/es.object.create');
|
||||
require('../../modules/es.object.freeze');
|
||||
var parent = require('../../stable/json/raw-json');
|
||||
require('../../modules/es.json.stringify');
|
||||
require('../../modules/esnext.json.raw-json');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.JSON.rawJSON;
|
||||
module.exports = parent;
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
'use strict';
|
||||
require('../../modules/es.object.create');
|
||||
require('../../modules/es.object.freeze');
|
||||
require('../../modules/es.object.keys');
|
||||
require('../../modules/es.date.to-json');
|
||||
require('../../modules/es.json.is-raw-json');
|
||||
require('../../modules/es.json.parse');
|
||||
require('../../modules/es.json.raw-json');
|
||||
require('../../modules/es.json.stringify');
|
||||
require('../../modules/es.json.to-string-tag');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
'use strict';
|
||||
require('../../modules/es.json.is-raw-json');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.JSON.isRawJSON;
|
||||
@@ -0,0 +1,6 @@
|
||||
'use strict';
|
||||
require('../../modules/es.object.keys');
|
||||
require('../../modules/es.json.parse');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.JSON.parse;
|
||||
@@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
require('../../modules/es.object.create');
|
||||
require('../../modules/es.object.freeze');
|
||||
require('../../modules/es.json.raw-json');
|
||||
var path = require('../../internals/path');
|
||||
|
||||
module.exports = path.JSON.rawJSON;
|
||||
@@ -1,30 +0,0 @@
|
||||
'use strict';
|
||||
var uncurryThis = require('../internals/function-uncurry-this');
|
||||
var isArray = require('../internals/is-array');
|
||||
var isCallable = require('../internals/is-callable');
|
||||
var classof = require('../internals/classof-raw');
|
||||
var toString = require('../internals/to-string');
|
||||
|
||||
var push = uncurryThis([].push);
|
||||
|
||||
module.exports = function (replacer) {
|
||||
if (isCallable(replacer)) return replacer;
|
||||
if (!isArray(replacer)) return;
|
||||
var rawLength = replacer.length;
|
||||
var keys = [];
|
||||
for (var i = 0; i < rawLength; i++) {
|
||||
var element = replacer[i];
|
||||
if (typeof element == 'string') push(keys, element);
|
||||
else if (typeof element == 'number' || classof(element) === 'Number' || classof(element) === 'String') push(keys, toString(element));
|
||||
}
|
||||
var keysLength = keys.length;
|
||||
var root = true;
|
||||
return function (key, value) {
|
||||
if (root) {
|
||||
root = false;
|
||||
return value;
|
||||
}
|
||||
if (isArray(this)) return value;
|
||||
for (var j = 0; j < keysLength; j++) if (keys[j] === key) return value;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
var $ = require('../internals/export');
|
||||
var NATIVE_RAW_JSON = require('../internals/native-raw-json');
|
||||
var isRawJSON = require('../internals/is-raw-json');
|
||||
|
||||
// `JSON.isRawJSON` method
|
||||
// https://tc39.es/proposal-json-parse-with-source/#sec-json.israwjson
|
||||
// https://github.com/tc39/proposal-json-parse-with-source
|
||||
$({ target: 'JSON', stat: true, forced: !NATIVE_RAW_JSON }, {
|
||||
isRawJSON: isRawJSON
|
||||
});
|
||||
@@ -0,0 +1,251 @@
|
||||
'use strict';
|
||||
var $ = require('../internals/export');
|
||||
var DESCRIPTORS = require('../internals/descriptors');
|
||||
var globalThis = require('../internals/global-this');
|
||||
var getBuiltIn = require('../internals/get-built-in');
|
||||
var uncurryThis = require('../internals/function-uncurry-this');
|
||||
var call = require('../internals/function-call');
|
||||
var isCallable = require('../internals/is-callable');
|
||||
var isObject = require('../internals/is-object');
|
||||
var isArray = require('../internals/is-array');
|
||||
var hasOwn = require('../internals/has-own-property');
|
||||
var toString = require('../internals/to-string');
|
||||
var lengthOfArrayLike = require('../internals/length-of-array-like');
|
||||
var createProperty = require('../internals/create-property');
|
||||
var fails = require('../internals/fails');
|
||||
var parseJSONString = require('../internals/parse-json-string');
|
||||
var NATIVE_SYMBOL = require('../internals/symbol-constructor-detection');
|
||||
|
||||
var JSON = globalThis.JSON;
|
||||
var Number = globalThis.Number;
|
||||
var SyntaxError = globalThis.SyntaxError;
|
||||
var nativeParse = JSON && JSON.parse;
|
||||
var enumerableOwnProperties = getBuiltIn('Object', 'keys');
|
||||
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
|
||||
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
||||
var at = uncurryThis(''.charAt);
|
||||
var slice = uncurryThis(''.slice);
|
||||
var exec = uncurryThis(/./.exec);
|
||||
var push = uncurryThis([].push);
|
||||
|
||||
var IS_DIGIT = /^\d$/;
|
||||
var IS_NON_ZERO_DIGIT = /^[1-9]$/;
|
||||
var IS_NUMBER_START = /^[\d-]$/;
|
||||
var IS_WHITESPACE = /^[\t\n\r ]$/;
|
||||
|
||||
var PRIMITIVE = 0;
|
||||
var OBJECT = 1;
|
||||
|
||||
var $parse = function (source, reviver) {
|
||||
source = toString(source);
|
||||
var context = new Context(source, 0, '');
|
||||
var root = context.parse();
|
||||
var value = root.value;
|
||||
var endIndex = context.skip(IS_WHITESPACE, root.end);
|
||||
if (endIndex < source.length) {
|
||||
throw new SyntaxError('Unexpected extra character: "' + at(source, endIndex) + '" after the parsed data at: ' + endIndex);
|
||||
}
|
||||
return isCallable(reviver) ? internalize({ '': value }, '', reviver, root) : value;
|
||||
};
|
||||
|
||||
var internalize = function (holder, name, reviver, node) {
|
||||
var val = holder[name];
|
||||
var unmodified = node && val === node.value;
|
||||
var context = unmodified && typeof node.source == 'string' ? { source: node.source } : {};
|
||||
var elementRecordsLen, keys, len, i, P;
|
||||
if (isObject(val)) {
|
||||
var nodeIsArray = isArray(val);
|
||||
var nodes = unmodified ? node.nodes : nodeIsArray ? [] : {};
|
||||
if (nodeIsArray) {
|
||||
elementRecordsLen = nodes.length;
|
||||
len = lengthOfArrayLike(val);
|
||||
for (i = 0; i < len; i++) {
|
||||
internalizeProperty(val, i, internalize(val, '' + i, reviver, i < elementRecordsLen ? nodes[i] : undefined));
|
||||
}
|
||||
} else {
|
||||
keys = enumerableOwnProperties(val);
|
||||
len = lengthOfArrayLike(keys);
|
||||
for (i = 0; i < len; i++) {
|
||||
P = keys[i];
|
||||
internalizeProperty(val, P, internalize(val, P, reviver, hasOwn(nodes, P) ? nodes[P] : undefined));
|
||||
}
|
||||
}
|
||||
}
|
||||
return call(reviver, holder, name, val, context);
|
||||
};
|
||||
|
||||
var internalizeProperty = function (object, key, value) {
|
||||
if (DESCRIPTORS) {
|
||||
var descriptor = getOwnPropertyDescriptor(object, key);
|
||||
if (descriptor && !descriptor.configurable) return;
|
||||
}
|
||||
if (value === undefined) delete object[key];
|
||||
else createProperty(object, key, value);
|
||||
};
|
||||
|
||||
var Node = function (value, end, source, nodes) {
|
||||
this.value = value;
|
||||
this.end = end;
|
||||
this.source = source;
|
||||
this.nodes = nodes;
|
||||
};
|
||||
|
||||
var Context = function (source, index) {
|
||||
this.source = source;
|
||||
this.index = index;
|
||||
};
|
||||
|
||||
// https://www.json.org/json-en.html
|
||||
Context.prototype = {
|
||||
fork: function (nextIndex) {
|
||||
return new Context(this.source, nextIndex);
|
||||
},
|
||||
parse: function () {
|
||||
var source = this.source;
|
||||
var i = this.skip(IS_WHITESPACE, this.index);
|
||||
var fork = this.fork(i);
|
||||
var chr = at(source, i);
|
||||
if (exec(IS_NUMBER_START, chr)) return fork.number();
|
||||
switch (chr) {
|
||||
case '{':
|
||||
return fork.object();
|
||||
case '[':
|
||||
return fork.array();
|
||||
case '"':
|
||||
return fork.string();
|
||||
case 't':
|
||||
return fork.keyword(true);
|
||||
case 'f':
|
||||
return fork.keyword(false);
|
||||
case 'n':
|
||||
return fork.keyword(null);
|
||||
} throw new SyntaxError('Unexpected character: "' + chr + '" at: ' + i);
|
||||
},
|
||||
node: function (type, value, start, end, nodes) {
|
||||
return new Node(value, end, type ? null : slice(this.source, start, end), nodes);
|
||||
},
|
||||
object: function () {
|
||||
var source = this.source;
|
||||
var i = this.index + 1;
|
||||
var expectKeypair = false;
|
||||
var object = {};
|
||||
var nodes = {};
|
||||
while (i < source.length) {
|
||||
i = this.until(['"', '}'], i);
|
||||
if (at(source, i) === '}' && !expectKeypair) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
// Parsing the key
|
||||
var result = this.fork(i).string();
|
||||
var key = result.value;
|
||||
i = result.end;
|
||||
i = this.until([':'], i) + 1;
|
||||
// Parsing value
|
||||
i = this.skip(IS_WHITESPACE, i);
|
||||
result = this.fork(i).parse();
|
||||
createProperty(nodes, key, result);
|
||||
createProperty(object, key, result.value);
|
||||
i = this.until([',', '}'], result.end);
|
||||
var chr = at(source, i);
|
||||
if (chr === ',') {
|
||||
expectKeypair = true;
|
||||
i++;
|
||||
} else if (chr === '}') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this.node(OBJECT, object, this.index, i, nodes);
|
||||
},
|
||||
array: function () {
|
||||
var source = this.source;
|
||||
var i = this.index + 1;
|
||||
var expectElement = false;
|
||||
var array = [];
|
||||
var nodes = [];
|
||||
while (i < source.length) {
|
||||
i = this.skip(IS_WHITESPACE, i);
|
||||
if (at(source, i) === ']' && !expectElement) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
var result = this.fork(i).parse();
|
||||
push(nodes, result);
|
||||
push(array, result.value);
|
||||
i = this.until([',', ']'], result.end);
|
||||
if (at(source, i) === ',') {
|
||||
expectElement = true;
|
||||
i++;
|
||||
} else if (at(source, i) === ']') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this.node(OBJECT, array, this.index, i, nodes);
|
||||
},
|
||||
string: function () {
|
||||
var index = this.index;
|
||||
var parsed = parseJSONString(this.source, this.index + 1);
|
||||
return this.node(PRIMITIVE, parsed.value, index, parsed.end);
|
||||
},
|
||||
number: function () {
|
||||
var source = this.source;
|
||||
var startIndex = this.index;
|
||||
var i = startIndex;
|
||||
if (at(source, i) === '-') i++;
|
||||
if (at(source, i) === '0') i++;
|
||||
else if (exec(IS_NON_ZERO_DIGIT, at(source, i))) i = this.skip(IS_DIGIT, i + 1);
|
||||
else throw new SyntaxError('Failed to parse number at: ' + i);
|
||||
if (at(source, i) === '.') i = this.skip(IS_DIGIT, i + 1);
|
||||
if (at(source, i) === 'e' || at(source, i) === 'E') {
|
||||
i++;
|
||||
if (at(source, i) === '+' || at(source, i) === '-') i++;
|
||||
var exponentStartIndex = i;
|
||||
i = this.skip(IS_DIGIT, i);
|
||||
if (exponentStartIndex === i) throw new SyntaxError("Failed to parse number's exponent value at: " + i);
|
||||
}
|
||||
return this.node(PRIMITIVE, Number(slice(source, startIndex, i)), startIndex, i);
|
||||
},
|
||||
keyword: function (value) {
|
||||
var keyword = '' + value;
|
||||
var index = this.index;
|
||||
var endIndex = index + keyword.length;
|
||||
if (slice(this.source, index, endIndex) !== keyword) throw new SyntaxError('Failed to parse value at: ' + index);
|
||||
return this.node(PRIMITIVE, value, index, endIndex);
|
||||
},
|
||||
skip: function (regex, i) {
|
||||
var source = this.source;
|
||||
for (; i < source.length; i++) if (!exec(regex, at(source, i))) break;
|
||||
return i;
|
||||
},
|
||||
until: function (array, i) {
|
||||
i = this.skip(IS_WHITESPACE, i);
|
||||
var chr = at(this.source, i);
|
||||
for (var j = 0; j < array.length; j++) if (array[j] === chr) return i;
|
||||
throw new SyntaxError('Unexpected character: "' + chr + '" at: ' + i);
|
||||
}
|
||||
};
|
||||
|
||||
var NO_SOURCE_SUPPORT = fails(function () {
|
||||
var unsafeInt = '9007199254740993';
|
||||
var source;
|
||||
nativeParse(unsafeInt, function (key, value, context) {
|
||||
source = context.source;
|
||||
});
|
||||
return source !== unsafeInt;
|
||||
});
|
||||
|
||||
var PROPER_BASE_PARSE = NATIVE_SYMBOL && !fails(function () {
|
||||
// Safari 9 bug
|
||||
return 1 / nativeParse('-0 \t') !== -Infinity;
|
||||
});
|
||||
|
||||
// `JSON.parse` method
|
||||
// https://tc39.es/ecma262/#sec-json.parse
|
||||
// https://github.com/tc39/proposal-json-parse-with-source
|
||||
$({ target: 'JSON', stat: true, forced: NO_SOURCE_SUPPORT }, {
|
||||
parse: function parse(text, reviver) {
|
||||
return PROPER_BASE_PARSE && !isCallable(reviver) ? nativeParse(text) : $parse(text, reviver);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
var $ = require('../internals/export');
|
||||
var FREEZING = require('../internals/freezing');
|
||||
var NATIVE_RAW_JSON = require('../internals/native-raw-json');
|
||||
var getBuiltIn = require('../internals/get-built-in');
|
||||
var uncurryThis = require('../internals/function-uncurry-this');
|
||||
var toString = require('../internals/to-string');
|
||||
var createProperty = require('../internals/create-property');
|
||||
var setInternalState = require('../internals/internal-state').set;
|
||||
|
||||
var $SyntaxError = SyntaxError;
|
||||
var parse = getBuiltIn('JSON', 'parse');
|
||||
var create = getBuiltIn('Object', 'create');
|
||||
var freeze = getBuiltIn('Object', 'freeze');
|
||||
var at = uncurryThis(''.charAt);
|
||||
|
||||
var ERROR_MESSAGE = 'Unacceptable as raw JSON';
|
||||
|
||||
var isWhitespace = function (it) {
|
||||
return it === ' ' || it === '\t' || it === '\n' || it === '\r';
|
||||
};
|
||||
|
||||
// `JSON.rawJSON` method
|
||||
// https://tc39.es/proposal-json-parse-with-source/#sec-json.rawjson
|
||||
// https://github.com/tc39/proposal-json-parse-with-source
|
||||
$({ target: 'JSON', stat: true, forced: !NATIVE_RAW_JSON }, {
|
||||
rawJSON: function rawJSON(text) {
|
||||
var jsonString = toString(text);
|
||||
if (jsonString === '' || isWhitespace(at(jsonString, 0)) || isWhitespace(at(jsonString, jsonString.length - 1))) {
|
||||
throw new $SyntaxError(ERROR_MESSAGE);
|
||||
}
|
||||
var parsed = parse(jsonString);
|
||||
if (typeof parsed == 'object' && parsed !== null) throw new $SyntaxError(ERROR_MESSAGE);
|
||||
var obj = create(null);
|
||||
setInternalState(obj, { type: 'RawJSON' });
|
||||
createProperty(obj, 'rawJSON', jsonString);
|
||||
return FREEZING ? freeze(obj) : obj;
|
||||
}
|
||||
});
|
||||
@@ -5,11 +5,17 @@ var apply = require('../internals/function-apply');
|
||||
var call = require('../internals/function-call');
|
||||
var uncurryThis = require('../internals/function-uncurry-this');
|
||||
var fails = require('../internals/fails');
|
||||
var isArray = require('../internals/is-array');
|
||||
var isCallable = require('../internals/is-callable');
|
||||
var isRawJSON = require('../internals/is-raw-json');
|
||||
var isSymbol = require('../internals/is-symbol');
|
||||
var classof = require('../internals/classof-raw');
|
||||
var toString = require('../internals/to-string');
|
||||
var arraySlice = require('../internals/array-slice');
|
||||
var getReplacerFunction = require('../internals/get-json-replacer-function');
|
||||
var parseJSONString = require('../internals/parse-json-string');
|
||||
var uid = require('../internals/uid');
|
||||
var NATIVE_SYMBOL = require('../internals/symbol-constructor-detection');
|
||||
var NATIVE_RAW_JSON = require('../internals/native-raw-json');
|
||||
|
||||
var $String = String;
|
||||
var $stringify = getBuiltIn('JSON', 'stringify');
|
||||
@@ -17,11 +23,16 @@ var exec = uncurryThis(/./.exec);
|
||||
var charAt = uncurryThis(''.charAt);
|
||||
var charCodeAt = uncurryThis(''.charCodeAt);
|
||||
var replace = uncurryThis(''.replace);
|
||||
var slice = uncurryThis(''.slice);
|
||||
var push = uncurryThis([].push);
|
||||
var numberToString = uncurryThis(1.1.toString);
|
||||
|
||||
var tester = /[\uD800-\uDFFF]/g;
|
||||
var low = /^[\uD800-\uDBFF]$/;
|
||||
var hi = /^[\uDC00-\uDFFF]$/;
|
||||
var surrogates = /[\uD800-\uDFFF]/g;
|
||||
var lowSurrogates = /^[\uD800-\uDBFF]$/;
|
||||
var hiSurrogates = /^[\uDC00-\uDFFF]$/;
|
||||
|
||||
var MARK = uid();
|
||||
var MARK_LENGTH = MARK.length;
|
||||
|
||||
var WRONG_SYMBOLS_CONVERSION = !NATIVE_SYMBOL || fails(function () {
|
||||
var symbol = getBuiltIn('Symbol')('stringify detection');
|
||||
@@ -39,7 +50,7 @@ var ILL_FORMED_UNICODE = fails(function () {
|
||||
|| $stringify('\uDEAD') !== '"\\udead"';
|
||||
});
|
||||
|
||||
var stringifyWithSymbolsFix = function (it, replacer) {
|
||||
var stringifyWithProperSymbolsConversion = WRONG_SYMBOLS_CONVERSION ? function (it, replacer) {
|
||||
var args = arraySlice(arguments);
|
||||
var $replacer = getReplacerFunction(replacer);
|
||||
if (!isCallable($replacer) && (it === undefined || isSymbol(it))) return; // IE8 returns string on undefined
|
||||
@@ -49,25 +60,73 @@ var stringifyWithSymbolsFix = function (it, replacer) {
|
||||
if (!isSymbol(value)) return value;
|
||||
};
|
||||
return apply($stringify, null, args);
|
||||
};
|
||||
} : $stringify;
|
||||
|
||||
var fixIllFormed = function (match, offset, string) {
|
||||
var fixIllFormedJSON = function (match, offset, string) {
|
||||
var prev = charAt(string, offset - 1);
|
||||
var next = charAt(string, offset + 1);
|
||||
if ((exec(low, match) && !exec(hi, next)) || (exec(hi, match) && !exec(low, prev))) {
|
||||
if ((exec(lowSurrogates, match) && !exec(hiSurrogates, next)) || (exec(hiSurrogates, match) && !exec(lowSurrogates, prev))) {
|
||||
return '\\u' + numberToString(charCodeAt(match, 0), 16);
|
||||
} return match;
|
||||
};
|
||||
|
||||
if ($stringify) {
|
||||
// `JSON.stringify` method
|
||||
// https://tc39.es/ecma262/#sec-json.stringify
|
||||
$({ target: 'JSON', stat: true, arity: 3, forced: WRONG_SYMBOLS_CONVERSION || ILL_FORMED_UNICODE }, {
|
||||
// eslint-disable-next-line no-unused-vars -- required for `.length`
|
||||
stringify: function stringify(it, replacer, space) {
|
||||
var args = arraySlice(arguments);
|
||||
var result = apply(WRONG_SYMBOLS_CONVERSION ? stringifyWithSymbolsFix : $stringify, null, args);
|
||||
return ILL_FORMED_UNICODE && typeof result == 'string' ? replace(result, tester, fixIllFormed) : result;
|
||||
var getReplacerFunction = function (replacer) {
|
||||
if (isCallable(replacer)) return replacer;
|
||||
if (!isArray(replacer)) return;
|
||||
var rawLength = replacer.length;
|
||||
var keys = [];
|
||||
for (var i = 0; i < rawLength; i++) {
|
||||
var element = replacer[i];
|
||||
if (typeof element == 'string') push(keys, element);
|
||||
else if (typeof element == 'number' || classof(element) === 'Number' || classof(element) === 'String') push(keys, toString(element));
|
||||
}
|
||||
var keysLength = keys.length;
|
||||
var root = true;
|
||||
return function (key, value) {
|
||||
if (root) {
|
||||
root = false;
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (isArray(this)) return value;
|
||||
for (var j = 0; j < keysLength; j++) if (keys[j] === key) return value;
|
||||
};
|
||||
};
|
||||
|
||||
// `JSON.stringify` method
|
||||
// https://tc39.es/ecma262/#sec-json.stringify
|
||||
// https://github.com/tc39/proposal-json-parse-with-source
|
||||
if ($stringify) $({ target: 'JSON', stat: true, arity: 3, forced: WRONG_SYMBOLS_CONVERSION || ILL_FORMED_UNICODE || !NATIVE_RAW_JSON }, {
|
||||
stringify: function stringify(text, replacer, space) {
|
||||
var replacerFunction = getReplacerFunction(replacer);
|
||||
var rawStrings = [];
|
||||
|
||||
var json = stringifyWithProperSymbolsConversion(text, function (key, value) {
|
||||
// some old implementations (like WebKit) could pass numbers as keys
|
||||
var v = isCallable(replacerFunction) ? call(replacerFunction, this, $String(key), value) : value;
|
||||
return !NATIVE_RAW_JSON && isRawJSON(v) ? MARK + (push(rawStrings, v.rawJSON) - 1) : v;
|
||||
}, space);
|
||||
|
||||
if (typeof json != 'string') return json;
|
||||
|
||||
if (ILL_FORMED_UNICODE) json = replace(json, surrogates, fixIllFormedJSON);
|
||||
|
||||
if (NATIVE_RAW_JSON) return json;
|
||||
|
||||
var result = '';
|
||||
var length = json.length;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
var chr = charAt(json, i);
|
||||
if (chr === '"') {
|
||||
var end = parseJSONString(json, ++i).end - 1;
|
||||
var string = slice(json, i, end);
|
||||
result += slice(string, 0, MARK_LENGTH) === MARK
|
||||
? rawStrings[slice(string, MARK_LENGTH)]
|
||||
: '"' + string + '"';
|
||||
i = end;
|
||||
} else result += chr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
'use strict';
|
||||
var $ = require('../internals/export');
|
||||
var NATIVE_RAW_JSON = require('../internals/native-raw-json');
|
||||
var isRawJSON = require('../internals/is-raw-json');
|
||||
|
||||
// `JSON.isRawJSON` method
|
||||
// https://tc39.es/proposal-json-parse-with-source/#sec-json.israwjson
|
||||
// https://github.com/tc39/proposal-json-parse-with-source
|
||||
$({ target: 'JSON', stat: true, forced: !NATIVE_RAW_JSON }, {
|
||||
isRawJSON: isRawJSON
|
||||
});
|
||||
// TODO: Remove from `core-js@4`
|
||||
require('../modules/es.json.is-raw-json');
|
||||
|
||||
@@ -1,251 +1,3 @@
|
||||
'use strict';
|
||||
var $ = require('../internals/export');
|
||||
var DESCRIPTORS = require('../internals/descriptors');
|
||||
var globalThis = require('../internals/global-this');
|
||||
var getBuiltIn = require('../internals/get-built-in');
|
||||
var uncurryThis = require('../internals/function-uncurry-this');
|
||||
var call = require('../internals/function-call');
|
||||
var isCallable = require('../internals/is-callable');
|
||||
var isObject = require('../internals/is-object');
|
||||
var isArray = require('../internals/is-array');
|
||||
var hasOwn = require('../internals/has-own-property');
|
||||
var toString = require('../internals/to-string');
|
||||
var lengthOfArrayLike = require('../internals/length-of-array-like');
|
||||
var createProperty = require('../internals/create-property');
|
||||
var fails = require('../internals/fails');
|
||||
var parseJSONString = require('../internals/parse-json-string');
|
||||
var NATIVE_SYMBOL = require('../internals/symbol-constructor-detection');
|
||||
|
||||
var JSON = globalThis.JSON;
|
||||
var Number = globalThis.Number;
|
||||
var SyntaxError = globalThis.SyntaxError;
|
||||
var nativeParse = JSON && JSON.parse;
|
||||
var enumerableOwnProperties = getBuiltIn('Object', 'keys');
|
||||
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
|
||||
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
||||
var at = uncurryThis(''.charAt);
|
||||
var slice = uncurryThis(''.slice);
|
||||
var exec = uncurryThis(/./.exec);
|
||||
var push = uncurryThis([].push);
|
||||
|
||||
var IS_DIGIT = /^\d$/;
|
||||
var IS_NON_ZERO_DIGIT = /^[1-9]$/;
|
||||
var IS_NUMBER_START = /^[\d-]$/;
|
||||
var IS_WHITESPACE = /^[\t\n\r ]$/;
|
||||
|
||||
var PRIMITIVE = 0;
|
||||
var OBJECT = 1;
|
||||
|
||||
var $parse = function (source, reviver) {
|
||||
source = toString(source);
|
||||
var context = new Context(source, 0, '');
|
||||
var root = context.parse();
|
||||
var value = root.value;
|
||||
var endIndex = context.skip(IS_WHITESPACE, root.end);
|
||||
if (endIndex < source.length) {
|
||||
throw new SyntaxError('Unexpected extra character: "' + at(source, endIndex) + '" after the parsed data at: ' + endIndex);
|
||||
}
|
||||
return isCallable(reviver) ? internalize({ '': value }, '', reviver, root) : value;
|
||||
};
|
||||
|
||||
var internalize = function (holder, name, reviver, node) {
|
||||
var val = holder[name];
|
||||
var unmodified = node && val === node.value;
|
||||
var context = unmodified && typeof node.source == 'string' ? { source: node.source } : {};
|
||||
var elementRecordsLen, keys, len, i, P;
|
||||
if (isObject(val)) {
|
||||
var nodeIsArray = isArray(val);
|
||||
var nodes = unmodified ? node.nodes : nodeIsArray ? [] : {};
|
||||
if (nodeIsArray) {
|
||||
elementRecordsLen = nodes.length;
|
||||
len = lengthOfArrayLike(val);
|
||||
for (i = 0; i < len; i++) {
|
||||
internalizeProperty(val, i, internalize(val, '' + i, reviver, i < elementRecordsLen ? nodes[i] : undefined));
|
||||
}
|
||||
} else {
|
||||
keys = enumerableOwnProperties(val);
|
||||
len = lengthOfArrayLike(keys);
|
||||
for (i = 0; i < len; i++) {
|
||||
P = keys[i];
|
||||
internalizeProperty(val, P, internalize(val, P, reviver, hasOwn(nodes, P) ? nodes[P] : undefined));
|
||||
}
|
||||
}
|
||||
}
|
||||
return call(reviver, holder, name, val, context);
|
||||
};
|
||||
|
||||
var internalizeProperty = function (object, key, value) {
|
||||
if (DESCRIPTORS) {
|
||||
var descriptor = getOwnPropertyDescriptor(object, key);
|
||||
if (descriptor && !descriptor.configurable) return;
|
||||
}
|
||||
if (value === undefined) delete object[key];
|
||||
else createProperty(object, key, value);
|
||||
};
|
||||
|
||||
var Node = function (value, end, source, nodes) {
|
||||
this.value = value;
|
||||
this.end = end;
|
||||
this.source = source;
|
||||
this.nodes = nodes;
|
||||
};
|
||||
|
||||
var Context = function (source, index) {
|
||||
this.source = source;
|
||||
this.index = index;
|
||||
};
|
||||
|
||||
// https://www.json.org/json-en.html
|
||||
Context.prototype = {
|
||||
fork: function (nextIndex) {
|
||||
return new Context(this.source, nextIndex);
|
||||
},
|
||||
parse: function () {
|
||||
var source = this.source;
|
||||
var i = this.skip(IS_WHITESPACE, this.index);
|
||||
var fork = this.fork(i);
|
||||
var chr = at(source, i);
|
||||
if (exec(IS_NUMBER_START, chr)) return fork.number();
|
||||
switch (chr) {
|
||||
case '{':
|
||||
return fork.object();
|
||||
case '[':
|
||||
return fork.array();
|
||||
case '"':
|
||||
return fork.string();
|
||||
case 't':
|
||||
return fork.keyword(true);
|
||||
case 'f':
|
||||
return fork.keyword(false);
|
||||
case 'n':
|
||||
return fork.keyword(null);
|
||||
} throw new SyntaxError('Unexpected character: "' + chr + '" at: ' + i);
|
||||
},
|
||||
node: function (type, value, start, end, nodes) {
|
||||
return new Node(value, end, type ? null : slice(this.source, start, end), nodes);
|
||||
},
|
||||
object: function () {
|
||||
var source = this.source;
|
||||
var i = this.index + 1;
|
||||
var expectKeypair = false;
|
||||
var object = {};
|
||||
var nodes = {};
|
||||
while (i < source.length) {
|
||||
i = this.until(['"', '}'], i);
|
||||
if (at(source, i) === '}' && !expectKeypair) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
// Parsing the key
|
||||
var result = this.fork(i).string();
|
||||
var key = result.value;
|
||||
i = result.end;
|
||||
i = this.until([':'], i) + 1;
|
||||
// Parsing value
|
||||
i = this.skip(IS_WHITESPACE, i);
|
||||
result = this.fork(i).parse();
|
||||
createProperty(nodes, key, result);
|
||||
createProperty(object, key, result.value);
|
||||
i = this.until([',', '}'], result.end);
|
||||
var chr = at(source, i);
|
||||
if (chr === ',') {
|
||||
expectKeypair = true;
|
||||
i++;
|
||||
} else if (chr === '}') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this.node(OBJECT, object, this.index, i, nodes);
|
||||
},
|
||||
array: function () {
|
||||
var source = this.source;
|
||||
var i = this.index + 1;
|
||||
var expectElement = false;
|
||||
var array = [];
|
||||
var nodes = [];
|
||||
while (i < source.length) {
|
||||
i = this.skip(IS_WHITESPACE, i);
|
||||
if (at(source, i) === ']' && !expectElement) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
var result = this.fork(i).parse();
|
||||
push(nodes, result);
|
||||
push(array, result.value);
|
||||
i = this.until([',', ']'], result.end);
|
||||
if (at(source, i) === ',') {
|
||||
expectElement = true;
|
||||
i++;
|
||||
} else if (at(source, i) === ']') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this.node(OBJECT, array, this.index, i, nodes);
|
||||
},
|
||||
string: function () {
|
||||
var index = this.index;
|
||||
var parsed = parseJSONString(this.source, this.index + 1);
|
||||
return this.node(PRIMITIVE, parsed.value, index, parsed.end);
|
||||
},
|
||||
number: function () {
|
||||
var source = this.source;
|
||||
var startIndex = this.index;
|
||||
var i = startIndex;
|
||||
if (at(source, i) === '-') i++;
|
||||
if (at(source, i) === '0') i++;
|
||||
else if (exec(IS_NON_ZERO_DIGIT, at(source, i))) i = this.skip(IS_DIGIT, i + 1);
|
||||
else throw new SyntaxError('Failed to parse number at: ' + i);
|
||||
if (at(source, i) === '.') i = this.skip(IS_DIGIT, i + 1);
|
||||
if (at(source, i) === 'e' || at(source, i) === 'E') {
|
||||
i++;
|
||||
if (at(source, i) === '+' || at(source, i) === '-') i++;
|
||||
var exponentStartIndex = i;
|
||||
i = this.skip(IS_DIGIT, i);
|
||||
if (exponentStartIndex === i) throw new SyntaxError("Failed to parse number's exponent value at: " + i);
|
||||
}
|
||||
return this.node(PRIMITIVE, Number(slice(source, startIndex, i)), startIndex, i);
|
||||
},
|
||||
keyword: function (value) {
|
||||
var keyword = '' + value;
|
||||
var index = this.index;
|
||||
var endIndex = index + keyword.length;
|
||||
if (slice(this.source, index, endIndex) !== keyword) throw new SyntaxError('Failed to parse value at: ' + index);
|
||||
return this.node(PRIMITIVE, value, index, endIndex);
|
||||
},
|
||||
skip: function (regex, i) {
|
||||
var source = this.source;
|
||||
for (; i < source.length; i++) if (!exec(regex, at(source, i))) break;
|
||||
return i;
|
||||
},
|
||||
until: function (array, i) {
|
||||
i = this.skip(IS_WHITESPACE, i);
|
||||
var chr = at(this.source, i);
|
||||
for (var j = 0; j < array.length; j++) if (array[j] === chr) return i;
|
||||
throw new SyntaxError('Unexpected character: "' + chr + '" at: ' + i);
|
||||
}
|
||||
};
|
||||
|
||||
var NO_SOURCE_SUPPORT = fails(function () {
|
||||
var unsafeInt = '9007199254740993';
|
||||
var source;
|
||||
nativeParse(unsafeInt, function (key, value, context) {
|
||||
source = context.source;
|
||||
});
|
||||
return source !== unsafeInt;
|
||||
});
|
||||
|
||||
var PROPER_BASE_PARSE = NATIVE_SYMBOL && !fails(function () {
|
||||
// Safari 9 bug
|
||||
return 1 / nativeParse('-0 \t') !== -Infinity;
|
||||
});
|
||||
|
||||
// `JSON.parse` method
|
||||
// https://tc39.es/ecma262/#sec-json.parse
|
||||
// https://github.com/tc39/proposal-json-parse-with-source
|
||||
$({ target: 'JSON', stat: true, forced: NO_SOURCE_SUPPORT }, {
|
||||
parse: function parse(text, reviver) {
|
||||
return PROPER_BASE_PARSE && !isCallable(reviver) ? nativeParse(text) : $parse(text, reviver);
|
||||
}
|
||||
});
|
||||
// TODO: Remove from `core-js@4`
|
||||
require('../modules/es.json.parse');
|
||||
|
||||
@@ -1,86 +1,3 @@
|
||||
'use strict';
|
||||
var $ = require('../internals/export');
|
||||
var FREEZING = require('../internals/freezing');
|
||||
var NATIVE_RAW_JSON = require('../internals/native-raw-json');
|
||||
var getBuiltIn = require('../internals/get-built-in');
|
||||
var call = require('../internals/function-call');
|
||||
var uncurryThis = require('../internals/function-uncurry-this');
|
||||
var isCallable = require('../internals/is-callable');
|
||||
var isRawJSON = require('../internals/is-raw-json');
|
||||
var toString = require('../internals/to-string');
|
||||
var createProperty = require('../internals/create-property');
|
||||
var parseJSONString = require('../internals/parse-json-string');
|
||||
var getReplacerFunction = require('../internals/get-json-replacer-function');
|
||||
var uid = require('../internals/uid');
|
||||
var setInternalState = require('../internals/internal-state').set;
|
||||
|
||||
var $String = String;
|
||||
var $SyntaxError = SyntaxError;
|
||||
var parse = getBuiltIn('JSON', 'parse');
|
||||
var $stringify = getBuiltIn('JSON', 'stringify');
|
||||
var create = getBuiltIn('Object', 'create');
|
||||
var freeze = getBuiltIn('Object', 'freeze');
|
||||
var at = uncurryThis(''.charAt);
|
||||
var slice = uncurryThis(''.slice);
|
||||
var push = uncurryThis([].push);
|
||||
|
||||
var MARK = uid();
|
||||
var MARK_LENGTH = MARK.length;
|
||||
var ERROR_MESSAGE = 'Unacceptable as raw JSON';
|
||||
|
||||
var isWhitespace = function (it) {
|
||||
return it === ' ' || it === '\t' || it === '\n' || it === '\r';
|
||||
};
|
||||
|
||||
// `JSON.rawJSON` method
|
||||
// https://tc39.es/proposal-json-parse-with-source/#sec-json.rawjson
|
||||
// https://github.com/tc39/proposal-json-parse-with-source
|
||||
$({ target: 'JSON', stat: true, forced: !NATIVE_RAW_JSON }, {
|
||||
rawJSON: function rawJSON(text) {
|
||||
var jsonString = toString(text);
|
||||
if (jsonString === '' || isWhitespace(at(jsonString, 0)) || isWhitespace(at(jsonString, jsonString.length - 1))) {
|
||||
throw new $SyntaxError(ERROR_MESSAGE);
|
||||
}
|
||||
var parsed = parse(jsonString);
|
||||
if (typeof parsed == 'object' && parsed !== null) throw new $SyntaxError(ERROR_MESSAGE);
|
||||
var obj = create(null);
|
||||
setInternalState(obj, { type: 'RawJSON' });
|
||||
createProperty(obj, 'rawJSON', jsonString);
|
||||
return FREEZING ? freeze(obj) : obj;
|
||||
}
|
||||
});
|
||||
|
||||
// `JSON.stringify` method
|
||||
// https://tc39.es/ecma262/#sec-json.stringify
|
||||
// https://github.com/tc39/proposal-json-parse-with-source
|
||||
if ($stringify) $({ target: 'JSON', stat: true, arity: 3, forced: !NATIVE_RAW_JSON }, {
|
||||
stringify: function stringify(text, replacer, space) {
|
||||
var replacerFunction = getReplacerFunction(replacer);
|
||||
var rawStrings = [];
|
||||
|
||||
var json = $stringify(text, function (key, value) {
|
||||
// some old implementations (like WebKit) could pass numbers as keys
|
||||
var v = isCallable(replacerFunction) ? call(replacerFunction, this, $String(key), value) : value;
|
||||
return isRawJSON(v) ? MARK + (push(rawStrings, v.rawJSON) - 1) : v;
|
||||
}, space);
|
||||
|
||||
if (typeof json != 'string') return json;
|
||||
|
||||
var result = '';
|
||||
var length = json.length;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
var chr = at(json, i);
|
||||
if (chr === '"') {
|
||||
var end = parseJSONString(json, ++i).end - 1;
|
||||
var string = slice(json, i, end);
|
||||
result += slice(string, 0, MARK_LENGTH) === MARK
|
||||
? rawStrings[slice(string, MARK_LENGTH)]
|
||||
: '"' + string + '"';
|
||||
i = end;
|
||||
} else result += chr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
// TODO: Remove from `core-js@4`
|
||||
require('../modules/es.json.raw-json');
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
'use strict';
|
||||
var parent = require('../../es/json/is-raw-json');
|
||||
|
||||
module.exports = parent;
|
||||
@@ -0,0 +1,4 @@
|
||||
'use strict';
|
||||
var parent = require('../../es/json/parse');
|
||||
|
||||
module.exports = parent;
|
||||
@@ -0,0 +1,4 @@
|
||||
'use strict';
|
||||
var parent = require('../../es/json/raw-json');
|
||||
|
||||
module.exports = parent;
|
||||
@@ -3,7 +3,6 @@ var parent = require('./4');
|
||||
|
||||
require('../proposals/decorator-metadata-v2');
|
||||
require('../proposals/joint-iteration');
|
||||
require('../proposals/json-parse-with-source');
|
||||
require('../proposals/map-upsert-v4');
|
||||
// TODO: Obsolete versions, remove from `core-js@4`
|
||||
require('../proposals/array-grouping-stage-3');
|
||||
|
||||
@@ -14,6 +14,7 @@ require('../proposals/global-this');
|
||||
require('../proposals/is-error');
|
||||
require('../proposals/iterator-helpers-stage-3-2');
|
||||
require('../proposals/iterator-sequencing');
|
||||
require('../proposals/json-parse-with-source');
|
||||
require('../proposals/math-sum');
|
||||
require('../proposals/promise-all-settled');
|
||||
require('../proposals/promise-any');
|
||||
|
||||
+11
-11
@@ -835,7 +835,17 @@ GLOBAL.tests = {
|
||||
'es.iterator.to-array': function () {
|
||||
return Iterator.prototype.toArray;
|
||||
},
|
||||
'es.json.stringify': [SYMBOLS_SUPPORT, function () {
|
||||
'es.json.is-raw-json': NATIVE_RAW_JSON,
|
||||
'es.json.parse': function () {
|
||||
var unsafeInt = '9007199254740993';
|
||||
var source;
|
||||
JSON.parse(unsafeInt, function (key, value, context) {
|
||||
source = context.source;
|
||||
});
|
||||
return source === unsafeInt;
|
||||
},
|
||||
'es.json.raw-json': NATIVE_RAW_JSON,
|
||||
'es.json.stringify': [NATIVE_RAW_JSON, SYMBOLS_SUPPORT, function () {
|
||||
var symbol = Symbol('stringify detection');
|
||||
return JSON.stringify([symbol]) === '[null]'
|
||||
&& JSON.stringify({ a: symbol }) === '{}'
|
||||
@@ -1913,16 +1923,6 @@ GLOBAL.tests = {
|
||||
'esnext.iterator.zip-keyed': function () {
|
||||
return Iterator.zipKeyed;
|
||||
},
|
||||
'esnext.json.is-raw-json': NATIVE_RAW_JSON,
|
||||
'esnext.json.parse': function () {
|
||||
var unsafeInt = '9007199254740993';
|
||||
var source;
|
||||
JSON.parse(unsafeInt, function (key, value, context) {
|
||||
source = context.source;
|
||||
});
|
||||
return source === unsafeInt;
|
||||
},
|
||||
'esnext.json.raw-json': NATIVE_RAW_JSON,
|
||||
'esnext.map.delete-all': function () {
|
||||
return Map.prototype.deleteAll;
|
||||
},
|
||||
|
||||
@@ -282,6 +282,9 @@ for (PATH of ['core-js-pure', 'core-js']) {
|
||||
ok(load(NS, 'escape')('!q2ф') === '%21q2%u0444');
|
||||
ok(load(NS, 'unescape')('%21q2%u0444') === '!q2ф');
|
||||
ok(load(NS, 'json').stringify([1]) === '[1]');
|
||||
ok(load(NS, 'json/is-raw-json')({}) === false);
|
||||
ok(load(NS, 'json/parse')('[42]', (key, value, { source }) => typeof value == 'number' ? source + source : value)[0] === '4242');
|
||||
ok(typeof load(NS, 'json/raw-json')(42) == 'object');
|
||||
ok(load(NS, 'json/stringify')([1]) === '[1]');
|
||||
ok(load(NS, 'json/to-string-tag') === 'JSON');
|
||||
ok(typeof load(NS, 'date/now')(new Date()) === 'number');
|
||||
@@ -714,9 +717,6 @@ for (PATH of ['core-js-pure', 'core-js']) {
|
||||
ok(typeof load(NS, 'iterator/to-async') == 'function');
|
||||
ok(typeof load(NS, 'iterator/zip') == 'function');
|
||||
ok(typeof load(NS, 'iterator/zip-keyed') == 'function');
|
||||
ok(load(NS, 'json/is-raw-json')({}) === false);
|
||||
ok(load(NS, 'json/parse')('[42]', (key, value, { source }) => typeof value == 'number' ? source + source : value)[0] === '4242');
|
||||
ok(typeof load(NS, 'json/raw-json')(42) == 'object');
|
||||
ok(load(NS, 'map/get-or-insert')(new Map([[1, 2]]), 1, 3) === 2);
|
||||
ok(load(NS, 'map/get-or-insert-computed')(new Map([[1, 2]]), 1, key => key) === 2);
|
||||
ok(load(NS, 'symbol/metadata'));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import isRawJSON from 'core-js-pure/actual/json/is-raw-json';
|
||||
import rawJSON from 'core-js-pure/actual/json/raw-json';
|
||||
import isRawJSON from 'core-js-pure/es/json/is-raw-json';
|
||||
import rawJSON from 'core-js-pure/es/json/raw-json';
|
||||
import freeze from 'core-js-pure/es/object/freeze';
|
||||
import Symbol from 'core-js-pure/es/symbol';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
/* eslint-disable unicorn/escape-case -- testing */
|
||||
import { DESCRIPTORS, REDEFINABLE_PROTO } from '../helpers/constants.js';
|
||||
import parse from 'core-js-pure/actual/json/parse';
|
||||
import parse from 'core-js-pure/es/json/parse';
|
||||
import defineProperty from 'core-js-pure/es/object/define-property';
|
||||
import hasOwn from 'core-js-pure/es/object/has-own';
|
||||
import keys from 'core-js-pure/es/object/keys';
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FREEZING } from '../helpers/constants.js';
|
||||
import rawJSON from 'core-js-pure/actual/json/raw-json';
|
||||
import stringify from 'core-js-pure/actual/json/stringify';
|
||||
import rawJSON from 'core-js-pure/es/json/raw-json';
|
||||
import stringify from 'core-js-pure/es/json/stringify';
|
||||
import isFrozen from 'core-js-pure/es/object/is-frozen';
|
||||
import hasOwn from 'core-js-pure/es/object/has-own';
|
||||
|
||||
Reference in New Issue
Block a user