From 931c1c8ec3b16d97711d83b56af3fc591865f98a Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 17 Feb 2015 16:38:00 +0100 Subject: [PATCH] [ADD] explanation + interaction of journals + chart of accounts After discussion with fp this probably isn't the direction (ish), but want to checkpoint this in order to work on other stuff earlier in the document, but not commit a single gigantic blob of stuff. --- _static/atom.js | 48 + _static/chart-of-accounts.js | 355 ++ _static/{accounting.js => fiscalyear.js} | 145 +- _static/immutable.js | 4856 ++++++++++++++++++++++ _themes/odoodoc/sphinx_monkeypatch.py | 9 +- _themes/odoodoc/static/odoodoc.css_t | 2 +- _themes/odoodoc/static/style.css | 344 +- _themes/odoodoc/static/style.less | 21 +- conf.py | 5 +- index.rst | 159 +- 10 files changed, 5615 insertions(+), 329 deletions(-) create mode 100644 _static/atom.js create mode 100644 _static/chart-of-accounts.js rename _static/{accounting.js => fiscalyear.js} (67%) create mode 100644 _static/immutable.js 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 |