if (typeof ot === 'undefined') { // Export for browsers var ot = {}; } ot.WrappedOperation = (function (global) { 'use strict'; // A WrappedOperation contains an operation and corresponing metadata. function WrappedOperation (operation, meta) { this.wrapped = operation; this.meta = meta; } WrappedOperation.prototype.apply = function () { return this.wrapped.apply.apply(this.wrapped, arguments); }; WrappedOperation.prototype.invert = function () { var meta = this.meta; return new WrappedOperation( this.wrapped.invert.apply(this.wrapped, arguments), meta && typeof meta === 'object' && typeof meta.invert === 'function' ? meta.invert.apply(meta, arguments) : meta ); }; // Copy all properties from source to target. function copy (source, target) { for (var key in source) { if (source.hasOwnProperty(key)) { target[key] = source[key]; } } } function composeMeta (a, b) { if (a && typeof a === 'object') { if (typeof a.compose === 'function') { return a.compose(b); } var meta = {}; copy(a, meta); copy(b, meta); return meta; } return b; } WrappedOperation.prototype.compose = function (other) { return new WrappedOperation( this.wrapped.compose(other.wrapped), composeMeta(this.meta, other.meta) ); }; function transformMeta (meta, operation) { if (meta && typeof meta === 'object') { if (typeof meta.transform === 'function') { return meta.transform(operation); } } return meta; } WrappedOperation.transform = function (a, b) { var transform = a.wrapped.constructor.transform; var pair = transform(a.wrapped, b.wrapped); return [ new WrappedOperation(pair[0], transformMeta(a.meta, b.wrapped)), new WrappedOperation(pair[1], transformMeta(b.meta, a.wrapped)) ]; }; return WrappedOperation; }(this)); // Export for CommonJS if (typeof module === 'object') { module.exports = ot.WrappedOperation; }