diff --git a/README.md b/README.md index 96f23bfd6..e4cc19eea 100644 --- a/README.md +++ b/README.md @@ -106,22 +106,22 @@ RainLoop 1.14 vs SnappyMail |js/* |RainLoop |Snappy | |----------- |--------: |--------: | -|admin.js |2.130.942 | 776.615 | -|app.js |4.184.455 |2.430.639 | +|admin.js |2.130.942 | 774.301 | +|app.js |4.184.455 |2.424.578 | |boot.js | 671.522 | 5.285 | -|libs.js | 647.614 | 255.041 | +|libs.js | 647.614 | 249.953 | |polyfills.js | 325.834 | 0 | -|TOTAL |7.960.367 |3.467.580 | +|TOTAL |7.960.367 |3.454.117 | |js/min/* |RainLoop |Snappy |Rain gzip |gzip |brotli | |--------------- |--------: |--------: |--------: |--------: |--------: | -|admin.min.js | 252.147 | 104.046 | 73.657 | 27.739 | 24.058 | -|app.min.js | 511.202 | 329.887 |140.462 | 84.844 | 68.843 | +|admin.min.js | 252.147 | 103.761 | 73.657 | 27.632 | 24.004 | +|app.min.js | 511.202 | 328.005 |140.462 | 84.451 | 68.571 | |boot.min.js | 66.007 | 2.935 | 22.567 | 1.510 | 1.285 | -|libs.min.js | 572.545 | 149.712 |176.720 | 52.703 | 46.853 | +|libs.min.js | 572.545 | 144.650 |176.720 | 51.765 | 46.049 | |polyfills.min.js | 32.452 | 0 | 11.312 | 0 | 0 | -|TOTAL |1.434.353 | 586.580 |424.718 |166.796 |141.039 | -|TOTAL (no admin) |1.182.206 | 482.534 |351.061 |139.057 |116.981 | +|TOTAL |1.434.353 | 579.351 |424.718 |165.358 |139.909 | +|TOTAL (no admin) |1.182.206 | 475.590 |351.061 |137.726 |115.905 | For a user its around 60% smaller and faster than traditional RainLoop. diff --git a/vendors/knockout/Gruntfile.js b/vendors/knockout/Gruntfile.js index 1f1fe2681..92f1cb663 100644 --- a/vendors/knockout/Gruntfile.js +++ b/vendors/knockout/Gruntfile.js @@ -109,8 +109,8 @@ module.exports = function(grunt) { function buildMin(output, done) { var cc = require('closure-compiler'); var options = { -// language_in:'ECMASCRIPT6', // BROKEN!! -// language_out:'ECMASCRIPT6', + language_in:'ECMASCRIPT6', // BROKEN!! + language_out:'ECMASCRIPT6', compilation_level: 'ADVANCED_OPTIMIZATIONS', output_wrapper: '(function() {%output%})();' }; diff --git a/vendors/knockout/README.md b/vendors/knockout/README.md index 137c17846..e2eda33c8 100644 --- a/vendors/knockout/README.md +++ b/vendors/knockout/README.md @@ -2,6 +2,13 @@ **Knockout** is a JavaScript [MVVM](http://en.wikipedia.org/wiki/Model_View_ViewModel) (a modern variant of MVC) library that makes it easier to create rich, desktop-like user interfaces with JavaScript and HTML. It uses *observers* to make your UI automatically stay in sync with an underlying data model, along with a powerful and extensible set of *declarative bindings* to enable productive development. +## SnappyMail Modifications + +Knockout has a high level of backward compatibility. We don't use it, so a lot of IE code is stripped. + +npm closure-compiler is old and broken for ES2015/ES6, so we use the new google-closure-compiler. + + ## Getting started [![Join the chat at https://gitter.im/knockout/knockout](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knockout/knockout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) diff --git a/vendors/knockout/build/fragments/source-references.js b/vendors/knockout/build/fragments/source-references.js index 054d8d3ea..30ba9817c 100644 --- a/vendors/knockout/build/fragments/source-references.js +++ b/vendors/knockout/build/fragments/source-references.js @@ -27,23 +27,23 @@ knockoutDebugCallback([ 'src/components/customElements.js', 'src/components/componentBinding.js', 'src/binding/defaultBindings/attr.js', - 'src/binding/defaultBindings/checked.js', +// 'src/binding/defaultBindings/checked.js', 'src/binding/defaultBindings/css.js', 'src/binding/defaultBindings/enableDisable.js', 'src/binding/defaultBindings/event.js', 'src/binding/defaultBindings/foreach.js', 'src/binding/defaultBindings/hasfocus.js', 'src/binding/defaultBindings/html.js', - 'src/binding/defaultBindings/ifIfnotWith.js', - 'src/binding/defaultBindings/let.js', +// 'src/binding/defaultBindings/ifIfnotWith.js', +// 'src/binding/defaultBindings/let.js', 'src/binding/defaultBindings/options.js', - 'src/binding/defaultBindings/selectedOptions.js', +// 'src/binding/defaultBindings/selectedOptions.js', 'src/binding/defaultBindings/style.js', 'src/binding/defaultBindings/submit.js', 'src/binding/defaultBindings/text.js', 'src/binding/defaultBindings/textInput.js', - 'src/binding/defaultBindings/uniqueName.js', - 'src/binding/defaultBindings/using.js', +// 'src/binding/defaultBindings/uniqueName.js', +// 'src/binding/defaultBindings/using.js', 'src/binding/defaultBindings/value.js', 'src/binding/defaultBindings/visibleHidden.js', // click depends on event - The order matters for specs, which includes each file individually diff --git a/vendors/knockout/build/output/knockout-latest.debug.js b/vendors/knockout/build/output/knockout-latest.debug.js index a683a3628..73f985f93 100644 --- a/vendors/knockout/build/output/knockout-latest.debug.js +++ b/vendors/knockout/build/output/knockout-latest.debug.js @@ -59,23 +59,19 @@ ko.options = { }; //ko.exportSymbol('options', ko.options); // 'options' isn't minified -ko.utils = (function () { +ko.utils = (() => { function arrayCall(name, arr, p1, p2) { return Array.prototype[name].call(arr, p1, p2); } function objectForEach(obj, action) { - obj && Object.entries(obj).forEach(function(prop) { - action(prop[0], prop[1]); - }); + obj && Object.entries(obj).forEach(prop => action(prop[0], prop[1])); } function extend(target, source) { if (source) { - Object.entries(source).forEach(function(prop) { - target[prop[0]] = prop[1]; - }); + Object.entries(source).forEach(prop => target[prop[0]] = prop[1]); } return target; } @@ -92,22 +88,20 @@ ko.utils = (function () { function toggleDomNodeCssClass(node, classNames, shouldHaveClass) { if (classNames) { var addOrRemoveFn = shouldHaveClass ? 'add' : 'remove'; - classNames.split(/\s+/).forEach(function(className) { - node.classList[addOrRemoveFn](className); - }); + classNames.split(/\s+/).forEach(className => + node.classList[addOrRemoveFn](className) + ); } } return { - arrayForEach: function (array, action, actionOwner) { - arrayCall('forEach', array, action, actionOwner); - }, + arrayForEach: (array, action, actionOwner) => + arrayCall('forEach', array, action, actionOwner), - arrayIndexOf: function (array, item) { - return arrayCall('indexOf', array, item); - }, + arrayIndexOf: (array, item) => + arrayCall('indexOf', array, item), - arrayFirst: function (array, predicate, predicateOwner) { + arrayFirst: (array, predicate, predicateOwner) => { for (var i = 0, j = array.length; i < j; i++) { if (predicate.call(predicateOwner, array[i], i, array)) return array[i]; @@ -115,7 +109,7 @@ ko.utils = (function () { return undefined; }, - arrayRemoveItem: function (array, itemToRemove) { + arrayRemoveItem: (array, itemToRemove) => { var index = ko.utils.arrayIndexOf(array, itemToRemove); if (index > 0) { array.splice(index, 1); @@ -125,11 +119,10 @@ ko.utils = (function () { } }, - arrayFilter: function (array, predicate, predicateOwner) { - return array ? arrayCall('filter', array, predicate, predicateOwner) : []; - }, + arrayFilter: (array, predicate, predicateOwner) => + array ? arrayCall('filter', array, predicate, predicateOwner) : [], - arrayPushAll: function (array, valuesToPush) { + arrayPushAll: (array, valuesToPush) => { if (valuesToPush instanceof Array) array.push.apply(array, valuesToPush); else @@ -148,48 +141,45 @@ ko.utils = (function () { objectForEach: objectForEach, - objectMap: function(source, mapping, mappingOwner) { + objectMap: (source, mapping, mappingOwner) => { if (!source) return source; var target = {}; - Object.entries(source).forEach(function(prop) { - target[prop[0]] = mapping.call(mappingOwner, prop[1], prop[0], source); - }); + Object.entries(source).forEach(prop => + target[prop[0]] = mapping.call(mappingOwner, prop[1], prop[0], source) + ); return target; }, - emptyDomNode: function (domNode) { + emptyDomNode: domNode => { while (domNode.firstChild) { ko.removeNode(domNode.firstChild); } }, - moveCleanedNodesToContainerElement: function(nodes) { + moveCleanedNodesToContainerElement: nodes => { // Ensure it's a real array, as we're about to reparent the nodes and // we don't want the underlying collection to change while we're doing that. var nodesArray = ko.utils.makeArray(nodes); var templateDocument = (nodesArray[0] && nodesArray[0].ownerDocument) || document; var container = templateDocument.createElement('div'); - nodes.forEach(function(node){container.append(ko.cleanNode(node));}); + nodes.forEach(node => container.append(ko.cleanNode(node))); return container; }, - cloneNodes: function (nodesArray, shouldCleanNodes) { - return arrayCall('map', nodesArray, shouldCleanNodes - ? function(node){return ko.cleanNode(node.cloneNode(true));} - : function(node){return node.cloneNode(true);} - ); - }, + cloneNodes: (nodesArray, shouldCleanNodes) => + arrayCall('map', nodesArray, shouldCleanNodes + ? node => ko.cleanNode(node.cloneNode(true)) + : node => node.cloneNode(true) + ), - setDomNodeChildren: function (domNode, childNodes) { + setDomNodeChildren: (domNode, childNodes) => { ko.utils.emptyDomNode(domNode); - if (childNodes) { - domNode.append.apply(domNode, childNodes); - } + childNodes && domNode.append.apply(domNode, childNodes); }, - replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) { + replaceDomNodes: (nodeToReplaceOrNodeArray, newNodesArray) => { var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray; if (nodesToReplaceArray.length > 0) { @@ -204,7 +194,7 @@ ko.utils = (function () { } }, - fixUpContinuousNodeArray: function(continuousNodeArray, parentNode) { + fixUpContinuousNodeArray: (continuousNodeArray, parentNode) => { // Before acting on a set of nodes that were previously outputted by a template function, we have to reconcile // them against what is in the DOM right now. It may be that some of the nodes have already been removed, or that // new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been @@ -249,40 +239,31 @@ ko.utils = (function () { return continuousNodeArray; }, - stringTrim: function (string) { - return string === null || string === undefined ? '' : + stringTrim: string => string === null || string === undefined ? '' : string.trim ? string.trim() : - string.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); - }, + string.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''), - stringStartsWith: function (string, startsWith) { + stringStartsWith: (string, startsWith) => { string = string || ""; if (startsWith.length > string.length) return false; return string.substring(0, startsWith.length) === startsWith; }, - domNodeIsContainedBy: function (node, containedByNode) { - return containedByNode.contains(node.nodeType !== 1 ? node.parentNode : node); - }, + domNodeIsContainedBy: (node, containedByNode) => + containedByNode.contains(node.nodeType !== 1 ? node.parentNode : node), - domNodeIsAttachedToDocument: function (node) { - return ko.utils.domNodeIsContainedBy(node, node.ownerDocument.documentElement); - }, + domNodeIsAttachedToDocument: node => ko.utils.domNodeIsContainedBy(node, node.ownerDocument.documentElement), - anyDomNodeIsAttachedToDocument: function(nodes) { - return !!ko.utils.arrayFirst(nodes, ko.utils.domNodeIsAttachedToDocument); - }, + anyDomNodeIsAttachedToDocument: nodes => !!ko.utils.arrayFirst(nodes, ko.utils.domNodeIsAttachedToDocument), - tagNameLower: function(element) { - // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case. - // Possible future optimization: If we know it's an element from an XHTML document (not HTML), - // we don't need to do the .toLowerCase() as it will always be lower case anyway. - return element && element.tagName && element.tagName.toLowerCase(); - }, + // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case. + // Possible future optimization: If we know it's an element from an XHTML document (not HTML), + // we don't need to do the .toLowerCase() as it will always be lower case anyway. + tagNameLower: element => element && element.tagName && element.tagName.toLowerCase(), - catchFunctionErrors: function (delegate) { + catchFunctionErrors: delegate => { return ko['onError'] ? function () { try { return delegate.apply(this, arguments); @@ -293,41 +274,33 @@ ko.utils = (function () { } : delegate; }, - setTimeout: function (handler, timeout) { - return setTimeout(ko.utils.catchFunctionErrors(handler), timeout); - }, + setTimeout: (handler, timeout) => setTimeout(ko.utils.catchFunctionErrors(handler), timeout), - deferError: function (error) { - setTimeout(function () { + deferError: error => setTimeout(() => { ko['onError'] && ko['onError'](error); throw error; - }, 0); - }, + }, 0), - registerEventHandler: function (element, eventType, handler) { + registerEventHandler: (element, eventType, handler) => { var wrappedHandler = ko.utils.catchFunctionErrors(handler); element.addEventListener(eventType, wrappedHandler, false); }, - triggerEvent: function (element, eventType) { + triggerEvent: (element, eventType) => { if (!(element && element.nodeType)) throw new Error("element must be a DOM node when calling triggerEvent"); element.dispatchEvent(new Event(eventType)); }, - unwrapObservable: function (value) { - return ko.isObservable(value) ? value() : value; - }, + unwrapObservable: value => ko.isObservable(value) ? value() : value, - peekObservable: function (value) { - return ko.isObservable(value) ? value.peek() : value; - }, + peekObservable: value => ko.isObservable(value) ? value.peek() : value, toggleDomNodeCssClass: toggleDomNodeCssClass, - setTextContent: function(element, textContent) { + setTextContent: (element, textContent) => { var value = ko.utils.unwrapObservable(textContent); if ((value === null) || (value === undefined)) value = ""; @@ -343,11 +316,9 @@ ko.utils = (function () { } }, - makeArray: function(arrayLikeObject) { - return Array['from'](arrayLikeObject); - } + makeArray: arrayLikeObject => Array['from'](arrayLikeObject) } -}()); +})(); ko.exportSymbol('utils', ko.utils); ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach); @@ -373,18 +344,18 @@ ko.utils.domData = new (function () { var uniqueId = 0; var dataStoreKeyExpandoPropertyName = "__ko__" + (Date.now()); - var getDataForNode, clear; + var // We considered using WeakMap, but it has a problem in IE 11 and Edge that prevents using // it cross-window, so instead we just store the data directly on the node. // See https://github.com/knockout/knockout/issues/2141 - getDataForNode = function (node, createIfNotFound) { + getDataForNode = (node, createIfNotFound) => { var dataForNode = node[dataStoreKeyExpandoPropertyName]; if (!dataForNode && createIfNotFound) { dataForNode = node[dataStoreKeyExpandoPropertyName] = {}; } return dataForNode; - }; - clear = function (node) { + }, + clear = node => { if (node[dataStoreKeyExpandoPropertyName]) { delete node[dataStoreKeyExpandoPropertyName]; return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended @@ -393,24 +364,22 @@ ko.utils.domData = new (function () { }; return { - get: function (node, key) { + get: (node, key) => { var dataForNode = getDataForNode(node, false); return dataForNode && dataForNode[key]; }, - set: function (node, key, value) { + set: (node, key, value) => { // Make sure we don't actually create a new domData key if we are actually deleting a value var dataForNode = getDataForNode(node, value !== undefined /* createIfNotFound */); dataForNode && (dataForNode[key] = value); }, - getOrSet: function (node, key, value) { + getOrSet: (node, key, value) => { var dataForNode = getDataForNode(node, true /* createIfNotFound */); return dataForNode[key] || (dataForNode[key] = value); }, clear: clear, - nextKey: function () { - return (uniqueId++) + dataStoreKeyExpandoPropertyName; - } + nextKey: () => (uniqueId++) + dataStoreKeyExpandoPropertyName }; })(); @@ -459,20 +428,20 @@ ko.utils.domNodeDisposal = new (function () { if (!onlyComments || nodeList[i].nodeType === 8) { cleanSingleNode(cleanedNodes[cleanedNodes.length] = lastCleanedNode = nodeList[i]); if (nodeList[i] !== lastCleanedNode) { - while (i-- && ko.utils.arrayIndexOf(cleanedNodes, nodeList[i]) == -1) {} + while (i-- && ko.utils.arrayIndexOf(cleanedNodes, nodeList[i]) == -1); } } } } return { - addDisposeCallback : function(node, callback) { + addDisposeCallback : (node, callback) => { if (typeof callback != "function") throw new Error("Callback must be a function"); getDisposeCallbacksCollection(node, true).push(callback); }, - removeDisposeCallback : function(node, callback) { + removeDisposeCallback : (node, callback) => { var callbacksCollection = getDisposeCallbacksCollection(node, false); if (callbacksCollection) { ko.utils.arrayRemoveItem(callbacksCollection, callback); @@ -481,8 +450,8 @@ ko.utils.domNodeDisposal = new (function () { } }, - cleanNode : function(node) { - ko.dependencyDetection.ignore(function () { + cleanNode : node => { + ko.dependencyDetection.ignore(() => { // First clean this node, where applicable if (cleanableNodeTypes[node.nodeType]) { cleanSingleNode(node); @@ -497,7 +466,7 @@ ko.utils.domNodeDisposal = new (function () { return node; }, - removeNode : function(node) { + removeNode : node => { ko.cleanNode(node); if (node.parentNode) node.parentNode.removeChild(node); @@ -511,7 +480,7 @@ ko.exportSymbol('removeNode', ko.removeNode); ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal); ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback); ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback); -(function () { +(() => { var none = [0, "", ""], table = [1, "", "
"], tbody = [2, "", "
"], @@ -563,16 +532,15 @@ ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeD return ko.utils.makeArray(div.lastChild.childNodes); } - ko.utils.parseHtmlFragment = function(html, documentContext) { - return simpleHtmlParse(html, documentContext); // ... otherwise, this simple logic will do in most common cases. - }; + ko.utils.parseHtmlFragment = (html, documentContext) => + simpleHtmlParse(html, documentContext); // ... otherwise, this simple logic will do in most common cases. - ko.utils.parseHtmlForTemplateNodes = function(html, documentContext) { + ko.utils.parseHtmlForTemplateNodes = (html, documentContext) => { var nodes = ko.utils.parseHtmlFragment(html, documentContext); return (nodes.length && nodes[0].parentElement) || ko.utils.moveCleanedNodesToContainerElement(nodes); }; - ko.utils.setHtml = function(node, html) { + ko.utils.setHtml = (node, html) => { ko.utils.emptyDomNode(node); // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it @@ -619,7 +587,7 @@ ko.memoization = (function () { } return { - memoize: function (callback) { + memoize: callback => { if (typeof callback != "function") throw new Error("You can only pass a function to ko.memoization.memoize()"); var memoId = generateRandomId(); @@ -627,7 +595,7 @@ ko.memoization = (function () { return ""; }, - unmemoize: function (memoId, callbackParams) { + unmemoize: (memoId, callbackParams) => { var callback = memos[memoId]; if (callback === undefined) throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized."); @@ -638,7 +606,7 @@ ko.memoization = (function () { finally { delete memos[memoId]; } }, - unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) { + unmemoizeDomNodeAndDescendants: (domNode, extraCallbackParamsArray) => { var memos = []; findMemoNodes(domNode, memos); for (var i = 0, j = memos.length; i < j; i++) { @@ -653,8 +621,8 @@ ko.memoization = (function () { } }, - parseMemoText: function (memoText) { - var match = memoText.match(/^\[ko_memo\:(.*?)\]$/); + parseMemoText: memoText => { + var match = memoText.match(/^\[ko_memo:(.*?)\]$/); return match ? match[1] : null; } }; @@ -665,19 +633,18 @@ ko.exportSymbol('memoization.memoize', ko.memoization.memoize); ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize); ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText); ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants); -ko.tasks = (function () { - var scheduler, - taskQueue = [], +ko.tasks = (() => { + var taskQueue = [], taskQueueLength = 0, nextHandle = 1, - nextIndexToProcess = 0; + nextIndexToProcess = 0, // Chrome 27+, Firefox 14+, IE 11+, Opera 15+, Safari 6.1+ // From https://github.com/petkaantonov/bluebird * Copyright (c) 2014 Petka Antonov * License: MIT - scheduler = (function (callback) { + scheduler = (callback => { var div = document.createElement("div"); new MutationObserver(callback).observe(div, {attributes: true}); - return function () { div.classList.toggle("foo"); }; + return () => div.classList.toggle("foo"); })(scheduledProcess); function processTasks() { @@ -714,37 +681,22 @@ ko.tasks = (function () { nextIndexToProcess = taskQueueLength = taskQueue.length = 0; } - function scheduleTaskProcessing() { - ko.tasks['scheduler'](scheduledProcess); - } - var tasks = { - 'scheduler': scheduler, // Allow overriding the scheduler - - schedule: function (func) { + schedule: func => { if (!taskQueueLength) { - scheduleTaskProcessing(); + scheduler(scheduledProcess); } taskQueue[taskQueueLength++] = func; return nextHandle++; }, - cancel: function (handle) { + cancel: handle => { var index = handle - (nextHandle - taskQueueLength); if (index >= nextIndexToProcess && index < taskQueueLength) { taskQueue[index] = null; } - }, - - // For testing only: reset the queue and return the previous queue length - 'resetForTesting': function () { - var length = taskQueueLength - nextIndexToProcess; - nextIndexToProcess = taskQueueLength = taskQueue.length = 0; - return length; - }, - - runEarly: processTasks + } }; return tasks; @@ -753,9 +705,8 @@ ko.tasks = (function () { ko.exportSymbol('tasks', ko.tasks); ko.exportSymbol('tasks.schedule', ko.tasks.schedule); //ko.exportSymbol('tasks.cancel', ko.tasks.cancel); "cancel" isn't minified -ko.exportSymbol('tasks.runEarly', ko.tasks.runEarly); ko.extenders = { - 'throttle': function(target, timeout) { + 'throttle': (target, timeout) => { // Throttling means two things: // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies @@ -767,16 +718,14 @@ ko.extenders = { var writeTimeoutInstance = null; return ko.dependentObservable({ 'read': target, - 'write': function(value) { + 'write': value => { clearTimeout(writeTimeoutInstance); - writeTimeoutInstance = ko.utils.setTimeout(function() { - target(value); - }, timeout); + writeTimeoutInstance = ko.utils.setTimeout(() => target(value), timeout); } }); }, - 'rateLimit': function(target, options) { + 'rateLimit': (target, options) => { var timeout, method, limitFunction; if (typeof options == 'number') { @@ -790,22 +739,20 @@ ko.extenders = { target._deferUpdates = false; limitFunction = typeof method == 'function' ? method : method == 'notifyWhenChangesStop' ? debounce : throttle; - target.limit(function(callback) { - return limitFunction(callback, timeout, options); - }); + target.limit(callback => limitFunction(callback, timeout, options)); }, - 'deferred': function(target, options) { + 'deferred': (target, options) => { if (options !== true) { throw new Error('The \'deferred\' extender only accepts the value \'true\', because it is not supported to turn deferral off once enabled.') } if (!target._deferUpdates) { target._deferUpdates = true; - target.limit(function (callback) { + target.limit(callback => { var handle, ignoreUpdates = false; - return function () { + return () => { if (!ignoreUpdates) { ko.tasks.cancel(handle); handle = ko.tasks.schedule(callback); @@ -822,7 +769,7 @@ ko.extenders = { } }, - 'notify': function(target, notifyWhen) { + 'notify': (target, notifyWhen) => { target["equalityComparer"] = notifyWhen == "always" ? null : // null equalityComparer means to always notify valuesArePrimitiveAndEqual; @@ -837,9 +784,9 @@ function valuesArePrimitiveAndEqual(a, b) { function throttle(callback, timeout) { var timeoutInstance; - return function () { + return () => { if (!timeoutInstance) { - timeoutInstance = ko.utils.setTimeout(function () { + timeoutInstance = ko.utils.setTimeout(() => { timeoutInstance = undefined; callback(); }, timeout); @@ -849,7 +796,7 @@ function throttle(callback, timeout) { function debounce(callback, timeout) { var timeoutInstance; - return function () { + return () => { clearTimeout(timeoutInstance); timeoutInstance = ko.utils.setTimeout(callback, timeout); }; @@ -858,7 +805,7 @@ function debounce(callback, timeout) { function applyExtenders(requestedExtenders) { var target = this; if (requestedExtenders) { - ko.utils.objectForEach(requestedExtenders, function(key, value) { + ko.utils.objectForEach(requestedExtenders, (key, value) => { var extenderHandler = ko.extenders[key]; if (typeof extenderHandler == 'function') { target = extenderHandler(target, value) || target; @@ -916,7 +863,7 @@ function limitNotifySubscribers(value, event) { } var ko_subscribable_fn = { - init: function(instance) { + init: instance => { instance._subscriptions = { "change": [] }; instance._versionNumber = 1; }, @@ -927,7 +874,7 @@ var ko_subscribable_fn = { event = event || defaultEvent; var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback; - var subscription = new ko.subscription(self, boundCallback, function () { + var subscription = new ko.subscription(self, boundCallback, () => { ko.utils.arrayRemoveItem(self._subscriptions[event], subscription); if (self.afterSubscriptionRemove) self.afterSubscriptionRemove(event); @@ -986,7 +933,7 @@ var ko_subscribable_fn = { self["notifySubscribers"] = limitNotifySubscribers; } - var finish = limitFunction(function() { + var finish = limitFunction(() => { self._notificationIsPending = false; // If an observable provided a reference to itself, access it to get the latest value. @@ -1003,7 +950,7 @@ var ko_subscribable_fn = { } }); - self._limitChange = function(value, isDirty) { + self._limitChange = (value, isDirty) => { if (!isDirty || !self._notificationIsPending) { didUpdate = !isDirty; } @@ -1012,16 +959,16 @@ var ko_subscribable_fn = { pendingValue = value; finish(); }; - self._limitBeforeChange = function(value) { + self._limitBeforeChange = value => { if (!ignoreBeforeChange) { previousValue = value; self._origNotifySubscribers(value, beforeChange); } }; - self._recordUpdate = function() { + self._recordUpdate = () => { didUpdate = true; }; - self._notifyNextChangeIfValueIsDifferent = function() { + self._notifyNextChangeIfValueIsDifferent = () => { if (self.isDifferent(previousValue, self.peek(true /*evaluate*/))) { notifyNextChange = true; } @@ -1035,23 +982,20 @@ var ko_subscribable_fn = { getSubscriptionsCount: function (event) { if (event) { return this._subscriptions[event] && this._subscriptions[event].length || 0; - } else { - var total = 0; - ko.utils.objectForEach(this._subscriptions, function(eventName, subscriptions) { - if (eventName !== 'dirty') - total += subscriptions.length; - }); - return total; } + var total = 0; + ko.utils.objectForEach(this._subscriptions, (eventName, subscriptions) => { + if (eventName !== 'dirty') + total += subscriptions.length; + }); + return total; }, isDifferent: function(oldValue, newValue) { return !this['equalityComparer'] || !this['equalityComparer'](oldValue, newValue); }, - toString: function() { - return '[object Object]' - }, + toString: () => '[object Object]', extend: applyExtenders }; @@ -1071,28 +1015,17 @@ if (ko.utils.canSetPrototype) { ko.subscribable['fn'] = ko_subscribable_fn; -ko.isSubscribable = function (instance) { - return instance != null && typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function"; -}; +ko.isSubscribable = instance => + instance != null && typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function"; ko.exportSymbol('subscribable', ko.subscribable); ko.exportSymbol('isSubscribable', ko.isSubscribable); -ko.computedContext = ko.dependencyDetection = (function () { +ko.computedContext = ko.dependencyDetection = (() => { var outerFrames = [], currentFrame, lastId = 0; - // Return a unique ID that can be assigned to an observable for dependency tracking. - // Theoretically, you could eventually overflow the number storage size, resulting - // in duplicate IDs. But in JavaScript, the largest exact integral value is 2^53 - // or 9,007,199,254,740,992. If you created 1,000,000 IDs per second, it would - // take over 285 years to reach that number. - // Reference http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html - function getId() { - return ++lastId; - } - function begin(options) { outerFrames.push(currentFrame); currentFrame = options; @@ -1107,15 +1040,15 @@ ko.computedContext = ko.dependencyDetection = (function () { end: end, - registerDependency: function (subscribable) { + registerDependency: subscribable => { if (currentFrame) { if (!ko.isSubscribable(subscribable)) throw new Error("Only subscribable things can act as dependencies"); - currentFrame.callback.call(currentFrame.callbackTarget, subscribable, subscribable._id || (subscribable._id = getId())); + currentFrame.callback.call(currentFrame.callbackTarget, subscribable, subscribable._id || (subscribable._id = ++lastId)); } }, - ignore: function (callback, callbackTarget, callbackArgs) { + ignore: (callback, callbackTarget, callbackArgs) => { try { begin(); return callback.apply(callbackTarget, callbackArgs || []); @@ -1124,22 +1057,22 @@ ko.computedContext = ko.dependencyDetection = (function () { } }, - getDependenciesCount: function () { + getDependenciesCount: () => { if (currentFrame) return currentFrame.computed.getDependenciesCount(); }, - getDependencies: function () { + getDependencies: () => { if (currentFrame) return currentFrame.computed.getDependencies(); }, - isInitial: function() { + isInitial: () => { if (currentFrame) return currentFrame.isInitial; }, - computed: function() { + computed: () => { if (currentFrame) return currentFrame.computed; } @@ -1155,7 +1088,7 @@ ko.exportSymbol('computedContext.registerDependency', ko.computedContext.registe ko.exportSymbol('ignoreDependencies', ko.ignoreDependencies = ko.dependencyDetection.ignore); var observableLatestValue = Symbol('_latestValue'); -ko.observable = function (initialValue) { +ko.observable = initialValue => { function observable() { if (arguments.length > 0) { // Write @@ -1214,7 +1147,7 @@ if (ko.utils.canSetPrototype) { var protoProperty = ko.observable.protoProperty = '__ko_proto__'; observableFn[protoProperty] = ko.observable; -ko.isObservable = function (instance) { +ko.isObservable = instance => { var proto = typeof instance == 'function' && instance[protoProperty]; if (proto && proto !== observableFn[protoProperty] && proto !== ko.computed['fn'][protoProperty]) { throw Error("Invalid object that looks like an observable; possibly from another Knockout instance"); @@ -1222,7 +1155,7 @@ ko.isObservable = function (instance) { return !!proto; }; -ko.isWriteableObservable = function (instance) { +ko.isWriteableObservable = instance => { return (typeof instance == 'function' && ( (instance[protoProperty] === observableFn[protoProperty]) || // Observable (instance[protoProperty] === ko.computed['fn'][protoProperty] && instance.hasWriteFunction))); // Writable computed observable @@ -1236,7 +1169,7 @@ ko.exportSymbol('observable.fn', observableFn); ko.exportProperty(observableFn, 'peek', observableFn.peek); ko.exportProperty(observableFn, 'valueHasMutated', observableFn.valueHasMutated); ko.exportProperty(observableFn, 'valueWillMutate', observableFn.valueWillMutate); -ko.observableArray = function (initialValues) { +ko.observableArray = initialValues => { initialValues = initialValues || []; if (typeof initialValues != 'object' || !('length' in initialValues)) @@ -1304,7 +1237,7 @@ if (ko.utils.canSetPrototype) { // Populate ko.observableArray.fn with read/write functions from native arrays // Important: Do not add any additional functions here that may reasonably be used to *read* data from the array // because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale -ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) { +ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], methodName => { ko.observableArray['fn'][methodName] = function () { // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of // (for consistency with mutating regular observables) @@ -1319,14 +1252,14 @@ ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "uns }); // Populate ko.observableArray.fn with read-only functions from native arrays -ko.utils.arrayForEach(["slice"], function (methodName) { +ko.utils.arrayForEach(["slice"], methodName => { ko.observableArray['fn'][methodName] = function () { var underlyingArray = this(); return underlyingArray[methodName].apply(underlyingArray, arguments); }; }); -ko.isObservableArray = function (instance) { +ko.isObservableArray = instance => { return ko.isObservable(instance) && typeof instance["remove"] == "function" && typeof instance["push"] == "function"; @@ -1335,7 +1268,7 @@ ko.isObservableArray = function (instance) { ko.exportSymbol('observableArray', ko.observableArray); ko.exportSymbol('isObservableArray', ko.isObservableArray); var arrayChangeEventName = 'arrayChange'; -ko.extenders['trackArrayChanges'] = function(target, options) { +ko.extenders['trackArrayChanges'] = (target, options) => { // Use the provided options--each call to trackArrayChanges overwrites the previously set options target.compareArrayOptions = {}; if (options && typeof options == "object") { @@ -1357,7 +1290,7 @@ ko.extenders['trackArrayChanges'] = function(target, options) { underlyingAfterSubscriptionRemoveFunction = target.afterSubscriptionRemove; // Watch "subscribe" calls, and for array change events, ensure change tracking is enabled - target.beforeSubscriptionAdd = function (event) { + target.beforeSubscriptionAdd = event => { if (underlyingBeforeSubscriptionAddFunction) { underlyingBeforeSubscriptionAddFunction.call(target, event); } @@ -1366,7 +1299,7 @@ ko.extenders['trackArrayChanges'] = function(target, options) { } }; // Watch "dispose" calls, and for array change events, ensure change tracking is disabled when all are disposed - target.afterSubscriptionRemove = function (event) { + target.afterSubscriptionRemove = event => { if (underlyingAfterSubscriptionRemoveFunction) { underlyingAfterSubscriptionRemoveFunction.call(target, event); } @@ -1394,9 +1327,7 @@ ko.extenders['trackArrayChanges'] = function(target, options) { trackingChanges = true; // Track how many times the array actually changed value - spectateSubscription = target.subscribe(function () { - ++pendingChanges; - }, null, "spectate"); + spectateSubscription = target.subscribe(() => ++pendingChanges, null, "spectate"); // Each time the array changes value, capture a clone so that on the next // change it's possible to produce a diff @@ -1438,7 +1369,7 @@ ko.extenders['trackArrayChanges'] = function(target, options) { return cachedDiff; } - target.cacheDiffForKnownOperation = function(rawArray, operationName, args) { + target.cacheDiffForKnownOperation = (rawArray, operationName, args) => { // Only run if we're currently tracking changes for this observable array // and there aren't any pending deferred notifications. if (!trackingChanges || pendingChanges) { @@ -1647,9 +1578,9 @@ var computedFn = { getDependencies: function () { var dependencyTracking = this[computedState].dependencyTracking, dependentObservables = []; - ko.utils.objectForEach(dependencyTracking, function (id, dependency) { - dependentObservables[dependency._order] = dependency._target; - }); + ko.utils.objectForEach(dependencyTracking, (id, dependency) => + dependentObservables[dependency._order] = dependency._target + ); return dependentObservables; }, @@ -1661,9 +1592,9 @@ var computedFn = { if (ko.utils.arrayIndexOf(dependencies, obs) !== -1) { return true; } - return !!ko.utils.arrayFirst(dependencies, function (dep) { - return dep.hasAncestorDependency && dep.hasAncestorDependency(obs); - }); + return !!ko.utils.arrayFirst(dependencies, dep => + dep.hasAncestorDependency && dep.hasAncestorDependency(obs) + ); }, addDependencyTracking: function (id, target, trackingObj) { if (this[computedState].pure && target === this) { @@ -1709,7 +1640,7 @@ var computedFn = { changeSub = target.subscribe(this.respondToChange, this); return { _target: target, - dispose: function () { + dispose: () => { dirtySub.dispose(); changeSub.dispose(); } @@ -1723,9 +1654,9 @@ var computedFn = { throttleEvaluationTimeout = computedObservable['throttleEvaluation']; if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) { clearTimeout(this[computedState].evaluationTimeoutInstance); - this[computedState].evaluationTimeoutInstance = ko.utils.setTimeout(function () { - computedObservable.evaluateImmediate(true /*notifyChange*/); - }, throttleEvaluationTimeout); + this[computedState].evaluationTimeoutInstance = ko.utils.setTimeout(() => + computedObservable.evaluateImmediate(true /*notifyChange*/) + , throttleEvaluationTimeout); } else if (computedObservable._evalDelayed) { computedObservable._evalDelayed(true /*isChange*/); } else { @@ -1834,7 +1765,7 @@ var computedFn = { return changed; }, - evaluateImmediate_CallReadThenEndDependencyDetection: function (state, dependencyDetectionContext) { + evaluateImmediate_CallReadThenEndDependencyDetection: (state, dependencyDetectionContext) => { // This function is really part of the evaluateImmediate_CallReadWithDependencyDetection logic. // You'd never call it from anywhere else. Factoring it out means that evaluateImmediate_CallReadWithDependencyDetection // can be independent of try/finally blocks, which contributes to saving about 40% off the CPU @@ -1893,10 +1824,9 @@ var computedFn = { dispose: function () { var state = this[computedState]; if (!state.isSleeping && state.dependencyTracking) { - ko.utils.objectForEach(state.dependencyTracking, function (id, dependency) { - if (dependency.dispose) - dependency.dispose(); - }); + ko.utils.objectForEach(state.dependencyTracking, (id, dependency) => + dependency.dispose && dependency.dispose() + ); } if (state.disposeWhenNodeIsRemoved && state.domNodeDisposalCallback) { ko.utils.domNodeDisposal.removeDisposeCallback(state.disposeWhenNodeIsRemoved, state.domNodeDisposalCallback); @@ -1932,11 +1862,11 @@ var pureComputedOverrides = { } else { // First put the dependencies in order var dependenciesOrder = []; - ko.utils.objectForEach(state.dependencyTracking, function (id, dependency) { - dependenciesOrder[dependency._order] = id; - }); + ko.utils.objectForEach(state.dependencyTracking, (id, dependency) => + dependenciesOrder[dependency._order] = id + ); // Next, subscribe to each one - ko.utils.arrayForEach(dependenciesOrder, function (id, order) { + ko.utils.arrayForEach(dependenciesOrder, (id, order) => { var dependency = state.dependencyTracking[id], subscription = computedObservable.subscribeToDependency(dependency._target); subscription._order = order; @@ -1959,7 +1889,7 @@ var pureComputedOverrides = { afterSubscriptionRemove: function (event) { var state = this[computedState]; if (!state.isDisposed && event == 'change' && !this.hasSubscriptionsForEvent('change')) { - ko.utils.objectForEach(state.dependencyTracking, function (id, dependency) { + ko.utils.objectForEach(state.dependencyTracking, (id, dependency) => { if (dependency.dispose) { state.dependencyTracking[id] = { _target: dependency._target, @@ -2004,13 +1934,9 @@ if (ko.utils.canSetPrototype) { var protoProp = ko.observable.protoProperty; // == "__ko_proto__" computedFn[protoProp] = ko.computed; -ko.isComputed = function (instance) { - return (typeof instance == 'function' && instance[protoProp] === computedFn[protoProp]); -}; +ko.isComputed = instance => (typeof instance == 'function' && instance[protoProp] === computedFn[protoProp]); -ko.isPureComputed = function (instance) { - return ko.isComputed(instance) && instance[computedState] && instance[computedState].pure; -}; +ko.isPureComputed = instance => ko.isComputed(instance) && instance[computedState] && instance[computedState].pure; ko.exportSymbol('computed', ko.computed); ko.exportSymbol('dependentObservable', ko.computed); // export ko.dependentObservable for backwards compatibility (1.x) @@ -2023,20 +1949,19 @@ ko.exportProperty(computedFn, 'isActive', computedFn.isActive); ko.exportProperty(computedFn, 'getDependenciesCount', computedFn.getDependenciesCount); ko.exportProperty(computedFn, 'getDependencies', computedFn.getDependencies); -ko.pureComputed = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget) { +ko.pureComputed = (evaluatorFunctionOrOptions, evaluatorFunctionTarget) => { if (typeof evaluatorFunctionOrOptions === 'function') { return ko.computed(evaluatorFunctionOrOptions, evaluatorFunctionTarget, {'pure':true}); - } else { - evaluatorFunctionOrOptions = ko.utils.extend({}, evaluatorFunctionOrOptions); // make a copy of the parameter object - evaluatorFunctionOrOptions['pure'] = true; - return ko.computed(evaluatorFunctionOrOptions, evaluatorFunctionTarget); } -} + evaluatorFunctionOrOptions = ko.utils.extend({}, evaluatorFunctionOrOptions); // make a copy of the parameter object + evaluatorFunctionOrOptions['pure'] = true; + return ko.computed(evaluatorFunctionOrOptions, evaluatorFunctionTarget); +}; ko.exportSymbol('pureComputed', ko.pureComputed); -ko.when = function(predicate, callback, context) { +ko.when = (predicate, callback, context) => { function kowhen (resolve) { var observable = ko.pureComputed(predicate, context).extend({notify:'always'}); - var subscription = observable.subscribe(function(value) { + var subscription = observable.subscribe(value => { if (value) { subscription.dispose(); resolve(value); @@ -2047,21 +1972,18 @@ ko.when = function(predicate, callback, context) { return subscription; } - if (callback) { - return kowhen(callback.bind(context)); - } - return new Promise(kowhen); + return callback ? kowhen(callback.bind(context)) : new Promise(kowhen); }; ko.exportSymbol('when', ko.when); -(function () { +(() => { var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__'; // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns. ko.selectExtensions = { - readValue : function(element) { + readValue : element => { switch (ko.utils.tagNameLower(element)) { case 'option': if (element[hasDomDataExpandoProperty] === true) @@ -2074,7 +1996,7 @@ ko.exportSymbol('when', ko.when); } }, - writeValue: function(element, value, allowUnset) { + writeValue: (element, value, allowUnset) => { switch (ko.utils.tagNameLower(element)) { case 'option': if (typeof value === "string") { @@ -2120,7 +2042,7 @@ ko.exportSymbol('when', ko.when); ko.exportSymbol('selectExtensions', ko.selectExtensions); ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue); ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue); -ko.expressionRewriting = (function () { +ko.expressionRewriting = (() => { var javaScriptReservedWords = ["true", "false", "null", "undefined"]; // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor @@ -2150,7 +2072,7 @@ ko.expressionRewriting = (function () { "//.*\n", // Match a regular expression (text enclosed by slashes), but will also match sets of divisions // as a regular expression (this is handled by the parsing loop below). - '/(?:\\\\.|[^/])+/\w*', + '/(?:\\\\.|[^/])+/w*', // Match text (at least two characters) that does not contain any of the above special characters, // although some of the special characters are allowed to start it (all but the colon and comma). // The text can contain spaces, but leading or trailing spaces are skipped. @@ -2265,9 +2187,9 @@ ko.expressionRewriting = (function () { keyValueArray = typeof bindingsStringOrKeyValueArray === "string" ? parseObjectLiteral(bindingsStringOrKeyValueArray) : bindingsStringOrKeyValueArray; - ko.utils.arrayForEach(keyValueArray, function(keyValue) { - processKeyValue(keyValue.key || keyValue['unknown'], keyValue.value); - }); + ko.utils.arrayForEach(keyValueArray, keyValue => + processKeyValue(keyValue.key || keyValue['unknown'], keyValue.value) + ); if (propertyAccessorResultStrings.length) processKeyValue('_ko_property_writers', "{" + propertyAccessorResultStrings.join(",") + " }"); @@ -2284,7 +2206,7 @@ ko.expressionRewriting = (function () { preProcessBindings: preProcessBindings, - keyValueArrayContainsKey: function(keyValueArray, key) { + keyValueArrayContainsKey: (keyValueArray, key) => { for (var i = 0; i < keyValueArray.length; i++) if (keyValueArray[i]['key'] == key) return true; @@ -2300,7 +2222,7 @@ ko.expressionRewriting = (function () { // value: The value to be written // checkIfDifferent: If true, and if the property being written is a writable observable, the value will only be written if // it is !== existing value on that writable observable - writeValueToProperty: function(property, allBindings, key, value, checkIfDifferent) { + writeValueToProperty: (property, allBindings, key, value, checkIfDifferent) => { if (!property || !ko.isObservable(property)) { var propWriters = allBindings.get('_ko_property_writers'); if (propWriters && propWriters[key]) @@ -2316,21 +2238,7 @@ ko.exportSymbol('expressionRewriting', ko.expressionRewriting); ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators); ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral); ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings); - -// Making bindings explicitly declare themselves as "two way" isn't ideal in the long term (it would be better if -// all bindings could use an official 'property writer' API without needing to declare that they might). However, -// since this is not, and has never been, a public API (_ko_property_writers was never documented), it's acceptable -// as an internal implementation detail in the short term. -// For those developers who rely on _ko_property_writers in their custom bindings, we expose _twoWayBindings as an -// undocumented feature that makes it relatively easy to upgrade to KO 3.0. However, this is still not an official -// public API, and we reserve the right to remove it at any time if we create a real public property writers API. -ko.exportSymbol('expressionRewriting._twoWayBindings', ko.expressionRewriting.twoWayBindings); - -// For backward compatibility, define the following aliases. (Previously, these function names were misleading because -// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.) -ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting); -ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings); -(function() { +(() => { // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes // may be used to represent hierarchy (in addition to the DOM's natural hierarchy). // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state @@ -2384,18 +2292,16 @@ ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.ex if (allVirtualChildren.length > 0) return allVirtualChildren[allVirtualChildren.length - 1].nextSibling; return startComment.nextSibling; - } else - return null; // Must have no matching end comment, and allowUnbalanced is true + } + return null; // Must have no matching end comment, and allowUnbalanced is true } ko.virtualElements = { allowedBindings: {}, - childNodes: function(node) { - return isStartComment(node) ? getVirtualChildren(node) : node.childNodes; - }, + childNodes: node => isStartComment(node) ? getVirtualChildren(node) : node.childNodes, - emptyNode: function(node) { + emptyNode: node => { if (!isStartComment(node)) ko.utils.emptyDomNode(node); else { @@ -2405,7 +2311,7 @@ ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.ex } }, - setDomNodeChildren: function(node, childNodes) { + setDomNodeChildren: (node, childNodes) => { if (!isStartComment(node)) ko.utils.setDomNodeChildren(node, childNodes); else { @@ -2416,7 +2322,7 @@ ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.ex } }, - prepend: function(containerNode, nodeToPrepend) { + prepend: (containerNode, nodeToPrepend) => { var insertBeforeNode; if (isStartComment(containerNode)) { @@ -2430,7 +2336,7 @@ ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.ex containerNode.insertBefore(nodeToPrepend, insertBeforeNode); }, - insertAfter: function(containerNode, nodeToInsert, insertAfterNode) { + insertAfter: (containerNode, nodeToInsert, insertAfterNode) => { if (!insertAfterNode) { ko.virtualElements.prepend(containerNode, nodeToInsert); } else { @@ -2445,20 +2351,17 @@ ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.ex } }, - firstChild: function(node) { + firstChild: node => { if (!isStartComment(node)) { if (node.firstChild && isEndComment(node.firstChild)) { throw new Error("Found invalid end comment, as the first child of " + node); } return node.firstChild; - } else if (!node.nextSibling || isEndComment(node.nextSibling)) { - return null; - } else { - return node.nextSibling; } + return (!node.nextSibling || isEndComment(node.nextSibling)) ? null : node.nextSibling; }, - nextSibling: function(node) { + nextSibling: node => { if (isStartComment(node)) { node = getMatchingEndComment(node); } @@ -2466,17 +2369,15 @@ ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.ex if (node.nextSibling && isEndComment(node.nextSibling)) { if (isUnmatchedEndComment(node.nextSibling)) { throw Error("Found end comment without a matching opening comment, as child of " + node); - } else { - return null; } - } else { - return node.nextSibling; + return null; } + return node.nextSibling; }, hasBindingValue: isStartComment, - virtualNodeBindingValue: function(node) { + virtualNodeBindingValue: node => { var regexMatch = (node.nodeValue).match(startCommentRegex); return regexMatch ? regexMatch[1] : null; } @@ -2498,7 +2399,7 @@ ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomN }; ko.utils.extend(ko.bindingProvider.prototype, { - 'nodeHasBindings': function(node) { + 'nodeHasBindings': node => { switch (node.nodeType) { case 1: // Element return node.getAttribute(defaultBindingAttributeName) != null @@ -2523,12 +2424,12 @@ ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomN // The following function is only used internally by this default provider. // It's not part of the interface definition for a general binding provider. - 'getBindingsString': function(node, bindingContext) { + 'getBindingsString': (node, bindingContext) => { switch (node.nodeType) { case 1: return node.getAttribute(defaultBindingAttributeName); // Element case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node - default: return null; } + return null; }, // The following function is only used internally by this default provider. @@ -2563,7 +2464,7 @@ ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomN })(); ko.exportSymbol('bindingProvider', ko.bindingProvider); -(function () { +(() => { // Hide or don't minify context properties, see https://github.com/knockout/knockout/issues/2294 var contextSubscribable = Symbol('_subscribable'); var contextAncestorBindingInfo = Symbol('_ancestorBindingInfo'); @@ -2584,9 +2485,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); }; // Use an overridable method for retrieving binding handlers so that plugins may support dynamically created handlers - ko['getBindingHandler'] = function(bindingKey) { - return ko.bindingHandlers[bindingKey]; - }; + ko['getBindingHandler'] = bindingKey => ko.bindingHandlers[bindingKey]; var inheritParentVm = {}; @@ -2658,7 +2557,6 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); shouldInheritData = dataItemOrAccessor === inheritParentVm, realDataItemOrAccessor = shouldInheritData ? undefined : dataItemOrAccessor, isFunc = typeof(realDataItemOrAccessor) == "function" && !ko.isObservable(realDataItemOrAccessor), - nodes, subscribable, dataDependency = options && options['dataDependency']; @@ -2697,14 +2595,14 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); if (dataItemAlias && options && options['noChildContext']) { var isFunc = typeof(dataItemOrAccessor) == "function" && !ko.isObservable(dataItemOrAccessor); - return new ko.bindingContext(inheritParentVm, this, null, function (self) { + return new ko.bindingContext(inheritParentVm, this, null, self => { if (extendCallback) extendCallback(self); self[dataItemAlias] = isFunc ? dataItemOrAccessor() : dataItemOrAccessor; }, options); } - return new ko.bindingContext(dataItemOrAccessor, this, dataItemAlias, function (self, parentContext) { + return new ko.bindingContext(dataItemOrAccessor, this, dataItemAlias, (self, parentContext) => { // Extend the context hierarchy by setting the appropriate pointers self['$parentContext'] = parentContext; self['$parent'] = parentContext['$data']; @@ -2719,9 +2617,9 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); // Similarly to "child" contexts, provide a function here to make sure that the correct values are set // when an observable view model is updated. ko.bindingContext.prototype['extend'] = function(properties, options) { - return new ko.bindingContext(inheritParentVm, this, null, function(self, parentContext) { - ko.utils.extend(self, typeof(properties) == "function" ? properties(self) : properties); - }, options); + return new ko.bindingContext(inheritParentVm, this, null, self => + ko.utils.extend(self, typeof(properties) == "function" ? properties(self) : properties) + , options); }; var boundElementDomDataKey = ko.utils.domData.nextKey(); @@ -2774,7 +2672,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); childrenComplete: "childrenComplete", descendantsComplete : "descendantsComplete", - subscribe: function (node, event, callback, context, options) { + subscribe: (node, event, callback, context, options) => { var bindingInfo = ko.utils.domData.getOrSet(node, boundElementDomDataKey, {}); if (!bindingInfo.eventSubscribable) { bindingInfo.eventSubscribable = new ko.subscribable; @@ -2785,7 +2683,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); return bindingInfo.eventSubscribable.subscribe(callback, context, event); }, - notify: function (node, event) { + notify: (node, event) => { var bindingInfo = ko.utils.domData.get(node, boundElementDomDataKey); if (bindingInfo) { bindingInfo.notifiedEvents[event] = true; @@ -2804,7 +2702,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); } }, - startPossiblyAsyncContentBinding: function (node, bindingContext) { + startPossiblyAsyncContentBinding: (node, bindingContext) => { var bindingInfo = ko.utils.domData.getOrSet(node, boundElementDomDataKey, {}); if (!bindingInfo.asyncContext) { @@ -2816,7 +2714,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); return bindingContext; } - return bindingContext['extend'](function (ctx) { + return bindingContext['extend'](ctx => { ctx[contextAncestorBindingInfo] = bindingInfo; }); } @@ -3004,28 +2902,19 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); // context update), just return the value accessor from the binding. Otherwise, return a function that always gets // the latest binding value and registers a dependency on the binding updater. var getValueAccessor = bindingsUpdater - ? function(bindingKey) { - return function() { - return evaluateValueAccessor(bindingsUpdater()[bindingKey]); - }; - } : function(bindingKey) { - return bindings[bindingKey]; - }; + ? bindingKey => () => evaluateValueAccessor(bindingsUpdater()[bindingKey]) + : bindingKey => bindings[bindingKey]; // Use of allBindings as a function is maintained for backwards compatibility, but its use is deprecated function allBindings() { return ko.utils.objectMap(bindingsUpdater ? bindingsUpdater() : bindings, evaluateValueAccessor); } // The following is the 3.x allBindings API - allBindings['get'] = function(key) { - return bindings[key] && evaluateValueAccessor(getValueAccessor(key)); - }; - allBindings['has'] = function(key) { - return key in bindings; - }; + allBindings['get'] = key => bindings[key] && evaluateValueAccessor(getValueAccessor(key)); + allBindings['has'] = key => key in bindings; if (ko.bindingEvent.childrenComplete in bindings) { - ko.bindingEvent.subscribe(node, ko.bindingEvent.childrenComplete, function () { + ko.bindingEvent.subscribe(node, ko.bindingEvent.childrenComplete, () => { var callback = evaluateValueAccessor(bindings[ko.bindingEvent.childrenComplete]); if (callback) { var nodes = ko.virtualElements.childNodes(node); @@ -3064,7 +2953,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); try { // Run init, ignoring any dependencies if (typeof handlerInitFn == "function") { - ko.dependencyDetection.ignore(function() { + ko.dependencyDetection.ignore(() => { var initResult = handlerInitFn(node, getValueAccessor(bindingKey), allBindings, contextToExtend['$data'], contextToExtend); // If this binding handler claims to control descendant bindings, make a note of this @@ -3079,9 +2968,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); // Run update in its own computed wrapper if (typeof handlerUpdateFn == "function") { ko.dependentObservable( - function() { - handlerUpdateFn(node, getValueAccessor(bindingKey), allBindings, contextToExtend['$data'], contextToExtend); - }, + () => handlerUpdateFn(node, getValueAccessor(bindingKey), allBindings, contextToExtend['$data'], contextToExtend), null, { disposeWhenNodeIsRemoved: node } ); @@ -3098,9 +2985,9 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); 'shouldBindDescendants': shouldBindDescendants, 'bindingContextForDescendants': shouldBindDescendants && contextToExtend }; - }; + } - ko.storedBindingContextForNode = function (node) { + ko.storedBindingContextForNode = node => { var bindingInfo = ko.utils.domData.get(node, boundElementDomDataKey); return bindingInfo && bindingInfo.context; } @@ -3111,16 +2998,15 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); : new ko.bindingContext(viewModelOrBindingContext, undefined, undefined, extendContextCallback); } - ko.applyBindingAccessorsToNode = function (node, bindings, viewModelOrBindingContext) { - return applyBindingsToNodeInternal(node, bindings, getBindingContext(viewModelOrBindingContext)); - }; + ko.applyBindingAccessorsToNode = (node, bindings, viewModelOrBindingContext) => + applyBindingsToNodeInternal(node, bindings, getBindingContext(viewModelOrBindingContext)); - ko.applyBindingsToNode = function (node, bindings, viewModelOrBindingContext) { + ko.applyBindingsToNode = (node, bindings, viewModelOrBindingContext) => { var context = getBindingContext(viewModelOrBindingContext); return ko.applyBindingAccessorsToNode(node, makeBindingAccessors(bindings, context, node), context); }; - ko.applyBindingsToDescendants = function(viewModelOrBindingContext, rootNode) { + ko.applyBindingsToDescendants = (viewModelOrBindingContext, rootNode) => { if (rootNode.nodeType === 1 || rootNode.nodeType === 8) applyBindingsToDescendantsInternal(getBindingContext(viewModelOrBindingContext), rootNode); }; @@ -3139,13 +3025,13 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); }; // Retrieving binding context from arbitrary nodes - ko.contextFor = function(node) { + ko.contextFor = node => { // We can only do something meaningful for elements and comment nodes (in particular, not text nodes, as IE can't store domdata for them) if (node && (node.nodeType === 1 || node.nodeType === 8)) { return ko.storedBindingContextForNode(node); } }; - ko.dataFor = function(node) { + ko.dataFor = node => { var context = ko.contextFor(node); return context ? context['$data'] : undefined; }; @@ -3160,23 +3046,23 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode); ko.exportSymbol('dataFor', ko.dataFor); })(); -(function(undefined) { +(() => { var loadingSubscribablesCache = {}, // Tracks component loads that are currently in flight loadedDefinitionsCache = {}; // Tracks component loads that have already completed ko.components = { - get: function(componentName, callback) { + get: (componentName, callback) => { var cachedDefinition = getObjectOwnProperty(loadedDefinitionsCache, componentName); if (cachedDefinition) { // It's already loaded and cached. Reuse the same definition object. // Note that for API consistency, even cache hits complete asynchronously by default. // You can bypass this by putting synchronous:true on your component config. if (cachedDefinition.isSynchronousComponent) { - ko.dependencyDetection.ignore(function() { // See comment in loaderRegistryBehaviors.js for reasoning - callback(cachedDefinition.definition); - }); + ko.dependencyDetection.ignore(() => // See comment in loaderRegistryBehaviors.js for reasoning + callback(cachedDefinition.definition) + ); } else { - ko.tasks.schedule(function() { callback(cachedDefinition.definition); }); + ko.tasks.schedule(() => callback(cachedDefinition.definition) ); } } else { // Join the loading process that is already underway, or start a new one. @@ -3184,9 +3070,9 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); } }, - clearCachedDefinition: function(componentName) { - delete loadedDefinitionsCache[componentName]; - }, + clearCachedDefinition: componentName => + delete loadedDefinitionsCache[componentName] + , _getFirstResultFromLoaders: getFirstResultFromLoaders }; @@ -3203,7 +3089,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); subscribable = loadingSubscribablesCache[componentName] = new ko.subscribable(); subscribable.subscribe(callback); - beginLoadingComponent(componentName, function(definition, config) { + beginLoadingComponent(componentName, (definition, config) => { var isSynchronousComponent = !!(config && config['synchronous']); loadedDefinitionsCache[componentName] = { definition: definition, isSynchronousComponent: isSynchronousComponent }; delete loadingSubscribablesCache[componentName]; @@ -3219,9 +3105,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); // See comment in loaderRegistryBehaviors.js for reasoning subscribable['notifySubscribers'](definition); } else { - ko.tasks.schedule(function() { - subscribable['notifySubscribers'](definition); - }); + ko.tasks.schedule(() => subscribable['notifySubscribers'](definition)); } }); completedAsync = true; @@ -3231,12 +3115,12 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); } function beginLoadingComponent(componentName, callback) { - getFirstResultFromLoaders('getConfig', [componentName], function(config) { + getFirstResultFromLoaders('getConfig', [componentName], config => { if (config) { // We have a config, so now load its definition - getFirstResultFromLoaders('loadComponent', [componentName, config], function(definition) { - callback(definition, config); - }); + getFirstResultFromLoaders('loadComponent', [componentName, config], definition => + callback(definition, config) + ); } else { // The component has no config - it's unknown to all the loaders. // Note that this is not an error (e.g., a module loading error) - that would abort the @@ -3302,7 +3186,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); ko.exportSymbol('components.get', ko.components.get); ko.exportSymbol('components.clearCachedDefinition', ko.components.clearCachedDefinition); })(); -(function(undefined) { +(() => { // The default loader is responsible for two things: // 1. Maintaining the default in-memory registry of component configuration objects @@ -3316,7 +3200,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); var defaultConfigRegistry = {}; - ko.components.register = function(componentName, config) { + ko.components.register = (componentName, config) => { if (!config) { throw new Error('Invalid configuration for ' + componentName); } @@ -3328,37 +3212,35 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); defaultConfigRegistry[componentName] = config; }; - ko.components.isRegistered = function(componentName) { - return Object.prototype.hasOwnProperty.call(defaultConfigRegistry, componentName); - }; + ko.components.isRegistered = componentName => + Object.prototype.hasOwnProperty.call(defaultConfigRegistry, componentName); - ko.components.unregister = function(componentName) { + ko.components.unregister = componentName => { delete defaultConfigRegistry[componentName]; ko.components.clearCachedDefinition(componentName); }; ko.components.defaultLoader = { - 'getConfig': function(componentName, callback) { + 'getConfig': (componentName, callback) => { var result = ko.components.isRegistered(componentName) ? defaultConfigRegistry[componentName] : null; callback(result); }, - 'loadComponent': function(componentName, config, callback) { + 'loadComponent': (componentName, config, callback) => { var errorCallback = makeErrorCallback(componentName); - possiblyGetConfigFromAmd(errorCallback, config, function(loadedConfig) { - resolveConfig(componentName, errorCallback, loadedConfig, callback); - }); + possiblyGetConfigFromAmd(errorCallback, config, loadedConfig => + resolveConfig(componentName, errorCallback, loadedConfig, callback) + ); }, - 'loadTemplate': function(componentName, templateConfig, callback) { - resolveTemplate(makeErrorCallback(componentName), templateConfig, callback); - }, + 'loadTemplate': (componentName, templateConfig, callback) => + resolveTemplate(makeErrorCallback(componentName), templateConfig, callback) + , - 'loadViewModel': function(componentName, viewModelConfig, callback) { - resolveViewModel(makeErrorCallback(componentName), viewModelConfig, callback); - } + 'loadViewModel': (componentName, viewModelConfig, callback) => + resolveViewModel(makeErrorCallback(componentName), viewModelConfig, callback) }; var createViewModelKey = 'createViewModel'; @@ -3372,7 +3254,7 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); function resolveConfig(componentName, errorCallback, config, callback) { var result = {}, makeCallBackWhenZero = 2, - tryIssueCallback = function() { + tryIssueCallback = () => { if (--makeCallBackWhenZero === 0) { callback(result); } @@ -3381,23 +3263,23 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); viewModelConfig = config['viewModel']; if (templateConfig) { - possiblyGetConfigFromAmd(errorCallback, templateConfig, function(loadedConfig) { - ko.components._getFirstResultFromLoaders('loadTemplate', [componentName, loadedConfig], function(resolvedTemplate) { + possiblyGetConfigFromAmd(errorCallback, templateConfig, loadedConfig => + ko.components._getFirstResultFromLoaders('loadTemplate', [componentName, loadedConfig], resolvedTemplate => { result['template'] = resolvedTemplate; tryIssueCallback(); - }); - }); + }) + ); } else { tryIssueCallback(); } if (viewModelConfig) { - possiblyGetConfigFromAmd(errorCallback, viewModelConfig, function(loadedConfig) { - ko.components._getFirstResultFromLoaders('loadViewModel', [componentName, loadedConfig], function(resolvedViewModel) { + possiblyGetConfigFromAmd(errorCallback, viewModelConfig, loadedConfig => + ko.components._getFirstResultFromLoaders('loadViewModel', [componentName, loadedConfig], resolvedViewModel => { result[createViewModelKey] = resolvedViewModel; tryIssueCallback(); - }); - }); + }) + ); } else { tryIssueCallback(); } @@ -3410,12 +3292,12 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); } else if (templateConfig instanceof Array) { // Assume already an array of DOM nodes - pass through unchanged callback(templateConfig); - } else if (isDocumentFragment(templateConfig)) { + } else if (templateConfig instanceof DocumentFragment) { // Document fragment - use its child nodes callback(ko.utils.makeArray(templateConfig.childNodes)); } else if (templateConfig['element']) { var element = templateConfig['element']; - if (isDomElement(element)) { + if (element instanceof HTMLElement) { // Element instance - copy its child nodes callback(cloneNodesFromTemplateSourceElement(element)); } else if (typeof element === 'string') { @@ -3440,18 +3322,14 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); // By design, this does *not* supply componentInfo to the constructor, as the intent is that // componentInfo contains non-viewmodel data (e.g., the component's element) that should only // be used in factory functions, not viewmodel constructors. - callback(function (params /*, componentInfo */) { - return new viewModelConfig(params); - }); + callback(params => new viewModelConfig(params)); } else if (typeof viewModelConfig[createViewModelKey] === 'function') { // Already a factory function - use it as-is callback(viewModelConfig[createViewModelKey]); } else if ('instance' in viewModelConfig) { // Fixed object instance - promote to createViewModel format for API consistency var fixedInstance = viewModelConfig['instance']; - callback(function (params, componentInfo) { - return fixedInstance; - }); + callback(() => fixedInstance); } else if ('viewModel' in viewModelConfig) { // Resolved AMD module whose value is of the form { viewModel: ... } resolveViewModel(errorCallback, viewModelConfig['viewModel'], callback); @@ -3464,34 +3342,18 @@ ko.exportSymbol('bindingProvider', ko.bindingProvider); if ('template' == ko.utils.tagNameLower(elemInstance)) { // For browsers with proper