From 4572b40989a423b17a3ec314bda30dba4ab5c51b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 12 Jun 2023 13:53:44 +0200 Subject: [PATCH 1/3] feat: support `destrSafe` --- src/index.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index bb8253b..a293758 100644 --- a/src/index.ts +++ b/src/index.ts @@ -60,13 +60,16 @@ export function destr(value: any, options: Options = {}): T { if (!JsonSigRx.test(value)) { if (options.strict) { - throw new SyntaxError("Invalid JSON"); + throw new SyntaxError("[destr] Invalid JSON"); } return value as T; } try { if (suspectProtoRx.test(value) || suspectConstructorRx.test(value)) { + if (options.strict) { + throw new Error("[destr] Possible prototype pollution"); + } return JSON.parse(value, jsonParseTransform); } return JSON.parse(value); @@ -78,4 +81,8 @@ export function destr(value: any, options: Options = {}): T { } } +export function destrSafe(value: any, options: Options = {}): T { + return destr(value, { ...options, strict: true }); +} + export default destr; From c0a0c803b6365121a173fa5b5e5016ec531b8a82 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 12 Jun 2023 13:56:35 +0200 Subject: [PATCH 2/3] feat: `destrSafe` util --- README.md | 12 ++++++------ lib/index.cjs | 3 ++- test/index.test.ts | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 18efb6d..3b1929b 100644 --- a/README.md +++ b/README.md @@ -28,16 +28,16 @@ Import into your Node.js project: ```js // CommonJS -const { destr } = require("destr"); +const { destr, destrSafe } = require("destr"); // ESM -import { destr } from "destr"; +import { destr, destrSafe } from "destr"; ``` ### Deno ```js -import { destr } from "https://deno.land/x/destr/src/index.ts"; +import { destr, destrSafe } from "https://deno.land/x/destr/src/index.ts"; console.log(destr('{ "deno": "yay" }')); ``` @@ -98,14 +98,14 @@ destr(input); ### Strict Mode -If `{ strict: true }` passed as second argument, `destr` will throw an error if the input is not a valid JSON string or parsing fails. (non string values and built-ins will be still returned as-is) +When using `destrSafe` it will throw an error if the input is not a valid JSON string or parsing fails. (non string values and built-ins will be still returned as-is) ```js // Returns "[foo" -destr("[foo"); +destrSafe("[foo"); // Throws an error -destr("[foo", { strict: true }); +destrSafe("[foo", { strict: true }); ``` ## Benchmarks diff --git a/lib/index.cjs b/lib/index.cjs index 40e9c78..de84d27 100644 --- a/lib/index.cjs +++ b/lib/index.cjs @@ -1,6 +1,7 @@ -const { destr } = require("../dist/index.cjs"); +const { destr, destrSafe } = require("../dist/index.cjs"); // Allow mixed default and named exports destr.destr = destr; +destr.destrSafe = destrSafe; module.exports = destr; diff --git a/test/index.test.ts b/test/index.test.ts index e9fc69e..621de75 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,5 +1,5 @@ import { expect, it, describe, vi } from "vitest"; -import { destr } from "../src"; +import { destr, destrSafe } from "../src"; describe("destr", () => { it("returns the passed value if it's not a string", () => { @@ -107,7 +107,7 @@ describe("destr", () => { } }); - it("returns the passed string if it's a invalid JSON text and `strict` option is set `false`", () => { + it("returns the passed string if it's a invalid JSON text by default", () => { const testCases = [ { input: "{ " }, { input: "[ " }, @@ -121,7 +121,7 @@ describe("destr", () => { } }); - it("throws an error if it's a invalid JSON texts and `strict` option is set `true`", () => { + it("throws an error if it's a invalid JSON texts with destrSafe", () => { const testCases = [ { input: "{ ", output: "Unexpected end of JSON input" }, { input: "[ ", output: "Unexpected end of JSON input" }, @@ -131,7 +131,7 @@ describe("destr", () => { ]; for (const testCase of testCases) { - expect(() => destr(testCase.input, { strict: true })).toThrowError( + expect(() => destrSafe(testCase.input)).toThrowError( testCase.output || "" ); } From a29e1376da0e7a4190153f90c2d86fafcaa25694 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 12 Jun 2023 13:59:44 +0200 Subject: [PATCH 3/3] rename to `safeDestr` --- README.md | 12 ++++++------ lib/index.cjs | 4 ++-- src/index.ts | 2 +- test/index.test.ts | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 3b1929b..ed4e959 100644 --- a/README.md +++ b/README.md @@ -28,16 +28,16 @@ Import into your Node.js project: ```js // CommonJS -const { destr, destrSafe } = require("destr"); +const { destr, safeDestr } = require("destr"); // ESM -import { destr, destrSafe } from "destr"; +import { destr, safeDestr } from "destr"; ``` ### Deno ```js -import { destr, destrSafe } from "https://deno.land/x/destr/src/index.ts"; +import { destr, safeDestr } from "https://deno.land/x/destr/src/index.ts"; console.log(destr('{ "deno": "yay" }')); ``` @@ -98,14 +98,14 @@ destr(input); ### Strict Mode -When using `destrSafe` it will throw an error if the input is not a valid JSON string or parsing fails. (non string values and built-ins will be still returned as-is) +When using `safeDestr` it will throw an error if the input is not a valid JSON string or parsing fails. (non string values and built-ins will be still returned as-is) ```js // Returns "[foo" -destrSafe("[foo"); +safeDestr("[foo"); // Throws an error -destrSafe("[foo", { strict: true }); +safeDestr("[foo", { strict: true }); ``` ## Benchmarks diff --git a/lib/index.cjs b/lib/index.cjs index de84d27..8d4fa4b 100644 --- a/lib/index.cjs +++ b/lib/index.cjs @@ -1,7 +1,7 @@ -const { destr, destrSafe } = require("../dist/index.cjs"); +const { destr, safeDestr } = require("../dist/index.cjs"); // Allow mixed default and named exports destr.destr = destr; -destr.destrSafe = destrSafe; +destr.safeDestr = safeDestr; module.exports = destr; diff --git a/src/index.ts b/src/index.ts index a293758..8581d94 100644 --- a/src/index.ts +++ b/src/index.ts @@ -81,7 +81,7 @@ export function destr(value: any, options: Options = {}): T { } } -export function destrSafe(value: any, options: Options = {}): T { +export function safeDestr(value: any, options: Options = {}): T { return destr(value, { ...options, strict: true }); } diff --git a/test/index.test.ts b/test/index.test.ts index 621de75..6fc4b03 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,5 +1,5 @@ import { expect, it, describe, vi } from "vitest"; -import { destr, destrSafe } from "../src"; +import { destr, safeDestr } from "../src"; describe("destr", () => { it("returns the passed value if it's not a string", () => { @@ -121,7 +121,7 @@ describe("destr", () => { } }); - it("throws an error if it's a invalid JSON texts with destrSafe", () => { + it("throws an error if it's a invalid JSON texts with safeDestr", () => { const testCases = [ { input: "{ ", output: "Unexpected end of JSON input" }, { input: "[ ", output: "Unexpected end of JSON input" }, @@ -131,7 +131,7 @@ describe("destr", () => { ]; for (const testCase of testCases) { - expect(() => destrSafe(testCase.input)).toThrowError( + expect(() => safeDestr(testCase.input)).toThrowError( testCase.output || "" ); }