diff --git a/_static/atom.js b/_static/atom.js new file mode 100644 index 000000000..49642ee41 --- /dev/null +++ b/_static/atom.js @@ -0,0 +1,48 @@ +function createAtom(val, options) { + var watchers = {}; + var validator = options && options.validator || function () { return true; }; + + function transition(next) { + if (!validator(next)) { + var err = new Error(next + " failed validation"); + err.name = "AssertionError"; + throw err; + } + + var prev = val; + val = next; + + Object.keys(watchers).forEach(function (k) { + watchers[k](k, atom, prev, next); + }); + } + + var atom = { + addWatch: function (key, fn) { + watchers[key] = fn; + }, + + removeWatch: function (key) { + delete watchers[key]; + }, + + swap: function (fn) { + var args = [val].concat([].slice.call(arguments, 1)); + transition(fn.apply(null, args)); + }, + + reset: function (v) { + transition(v); + }, + + deref: function () { + return val; + }, + + toString: function () { + return "Atom(" + JSON.stringify(val) + ")"; + } + }; + + return atom; +} diff --git a/_static/chart-of-accounts.js b/_static/chart-of-accounts.js new file mode 100644 index 000000000..bc272e882 --- /dev/null +++ b/_static/chart-of-accounts.js @@ -0,0 +1,355 @@ +(function () { + 'use strict'; + + // .journals + // .t-accounts + // .chart-of-accounts + // document.addEventListener('DOMContentLoaded', function () { + // React.render( + // React.createElement(CoA), + // document.querySelector('.chart-of-accounts')); + // }); + var data = createAtom(); + + function toKey(s, postfix) { + if (postfix) { + s += ' ' + postfix; + } + return s.replace(/[^0-9a-z ]/gi, '').toLowerCase().split(/\s+/).join('-'); + + } + var isFulfilled = (function () { + var enabledTransactions = Immutable.Seq(); + // memoize enabled ops so they don't have to be recomputed all the time + data.addWatch('enableds', function (k, m, prev, next) { + enabledTransactions = next.filter(function (v, k) { + return v.get('enabled'); + }).keySeq(); + }); + return function isFulfilled(deps) { + var d = Immutable.Set(deps); + return d.isEmpty() || d.subtract(enabledTransactions).isEmpty(); + } + })(); + + function isEnabled(transaction) { + var item = data.deref().get(transaction); + return item.get('enabled') && isFulfilled(item.get('depends')); + } + var Controls = React.createClass({ + getInitialState: function () { + return { folded: true }; + }, + toggle: function () { + this.setState({folded: !this.state.folded}); + }, + render: function () { + return React.DOM.div( + null, + React.DOM.h4( + { onClick: this.toggle, style: { cursor: 'pointer' } }, + this.state.folded ? "\u25B8 " : "\u25BE ", + "Operations"), + this.state.folded ? undefined : this.props.p.map(function (v, k) { + return React.DOM.label( + {key: k, style: {display: 'block' } }, + React.DOM.input({ + type: 'checkbox', + disabled: !isFulfilled(v.get('depends')), + checked: v.get('enabled'), + onChange: function () { + data.swap(function (d) { + return d.updateIn( + [k, 'enabled'], + function (check) { return !check; }); + }); + } + }), + " ", + v.get('label') + ); + }, this).toArray() + ); + } + }); + + var Journal = React.createClass({ + render: function () { + return React.DOM.div( + null, + React.createElement(Controls, this.props), + React.DOM.table( + {className: 'table'}, + React.DOM.thead( + null, + React.DOM.tr( + null, + React.DOM.th(), + React.DOM.th({width: '20%'}, "Debit"), + React.DOM.th({width: '20%'}, "Credit") + ) + ), + React.DOM.tbody( + null, + this.props.p + .filter(function (v, k) { return isEnabled(k); }) + .valueSeq() + .flatMap(function (tx) { + if (tx.get('operations').isEmpty()) { + return []; + } + var label = tx.get('label'); + var k = toKey(label); + return tx.get('operations').toSeq().map(function (op) { + var credit = op.get('credit'), debit = op.get('debit'); + return React.DOM.tr( + {key: toKey(label, op.get('account'))}, + React.DOM.td( + null, + credit ? '\u2001' : '', + accounts[op.get('account')].label + ), + React.DOM.td(null, debit && debit(this.props.p)), + React.DOM.td(null, credit && credit(this.props.p)) + ); + }, this).concat( + React.DOM.tr( + {key: k + '-label'}, + React.DOM.td( + {colSpan: 3, style: {textAlign: 'center'}}, + label)), + React.DOM.tr( + {key: k + '-spacer'}, + React.DOM.td({colSpan: 3}, "\u00A0")) + ); + }, this) + .toArray() + ) + ) + ); + } + }); + + data.addWatch('journals', function (k, m, prev, next) { + React.render( + React.createElement(Journal, {p: next}), + document.querySelector('.journals') + ); + }); + + var Chart = React.createClass({ + render: function () { + return React.DOM.div( + null, + React.createElement(Controls, {p: this.props.p}), + DOM.table( + {className: 'table'}, + DOM.tr( + null, + DOM.th(), + DOM.th({className: 'text-right'}, "Debit"), + DOM.th({className: 'text-right'}, "Credit"), + DOM.th({className: 'text-right'}, "Balance")), + this.accounts().map(function (data) { + return DOM.tr( + {key: data.code}, + DOM.th(null, + data.level ? '\u2001 ' : '', + data.code, ' ', data.label), + DOM.td({className: 'text-right'}, data.debit), + DOM.td({className: 'text-right'}, data.credit), + DOM.td({className: 'text-right'}, data.debit - data.credit) + ); + }) + ) + ); + }, + accounts: function() { + var _this = this; + var out = []; + var zero = function () { return 0; } + var data = this.props.p; + // for each operated-on account, apply all operations and save the + // resulting (debit, credit) state + var chart = data + .filter(function (v, k) { return isEnabled(k); }) + .valueSeq() + .flatMap(function (v) { return v.get('operations'); }) + .reduce(function (acc, op) { + // update operation's account debit and credit by adding + // operation's debit and credit to them, initialize to 0 + // if not set yet + return acc + .updateIn([op.get('account'), 'debit'], 0, function (d) { + return d + op.get('debit', zero)(data); + }) + .updateIn([op.get('account'), 'credit'], 0, function (c) { + return c + op.get('credit', zero)(data); + }); + }, Immutable.Map()); + categories.forEach(function (cat) { + var current = { level: 0, label: cat.label, code: cat.code, credit: 0, debit: 0 }; + var values = accs(cat).map(function (acc) { + // If no operation has been performed on an account, 0 debit or credit + var it = chart.get(acc.code, Immutable.Map({credit: 0, debit: 0})); + var debit = it.get('debit') || 0; + var credit = it.get('credit') || 0; + current.debit += debit; + current.credit += credit; + return { + level: 1, + code: acc.code, + label: acc.label, + debit: debit, + credit: credit + } + }); + values.unshift(current); + out.push.apply(out, values); + }); + return out; + } + }); + data.addWatch('chart', function (k, m, prev, next) { + React.render( + React.createElement(Chart, {p: next}), + document.querySelector('.chart-of-accounts')); + }); + + document.addEventListener('DOMContentLoaded', function () { + var sale = 100, + tax = sale * 0.09, + total = sale + tax, + refund = sale * 0.1, + purchase = 80; + data.reset(Immutable.fromJS({ + customer_invoice: { + enabled: false, + label: "Customer Invoice ($100 + 9% tax)", + depends: [], + operations: [ + {account: ASSETS.ACCOUNTS_RECEIVABLE.code, debit: function () { return total; }}, + {account: REVENUE.SALES.code, credit: function () { return sale; }}, + {account: LIABILITIES.TAXES_PAYABLE.code, credit: function () { return tax; }} + ] + }, + // TODO: dependencies? + customer_refund: { + enabled: false, + label: "Customer Refund 10%", + depends: ['customer_invoice'], + operations: [ + {account: REVENUE.SALES.code, debit: function () { return refund; }}, + {account: ASSETS.ACCOUNTS_RECEIVABLE.code, credit: function () { return refund; }} + ] + }, + customer_payment: { + enabled: false, + label: "Customer Payment", + depends: ['customer_invoice'], + operations: [ + // TODO: depends of refund + {account: ASSETS.CASH.code, debit: function (ops) { + return ops.getIn(['customer_refund', 'enabled']) + ? total - refund + : total; + }}, + {account: ASSETS.ACCOUNTS_RECEIVABLE.code, credit: function (ops) { + return ops.getIn(['customer_refund', 'enabled']) + ? total - refund + : total; + }} + ] + }, + supplier_invoice: { + enabled: false, + label: "Supplier Invoice", + depends: [], + operations: [ + {account: EXPENSES.PURCHASES.code, debit: function () { return purchase; }}, + {account: LIABILITIES.ACCOUNTS_PAYABLE.code, credit: function () { return purchase; }}, + ] + }, + supplier_invoice_paid: { + enabled: false, + label: "Supplier Invoice Paid", + depends: ['supplier_invoice'], + operations: [ + {account: LIABILITIES.ACCOUNTS_PAYABLE.code, debit: function () { return purchase; }}, + {account: ASSETS.CASH.code, credit: function () { return purchase; }} + ] + }, + inventory_reception: { + enabled: false, + label: "Inventory Reception", + depends: ['supplier_invoice'], + // TODO: ??? + operations: [] + }, + customer_delivery: { + enabled: false, + label: "Customer Delivery", + depends: ['customer_invoice', 'inventory_reception'], + // TODO: ??? + operations: [], + }, + taxes: { + enabled: false, + label: "Pay Taxes Due", + depends: [], + // TODO: no taxes due if no customer invoice? + operations: [ + {account: LIABILITIES.TAXES_PAYABLE.code, debit: function () { return tax; }}, + {account: ASSETS.CASH.code, credit: function () { return tax; }} + ] + }, + })); + }); + + var DOM = React.DOM; + + var ASSETS = { + code: 1, + label: "Assets", + CASH: { code: 10100, label: "Cash" }, + ACCOUNTS_RECEIVABLE: { code: 12100, label: "Accounts Receivable" } + }; + var LIABILITIES = { + code: 2, + label: "Liabilities", + ACCOUNTS_PAYABLE: { code: 21000, label: "Accounts Payable" }, + TAXES_PAYABLE: { code: 23100, label: "Taxes Payable" } + }; + var REVENUE = { + code: 4, + label: "Revenue", + SALES: { code: 40100, label: "Sales" } + }; + var EXPENSES = { + code: 5, + label: "Expenses", + PURCHASES: { code: 50100, label: "Purchases" } + }; + var categories = [ASSETS, LIABILITIES, REVENUE, EXPENSES]; + var accounts = (function () { + var acs = {}; + categories.forEach(function (cat) { + acs[cat.code] = cat; + accs(cat).forEach(function (acc) { + acs[acc.code] = acc; + }); + }); + return acs; + })(); + + + function accs(category) { + var out = []; + for(var k in category) { + if (k.toUpperCase() === k) { + out.push(category[k]); + } + } + return out; + } +})(); diff --git a/_static/accounting.js b/_static/fiscalyear.js similarity index 67% rename from _static/accounting.js rename to _static/fiscalyear.js index fb2a0daa3..22171c8c3 100644 --- a/_static/accounting.js +++ b/_static/fiscalyear.js @@ -1,46 +1,22 @@ (function () { 'use strict'; - var Table = React.createClass({ - getInitialState: function () { - return {text: [], counter: 0}; - }, - render: function () { - return React.createElement( - 'div', null, - React.createElement('button', { - style: {color: 'red'}, - onClick: this.handleClick, - }, "Click Me!"), - React.createElement('ul', null, this.state.text.map(function (item) { - return React.createElement( - 'li', null, "This is number ", item); - })) - ); - }, - handleClick: function () { - this.setState({ - text: this.state.text.concat([this.state.counter]), - counter: this.state.counter + 1, - }) - }, - }); - function item(it) { if (it.credit && it.debit) { throw new Error("A journal item can't have both credit and debit, got " + JSON.stringify(it)); } - return React.createElement( - 'tr', null, - React.createElement('td', null, (it.credit ? '\u2001' : '') + it.label), - React.createElement('td', null, it.debit), - React.createElement('td', null, it.credit) + return React.DOM.tr( + {key: it.label.toLowerCase().split(' ').concat( + ['debit', it.debit, 'credit', it.credit] + ).join('-') + }, + React.DOM.td(null, (it.credit ? '\u2001' : '') + it.label), + React.DOM.td(null, it.debit), + React.DOM.td(null, it.credit) ); } - function spacer() { - return React.createElement( - 'tr', null, React.createElement( - 'td', {colSpan: 3}, "\u00A0")); + function spacer(key) { + return React.DOM.tr({key: 'spacer-' + key}, React.DOM.td({colSpan: 3}, "\u00A0")); } var ClotureTable = React.createClass({ @@ -68,18 +44,18 @@ }, render: function () { - return React.createElement( - 'div', null, + return React.DOM.div( + null, this.controls(), - React.createElement( - 'table', {className: 'table'}, + React.DOM.table( + {className: 'table'}, this.makeHeader(), - React.createElement( - 'tbody', null, + React.DOM.tbody( + null, this.revenues(this.state.revenues), - spacer(), + spacer('table-1'), this.expenses(this.state.expenses), - spacer(), + spacer('table-2'), this.closure({ dividends: this.state.dividends, income: this.income(), @@ -89,13 +65,13 @@ ); }, makeHeader: function () { - return React.createElement( - 'thead', null, - React.createElement( - 'tr', null, - React.createElement('th'), - React.createElement('th', null, "Debit"), - React.createElement('th', null, "Credit") + return React.DOM.thead( + null, + React.DOM.tr( + null, + React.DOM.th(), + React.DOM.th(null, "Debit"), + React.DOM.th(null, "Credit") ) ); }, @@ -103,12 +79,12 @@ controls: function () { var _this = this; return [ - React.createElement( - 'fieldset', null, - React.createElement('legend', null, "Income"), - React.createElement( - 'label', null, "Cash ", - React.createElement('input', { + React.DOM.fieldset( + {key: 'income'}, + React.DOM.legend(null, "Income"), + React.DOM.label( + null, "Cash ", + React.DOM.input({ type: 'number', step: 1, value: this.state.revenues.cash, @@ -123,9 +99,10 @@ } }) ), - React.createElement( - 'label', null, " Accounts Receivable ", - React.createElement('input', { + ' ', + React.DOM.label( + null, " Accounts Receivable ", + React.DOM.input({ type: 'number', step: 1, value: this.state.revenues.receivable, @@ -141,12 +118,12 @@ }) ) ), - React.createElement( - 'fieldset', null, - React.createElement('legend', null, "Expenses"), - React.createElement( - 'label', null, "Cash ", - React.createElement('input', { + React.DOM.fieldset( + {key: 'expenses'}, + React.DOM.legend(null, "Expenses"), + React.DOM.label( + null, "Cash ", + React.DOM.input({ type: 'number', step: 1, value: this.state.expenses.cash, @@ -161,9 +138,10 @@ } }) ), - React.createElement( - 'label', null, " Accounts Payable ", - React.createElement('input', { + ' ', + React.DOM.label( + null, " Accounts Payable ", + React.DOM.input({ type: 'number', step: 1, value: this.state.expenses.payable, @@ -179,13 +157,13 @@ }) ) ), - React.createElement( - 'fieldset', null, - React.createElement('legend', null, "Dividends"), - React.createElement( - 'label', null, + React.DOM.fieldset( + {key: 'dividends'}, + React.DOM.legend(null, "Dividends"), + React.DOM.label( + null, "Ratio (from retained earnings) ", - React.createElement('input', { + React.DOM.input({ type: 'range', min: 0, max: 1, @@ -220,7 +198,7 @@ } if (dividends) { result = result.concat([ - spacer(), + spacer('closure'), item({label: "Retained Earnings", debit: dividends}), item({label: "Dividends Payable", credit: dividends}) ]); @@ -233,13 +211,10 @@ item({label: "Cash", debit: props.cash}), item({label: "Accounts Receivable", debit: props.receivable}), item({label: "Revenue", credit: total}), - React.createElement( - 'tr', null, React.createElement( - 'td', {colSpan: 3}, - "\u2001\u2001Consolidation of revenues" - ) - ), - spacer(), + React.DOM.tr({key: 'revenue-notes'}, React.DOM.td( + {colSpan: 3}, + "\u2001\u2001Consolidation of revenues")), + spacer('revenues'), item({label: "Revenue", debit: total}), item({label: "Income Summary", credit: total}) ]; @@ -250,13 +225,13 @@ item({label: "Expenses", debit: total}), item({label: "Cash", credit: props.cash}), item({label: "Accounts Payable", credit: props.payable}), - React.createElement( - 'tr', null, React.createElement( - 'td', {colSpan: 3}, + React.DOM.tr( + {key: 'expenses-note'}, React.DOM.td( + {colSpan: 3}, "\u2001\u2001Consolidation of expenses" ) ), - spacer(), + spacer('expenses'), item({label: "Income Summary", debit: total}), item({label: "Expenses", credit: total}) ]; diff --git a/_static/immutable.js b/_static/immutable.js new file mode 100644 index 000000000..bbcc977e4 --- /dev/null +++ b/_static/immutable.js @@ -0,0 +1,4856 @@ +/** + * Copyright (c) 2014-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.Immutable = factory() +}(this, function () { 'use strict';var SLICE$0 = Array.prototype.slice; + + function createClass(ctor, superClass) { + if (superClass) { + ctor.prototype = Object.create(superClass.prototype); + } + ctor.prototype.constructor = ctor; + } + + // Used for setting prototype methods that IE8 chokes on. + var DELETE = 'delete'; + + // Constants describing the size of trie nodes. + var SHIFT = 5; // Resulted in best performance after ______? + var SIZE = 1 << SHIFT; + var MASK = SIZE - 1; + + // A consistent shared value representing "not set" which equals nothing other + // than itself, and nothing that could be provided externally. + var NOT_SET = {}; + + // Boolean references, Rough equivalent of `bool &`. + var CHANGE_LENGTH = { value: false }; + var DID_ALTER = { value: false }; + + function MakeRef(ref) { + ref.value = false; + return ref; + } + + function SetRef(ref) { + ref && (ref.value = true); + } + + // A function which returns a value representing an "owner" for transient writes + // to tries. The return value will only ever equal itself, and will not equal + // the return of any subsequent call of this function. + function OwnerID() {} + + // http://jsperf.com/copy-array-inline + function arrCopy(arr, offset) { + offset = offset || 0; + var len = Math.max(0, arr.length - offset); + var newArr = new Array(len); + for (var ii = 0; ii < len; ii++) { + newArr[ii] = arr[ii + offset]; + } + return newArr; + } + + function ensureSize(iter) { + if (iter.size === undefined) { + iter.size = iter.__iterate(returnTrue); + } + return iter.size; + } + + function wrapIndex(iter, index) { + return index >= 0 ? (+index) : ensureSize(iter) + (+index); + } + + function returnTrue() { + return true; + } + + function wholeSlice(begin, end, size) { + return (begin === 0 || (size !== undefined && begin <= -size)) && + (end === undefined || (size !== undefined && end >= size)); + } + + function resolveBegin(begin, size) { + return resolveIndex(begin, size, 0); + } + + function resolveEnd(end, size) { + return resolveIndex(end, size, size); + } + + function resolveIndex(index, size, defaultIndex) { + return index === undefined ? + defaultIndex : + index < 0 ? + Math.max(0, size + index) : + size === undefined ? + index : + Math.min(size, index); + } + + function Iterable(value) { + return isIterable(value) ? value : Seq(value); + } + + + createClass(KeyedIterable, Iterable); + function KeyedIterable(value) { + return isKeyed(value) ? value : KeyedSeq(value); + } + + + createClass(IndexedIterable, Iterable); + function IndexedIterable(value) { + return isIndexed(value) ? value : IndexedSeq(value); + } + + + createClass(SetIterable, Iterable); + function SetIterable(value) { + return isIterable(value) && !isAssociative(value) ? value : SetSeq(value); + } + + + + function isIterable(maybeIterable) { + return !!(maybeIterable && maybeIterable[IS_ITERABLE_SENTINEL]); + } + + function isKeyed(maybeKeyed) { + return !!(maybeKeyed && maybeKeyed[IS_KEYED_SENTINEL]); + } + + function isIndexed(maybeIndexed) { + return !!(maybeIndexed && maybeIndexed[IS_INDEXED_SENTINEL]); + } + + function isAssociative(maybeAssociative) { + return isKeyed(maybeAssociative) || isIndexed(maybeAssociative); + } + + function isOrdered(maybeOrdered) { + return !!(maybeOrdered && maybeOrdered[IS_ORDERED_SENTINEL]); + } + + Iterable.isIterable = isIterable; + Iterable.isKeyed = isKeyed; + Iterable.isIndexed = isIndexed; + Iterable.isAssociative = isAssociative; + Iterable.isOrdered = isOrdered; + + Iterable.Keyed = KeyedIterable; + Iterable.Indexed = IndexedIterable; + Iterable.Set = SetIterable; + + + var IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@'; + var IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@'; + var IS_INDEXED_SENTINEL = '@@__IMMUTABLE_INDEXED__@@'; + var IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@'; + + /* global Symbol */ + + var ITERATE_KEYS = 0; + var ITERATE_VALUES = 1; + var ITERATE_ENTRIES = 2; + + var REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; + var FAUX_ITERATOR_SYMBOL = '@@iterator'; + + var ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL; + + + function Iterator(next) { + this.next = next; + } + + Iterator.prototype.toString = function() { + return '[Iterator]'; + }; + + + Iterator.KEYS = ITERATE_KEYS; + Iterator.VALUES = ITERATE_VALUES; + Iterator.ENTRIES = ITERATE_ENTRIES; + + Iterator.prototype.inspect = + Iterator.prototype.toSource = function () { return this.toString(); } + Iterator.prototype[ITERATOR_SYMBOL] = function () { + return this; + }; + + + function iteratorValue(type, k, v, iteratorResult) { + var value = type === 0 ? k : type === 1 ? v : [k, v]; + iteratorResult ? (iteratorResult.value = value) : (iteratorResult = { + value: value, done: false + }); + return iteratorResult; + } + + function iteratorDone() { + return { value: undefined, done: true }; + } + + function hasIterator(maybeIterable) { + return !!getIteratorFn(maybeIterable); + } + + function isIterator(maybeIterator) { + return maybeIterator && typeof maybeIterator.next === 'function'; + } + + function getIterator(iterable) { + var iteratorFn = getIteratorFn(iterable); + return iteratorFn && iteratorFn.call(iterable); + } + + function getIteratorFn(iterable) { + var iteratorFn = iterable && ( + (REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) || + iterable[FAUX_ITERATOR_SYMBOL] + ); + if (typeof iteratorFn === 'function') { + return iteratorFn; + } + } + + function isArrayLike(value) { + return value && typeof value.length === 'number'; + } + + createClass(Seq, Iterable); + function Seq(value) { + return value === null || value === undefined ? emptySequence() : + isIterable(value) ? value.toSeq() : seqFromValue(value); + } + + Seq.of = function(/*...values*/) { + return Seq(arguments); + }; + + Seq.prototype.toSeq = function() { + return this; + }; + + Seq.prototype.toString = function() { + return this.__toString('Seq {', '}'); + }; + + Seq.prototype.cacheResult = function() { + if (!this._cache && this.__iterateUncached) { + this._cache = this.entrySeq().toArray(); + this.size = this._cache.length; + } + return this; + }; + + // abstract __iterateUncached(fn, reverse) + + Seq.prototype.__iterate = function(fn, reverse) { + return seqIterate(this, fn, reverse, true); + }; + + // abstract __iteratorUncached(type, reverse) + + Seq.prototype.__iterator = function(type, reverse) { + return seqIterator(this, type, reverse, true); + }; + + + + createClass(KeyedSeq, Seq); + function KeyedSeq(value) { + return value === null || value === undefined ? + emptySequence().toKeyedSeq() : + isIterable(value) ? + (isKeyed(value) ? value.toSeq() : value.fromEntrySeq()) : + keyedSeqFromValue(value); + } + + KeyedSeq.prototype.toKeyedSeq = function() { + return this; + }; + + + + createClass(IndexedSeq, Seq); + function IndexedSeq(value) { + return value === null || value === undefined ? emptySequence() : + !isIterable(value) ? indexedSeqFromValue(value) : + isKeyed(value) ? value.entrySeq() : value.toIndexedSeq(); + } + + IndexedSeq.of = function(/*...values*/) { + return IndexedSeq(arguments); + }; + + IndexedSeq.prototype.toIndexedSeq = function() { + return this; + }; + + IndexedSeq.prototype.toString = function() { + return this.__toString('Seq [', ']'); + }; + + IndexedSeq.prototype.__iterate = function(fn, reverse) { + return seqIterate(this, fn, reverse, false); + }; + + IndexedSeq.prototype.__iterator = function(type, reverse) { + return seqIterator(this, type, reverse, false); + }; + + + + createClass(SetSeq, Seq); + function SetSeq(value) { + return ( + value === null || value === undefined ? emptySequence() : + !isIterable(value) ? indexedSeqFromValue(value) : + isKeyed(value) ? value.entrySeq() : value + ).toSetSeq(); + } + + SetSeq.of = function(/*...values*/) { + return SetSeq(arguments); + }; + + SetSeq.prototype.toSetSeq = function() { + return this; + }; + + + + Seq.isSeq = isSeq; + Seq.Keyed = KeyedSeq; + Seq.Set = SetSeq; + Seq.Indexed = IndexedSeq; + + var IS_SEQ_SENTINEL = '@@__IMMUTABLE_SEQ__@@'; + + Seq.prototype[IS_SEQ_SENTINEL] = true; + + + + // #pragma Root Sequences + + createClass(ArraySeq, IndexedSeq); + function ArraySeq(array) { + this._array = array; + this.size = array.length; + } + + ArraySeq.prototype.get = function(index, notSetValue) { + return this.has(index) ? this._array[wrapIndex(this, index)] : notSetValue; + }; + + ArraySeq.prototype.__iterate = function(fn, reverse) { + var array = this._array; + var maxIndex = array.length - 1; + for (var ii = 0; ii <= maxIndex; ii++) { + if (fn(array[reverse ? maxIndex - ii : ii], ii, this) === false) { + return ii + 1; + } + } + return ii; + }; + + ArraySeq.prototype.__iterator = function(type, reverse) { + var array = this._array; + var maxIndex = array.length - 1; + var ii = 0; + return new Iterator(function() + {return ii > maxIndex ? + iteratorDone() : + iteratorValue(type, ii, array[reverse ? maxIndex - ii++ : ii++])} + ); + }; + + + + createClass(ObjectSeq, KeyedSeq); + function ObjectSeq(object) { + var keys = Object.keys(object); + this._object = object; + this._keys = keys; + this.size = keys.length; + } + + ObjectSeq.prototype.get = function(key, notSetValue) { + if (notSetValue !== undefined && !this.has(key)) { + return notSetValue; + } + return this._object[key]; + }; + + ObjectSeq.prototype.has = function(key) { + return this._object.hasOwnProperty(key); + }; + + ObjectSeq.prototype.__iterate = function(fn, reverse) { + var object = this._object; + var keys = this._keys; + var maxIndex = keys.length - 1; + for (var ii = 0; ii <= maxIndex; ii++) { + var key = keys[reverse ? maxIndex - ii : ii]; + if (fn(object[key], key, this) === false) { + return ii + 1; + } + } + return ii; + }; + + ObjectSeq.prototype.__iterator = function(type, reverse) { + var object = this._object; + var keys = this._keys; + var maxIndex = keys.length - 1; + var ii = 0; + return new Iterator(function() { + var key = keys[reverse ? maxIndex - ii : ii]; + return ii++ > maxIndex ? + iteratorDone() : + iteratorValue(type, key, object[key]); + }); + }; + + ObjectSeq.prototype[IS_ORDERED_SENTINEL] = true; + + + createClass(IterableSeq, IndexedSeq); + function IterableSeq(iterable) { + this._iterable = iterable; + this.size = iterable.length || iterable.size; + } + + IterableSeq.prototype.__iterateUncached = function(fn, reverse) { + if (reverse) { + return this.cacheResult().__iterate(fn, reverse); + } + var iterable = this._iterable; + var iterator = getIterator(iterable); + var iterations = 0; + if (isIterator(iterator)) { + var step; + while (!(step = iterator.next()).done) { + if (fn(step.value, iterations++, this) === false) { + break; + } + } + } + return iterations; + }; + + IterableSeq.prototype.__iteratorUncached = function(type, reverse) { + if (reverse) { + return this.cacheResult().__iterator(type, reverse); + } + var iterable = this._iterable; + var iterator = getIterator(iterable); + if (!isIterator(iterator)) { + return new Iterator(iteratorDone); + } + var iterations = 0; + return new Iterator(function() { + var step = iterator.next(); + return step.done ? step : iteratorValue(type, iterations++, step.value); + }); + }; + + + + createClass(IteratorSeq, IndexedSeq); + function IteratorSeq(iterator) { + this._iterator = iterator; + this._iteratorCache = []; + } + + IteratorSeq.prototype.__iterateUncached = function(fn, reverse) { + if (reverse) { + return this.cacheResult().__iterate(fn, reverse); + } + var iterator = this._iterator; + var cache = this._iteratorCache; + var iterations = 0; + while (iterations < cache.length) { + if (fn(cache[iterations], iterations++, this) === false) { + return iterations; + } + } + var step; + while (!(step = iterator.next()).done) { + var val = step.value; + cache[iterations] = val; + if (fn(val, iterations++, this) === false) { + break; + } + } + return iterations; + }; + + IteratorSeq.prototype.__iteratorUncached = function(type, reverse) { + if (reverse) { + return this.cacheResult().__iterator(type, reverse); + } + var iterator = this._iterator; + var cache = this._iteratorCache; + var iterations = 0; + return new Iterator(function() { + if (iterations >= cache.length) { + var step = iterator.next(); + if (step.done) { + return step; + } + cache[iterations] = step.value; + } + return iteratorValue(type, iterations, cache[iterations++]); + }); + }; + + + + + // # pragma Helper functions + + function isSeq(maybeSeq) { + return !!(maybeSeq && maybeSeq[IS_SEQ_SENTINEL]); + } + + var EMPTY_SEQ; + + function emptySequence() { + return EMPTY_SEQ || (EMPTY_SEQ = new ArraySeq([])); + } + + function keyedSeqFromValue(value) { + var seq = + Array.isArray(value) ? new ArraySeq(value).fromEntrySeq() : + isIterator(value) ? new IteratorSeq(value).fromEntrySeq() : + hasIterator(value) ? new IterableSeq(value).fromEntrySeq() : + typeof value === 'object' ? new ObjectSeq(value) : + undefined; + if (!seq) { + throw new TypeError( + 'Expected Array or iterable object of [k, v] entries, '+ + 'or keyed object: ' + value + ); + } + return seq; + } + + function indexedSeqFromValue(value) { + var seq = maybeIndexedSeqFromValue(value); + if (!seq) { + throw new TypeError( + 'Expected Array or iterable object of values: ' + value + ); + } + return seq; + } + + function seqFromValue(value) { + var seq = maybeIndexedSeqFromValue(value) || + (typeof value === 'object' && new ObjectSeq(value)); + if (!seq) { + throw new TypeError( + 'Expected Array or iterable object of values, or keyed object: ' + value + ); + } + return seq; + } + + function maybeIndexedSeqFromValue(value) { + return ( + isArrayLike(value) ? new ArraySeq(value) : + isIterator(value) ? new IteratorSeq(value) : + hasIterator(value) ? new IterableSeq(value) : + undefined + ); + } + + function seqIterate(seq, fn, reverse, useKeys) { + var cache = seq._cache; + if (cache) { + var maxIndex = cache.length - 1; + for (var ii = 0; ii <= maxIndex; ii++) { + var entry = cache[reverse ? maxIndex - ii : ii]; + if (fn(entry[1], useKeys ? entry[0] : ii, seq) === false) { + return ii + 1; + } + } + return ii; + } + return seq.__iterateUncached(fn, reverse); + } + + function seqIterator(seq, type, reverse, useKeys) { + var cache = seq._cache; + if (cache) { + var maxIndex = cache.length - 1; + var ii = 0; + return new Iterator(function() { + var entry = cache[reverse ? maxIndex - ii : ii]; + return ii++ > maxIndex ? + iteratorDone() : + iteratorValue(type, useKeys ? entry[0] : ii - 1, entry[1]); + }); + } + return seq.__iteratorUncached(type, reverse); + } + + createClass(Collection, Iterable); + function Collection() { + throw TypeError('Abstract'); + } + + + createClass(KeyedCollection, Collection);function KeyedCollection() {} + + createClass(IndexedCollection, Collection);function IndexedCollection() {} + + createClass(SetCollection, Collection);function SetCollection() {} + + + Collection.Keyed = KeyedCollection; + Collection.Indexed = IndexedCollection; + Collection.Set = SetCollection; + + /** + * An extension of the "same-value" algorithm as [described for use by ES6 Map + * and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality) + * + * NaN is considered the same as NaN, however -0 and 0 are considered the same + * value, which is different from the algorithm described by + * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). + * + * This is extended further to allow Objects to describe the values they + * represent, by way of `valueOf` or `equals` (and `hashCode`). + * + * Note: because of this extension, the key equality of Immutable.Map and the + * value equality of Immutable.Set will differ from ES6 Map and Set. + * + * ### Defining custom values + * + * The easiest way to describe the value an object represents is by implementing + * `valueOf`. For example, `Date` represents a value by returning a unix + * timestamp for `valueOf`: + * + * var date1 = new Date(1234567890000); // Fri Feb 13 2009 ... + * var date2 = new Date(1234567890000); + * date1.valueOf(); // 1234567890000 + * assert( date1 !== date2 ); + * assert( Immutable.is( date1, date2 ) ); + * + * Note: overriding `valueOf` may have other implications if you use this object + * where JavaScript expects a primitive, such as implicit string coercion. + * + * For more complex types, especially collections, implementing `valueOf` may + * not be performant. An alternative is to implement `equals` and `hashCode`. + * + * `equals` takes another object, presumably of similar type, and returns true + * if the it is equal. Equality is symmetrical, so the same result should be + * returned if this and the argument are flipped. + * + * assert( a.equals(b) === b.equals(a) ); + * + * `hashCode` returns a 32bit integer number representing the object which will + * be used to determine how to store the value object in a Map or Set. You must + * provide both or neither methods, one must not exist without the other. + * + * Also, an important relationship between these methods must be upheld: if two + * values are equal, they *must* return the same hashCode. If the values are not + * equal, they might have the same hashCode; this is called a hash collision, + * and while undesirable for performance reasons, it is acceptable. + * + * if (a.equals(b)) { + * assert( a.hashCode() === b.hashCode() ); + * } + * + * All Immutable collections implement `equals` and `hashCode`. + * + */ + function is(valueA, valueB) { + if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) { + return true; + } + if (!valueA || !valueB) { + return false; + } + if (typeof valueA.valueOf === 'function' && + typeof valueB.valueOf === 'function') { + valueA = valueA.valueOf(); + valueB = valueB.valueOf(); + } + return typeof valueA.equals === 'function' && + typeof valueB.equals === 'function' ? + valueA.equals(valueB) : + valueA === valueB || (valueA !== valueA && valueB !== valueB); + } + + function fromJS(json, converter) { + return converter ? + fromJSWith(converter, json, '', {'': json}) : + fromJSDefault(json); + } + + function fromJSWith(converter, json, key, parentJSON) { + if (Array.isArray(json)) { + return converter.call(parentJSON, key, IndexedSeq(json).map(function(v, k) {return fromJSWith(converter, v, k, json)})); + } + if (isPlainObj(json)) { + return converter.call(parentJSON, key, KeyedSeq(json).map(function(v, k) {return fromJSWith(converter, v, k, json)})); + } + return json; + } + + function fromJSDefault(json) { + if (Array.isArray(json)) { + return IndexedSeq(json).map(fromJSDefault).toList(); + } + if (isPlainObj(json)) { + return KeyedSeq(json).map(fromJSDefault).toMap(); + } + return json; + } + + function isPlainObj(value) { + return value && (value.constructor === Object || value.constructor === undefined); + } + + var Math__imul = + typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2 ? + Math.imul : + function Math__imul(a, b) { + a = a | 0; // int + b = b | 0; // int + var c = a & 0xffff; + var d = b & 0xffff; + // Shift by 0 fixes the sign on the high part. + return (c * d) + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0) | 0; // int + }; + + // v8 has an optimization for storing 31-bit signed numbers. + // Values which have either 00 or 11 as the high order bits qualify. + // This function drops the highest order bit in a signed number, maintaining + // the sign bit. + function smi(i32) { + return ((i32 >>> 1) & 0x40000000) | (i32 & 0xBFFFFFFF); + } + + function hash(o) { + if (o === false || o === null || o === undefined) { + return 0; + } + if (typeof o.valueOf === 'function') { + o = o.valueOf(); + if (o === false || o === null || o === undefined) { + return 0; + } + } + if (o === true) { + return 1; + } + var type = typeof o; + if (type === 'number') { + var h = o | 0; + if (h !== o) { + h ^= o * 0xFFFFFFFF; + } + while (o > 0xFFFFFFFF) { + o /= 0xFFFFFFFF; + h ^= o; + } + return smi(h); + } + if (type === 'string') { + return o.length > STRING_HASH_CACHE_MIN_STRLEN ? cachedHashString(o) : hashString(o); + } + if (typeof o.hashCode === 'function') { + return o.hashCode(); + } + return hashJSObj(o); + } + + function cachedHashString(string) { + var hash = stringHashCache[string]; + if (hash === undefined) { + hash = hashString(string); + if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) { + STRING_HASH_CACHE_SIZE = 0; + stringHashCache = {}; + } + STRING_HASH_CACHE_SIZE++; + stringHashCache[string] = hash; + } + return hash; + } + + // http://jsperf.com/hashing-strings + function hashString(string) { + // This is the hash from JVM + // The hash code for a string is computed as + // s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1], + // where s[i] is the ith character of the string and n is the length of + // the string. We "mod" the result to make it between 0 (inclusive) and 2^31 + // (exclusive) by dropping high bits. + var hash = 0; + for (var ii = 0; ii < string.length; ii++) { + hash = 31 * hash + string.charCodeAt(ii) | 0; + } + return smi(hash); + } + + function hashJSObj(obj) { + var hash = weakMap && weakMap.get(obj); + if (hash) return hash; + + hash = obj[UID_HASH_KEY]; + if (hash) return hash; + + if (!canDefineProperty) { + hash = obj.propertyIsEnumerable && obj.propertyIsEnumerable[UID_HASH_KEY]; + if (hash) return hash; + + hash = getIENodeHash(obj); + if (hash) return hash; + } + + if (Object.isExtensible && !Object.isExtensible(obj)) { + throw new Error('Non-extensible objects are not allowed as keys.'); + } + + hash = ++objHashUID; + if (objHashUID & 0x40000000) { + objHashUID = 0; + } + + if (weakMap) { + weakMap.set(obj, hash); + } else if (canDefineProperty) { + Object.defineProperty(obj, UID_HASH_KEY, { + 'enumerable': false, + 'configurable': false, + 'writable': false, + 'value': hash + }); + } else if (obj.propertyIsEnumerable && + obj.propertyIsEnumerable === obj.constructor.prototype.propertyIsEnumerable) { + // Since we can't define a non-enumerable property on the object + // we'll hijack one of the less-used non-enumerable properties to + // save our hash on it. Since this is a function it will not show up in + // `JSON.stringify` which is what we want. + obj.propertyIsEnumerable = function() { + return this.constructor.prototype.propertyIsEnumerable.apply(this, arguments); + }; + obj.propertyIsEnumerable[UID_HASH_KEY] = hash; + } else if (obj.nodeType) { + // At this point we couldn't get the IE `uniqueID` to use as a hash + // and we couldn't use a non-enumerable property to exploit the + // dontEnum bug so we simply add the `UID_HASH_KEY` on the node + // itself. + obj[UID_HASH_KEY] = hash; + } else { + throw new Error('Unable to set a non-enumerable property on object.'); + } + + return hash; + } + + // True if Object.defineProperty works as expected. IE8 fails this test. + var canDefineProperty = (function() { + try { + Object.defineProperty({}, '@', {}); + return true; + } catch (e) { + return false; + } + }()); + + // IE has a `uniqueID` property on DOM nodes. We can construct the hash from it + // and avoid memory leaks from the IE cloneNode bug. + function getIENodeHash(node) { + if (node && node.nodeType > 0) { + switch (node.nodeType) { + case 1: // Element + return node.uniqueID; + case 9: // Document + return node.documentElement && node.documentElement.uniqueID; + } + } + } + + // If possible, use a WeakMap. + var weakMap = typeof WeakMap === 'function' && new WeakMap(); + + var objHashUID = 0; + + var UID_HASH_KEY = '__immutablehash__'; + if (typeof Symbol === 'function') { + UID_HASH_KEY = Symbol(UID_HASH_KEY); + } + + var STRING_HASH_CACHE_MIN_STRLEN = 16; + var STRING_HASH_CACHE_MAX_SIZE = 255; + var STRING_HASH_CACHE_SIZE = 0; + var stringHashCache = {}; + + function invariant(condition, error) { + if (!condition) throw new Error(error); + } + + function assertNotInfinite(size) { + invariant( + size !== Infinity, + 'Cannot perform this action with an infinite size.' + ); + } + + createClass(ToKeyedSequence, KeyedSeq); + function ToKeyedSequence(indexed, useKeys) { + this._iter = indexed; + this._useKeys = useKeys; + this.size = indexed.size; + } + + ToKeyedSequence.prototype.get = function(key, notSetValue) { + return this._iter.get(key, notSetValue); + }; + + ToKeyedSequence.prototype.has = function(key) { + return this._iter.has(key); + }; + + ToKeyedSequence.prototype.valueSeq = function() { + return this._iter.valueSeq(); + }; + + ToKeyedSequence.prototype.reverse = function() {var this$0 = this; + var reversedSequence = reverseFactory(this, true); + if (!this._useKeys) { + reversedSequence.valueSeq = function() {return this$0._iter.toSeq().reverse()}; + } + return reversedSequence; + }; + + ToKeyedSequence.prototype.map = function(mapper, context) {var this$0 = this; + var mappedSequence = mapFactory(this, mapper, context); + if (!this._useKeys) { + mappedSequence.valueSeq = function() {return this$0._iter.toSeq().map(mapper, context)}; + } + return mappedSequence; + }; + + ToKeyedSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this; + var ii; + return this._iter.__iterate( + this._useKeys ? + function(v, k) {return fn(v, k, this$0)} : + ((ii = reverse ? resolveSize(this) : 0), + function(v ) {return fn(v, reverse ? --ii : ii++, this$0)}), + reverse + ); + }; + + ToKeyedSequence.prototype.__iterator = function(type, reverse) { + if (this._useKeys) { + return this._iter.__iterator(type, reverse); + } + var iterator = this._iter.__iterator(ITERATE_VALUES, reverse); + var ii = reverse ? resolveSize(this) : 0; + return new Iterator(function() { + var step = iterator.next(); + return step.done ? step : + iteratorValue(type, reverse ? --ii : ii++, step.value, step); + }); + }; + + ToKeyedSequence.prototype[IS_ORDERED_SENTINEL] = true; + + + createClass(ToIndexedSequence, IndexedSeq); + function ToIndexedSequence(iter) { + this._iter = iter; + this.size = iter.size; + } + + ToIndexedSequence.prototype.contains = function(value) { + return this._iter.contains(value); + }; + + ToIndexedSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this; + var iterations = 0; + return this._iter.__iterate(function(v ) {return fn(v, iterations++, this$0)}, reverse); + }; + + ToIndexedSequence.prototype.__iterator = function(type, reverse) { + var iterator = this._iter.__iterator(ITERATE_VALUES, reverse); + var iterations = 0; + return new Iterator(function() { + var step = iterator.next(); + return step.done ? step : + iteratorValue(type, iterations++, step.value, step) + }); + }; + + + + createClass(ToSetSequence, SetSeq); + function ToSetSequence(iter) { + this._iter = iter; + this.size = iter.size; + } + + ToSetSequence.prototype.has = function(key) { + return this._iter.contains(key); + }; + + ToSetSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this; + return this._iter.__iterate(function(v ) {return fn(v, v, this$0)}, reverse); + }; + + ToSetSequence.prototype.__iterator = function(type, reverse) { + var iterator = this._iter.__iterator(ITERATE_VALUES, reverse); + return new Iterator(function() { + var step = iterator.next(); + return step.done ? step : + iteratorValue(type, step.value, step.value, step); + }); + }; + + + + createClass(FromEntriesSequence, KeyedSeq); + function FromEntriesSequence(entries) { + this._iter = entries; + this.size = entries.size; + } + + FromEntriesSequence.prototype.entrySeq = function() { + return this._iter.toSeq(); + }; + + FromEntriesSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this; + return this._iter.__iterate(function(entry ) { + // Check if entry exists first so array access doesn't throw for holes + // in the parent iteration. + if (entry) { + validateEntry(entry); + return fn(entry[1], entry[0], this$0); + } + }, reverse); + }; + + FromEntriesSequence.prototype.__iterator = function(type, reverse) { + var iterator = this._iter.__iterator(ITERATE_VALUES, reverse); + return new Iterator(function() { + while (true) { + var step = iterator.next(); + if (step.done) { + return step; + } + var entry = step.value; + // Check if entry exists first so array access doesn't throw for holes + // in the parent iteration. + if (entry) { + validateEntry(entry); + return type === ITERATE_ENTRIES ? step : + iteratorValue(type, entry[0], entry[1], step); + } + } + }); + }; + + + ToIndexedSequence.prototype.cacheResult = + ToKeyedSequence.prototype.cacheResult = + ToSetSequence.prototype.cacheResult = + FromEntriesSequence.prototype.cacheResult = + cacheResultThrough; + + + function flipFactory(iterable) { + var flipSequence = makeSequence(iterable); + flipSequence._iter = iterable; + flipSequence.size = iterable.size; + flipSequence.flip = function() {return iterable}; + flipSequence.reverse = function () { + var reversedSequence = iterable.reverse.apply(this); // super.reverse() + reversedSequence.flip = function() {return iterable.reverse()}; + return reversedSequence; + }; + flipSequence.has = function(key ) {return iterable.contains(key)}; + flipSequence.contains = function(key ) {return iterable.has(key)}; + flipSequence.cacheResult = cacheResultThrough; + flipSequence.__iterateUncached = function (fn, reverse) {var this$0 = this; + return iterable.__iterate(function(v, k) {return fn(k, v, this$0) !== false}, reverse); + } + flipSequence.__iteratorUncached = function(type, reverse) { + if (type === ITERATE_ENTRIES) { + var iterator = iterable.__iterator(type, reverse); + return new Iterator(function() { + var step = iterator.next(); + if (!step.done) { + var k = step.value[0]; + step.value[0] = step.value[1]; + step.value[1] = k; + } + return step; + }); + } + return iterable.__iterator( + type === ITERATE_VALUES ? ITERATE_KEYS : ITERATE_VALUES, + reverse + ); + } + return flipSequence; + } + + + function mapFactory(iterable, mapper, context) { + var mappedSequence = makeSequence(iterable); + mappedSequence.size = iterable.size; + mappedSequence.has = function(key ) {return iterable.has(key)}; + mappedSequence.get = function(key, notSetValue) { + var v = iterable.get(key, NOT_SET); + return v === NOT_SET ? + notSetValue : + mapper.call(context, v, key, iterable); + }; + mappedSequence.__iterateUncached = function (fn, reverse) {var this$0 = this; + return iterable.__iterate( + function(v, k, c) {return fn(mapper.call(context, v, k, c), k, this$0) !== false}, + reverse + ); + } + mappedSequence.__iteratorUncached = function (type, reverse) { + var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse); + return new Iterator(function() { + var step = iterator.next(); + if (step.done) { + return step; + } + var entry = step.value; + var key = entry[0]; + return iteratorValue( + type, + key, + mapper.call(context, entry[1], key, iterable), + step + ); + }); + } + return mappedSequence; + } + + + function reverseFactory(iterable, useKeys) { + var reversedSequence = makeSequence(iterable); + reversedSequence._iter = iterable; + reversedSequence.size = iterable.size; + reversedSequence.reverse = function() {return iterable}; + if (iterable.flip) { + reversedSequence.flip = function () { + var flipSequence = flipFactory(iterable); + flipSequence.reverse = function() {return iterable.flip()}; + return flipSequence; + }; + } + reversedSequence.get = function(key, notSetValue) + {return iterable.get(useKeys ? key : -1 - key, notSetValue)}; + reversedSequence.has = function(key ) + {return iterable.has(useKeys ? key : -1 - key)}; + reversedSequence.contains = function(value ) {return iterable.contains(value)}; + reversedSequence.cacheResult = cacheResultThrough; + reversedSequence.__iterate = function (fn, reverse) {var this$0 = this; + return iterable.__iterate(function(v, k) {return fn(v, k, this$0)}, !reverse); + }; + reversedSequence.__iterator = + function(type, reverse) {return iterable.__iterator(type, !reverse)}; + return reversedSequence; + } + + + function filterFactory(iterable, predicate, context, useKeys) { + var filterSequence = makeSequence(iterable); + if (useKeys) { + filterSequence.has = function(key ) { + var v = iterable.get(key, NOT_SET); + return v !== NOT_SET && !!predicate.call(context, v, key, iterable); + }; + filterSequence.get = function(key, notSetValue) { + var v = iterable.get(key, NOT_SET); + return v !== NOT_SET && predicate.call(context, v, key, iterable) ? + v : notSetValue; + }; + } + filterSequence.__iterateUncached = function (fn, reverse) {var this$0 = this; + var iterations = 0; + iterable.__iterate(function(v, k, c) { + if (predicate.call(context, v, k, c)) { + iterations++; + return fn(v, useKeys ? k : iterations - 1, this$0); + } + }, reverse); + return iterations; + }; + filterSequence.__iteratorUncached = function (type, reverse) { + var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse); + var iterations = 0; + return new Iterator(function() { + while (true) { + var step = iterator.next(); + if (step.done) { + return step; + } + var entry = step.value; + var key = entry[0]; + var value = entry[1]; + if (predicate.call(context, value, key, iterable)) { + return iteratorValue(type, useKeys ? key : iterations++, value, step); + } + } + }); + } + return filterSequence; + } + + + function countByFactory(iterable, grouper, context) { + var groups = Map().asMutable(); + iterable.__iterate(function(v, k) { + groups.update( + grouper.call(context, v, k, iterable), + 0, + function(a ) {return a + 1} + ); + }); + return groups.asImmutable(); + } + + + function groupByFactory(iterable, grouper, context) { + var isKeyedIter = isKeyed(iterable); + var groups = (isOrdered(iterable) ? OrderedMap() : Map()).asMutable(); + iterable.__iterate(function(v, k) { + groups.update( + grouper.call(context, v, k, iterable), + function(a ) {return (a = a || [], a.push(isKeyedIter ? [k, v] : v), a)} + ); + }); + var coerce = iterableClass(iterable); + return groups.map(function(arr ) {return reify(iterable, coerce(arr))}); + } + + + function sliceFactory(iterable, begin, end, useKeys) { + var originalSize = iterable.size; + + if (wholeSlice(begin, end, originalSize)) { + return iterable; + } + + var resolvedBegin = resolveBegin(begin, originalSize); + var resolvedEnd = resolveEnd(end, originalSize); + + // begin or end will be NaN if they were provided as negative numbers and + // this iterable's size is unknown. In that case, cache first so there is + // a known size. + if (resolvedBegin !== resolvedBegin || resolvedEnd !== resolvedEnd) { + return sliceFactory(iterable.toSeq().cacheResult(), begin, end, useKeys); + } + + var sliceSize = resolvedEnd - resolvedBegin; + if (sliceSize < 0) { + sliceSize = 0; + } + + var sliceSeq = makeSequence(iterable); + + sliceSeq.size = sliceSize === 0 ? sliceSize : iterable.size && sliceSize || undefined; + + if (!useKeys && isSeq(iterable) && sliceSize >= 0) { + sliceSeq.get = function (index, notSetValue) { + index = wrapIndex(this, index); + return index >= 0 && index < sliceSize ? + iterable.get(index + resolvedBegin, notSetValue) : + notSetValue; + } + } + + sliceSeq.__iterateUncached = function(fn, reverse) {var this$0 = this; + if (sliceSize === 0) { + return 0; + } + if (reverse) { + return this.cacheResult().__iterate(fn, reverse); + } + var skipped = 0; + var isSkipping = true; + var iterations = 0; + iterable.__iterate(function(v, k) { + if (!(isSkipping && (isSkipping = skipped++ < resolvedBegin))) { + iterations++; + return fn(v, useKeys ? k : iterations - 1, this$0) !== false && + iterations !== sliceSize; + } + }); + return iterations; + }; + + sliceSeq.__iteratorUncached = function(type, reverse) { + if (sliceSize && reverse) { + return this.cacheResult().__iterator(type, reverse); + } + // Don't bother instantiating parent iterator if taking 0. + var iterator = sliceSize && iterable.__iterator(type, reverse); + var skipped = 0; + var iterations = 0; + return new Iterator(function() { + while (skipped++ !== resolvedBegin) { + iterator.next(); + } + if (++iterations > sliceSize) { + return iteratorDone(); + } + var step = iterator.next(); + if (useKeys || type === ITERATE_VALUES) { + return step; + } else if (type === ITERATE_KEYS) { + return iteratorValue(type, iterations - 1, undefined, step); + } else { + return iteratorValue(type, iterations - 1, step.value[1], step); + } + }); + } + + return sliceSeq; + } + + + function takeWhileFactory(iterable, predicate, context) { + var takeSequence = makeSequence(iterable); + takeSequence.__iterateUncached = function(fn, reverse) {var this$0 = this; + if (reverse) { + return this.cacheResult().__iterate(fn, reverse); + } + var iterations = 0; + iterable.__iterate(function(v, k, c) + {return predicate.call(context, v, k, c) && ++iterations && fn(v, k, this$0)} + ); + return iterations; + }; + takeSequence.__iteratorUncached = function(type, reverse) {var this$0 = this; + if (reverse) { + return this.cacheResult().__iterator(type, reverse); + } + var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse); + var iterating = true; + return new Iterator(function() { + if (!iterating) { + return iteratorDone(); + } + var step = iterator.next(); + if (step.done) { + return step; + } + var entry = step.value; + var k = entry[0]; + var v = entry[1]; + if (!predicate.call(context, v, k, this$0)) { + iterating = false; + return iteratorDone(); + } + return type === ITERATE_ENTRIES ? step : + iteratorValue(type, k, v, step); + }); + }; + return takeSequence; + } + + + function skipWhileFactory(iterable, predicate, context, useKeys) { + var skipSequence = makeSequence(iterable); + skipSequence.__iterateUncached = function (fn, reverse) {var this$0 = this; + if (reverse) { + return this.cacheResult().__iterate(fn, reverse); + } + var isSkipping = true; + var iterations = 0; + iterable.__iterate(function(v, k, c) { + if (!(isSkipping && (isSkipping = predicate.call(context, v, k, c)))) { + iterations++; + return fn(v, useKeys ? k : iterations - 1, this$0); + } + }); + return iterations; + }; + skipSequence.__iteratorUncached = function(type, reverse) {var this$0 = this; + if (reverse) { + return this.cacheResult().__iterator(type, reverse); + } + var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse); + var skipping = true; + var iterations = 0; + return new Iterator(function() { + var step, k, v; + do { + step = iterator.next(); + if (step.done) { + if (useKeys || type === ITERATE_VALUES) { + return step; + } else if (type === ITERATE_KEYS) { + return iteratorValue(type, iterations++, undefined, step); + } else { + return iteratorValue(type, iterations++, step.value[1], step); + } + } + var entry = step.value; + k = entry[0]; + v = entry[1]; + skipping && (skipping = predicate.call(context, v, k, this$0)); + } while (skipping); + return type === ITERATE_ENTRIES ? step : + iteratorValue(type, k, v, step); + }); + }; + return skipSequence; + } + + + function concatFactory(iterable, values) { + var isKeyedIterable = isKeyed(iterable); + var iters = [iterable].concat(values).map(function(v ) { + if (!isIterable(v)) { + v = isKeyedIterable ? + keyedSeqFromValue(v) : + indexedSeqFromValue(Array.isArray(v) ? v : [v]); + } else if (isKeyedIterable) { + v = KeyedIterable(v); + } + return v; + }).filter(function(v ) {return v.size !== 0}); + + if (iters.length === 0) { + return iterable; + } + + if (iters.length === 1) { + var singleton = iters[0]; + if (singleton === iterable || + isKeyedIterable && isKeyed(singleton) || + isIndexed(iterable) && isIndexed(singleton)) { + return singleton; + } + } + + var concatSeq = new ArraySeq(iters); + if (isKeyedIterable) { + concatSeq = concatSeq.toKeyedSeq(); + } else if (!isIndexed(iterable)) { + concatSeq = concatSeq.toSetSeq(); + } + concatSeq = concatSeq.flatten(true); + concatSeq.size = iters.reduce( + function(sum, seq) { + if (sum !== undefined) { + var size = seq.size; + if (size !== undefined) { + return sum + size; + } + } + }, + 0 + ); + return concatSeq; + } + + + function flattenFactory(iterable, depth, useKeys) { + var flatSequence = makeSequence(iterable); + flatSequence.__iterateUncached = function(fn, reverse) { + var iterations = 0; + var stopped = false; + function flatDeep(iter, currentDepth) {var this$0 = this; + iter.__iterate(function(v, k) { + if ((!depth || currentDepth < depth) && isIterable(v)) { + flatDeep(v, currentDepth + 1); + } else if (fn(v, useKeys ? k : iterations++, this$0) === false) { + stopped = true; + } + return !stopped; + }, reverse); + } + flatDeep(iterable, 0); + return iterations; + } + flatSequence.__iteratorUncached = function(type, reverse) { + var iterator = iterable.__iterator(type, reverse); + var stack = []; + var iterations = 0; + return new Iterator(function() { + while (iterator) { + var step = iterator.next(); + if (step.done !== false) { + iterator = stack.pop(); + continue; + } + var v = step.value; + if (type === ITERATE_ENTRIES) { + v = v[1]; + } + if ((!depth || stack.length < depth) && isIterable(v)) { + stack.push(iterator); + iterator = v.__iterator(type, reverse); + } else { + return useKeys ? step : iteratorValue(type, iterations++, v, step); + } + } + return iteratorDone(); + }); + } + return flatSequence; + } + + + function flatMapFactory(iterable, mapper, context) { + var coerce = iterableClass(iterable); + return iterable.toSeq().map( + function(v, k) {return coerce(mapper.call(context, v, k, iterable))} + ).flatten(true); + } + + + function interposeFactory(iterable, separator) { + var interposedSequence = makeSequence(iterable); + interposedSequence.size = iterable.size && iterable.size * 2 -1; + interposedSequence.__iterateUncached = function(fn, reverse) {var this$0 = this; + var iterations = 0; + iterable.__iterate(function(v, k) + {return (!iterations || fn(separator, iterations++, this$0) !== false) && + fn(v, iterations++, this$0) !== false}, + reverse + ); + return iterations; + }; + interposedSequence.__iteratorUncached = function(type, reverse) { + var iterator = iterable.__iterator(ITERATE_VALUES, reverse); + var iterations = 0; + var step; + return new Iterator(function() { + if (!step || iterations % 2) { + step = iterator.next(); + if (step.done) { + return step; + } + } + return iterations % 2 ? + iteratorValue(type, iterations++, separator) : + iteratorValue(type, iterations++, step.value, step); + }); + }; + return interposedSequence; + } + + + function sortFactory(iterable, comparator, mapper) { + if (!comparator) { + comparator = defaultComparator; + } + var isKeyedIterable = isKeyed(iterable); + var index = 0; + var entries = iterable.toSeq().map( + function(v, k) {return [k, v, index++, mapper ? mapper(v, k, iterable) : v]} + ).toArray(); + entries.sort(function(a, b) {return comparator(a[3], b[3]) || a[2] - b[2]}).forEach( + isKeyedIterable ? + function(v, i) { entries[i].length = 2; } : + function(v, i) { entries[i] = v[1]; } + ); + return isKeyedIterable ? KeyedSeq(entries) : + isIndexed(iterable) ? IndexedSeq(entries) : + SetSeq(entries); + } + + + function maxFactory(iterable, comparator, mapper) { + if (!comparator) { + comparator = defaultComparator; + } + if (mapper) { + var entry = iterable.toSeq() + .map(function(v, k) {return [v, mapper(v, k, iterable)]}) + .reduce(function(a, b) {return maxCompare(comparator, a[1], b[1]) ? b : a}); + return entry && entry[0]; + } else { + return iterable.reduce(function(a, b) {return maxCompare(comparator, a, b) ? b : a}); + } + } + + function maxCompare(comparator, a, b) { + var comp = comparator(b, a); + // b is considered the new max if the comparator declares them equal, but + // they are not equal and b is in fact a nullish value. + return (comp === 0 && b !== a && (b === undefined || b === null || b !== b)) || comp > 0; + } + + + function zipWithFactory(keyIter, zipper, iters) { + var zipSequence = makeSequence(keyIter); + zipSequence.size = new ArraySeq(iters).map(function(i ) {return i.size}).min(); + // Note: this a generic base implementation of __iterate in terms of + // __iterator which may be more generically useful in the future. + zipSequence.__iterate = function(fn, reverse) { + /* generic: + var iterator = this.__iterator(ITERATE_ENTRIES, reverse); + var step; + var iterations = 0; + while (!(step = iterator.next()).done) { + iterations++; + if (fn(step.value[1], step.value[0], this) === false) { + break; + } + } + return iterations; + */ + // indexed: + var iterator = this.__iterator(ITERATE_VALUES, reverse); + var step; + var iterations = 0; + while (!(step = iterator.next()).done) { + if (fn(step.value, iterations++, this) === false) { + break; + } + } + return iterations; + }; + zipSequence.__iteratorUncached = function(type, reverse) { + var iterators = iters.map(function(i ) + {return (i = Iterable(i), getIterator(reverse ? i.reverse() : i))} + ); + var iterations = 0; + var isDone = false; + return new Iterator(function() { + var steps; + if (!isDone) { + steps = iterators.map(function(i ) {return i.next()}); + isDone = steps.some(function(s ) {return s.done}); + } + if (isDone) { + return iteratorDone(); + } + return iteratorValue( + type, + iterations++, + zipper.apply(null, steps.map(function(s ) {return s.value})) + ); + }); + }; + return zipSequence + } + + + // #pragma Helper Functions + + function reify(iter, seq) { + return isSeq(iter) ? seq : iter.constructor(seq); + } + + function validateEntry(entry) { + if (entry !== Object(entry)) { + throw new TypeError('Expected [K, V] tuple: ' + entry); + } + } + + function resolveSize(iter) { + assertNotInfinite(iter.size); + return ensureSize(iter); + } + + function iterableClass(iterable) { + return isKeyed(iterable) ? KeyedIterable : + isIndexed(iterable) ? IndexedIterable : + SetIterable; + } + + function makeSequence(iterable) { + return Object.create( + ( + isKeyed(iterable) ? KeyedSeq : + isIndexed(iterable) ? IndexedSeq : + SetSeq + ).prototype + ); + } + + function cacheResultThrough() { + if (this._iter.cacheResult) { + this._iter.cacheResult(); + this.size = this._iter.size; + return this; + } else { + return Seq.prototype.cacheResult.call(this); + } + } + + function defaultComparator(a, b) { + return a > b ? 1 : a < b ? -1 : 0; + } + + function forceIterator(keyPath) { + var iter = getIterator(keyPath); + if (!iter) { + // Array might not be iterable in this environment, so we need a fallback + // to our wrapped type. + if (!isArrayLike(keyPath)) { + throw new TypeError('Expected iterable or array-like: ' + keyPath); + } + iter = getIterator(Iterable(keyPath)); + } + return iter; + } + + createClass(Map, KeyedCollection); + + // @pragma Construction + + function Map(value) { + return value === null || value === undefined ? emptyMap() : + isMap(value) ? value : + emptyMap().withMutations(function(map ) { + var iter = KeyedIterable(value); + assertNotInfinite(iter.size); + iter.forEach(function(v, k) {return map.set(k, v)}); + }); + } + + Map.prototype.toString = function() { + return this.__toString('Map {', '}'); + }; + + // @pragma Access + + Map.prototype.get = function(k, notSetValue) { + return this._root ? + this._root.get(0, undefined, k, notSetValue) : + notSetValue; + }; + + // @pragma Modification + + Map.prototype.set = function(k, v) { + return updateMap(this, k, v); + }; + + Map.prototype.setIn = function(keyPath, v) { + return this.updateIn(keyPath, NOT_SET, function() {return v}); + }; + + Map.prototype.remove = function(k) { + return updateMap(this, k, NOT_SET); + }; + + Map.prototype.deleteIn = function(keyPath) { + return this.updateIn(keyPath, function() {return NOT_SET}); + }; + + Map.prototype.update = function(k, notSetValue, updater) { + return arguments.length === 1 ? + k(this) : + this.updateIn([k], notSetValue, updater); + }; + + Map.prototype.updateIn = function(keyPath, notSetValue, updater) { + if (!updater) { + updater = notSetValue; + notSetValue = undefined; + } + var updatedValue = updateInDeepMap( + this, + forceIterator(keyPath), + notSetValue, + updater + ); + return updatedValue === NOT_SET ? undefined : updatedValue; + }; + + Map.prototype.clear = function() { + if (this.size === 0) { + return this; + } + if (this.__ownerID) { + this.size = 0; + this._root = null; + this.__hash = undefined; + this.__altered = true; + return this; + } + return emptyMap(); + }; + + // @pragma Composition + + Map.prototype.merge = function(/*...iters*/) { + return mergeIntoMapWith(this, undefined, arguments); + }; + + Map.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1); + return mergeIntoMapWith(this, merger, iters); + }; + + Map.prototype.mergeIn = function(keyPath) {var iters = SLICE$0.call(arguments, 1); + return this.updateIn(keyPath, emptyMap(), function(m ) {return m.merge.apply(m, iters)}); + }; + + Map.prototype.mergeDeep = function(/*...iters*/) { + return mergeIntoMapWith(this, deepMerger(undefined), arguments); + }; + + Map.prototype.mergeDeepWith = function(merger) {var iters = SLICE$0.call(arguments, 1); + return mergeIntoMapWith(this, deepMerger(merger), iters); + }; + + Map.prototype.mergeDeepIn = function(keyPath) {var iters = SLICE$0.call(arguments, 1); + return this.updateIn(keyPath, emptyMap(), function(m ) {return m.mergeDeep.apply(m, iters)}); + }; + + Map.prototype.sort = function(comparator) { + // Late binding + return OrderedMap(sortFactory(this, comparator)); + }; + + Map.prototype.sortBy = function(mapper, comparator) { + // Late binding + return OrderedMap(sortFactory(this, comparator, mapper)); + }; + + // @pragma Mutability + + Map.prototype.withMutations = function(fn) { + var mutable = this.asMutable(); + fn(mutable); + return mutable.wasAltered() ? mutable.__ensureOwner(this.__ownerID) : this; + }; + + Map.prototype.asMutable = function() { + return this.__ownerID ? this : this.__ensureOwner(new OwnerID()); + }; + + Map.prototype.asImmutable = function() { + return this.__ensureOwner(); + }; + + Map.prototype.wasAltered = function() { + return this.__altered; + }; + + Map.prototype.__iterator = function(type, reverse) { + return new MapIterator(this, type, reverse); + }; + + Map.prototype.__iterate = function(fn, reverse) {var this$0 = this; + var iterations = 0; + this._root && this._root.iterate(function(entry ) { + iterations++; + return fn(entry[1], entry[0], this$0); + }, reverse); + return iterations; + }; + + Map.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + if (!ownerID) { + this.__ownerID = ownerID; + this.__altered = false; + return this; + } + return makeMap(this.size, this._root, ownerID, this.__hash); + }; + + + function isMap(maybeMap) { + return !!(maybeMap && maybeMap[IS_MAP_SENTINEL]); + } + + Map.isMap = isMap; + + var IS_MAP_SENTINEL = '@@__IMMUTABLE_MAP__@@'; + + var MapPrototype = Map.prototype; + MapPrototype[IS_MAP_SENTINEL] = true; + MapPrototype[DELETE] = MapPrototype.remove; + MapPrototype.removeIn = MapPrototype.deleteIn; + + + // #pragma Trie Nodes + + + + function ArrayMapNode(ownerID, entries) { + this.ownerID = ownerID; + this.entries = entries; + } + + ArrayMapNode.prototype.get = function(shift, keyHash, key, notSetValue) { + var entries = this.entries; + for (var ii = 0, len = entries.length; ii < len; ii++) { + if (is(key, entries[ii][0])) { + return entries[ii][1]; + } + } + return notSetValue; + }; + + ArrayMapNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + var removed = value === NOT_SET; + + var entries = this.entries; + var idx = 0; + for (var len = entries.length; idx < len; idx++) { + if (is(key, entries[idx][0])) { + break; + } + } + var exists = idx < len; + + if (exists ? entries[idx][1] === value : removed) { + return this; + } + + SetRef(didAlter); + (removed || !exists) && SetRef(didChangeSize); + + if (removed && entries.length === 1) { + return; // undefined + } + + if (!exists && !removed && entries.length >= MAX_ARRAY_MAP_SIZE) { + return createNodes(ownerID, entries, key, value); + } + + var isEditable = ownerID && ownerID === this.ownerID; + var newEntries = isEditable ? entries : arrCopy(entries); + + if (exists) { + if (removed) { + idx === len - 1 ? newEntries.pop() : (newEntries[idx] = newEntries.pop()); + } else { + newEntries[idx] = [key, value]; + } + } else { + newEntries.push([key, value]); + } + + if (isEditable) { + this.entries = newEntries; + return this; + } + + return new ArrayMapNode(ownerID, newEntries); + }; + + + + + function BitmapIndexedNode(ownerID, bitmap, nodes) { + this.ownerID = ownerID; + this.bitmap = bitmap; + this.nodes = nodes; + } + + BitmapIndexedNode.prototype.get = function(shift, keyHash, key, notSetValue) { + if (keyHash === undefined) { + keyHash = hash(key); + } + var bit = (1 << ((shift === 0 ? keyHash : keyHash >>> shift) & MASK)); + var bitmap = this.bitmap; + return (bitmap & bit) === 0 ? notSetValue : + this.nodes[popCount(bitmap & (bit - 1))].get(shift + SHIFT, keyHash, key, notSetValue); + }; + + BitmapIndexedNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + if (keyHash === undefined) { + keyHash = hash(key); + } + var keyHashFrag = (shift === 0 ? keyHash : keyHash >>> shift) & MASK; + var bit = 1 << keyHashFrag; + var bitmap = this.bitmap; + var exists = (bitmap & bit) !== 0; + + if (!exists && value === NOT_SET) { + return this; + } + + var idx = popCount(bitmap & (bit - 1)); + var nodes = this.nodes; + var node = exists ? nodes[idx] : undefined; + var newNode = updateNode(node, ownerID, shift + SHIFT, keyHash, key, value, didChangeSize, didAlter); + + if (newNode === node) { + return this; + } + + if (!exists && newNode && nodes.length >= MAX_BITMAP_INDEXED_SIZE) { + return expandNodes(ownerID, nodes, bitmap, keyHashFrag, newNode); + } + + if (exists && !newNode && nodes.length === 2 && isLeafNode(nodes[idx ^ 1])) { + return nodes[idx ^ 1]; + } + + if (exists && newNode && nodes.length === 1 && isLeafNode(newNode)) { + return newNode; + } + + var isEditable = ownerID && ownerID === this.ownerID; + var newBitmap = exists ? newNode ? bitmap : bitmap ^ bit : bitmap | bit; + var newNodes = exists ? newNode ? + setIn(nodes, idx, newNode, isEditable) : + spliceOut(nodes, idx, isEditable) : + spliceIn(nodes, idx, newNode, isEditable); + + if (isEditable) { + this.bitmap = newBitmap; + this.nodes = newNodes; + return this; + } + + return new BitmapIndexedNode(ownerID, newBitmap, newNodes); + }; + + + + + function HashArrayMapNode(ownerID, count, nodes) { + this.ownerID = ownerID; + this.count = count; + this.nodes = nodes; + } + + HashArrayMapNode.prototype.get = function(shift, keyHash, key, notSetValue) { + if (keyHash === undefined) { + keyHash = hash(key); + } + var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK; + var node = this.nodes[idx]; + return node ? node.get(shift + SHIFT, keyHash, key, notSetValue) : notSetValue; + }; + + HashArrayMapNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + if (keyHash === undefined) { + keyHash = hash(key); + } + var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK; + var removed = value === NOT_SET; + var nodes = this.nodes; + var node = nodes[idx]; + + if (removed && !node) { + return this; + } + + var newNode = updateNode(node, ownerID, shift + SHIFT, keyHash, key, value, didChangeSize, didAlter); + if (newNode === node) { + return this; + } + + var newCount = this.count; + if (!node) { + newCount++; + } else if (!newNode) { + newCount--; + if (newCount < MIN_HASH_ARRAY_MAP_SIZE) { + return packNodes(ownerID, nodes, newCount, idx); + } + } + + var isEditable = ownerID && ownerID === this.ownerID; + var newNodes = setIn(nodes, idx, newNode, isEditable); + + if (isEditable) { + this.count = newCount; + this.nodes = newNodes; + return this; + } + + return new HashArrayMapNode(ownerID, newCount, newNodes); + }; + + + + + function HashCollisionNode(ownerID, keyHash, entries) { + this.ownerID = ownerID; + this.keyHash = keyHash; + this.entries = entries; + } + + HashCollisionNode.prototype.get = function(shift, keyHash, key, notSetValue) { + var entries = this.entries; + for (var ii = 0, len = entries.length; ii < len; ii++) { + if (is(key, entries[ii][0])) { + return entries[ii][1]; + } + } + return notSetValue; + }; + + HashCollisionNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + if (keyHash === undefined) { + keyHash = hash(key); + } + + var removed = value === NOT_SET; + + if (keyHash !== this.keyHash) { + if (removed) { + return this; + } + SetRef(didAlter); + SetRef(didChangeSize); + return mergeIntoNode(this, ownerID, shift, keyHash, [key, value]); + } + + var entries = this.entries; + var idx = 0; + for (var len = entries.length; idx < len; idx++) { + if (is(key, entries[idx][0])) { + break; + } + } + var exists = idx < len; + + if (exists ? entries[idx][1] === value : removed) { + return this; + } + + SetRef(didAlter); + (removed || !exists) && SetRef(didChangeSize); + + if (removed && len === 2) { + return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1]); + } + + var isEditable = ownerID && ownerID === this.ownerID; + var newEntries = isEditable ? entries : arrCopy(entries); + + if (exists) { + if (removed) { + idx === len - 1 ? newEntries.pop() : (newEntries[idx] = newEntries.pop()); + } else { + newEntries[idx] = [key, value]; + } + } else { + newEntries.push([key, value]); + } + + if (isEditable) { + this.entries = newEntries; + return this; + } + + return new HashCollisionNode(ownerID, this.keyHash, newEntries); + }; + + + + + function ValueNode(ownerID, keyHash, entry) { + this.ownerID = ownerID; + this.keyHash = keyHash; + this.entry = entry; + } + + ValueNode.prototype.get = function(shift, keyHash, key, notSetValue) { + return is(key, this.entry[0]) ? this.entry[1] : notSetValue; + }; + + ValueNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + var removed = value === NOT_SET; + var keyMatch = is(key, this.entry[0]); + if (keyMatch ? value === this.entry[1] : removed) { + return this; + } + + SetRef(didAlter); + + if (removed) { + SetRef(didChangeSize); + return; // undefined + } + + if (keyMatch) { + if (ownerID && ownerID === this.ownerID) { + this.entry[1] = value; + return this; + } + return new ValueNode(ownerID, this.keyHash, [key, value]); + } + + SetRef(didChangeSize); + return mergeIntoNode(this, ownerID, shift, hash(key), [key, value]); + }; + + + + // #pragma Iterators + + ArrayMapNode.prototype.iterate = + HashCollisionNode.prototype.iterate = function (fn, reverse) { + var entries = this.entries; + for (var ii = 0, maxIndex = entries.length - 1; ii <= maxIndex; ii++) { + if (fn(entries[reverse ? maxIndex - ii : ii]) === false) { + return false; + } + } + } + + BitmapIndexedNode.prototype.iterate = + HashArrayMapNode.prototype.iterate = function (fn, reverse) { + var nodes = this.nodes; + for (var ii = 0, maxIndex = nodes.length - 1; ii <= maxIndex; ii++) { + var node = nodes[reverse ? maxIndex - ii : ii]; + if (node && node.iterate(fn, reverse) === false) { + return false; + } + } + } + + ValueNode.prototype.iterate = function (fn, reverse) { + return fn(this.entry); + } + + createClass(MapIterator, Iterator); + + function MapIterator(map, type, reverse) { + this._type = type; + this._reverse = reverse; + this._stack = map._root && mapIteratorFrame(map._root); + } + + MapIterator.prototype.next = function() { + var type = this._type; + var stack = this._stack; + while (stack) { + var node = stack.node; + var index = stack.index++; + var maxIndex; + if (node.entry) { + if (index === 0) { + return mapIteratorValue(type, node.entry); + } + } else if (node.entries) { + maxIndex = node.entries.length - 1; + if (index <= maxIndex) { + return mapIteratorValue(type, node.entries[this._reverse ? maxIndex - index : index]); + } + } else { + maxIndex = node.nodes.length - 1; + if (index <= maxIndex) { + var subNode = node.nodes[this._reverse ? maxIndex - index : index]; + if (subNode) { + if (subNode.entry) { + return mapIteratorValue(type, subNode.entry); + } + stack = this._stack = mapIteratorFrame(subNode, stack); + } + continue; + } + } + stack = this._stack = this._stack.__prev; + } + return iteratorDone(); + }; + + + function mapIteratorValue(type, entry) { + return iteratorValue(type, entry[0], entry[1]); + } + + function mapIteratorFrame(node, prev) { + return { + node: node, + index: 0, + __prev: prev + }; + } + + function makeMap(size, root, ownerID, hash) { + var map = Object.create(MapPrototype); + map.size = size; + map._root = root; + map.__ownerID = ownerID; + map.__hash = hash; + map.__altered = false; + return map; + } + + var EMPTY_MAP; + function emptyMap() { + return EMPTY_MAP || (EMPTY_MAP = makeMap(0)); + } + + function updateMap(map, k, v) { + var newRoot; + var newSize; + if (!map._root) { + if (v === NOT_SET) { + return map; + } + newSize = 1; + newRoot = new ArrayMapNode(map.__ownerID, [[k, v]]); + } else { + var didChangeSize = MakeRef(CHANGE_LENGTH); + var didAlter = MakeRef(DID_ALTER); + newRoot = updateNode(map._root, map.__ownerID, 0, undefined, k, v, didChangeSize, didAlter); + if (!didAlter.value) { + return map; + } + newSize = map.size + (didChangeSize.value ? v === NOT_SET ? -1 : 1 : 0); + } + if (map.__ownerID) { + map.size = newSize; + map._root = newRoot; + map.__hash = undefined; + map.__altered = true; + return map; + } + return newRoot ? makeMap(newSize, newRoot) : emptyMap(); + } + + function updateNode(node, ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { + if (!node) { + if (value === NOT_SET) { + return node; + } + SetRef(didAlter); + SetRef(didChangeSize); + return new ValueNode(ownerID, keyHash, [key, value]); + } + return node.update(ownerID, shift, keyHash, key, value, didChangeSize, didAlter); + } + + function isLeafNode(node) { + return node.constructor === ValueNode || node.constructor === HashCollisionNode; + } + + function mergeIntoNode(node, ownerID, shift, keyHash, entry) { + if (node.keyHash === keyHash) { + return new HashCollisionNode(ownerID, keyHash, [node.entry, entry]); + } + + var idx1 = (shift === 0 ? node.keyHash : node.keyHash >>> shift) & MASK; + var idx2 = (shift === 0 ? keyHash : keyHash >>> shift) & MASK; + + var newNode; + var nodes = idx1 === idx2 ? + [mergeIntoNode(node, ownerID, shift + SHIFT, keyHash, entry)] : + ((newNode = new ValueNode(ownerID, keyHash, entry)), idx1 < idx2 ? [node, newNode] : [newNode, node]); + + return new BitmapIndexedNode(ownerID, (1 << idx1) | (1 << idx2), nodes); + } + + function createNodes(ownerID, entries, key, value) { + if (!ownerID) { + ownerID = new OwnerID(); + } + var node = new ValueNode(ownerID, hash(key), [key, value]); + for (var ii = 0; ii < entries.length; ii++) { + var entry = entries[ii]; + node = node.update(ownerID, 0, undefined, entry[0], entry[1]); + } + return node; + } + + function packNodes(ownerID, nodes, count, excluding) { + var bitmap = 0; + var packedII = 0; + var packedNodes = new Array(count); + for (var ii = 0, bit = 1, len = nodes.length; ii < len; ii++, bit <<= 1) { + var node = nodes[ii]; + if (node !== undefined && ii !== excluding) { + bitmap |= bit; + packedNodes[packedII++] = node; + } + } + return new BitmapIndexedNode(ownerID, bitmap, packedNodes); + } + + function expandNodes(ownerID, nodes, bitmap, including, node) { + var count = 0; + var expandedNodes = new Array(SIZE); + for (var ii = 0; bitmap !== 0; ii++, bitmap >>>= 1) { + expandedNodes[ii] = bitmap & 1 ? nodes[count++] : undefined; + } + expandedNodes[including] = node; + return new HashArrayMapNode(ownerID, count + 1, expandedNodes); + } + + function mergeIntoMapWith(map, merger, iterables) { + var iters = []; + for (var ii = 0; ii < iterables.length; ii++) { + var value = iterables[ii]; + var iter = KeyedIterable(value); + if (!isIterable(value)) { + iter = iter.map(function(v ) {return fromJS(v)}); + } + iters.push(iter); + } + return mergeIntoCollectionWith(map, merger, iters); + } + + function deepMerger(merger) { + return function(existing, value) + {return existing && existing.mergeDeepWith && isIterable(value) ? + existing.mergeDeepWith(merger, value) : + merger ? merger(existing, value) : value}; + } + + function mergeIntoCollectionWith(collection, merger, iters) { + iters = iters.filter(function(x ) {return x.size !== 0}); + if (iters.length === 0) { + return collection; + } + if (collection.size === 0 && iters.length === 1) { + return collection.constructor(iters[0]); + } + return collection.withMutations(function(collection ) { + var mergeIntoMap = merger ? + function(value, key) { + collection.update(key, NOT_SET, function(existing ) + {return existing === NOT_SET ? value : merger(existing, value)} + ); + } : + function(value, key) { + collection.set(key, value); + } + for (var ii = 0; ii < iters.length; ii++) { + iters[ii].forEach(mergeIntoMap); + } + }); + } + + function updateInDeepMap(existing, keyPathIter, notSetValue, updater) { + var isNotSet = existing === NOT_SET; + var step = keyPathIter.next(); + if (step.done) { + var existingValue = isNotSet ? notSetValue : existing; + var newValue = updater(existingValue); + return newValue === existingValue ? existing : newValue; + } + invariant( + isNotSet || (existing && existing.set), + 'invalid keyPath' + ); + var key = step.value; + var nextExisting = isNotSet ? NOT_SET : existing.get(key, NOT_SET); + var nextUpdated = updateInDeepMap( + nextExisting, + keyPathIter, + notSetValue, + updater + ); + return nextUpdated === nextExisting ? existing : + nextUpdated === NOT_SET ? existing.remove(key) : + (isNotSet ? emptyMap() : existing).set(key, nextUpdated); + } + + function popCount(x) { + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0f0f0f0f; + x = x + (x >> 8); + x = x + (x >> 16); + return x & 0x7f; + } + + function setIn(array, idx, val, canEdit) { + var newArray = canEdit ? array : arrCopy(array); + newArray[idx] = val; + return newArray; + } + + function spliceIn(array, idx, val, canEdit) { + var newLen = array.length + 1; + if (canEdit && idx + 1 === newLen) { + array[idx] = val; + return array; + } + var newArray = new Array(newLen); + var after = 0; + for (var ii = 0; ii < newLen; ii++) { + if (ii === idx) { + newArray[ii] = val; + after = -1; + } else { + newArray[ii] = array[ii + after]; + } + } + return newArray; + } + + function spliceOut(array, idx, canEdit) { + var newLen = array.length - 1; + if (canEdit && idx === newLen) { + array.pop(); + return array; + } + var newArray = new Array(newLen); + var after = 0; + for (var ii = 0; ii < newLen; ii++) { + if (ii === idx) { + after = 1; + } + newArray[ii] = array[ii + after]; + } + return newArray; + } + + var MAX_ARRAY_MAP_SIZE = SIZE / 4; + var MAX_BITMAP_INDEXED_SIZE = SIZE / 2; + var MIN_HASH_ARRAY_MAP_SIZE = SIZE / 4; + + createClass(List, IndexedCollection); + + // @pragma Construction + + function List(value) { + var empty = emptyList(); + if (value === null || value === undefined) { + return empty; + } + if (isList(value)) { + return value; + } + var iter = IndexedIterable(value); + var size = iter.size; + if (size === 0) { + return empty; + } + assertNotInfinite(size); + if (size > 0 && size < SIZE) { + return makeList(0, size, SHIFT, null, new VNode(iter.toArray())); + } + return empty.withMutations(function(list ) { + list.setSize(size); + iter.forEach(function(v, i) {return list.set(i, v)}); + }); + } + + List.of = function(/*...values*/) { + return this(arguments); + }; + + List.prototype.toString = function() { + return this.__toString('List [', ']'); + }; + + // @pragma Access + + List.prototype.get = function(index, notSetValue) { + index = wrapIndex(this, index); + if (index < 0 || index >= this.size) { + return notSetValue; + } + index += this._origin; + var node = listNodeFor(this, index); + return node && node.array[index & MASK]; + }; + + // @pragma Modification + + List.prototype.set = function(index, value) { + return updateList(this, index, value); + }; + + List.prototype.remove = function(index) { + return !this.has(index) ? this : + index === 0 ? this.shift() : + index === this.size - 1 ? this.pop() : + this.splice(index, 1); + }; + + List.prototype.clear = function() { + if (this.size === 0) { + return this; + } + if (this.__ownerID) { + this.size = this._origin = this._capacity = 0; + this._level = SHIFT; + this._root = this._tail = null; + this.__hash = undefined; + this.__altered = true; + return this; + } + return emptyList(); + }; + + List.prototype.push = function(/*...values*/) { + var values = arguments; + var oldSize = this.size; + return this.withMutations(function(list ) { + setListBounds(list, 0, oldSize + values.length); + for (var ii = 0; ii < values.length; ii++) { + list.set(oldSize + ii, values[ii]); + } + }); + }; + + List.prototype.pop = function() { + return setListBounds(this, 0, -1); + }; + + List.prototype.unshift = function(/*...values*/) { + var values = arguments; + return this.withMutations(function(list ) { + setListBounds(list, -values.length); + for (var ii = 0; ii < values.length; ii++) { + list.set(ii, values[ii]); + } + }); + }; + + List.prototype.shift = function() { + return setListBounds(this, 1); + }; + + // @pragma Composition + + List.prototype.merge = function(/*...iters*/) { + return mergeIntoListWith(this, undefined, arguments); + }; + + List.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1); + return mergeIntoListWith(this, merger, iters); + }; + + List.prototype.mergeDeep = function(/*...iters*/) { + return mergeIntoListWith(this, deepMerger(undefined), arguments); + }; + + List.prototype.mergeDeepWith = function(merger) {var iters = SLICE$0.call(arguments, 1); + return mergeIntoListWith(this, deepMerger(merger), iters); + }; + + List.prototype.setSize = function(size) { + return setListBounds(this, 0, size); + }; + + // @pragma Iteration + + List.prototype.slice = function(begin, end) { + var size = this.size; + if (wholeSlice(begin, end, size)) { + return this; + } + return setListBounds( + this, + resolveBegin(begin, size), + resolveEnd(end, size) + ); + }; + + List.prototype.__iterator = function(type, reverse) { + var index = 0; + var values = iterateList(this, reverse); + return new Iterator(function() { + var value = values(); + return value === DONE ? + iteratorDone() : + iteratorValue(type, index++, value); + }); + }; + + List.prototype.__iterate = function(fn, reverse) { + var index = 0; + var values = iterateList(this, reverse); + var value; + while ((value = values()) !== DONE) { + if (fn(value, index++, this) === false) { + break; + } + } + return index; + }; + + List.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + if (!ownerID) { + this.__ownerID = ownerID; + return this; + } + return makeList(this._origin, this._capacity, this._level, this._root, this._tail, ownerID, this.__hash); + }; + + + function isList(maybeList) { + return !!(maybeList && maybeList[IS_LIST_SENTINEL]); + } + + List.isList = isList; + + var IS_LIST_SENTINEL = '@@__IMMUTABLE_LIST__@@'; + + var ListPrototype = List.prototype; + ListPrototype[IS_LIST_SENTINEL] = true; + ListPrototype[DELETE] = ListPrototype.remove; + ListPrototype.setIn = MapPrototype.setIn; + ListPrototype.deleteIn = + ListPrototype.removeIn = MapPrototype.removeIn; + ListPrototype.update = MapPrototype.update; + ListPrototype.updateIn = MapPrototype.updateIn; + ListPrototype.mergeIn = MapPrototype.mergeIn; + ListPrototype.mergeDeepIn = MapPrototype.mergeDeepIn; + ListPrototype.withMutations = MapPrototype.withMutations; + ListPrototype.asMutable = MapPrototype.asMutable; + ListPrototype.asImmutable = MapPrototype.asImmutable; + ListPrototype.wasAltered = MapPrototype.wasAltered; + + + + function VNode(array, ownerID) { + this.array = array; + this.ownerID = ownerID; + } + + // TODO: seems like these methods are very similar + + VNode.prototype.removeBefore = function(ownerID, level, index) { + if (index === level ? 1 << level : 0 || this.array.length === 0) { + return this; + } + var originIndex = (index >>> level) & MASK; + if (originIndex >= this.array.length) { + return new VNode([], ownerID); + } + var removingFirst = originIndex === 0; + var newChild; + if (level > 0) { + var oldChild = this.array[originIndex]; + newChild = oldChild && oldChild.removeBefore(ownerID, level - SHIFT, index); + if (newChild === oldChild && removingFirst) { + return this; + } + } + if (removingFirst && !newChild) { + return this; + } + var editable = editableVNode(this, ownerID); + if (!removingFirst) { + for (var ii = 0; ii < originIndex; ii++) { + editable.array[ii] = undefined; + } + } + if (newChild) { + editable.array[originIndex] = newChild; + } + return editable; + }; + + VNode.prototype.removeAfter = function(ownerID, level, index) { + if (index === level ? 1 << level : 0 || this.array.length === 0) { + return this; + } + var sizeIndex = ((index - 1) >>> level) & MASK; + if (sizeIndex >= this.array.length) { + return this; + } + var removingLast = sizeIndex === this.array.length - 1; + var newChild; + if (level > 0) { + var oldChild = this.array[sizeIndex]; + newChild = oldChild && oldChild.removeAfter(ownerID, level - SHIFT, index); + if (newChild === oldChild && removingLast) { + return this; + } + } + if (removingLast && !newChild) { + return this; + } + var editable = editableVNode(this, ownerID); + if (!removingLast) { + editable.array.pop(); + } + if (newChild) { + editable.array[sizeIndex] = newChild; + } + return editable; + }; + + + + var DONE = {}; + + function iterateList(list, reverse) { + var left = list._origin; + var right = list._capacity; + var tailPos = getTailOffset(right); + var tail = list._tail; + + return iterateNodeOrLeaf(list._root, list._level, 0); + + function iterateNodeOrLeaf(node, level, offset) { + return level === 0 ? + iterateLeaf(node, offset) : + iterateNode(node, level, offset); + } + + function iterateLeaf(node, offset) { + var array = offset === tailPos ? tail && tail.array : node && node.array; + var from = offset > left ? 0 : left - offset; + var to = right - offset; + if (to > SIZE) { + to = SIZE; + } + return function() { + if (from === to) { + return DONE; + } + var idx = reverse ? --to : from++; + return array && array[idx]; + }; + } + + function iterateNode(node, level, offset) { + var values; + var array = node && node.array; + var from = offset > left ? 0 : (left - offset) >> level; + var to = ((right - offset) >> level) + 1; + if (to > SIZE) { + to = SIZE; + } + return function() { + do { + if (values) { + var value = values(); + if (value !== DONE) { + return value; + } + values = null; + } + if (from === to) { + return DONE; + } + var idx = reverse ? --to : from++; + values = iterateNodeOrLeaf( + array && array[idx], level - SHIFT, offset + (idx << level) + ); + } while (true); + }; + } + } + + function makeList(origin, capacity, level, root, tail, ownerID, hash) { + var list = Object.create(ListPrototype); + list.size = capacity - origin; + list._origin = origin; + list._capacity = capacity; + list._level = level; + list._root = root; + list._tail = tail; + list.__ownerID = ownerID; + list.__hash = hash; + list.__altered = false; + return list; + } + + var EMPTY_LIST; + function emptyList() { + return EMPTY_LIST || (EMPTY_LIST = makeList(0, 0, SHIFT)); + } + + function updateList(list, index, value) { + index = wrapIndex(list, index); + + if (index >= list.size || index < 0) { + return list.withMutations(function(list ) { + index < 0 ? + setListBounds(list, index).set(0, value) : + setListBounds(list, 0, index + 1).set(index, value) + }); + } + + index += list._origin; + + var newTail = list._tail; + var newRoot = list._root; + var didAlter = MakeRef(DID_ALTER); + if (index >= getTailOffset(list._capacity)) { + newTail = updateVNode(newTail, list.__ownerID, 0, index, value, didAlter); + } else { + newRoot = updateVNode(newRoot, list.__ownerID, list._level, index, value, didAlter); + } + + if (!didAlter.value) { + return list; + } + + if (list.__ownerID) { + list._root = newRoot; + list._tail = newTail; + list.__hash = undefined; + list.__altered = true; + return list; + } + return makeList(list._origin, list._capacity, list._level, newRoot, newTail); + } + + function updateVNode(node, ownerID, level, index, value, didAlter) { + var idx = (index >>> level) & MASK; + var nodeHas = node && idx < node.array.length; + if (!nodeHas && value === undefined) { + return node; + } + + var newNode; + + if (level > 0) { + var lowerNode = node && node.array[idx]; + var newLowerNode = updateVNode(lowerNode, ownerID, level - SHIFT, index, value, didAlter); + if (newLowerNode === lowerNode) { + return node; + } + newNode = editableVNode(node, ownerID); + newNode.array[idx] = newLowerNode; + return newNode; + } + + if (nodeHas && node.array[idx] === value) { + return node; + } + + SetRef(didAlter); + + newNode = editableVNode(node, ownerID); + if (value === undefined && idx === newNode.array.length - 1) { + newNode.array.pop(); + } else { + newNode.array[idx] = value; + } + return newNode; + } + + function editableVNode(node, ownerID) { + if (ownerID && node && ownerID === node.ownerID) { + return node; + } + return new VNode(node ? node.array.slice() : [], ownerID); + } + + function listNodeFor(list, rawIndex) { + if (rawIndex >= getTailOffset(list._capacity)) { + return list._tail; + } + if (rawIndex < 1 << (list._level + SHIFT)) { + var node = list._root; + var level = list._level; + while (node && level > 0) { + node = node.array[(rawIndex >>> level) & MASK]; + level -= SHIFT; + } + return node; + } + } + + function setListBounds(list, begin, end) { + var owner = list.__ownerID || new OwnerID(); + var oldOrigin = list._origin; + var oldCapacity = list._capacity; + var newOrigin = oldOrigin + begin; + var newCapacity = end === undefined ? oldCapacity : end < 0 ? oldCapacity + end : oldOrigin + end; + if (newOrigin === oldOrigin && newCapacity === oldCapacity) { + return list; + } + + // If it's going to end after it starts, it's empty. + if (newOrigin >= newCapacity) { + return list.clear(); + } + + var newLevel = list._level; + var newRoot = list._root; + + // New origin might require creating a higher root. + var offsetShift = 0; + while (newOrigin + offsetShift < 0) { + newRoot = new VNode(newRoot && newRoot.array.length ? [undefined, newRoot] : [], owner); + newLevel += SHIFT; + offsetShift += 1 << newLevel; + } + if (offsetShift) { + newOrigin += offsetShift; + oldOrigin += offsetShift; + newCapacity += offsetShift; + oldCapacity += offsetShift; + } + + var oldTailOffset = getTailOffset(oldCapacity); + var newTailOffset = getTailOffset(newCapacity); + + // New size might require creating a higher root. + while (newTailOffset >= 1 << (newLevel + SHIFT)) { + newRoot = new VNode(newRoot && newRoot.array.length ? [newRoot] : [], owner); + newLevel += SHIFT; + } + + // Locate or create the new tail. + var oldTail = list._tail; + var newTail = newTailOffset < oldTailOffset ? + listNodeFor(list, newCapacity - 1) : + newTailOffset > oldTailOffset ? new VNode([], owner) : oldTail; + + // Merge Tail into tree. + if (oldTail && newTailOffset > oldTailOffset && newOrigin < oldCapacity && oldTail.array.length) { + newRoot = editableVNode(newRoot, owner); + var node = newRoot; + for (var level = newLevel; level > SHIFT; level -= SHIFT) { + var idx = (oldTailOffset >>> level) & MASK; + node = node.array[idx] = editableVNode(node.array[idx], owner); + } + node.array[(oldTailOffset >>> SHIFT) & MASK] = oldTail; + } + + // If the size has been reduced, there's a chance the tail needs to be trimmed. + if (newCapacity < oldCapacity) { + newTail = newTail && newTail.removeAfter(owner, 0, newCapacity); + } + + // If the new origin is within the tail, then we do not need a root. + if (newOrigin >= newTailOffset) { + newOrigin -= newTailOffset; + newCapacity -= newTailOffset; + newLevel = SHIFT; + newRoot = null; + newTail = newTail && newTail.removeBefore(owner, 0, newOrigin); + + // Otherwise, if the root has been trimmed, garbage collect. + } else if (newOrigin > oldOrigin || newTailOffset < oldTailOffset) { + offsetShift = 0; + + // Identify the new top root node of the subtree of the old root. + while (newRoot) { + var beginIndex = (newOrigin >>> newLevel) & MASK; + if (beginIndex !== (newTailOffset >>> newLevel) & MASK) { + break; + } + if (beginIndex) { + offsetShift += (1 << newLevel) * beginIndex; + } + newLevel -= SHIFT; + newRoot = newRoot.array[beginIndex]; + } + + // Trim the new sides of the new root. + if (newRoot && newOrigin > oldOrigin) { + newRoot = newRoot.removeBefore(owner, newLevel, newOrigin - offsetShift); + } + if (newRoot && newTailOffset < oldTailOffset) { + newRoot = newRoot.removeAfter(owner, newLevel, newTailOffset - offsetShift); + } + if (offsetShift) { + newOrigin -= offsetShift; + newCapacity -= offsetShift; + } + } + + if (list.__ownerID) { + list.size = newCapacity - newOrigin; + list._origin = newOrigin; + list._capacity = newCapacity; + list._level = newLevel; + list._root = newRoot; + list._tail = newTail; + list.__hash = undefined; + list.__altered = true; + return list; + } + return makeList(newOrigin, newCapacity, newLevel, newRoot, newTail); + } + + function mergeIntoListWith(list, merger, iterables) { + var iters = []; + var maxSize = 0; + for (var ii = 0; ii < iterables.length; ii++) { + var value = iterables[ii]; + var iter = IndexedIterable(value); + if (iter.size > maxSize) { + maxSize = iter.size; + } + if (!isIterable(value)) { + iter = iter.map(function(v ) {return fromJS(v)}); + } + iters.push(iter); + } + if (maxSize > list.size) { + list = list.setSize(maxSize); + } + return mergeIntoCollectionWith(list, merger, iters); + } + + function getTailOffset(size) { + return size < SIZE ? 0 : (((size - 1) >>> SHIFT) << SHIFT); + } + + createClass(OrderedMap, Map); + + // @pragma Construction + + function OrderedMap(value) { + return value === null || value === undefined ? emptyOrderedMap() : + isOrderedMap(value) ? value : + emptyOrderedMap().withMutations(function(map ) { + var iter = KeyedIterable(value); + assertNotInfinite(iter.size); + iter.forEach(function(v, k) {return map.set(k, v)}); + }); + } + + OrderedMap.of = function(/*...values*/) { + return this(arguments); + }; + + OrderedMap.prototype.toString = function() { + return this.__toString('OrderedMap {', '}'); + }; + + // @pragma Access + + OrderedMap.prototype.get = function(k, notSetValue) { + var index = this._map.get(k); + return index !== undefined ? this._list.get(index)[1] : notSetValue; + }; + + // @pragma Modification + + OrderedMap.prototype.clear = function() { + if (this.size === 0) { + return this; + } + if (this.__ownerID) { + this.size = 0; + this._map.clear(); + this._list.clear(); + return this; + } + return emptyOrderedMap(); + }; + + OrderedMap.prototype.set = function(k, v) { + return updateOrderedMap(this, k, v); + }; + + OrderedMap.prototype.remove = function(k) { + return updateOrderedMap(this, k, NOT_SET); + }; + + OrderedMap.prototype.wasAltered = function() { + return this._map.wasAltered() || this._list.wasAltered(); + }; + + OrderedMap.prototype.__iterate = function(fn, reverse) {var this$0 = this; + return this._list.__iterate( + function(entry ) {return entry && fn(entry[1], entry[0], this$0)}, + reverse + ); + }; + + OrderedMap.prototype.__iterator = function(type, reverse) { + return this._list.fromEntrySeq().__iterator(type, reverse); + }; + + OrderedMap.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + var newMap = this._map.__ensureOwner(ownerID); + var newList = this._list.__ensureOwner(ownerID); + if (!ownerID) { + this.__ownerID = ownerID; + this._map = newMap; + this._list = newList; + return this; + } + return makeOrderedMap(newMap, newList, ownerID, this.__hash); + }; + + + function isOrderedMap(maybeOrderedMap) { + return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap); + } + + OrderedMap.isOrderedMap = isOrderedMap; + + OrderedMap.prototype[IS_ORDERED_SENTINEL] = true; + OrderedMap.prototype[DELETE] = OrderedMap.prototype.remove; + + + + function makeOrderedMap(map, list, ownerID, hash) { + var omap = Object.create(OrderedMap.prototype); + omap.size = map ? map.size : 0; + omap._map = map; + omap._list = list; + omap.__ownerID = ownerID; + omap.__hash = hash; + return omap; + } + + var EMPTY_ORDERED_MAP; + function emptyOrderedMap() { + return EMPTY_ORDERED_MAP || (EMPTY_ORDERED_MAP = makeOrderedMap(emptyMap(), emptyList())); + } + + function updateOrderedMap(omap, k, v) { + var map = omap._map; + var list = omap._list; + var i = map.get(k); + var has = i !== undefined; + var newMap; + var newList; + if (v === NOT_SET) { // removed + if (!has) { + return omap; + } + if (list.size >= SIZE && list.size >= map.size * 2) { + newList = list.filter(function(entry, idx) {return entry !== undefined && i !== idx}); + newMap = newList.toKeyedSeq().map(function(entry ) {return entry[0]}).flip().toMap(); + if (omap.__ownerID) { + newMap.__ownerID = newList.__ownerID = omap.__ownerID; + } + } else { + newMap = map.remove(k); + newList = i === list.size - 1 ? list.pop() : list.set(i, undefined); + } + } else { + if (has) { + if (v === list.get(i)[1]) { + return omap; + } + newMap = map; + newList = list.set(i, [k, v]); + } else { + newMap = map.set(k, list.size); + newList = list.set(list.size, [k, v]); + } + } + if (omap.__ownerID) { + omap.size = newMap.size; + omap._map = newMap; + omap._list = newList; + omap.__hash = undefined; + return omap; + } + return makeOrderedMap(newMap, newList); + } + + createClass(Stack, IndexedCollection); + + // @pragma Construction + + function Stack(value) { + return value === null || value === undefined ? emptyStack() : + isStack(value) ? value : + emptyStack().unshiftAll(value); + } + + Stack.of = function(/*...values*/) { + return this(arguments); + }; + + Stack.prototype.toString = function() { + return this.__toString('Stack [', ']'); + }; + + // @pragma Access + + Stack.prototype.get = function(index, notSetValue) { + var head = this._head; + while (head && index--) { + head = head.next; + } + return head ? head.value : notSetValue; + }; + + Stack.prototype.peek = function() { + return this._head && this._head.value; + }; + + // @pragma Modification + + Stack.prototype.push = function(/*...values*/) { + if (arguments.length === 0) { + return this; + } + var newSize = this.size + arguments.length; + var head = this._head; + for (var ii = arguments.length - 1; ii >= 0; ii--) { + head = { + value: arguments[ii], + next: head + }; + } + if (this.__ownerID) { + this.size = newSize; + this._head = head; + this.__hash = undefined; + this.__altered = true; + return this; + } + return makeStack(newSize, head); + }; + + Stack.prototype.pushAll = function(iter) { + iter = IndexedIterable(iter); + if (iter.size === 0) { + return this; + } + assertNotInfinite(iter.size); + var newSize = this.size; + var head = this._head; + iter.reverse().forEach(function(value ) { + newSize++; + head = { + value: value, + next: head + }; + }); + if (this.__ownerID) { + this.size = newSize; + this._head = head; + this.__hash = undefined; + this.__altered = true; + return this; + } + return makeStack(newSize, head); + }; + + Stack.prototype.pop = function() { + return this.slice(1); + }; + + Stack.prototype.unshift = function(/*...values*/) { + return this.push.apply(this, arguments); + }; + + Stack.prototype.unshiftAll = function(iter) { + return this.pushAll(iter); + }; + + Stack.prototype.shift = function() { + return this.pop.apply(this, arguments); + }; + + Stack.prototype.clear = function() { + if (this.size === 0) { + return this; + } + if (this.__ownerID) { + this.size = 0; + this._head = undefined; + this.__hash = undefined; + this.__altered = true; + return this; + } + return emptyStack(); + }; + + Stack.prototype.slice = function(begin, end) { + if (wholeSlice(begin, end, this.size)) { + return this; + } + var resolvedBegin = resolveBegin(begin, this.size); + var resolvedEnd = resolveEnd(end, this.size); + if (resolvedEnd !== this.size) { + // super.slice(begin, end); + return IndexedCollection.prototype.slice.call(this, begin, end); + } + var newSize = this.size - resolvedBegin; + var head = this._head; + while (resolvedBegin--) { + head = head.next; + } + if (this.__ownerID) { + this.size = newSize; + this._head = head; + this.__hash = undefined; + this.__altered = true; + return this; + } + return makeStack(newSize, head); + }; + + // @pragma Mutability + + Stack.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + if (!ownerID) { + this.__ownerID = ownerID; + this.__altered = false; + return this; + } + return makeStack(this.size, this._head, ownerID, this.__hash); + }; + + // @pragma Iteration + + Stack.prototype.__iterate = function(fn, reverse) { + if (reverse) { + return this.toSeq().cacheResult.__iterate(fn, reverse); + } + var iterations = 0; + var node = this._head; + while (node) { + if (fn(node.value, iterations++, this) === false) { + break; + } + node = node.next; + } + return iterations; + }; + + Stack.prototype.__iterator = function(type, reverse) { + if (reverse) { + return this.toSeq().cacheResult().__iterator(type, reverse); + } + var iterations = 0; + var node = this._head; + return new Iterator(function() { + if (node) { + var value = node.value; + node = node.next; + return iteratorValue(type, iterations++, value); + } + return iteratorDone(); + }); + }; + + + function isStack(maybeStack) { + return !!(maybeStack && maybeStack[IS_STACK_SENTINEL]); + } + + Stack.isStack = isStack; + + var IS_STACK_SENTINEL = '@@__IMMUTABLE_STACK__@@'; + + var StackPrototype = Stack.prototype; + StackPrototype[IS_STACK_SENTINEL] = true; + StackPrototype.withMutations = MapPrototype.withMutations; + StackPrototype.asMutable = MapPrototype.asMutable; + StackPrototype.asImmutable = MapPrototype.asImmutable; + StackPrototype.wasAltered = MapPrototype.wasAltered; + + + function makeStack(size, head, ownerID, hash) { + var map = Object.create(StackPrototype); + map.size = size; + map._head = head; + map.__ownerID = ownerID; + map.__hash = hash; + map.__altered = false; + return map; + } + + var EMPTY_STACK; + function emptyStack() { + return EMPTY_STACK || (EMPTY_STACK = makeStack(0)); + } + + createClass(Set, SetCollection); + + // @pragma Construction + + function Set(value) { + return value === null || value === undefined ? emptySet() : + isSet(value) ? value : + emptySet().withMutations(function(set ) { + var iter = SetIterable(value); + assertNotInfinite(iter.size); + iter.forEach(function(v ) {return set.add(v)}); + }); + } + + Set.of = function(/*...values*/) { + return this(arguments); + }; + + Set.fromKeys = function(value) { + return this(KeyedIterable(value).keySeq()); + }; + + Set.prototype.toString = function() { + return this.__toString('Set {', '}'); + }; + + // @pragma Access + + Set.prototype.has = function(value) { + return this._map.has(value); + }; + + // @pragma Modification + + Set.prototype.add = function(value) { + return updateSet(this, this._map.set(value, true)); + }; + + Set.prototype.remove = function(value) { + return updateSet(this, this._map.remove(value)); + }; + + Set.prototype.clear = function() { + return updateSet(this, this._map.clear()); + }; + + // @pragma Composition + + Set.prototype.union = function() {var iters = SLICE$0.call(arguments, 0); + iters = iters.filter(function(x ) {return x.size !== 0}); + if (iters.length === 0) { + return this; + } + if (this.size === 0 && iters.length === 1) { + return this.constructor(iters[0]); + } + return this.withMutations(function(set ) { + for (var ii = 0; ii < iters.length; ii++) { + SetIterable(iters[ii]).forEach(function(value ) {return set.add(value)}); + } + }); + }; + + Set.prototype.intersect = function() {var iters = SLICE$0.call(arguments, 0); + if (iters.length === 0) { + return this; + } + iters = iters.map(function(iter ) {return SetIterable(iter)}); + var originalSet = this; + return this.withMutations(function(set ) { + originalSet.forEach(function(value ) { + if (!iters.every(function(iter ) {return iter.contains(value)})) { + set.remove(value); + } + }); + }); + }; + + Set.prototype.subtract = function() {var iters = SLICE$0.call(arguments, 0); + if (iters.length === 0) { + return this; + } + iters = iters.map(function(iter ) {return SetIterable(iter)}); + var originalSet = this; + return this.withMutations(function(set ) { + originalSet.forEach(function(value ) { + if (iters.some(function(iter ) {return iter.contains(value)})) { + set.remove(value); + } + }); + }); + }; + + Set.prototype.merge = function() { + return this.union.apply(this, arguments); + }; + + Set.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1); + return this.union.apply(this, iters); + }; + + Set.prototype.sort = function(comparator) { + // Late binding + return OrderedSet(sortFactory(this, comparator)); + }; + + Set.prototype.sortBy = function(mapper, comparator) { + // Late binding + return OrderedSet(sortFactory(this, comparator, mapper)); + }; + + Set.prototype.wasAltered = function() { + return this._map.wasAltered(); + }; + + Set.prototype.__iterate = function(fn, reverse) {var this$0 = this; + return this._map.__iterate(function(_, k) {return fn(k, k, this$0)}, reverse); + }; + + Set.prototype.__iterator = function(type, reverse) { + return this._map.map(function(_, k) {return k}).__iterator(type, reverse); + }; + + Set.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + var newMap = this._map.__ensureOwner(ownerID); + if (!ownerID) { + this.__ownerID = ownerID; + this._map = newMap; + return this; + } + return this.__make(newMap, ownerID); + }; + + + function isSet(maybeSet) { + return !!(maybeSet && maybeSet[IS_SET_SENTINEL]); + } + + Set.isSet = isSet; + + var IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@'; + + var SetPrototype = Set.prototype; + SetPrototype[IS_SET_SENTINEL] = true; + SetPrototype[DELETE] = SetPrototype.remove; + SetPrototype.mergeDeep = SetPrototype.merge; + SetPrototype.mergeDeepWith = SetPrototype.mergeWith; + SetPrototype.withMutations = MapPrototype.withMutations; + SetPrototype.asMutable = MapPrototype.asMutable; + SetPrototype.asImmutable = MapPrototype.asImmutable; + + SetPrototype.__empty = emptySet; + SetPrototype.__make = makeSet; + + function updateSet(set, newMap) { + if (set.__ownerID) { + set.size = newMap.size; + set._map = newMap; + return set; + } + return newMap === set._map ? set : + newMap.size === 0 ? set.__empty() : + set.__make(newMap); + } + + function makeSet(map, ownerID) { + var set = Object.create(SetPrototype); + set.size = map ? map.size : 0; + set._map = map; + set.__ownerID = ownerID; + return set; + } + + var EMPTY_SET; + function emptySet() { + return EMPTY_SET || (EMPTY_SET = makeSet(emptyMap())); + } + + createClass(OrderedSet, Set); + + // @pragma Construction + + function OrderedSet(value) { + return value === null || value === undefined ? emptyOrderedSet() : + isOrderedSet(value) ? value : + emptyOrderedSet().withMutations(function(set ) { + var iter = SetIterable(value); + assertNotInfinite(iter.size); + iter.forEach(function(v ) {return set.add(v)}); + }); + } + + OrderedSet.of = function(/*...values*/) { + return this(arguments); + }; + + OrderedSet.fromKeys = function(value) { + return this(KeyedIterable(value).keySeq()); + }; + + OrderedSet.prototype.toString = function() { + return this.__toString('OrderedSet {', '}'); + }; + + + function isOrderedSet(maybeOrderedSet) { + return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet); + } + + OrderedSet.isOrderedSet = isOrderedSet; + + var OrderedSetPrototype = OrderedSet.prototype; + OrderedSetPrototype[IS_ORDERED_SENTINEL] = true; + + OrderedSetPrototype.__empty = emptyOrderedSet; + OrderedSetPrototype.__make = makeOrderedSet; + + function makeOrderedSet(map, ownerID) { + var set = Object.create(OrderedSetPrototype); + set.size = map ? map.size : 0; + set._map = map; + set.__ownerID = ownerID; + return set; + } + + var EMPTY_ORDERED_SET; + function emptyOrderedSet() { + return EMPTY_ORDERED_SET || (EMPTY_ORDERED_SET = makeOrderedSet(emptyOrderedMap())); + } + + createClass(Record, KeyedCollection); + + function Record(defaultValues, name) { + var RecordType = function Record(values) { + if (!(this instanceof RecordType)) { + return new RecordType(values); + } + this._map = Map(values); + }; + + var keys = Object.keys(defaultValues); + + var RecordTypePrototype = RecordType.prototype = Object.create(RecordPrototype); + RecordTypePrototype.constructor = RecordType; + name && (RecordTypePrototype._name = name); + RecordTypePrototype._defaultValues = defaultValues; + RecordTypePrototype._keys = keys; + RecordTypePrototype.size = keys.length; + + try { + keys.forEach(function(key ) { + Object.defineProperty(RecordType.prototype, key, { + get: function() { + return this.get(key); + }, + set: function(value) { + invariant(this.__ownerID, 'Cannot set on an immutable record.'); + this.set(key, value); + } + }); + }); + } catch (error) { + // Object.defineProperty failed. Probably IE8. + } + + return RecordType; + } + + Record.prototype.toString = function() { + return this.__toString(recordName(this) + ' {', '}'); + }; + + // @pragma Access + + Record.prototype.has = function(k) { + return this._defaultValues.hasOwnProperty(k); + }; + + Record.prototype.get = function(k, notSetValue) { + if (!this.has(k)) { + return notSetValue; + } + var defaultVal = this._defaultValues[k]; + return this._map ? this._map.get(k, defaultVal) : defaultVal; + }; + + // @pragma Modification + + Record.prototype.clear = function() { + if (this.__ownerID) { + this._map && this._map.clear(); + return this; + } + var SuperRecord = Object.getPrototypeOf(this).constructor; + return SuperRecord._empty || (SuperRecord._empty = makeRecord(this, emptyMap())); + }; + + Record.prototype.set = function(k, v) { + if (!this.has(k)) { + throw new Error('Cannot set unknown key "' + k + '" on ' + recordName(this)); + } + var newMap = this._map && this._map.set(k, v); + if (this.__ownerID || newMap === this._map) { + return this; + } + return makeRecord(this, newMap); + }; + + Record.prototype.remove = function(k) { + if (!this.has(k)) { + return this; + } + var newMap = this._map && this._map.remove(k); + if (this.__ownerID || newMap === this._map) { + return this; + } + return makeRecord(this, newMap); + }; + + Record.prototype.wasAltered = function() { + return this._map.wasAltered(); + }; + + Record.prototype.__iterator = function(type, reverse) {var this$0 = this; + return KeyedIterable(this._defaultValues).map(function(_, k) {return this$0.get(k)}).__iterator(type, reverse); + }; + + Record.prototype.__iterate = function(fn, reverse) {var this$0 = this; + return KeyedIterable(this._defaultValues).map(function(_, k) {return this$0.get(k)}).__iterate(fn, reverse); + }; + + Record.prototype.__ensureOwner = function(ownerID) { + if (ownerID === this.__ownerID) { + return this; + } + var newMap = this._map && this._map.__ensureOwner(ownerID); + if (!ownerID) { + this.__ownerID = ownerID; + this._map = newMap; + return this; + } + return makeRecord(this, newMap, ownerID); + }; + + + var RecordPrototype = Record.prototype; + RecordPrototype[DELETE] = RecordPrototype.remove; + RecordPrototype.deleteIn = + RecordPrototype.removeIn = MapPrototype.removeIn; + RecordPrototype.merge = MapPrototype.merge; + RecordPrototype.mergeWith = MapPrototype.mergeWith; + RecordPrototype.mergeIn = MapPrototype.mergeIn; + RecordPrototype.mergeDeep = MapPrototype.mergeDeep; + RecordPrototype.mergeDeepWith = MapPrototype.mergeDeepWith; + RecordPrototype.mergeDeepIn = MapPrototype.mergeDeepIn; + RecordPrototype.setIn = MapPrototype.setIn; + RecordPrototype.update = MapPrototype.update; + RecordPrototype.updateIn = MapPrototype.updateIn; + RecordPrototype.withMutations = MapPrototype.withMutations; + RecordPrototype.asMutable = MapPrototype.asMutable; + RecordPrototype.asImmutable = MapPrototype.asImmutable; + + + function makeRecord(likeRecord, map, ownerID) { + var record = Object.create(Object.getPrototypeOf(likeRecord)); + record._map = map; + record.__ownerID = ownerID; + return record; + } + + function recordName(record) { + return record._name || record.constructor.name; + } + + function deepEqual(a, b) { + if (a === b) { + return true; + } + + if ( + !isIterable(b) || + a.size !== undefined && b.size !== undefined && a.size !== b.size || + a.__hash !== undefined && b.__hash !== undefined && a.__hash !== b.__hash || + isKeyed(a) !== isKeyed(b) || + isIndexed(a) !== isIndexed(b) || + isOrdered(a) !== isOrdered(b) + ) { + return false; + } + + if (a.size === 0 && b.size === 0) { + return true; + } + + var notAssociative = !isAssociative(a); + + if (isOrdered(a)) { + var entries = a.entries(); + return b.every(function(v, k) { + var entry = entries.next().value; + return entry && is(entry[1], v) && (notAssociative || is(entry[0], k)); + }) && entries.next().done; + } + + var flipped = false; + + if (a.size === undefined) { + if (b.size === undefined) { + a.cacheResult(); + } else { + flipped = true; + var _ = a; + a = b; + b = _; + } + } + + var allEqual = true; + var bSize = b.__iterate(function(v, k) { + if (notAssociative ? !a.has(v) : + flipped ? !is(v, a.get(k, NOT_SET)) : !is(a.get(k, NOT_SET), v)) { + allEqual = false; + return false; + } + }); + + return allEqual && a.size === bSize; + } + + createClass(Range, IndexedSeq); + + function Range(start, end, step) { + if (!(this instanceof Range)) { + return new Range(start, end, step); + } + invariant(step !== 0, 'Cannot step a Range by 0'); + start = start || 0; + if (end === undefined) { + end = Infinity; + } + step = step === undefined ? 1 : Math.abs(step); + if (end < start) { + step = -step; + } + this._start = start; + this._end = end; + this._step = step; + this.size = Math.max(0, Math.ceil((end - start) / step - 1) + 1); + if (this.size === 0) { + if (EMPTY_RANGE) { + return EMPTY_RANGE; + } + EMPTY_RANGE = this; + } + } + + Range.prototype.toString = function() { + if (this.size === 0) { + return 'Range []'; + } + return 'Range [ ' + + this._start + '...' + this._end + + (this._step > 1 ? ' by ' + this._step : '') + + ' ]'; + }; + + Range.prototype.get = function(index, notSetValue) { + return this.has(index) ? + this._start + wrapIndex(this, index) * this._step : + notSetValue; + }; + + Range.prototype.contains = function(searchValue) { + var possibleIndex = (searchValue - this._start) / this._step; + return possibleIndex >= 0 && + possibleIndex < this.size && + possibleIndex === Math.floor(possibleIndex); + }; + + Range.prototype.slice = function(begin, end) { + if (wholeSlice(begin, end, this.size)) { + return this; + } + begin = resolveBegin(begin, this.size); + end = resolveEnd(end, this.size); + if (end <= begin) { + return new Range(0, 0); + } + return new Range(this.get(begin, this._end), this.get(end, this._end), this._step); + }; + + Range.prototype.indexOf = function(searchValue) { + var offsetValue = searchValue - this._start; + if (offsetValue % this._step === 0) { + var index = offsetValue / this._step; + if (index >= 0 && index < this.size) { + return index + } + } + return -1; + }; + + Range.prototype.lastIndexOf = function(searchValue) { + return this.indexOf(searchValue); + }; + + Range.prototype.__iterate = function(fn, reverse) { + var maxIndex = this.size - 1; + var step = this._step; + var value = reverse ? this._start + maxIndex * step : this._start; + for (var ii = 0; ii <= maxIndex; ii++) { + if (fn(value, ii, this) === false) { + return ii + 1; + } + value += reverse ? -step : step; + } + return ii; + }; + + Range.prototype.__iterator = function(type, reverse) { + var maxIndex = this.size - 1; + var step = this._step; + var value = reverse ? this._start + maxIndex * step : this._start; + var ii = 0; + return new Iterator(function() { + var v = value; + value += reverse ? -step : step; + return ii > maxIndex ? iteratorDone() : iteratorValue(type, ii++, v); + }); + }; + + Range.prototype.equals = function(other) { + return other instanceof Range ? + this._start === other._start && + this._end === other._end && + this._step === other._step : + deepEqual(this, other); + }; + + + var EMPTY_RANGE; + + createClass(Repeat, IndexedSeq); + + function Repeat(value, times) { + if (!(this instanceof Repeat)) { + return new Repeat(value, times); + } + this._value = value; + this.size = times === undefined ? Infinity : Math.max(0, times); + if (this.size === 0) { + if (EMPTY_REPEAT) { + return EMPTY_REPEAT; + } + EMPTY_REPEAT = this; + } + } + + Repeat.prototype.toString = function() { + if (this.size === 0) { + return 'Repeat []'; + } + return 'Repeat [ ' + this._value + ' ' + this.size + ' times ]'; + }; + + Repeat.prototype.get = function(index, notSetValue) { + return this.has(index) ? this._value : notSetValue; + }; + + Repeat.prototype.contains = function(searchValue) { + return is(this._value, searchValue); + }; + + Repeat.prototype.slice = function(begin, end) { + var size = this.size; + return wholeSlice(begin, end, size) ? this : + new Repeat(this._value, resolveEnd(end, size) - resolveBegin(begin, size)); + }; + + Repeat.prototype.reverse = function() { + return this; + }; + + Repeat.prototype.indexOf = function(searchValue) { + if (is(this._value, searchValue)) { + return 0; + } + return -1; + }; + + Repeat.prototype.lastIndexOf = function(searchValue) { + if (is(this._value, searchValue)) { + return this.size; + } + return -1; + }; + + Repeat.prototype.__iterate = function(fn, reverse) { + for (var ii = 0; ii < this.size; ii++) { + if (fn(this._value, ii, this) === false) { + return ii + 1; + } + } + return ii; + }; + + Repeat.prototype.__iterator = function(type, reverse) {var this$0 = this; + var ii = 0; + return new Iterator(function() + {return ii < this$0.size ? iteratorValue(type, ii++, this$0._value) : iteratorDone()} + ); + }; + + Repeat.prototype.equals = function(other) { + return other instanceof Repeat ? + is(this._value, other._value) : + deepEqual(other); + }; + + + var EMPTY_REPEAT; + + /** + * Contributes additional methods to a constructor + */ + function mixin(ctor, methods) { + var keyCopier = function(key ) { ctor.prototype[key] = methods[key]; }; + Object.keys(methods).forEach(keyCopier); + Object.getOwnPropertySymbols && + Object.getOwnPropertySymbols(methods).forEach(keyCopier); + return ctor; + } + + Iterable.Iterator = Iterator; + + mixin(Iterable, { + + // ### Conversion to other types + + toArray: function() { + assertNotInfinite(this.size); + var array = new Array(this.size || 0); + this.valueSeq().__iterate(function(v, i) { array[i] = v; }); + return array; + }, + + toIndexedSeq: function() { + return new ToIndexedSequence(this); + }, + + toJS: function() { + return this.toSeq().map( + function(value ) {return value && typeof value.toJS === 'function' ? value.toJS() : value} + ).__toJS(); + }, + + toJSON: function() { + return this.toSeq().map( + function(value ) {return value && typeof value.toJSON === 'function' ? value.toJSON() : value} + ).__toJS(); + }, + + toKeyedSeq: function() { + return new ToKeyedSequence(this, true); + }, + + toMap: function() { + // Use Late Binding here to solve the circular dependency. + return Map(this.toKeyedSeq()); + }, + + toObject: function() { + assertNotInfinite(this.size); + var object = {}; + this.__iterate(function(v, k) { object[k] = v; }); + return object; + }, + + toOrderedMap: function() { + // Use Late Binding here to solve the circular dependency. + return OrderedMap(this.toKeyedSeq()); + }, + + toOrderedSet: function() { + // Use Late Binding here to solve the circular dependency. + return OrderedSet(isKeyed(this) ? this.valueSeq() : this); + }, + + toSet: function() { + // Use Late Binding here to solve the circular dependency. + return Set(isKeyed(this) ? this.valueSeq() : this); + }, + + toSetSeq: function() { + return new ToSetSequence(this); + }, + + toSeq: function() { + return isIndexed(this) ? this.toIndexedSeq() : + isKeyed(this) ? this.toKeyedSeq() : + this.toSetSeq(); + }, + + toStack: function() { + // Use Late Binding here to solve the circular dependency. + return Stack(isKeyed(this) ? this.valueSeq() : this); + }, + + toList: function() { + // Use Late Binding here to solve the circular dependency. + return List(isKeyed(this) ? this.valueSeq() : this); + }, + + + // ### Common JavaScript methods and properties + + toString: function() { + return '[Iterable]'; + }, + + __toString: function(head, tail) { + if (this.size === 0) { + return head + tail; + } + return head + ' ' + this.toSeq().map(this.__toStringMapper).join(', ') + ' ' + tail; + }, + + + // ### ES6 Collection methods (ES6 Array and Map) + + concat: function() {var values = SLICE$0.call(arguments, 0); + return reify(this, concatFactory(this, values)); + }, + + contains: function(searchValue) { + return this.some(function(value ) {return is(value, searchValue)}); + }, + + entries: function() { + return this.__iterator(ITERATE_ENTRIES); + }, + + every: function(predicate, context) { + assertNotInfinite(this.size); + var returnValue = true; + this.__iterate(function(v, k, c) { + if (!predicate.call(context, v, k, c)) { + returnValue = false; + return false; + } + }); + return returnValue; + }, + + filter: function(predicate, context) { + return reify(this, filterFactory(this, predicate, context, true)); + }, + + find: function(predicate, context, notSetValue) { + var entry = this.findEntry(predicate, context); + return entry ? entry[1] : notSetValue; + }, + + findEntry: function(predicate, context) { + var found; + this.__iterate(function(v, k, c) { + if (predicate.call(context, v, k, c)) { + found = [k, v]; + return false; + } + }); + return found; + }, + + findLastEntry: function(predicate, context) { + return this.toSeq().reverse().findEntry(predicate, context); + }, + + forEach: function(sideEffect, context) { + assertNotInfinite(this.size); + return this.__iterate(context ? sideEffect.bind(context) : sideEffect); + }, + + join: function(separator) { + assertNotInfinite(this.size); + separator = separator !== undefined ? '' + separator : ','; + var joined = ''; + var isFirst = true; + this.__iterate(function(v ) { + isFirst ? (isFirst = false) : (joined += separator); + joined += v !== null && v !== undefined ? v.toString() : ''; + }); + return joined; + }, + + keys: function() { + return this.__iterator(ITERATE_KEYS); + }, + + map: function(mapper, context) { + return reify(this, mapFactory(this, mapper, context)); + }, + + reduce: function(reducer, initialReduction, context) { + assertNotInfinite(this.size); + var reduction; + var useFirst; + if (arguments.length < 2) { + useFirst = true; + } else { + reduction = initialReduction; + } + this.__iterate(function(v, k, c) { + if (useFirst) { + useFirst = false; + reduction = v; + } else { + reduction = reducer.call(context, reduction, v, k, c); + } + }); + return reduction; + }, + + reduceRight: function(reducer, initialReduction, context) { + var reversed = this.toKeyedSeq().reverse(); + return reversed.reduce.apply(reversed, arguments); + }, + + reverse: function() { + return reify(this, reverseFactory(this, true)); + }, + + slice: function(begin, end) { + return reify(this, sliceFactory(this, begin, end, true)); + }, + + some: function(predicate, context) { + return !this.every(not(predicate), context); + }, + + sort: function(comparator) { + return reify(this, sortFactory(this, comparator)); + }, + + values: function() { + return this.__iterator(ITERATE_VALUES); + }, + + + // ### More sequential methods + + butLast: function() { + return this.slice(0, -1); + }, + + isEmpty: function() { + return this.size !== undefined ? this.size === 0 : !this.some(function() {return true}); + }, + + count: function(predicate, context) { + return ensureSize( + predicate ? this.toSeq().filter(predicate, context) : this + ); + }, + + countBy: function(grouper, context) { + return countByFactory(this, grouper, context); + }, + + equals: function(other) { + return deepEqual(this, other); + }, + + entrySeq: function() { + var iterable = this; + if (iterable._cache) { + // We cache as an entries array, so we can just return the cache! + return new ArraySeq(iterable._cache); + } + var entriesSequence = iterable.toSeq().map(entryMapper).toIndexedSeq(); + entriesSequence.fromEntrySeq = function() {return iterable.toSeq()}; + return entriesSequence; + }, + + filterNot: function(predicate, context) { + return this.filter(not(predicate), context); + }, + + findLast: function(predicate, context, notSetValue) { + return this.toKeyedSeq().reverse().find(predicate, context, notSetValue); + }, + + first: function() { + return this.find(returnTrue); + }, + + flatMap: function(mapper, context) { + return reify(this, flatMapFactory(this, mapper, context)); + }, + + flatten: function(depth) { + return reify(this, flattenFactory(this, depth, true)); + }, + + fromEntrySeq: function() { + return new FromEntriesSequence(this); + }, + + get: function(searchKey, notSetValue) { + return this.find(function(_, key) {return is(key, searchKey)}, undefined, notSetValue); + }, + + getIn: function(searchKeyPath, notSetValue) { + var nested = this; + // Note: in an ES6 environment, we would prefer: + // for (var key of searchKeyPath) { + var iter = forceIterator(searchKeyPath); + var step; + while (!(step = iter.next()).done) { + var key = step.value; + nested = nested && nested.get ? nested.get(key, NOT_SET) : NOT_SET; + if (nested === NOT_SET) { + return notSetValue; + } + } + return nested; + }, + + groupBy: function(grouper, context) { + return groupByFactory(this, grouper, context); + }, + + has: function(searchKey) { + return this.get(searchKey, NOT_SET) !== NOT_SET; + }, + + hasIn: function(searchKeyPath) { + return this.getIn(searchKeyPath, NOT_SET) !== NOT_SET; + }, + + isSubset: function(iter) { + iter = typeof iter.contains === 'function' ? iter : Iterable(iter); + return this.every(function(value ) {return iter.contains(value)}); + }, + + isSuperset: function(iter) { + return iter.isSubset(this); + }, + + keySeq: function() { + return this.toSeq().map(keyMapper).toIndexedSeq(); + }, + + last: function() { + return this.toSeq().reverse().first(); + }, + + max: function(comparator) { + return maxFactory(this, comparator); + }, + + maxBy: function(mapper, comparator) { + return maxFactory(this, comparator, mapper); + }, + + min: function(comparator) { + return maxFactory(this, comparator ? neg(comparator) : defaultNegComparator); + }, + + minBy: function(mapper, comparator) { + return maxFactory(this, comparator ? neg(comparator) : defaultNegComparator, mapper); + }, + + rest: function() { + return this.slice(1); + }, + + skip: function(amount) { + return this.slice(Math.max(0, amount)); + }, + + skipLast: function(amount) { + return reify(this, this.toSeq().reverse().skip(amount).reverse()); + }, + + skipWhile: function(predicate, context) { + return reify(this, skipWhileFactory(this, predicate, context, true)); + }, + + skipUntil: function(predicate, context) { + return this.skipWhile(not(predicate), context); + }, + + sortBy: function(mapper, comparator) { + return reify(this, sortFactory(this, comparator, mapper)); + }, + + take: function(amount) { + return this.slice(0, Math.max(0, amount)); + }, + + takeLast: function(amount) { + return reify(this, this.toSeq().reverse().take(amount).reverse()); + }, + + takeWhile: function(predicate, context) { + return reify(this, takeWhileFactory(this, predicate, context)); + }, + + takeUntil: function(predicate, context) { + return this.takeWhile(not(predicate), context); + }, + + valueSeq: function() { + return this.toIndexedSeq(); + }, + + + // ### Hashable Object + + hashCode: function() { + return this.__hash || (this.__hash = hashIterable(this)); + }, + + + // ### Internal + + // abstract __iterate(fn, reverse) + + // abstract __iterator(type, reverse) + }); + + // var IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@'; + // var IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@'; + // var IS_INDEXED_SENTINEL = '@@__IMMUTABLE_INDEXED__@@'; + // var IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@'; + + var IterablePrototype = Iterable.prototype; + IterablePrototype[IS_ITERABLE_SENTINEL] = true; + IterablePrototype[ITERATOR_SYMBOL] = IterablePrototype.values; + IterablePrototype.__toJS = IterablePrototype.toArray; + IterablePrototype.__toStringMapper = quoteString; + IterablePrototype.inspect = + IterablePrototype.toSource = function() { return this.toString(); }; + IterablePrototype.chain = IterablePrototype.flatMap; + + // Temporary warning about using length + (function () { + try { + Object.defineProperty(IterablePrototype, 'length', { + get: function () { + if (!Iterable.noLengthWarning) { + var stack; + try { + throw new Error(); + } catch (error) { + stack = error.stack; + } + if (stack.indexOf('_wrapObject') === -1) { + console && console.warn && console.warn( + 'iterable.length has been deprecated, '+ + 'use iterable.size or iterable.count(). '+ + 'This warning will become a silent error in a future version. ' + + stack + ); + return this.size; + } + } + } + }); + } catch (e) {} + })(); + + + + mixin(KeyedIterable, { + + // ### More sequential methods + + flip: function() { + return reify(this, flipFactory(this)); + }, + + findKey: function(predicate, context) { + var entry = this.findEntry(predicate, context); + return entry && entry[0]; + }, + + findLastKey: function(predicate, context) { + return this.toSeq().reverse().findKey(predicate, context); + }, + + keyOf: function(searchValue) { + return this.findKey(function(value ) {return is(value, searchValue)}); + }, + + lastKeyOf: function(searchValue) { + return this.findLastKey(function(value ) {return is(value, searchValue)}); + }, + + mapEntries: function(mapper, context) {var this$0 = this; + var iterations = 0; + return reify(this, + this.toSeq().map( + function(v, k) {return mapper.call(context, [k, v], iterations++, this$0)} + ).fromEntrySeq() + ); + }, + + mapKeys: function(mapper, context) {var this$0 = this; + return reify(this, + this.toSeq().flip().map( + function(k, v) {return mapper.call(context, k, v, this$0)} + ).flip() + ); + }, + + }); + + var KeyedIterablePrototype = KeyedIterable.prototype; + KeyedIterablePrototype[IS_KEYED_SENTINEL] = true; + KeyedIterablePrototype[ITERATOR_SYMBOL] = IterablePrototype.entries; + KeyedIterablePrototype.__toJS = IterablePrototype.toObject; + KeyedIterablePrototype.__toStringMapper = function(v, k) {return k + ': ' + quoteString(v)}; + + + + mixin(IndexedIterable, { + + // ### Conversion to other types + + toKeyedSeq: function() { + return new ToKeyedSequence(this, false); + }, + + + // ### ES6 Collection methods (ES6 Array and Map) + + filter: function(predicate, context) { + return reify(this, filterFactory(this, predicate, context, false)); + }, + + findIndex: function(predicate, context) { + var entry = this.findEntry(predicate, context); + return entry ? entry[0] : -1; + }, + + indexOf: function(searchValue) { + var key = this.toKeyedSeq().keyOf(searchValue); + return key === undefined ? -1 : key; + }, + + lastIndexOf: function(searchValue) { + return this.toSeq().reverse().indexOf(searchValue); + }, + + reverse: function() { + return reify(this, reverseFactory(this, false)); + }, + + slice: function(begin, end) { + return reify(this, sliceFactory(this, begin, end, false)); + }, + + splice: function(index, removeNum /*, ...values*/) { + var numArgs = arguments.length; + removeNum = Math.max(removeNum | 0, 0); + if (numArgs === 0 || (numArgs === 2 && !removeNum)) { + return this; + } + index = resolveBegin(index, this.size); + var spliced = this.slice(0, index); + return reify( + this, + numArgs === 1 ? + spliced : + spliced.concat(arrCopy(arguments, 2), this.slice(index + removeNum)) + ); + }, + + + // ### More collection methods + + findLastIndex: function(predicate, context) { + var key = this.toKeyedSeq().findLastKey(predicate, context); + return key === undefined ? -1 : key; + }, + + first: function() { + return this.get(0); + }, + + flatten: function(depth) { + return reify(this, flattenFactory(this, depth, false)); + }, + + get: function(index, notSetValue) { + index = wrapIndex(this, index); + return (index < 0 || (this.size === Infinity || + (this.size !== undefined && index > this.size))) ? + notSetValue : + this.find(function(_, key) {return key === index}, undefined, notSetValue); + }, + + has: function(index) { + index = wrapIndex(this, index); + return index >= 0 && (this.size !== undefined ? + this.size === Infinity || index < this.size : + this.indexOf(index) !== -1 + ); + }, + + interpose: function(separator) { + return reify(this, interposeFactory(this, separator)); + }, + + interleave: function(/*...iterables*/) { + var iterables = [this].concat(arrCopy(arguments)); + var zipped = zipWithFactory(this.toSeq(), IndexedSeq.of, iterables); + var interleaved = zipped.flatten(true); + if (zipped.size) { + interleaved.size = zipped.size * iterables.length; + } + return reify(this, interleaved); + }, + + last: function() { + return this.get(-1); + }, + + skipWhile: function(predicate, context) { + return reify(this, skipWhileFactory(this, predicate, context, false)); + }, + + zip: function(/*, ...iterables */) { + var iterables = [this].concat(arrCopy(arguments)); + return reify(this, zipWithFactory(this, defaultZipper, iterables)); + }, + + zipWith: function(zipper/*, ...iterables */) { + var iterables = arrCopy(arguments); + iterables[0] = this; + return reify(this, zipWithFactory(this, zipper, iterables)); + }, + + }); + + IndexedIterable.prototype[IS_INDEXED_SENTINEL] = true; + IndexedIterable.prototype[IS_ORDERED_SENTINEL] = true; + + + + mixin(SetIterable, { + + // ### ES6 Collection methods (ES6 Array and Map) + + get: function(value, notSetValue) { + return this.has(value) ? value : notSetValue; + }, + + contains: function(value) { + return this.has(value); + }, + + + // ### More sequential methods + + keySeq: function() { + return this.valueSeq(); + }, + + }); + + SetIterable.prototype.has = IterablePrototype.contains; + + + // Mixin subclasses + + mixin(KeyedSeq, KeyedIterable.prototype); + mixin(IndexedSeq, IndexedIterable.prototype); + mixin(SetSeq, SetIterable.prototype); + + mixin(KeyedCollection, KeyedIterable.prototype); + mixin(IndexedCollection, IndexedIterable.prototype); + mixin(SetCollection, SetIterable.prototype); + + + // #pragma Helper functions + + function keyMapper(v, k) { + return k; + } + + function entryMapper(v, k) { + return [k, v]; + } + + function not(predicate) { + return function() { + return !predicate.apply(this, arguments); + } + } + + function neg(predicate) { + return function() { + return -predicate.apply(this, arguments); + } + } + + function quoteString(value) { + return typeof value === 'string' ? JSON.stringify(value) : value; + } + + function defaultZipper() { + return arrCopy(arguments); + } + + function defaultNegComparator(a, b) { + return a < b ? 1 : a > b ? -1 : 0; + } + + function hashIterable(iterable) { + if (iterable.size === Infinity) { + return 0; + } + var ordered = isOrdered(iterable); + var keyed = isKeyed(iterable); + var h = ordered ? 1 : 0; + var size = iterable.__iterate( + keyed ? + ordered ? + function(v, k) { h = 31 * h + hashMerge(hash(v), hash(k)) | 0; } : + function(v, k) { h = h + hashMerge(hash(v), hash(k)) | 0; } : + ordered ? + function(v ) { h = 31 * h + hash(v) | 0; } : + function(v ) { h = h + hash(v) | 0; } + ); + return murmurHashOfSize(size, h); + } + + function murmurHashOfSize(size, h) { + h = Math__imul(h, 0xCC9E2D51); + h = Math__imul(h << 15 | h >>> -15, 0x1B873593); + h = Math__imul(h << 13 | h >>> -13, 5); + h = (h + 0xE6546B64 | 0) ^ size; + h = Math__imul(h ^ h >>> 16, 0x85EBCA6B); + h = Math__imul(h ^ h >>> 13, 0xC2B2AE35); + h = smi(h ^ h >>> 16); + return h; + } + + function hashMerge(a, b) { + return a ^ b + 0x9E3779B9 + (a << 6) + (a >> 2) | 0; // int + } + + var Immutable = { + + Iterable: Iterable, + + Seq: Seq, + Collection: Collection, + Map: Map, + OrderedMap: OrderedMap, + List: List, + Stack: Stack, + Set: Set, + OrderedSet: OrderedSet, + + Record: Record, + Range: Range, + Repeat: Repeat, + + is: is, + fromJS: fromJS, + + }; + + return Immutable; + +})); \ No newline at end of file diff --git a/_themes/odoodoc/sphinx_monkeypatch.py b/_themes/odoodoc/sphinx_monkeypatch.py index 182fef89c..5bce9c9a1 100644 --- a/_themes/odoodoc/sphinx_monkeypatch.py +++ b/_themes/odoodoc/sphinx_monkeypatch.py @@ -68,8 +68,13 @@ def visit_table(self, node): self._table_row_index = 0 self.context.append(self.compact_p) self.compact_p = True - classes = ' '.join({'table', self.settings.table_style}).strip() - self.body.append(self.starttag(node, 'table', CLASS=classes)) + + classes = {self.settings.table_style} + node_classes = node.get('classes', []) + if 'no-table' in node_classes: node_classes.remove('no-table') + else: classes.add('table') + + self.body.append(self.starttag(node, 'table', CLASS=' '.join(classes).strip())) def starttag_data(self, node, tagname, suffix='\n', empty=False, **attributes): attributes.update( diff --git a/_themes/odoodoc/static/odoodoc.css_t b/_themes/odoodoc/static/odoodoc.css_t index a70db9fb8..64a14dc61 100644 --- a/_themes/odoodoc/static/odoodoc.css_t +++ b/_themes/odoodoc/static/odoodoc.css_t @@ -1 +1 @@ -@import "style.css"; +@import url("style.css"); diff --git a/_themes/odoodoc/static/style.css b/_themes/odoodoc/static/style.css index df3551b15..985c9d1dd 100644 --- a/_themes/odoodoc/static/style.css +++ b/_themes/odoodoc/static/style.css @@ -6811,58 +6811,58 @@ td.field-body > ul { margin-bottom: 2em; } @media (min-width: 992px) { - .stripe .section > *, - .stripe .section > .force-left { + .stripe .section:not(.force-right) > *, + .stripe .section:not(.force-right) > .force-left { width: 49%; float: left; clear: left; } - .stripe .section > .force-right { + .stripe .section:not(.force-right) > .force-right { padding-left: 1em; padding-right: 1em; } - .stripe .section > .force-right, - .stripe .section > [class*=highlight] { + .stripe .section:not(.force-right) > .force-right, + .stripe .section:not(.force-right) > [class*=highlight] { float: none; clear: none; margin-left: 50%; width: 50%; color: #eeeeee; } - .stripe .section > .force-right legend, - .stripe .section > [class*=highlight] legend { + .stripe .section:not(.force-right) > .force-right legend, + .stripe .section:not(.force-right) > [class*=highlight] legend { color: inherit; } - .stripe .section > .force-right input, - .stripe .section > [class*=highlight] input { + .stripe .section:not(.force-right) > .force-right input, + .stripe .section:not(.force-right) > [class*=highlight] input { color: inherit; background-color: #555555; } - .stripe .section > .force-right a, - .stripe .section > [class*=highlight] a { + .stripe .section:not(.force-right) > .force-right a, + .stripe .section:not(.force-right) > [class*=highlight] a { color: #d9a8cc; } - .stripe .section > .force-right code, - .stripe .section > [class*=highlight] code, - .stripe .section > .force-right .literal, - .stripe .section > [class*=highlight] .literal { + .stripe .section:not(.force-right) > .force-right code, + .stripe .section:not(.force-right) > [class*=highlight] code, + .stripe .section:not(.force-right) > .force-right .literal, + .stripe .section:not(.force-right) > [class*=highlight] .literal { color: #f9f2f4; background-color: #555555; } - .stripe .section > .force-right:not(.highlight-json) .highlight, - .stripe .section > [class*=highlight]:not(.highlight-json) .highlight { + .stripe .section:not(.force-right) > .force-right:not(.highlight-json) .highlight, + .stripe .section:not(.force-right) > [class*=highlight]:not(.highlight-json) .highlight { border-bottom-color: #777777; } - .stripe .section > .force-right.admonition, - .stripe .section > [class*=highlight].admonition { + .stripe .section:not(.force-right) > .force-right.admonition, + .stripe .section:not(.force-right) > [class*=highlight].admonition { margin-left: 51%; width: 49%; border-top-color: #777777; border-bottom-color: #777777; border-right-color: #777777; } - .stripe .section > .force-right .highlight, - .stripe .section > [class*=highlight] .highlight { + .stripe .section:not(.force-right) > .force-right .highlight, + .stripe .section:not(.force-right) > [class*=highlight] .highlight { border-color: #555555; border-style: solid; border-width: 1px 0; @@ -6939,302 +6939,302 @@ td.field-body > ul { /* Name.Variable.Instance */ /* Literal.Number.Integer.Long */ } - .stripe .section > .force-right .highlight .lineno, - .stripe .section > [class*=highlight] .highlight .lineno { + .stripe .section:not(.force-right) > .force-right .highlight .lineno, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .lineno { color: #586e75; } - .stripe .section > .force-right .highlight .c, - .stripe .section > [class*=highlight] .highlight .c { + .stripe .section:not(.force-right) > .force-right .highlight .c, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .c { color: #586e75; } - .stripe .section > .force-right .highlight .err, - .stripe .section > [class*=highlight] .highlight .err { + .stripe .section:not(.force-right) > .force-right .highlight .err, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .err { color: #cccccc; } - .stripe .section > .force-right .highlight .g, - .stripe .section > [class*=highlight] .highlight .g { + .stripe .section:not(.force-right) > .force-right .highlight .g, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .g { color: #cccccc; } - .stripe .section > .force-right .highlight .k, - .stripe .section > [class*=highlight] .highlight .k { + .stripe .section:not(.force-right) > .force-right .highlight .k, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .k { color: #859900; } - .stripe .section > .force-right .highlight .l, - .stripe .section > [class*=highlight] .highlight .l { + .stripe .section:not(.force-right) > .force-right .highlight .l, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .l { color: #cccccc; } - .stripe .section > .force-right .highlight .n, - .stripe .section > [class*=highlight] .highlight .n { + .stripe .section:not(.force-right) > .force-right .highlight .n, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .n { color: #cccccc; } - .stripe .section > .force-right .highlight .o, - .stripe .section > [class*=highlight] .highlight .o { + .stripe .section:not(.force-right) > .force-right .highlight .o, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .o { color: #859900; } - .stripe .section > .force-right .highlight .x, - .stripe .section > [class*=highlight] .highlight .x { + .stripe .section:not(.force-right) > .force-right .highlight .x, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .x { color: #cb4b16; } - .stripe .section > .force-right .highlight .p, - .stripe .section > [class*=highlight] .highlight .p { + .stripe .section:not(.force-right) > .force-right .highlight .p, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .p { color: #cccccc; } - .stripe .section > .force-right .highlight .cm, - .stripe .section > [class*=highlight] .highlight .cm { + .stripe .section:not(.force-right) > .force-right .highlight .cm, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .cm { color: #586e75; } - .stripe .section > .force-right .highlight .cp, - .stripe .section > [class*=highlight] .highlight .cp { + .stripe .section:not(.force-right) > .force-right .highlight .cp, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .cp { color: #859900; } - .stripe .section > .force-right .highlight .c1, - .stripe .section > [class*=highlight] .highlight .c1 { + .stripe .section:not(.force-right) > .force-right .highlight .c1, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .c1 { color: #586e75; } - .stripe .section > .force-right .highlight .cs, - .stripe .section > [class*=highlight] .highlight .cs { + .stripe .section:not(.force-right) > .force-right .highlight .cs, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .cs { color: #859900; } - .stripe .section > .force-right .highlight .gd, - .stripe .section > [class*=highlight] .highlight .gd { + .stripe .section:not(.force-right) > .force-right .highlight .gd, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .gd { color: #2aa198; } - .stripe .section > .force-right .highlight .ge, - .stripe .section > [class*=highlight] .highlight .ge { + .stripe .section:not(.force-right) > .force-right .highlight .ge, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .ge { color: #cccccc; font-style: italic; } - .stripe .section > .force-right .highlight .gr, - .stripe .section > [class*=highlight] .highlight .gr { + .stripe .section:not(.force-right) > .force-right .highlight .gr, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .gr { color: #dc322f; } - .stripe .section > .force-right .highlight .gh, - .stripe .section > [class*=highlight] .highlight .gh { + .stripe .section:not(.force-right) > .force-right .highlight .gh, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .gh { color: #cb4b16; } - .stripe .section > .force-right .highlight .gi, - .stripe .section > [class*=highlight] .highlight .gi { + .stripe .section:not(.force-right) > .force-right .highlight .gi, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .gi { color: #859900; } - .stripe .section > .force-right .highlight .go, - .stripe .section > [class*=highlight] .highlight .go { + .stripe .section:not(.force-right) > .force-right .highlight .go, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .go { color: #cccccc; } - .stripe .section > .force-right .highlight .gp, - .stripe .section > [class*=highlight] .highlight .gp { + .stripe .section:not(.force-right) > .force-right .highlight .gp, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .gp { color: #cccccc; } - .stripe .section > .force-right .highlight .gs, - .stripe .section > [class*=highlight] .highlight .gs { + .stripe .section:not(.force-right) > .force-right .highlight .gs, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .gs { color: #cccccc; font-weight: bold; } - .stripe .section > .force-right .highlight .gu, - .stripe .section > [class*=highlight] .highlight .gu { + .stripe .section:not(.force-right) > .force-right .highlight .gu, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .gu { color: #cb4b16; } - .stripe .section > .force-right .highlight .gt, - .stripe .section > [class*=highlight] .highlight .gt { + .stripe .section:not(.force-right) > .force-right .highlight .gt, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .gt { color: #cccccc; } - .stripe .section > .force-right .highlight .kc, - .stripe .section > [class*=highlight] .highlight .kc { + .stripe .section:not(.force-right) > .force-right .highlight .kc, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .kc { color: #cb4b16; } - .stripe .section > .force-right .highlight .kd, - .stripe .section > [class*=highlight] .highlight .kd { + .stripe .section:not(.force-right) > .force-right .highlight .kd, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .kd { color: #268bd2; } - .stripe .section > .force-right .highlight .kn, - .stripe .section > [class*=highlight] .highlight .kn { + .stripe .section:not(.force-right) > .force-right .highlight .kn, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .kn { color: #859900; } - .stripe .section > .force-right .highlight .kp, - .stripe .section > [class*=highlight] .highlight .kp { + .stripe .section:not(.force-right) > .force-right .highlight .kp, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .kp { color: #859900; } - .stripe .section > .force-right .highlight .kr, - .stripe .section > [class*=highlight] .highlight .kr { + .stripe .section:not(.force-right) > .force-right .highlight .kr, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .kr { color: #268bd2; } - .stripe .section > .force-right .highlight .kt, - .stripe .section > [class*=highlight] .highlight .kt { + .stripe .section:not(.force-right) > .force-right .highlight .kt, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .kt { color: #dc322f; } - .stripe .section > .force-right .highlight .ld, - .stripe .section > [class*=highlight] .highlight .ld { + .stripe .section:not(.force-right) > .force-right .highlight .ld, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .ld { color: #cccccc; } - .stripe .section > .force-right .highlight .m, - .stripe .section > [class*=highlight] .highlight .m { + .stripe .section:not(.force-right) > .force-right .highlight .m, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .m { color: #2aa198; } - .stripe .section > .force-right .highlight .s, - .stripe .section > [class*=highlight] .highlight .s { + .stripe .section:not(.force-right) > .force-right .highlight .s, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .s { color: #2aa198; } - .stripe .section > .force-right .highlight .na, - .stripe .section > [class*=highlight] .highlight .na { + .stripe .section:not(.force-right) > .force-right .highlight .na, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .na { color: #cccccc; } - .stripe .section > .force-right .highlight .nb, - .stripe .section > [class*=highlight] .highlight .nb { + .stripe .section:not(.force-right) > .force-right .highlight .nb, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .nb { color: #b58900; } - .stripe .section > .force-right .highlight .nc, - .stripe .section > [class*=highlight] .highlight .nc { + .stripe .section:not(.force-right) > .force-right .highlight .nc, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .nc { color: #268bd2; } - .stripe .section > .force-right .highlight .no, - .stripe .section > [class*=highlight] .highlight .no { + .stripe .section:not(.force-right) > .force-right .highlight .no, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .no { color: #cb4b16; } - .stripe .section > .force-right .highlight .nd, - .stripe .section > [class*=highlight] .highlight .nd { + .stripe .section:not(.force-right) > .force-right .highlight .nd, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .nd { color: #268bd2; } - .stripe .section > .force-right .highlight .ni, - .stripe .section > [class*=highlight] .highlight .ni { + .stripe .section:not(.force-right) > .force-right .highlight .ni, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .ni { color: #cb4b16; } - .stripe .section > .force-right .highlight .ne, - .stripe .section > [class*=highlight] .highlight .ne { + .stripe .section:not(.force-right) > .force-right .highlight .ne, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .ne { color: #cb4b16; } - .stripe .section > .force-right .highlight .nf, - .stripe .section > [class*=highlight] .highlight .nf { + .stripe .section:not(.force-right) > .force-right .highlight .nf, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .nf { color: #268bd2; } - .stripe .section > .force-right .highlight .nl, - .stripe .section > [class*=highlight] .highlight .nl { + .stripe .section:not(.force-right) > .force-right .highlight .nl, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .nl { color: #cccccc; } - .stripe .section > .force-right .highlight .nn, - .stripe .section > [class*=highlight] .highlight .nn { + .stripe .section:not(.force-right) > .force-right .highlight .nn, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .nn { color: #cccccc; } - .stripe .section > .force-right .highlight .nx, - .stripe .section > [class*=highlight] .highlight .nx { + .stripe .section:not(.force-right) > .force-right .highlight .nx, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .nx { color: #cccccc; } - .stripe .section > .force-right .highlight .py, - .stripe .section > [class*=highlight] .highlight .py { + .stripe .section:not(.force-right) > .force-right .highlight .py, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .py { color: #cccccc; } - .stripe .section > .force-right .highlight .nt, - .stripe .section > [class*=highlight] .highlight .nt { + .stripe .section:not(.force-right) > .force-right .highlight .nt, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .nt { color: #268bd2; } - .stripe .section > .force-right .highlight .nv, - .stripe .section > [class*=highlight] .highlight .nv { + .stripe .section:not(.force-right) > .force-right .highlight .nv, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .nv { color: #268bd2; } - .stripe .section > .force-right .highlight .ow, - .stripe .section > [class*=highlight] .highlight .ow { + .stripe .section:not(.force-right) > .force-right .highlight .ow, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .ow { color: #859900; } - .stripe .section > .force-right .highlight .w, - .stripe .section > [class*=highlight] .highlight .w { + .stripe .section:not(.force-right) > .force-right .highlight .w, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .w { color: #cccccc; } - .stripe .section > .force-right .highlight .mf, - .stripe .section > [class*=highlight] .highlight .mf { + .stripe .section:not(.force-right) > .force-right .highlight .mf, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .mf { color: #2aa198; } - .stripe .section > .force-right .highlight .mh, - .stripe .section > [class*=highlight] .highlight .mh { + .stripe .section:not(.force-right) > .force-right .highlight .mh, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .mh { color: #2aa198; } - .stripe .section > .force-right .highlight .mi, - .stripe .section > [class*=highlight] .highlight .mi { + .stripe .section:not(.force-right) > .force-right .highlight .mi, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .mi { color: #2aa198; } - .stripe .section > .force-right .highlight .mo, - .stripe .section > [class*=highlight] .highlight .mo { + .stripe .section:not(.force-right) > .force-right .highlight .mo, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .mo { color: #2aa198; } - .stripe .section > .force-right .highlight .sb, - .stripe .section > [class*=highlight] .highlight .sb { + .stripe .section:not(.force-right) > .force-right .highlight .sb, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .sb { color: #586e75; } - .stripe .section > .force-right .highlight .sc, - .stripe .section > [class*=highlight] .highlight .sc { + .stripe .section:not(.force-right) > .force-right .highlight .sc, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .sc { color: #2aa198; } - .stripe .section > .force-right .highlight .sd, - .stripe .section > [class*=highlight] .highlight .sd { + .stripe .section:not(.force-right) > .force-right .highlight .sd, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .sd { color: #cccccc; } - .stripe .section > .force-right .highlight .s2, - .stripe .section > [class*=highlight] .highlight .s2 { + .stripe .section:not(.force-right) > .force-right .highlight .s2, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .s2 { color: #2aa198; } - .stripe .section > .force-right .highlight .se, - .stripe .section > [class*=highlight] .highlight .se { + .stripe .section:not(.force-right) > .force-right .highlight .se, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .se { color: #cb4b16; } - .stripe .section > .force-right .highlight .sh, - .stripe .section > [class*=highlight] .highlight .sh { + .stripe .section:not(.force-right) > .force-right .highlight .sh, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .sh { color: #cccccc; } - .stripe .section > .force-right .highlight .si, - .stripe .section > [class*=highlight] .highlight .si { + .stripe .section:not(.force-right) > .force-right .highlight .si, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .si { color: #2aa198; } - .stripe .section > .force-right .highlight .sx, - .stripe .section > [class*=highlight] .highlight .sx { + .stripe .section:not(.force-right) > .force-right .highlight .sx, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .sx { color: #2aa198; } - .stripe .section > .force-right .highlight .sr, - .stripe .section > [class*=highlight] .highlight .sr { + .stripe .section:not(.force-right) > .force-right .highlight .sr, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .sr { color: #dc322f; } - .stripe .section > .force-right .highlight .s1, - .stripe .section > [class*=highlight] .highlight .s1 { + .stripe .section:not(.force-right) > .force-right .highlight .s1, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .s1 { color: #2aa198; } - .stripe .section > .force-right .highlight .ss, - .stripe .section > [class*=highlight] .highlight .ss { + .stripe .section:not(.force-right) > .force-right .highlight .ss, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .ss { color: #2aa198; } - .stripe .section > .force-right .highlight .bp, - .stripe .section > [class*=highlight] .highlight .bp { + .stripe .section:not(.force-right) > .force-right .highlight .bp, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .bp { color: #268bd2; } - .stripe .section > .force-right .highlight .vc, - .stripe .section > [class*=highlight] .highlight .vc { + .stripe .section:not(.force-right) > .force-right .highlight .vc, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .vc { color: #268bd2; } - .stripe .section > .force-right .highlight .vg, - .stripe .section > [class*=highlight] .highlight .vg { + .stripe .section:not(.force-right) > .force-right .highlight .vg, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .vg { color: #268bd2; } - .stripe .section > .force-right .highlight .vi, - .stripe .section > [class*=highlight] .highlight .vi { + .stripe .section:not(.force-right) > .force-right .highlight .vi, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .vi { color: #268bd2; } - .stripe .section > .force-right .highlight .il, - .stripe .section > [class*=highlight] .highlight .il { + .stripe .section:not(.force-right) > .force-right .highlight .il, + .stripe .section:not(.force-right) > [class*=highlight] .highlight .il { color: #2aa198; } .stripe .body > .section > .section { border-top: 1px solid #eeeeee; } - .stripe .section > h1, - .stripe .section > h2, - .stripe .section > h3, - .stripe .section > h4, - .stripe .section > h5, - .stripe .section > h6 { + .stripe .section:not(.force-right) > h1, + .stripe .section:not(.force-right) > h2, + .stripe .section:not(.force-right) > h3, + .stripe .section:not(.force-right) > h4, + .stripe .section:not(.force-right) > h5, + .stripe .section:not(.force-right) > h6 { max-width: 50%; } - .stripe .section > h1, - .stripe .section > h2, - .stripe .section > h3, - .stripe .section > h4, - .stripe .section > h5, - .stripe .section > h6, - .stripe .section > .section { + .stripe .section:not(.force-right) > h1, + .stripe .section:not(.force-right) > h2, + .stripe .section:not(.force-right) > h3, + .stripe .section:not(.force-right) > h4, + .stripe .section:not(.force-right) > h5, + .stripe .section:not(.force-right) > h6, + .stripe .section > .section:not(.force-right) { position: relative; width: auto; float: none; diff --git a/_themes/odoodoc/static/style.less b/_themes/odoodoc/static/style.less index 05617707d..bea588932 100644 --- a/_themes/odoodoc/static/style.less +++ b/_themes/odoodoc/static/style.less @@ -610,19 +610,19 @@ td.field-body { // === columning only on medium+ === @media (min-width: @screen-md-min) { // column 1 - .section > *, - .section > .force-left { + .section:not(.force-right) > *, + .section:not(.force-right) > .force-left { width: 49%; float: left; clear: left; } // column 2 - .section > .force-right { + .section:not(.force-right) > .force-right { padding-left: 1em; padding-right: 1em; } - .section > .force-right, - .section > [class*=highlight] { + .section:not(.force-right) > .force-right, + .section:not(.force-right) > [class*=highlight] { float: none; clear: none; margin-left: 50%; @@ -735,13 +735,16 @@ td.field-body { .body > .section > .section { border-top: 1px solid @color-right; } - .section > h1, .section > h2, .section > h3, .section > h4, .section > h5, - .section > h6 { + .section:not(.force-right) > h1, .section:not(.force-right) > h2, + .section:not(.force-right) > h3, .section:not(.force-right) > h4, + .section:not(.force-right) > h5, .section:not(.force-right) > h6 { max-width: 50%; } - .section > h1, .section > h2, .section > h3, .section > h4, .section > h5, - .section > h6, .section > .section { + .section:not(.force-right) > h1, .section:not(.force-right) > h2, + .section:not(.force-right) > h3, .section:not(.force-right) > h4, + .section:not(.force-right) > h5, .section:not(.force-right) > h6, + .section > .section:not(.force-right) { position: relative; width: auto; float: none; diff --git a/conf.py b/conf.py index 664d8b0e6..fe277499c 100644 --- a/conf.py +++ b/conf.py @@ -265,5 +265,8 @@ texinfo_documents = [ #texinfo_no_detailmenu = False def setup(app): + app.add_javascript('atom.js') + app.add_javascript('immutable.js') app.add_javascript('react.js') - app.add_javascript('accounting.js') + app.add_javascript('chart-of-accounts.js') + app.add_javascript('fiscalyear.js') diff --git a/index.rst b/index.rst index 8030c77f5..057abb60c 100644 --- a/index.rst +++ b/index.rst @@ -52,35 +52,37 @@ them being consumed for the company to "work". What is owned has been financed through debts to reimburse or acquired assets (profits, capical). -Journal Entries -=============== +Journals +======== -The chart of accounts is a list of P&L and balance sheet accounts. Journal -entries record debits and credits to accounts. For instance, for a banking -account: - -* debit 500€ (500€ income) -* Credit 200€ (paid out 200€) -* Balance: 300€ (300€ left on the account) - -Operations on an account are sometimes represented by T-accounts. +Accounting journals record business financial transactions as *journal +entries* before posting entries to account-specific ledgers. To each financial document (invoice, bank statement, receipt, loan agreement) -corresponds a *Journal Entry*, which is itself composed of multiple *journal -items*. Each journal item represents a single change to a single account, but -entries must be balanced, the sum of all credits in an entry must be equal to -the sum of all debits. +corresponds a *journal entry*. -Example: a house doesn't get owned out of thin air, it must have been paid -(conversion of an asset to an other asset, no change in wealth) and that money -generally comes from a loan (liability to asset). +Each journal entry is composed of multiple *journal items*. + +Each journal item represents a single change (debit or credit) to a single +account. + +In *double-entry bookkeeping*, a journal entry must be balanced by having the +sum of all its debits be equal to the sum of all its credits. A journal entry +is thus composed of at least two *journal items*, a debit and a credit, and +involves at least two accounts. + +Conventionally, all *debits* in journal entries are written first, with the +account name flush with their column, followed by all *credits* indented +slightly (to match the position/offset of the corresponding amount +column). Journal entries can include a note providing context for the +transaction. A journal entry almost always corresponds to a separate justifying document: invoice, pay slip, …. Financial audits may include matching "hard" evidence to journal entries. -Journal entries are generally triaged into **accounting journals** based on -their classification or frequency. Common accounting journals are: +Journal entries are generally triaged into accounting journals based on their +classification or frequency. Common accounting journals are: * Sales journals with all client transactions * Purchase journals with supplier transactions @@ -89,30 +91,56 @@ their classification or frequency. Common accounting journals are: .. rst-class:: force-right -.. todo:: +Transactions +------------ - Switch: European | Storno | Anglo-Saxon +.. h:div:: journals - Balance = Debit - Credit + needs javascript - By convention, on financial accounts. +Ledgers +======= - Active Documents To Show Impact: - Customer Invoice $100 + 9% tax - Customer Refund - Customer Payment - Customer Delivery - Pay Taxes Due - Supplier Invoice (an Asset) - Supplier Invoice (an Expense) - Inventory Reception +Where journals are general transaction logs (usually contextual on transaction +type or frequency), ledgers are change logs for a single account (or as a +central repository for all account changes when it comes to *general +ledgers*). - * provide a bunch of pre-defined operations (customisable accounts?) - * some operations enable further operations (e.g. a customer can only pay - if he got an invoice) - * selected operations get reflected on the ledger - * update the chart of accounts with content of each account? - * provide multiple GAAP accounts things? +.. todo:: is there a concept of ledger in Odoo? + +Ledgers are collections of T-accounts which summarize operations affecting a +specific account. T-accounts are shaped thus because they are shaped as a T, +with debits under the left arm and all credits under the right arm of the T: + +T-accounts can also be used as temporary scratch space when preparing +transactions by hand. + +.. rst-class:: force-right + +T-accounts for the transactions +------------------------------- + +.. h:div:: t-accounts + + needs javascript + +Chart of Accounts +================= + +The **chart of accounts** lists all balance sheet (assets, liabilities) and +P&L (revenue, expense) accounts. These accounts are used to organize and +classify the finances of the company to better understand the company's +financial state, and the chart can be used to get a snapshot of a company's +financial period. + +.. rst-class:: force-right + +Balance = debit - credit +------------------------ + +.. h:div:: chart-of-accounts + + Requires javascript Debit and credit ================ @@ -135,31 +163,39 @@ that adding money to a bank account is a *debit* (in accounting terms): credit on the receivable * the invoice must thus be a debit on receivable and a credit on income. -.. h:div:: force-right +.. rst-class:: force-right - Follow the money: +Follow the money +---------------- - 1. Customer Payment: Increase bank account, it's a Debit. Thus, the - receivable is a credit. +1. Customer Payment: Increase bank account, it's a Debit. Thus, the receivable + is a credit. - ================== ===== ====== - \ Debit Credit - ================== ===== ====== - Bank Account 109€ - Account Receivable 109€ - ================== ===== ====== + +---------------------+-----+------+ + | |Debit|Credit| + +=====================+=====+======+ + |Bank Account | 109 | | + +---------------------+-----+------+ + ||  Account Receivable| | 109 | + +---------------------+-----+------+ + ||   Payment by customer XXX | + +---------------------+-----+------+ - 2. As the invoice should compensate the receivable +2. As the invoice should compensate the receivable - ================== ===== ====== - \ Debit Credit - ================== ===== ====== - Account Receivable 109€ - Income 100€ - Taxes 9€ - ================== ===== ====== + +---------------------+-----+------+ + | |Debit|Credit| + +=====================+=====+======+ + |Account Receivable | 109 | | + +---------------------+-----+------+ + ||  Income | | 100 | + +---------------------+-----+------+ + ||  Taxes | | 9 | + +---------------------+-----+------+ + ||   Invoicing of customer XXX | + +---------------------+-----+------+ - → The income should be negative (a credit) +→ The income should be negative (a credit) Closing Fiscal Years ==================== @@ -179,7 +215,12 @@ E.g. if a company had 1000€ revenue and 600€ expenses it had a 400€ net income. At FY closure the following closure operation is applied: net income (debit 400) to retained earnings (credit 400). -.. h:div:: force-right fiscal-year-closing +.. rst-class:: force-right + +Ledger for a fiscal year +------------------------ + +.. h:div:: fiscal-year-closing +--------------------------+-------------------------+-------------------------+ | |Debit |Credit |