diff options
author | Florian Dold <florian.dold@gmail.com> | 2017-08-14 05:01:11 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2017-08-14 05:02:09 +0200 |
commit | 363723fc84f7b8477592e0105aeb331ec9a017af (patch) | |
tree | 29f92724f34131bac64d6a318dd7e30612e631c7 /node_modules/concordance/lib/describe.js | |
parent | 5634e77ad96bfe1818f6b6ee70b7379652e5487f (diff) |
node_modules
Diffstat (limited to 'node_modules/concordance/lib/describe.js')
-rw-r--r-- | node_modules/concordance/lib/describe.js | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/node_modules/concordance/lib/describe.js b/node_modules/concordance/lib/describe.js new file mode 100644 index 000000000..a8aa94572 --- /dev/null +++ b/node_modules/concordance/lib/describe.js @@ -0,0 +1,170 @@ +'use strict' + +const argumentsValue = require('./complexValues/arguments') +const arrayBufferValue = require('./complexValues/arrayBuffer') +const boxedValue = require('./complexValues/boxed') +const dataViewValue = require('./complexValues/dataView') +const dateValue = require('./complexValues/date') +const errorValue = require('./complexValues/error') +const functionValue = require('./complexValues/function') +const globalValue = require('./complexValues/global') +const mapValue = require('./complexValues/map') +const objectValue = require('./complexValues/object') +const promiseValue = require('./complexValues/promise') +const regexpValue = require('./complexValues/regexp') +const setValue = require('./complexValues/set') +const typedArrayValue = require('./complexValues/typedArray') + +const itemDescriptor = require('./metaDescriptors/item') +const mapEntryDescriptor = require('./metaDescriptors/mapEntry') +const propertyDescriptor = require('./metaDescriptors/property') + +const booleanValue = require('./primitiveValues/boolean') +const nullValue = require('./primitiveValues/null') +const numberValue = require('./primitiveValues/number') +const stringValue = require('./primitiveValues/string') +const symbolValue = require('./primitiveValues/symbol') +const undefinedValue = require('./primitiveValues/undefined') + +const getCtor = require('./getCtor') +const getStringTag = require('./getStringTag') +const pluginRegistry = require('./pluginRegistry') +const Registry = require('./Registry') + +const SpecializedComplexes = new Map([ + ['Arguments', argumentsValue.describe], + ['ArrayBuffer', arrayBufferValue.describe], + ['DataView', dataViewValue.describe], + ['Date', dateValue.describe], + ['Error', errorValue.describe], + ['Float32Array', typedArrayValue.describe], + ['Float64Array', typedArrayValue.describe], + ['Function', functionValue.describe], + ['GeneratorFunction', functionValue.describe], + ['global', globalValue.describe], + ['Int16Array', typedArrayValue.describe], + ['Int32Array', typedArrayValue.describe], + ['Int8Array', typedArrayValue.describe], + ['Map', mapValue.describe], + ['Promise', promiseValue.describe], + ['RegExp', regexpValue.describe], + ['Set', setValue.describe], + ['Uint16Array', typedArrayValue.describe], + ['Uint32Array', typedArrayValue.describe], + ['Uint8Array', typedArrayValue.describe], + ['Uint8ClampedArray', typedArrayValue.describe] +]) + +function describePrimitive (value) { + if (value === null) return nullValue.describe() + if (value === undefined) return undefinedValue.describe() + if (value === true || value === false) return booleanValue.describe(value) + + const type = typeof value + if (type === 'number') return numberValue.describe(value) + if (type === 'string') return stringValue.describe(value) + if (type === 'symbol') return symbolValue.describe(value) + + return null +} + +function unboxComplex (tag, complex) { + // Try to unbox by calling `valueOf()`. `describePrimitive()` will return + // `null` if the resulting value is not a primitive, in which case it's + // ignored. + if (typeof complex.valueOf === 'function') { + const value = complex.valueOf() + if (value !== complex) return describePrimitive(value) + } + + return null +} + +function registerPlugins (plugins) { + if (!Array.isArray(plugins) || plugins.length === 0) return () => null + + const tryFns = pluginRegistry.getTryDescribeValues(plugins) + return (value, stringTag, ctor) => { + for (const tryDescribeValue of tryFns) { + const describeValue = tryDescribeValue(value, stringTag, ctor) + if (describeValue) return describeValue + } + + return null + } +} + +function describeComplex (value, registry, tryPlugins, describeAny, describeItem, describeMapEntry, describeProperty) { + if (registry.has(value)) return registry.get(value) + + const stringTag = getStringTag(value) + const ctor = getCtor(stringTag, value) + const pointer = registry.alloc(value) + + let unboxed + let describeValue = tryPlugins(value, stringTag, ctor) + if (describeValue === null) { + if (SpecializedComplexes.has(stringTag)) { + describeValue = SpecializedComplexes.get(stringTag) + } else { + unboxed = unboxComplex(stringTag, value) + if (unboxed !== null) { + describeValue = boxedValue.describe + } else { + describeValue = objectValue.describe + } + } + } + + const descriptor = describeValue({ + ctor, + describeAny, + describeItem, + describeMapEntry, + describeProperty, + pointer: pointer.index, + stringTag, + unboxed, + value + }) + pointer.descriptor = descriptor + return descriptor +} + +function describe (value, options) { + const primitive = describePrimitive(value) + if (primitive !== null) return primitive + + const registry = new Registry() + const tryPlugins = registerPlugins(options && options.plugins) + const curriedComplex = c => { + return describeComplex(c, registry, tryPlugins, describeAny, describeItem, describeMapEntry, describeProperty) + } + + const describeAny = any => { + const descriptor = describePrimitive(any) + return descriptor !== null + ? descriptor + : curriedComplex(any) + } + + const describeItem = (index, valueDescriptor) => { + return valueDescriptor.isPrimitive === true + ? itemDescriptor.describePrimitive(index, valueDescriptor) + : itemDescriptor.describeComplex(index, valueDescriptor) + } + + const describeMapEntry = (keyDescriptor, valueDescriptor) => { + return mapEntryDescriptor.describe(keyDescriptor, valueDescriptor) + } + + const describeProperty = (key, valueDescriptor) => { + const keyDescriptor = describePrimitive(key) + return valueDescriptor.isPrimitive === true + ? propertyDescriptor.describePrimitive(keyDescriptor, valueDescriptor) + : propertyDescriptor.describeComplex(keyDescriptor, valueDescriptor) + } + + return curriedComplex(value) +} +module.exports = describe |