diff --git a/packages/base/source/adt/union/derivations/debug-representation.js b/packages/base/source/adt/union/derivations/debug-representation.js index 229b3dd..29572a5 100644 --- a/packages/base/source/adt/union/derivations/debug-representation.js +++ b/packages/base/source/adt/union/derivations/debug-representation.js @@ -49,14 +49,20 @@ const functionToString = (fn) => `[Function${functionNameToString(fn)}]`; */ const nullToString = () => 'null'; +/*~ + * type: (Any) => Bool + */ +const isPlainObject = (object) => + !object.toString || (object.toString === Object.prototype.toString); + /*~ * type: (Null | Object Any) => String */ const objectToString = (object) => - object === null ? nullToString - : Array.isArray(object) ? arrayToString - : object.toString() === ({}).toString() ? plainObjectToString - : /* otherwise */ object.toString; + object === null ? nullToString + : Array.isArray(object) ? arrayToString + : isPlainObject(object) ? plainObjectToString + : /* otherwise */ object.toString; /*~ diff --git a/packages/base/source/conversions/nullable-to-result.js b/packages/base/source/conversions/nullable-to-result.js index 6aa48f6..a58777e 100644 --- a/packages/base/source/conversions/nullable-to-result.js +++ b/packages/base/source/conversions/nullable-to-result.js @@ -22,7 +22,7 @@ const deprecated = require('folktale/helpers/warn-deprecation'); * & (a or None) => Result None a */ const nullableToResult = function(a, givenFallback) { - const oldBehaviour = arguments.length < 2; + const oldBehaviour = arguments.length < 2; // eslint-disable-line prefer-rest-params if (oldBehaviour) { deprecated(`nullableToResult(value) is being deprecated in favour of providing an explicit fallback value. nullableToResult(value, fallback) is the new preferred form of this function. diff --git a/packages/base/source/result/index.js b/packages/base/source/result/index.js index b14bf8d..f758759 100644 --- a/packages/base/source/result/index.js +++ b/packages/base/source/result/index.js @@ -32,7 +32,7 @@ module.exports = { fromNullable(aNullable, fallbackValue) { const nullableToResult = require('folktale/conversions/nullable-to-result'); - if (arguments.length > 1) { + if (arguments.length > 1) { // eslint-disable-line prefer-rest-params return nullableToResult(aNullable, fallbackValue); } else { return nullableToResult(aNullable); diff --git a/test/source/specs/base/adt/union.js b/test/source/specs/base/adt/union.js index a2c28f8..1dca2bd 100644 --- a/test/source/specs/base/adt/union.js +++ b/test/source/specs/base/adt/union.js @@ -214,6 +214,28 @@ describe('ADT: union', () => { property('Recursive Values have a string representation', () => { return AB.A({rec:AB.A(1)}).toString() === 'AB.A({ value: { rec: AB.A({ value: 1 }) } })' }) + + property('ADTs containing objects with custom .toString get serialised properly', () => { + const a = { toString(){ return 'hello' }}; + + return AB.A(a).toString() === 'AB.A({ value: hello })' + }); + + // Issue https://github.com/origamitower/folktale/issues/168 + property('ADTs containing objects without a .toString get serialised properly', () => { + const a = Object.create(null); + a.foo = 1; + + return AB.A(a).toString() === 'AB.A({ value: { foo: 1 } })' + }); + + // Issue https://github.com/origamitower/folktale/issues/167 + xit('Circular objects get serialised properly', () => { + const a = Object.create(null); + a.a = a; + + return AB.A(a).toString() === 'AB.A({ value: { a: [Circular] } })' + }); }); describe('Serialization', () => { const AB = union('folktale:AB', {