From aac5e0725fb0a184f9a99492bf28f0ad45261fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Fri, 2 Apr 2021 15:11:40 +0200 Subject: [PATCH 1/4] add types --- index.d.ts | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 59 insertions(+) create mode 100644 index.d.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..6ea2730 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,58 @@ +export type ParseOptions = { + /** + * What to do when a `__proto__` key is found. + * - `'error'` - throw a `SyntaxError` when a `__proto__` key is found. This is the default value. + * - `'remove'` - deletes any `__proto__` keys from the result object. + * - `'ignore'` - skips all validation (same as calling `JSON.parse()` directly). + */ + protoAction?: 'error' | 'remove' | 'ignore', + /** + * What to do when a `constructor` key is found. + * - `'error'` - throw a `SyntaxError` when a `constructor.prototype` key is found. This is the default value. + * - `'remove'` - deletes any `constructor` keys from the result object. + * - `'ignore'` - skips all validation (same as calling `JSON.parse()` directly). + */ + constructorAction?: 'error' | 'remove' | 'ignore', +}; + +export type ScanOptions = { + /** + * What to do when a `__proto__` key is found. + * - `'error'` - throw a `SyntaxError` when a `__proto__` key is found. This is the default value. + * - `'remove'` - deletes any `__proto__` keys from the input `obj`. + */ + protoAction?: 'error' | 'remove', + /** + * What to do when a `constructor` key is found. + * - `'error'` - throw a `SyntaxError` when a `constructor.prototype` key is found. This is the default value. + * - `'remove'` - deletes any `constructor` keys from the input `obj`. + */ + constructorAction?: 'error' | 'remove', +}; + +/** + * Parses a given JSON-formatted text into an object. + * + * @param text The JSON text string. + * @param reviver The `JSON.parse()` optional `reviver` argument. + * @param options Optional configuration object. + * @returns The parsed object. + */ +export function parse(text: string | Buffer, reviver?: (this: any, key: string, value: any) => any, options?: ParseOptions): any; + +/** + * Parses a given JSON-formatted text into an object. + * + * @param text The JSON text string. + * @param reviver The `JSON.parse()` optional `reviver` argument. + * @returns The parsed object, or `null` if there was an error or if the JSON contained possibly insecure properties. + */ +export function safeParse(text: string | Buffer, reviver?: (this: any, key: string, value: any) => any): any; + +/** + * Scans a given object for prototype properties. + * + * @param obj The object being scanned. + * @param options Optional configuration object. + */ +export function scan(obj: any, options?: ScanOptions): void; diff --git a/package.json b/package.json index d284b1a..a91730c 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "2.3.2", "description": "JSON parse with prototype poisoning protection", "main": "index.js", + "types": "index.d.ts", "scripts": { "benchmark": "cd benchmarks && npm install && npm run all", "test": "standard && nyc tape test.js", From f1c127fa19ed8f7b97cd112f60c09bc56d1bfa43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Fri, 2 Apr 2021 20:49:54 +0200 Subject: [PATCH 2/4] tsd --- index.d.ts | 12 +++++++----- index.test-d.ts | 30 ++++++++++++++++++++++++++++++ package.json | 5 +++-- 3 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 index.test-d.ts diff --git a/index.d.ts b/index.d.ts index 6ea2730..0c15f9e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -13,7 +13,7 @@ export type ParseOptions = { * - `'ignore'` - skips all validation (same as calling `JSON.parse()` directly). */ constructorAction?: 'error' | 'remove' | 'ignore', -}; +} export type ScanOptions = { /** @@ -28,7 +28,9 @@ export type ScanOptions = { * - `'remove'` - deletes any `constructor` keys from the input `obj`. */ constructorAction?: 'error' | 'remove', -}; +} + +type Reviver = (this: any, key: string, value: any) => any /** * Parses a given JSON-formatted text into an object. @@ -38,7 +40,7 @@ export type ScanOptions = { * @param options Optional configuration object. * @returns The parsed object. */ -export function parse(text: string | Buffer, reviver?: (this: any, key: string, value: any) => any, options?: ParseOptions): any; +export function parse(text: string | Buffer, reviver?: Reviver | null, options?: ParseOptions): any /** * Parses a given JSON-formatted text into an object. @@ -47,7 +49,7 @@ export function parse(text: string | Buffer, reviver?: (this: any, key: string, * @param reviver The `JSON.parse()` optional `reviver` argument. * @returns The parsed object, or `null` if there was an error or if the JSON contained possibly insecure properties. */ -export function safeParse(text: string | Buffer, reviver?: (this: any, key: string, value: any) => any): any; +export function safeParse(text: string | Buffer, reviver?: Reviver | null): any /** * Scans a given object for prototype properties. @@ -55,4 +57,4 @@ export function safeParse(text: string | Buffer, reviver?: (this: any, key: stri * @param obj The object being scanned. * @param options Optional configuration object. */ -export function scan(obj: any, options?: ScanOptions): void; +export function scan(obj: any, options?: ScanOptions): void diff --git a/index.test-d.ts b/index.test-d.ts new file mode 100644 index 0000000..002f2f9 --- /dev/null +++ b/index.test-d.ts @@ -0,0 +1,30 @@ +import { expectType, expectError } from 'tsd' +import sjson = require('.') + +expectError(sjson.parse(null)) +expectType(sjson.parse('{"anything":0}')) + +sjson.parse('"test"', null, { protoAction: 'remove' }) +expectError(sjson.parse('"test"', null, { protoAction: 'incorrect' })) +sjson.parse('"test"', null, { constructorAction: 'ignore' }) +expectError(sjson.parse('"test"', null, { constructorAction: 'incorrect' })) + +sjson.safeParse('"test"', null) +sjson.safeParse('"test"') +expectError(sjson.safeParse(null)) + +sjson.scan('"test"', { protoAction: 'remove' }) +expectError(sjson.scan('"test"', { protoAction: 'ignore' })) +sjson.scan('"test"', { constructorAction: 'error' }) +expectError(sjson.scan('"test"', { constructorAction: 'ignore' })) + +declare const input: Buffer +sjson.parse(input) +sjson.safeParse(input) + +sjson.parse('{"anything":0}', (key, value) => { + expectType(key) +}) +sjson.safeParse('{"anything":0}', (key, value) => { + expectType(key) +}) diff --git a/package.json b/package.json index a91730c..0bf1ad5 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "types": "index.d.ts", "scripts": { "benchmark": "cd benchmarks && npm install && npm run all", - "test": "standard && nyc tape test.js", + "test": "standard && tsd && nyc tape test.js", "test-in-browsers": "airtap test.js" }, "repository": { @@ -32,6 +32,7 @@ "nyc": "^14.1.1", "playwright": "^1.7.1", "standard": "^16.0.0", - "tape": "^5.1.1" + "tape": "^5.1.1", + "tsd": "^0.14.0" } } From 62176fd50750def89c0f8c8d90ebc1e8abe51948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Fri, 2 Apr 2021 21:05:36 +0200 Subject: [PATCH 3/4] downgrade tsd for node 8.x support --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0bf1ad5..2883f0d 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,6 @@ "playwright": "^1.7.1", "standard": "^16.0.0", "tape": "^5.1.1", - "tsd": "^0.14.0" + "tsd": "^0.12.1" } } From 9c86df24e1c199b0383807e48fa1ccf45c4ac0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Sat, 3 Apr 2021 12:21:26 +0200 Subject: [PATCH 4/4] exclude standard/tsd from ci on node.js 8.x and below --- .github/workflows/ci.yml | 17 ++++++++++++++++- package.json | 3 ++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70ae2d3..2026a0d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [6.x, 8.x, 10.x, 11.x, 12.x, 13.x, 14.x, 15.x] + node-version: [10.x, 11.x, 12.x, 13.x, 14.x, 15.x] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} @@ -25,3 +25,18 @@ jobs: run: npm install --ignore-scripts - name: Test run: npm run test + test-legacy: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [6.x, 8.x] + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2.1.5 + with: + node-version: ${{ matrix.node-version }} + - name: Install Dependencies + run: npm install --ignore-scripts + - name: Test + run: npm run test-legacy diff --git a/package.json b/package.json index 2883f0d..4536142 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "types": "index.d.ts", "scripts": { "benchmark": "cd benchmarks && npm install && npm run all", + "test-legacy": "nyc tape test.js", "test": "standard && tsd && nyc tape test.js", "test-in-browsers": "airtap test.js" }, @@ -33,6 +34,6 @@ "playwright": "^1.7.1", "standard": "^16.0.0", "tape": "^5.1.1", - "tsd": "^0.12.1" + "tsd": "^0.14.0" } }