Comparing version 5.17.0 to 5.18.0
# typeson CHANGES | ||
## 5.18.0 | ||
- Enhancement: Allow `TypesonPromise` `all` and `race` to work with | ||
non-`TypesonPromise` | ||
- Fix: Allow nested plain objects to async revive | ||
- Fix: Have empty keypath at very front, but nested first otherwise | ||
- Fix: Nested `Undefined` | ||
- Fix: Avoid recursion if `undefined` or `NaN`/`Infinity`/`-Infiinity` | ||
values return the same | ||
- Fix: Ensure `iterateIn` array can have async setting | ||
- Testing: Coverage, Intermediate async types | ||
- Docs: Document removing a previously registered spec; | ||
update/clarify `hasConstructorOf` `null` behavior | ||
## 5.17.0 | ||
- Fix: Restore old behavior of nullish spec potentially replacing | ||
- Enhancement: Allow nullifying previous `testPlainObject` specs (by | ||
- Enhancement: Allow nullifying previous `testPlainObjects` specs (by | ||
absence of `test`) | ||
@@ -8,0 +22,0 @@ - npm: Bump devDep. |
{ | ||
"name": "typeson", | ||
"version": "5.17.0", | ||
"version": "5.18.0", | ||
"description": "Preserves types over JSON, BSON or socket.io", | ||
@@ -5,0 +5,0 @@ "main": "./dist/typeson-commonjs2.min.js", |
@@ -431,2 +431,7 @@ # typeson.js | ||
Note that you can supply `null` as a spec to remove a regular previously | ||
registered spec, and supply an object with only `testPlainObjects: true` | ||
to remove a previously registered spec which can remove a previously | ||
registered spec with a plain object replacer. | ||
###### constructor-function | ||
@@ -646,3 +651,3 @@ | ||
`null` was supplied as the `classToCompare` in which case `true` will | ||
be returned. | ||
be returned when finding a `null` prototype (and `false` otherwise). | ||
@@ -649,0 +654,0 @@ #### `Typeson.isObject` (val) |
127
typeson.js
@@ -32,2 +32,6 @@ /* eslint-disable no-shadow */ | ||
function nestedPathsFirst (a, b) { | ||
if (a.keypath === '') { | ||
return -1; | ||
} | ||
let as = a.keypath.match(/\./gu) || 0; | ||
@@ -395,6 +399,10 @@ let bs = b.keypath.match(/\./gu) || 0; | ||
)) { | ||
ret = replace( | ||
keypath, value, stateObj, promisesData, | ||
false, resolvingTypesonPromise, runObserver | ||
); | ||
if (stateObj.replaced) { | ||
ret = value; | ||
} else { | ||
ret = replace( | ||
keypath, value, stateObj, promisesData, | ||
false, resolvingTypesonPromise, runObserver | ||
); | ||
} | ||
if (ret !== value) { | ||
@@ -464,8 +472,3 @@ observerData = {replaced: ret}; | ||
// eslint-disable-next-line no-lonely-if | ||
if ((isArr && stateObj.iterateIn !== 'object') || | ||
stateObj.iterateIn === 'array' | ||
) { | ||
clone = new Array(value.length); | ||
observerData = {clone}; | ||
} else if (keypath === '' && | ||
if (keypath === '' && | ||
hasConstructorOf(value, TypesonPromise) | ||
@@ -478,2 +481,7 @@ ) { | ||
ret = value; | ||
} else if ((isArr && stateObj.iterateIn !== 'object') || | ||
stateObj.iterateIn === 'array' | ||
) { | ||
clone = new Array(value.length); | ||
observerData = {clone}; | ||
} else if ( | ||
@@ -784,11 +792,5 @@ ( | ||
* @param {Any} val | ||
* @param {RevivalReducer} reducer [description] | ||
* @returns {[type]} [description] | ||
*/ | ||
function executeReviver (type, val, reducer) { | ||
if (hasConstructorOf(val, TypesonPromise)) { | ||
return val.then((v) => { // TypesonPromise here too | ||
return reducer(v, type); | ||
}); | ||
} | ||
function executeReviver (type, val) { | ||
const [reviver] = that.revivers[type] || []; | ||
@@ -850,2 +852,4 @@ if (!reviver) { | ||
} | ||
// console.log(plainObjectTypes.sort(nestedPathsFirst)); | ||
/** | ||
@@ -860,22 +864,29 @@ * @typedef {PlainObject} PlainObjectType | ||
}) { | ||
if (hasConstructorOf( | ||
possibleTypesonPromise, TypesonPromise | ||
)) { | ||
// TypesonPromise here too | ||
return possibleTypesonPromise.then((v) => { | ||
return reducer(v, type); | ||
if (isThenable(possibleTypesonPromise)) { | ||
return possibleTypesonPromise.then((val) => { | ||
return reducer(val, { | ||
keypath, type | ||
}); | ||
}); | ||
} | ||
// console.log('obj', JSON.stringify(keypath), obj); | ||
let val = getByKeyPath(obj, keypath); | ||
val = executeReviver(type, val, reducer); | ||
val = executeReviver(type, val); | ||
if (val === undefined) { | ||
return undefined; | ||
if (hasConstructorOf( | ||
val, TypesonPromise | ||
)) { | ||
return val.then((v) => { | ||
const newVal = setAtKeyPath( | ||
obj, keypath, v | ||
); | ||
if (newVal === v) { | ||
obj = newVal; | ||
} | ||
return undefined; | ||
}); | ||
} | ||
if (hasConstructorOf(val, Undefined)) { | ||
val = undefined; | ||
} | ||
const newVal = setAtKeyPath(obj, keypath, val); | ||
if (newVal === val) { | ||
obj = val; | ||
obj = newVal; | ||
} | ||
@@ -890,2 +901,3 @@ return undefined; | ||
const revivalPromises = []; | ||
/** | ||
@@ -905,4 +917,5 @@ * | ||
const type = types[keypath]; | ||
if (isArray(value) || isPlainObject(value)) { | ||
const clone = isArray(value) ? new Array(value.length) : {}; | ||
const isArr = isArray(value); | ||
if (isArr || isPlainObject(value)) { | ||
const clone = isArr ? new Array(value.length) : {}; | ||
// Iterate object or array | ||
@@ -917,6 +930,18 @@ keys(value).forEach((k) => { | ||
); | ||
if (hasConstructorOf(val, Undefined)) { | ||
clone[k] = undefined; | ||
} else if (val !== undefined) { | ||
clone[k] = val; | ||
const set = (v) => { | ||
if (hasConstructorOf(v, Undefined)) { | ||
clone[k] = undefined; | ||
} else if (v !== undefined) { | ||
clone[k] = v; | ||
} | ||
return v; | ||
}; | ||
if (hasConstructorOf(val, TypesonPromise)) { | ||
revivalPromises.push( | ||
val.then((ret) => { | ||
return set(ret); | ||
}) | ||
); | ||
} else { | ||
set(val); | ||
} | ||
@@ -929,5 +954,5 @@ }); | ||
const val = getByKeyPath(target, keyPath); | ||
if (hasConstructorOf(val, Undefined)) { | ||
clone[k] = undefined; | ||
} else if (val !== undefined) { | ||
// Typeson.Undefined not expected here as not cyclic or | ||
// `undefined` | ||
if (val !== undefined) { | ||
clone[k] = val; | ||
@@ -953,4 +978,10 @@ } else { | ||
return [].concat(type).reduce(function reducer (val, type) { | ||
return executeReviver(type, val, reducer); | ||
// `type` can be an array here | ||
return [].concat(type).reduce(function reducer (val, typ) { | ||
if (hasConstructorOf(val, TypesonPromise)) { | ||
return val.then((v) => { // TypesonPromise here too | ||
return reducer(v, typ); | ||
}); | ||
} | ||
return executeReviver(typ, val); | ||
}, value); | ||
@@ -972,6 +1003,18 @@ } | ||
ret = possibleTypesonPromise.then(() => { | ||
return _revive('', obj, null); | ||
return obj; | ||
}); | ||
} else { | ||
ret = _revive('', obj, null); | ||
if (revivalPromises.length) { | ||
// Ensure children resolved | ||
ret = TypesonPromise.resolve(ret).then((r) => { | ||
return TypesonPromise.all([ | ||
// May be a TypesonPromise or not | ||
r, | ||
...revivalPromises | ||
]); | ||
}).then(([r]) => { | ||
return r; | ||
}); | ||
} | ||
} | ||
@@ -978,0 +1021,0 @@ |
@@ -80,3 +80,6 @@ /** | ||
Promise[meth](promArr.map((prom) => { | ||
return prom.p; | ||
return prom && prom.constructor && | ||
prom.constructor.__typeson__type__ === 'TypesonPromise' | ||
? prom.p | ||
: prom; | ||
})).then(typesonResolve, typesonReject); | ||
@@ -83,0 +86,0 @@ }); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
248759
4337
703