Files
meteor/packages/minimongo/wrap_transform.js
David Glasser 4a5c980baa Don't doubly-wrap transforms
LocalCollection.wrapTransform is idempotent, so it's OK to doubly-wrap
them, but it's slightly more efficient to notice that a transform has
already been wrapped and not re-wrap it.

(One place where we doubly-wrap transforms is in SynchronousCursor,
which calls wrapTransform on a transform that probably came from
Mongo.Collection, which also wrapped it.)

Fixes #3623.
2015-03-05 17:09:36 -08:00

47 lines
1.5 KiB
JavaScript

// Wrap a transform function to return objects that have the _id field
// of the untransformed document. This ensures that subsystems such as
// the observe-sequence package that call `observe` can keep track of
// the documents identities.
//
// - Require that it returns objects
// - If the return value has an _id field, verify that it matches the
// original _id field
// - If the return value doesn't have an _id field, add it back.
LocalCollection.wrapTransform = function (transform) {
if (! transform)
return null;
// No need to doubly-wrap transforms.
if (transform.__wrappedTransform__)
return transform;
var wrapped = function (doc) {
if (!_.has(doc, '_id')) {
// XXX do we ever have a transform on the oplog's collection? because that
// collection has no _id.
throw new Error("can only transform documents with _id");
}
var id = doc._id;
// XXX consider making tracker a weak dependency and checking Package.tracker here
var transformed = Tracker.nonreactive(function () {
return transform(doc);
});
if (!isPlainObject(transformed)) {
throw new Error("transform must return object");
}
if (_.has(transformed, '_id')) {
if (!EJSON.equals(transformed._id, id)) {
throw new Error("transformed document can't have different _id");
}
} else {
transformed._id = id;
}
return transformed;
};
wrapped.__wrappedTransform__ = true;
return wrapped;
};