aboutsummaryrefslogtreecommitdiff
path: root/node_modules/concordance/lib/serialize.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/concordance/lib/serialize.js')
-rw-r--r--node_modules/concordance/lib/serialize.js339
1 files changed, 0 insertions, 339 deletions
diff --git a/node_modules/concordance/lib/serialize.js b/node_modules/concordance/lib/serialize.js
deleted file mode 100644
index 07f568415..000000000
--- a/node_modules/concordance/lib/serialize.js
+++ /dev/null
@@ -1,339 +0,0 @@
-'use strict'
-
-const md5hex = require('md5-hex')
-
-const encoder = require('./encoder')
-const pluginRegistry = require('./pluginRegistry')
-
-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 pointerDescriptor = require('./metaDescriptors/pointer')
-const propertyDescriptor = require('./metaDescriptors/property')
-const statsDescriptors = require('./metaDescriptors/stats')
-
-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')
-
-// Increment if encoding layout, descriptor IDs, or value types change. Previous
-// Concordance versions will not be able to decode buffers generated by a newer
-// version, so changing this value will require a major version bump of
-// Concordance itself. The version is encoded as an unsigned 16 bit integer.
-const VERSION = 2
-
-// Adding or removing mappings or changing an index requires the version in
-// encoder.js to be bumped, which necessitates a major version bump of
-// Concordance itself. Indexes are hexadecimal to make reading the binary
-// output easier.
-const mappings = [
- [0x01, booleanValue.tag, booleanValue.deserialize],
- [0x02, nullValue.tag, nullValue.deserialize],
- [0x03, numberValue.tag, numberValue.deserialize],
- [0x04, stringValue.tag, stringValue.deserialize],
- [0x05, symbolValue.tag, symbolValue.deserialize],
- [0x06, undefinedValue.tag, undefinedValue.deserialize],
-
- [0x07, objectValue.tag, objectValue.deserialize],
- [0x08, statsDescriptors.iterableTag, statsDescriptors.deserializeIterableStats],
- [0x09, statsDescriptors.listTag, statsDescriptors.deserializeListStats],
- [0x0A, itemDescriptor.complexTag, itemDescriptor.deserializeComplex],
- [0x0B, itemDescriptor.primitiveTag, itemDescriptor.deserializePrimitive],
- [0x0C, statsDescriptors.propertyTag, statsDescriptors.deserializePropertyStats],
- [0x0D, propertyDescriptor.complexTag, propertyDescriptor.deserializeComplex],
- [0x0E, propertyDescriptor.primitiveTag, propertyDescriptor.deserializePrimitive],
- [0x0F, pointerDescriptor.tag, pointerDescriptor.deserialize],
-
- [0x10, mapValue.tag, mapValue.deserialize],
- [0x11, mapEntryDescriptor.tag, mapEntryDescriptor.deserialize],
-
- [0x12, argumentsValue.tag, argumentsValue.deserialize],
- [0x13, arrayBufferValue.tag, arrayBufferValue.deserialize],
- [0x14, boxedValue.tag, boxedValue.deserialize],
- [0x15, dataViewValue.tag, dataViewValue.deserialize],
- [0x16, dateValue.tag, dateValue.deserialize],
- [0x17, errorValue.tag, errorValue.deserialize],
- [0x18, functionValue.tag, functionValue.deserialize],
- [0x19, globalValue.tag, globalValue.deserialize],
- [0x1A, promiseValue.tag, promiseValue.deserialize],
- [0x1B, regexpValue.tag, regexpValue.deserialize],
- [0x1C, setValue.tag, setValue.deserialize],
- [0x1D, typedArrayValue.tag, typedArrayValue.deserialize],
- [0x1E, typedArrayValue.bytesTag, typedArrayValue.deserializeBytes]
-]
-const tag2id = new Map(mappings.map(mapping => [mapping[1], mapping[0]]))
-const id2deserialize = new Map(mappings.map(mapping => [mapping[0], mapping[2]]))
-
-class DescriptorSerializationError extends Error {
- constructor (descriptor) {
- super('Could not serialize descriptor')
- this.name = 'DescriptorSerializationError'
- this.descriptor = descriptor
- }
-}
-
-class MissingPluginError extends Error {
- constructor (pluginName) {
- super(`Could not deserialize buffer: missing plugin ${JSON.stringify(pluginName)}`)
- this.name = 'MissingPluginError'
- this.pluginName = pluginName
- }
-}
-
-class PointerLookupError extends Error {
- constructor (index) {
- super(`Could not deserialize buffer: pointer ${index} could not be resolved`)
- this.name = 'PointerLookupError'
- this.index = index
- }
-}
-
-class UnsupportedPluginError extends Error {
- constructor (pluginName, serializerVersion) {
- super(`Could not deserialize buffer: plugin ${JSON.stringify(pluginName)} expects a different serialization`)
- this.name = 'UnsupportedPluginError'
- this.pluginName = pluginName
- this.serializerVersion = serializerVersion
- }
-}
-
-class UnsupportedVersion extends Error {
- constructor (serializerVersion) {
- super('Could not deserialize buffer: a different serialization was expected')
- this.name = 'UnsupportedVersion'
- this.serializerVersion = serializerVersion
- }
-}
-
-function shallowSerializeDescriptor (descriptor, resolvePluginRef) {
- if (!descriptor.serialize) return undefined
-
- return serializeState(descriptor.serialize(), resolvePluginRef)
-}
-
-function serializeState (state, resolvePluginRef) {
- if (Array.isArray(state)) return state.map(serializeState)
-
- if (state && state.tag) {
- let id, pluginIndex
- if (tag2id.has(state.tag)) {
- id = tag2id.get(state.tag)
- pluginIndex = 0
- } else {
- const ref = resolvePluginRef(state.tag)
- if (ref) {
- id = ref.id
- pluginIndex = ref.pluginIndex
- }
- }
-
- if (id !== undefined) {
- const serialized = [pluginIndex, id, shallowSerializeDescriptor(state, resolvePluginRef)]
- serialized[encoder.descriptorSymbol] = true
- return serialized
- }
- }
-
- return state
-}
-
-function serialize (descriptor) {
- const usedPlugins = new Map()
- const resolvePluginRef = tag => {
- const ref = pluginRegistry.resolveDescriptorRef(tag)
- if (!ref) return null
-
- if (!usedPlugins.has(ref.name)) {
- // Start at 1, since 0 is reserved for Concordance's descriptors.
- const index = usedPlugins.size + 1
- usedPlugins.set(ref.name, Object.assign({index}, ref.serialization))
- }
-
- return {
- id: ref.id,
- pluginIndex: usedPlugins.get(ref.name).index
- }
- }
-
- const seen = new Set()
-
- const stack = []
- let topIndex = -1
-
- let rootRecord
- do {
- if (descriptor.isComplex === true) {
- if (seen.has(descriptor.pointer)) {
- descriptor = pointerDescriptor.describe(descriptor.pointer)
- } else {
- seen.add(descriptor.pointer)
- }
- }
-
- let id
- let pluginIndex = 0
- if (tag2id.has(descriptor.tag)) {
- id = tag2id.get(descriptor.tag)
- } else {
- const ref = resolvePluginRef(descriptor.tag)
- if (!ref) throw new DescriptorSerializationError(descriptor)
-
- id = ref.id
- pluginIndex = ref.pluginIndex
- }
-
- const record = {
- id,
- pluginIndex,
- children: [],
- state: shallowSerializeDescriptor(descriptor, resolvePluginRef)
- }
- if (!rootRecord) {
- rootRecord = record
- } else {
- stack[topIndex].children.push(record)
- }
-
- if (descriptor.createRecursor) {
- stack.push({ recursor: descriptor.createRecursor(), children: record.children })
- topIndex++
- }
-
- while (topIndex >= 0) {
- descriptor = stack[topIndex].recursor()
- if (descriptor === null) {
- stack.pop()
- topIndex--
- } else {
- break
- }
- }
- } while (topIndex >= 0)
-
- return encoder.encode(VERSION, rootRecord, usedPlugins)
-}
-exports.serialize = serialize
-
-function deserializeState (state, getDescriptorDeserializer) {
- if (state && state[encoder.descriptorSymbol] === true) {
- return shallowDeserializeDescriptor(state, getDescriptorDeserializer)
- }
-
- return Array.isArray(state)
- ? state.map(item => deserializeState(item, getDescriptorDeserializer))
- : state
-}
-
-function shallowDeserializeDescriptor (entry, getDescriptorDeserializer) {
- const deserializeDescriptor = getDescriptorDeserializer(entry[0], entry[1])
- return deserializeDescriptor(entry[2])
-}
-
-function deserializeRecord (record, getDescriptorDeserializer, buffer) {
- const deserializeDescriptor = getDescriptorDeserializer(record.pluginIndex, record.id)
- const state = deserializeState(record.state, getDescriptorDeserializer)
-
- if (record.pointerAddresses.length === 0) {
- return deserializeDescriptor(state)
- }
-
- const endIndex = record.pointerAddresses.length
- let index = 0
- const recursor = () => {
- if (index === endIndex) return null
-
- const recursorRecord = encoder.decodeRecord(buffer, record.pointerAddresses[index++])
- return deserializeRecord(recursorRecord, getDescriptorDeserializer, buffer)
- }
-
- return deserializeDescriptor(state, recursor)
-}
-
-function buildPluginMap (buffer, options) {
- const cache = options && options.deserializedPluginsCache
- const cacheKey = md5hex(buffer)
- if (cache && cache.has(cacheKey)) return cache.get(cacheKey)
-
- const decodedPlugins = encoder.decodePlugins(buffer)
- if (decodedPlugins.size === 0) {
- const pluginMap = new Map()
- if (cache) cache.set(cacheKey, pluginMap)
- return pluginMap
- }
-
- const deserializerLookup = new Map()
- if (Array.isArray(options && options.plugins)) {
- for (const deserializer of pluginRegistry.getDeserializers(options.plugins)) {
- deserializerLookup.set(deserializer.name, deserializer)
- }
- }
-
- const pluginMap = new Map()
- for (const index of decodedPlugins.keys()) {
- const used = decodedPlugins.get(index)
- const pluginName = used.name
- const serializerVersion = used.serializerVersion
-
- // TODO: Allow plugin author to encode a helpful message in its serialization
- if (!deserializerLookup.has(pluginName)) {
- throw new MissingPluginError(pluginName)
- }
- if (serializerVersion !== deserializerLookup.get(pluginName).serializerVersion) {
- throw new UnsupportedPluginError(pluginName, serializerVersion)
- }
-
- pluginMap.set(index, deserializerLookup.get(pluginName).id2deserialize)
- }
-
- if (cache) cache.set(cacheKey, pluginMap)
- return pluginMap
-}
-
-function deserialize (buffer, options) {
- const version = encoder.extractVersion(buffer)
- if (version !== VERSION) throw new UnsupportedVersion(version)
-
- const decoded = encoder.decode(buffer)
- const pluginMap = buildPluginMap(decoded.pluginBuffer, options)
-
- const descriptorsByPointerIndex = new Map()
- const mapPointerDescriptor = descriptor => {
- if (descriptor.isPointer === true) {
- if (!descriptorsByPointerIndex.has(descriptor.index)) throw new PointerLookupError(descriptor.index)
-
- return descriptorsByPointerIndex.get(descriptor.index)
- } else if (descriptor.isComplex === true) {
- descriptorsByPointerIndex.set(descriptor.pointer, descriptor)
- }
- return descriptor
- }
-
- const getDescriptorDeserializer = (pluginIndex, id) => {
- return (state, recursor) => {
- const deserializeDescriptor = pluginIndex === 0
- ? id2deserialize.get(id)
- : pluginMap.get(pluginIndex).get(id)
-
- return mapPointerDescriptor(deserializeDescriptor(state, recursor))
- }
- }
- return deserializeRecord(decoded.rootRecord, getDescriptorDeserializer, buffer)
-}
-exports.deserialize = deserialize