whole_func_string: function (nodes) {
      return new Promise((resolve, reject) => {
  
        let transaction = this.db.transaction(['nodes'], 'readwrite');
        let nodesStore = transaction.objectStore('nodes');
        let startTime = new Date().getTime();
  
        this.putsRunning++;
  
        log('[IndexedDB] Starting put', nodes, this.putsRunning);
  
        for (var path in nodes) {
          var node = nodes[path];
          if(typeof(node) === 'object') {
            try {
              nodesStore.put(node);
            } catch(e) {
              log('[IndexedDB] Error while putting', node, e);
              throw e;
            }
          } else {
            try {
              nodesStore.delete(path);
            } catch(e) {
              log('[IndexedDB] Error while removing', nodesStore, node, e);
              throw e;
            }
          }
        }
  
        transaction.oncomplete = function () {
          this.putsRunning--;
          log('[IndexedDB] Finished put', nodes, this.putsRunning, (new Date().getTime() - startTime)+'ms');
          resolve();
        }.bind(this);
  
        transaction.onerror = function () {
          this.putsRunning--;
          reject('transaction error');
        }.bind(this);
  
        transaction.onabort = function () {
          reject('transaction abort');
          this.putsRunning--;
        }.bind(this);
  
      });
    }
func_code_string: function (nodes) {
      return new Promise((resolve, reject) => {
  
        let transaction = this.db.transaction(['nodes'], 'readwrite');
        let nodesStore = transaction.objectStore('nodes');
        let startTime = new Date().getTime();
  
        this.putsRunning++;
  
        log('[IndexedDB] Starting put', nodes, this.putsRunning);
  
        for (var path in nodes) {
          var node = nodes[path];
          if(typeof(node) === 'object') {
            try {
              nodesStore.put(node);
            } catch(e) {
              log('[IndexedDB] Error while putting', node, e);
              throw e;
            }
          } else {
            try {
              nodesStore.delete(path);
            } catch(e) {
              log('[IndexedDB] Error while removing', nodesStore, node, e);
              throw e;
            }
          }
        }
  
        transaction.oncomplete = function () {
          this.putsRunning--;
          log('[IndexedDB] Finished put', nodes, this.putsRunning, (new Date().getTime() - startTime)+'ms');
          resolve();
        }.bind(this);
  
        transaction.onerror = function () {
          this.putsRunning--;
          reject('transaction error');
        }.bind(this);
  
        transaction.onabort = function () {
          reject('transaction abort');
          this.putsRunning--;
        }.bind(this);
  
      });
    }
func_documentation_string: TODO: Document