Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bidar

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bidar - npm Package Compare versions

Comparing version 0.2.0 to 0.2.1

18

lib/iterate.js

@@ -176,10 +176,14 @@ // Copyright 2012 The Obvious Corporation.

innerValue = x[i];
if (type.isUndefined(innerValue) && !hasOwnProperty(x, i)) {
// The element is simply missing (as opposed to being
// defined but set to `undefined`).
continue;
// A missing element is truly absent, as opposed to being
// defined but set to `undefined`.
var missing =
type.isUndefined(innerValue) && !hasOwnProperty(x, i);
visitor.visitArrayElement(x, i, undefined, innerVisitor,
missing);
if (!missing) {
at++;
}
visitor.visitArrayElement(x, i, innerValue, innerVisitor);
at++;
}

@@ -186,0 +190,0 @@

@@ -17,2 +17,3 @@ // Copyright 2012 The Obvious Corporation.

var bufutil = require("./bufutil");
var iterate = require("./iterate");
var type = require("./type");

@@ -94,6 +95,3 @@

/** the function object `Object.hasOwnProperty` */
var hasOwnPropertyFunc = Object.hasOwnProperty;
/*

@@ -104,9 +102,2 @@ * Helper functions

/**
* Safe version of `obj.hasOwnProperty()`.
*/
function hasOwnProperty(obj, name) {
return hasOwnPropertyFunc.call(obj, name);
}
/**
* Determine the sets of all back-referenced objects and all non-data

@@ -118,51 +109,48 @@ * "holes" under the given root. The holes are filtered using the

function findBackRefsAndHoles(root, holeFilter) {
var allowHoles = type.isDefined(holeFilter);
var allRefs = oid.createMap();
var holeSet = oid.createSet();
var allowHoles = type.isDefined(holeFilter);
var holeSet = allowHoles ? oid.createSet() : undefined;
visitValue(root);
var holes = oid.createMap();
allowHoles = false;
holeSet.forEach(function (obj) {
var replacement = holeFilter(obj);
holes.set(obj, replacement);
visitValue(replacement);
});
var backRefs = oid.createSet();
allRefs.forEach(function (key, value) {
if (value > 1) {
backRefs.add(key);
/**
* Check to see if holes are currently being allowed. If not,
* complain appropriateley.
*/
function holeCheck() {
if (allowHoles) {
return;
} else if (type.isUndefined(holeFilter)) {
throw new Error("Hole-ful graph, but no hole filter.");
} else {
throw new Error("Holes not allowed in holes.");
}
});
}
return { backRefs: backRefs, holes: holes };
function addHole(x) {
holeSet.add(x);
}
function visitValue(x) {
switch (typeof x) {
case type.BOOLEAN:
case type.NUMBER:
case type.UNDEFINED: {
// Nothing to do for these.
break;
}
function nop() {
// This space intentionally left blank.
}
case type.FUNCTION: {
visitFunction(x);
break;
}
function keepGoing(obj, name, value, innerVisitor) {
if (innerVisitor) {
innerVisitor();
}
}
function addRef(obj, innerVisitor, mustBeHole) {
if (mustBeHole) {
holeCheck();
}
case type.OBJECT: {
visitObject(x);
break;
}
var count = allRefs.get(obj, 0) + 1;
case type.STRING: {
visitString(x);
break;
}
allRefs.set(obj, count);
default: {
throw new Error("Unknown value type: " + (typeof x));
if (count === 1) {
if (mustBeHole) {
addHole(obj);
} else if (innerVisitor) {
innerVisitor();
}

@@ -172,87 +160,56 @@ }

function visitString(x) {
allRefs.set(x, allRefs.get(x, 0) + 1);
function visitFunction(func, innerVisitor) {
addRef(func, innerVisitor, true);
}
function visitFunction(x) {
holeCheck();
var count = allRefs.get(x, 0) + 1;
allRefs.set(x, count);
if (count == 1) {
addHole(x);
function visitObject(obj, innerVisitor) {
if (Buffer.isBuffer(obj)) {
// Suppress inner visit for buffers.
addRef(obj, undefined);
} else {
addRef(obj, innerVisitor);
}
}
function visitObject(x) {
if (x === null) {
// Nothing to do.
return;
}
var visitor = {
visitObject: visitObject,
visitArray: addRef,
visitFunction: visitFunction,
visitString: addRef,
var count = allRefs.get(x, 0) + 1;
allRefs.set(x, count);
if (count > 1) {
return;
}
var proto = Object.getPrototypeOf(x);
visitObjectPrototype: keepGoing,
visitObjectBinding: keepGoing,
visitObjectGetter: keepGoing,
visitObjectSetter: keepGoing,
visitArrayElement: keepGoing,
if (Array.isArray(x)) {
// Precondition: We are not prepared to deal with an array
// with a "weird" prototype.
if (proto !== arrayPrototype) {
throw new Error("Invalid array prototype.");
}
visitMap(x);
} else if (proto === objectPrototype) {
visitMap(x);
} else if (Buffer.isBuffer(x)) {
// Nothing more to do here.
} else {
holeCheck();
addHole(x);
}
}
visitNumber: nop,
visitBoolean: nop,
visitUndefined: nop,
visitNull: nop
};
function visitMap(x) {
var keys = Object.keys(x);
var length = keys.length;
iterate.iterate(root, visitor);
for (var i = 0; i < length; i++) {
var key = keys[i];
var descriptor = Object.getOwnPropertyDescriptor(x, key);
var holes = undefined;
visitValue(key);
visitValue(descriptor.value);
if (allowHoles) {
holes = oid.createMap();
allowHoles = false;
if (descriptor.get) {
visitValue(descriptor.get);
}
holeSet.forEach(function (obj) {
var replacement = holeFilter(obj);
holes.set(obj, replacement);
iterate.iterate(replacement, visitor);
});
}
if (descriptor.set) {
visitValue(descriptor.set);
}
var backRefs = oid.createSet();
allRefs.forEach(function (key, value) {
if (value > 1) {
backRefs.add(key);
}
}
});
function addHole(x) {
holeSet.add(x);
}
/**
* Check to see if holes are currently being allowed. If not,
* complain appropriateley.
*/
function holeCheck() {
if (allowHoles) {
return;
} else if (type.isUndefined(holeFilter)) {
throw new Error("Hole-ful graph, but no hole filter.");
} else {
throw new Error("Holes not allowed in holes.");
}
}
return { backRefs: backRefs, holes: holes };
}

@@ -312,3 +269,2 @@

var tempBuf = new Buffer(9); // temporary buffer
var headerful = true;

@@ -320,7 +276,5 @@ var backRefSet = undefined;

function setHeaderless() {
headerful = false;
}
var visitor;
function writeGraph(root) {
function writeGraph(root, headerful) {
if (headerful) {

@@ -338,3 +292,3 @@ writeMagic();

writeValue(root);
iterate.iterate(root, visitor);

@@ -359,99 +313,86 @@ if (headerful) {

function writeValue(x) {
switch (typeof x) {
case type.BOOLEAN: writeBoolean(x); break;
case type.FUNCTION: writeFunction(x); break;
case type.NUMBER: writeNumber(x); break;
case type.OBJECT: writeObject(x); break;
case type.STRING: writeString(x); break;
case type.UNDEFINED: writeUndefined(); break;
default: {
throw new Error("Unknown value type: " + (typeof x));
}
}
function writeBuffer(buf) {
writeType(BUFFER_TYPE);
visitNumber(buf.length);
write(buf);
}
function writeBoolean(x) {
writeType(x ? TRUE_TYPE : FALSE_TYPE);
function writeHole(obj) {
var replacement = holeMap.get(obj, obj);
if (replacement === obj) {
throw new Error("Missing replacement for hole.");
}
writeType(HOLE_DEF_TYPE);
iterate.iterate(replacement, visitor);
}
function writeFunction(x) {
if (!handleBackRef(x)) {
writeHole(x);
function handleBackRef(obj) {
if (!backRefSet.has(obj)) {
// No multiple references for this value.
return false;
}
}
function writeNumber(x) {
// "small" exact integers (representable in 53 or fewer bits) are
// written little-endian, prefixed by the number of bytes as
// an ASCII character ('0'..'7'). Everything else is written as
// an IEEE double, prefixed by 'D'.
var index = backRefMap.get(obj);
// The "true" argument here is the "noAssert" flag. We use
// this not because we're sure that the buffer will be big
// enough (in fact we're sure, but that's not a big deal), but
// because if we don't use it, then writeDoubleLE() will throw
// an exception if you try to write out infinities or NaNs,
// even though the underlying code is perfectly happy doing
// so. (See lib/buffer.js in the Node source for more
// details.)
tempBuf.writeDoubleLE(x, 1, true);
if (type.isUndefined(index)) {
// First time this value has been encountered. Add a
// backref definition type tag, and then return false
// to allow the write to proceed.
writeType(BACK_REF_DEF_TYPE);
backRefMap.set(obj, backRefCount);
backRefCount++;
return false;
}
var count = toSmallIntIfPossible(x, tempBuf);
// Second or subsequent time this value has been encountered:
// Write out a back-reference use, and return true to indicate
// that there is nothing more to write in this case.
if (count > 0) {
write(tempBuf, 0, count);
} else {
tempBuf[0] = DOUBLE_TYPE;
write(tempBuf);
}
writeType(BACK_REF_USE_TYPE);
visitNumber(index);
return true;
}
function writeString(x) {
if (handleBackRef(x)) {
function visitObject(obj, innerVisitor) {
if (handleBackRef(obj)) {
// Nothing else to do.
return;
}
var length = x.length;
writeType(STRING_TYPE);
if (Object.getPrototypeOf(obj) === objectPrototype) {
// Header: Type tag and total number of keys.
writeType(MAP_TYPE);
visitNumber(Object.keys(obj).length);
if (x.length === 0) {
writeNumber(0);
// Main contents.
innerVisitor();
} else if (Buffer.isBuffer(obj)) {
writeBuffer(obj);
} else {
var buf = new Buffer(x);
writeNumber(buf.length);
write(buf);
writeHole(obj);
}
}
function visitObjectPrototype(obj, proto, innerVisitor) {
throw new Error("Cannot write object with prototype");
}
function writeUndefined() {
writeType(UNDEFINED_TYPE);
function visitObjectBinding(obj, name, props, innerVisitor) {
visitString(name);
innerVisitor();
}
function writeObject(x) {
if (x === null) {
writeType(NULL_TYPE);
} else if (handleBackRef(x)) {
// Nothing else to do.
} else if (Array.isArray(x)) {
writeArray(x);
} else if (Object.getPrototypeOf(x) === objectPrototype) {
writeMap(x);
} else if (Buffer.isBuffer(x)) {
writeBuffer(x);
} else {
writeHole(x);
}
function visitObjectGetter(obj, name, getter, innerVisitor) {
throw new Error("Cannot write object with dynamic getter");
}
function writeArray(x) {
var keys = Object.keys(x);
var length = x.length;
var count = 0; // number of items written; so as to skip array keys
function visitObjectSetter(obj, name, getter, innerVisitor) {
throw new Error("Cannot write object with dynamic setter");
}
// Precondition: We are not prepared to deal with an array with
// a "weird" prototype.
if (Object.getPrototypeOf(x) !== arrayPrototype) {
throw new Error("Invalid array prototype.");
function visitArray(arr, innerVisitor) {
if (handleBackRef(arr)) {
// Nothing else to do.
return;
}

@@ -463,105 +404,97 @@

writeType(ARRAY_TYPE);
writeNumber(keys.length);
writeNumber(length);
visitNumber(Object.keys(arr).length);
visitNumber(arr.length);
// The regular array elements.
// Main contents.
innerVisitor();
}
for (var i = 0; i < length; i++) {
var value = x[i];
if (type.isUndefined(value) && !hasOwnProperty(x, i)) {
// The element is simply missing (as opposed to being
// defined but set to `undefined`).
writeType(MISSING_ELEMENT_TYPE);
} else {
// The usual case (has a value of some sort).
writeValue(value);
count++;
}
function visitArrayElement(arr, index, value, innerVisitor, missing) {
if (missing) {
writeType(MISSING_ELEMENT_TYPE);
} else {
innerVisitor();
}
}
// The additional map bindings. The sort on the keys is done
// to guarantee a canonical ordering.
keys = keys.slice(count).sort();
writeNameBindings(x, keys);
function visitFunction(func, innerVisitor) {
if (!handleBackRef(func)) {
writeHole(func);
}
}
function writeMap(x) {
// Sort the keys to guarantee a canonical ordering.
var keys = Object.keys(x).sort();
var length = keys.length;
function visitString(str) {
if (handleBackRef(str)) {
// Nothing else to do.
return;
}
// Header: Type tag and total number of keys.
writeType(MAP_TYPE);
writeNumber(length);
var length = str.length;
writeType(STRING_TYPE);
// Main contents.
writeNameBindings(x, keys);
if (str.length === 0) {
visitNumber(0);
} else {
var buf = new Buffer(str);
visitNumber(buf.length);
write(buf);
}
}
/**
* Common binding write code for both arrays and maps.
*/
function writeNameBindings(x, keys) {
var length = keys.length;
function visitNumber(num) {
// "Small" exact integers (representable in 64 or fewer bits) are
// written little-endian, prefixed by the number of bytes as
// an ASCII character ('0'..'7'). Everything else is written as
// an IEEE double, prefixed by 'D'.
for (var i = 0; i < length; i++) {
var key = keys[i];
var descriptor = Object.getOwnPropertyDescriptor(x, key);
// The "true" argument here is the "noAssert" flag. We use
// this not because we're sure that the buffer will be big
// enough (in fact we're sure, but that's not a big deal), but
// because if we don't use it, then writeDoubleLE() will throw
// an exception if you try to write out infinities or NaNs,
// even though the underlying code is perfectly happy doing
// so. (See lib/buffer.js in the Node source for more
// details.)
tempBuf.writeDoubleLE(num, 1, true);
if (descriptor.get || descriptor.set) {
throw new Error("Cannot encode dynamic properties.");
}
var count = toSmallIntIfPossible(num, tempBuf);
writeValue(key);
writeValue(descriptor.value);
if (count > 0) {
write(tempBuf, 0, count);
} else {
tempBuf[0] = DOUBLE_TYPE;
write(tempBuf);
}
}
function writeBuffer(x) {
writeType(BUFFER_TYPE);
writeNumber(x.length);
write(x);
function visitBoolean(bool) {
writeType(bool ? TRUE_TYPE : FALSE_TYPE);
}
function writeHole(x) {
var replacement = holeMap.get(x, x);
if (replacement === x) {
throw new Error("Missing replacement for hole.");
}
function visitUndefined() {
writeType(UNDEFINED_TYPE);
}
writeType(HOLE_DEF_TYPE);
writeValue(replacement);
function visitNull() {
writeType(NULL_TYPE);
}
function handleBackRef(x) {
if (!backRefSet.has(x)) {
// No multiple references for this value.
return false;
}
var visitor = {
visitArray: visitArray,
visitArrayElement: visitArrayElement,
visitBoolean: visitBoolean,
visitFunction: visitFunction,
visitNull: visitNull,
visitNumber: visitNumber,
visitObject: visitObject,
visitObjectBinding: visitObjectBinding,
visitObjectGetter: visitObjectGetter,
visitObjectPrototype: visitObjectPrototype,
visitObjectSetter: visitObjectSetter,
visitString: visitString,
visitUndefined: visitUndefined
};
var index = backRefMap.get(x);
if (type.isUndefined(index)) {
// First time this value has been encountered. Add a
// backref definition type tag, and then return false
// to allow the write to proceed.
writeType(BACK_REF_DEF_TYPE);
backRefMap.set(x, backRefCount);
backRefCount++;
return false;
}
// Second or subsequent time this value has been encountered:
// Write out a back-reference use, and return true to indicate
// that there is nothing more to write in this case.
writeType(BACK_REF_USE_TYPE);
writeValue(index);
return true;
}
return {
setHeaderless: setHeaderless,
writeGraph: writeGraph
writeGraph: writeGraph
};

@@ -575,3 +508,2 @@ }

function createParser(br, holeFiller) {
var headerful = true;
var read = br.read;

@@ -581,7 +513,3 @@ var tempBuf = new Buffer(9);

function setHeaderless() {
headerful = false;
}
function parseGraph() {
function parseGraph(headerful) {
if (headerful) {

@@ -823,4 +751,3 @@ readMagic();

return {
parseGraph: parseGraph,
setHeaderless: setHeaderless
parseGraph: parseGraph
};

@@ -841,3 +768,3 @@ }

serializer.writeGraph(root);
serializer.writeGraph(root, true);
return bw.toBuffer();

@@ -853,3 +780,3 @@ }

return parser.parseGraph();
return parser.parseGraph(true);
}

@@ -877,4 +804,3 @@

serializer.setHeaderless();
serializer.writeGraph(root);
serializer.writeGraph(root, false);
return bw.toBuffer();

@@ -890,4 +816,3 @@ }

parser.setHeaderless();
return parser.parseGraph();
return parser.parseGraph(false);
}

@@ -894,0 +819,0 @@

{
"name": "bidar",
"version": "0.2.0",
"version": "0.2.1",
"keywords":

@@ -5,0 +5,0 @@ ["object", "serialization", "data", "graph"],

@@ -74,3 +74,7 @@ Bidar: Binary Data Representation.

### Bonus
Though not directly about serialization, this module also provides
a generic object iterator, which is handy for all sorts of things.
Example

@@ -160,3 +164,3 @@ -------

### function parse(buf, [holeFiller])
### parse(buf, [holeFiller])

@@ -190,3 +194,3 @@ Parse a serialized form into an object graph, returning the root of the

### function parseNoHead(buf, [holeFiller])
### parseNoHead(buf, [holeFiller])
### parsePartialNoHead(buf, [startIndex], [holeFiller])

@@ -253,6 +257,12 @@ ### serializeNoHead(root, [holeFilter])

* `visitArrayElement(arr, index, value, innerVisitor)` -- called on array
elements, in index order. This is called multiple times from an array
inner visitor, and is always called before `visitObjectBinding() is
called for the named object bindings.
* `visitArrayElement(arr, index, value, innerVisitor, missing)` --
called on array elements, in index order. This is called multiple
times from an array inner visitor, and is always called before
`visitObjectBinding() is called for the named object bindings. The
`missing` parameter (placed after `innerVisitor` both so that it
is easily ignored and so that the `innerVisitor` is always the
fourth argument for object binding iteration calls) is a boolean
that indicates if an array element is actually missing (as opposed
to being set to `undefined`); it will only ever be `true` if `value`
is `undefined`.

@@ -259,0 +269,0 @@ * `visitFunction(func, innerVisitor)` -- called on function objects.

@@ -74,5 +74,9 @@ // Copyright 2012 The Obvious Corporation.

function visitArrayElement(arr, index, value, innerVisitor) {
addLog("visitArrayElement(" + index + ")");
doInner(innerVisitor);
function visitArrayElement(arr, index, value, innerVisitor, missing) {
if (missing) {
addLog("visitArrayElement(" + index + ", missing)");
} else {
addLog("visitArrayElement(" + index + ")");
doInner(innerVisitor);
}
}

@@ -224,2 +228,4 @@

"visitArray()\n" +
" visitArrayElement(0, missing)\n" +
" visitArrayElement(1, missing)\n" +
" visitArrayElement(2)\n" +

@@ -226,0 +232,0 @@ " visitNumber(123)\n" +

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