in public/dexie.js [2811:2933]
function (resolve, reject, idbstore) {
if (!idbstore.keyPath && !_this.schema.primKey.auto && !keys$$1)
throw new exceptions.InvalidArgument(
"bulkPut() with non-inbound keys requires keys array in second argument"
);
if (idbstore.keyPath && keys$$1)
throw new exceptions.InvalidArgument(
"bulkPut(): keys argument invalid on tables with inbound keys"
);
if (keys$$1 && keys$$1.length !== objects.length)
throw new exceptions.InvalidArgument(
"Arguments objects and keys must have the same length"
);
if (objects.length === 0) return resolve(); // Caller provided empty list.
var done = function (result) {
if (errorList.length === 0) resolve(result);
else
reject(
new BulkError(
_this.name +
".bulkPut(): " +
errorList.length +
" of " +
numObjs +
" operations failed",
errorList
)
);
};
var req,
errorList = [],
errorHandler,
numObjs = objects.length,
table = _this;
if (
_this.hook.creating.fire === nop &&
_this.hook.updating.fire === nop
) {
//
// Standard Bulk (no 'creating' or 'updating' hooks to care about)
//
errorHandler = BulkErrorHandlerCatchAll(errorList);
for (var i = 0, l = objects.length; i < l; ++i) {
req = keys$$1
? idbstore.put(objects[i], keys$$1[i])
: idbstore.put(objects[i]);
req.onerror = errorHandler;
}
// Only need to catch success or error on the last operation
// according to the IDB spec.
req.onerror = BulkErrorHandlerCatchAll(errorList, done);
req.onsuccess = eventSuccessHandler(done);
} else {
var effectiveKeys =
keys$$1 ||
(idbstore.keyPath &&
objects.map(function (o) {
return getByKeyPath(o, idbstore.keyPath);
}));
// Generate map of {[key]: object}
var objectLookup =
effectiveKeys &&
arrayToObject(effectiveKeys, function (key, i) {
return key != null && [key, objects[i]];
});
var promise = !effectiveKeys
? // Auto-incremented key-less objects only without any keys argument.
table.bulkAdd(objects)
: // Keys provided. Either as inbound in provided objects, or as a keys argument.
// Begin with updating those that exists in DB:
table
.where(":id")
.anyOf(
effectiveKeys.filter(function (key) {
return key != null;
})
)
.modify(function () {
this.value = objectLookup[this.primKey];
objectLookup[this.primKey] = null; // Mark as "don't add this"
})
.catch(ModifyError, function (e) {
errorList = e.failures; // No need to concat here. These are the first errors added.
})
.then(function () {
// Now, let's examine which items didnt exist so we can add them:
var objsToAdd = [],
keysToAdd = keys$$1 && [];
// Iterate backwards. Why? Because if same key was used twice, just add the last one.
for (var i = effectiveKeys.length - 1; i >= 0; --i) {
var key = effectiveKeys[i];
if (key == null || objectLookup[key]) {
objsToAdd.push(objects[i]);
keys$$1 && keysToAdd.push(key);
if (key != null) objectLookup[key] = null; // Mark as "dont add again"
}
}
// The items are in reverse order so reverse them before adding.
// Could be important in order to get auto-incremented keys the way the caller
// would expect. Could have used unshift instead of push()/reverse(),
// but: http://jsperf.com/unshift-vs-reverse
objsToAdd.reverse();
keys$$1 && keysToAdd.reverse();
return table.bulkAdd(objsToAdd, keysToAdd);
})
.then(function (lastAddedKey) {
// Resolve with key of the last object in given arguments to bulkPut():
var lastEffectiveKey =
effectiveKeys[effectiveKeys.length - 1]; // Key was provided.
return lastEffectiveKey != null
? lastEffectiveKey
: lastAddedKey;
});
promise
.then(done)
.catch(BulkError, function (e) {
// Concat failure from ModifyError and reject using our 'done' method.
errorList = errorList.concat(e.failures);
done();
})
.catch(reject);
}
},