New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

core-functions

Package Overview
Dependencies
Maintainers
1
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

core-functions - npm Package Compare versions

Comparing version 2.0.8 to 2.0.9

2

package.json
{
"name": "core-functions",
"version": "2.0.8",
"version": "2.0.9",
"description": "Core functions, utilities and classes for working with Node/JavaScript primitives and built-in objects, including strings, booleans, Promises, base 64, Arrays, Objects, standard AppErrors, etc.",

@@ -5,0 +5,0 @@ "author": "Byron du Preez",

@@ -1,2 +0,2 @@

# core-functions v2.0.8
# core-functions v2.0.9

@@ -106,2 +106,15 @@ Core functions, utilities and classes for working with Node/JavaScript primitives and built-in objects, including

### 2.0.9
- Patched and changed `strings.js` module's `stringify` function:
- To use objects' `toJSON` methods (if any) by default (prior versions did NOT use them at all)
- To add an optional `avoidToJSONMethods` argument to determine whether to avoid using objects' toJSON methods or not (default)
- To double-quote any string elements within an array in order to synchronize with the behaviour of `JSON.stringify`
- To re-sequence the order of errors' property names when they are stringified as normal objects - in order to have an
error's `name` as the first property, followed by its `message` as the second property, followed by the rest of its
enumerable properties (excluding its `stack` property)
- To differentiate simple references to identical objects within the object graph from true circular dependencies:
- Simple references are now marked as `[Reference: {name}]`, whereas the prior version marked them incorrectly as `[Circular: {name}]`
- True circular dependencies are still marked as `[Circular: {name}]`
### 2.0.8

@@ -108,0 +121,0 @@ - Changed `strings.js` module's `stringify` function:

@@ -102,9 +102,10 @@ 'use strict';

* @param {boolean|undefined} [useToStringForErrors] - whether to stringify errors using toString or as normal objects (default)
* @param {boolean|undefined} [avoidToJSONMethods] - whether to avoid using objects' toJSON methods or not (default)
* @param {boolean|undefined} [quoteStrings] - whether to surround simple string values with double-quotes or not (default)
* @returns {string} the value as a string
*/
function stringify(value, useToStringForErrors, quoteStrings) {
function stringify(value, useToStringForErrors, avoidToJSONMethods, quoteStrings) {
const history = new WeakMap();
function stringifyWithHistory(value, name, quoteStrings) {
function stringifyWithHistory(value, name, quote) {
// Special cases for undefined and null

@@ -117,4 +118,4 @@ if (value === undefined) return 'undefined';

// Special cases for strings and Strings
if (typeOfValue === 'string') return quoteStrings ? `"${value}"` : value;
if (value instanceof String) return quoteStrings ? `"${value.valueOf()}"` : value.valueOf();
if (typeOfValue === 'string') return quote ? `"${value}"` : value;
if (value instanceof String) return quote ? `"${value.valueOf()}"` : value.valueOf();

@@ -132,9 +133,20 @@ // Special cases for numbers and Numbers (and special numbers)

// Special case for Functions - show thm as [Function: {function name}]
// Special case for Functions - show them as [Function: {function name}]
if (typeOfValue === 'function') return isNotBlank(value.name) ? `[Function: ${value.name}]` : '[Function: anonymous]';
if (typeOfValue === 'object') {
// Special case for objects that have toJSON methods
if (!avoidToJSONMethods && typeof value.toJSON === 'function') {
return JSON.stringify(value.toJSON());
}
// Check if already seen this same object before
if (history.has(value)) {
// Special case for circular values - show thm as [Circular: {property name}]
return `[Circular: ${history.get(value)}]`;
const historyName = history.get(value);
if (isCircular(name, historyName)) {
// Special case for circular values - show them as [Circular: {property name}]
return `[Circular: ${historyName}]`;
} else {
// Special case for non-circular references to the same object - show them as [Reference: {property name}]
return `[Reference: ${historyName}]`;
}
}

@@ -145,3 +157,3 @@ history.set(value, name);

if (Array.isArray(value)) {
return `[${value.map((e, i) => stringifyWithHistory(e, `${name}[${i}]`, quoteStrings)).join(", ")}]`;
return `[${value.map((e, i) => stringifyWithHistory(e, `${name}[${i}]`, true)).join(", ")}]`;
}

@@ -154,6 +166,7 @@

// Special case for Error objects - include message and name (if any), but exclude stack, which are all normally hidden with JSON.stringify
names = names.filter(n => n !== 'stack');
if (value.name) {
names.push('name');
}
// First exclude name, message and stack
names = names.filter(n => n !== 'stack' && n !== 'name' && n !== 'message');
// Second re-add name and message to the front of the list
if (value.message) names.unshift('message');
if (value.name) names.unshift('name');
}

@@ -181,2 +194,14 @@

function isCircular(name1, name2) {
if (name1.startsWith(name2)) {
const rest1 = name1.substring(name2.length);
return rest1.length === 0 || rest1[0] === '.' || rest1[0] === '['
}
if (name2.startsWith(name1)) {
const rest2 = name2.substring(name1.length);
return rest2.length === 0 || rest2[0] === '.' || rest2[0] === '['
}
return false;
}
/**

@@ -183,0 +208,0 @@ * Returns the index of the nth occurrence of the given searchValue in the given string (if any); otherwise returns -1.

{
"name": "core-functions-tests",
"version": "2.0.8",
"version": "2.0.9",
"author": "Byron du Preez",

@@ -5,0 +5,0 @@ "license": "Apache-2.0",

@@ -98,2 +98,3 @@ 'use strict';

}
// undefined

@@ -173,2 +174,3 @@ check(undefined, !wrapInString); // blank ?

}
// undefined

@@ -247,4 +249,5 @@ check(undefined, wrapInString); // blank ?

}
function checkWithArgs(value, errorsAsObjects, quoteStrings, expected) {
return checkEqual(t, Strings.stringify, [wrap(value, wrapInString), errorsAsObjects, quoteStrings], expected, toPrefix(value, wrapInString));
function checkWithArgs(value, useToStringForErrors, avoidToJSONMethods, quoteStrings, expected) {
return checkEqual(t, Strings.stringify, [wrap(value, wrapInString), useToStringForErrors, avoidToJSONMethods, quoteStrings], expected, toPrefix(value, wrapInString));
}

@@ -320,10 +323,11 @@

check('ABC', 'ABC');
checkWithArgs('ABC', false, true, '"ABC"');
checkWithArgs('', false, false, true, '""');
checkWithArgs('ABC', false, false, true, '"ABC"');
// errors
check(new Error('Planned error'), wrapInString ? 'Error: Planned error' : '{"message":"Planned error","name":"Error"}');
checkWithArgs(new Error('Planned error'), true, false, wrapInString ? 'Error: Planned error' : 'Error: Planned error');
check(new Error('Planned error'), wrapInString ? 'Error: Planned error' : '{"name":"Error","message":"Planned error"}');
checkWithArgs(new Error('Planned error'), true, false, false, wrapInString ? 'Error: Planned error' : 'Error: Planned error');
// circular objects
const circular0 = {a: 1, o: {b:2}};
const circular0 = {a: 1, o: {b: 2}};
circular0.circular = circular0;

@@ -345,3 +349,3 @@ circular0.o.oAgain = circular0.o;

circular1.o.p.pAgain = circular1.o.p;
check(circular1, wrapInString ? '[object Object]' : '{"a":1,"b":2,"o":{"c":"C","p":{"d":"D","thisAgain":[Circular: this],"oAgain":[Circular: this.o],"pAgain":[Circular: this.o.p]},"thisAgain":[Circular: this],"oAgain":[Circular: this.o],"pAgain":[Circular: this.o.p]},"thisAgain":[Circular: this],"oAgain":[Circular: this.o],"pAgain":[Circular: this.o.p]}');
check(circular1, wrapInString ? '[object Object]' : '{"a":1,"b":2,"o":{"c":"C","p":{"d":"D","thisAgain":[Circular: this],"oAgain":[Circular: this.o],"pAgain":[Circular: this.o.p]},"thisAgain":[Circular: this],"oAgain":[Circular: this.o],"pAgain":[Reference: this.o.p]},"thisAgain":[Circular: this],"oAgain":[Reference: this.o],"pAgain":[Reference: this.o.p]}');

@@ -355,5 +359,5 @@ // circular arrays with circular objects

check(array2, wrapInString ? 'a,[object Object],123,' : '[a, {"thisAgain":[Circular: this],"this1Again":[Circular: this[1]]}, 123, [Circular: this]]');
check(array2, wrapInString ? 'a,[object Object],123,' : '["a", {"thisAgain":[Circular: this],"this1Again":[Circular: this[1]]}, 123, [Circular: this]]');
const array3 = ['x', {y:'Y'}, 123];
const array3 = ['x', {y: 'Y'}, 123];
const circular3 = array3[1];

@@ -377,3 +381,3 @@ circular3.thisAgain = circular3;

check(circular4, wrapInString ? '[object Object]' : '{"a":"A","array":["b", {"z":"Z","thisAgain":[Circular: this],"arrayAgain":[Circular: this.array]}, 456, [Circular: this.array]],"thisAgain":[Circular: this],"arrayAgain":[Circular: this.array]}');
check(circular4, wrapInString ? '[object Object]' : '{"a":"A","array":["b", {"z":"Z","thisAgain":[Circular: this],"arrayAgain":[Circular: this.array]}, 456, [Circular: this.array]],"thisAgain":[Circular: this],"arrayAgain":[Reference: this.array]}');

@@ -393,11 +397,76 @@ const array5 = ['c', {x: "X"}, 789];

check(array5, wrapInString ? 'c,[object Object],789,' : '[c, {"x":"X","thisAgain":[Circular: this],"this1Again":[Circular: this[1]],"circular5":{"a":"A","array":[Circular: this],"thisAgain":[Circular: this],"this1Again":[Circular: this[1]],"this1Circular5Again":[Circular: this[1].circular5],"this1Circular5ArrayAgain":[Circular: this]}}, 789, [Circular: this]]');
check(array5, wrapInString ? 'c,[object Object],789,' : '["c", {"x":"X","thisAgain":[Circular: this],"this1Again":[Circular: this[1]],"circular5":{"a":"A","array":[Circular: this],"thisAgain":[Circular: this],"this1Again":[Circular: this[1]],"this1Circular5Again":[Circular: this[1].circular5],"this1Circular5ArrayAgain":[Circular: this]}}, 789, [Circular: this]]');
// reference-only objects
const array6 = [{a:1}, {b:"B"}];
const references6 = {
array6: array6,
array6Again: array6,
array6aOnly: [array6[0]],
array6bOnly: [array6[1]],
diffArrayWithSameElems: [array6[0], array6[1]]
};
check(references6, wrapInString ? '[object Object]' : '{"array6":[{"a":1}, {"b":"B"}],"array6Again":[Reference: this.array6],"array6aOnly":[[Reference: this.array6[0]]],"array6bOnly":[[Reference: this.array6[1]]],"diffArrayWithSameElems":[[Reference: this.array6[0]], [Reference: this.array6[1]]]}');
// Functions
function func() {}
check(func, wrapInString ? 'function func() {}' : '[Function: func]');
check({fn:func}, wrapInString ? '[object Object]' : '{"fn":[Function: func]}');
function func() {
}
//check(func, wrapInString ? 'function func() {}' : '[Function: func]'); // this test breaks if function func() {} is reformatted to multi-line
if (wrapInString) {
t.ok(Strings.stringify(wrap(func, wrapInString)).startsWith('function func('), `stringify(new String(func)) -> ${Strings.stringify(func)} must start with 'function func('`);
} else {
check(func, '[Function: func]');
}
check({fn: func}, wrapInString ? '[object Object]' : '{"fn":[Function: func]}');
// undefined object properties
check({a:undefined}, wrapInString ? '[object Object]' : '{"a":undefined}');
check({a: undefined}, wrapInString ? '[object Object]' : '{"a":undefined}');
// objects with toJSON methods
const task = {
name: "Task1",
definition: {
name: "Task1",
executable: true,
execute: () => { },
subTaskDefs: [],
parent: undefined
},
executable: true,
execute: () => { },
_subTasks: [],
_subTasksByName: {},
parent: undefined,
_state: {
code: "Unstarted",
completed: false,
error: undefined,
rejected: false,
reason: undefined
},
_attempts: 1,
_lastExecutedAt: "2016-12-01T05:09:09.119Z",
_result: undefined,
_error: undefined,
_slaveTasks: [],
_frozen: true,
toJSON: function toJSON() {
return {
name: this.name,
executable: this.executable,
state: this._state,
attempts: this._attempts,
lastExecutedAt: this._lastExecutedAt,
subTasks: this._subTasks
};
}
};
// default behaviour must use toJSON method
check(task, wrapInString ? '[object Object]' : '{"name":"Task1","executable":true,"state":{"code":"Unstarted","completed":false,"rejected":false},"attempts":1,"lastExecutedAt":"2016-12-01T05:09:09.119Z","subTasks":[]}');
// explicit !avoidToJSONMethods must use toJSON method
checkWithArgs(task, false, false, false, wrapInString ? '[object Object]' : '{"name":"Task1","executable":true,"state":{"code":"Unstarted","completed":false,"rejected":false},"attempts":1,"lastExecutedAt":"2016-12-01T05:09:09.119Z","subTasks":[]}');
// explicit avoidToJSONMethods must NOT use toJSON method
checkWithArgs(task, false, true, false, wrapInString ? '[object Object]' : '{"name":"Task1","definition":{"name":"Task1","executable":true,"execute":[Function: anonymous],"subTaskDefs":[],"parent":undefined},"executable":true,"execute":[Function: anonymous],"_subTasks":[],"_subTasksByName":{},"parent":undefined,"_state":{"code":"Unstarted","completed":false,"error":undefined,"rejected":false,"reason":undefined},"_attempts":1,"_lastExecutedAt":"2016-12-01T05:09:09.119Z","_result":undefined,"_error":undefined,"_slaveTasks":[],"_frozen":true,"toJSON":[Function: toJSON]}');
}

@@ -404,0 +473,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc