Skip to content
This repository has been archived by the owner on Mar 15, 2024. It is now read-only.

Commit

Permalink
fix: use trully pure convertions
Browse files Browse the repository at this point in the history
Actually, `Object.prototype.toString` is impure as it invokes 
`Symbol.toStringTag`. Using a pure convertions makes the agent more 
transparent and less likely to affect the observed application.
  • Loading branch information
lachrist authored and dustinbyrne committed May 15, 2023
1 parent 6938cd8 commit 1416486
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 50 deletions.
111 changes: 72 additions & 39 deletions components/util/default/convert.mjs
Original file line number Diff line number Diff line change
@@ -1,33 +1,89 @@
const {
Boolean,
String,
undefined,
JSON: { stringify: stringifyJSON },
Reflect: { apply },
Object: {
prototype: { toString: Object_prototype_toString },
},
Number,
Number: { isNaN, NEGATIVE_INFINITY, POSITIVE_INFINITY, NaN },
parseInt,
Array: { isArray },
Number: {
isNaN,
NaN,
NEGATIVE_INFINITY,
POSITIVE_INFINITY,
MAX_SAFE_INTEGER,
MIN_SAFE_INTEGER,
},
Math: { round },
JSON: { stringify: stringifyJSON },
} = globalThis;

export const toBoolean = (any) =>
any !== null &&
any !== undefined &&
any !== false &&
any !== 0 &&
any !== 0n &&
any !== "";
export const toBoolean = Boolean;

export const toInteger = (any) => {
if (typeof any === "boolean") {
return Number(any);
} else if (typeof any === "number") {
if (any < MIN_SAFE_INTEGER) {
return NEGATIVE_INFINITY;
} else if (any > MAX_SAFE_INTEGER) {
return POSITIVE_INFINITY;
} else {
return round(any);
}
} else if (typeof any === "bigint") {
if (any < MIN_SAFE_INTEGER) {
return NEGATIVE_INFINITY;
} else if (any > MAX_SAFE_INTEGER) {
return POSITIVE_INFINITY;
} else {
return Number(any);
}
} else if (typeof any === "string") {
return parseInt(any);
} else {
return NaN;
}
};

export const toNumber = (any) => {
if (typeof any === "number") {
if (typeof any === "boolean") {
return any ? 1 : 0;
} else if (typeof any === "number") {
return any;
} else if (typeof any === "bigint" || typeof any === "string") {
} else if (typeof any === "bigint") {
return Number(any);
} else if (typeof any === "string") {
return Number(any);
} else {
return NaN;
}
};

export const toString = (any) => {
if (typeof any === "function") {
return "[function]";
} else if (isArray(any)) {
return "[array]";
} else if (typeof any === "object" && any !== null) {
return "[object]";
} else {
return String(any);
}
};

export const print = (any) => {
if (typeof any === "function") {
return "[function]";
} else if (isArray(any)) {
return "[array]";
} else if (typeof any === "object" && any !== null) {
return "[object]";
} else if (typeof any === "string") {
return stringifyJSON(any);
} else {
return String(any);
}
};

export const jsonifyNumber = (number, replacements) => {
if (number === NEGATIVE_INFINITY) {
return replacements.NEGATIVE_INFINITY;
Expand All @@ -39,26 +95,3 @@ export const jsonifyNumber = (number, replacements) => {
return number;
}
};

const generateStringify = (stringifyString) => (any) => {
if (
typeof any === "boolean" ||
typeof any === "bigint" ||
typeof any === "number" ||
typeof any === "symbol" ||
any === null ||
any === undefined
) {
return String(any);
} else if (typeof any === "string") {
return stringifyString(any);
} else {
return apply(Object_prototype_toString, any, []);
}
};

export const print = generateStringify(stringifyJSON);

const identity = (any) => any;

export const toString = generateStringify(identity);
48 changes: 39 additions & 9 deletions components/util/default/convert.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,64 @@ import { assertEqual } from "../../__fixture__.mjs";
import {
toBoolean,
toNumber,
toInteger,
jsonifyNumber,
print,
toString,
} from "./convert.mjs";

const {
Number,
BigInt,
Number: { NaN, NEGATIVE_INFINITY, POSITIVE_INFINITY },
} = globalThis;

// toBoolean //
assertEqual(toBoolean(1), true);
assertEqual(toBoolean(0), false);

// toInteger //
assertEqual(toInteger(false), 0);
assertEqual(toInteger(true), 1);
assertEqual(toInteger(123), 123);
assertEqual(toInteger(Number(`1${"0".repeat(100)}`)), POSITIVE_INFINITY);
assertEqual(toInteger(Number(`-1${"0".repeat(100)}`)), NEGATIVE_INFINITY);
assertEqual(toInteger(123.4), 123);
assertEqual(toInteger("123"), 123);
assertEqual(toInteger("123.4"), 123);
assertEqual(toInteger(123n), 123);
assertEqual(toInteger(BigInt(`1${"0".repeat(100)}`)), POSITIVE_INFINITY);
assertEqual(toInteger(BigInt(`-1${"0".repeat(100)}`)), NEGATIVE_INFINITY);
assertEqual(toInteger(null), NaN);

// toNumber //
assertEqual(toNumber(false), 0);
assertEqual(toNumber(true), 1);
assertEqual(toNumber(123), 123);
assertEqual(toNumber("123"), 123);
assertEqual(toNumber(123n), 123);
assertEqual(toNumber(null), NaN);

// toString //
assertEqual(
toString(function f() {}),
"[function]",
);
assertEqual(toString([]), "[array]");
assertEqual(toString({}), "[object]");
assertEqual(toString(123), "123");
assertEqual(toString("foo"), "foo");

// toString //
assertEqual(
print(function f() {}),
"[function]",
);
assertEqual(print([]), "[array]");
assertEqual(print({}), "[object]");
assertEqual(print(123), "123");
assertEqual(print("foo"), '"foo"');

// jsonifyNumber //
{
const replacements = {
Expand All @@ -33,12 +72,3 @@ assertEqual(toNumber(null), NaN);
assertEqual(jsonifyNumber(NEGATIVE_INFINITY, replacements), -1);
assertEqual(jsonifyNumber(POSITIVE_INFINITY, replacements), 1);
}

// print //
assertEqual(print(true), "true");
assertEqual(print("foo"), '"foo"');
assertEqual(print([]), "[object Array]");

// toString //
assertEqual(toString(true), "true");
assertEqual(toString("foo"), "foo");
4 changes: 2 additions & 2 deletions components/util/default/format.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ assertEqual(format("%j", [[123]]), "[123]");

// % o //

assertEqual(format("%o", [() => {}]), "[object Function]");
assertEqual(format("%o", [() => {}]), "[function]");

// %O //

Expand All @@ -48,5 +48,5 @@ assertEqual(
},
},
]),
"[object Object]",
"[object]",
);

0 comments on commit 1416486

Please sign in to comment.