Commit 9aff3608 authored by Vincent Bechu's avatar Vincent Bechu

erp5_web_renderjs_ui: Release v3.19.0 Jio

parent 96a9d8c5
...@@ -8428,6 +8428,15 @@ return new Parser; ...@@ -8428,6 +8428,15 @@ return new Parser;
CONFLICT_KEEP_REMOTE = 2, CONFLICT_KEEP_REMOTE = 2,
CONFLICT_CONTINUE = 3; CONFLICT_CONTINUE = 3;
function SkipError(message) {
if ((message !== undefined) && (typeof message !== "string")) {
throw new TypeError('You must pass a string.');
}
this.message = message || "Skip some asynchronous code";
}
SkipError.prototype = new Error();
SkipError.prototype.constructor = SkipError;
/**************************************************** /****************************************************
Use a local jIO to read/write/search documents Use a local jIO to read/write/search documents
Synchronize in background those document with a remote jIO. Synchronize in background those document with a remote jIO.
...@@ -8446,20 +8455,33 @@ return new Parser; ...@@ -8446,20 +8455,33 @@ return new Parser;
function ReplicateStorage(spec) { function ReplicateStorage(spec) {
this._query_options = spec.query || {}; this._query_options = spec.query || {};
if (spec.signature_hash_key !== undefined) {
this._query_options.select_list = [spec.signature_hash_key];
}
this._signature_hash_key = spec.signature_hash_key;
this._local_sub_storage = jIO.createJIO(spec.local_sub_storage); this._local_sub_storage = jIO.createJIO(spec.local_sub_storage);
this._remote_sub_storage = jIO.createJIO(spec.remote_sub_storage); this._remote_sub_storage = jIO.createJIO(spec.remote_sub_storage);
this._signature_hash = "_replicate_" + generateHash( if (spec.hasOwnProperty('signature_sub_storage')) {
stringify(spec.local_sub_storage) + this._signature_sub_storage = jIO.createJIO(spec.signature_sub_storage);
stringify(spec.remote_sub_storage) + this._custom_signature_sub_storage = true;
stringify(this._query_options) } else {
); this._signature_hash = "_replicate_" + generateHash(
this._signature_sub_storage = jIO.createJIO({ stringify(spec.local_sub_storage) +
type: "document", stringify(spec.remote_sub_storage) +
document_id: this._signature_hash, stringify(this._query_options)
sub_storage: spec.signature_storage || spec.local_sub_storage );
}); this._signature_sub_storage = jIO.createJIO({
type: "query",
sub_storage: {
type: "document",
document_id: this._signature_hash,
sub_storage: spec.local_sub_storage
}
});
this._custom_signature_sub_storage = false;
}
this._use_remote_post = spec.use_remote_post || false; this._use_remote_post = spec.use_remote_post || false;
// Number of request we allow browser execution for attachments // Number of request we allow browser execution for attachments
...@@ -8602,798 +8624,888 @@ return new Parser; ...@@ -8602,798 +8624,888 @@ return new Parser;
arguments); arguments);
}; };
ReplicateStorage.prototype.repair = function () { function dispatchQueue(context, function_used, argument_list,
var context = this, number_queue) {
argument_list = arguments, var result_promise_list = [],
skip_document_dict = {}; i;
// Do not sync the signature document
skip_document_dict[context._signature_hash] = null;
function dispatchQueue(function_used, argument_list, number_queue) {
var result_promise_list = [],
i;
function pushAndExecute(queue) {
queue
.push(function () {
if (argument_list.length > 0) {
var argument_array = argument_list.shift(),
sub_queue = new RSVP.Queue();
argument_array[0] = sub_queue;
function_used.apply(context, argument_array);
pushAndExecute(queue);
return sub_queue;
}
});
}
for (i = 0; i < number_queue; i += 1) {
result_promise_list.push(new RSVP.Queue());
pushAndExecute(result_promise_list[i]);
}
if (number_queue > 1) {
return RSVP.all(result_promise_list);
}
return result_promise_list[0];
}
function propagateAttachmentDeletion(skip_attachment_dict, function pushAndExecute(queue) {
destination, queue
id, name) {
return destination.removeAttachment(id, name)
.push(function () {
return context._signature_sub_storage.removeAttachment(id, name);
})
.push(function () { .push(function () {
skip_attachment_dict[name] = null; if (argument_list.length > 0) {
var argument_array = argument_list.shift(),
sub_queue = new RSVP.Queue();
argument_array[0] = sub_queue;
function_used.apply(context, argument_array);
pushAndExecute(queue);
return sub_queue;
}
}); });
} }
for (i = 0; i < number_queue; i += 1) {
function propagateAttachmentModification(skip_attachment_dict, result_promise_list.push(new RSVP.Queue());
destination, pushAndExecute(result_promise_list[i]);
blob, hash, id, name) { }
return destination.putAttachment(id, name, blob) if (number_queue > 1) {
.push(function () { return RSVP.all(result_promise_list);
return context._signature_sub_storage.putAttachment(id, name,
JSON.stringify({
hash: hash
}));
})
.push(function () {
skip_attachment_dict[name] = null;
});
} }
return result_promise_list[0];
}
function checkAndPropagateAttachment(skip_attachment_dict, function callAllDocsOnStorage(context, storage, cache, cache_key) {
status_hash, local_hash, blob, return new RSVP.Queue()
source, destination, id, name, .push(function () {
conflict_force, conflict_revert, if (!cache.hasOwnProperty(cache_key)) {
conflict_ignore) { return storage.allDocs(context._query_options)
var remote_blob; .push(function (result) {
return destination.getAttachment(id, name) var i,
.push(function (result) { cache_entry = {};
remote_blob = result; for (i = 0; i < result.data.total_rows; i += 1) {
return jIO.util.readBlobAsArrayBuffer(remote_blob); cache_entry[result.data.rows[i].id] = result.data.rows[i].value;
}) }
.push(function (evt) { cache[cache_key] = cache_entry;
return generateHashFromArrayBuffer( });
evt.target.result }
); })
}, function (error) { .push(function () {
if ((error instanceof jIO.util.jIOError) && return cache[cache_key];
(error.status_code === 404)) { });
remote_blob = null; }
return null;
}
throw error;
})
.push(function (remote_hash) {
if (local_hash === remote_hash) {
// Same modifications on both side
if (local_hash === null) {
// Deleted on both side, drop signature
return context._signature_sub_storage.removeAttachment(id, name)
.push(function () {
skip_attachment_dict[id] = null;
});
}
return context._signature_sub_storage.putAttachment(id, name, function propagateAttachmentDeletion(context, skip_attachment_dict,
JSON.stringify({ destination,
hash: local_hash id, name) {
})) return destination.removeAttachment(id, name)
.push(function () {
return context._signature_sub_storage.removeAttachment(id, name);
})
.push(function () {
skip_attachment_dict[name] = null;
});
}
function propagateAttachmentModification(context, skip_attachment_dict,
destination,
blob, hash, id, name) {
return destination.putAttachment(id, name, blob)
.push(function () {
return context._signature_sub_storage.putAttachment(id, name,
JSON.stringify({
hash: hash
}));
})
.push(function () {
skip_attachment_dict[name] = null;
});
}
function checkAndPropagateAttachment(context,
skip_attachment_dict,
status_hash, local_hash, blob,
source, destination, id, name,
conflict_force, conflict_revert,
conflict_ignore) {
var remote_blob;
return destination.getAttachment(id, name)
.push(function (result) {
remote_blob = result;
return jIO.util.readBlobAsArrayBuffer(remote_blob);
})
.push(function (evt) {
return generateHashFromArrayBuffer(
evt.target.result
);
}, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
remote_blob = null;
return null;
}
throw error;
})
.push(function (remote_hash) {
if (local_hash === remote_hash) {
// Same modifications on both side
if (local_hash === null) {
// Deleted on both side, drop signature
return context._signature_sub_storage.removeAttachment(id, name)
.push(function () { .push(function () {
skip_document_dict[id] = null; skip_attachment_dict[name] = null;
}); });
} }
if ((remote_hash === status_hash) || (conflict_force === true)) { return context._signature_sub_storage.putAttachment(id, name,
// Modified only locally. No conflict or force JSON.stringify({
if (local_hash === null) { hash: local_hash
// Deleted locally }))
return propagateAttachmentDeletion(skip_attachment_dict, .push(function () {
destination, skip_attachment_dict[name] = null;
id, name); });
} }
return propagateAttachmentModification(skip_attachment_dict,
destination, blob,
local_hash, id, name);
}
// Conflict cases if ((remote_hash === status_hash) || (conflict_force === true)) {
if (conflict_ignore === true) { // Modified only locally. No conflict or force
return; if (local_hash === null) {
// Deleted locally
return propagateAttachmentDeletion(context, skip_attachment_dict,
destination,
id, name);
} }
return propagateAttachmentModification(context,
skip_attachment_dict,
destination, blob,
local_hash, id, name);
}
if ((conflict_revert === true) || (local_hash === null)) { // Conflict cases
// Automatically resolve conflict or force revert if (conflict_ignore === true) {
if (remote_hash === null) { return;
// Deleted remotely }
return propagateAttachmentDeletion(skip_attachment_dict,
source, id, name);
}
return propagateAttachmentModification(
skip_attachment_dict,
source,
remote_blob,
remote_hash,
id,
name
);
}
// Minimize conflict if it can be resolved if ((conflict_revert === true) || (local_hash === null)) {
// Automatically resolve conflict or force revert
if (remote_hash === null) { if (remote_hash === null) {
// Copy remote modification remotely // Deleted remotely
return propagateAttachmentModification(skip_attachment_dict, return propagateAttachmentDeletion(context, skip_attachment_dict,
destination, blob, source, id, name);
local_hash, id, name);
}
throw new jIO.util.jIOError("Conflict on '" + id +
"' with attachment '" +
name + "'",
409);
});
}
function checkAttachmentSignatureDifference(queue, skip_attachment_dict,
source,
destination, id, name,
conflict_force,
conflict_revert,
conflict_ignore,
is_creation, is_modification) {
var blob,
status_hash;
queue
.push(function () {
// Optimisation to save a get call to signature storage
if (is_creation === true) {
return RSVP.all([
source.getAttachment(id, name),
{hash: null}
]);
}
if (is_modification === true) {
return RSVP.all([
source.getAttachment(id, name),
context._signature_sub_storage.getAttachment(
id,
name,
{format: 'json'}
)
]);
} }
throw new jIO.util.jIOError("Unexpected call of" return propagateAttachmentModification(
+ " checkAttachmentSignatureDifference", context,
409); skip_attachment_dict,
}) source,
.push(function (result_list) { remote_blob,
blob = result_list[0]; remote_hash,
status_hash = result_list[1].hash; id,
return jIO.util.readBlobAsArrayBuffer(blob); name
}) );
.push(function (evt) { }
var array_buffer = evt.target.result,
local_hash = generateHashFromArrayBuffer(array_buffer);
if (local_hash !== status_hash) {
return checkAndPropagateAttachment(skip_attachment_dict,
status_hash, local_hash, blob,
source, destination, id, name,
conflict_force, conflict_revert,
conflict_ignore);
}
});
}
function checkAttachmentLocalDeletion(queue, skip_attachment_dict,
destination, id, name, source,
conflict_force, conflict_revert,
conflict_ignore) {
var status_hash;
queue
.push(function () {
return context._signature_sub_storage.getAttachment(id, name,
{format: 'json'});
})
.push(function (result) {
status_hash = result.hash;
return checkAndPropagateAttachment(skip_attachment_dict,
status_hash, null, null,
source, destination, id, name,
conflict_force, conflict_revert,
conflict_ignore);
});
}
function pushDocumentAttachment(skip_attachment_dict, id, source, // Minimize conflict if it can be resolved
destination, options) { if (remote_hash === null) {
var queue = new RSVP.Queue(), // Copy remote modification remotely
local_dict = {}, return propagateAttachmentModification(context,
signature_dict = {}; skip_attachment_dict,
destination, blob,
local_hash, id, name);
}
throw new jIO.util.jIOError("Conflict on '" + id +
"' with attachment '" +
name + "'",
409);
});
}
return queue function checkAttachmentSignatureDifference(queue, context,
.push(function () { skip_attachment_dict,
source,
destination, id, name,
conflict_force,
conflict_revert,
conflict_ignore,
is_creation, is_modification) {
var blob,
status_hash;
queue
.push(function () {
// Optimisation to save a get call to signature storage
if (is_creation === true) {
return RSVP.all([ return RSVP.all([
source.allAttachments(id) source.getAttachment(id, name),
.push(undefined, function (error) { {hash: null}
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
return {};
}
throw error;
}),
context._signature_sub_storage.allAttachments(id)
.push(undefined, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
return {};
}
throw error;
})
]); ]);
}) }
.push(function (result_list) { if (is_modification === true) {
var is_modification, return RSVP.all([
is_creation, source.getAttachment(id, name),
key, context._signature_sub_storage.getAttachment(
argument_list = []; id,
for (key in result_list[0]) { name,
if (result_list[0].hasOwnProperty(key)) { {format: 'json'}
if (!skip_attachment_dict.hasOwnProperty(key)) { )
local_dict[key] = null; ]);
} }
throw new jIO.util.jIOError("Unexpected call of"
+ " checkAttachmentSignatureDifference",
409);
})
.push(function (result_list) {
blob = result_list[0];
status_hash = result_list[1].hash;
return jIO.util.readBlobAsArrayBuffer(blob);
})
.push(function (evt) {
var array_buffer = evt.target.result,
local_hash = generateHashFromArrayBuffer(array_buffer);
if (local_hash !== status_hash) {
return checkAndPropagateAttachment(context,
skip_attachment_dict,
status_hash, local_hash, blob,
source, destination, id, name,
conflict_force, conflict_revert,
conflict_ignore);
}
});
}
function checkAttachmentLocalDeletion(queue, context,
skip_attachment_dict,
destination, id, name, source,
conflict_force, conflict_revert,
conflict_ignore) {
var status_hash;
queue
.push(function () {
return context._signature_sub_storage.getAttachment(id, name,
{format: 'json'});
})
.push(function (result) {
status_hash = result.hash;
return checkAndPropagateAttachment(context,
skip_attachment_dict,
status_hash, null, null,
source, destination, id, name,
conflict_force, conflict_revert,
conflict_ignore);
});
}
function pushDocumentAttachment(context,
skip_attachment_dict, id, source,
destination, signature_allAttachments,
options) {
var local_dict = {},
signature_dict = {};
return source.allAttachments(id)
.push(undefined, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
return {};
}
throw error;
})
.push(function (source_allAttachments) {
var is_modification,
is_creation,
key,
argument_list = [];
for (key in source_allAttachments) {
if (source_allAttachments.hasOwnProperty(key)) {
if (!skip_attachment_dict.hasOwnProperty(key)) {
local_dict[key] = null;
} }
} }
for (key in result_list[1]) { }
if (result_list[1].hasOwnProperty(key)) { for (key in signature_allAttachments) {
if (!skip_attachment_dict.hasOwnProperty(key)) { if (signature_allAttachments.hasOwnProperty(key)) {
signature_dict[key] = null; if (!skip_attachment_dict.hasOwnProperty(key)) {
} signature_dict[key] = null;
} }
} }
}
for (key in local_dict) { for (key in local_dict) {
if (local_dict.hasOwnProperty(key)) { if (local_dict.hasOwnProperty(key)) {
is_modification = signature_dict.hasOwnProperty(key) is_modification = signature_dict.hasOwnProperty(key)
&& options.check_modification; && options.check_modification;
is_creation = !signature_dict.hasOwnProperty(key) is_creation = !signature_dict.hasOwnProperty(key)
&& options.check_creation; && options.check_creation;
if (is_modification === true || is_creation === true) { if (is_modification === true || is_creation === true) {
argument_list.push([undefined,
context,
skip_attachment_dict,
source,
destination, id, key,
options.conflict_force,
options.conflict_revert,
options.conflict_ignore,
is_creation,
is_modification]);
}
}
}
return dispatchQueue(
context,
checkAttachmentSignatureDifference,
argument_list,
context._parallel_operation_attachment_amount
);
})
.push(function () {
var key, argument_list = [];
if (options.check_deletion === true) {
for (key in signature_dict) {
if (signature_dict.hasOwnProperty(key)) {
if (!local_dict.hasOwnProperty(key)) {
argument_list.push([undefined, argument_list.push([undefined,
skip_attachment_dict, context,
source, skip_attachment_dict,
destination, id, key, destination, id, key,
options.conflict_force, source,
options.conflict_revert, options.conflict_force,
options.conflict_ignore, options.conflict_revert,
is_creation, options.conflict_ignore]);
is_modification]);
} }
} }
} }
return dispatchQueue( return dispatchQueue(
checkAttachmentSignatureDifference, context,
checkAttachmentLocalDeletion,
argument_list, argument_list,
context._parallel_operation_attachment_amount context._parallel_operation_attachment_amount
); );
}) }
.push(function () { });
var key, argument_list = []; }
if (options.check_deletion === true) {
for (key in signature_dict) {
if (signature_dict.hasOwnProperty(key)) {
if (!local_dict.hasOwnProperty(key)) {
argument_list.push([undefined,
skip_attachment_dict,
destination, id, key,
source,
options.conflict_force,
options.conflict_revert,
options.conflict_ignore]);
}
}
}
return dispatchQueue(
checkAttachmentLocalDeletion,
argument_list,
context._parallel_operation_attachment_amount
);
}
});
}
function repairDocumentAttachment(id) {
var skip_attachment_dict = {};
return new RSVP.Queue()
.push(function () {
if (context._check_local_attachment_modification ||
context._check_local_attachment_creation ||
context._check_local_attachment_deletion) {
return pushDocumentAttachment(
skip_attachment_dict,
id,
context._local_sub_storage,
context._remote_sub_storage,
{
conflict_force: (context._conflict_handling ===
CONFLICT_KEEP_LOCAL),
conflict_revert: (context._conflict_handling ===
CONFLICT_KEEP_REMOTE),
conflict_ignore: (context._conflict_handling ===
CONFLICT_CONTINUE),
check_modification:
context._check_local_attachment_modification,
check_creation: context._check_local_attachment_creation,
check_deletion: context._check_local_attachment_deletion
}
);
}
})
.push(function () {
if (context._check_remote_attachment_modification ||
context._check_remote_attachment_creation ||
context._check_remote_attachment_deletion) {
return pushDocumentAttachment(
skip_attachment_dict,
id,
context._remote_sub_storage,
context._local_sub_storage,
{
use_revert_post: context._use_remote_post,
conflict_force: (context._conflict_handling ===
CONFLICT_KEEP_REMOTE),
conflict_revert: (context._conflict_handling ===
CONFLICT_KEEP_LOCAL),
conflict_ignore: (context._conflict_handling ===
CONFLICT_CONTINUE),
check_modification:
context._check_remote_attachment_modification,
check_creation: context._check_remote_attachment_creation,
check_deletion: context._check_remote_attachment_deletion
}
);
}
});
}
function propagateModification(source, destination, doc, hash, id,
options) {
var result,
post_id,
to_skip = true;
if (options === undefined) {
options = {};
}
if (options.use_post) {
result = destination.post(doc)
.push(function (new_id) {
to_skip = false;
post_id = new_id;
return source.put(post_id, doc);
})
.push(function () {
// Copy all attachments
// This is not related to attachment replication
// It's just about not losing user data
return source.allAttachments(id);
})
.push(function (attachment_dict) {
var key,
copy_queue = new RSVP.Queue();
function copyAttachment(name) {
copy_queue
.push(function () {
return source.getAttachment(id, name);
})
.push(function (blob) {
return source.putAttachment(post_id, name, blob);
});
}
for (key in attachment_dict) { function repairDocumentAttachment(context, id) {
if (attachment_dict.hasOwnProperty(key)) { var skip_attachment_dict = {};
copyAttachment(key); return new RSVP.Queue()
} .push(function () {
if (context._check_local_attachment_modification ||
context._check_local_attachment_creation ||
context._check_local_attachment_deletion ||
context._check_remote_attachment_modification ||
context._check_remote_attachment_creation ||
context._check_remote_attachment_deletion) {
return context._signature_sub_storage.allAttachments(id);
}
return {};
})
.push(undefined, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
return {};
}
throw error;
})
.push(function (signature_allAttachments) {
if (context._check_local_attachment_modification ||
context._check_local_attachment_creation ||
context._check_local_attachment_deletion) {
return pushDocumentAttachment(
context,
skip_attachment_dict,
id,
context._local_sub_storage,
context._remote_sub_storage,
signature_allAttachments,
{
conflict_force: (context._conflict_handling ===
CONFLICT_KEEP_LOCAL),
conflict_revert: (context._conflict_handling ===
CONFLICT_KEEP_REMOTE),
conflict_ignore: (context._conflict_handling ===
CONFLICT_CONTINUE),
check_modification:
context._check_local_attachment_modification,
check_creation: context._check_local_attachment_creation,
check_deletion: context._check_local_attachment_deletion
} }
return copy_queue; )
}) .push(function () {
.push(function () { return signature_allAttachments;
return source.remove(id);
})
.push(function () {
return context._signature_sub_storage.remove(id);
})
.push(function () {
to_skip = true;
return context._signature_sub_storage.put(post_id, {
"hash": hash
});
})
.push(function () {
skip_document_dict[post_id] = null;
});
} else {
result = destination.put(id, doc)
.push(function () {
return context._signature_sub_storage.put(id, {
"hash": hash
}); });
}); }
} return signature_allAttachments;
return result })
.push(function (signature_allAttachments) {
if (context._check_remote_attachment_modification ||
context._check_remote_attachment_creation ||
context._check_remote_attachment_deletion) {
return pushDocumentAttachment(
context,
skip_attachment_dict,
id,
context._remote_sub_storage,
context._local_sub_storage,
signature_allAttachments,
{
use_revert_post: context._use_remote_post,
conflict_force: (context._conflict_handling ===
CONFLICT_KEEP_REMOTE),
conflict_revert: (context._conflict_handling ===
CONFLICT_KEEP_LOCAL),
conflict_ignore: (context._conflict_handling ===
CONFLICT_CONTINUE),
check_modification:
context._check_remote_attachment_modification,
check_creation: context._check_remote_attachment_creation,
check_deletion: context._check_remote_attachment_deletion
}
);
}
});
}
function propagateModification(context, source, destination, doc, hash, id,
skip_document_dict,
options) {
var result = new RSVP.Queue(),
post_id,
to_skip = true;
if (options === undefined) {
options = {};
}
if (doc === null) {
result
.push(function () { .push(function () {
if (to_skip) { return source.get(id);
skip_document_dict[id] = null; })
.push(function (source_doc) {
doc = source_doc;
}, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
throw new SkipError(id);
} }
throw error;
}); });
} }
if (options.use_post) {
function propagateDeletion(destination, id) { result
// Do not delete a document if it has an attachment .push(function () {
// ie, replication should prevent losing user data return destination.post(doc);
// Synchronize attachments before, to ensure })
// all of them will be deleted too .push(function (new_id) {
return repairDocumentAttachment(id) to_skip = false;
post_id = new_id;
return source.put(post_id, doc);
})
.push(function () { .push(function () {
return destination.allAttachments(id); // Copy all attachments
// This is not related to attachment replication
// It's just about not losing user data
return source.allAttachments(id);
}) })
.push(function (attachment_dict) { .push(function (attachment_dict) {
if (JSON.stringify(attachment_dict) === "{}") { var key,
return destination.remove(id) copy_queue = new RSVP.Queue();
function copyAttachment(name) {
copy_queue
.push(function () { .push(function () {
return context._signature_sub_storage.remove(id); return source.getAttachment(id, name);
})
.push(function (blob) {
return source.putAttachment(post_id, name, blob);
}); });
} }
}, function (error) {
if ((error instanceof jIO.util.jIOError) && for (key in attachment_dict) {
(error.status_code === 404)) { if (attachment_dict.hasOwnProperty(key)) {
return; copyAttachment(key);
}
} }
throw error; return copy_queue;
}) })
.push(function () { .push(function () {
skip_document_dict[id] = null; return source.remove(id);
})
.push(function () {
return context._signature_sub_storage.remove(id);
})
.push(function () {
to_skip = true;
return context._signature_sub_storage.put(post_id, {
"hash": hash
});
})
.push(function () {
skip_document_dict[post_id] = null;
}); });
} } else {
result
function checkAndPropagate(status_hash, local_hash, doc, .push(function () {
source, destination, id, // Drop signature if the destination document was empty
conflict_force, conflict_revert, // but a signature exists
conflict_ignore, if (options.create_new_document === true) {
options) { return context._signature_sub_storage.remove(id);
return destination.get(id)
.push(function (remote_doc) {
return [remote_doc, generateHash(stringify(remote_doc))];
}, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
return [null, null];
} }
throw error;
}) })
.push(function (remote_list) { .push(function () {
var remote_doc = remote_list[0], return destination.put(id, doc);
remote_hash = remote_list[1]; })
.push(function () {
if (local_hash === remote_hash) { return context._signature_sub_storage.put(id, {
// Same modifications on both side "hash": hash
if (local_hash === null) { });
// Deleted on both side, drop signature });
return context._signature_sub_storage.remove(id) }
.push(function () { return result
skip_document_dict[id] = null; .push(function () {
}); if (to_skip) {
skip_document_dict[id] = null;
}
})
.push(undefined, function (error) {
if (error instanceof SkipError) {
return;
}
throw error;
});
}
function propagateDeletion(context, destination, id, skip_document_dict) {
// Do not delete a document if it has an attachment
// ie, replication should prevent losing user data
// Synchronize attachments before, to ensure
// all of them will be deleted too
return repairDocumentAttachment(context, id)
.push(function () {
return destination.allAttachments(id);
})
.push(function (attachment_dict) {
if (JSON.stringify(attachment_dict) === "{}") {
return destination.remove(id)
.push(function () {
return context._signature_sub_storage.remove(id);
});
}
}, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
return;
}
throw error;
})
.push(function () {
skip_document_dict[id] = null;
});
}
function checkAndPropagate(context, skip_document_dict,
cache, destination_key,
status_hash, local_hash, doc,
source, destination, id,
conflict_force, conflict_revert,
conflict_ignore,
options) {
return new RSVP.Queue()
.push(function () {
if (options.signature_hash_key !== undefined) {
return callAllDocsOnStorage(context, destination,
cache, destination_key)
.push(function (result) {
if (result.hasOwnProperty(id)) {
return [null, result[id][options.signature_hash_key]];
}
return [null, null];
});
}
return destination.get(id)
.push(function (remote_doc) {
return [remote_doc, generateHash(stringify(remote_doc))];
}, function (error) {
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
return [null, null];
} }
throw error;
});
})
return context._signature_sub_storage.put(id, { .push(function (remote_list) {
"hash": local_hash var remote_doc = remote_list[0],
}) remote_hash = remote_list[1];
if (local_hash === remote_hash) {
// Same modifications on both side
if (local_hash === null) {
// Deleted on both side, drop signature
return context._signature_sub_storage.remove(id)
.push(function () { .push(function () {
skip_document_dict[id] = null; skip_document_dict[id] = null;
}); });
} }
if ((remote_hash === status_hash) || (conflict_force === true)) { return context._signature_sub_storage.put(id, {
// Modified only locally. No conflict or force "hash": local_hash
if (local_hash === null) { })
// Deleted locally .push(function () {
return propagateDeletion(destination, id); skip_document_dict[id] = null;
} });
return propagateModification(source, destination, doc, }
local_hash, id,
{use_post: ((options.use_post) &&
(remote_hash === null))});
}
// Conflict cases
if (conflict_ignore === true) {
return;
}
if ((conflict_revert === true) || (local_hash === null)) { if ((remote_hash === status_hash) || (conflict_force === true)) {
// Automatically resolve conflict or force revert // Modified only locally. No conflict or force
if (remote_hash === null) { if (local_hash === null) {
// Deleted remotely // Deleted locally
return propagateDeletion(source, id); return propagateDeletion(context, destination, id,
} skip_document_dict);
return propagateModification(
destination,
source,
remote_doc,
remote_hash,
id,
{use_post: ((options.use_revert_post) &&
(local_hash === null))}
);
} }
return propagateModification(context, source, destination, doc,
local_hash, id, skip_document_dict,
{use_post: ((options.use_post) &&
(remote_hash === null)),
create_new_document:
((remote_hash === null) &&
(status_hash !== null))
});
}
// Conflict cases
if (conflict_ignore === true) {
return;
}
// Minimize conflict if it can be resolved if ((conflict_revert === true) || (local_hash === null)) {
// Automatically resolve conflict or force revert
if (remote_hash === null) { if (remote_hash === null) {
// Copy remote modification remotely // Deleted remotely
return propagateModification(source, destination, doc, return propagateDeletion(context, source, id, skip_document_dict);
local_hash, id,
{use_post: options.use_post});
} }
throw new jIO.util.jIOError("Conflict on '" + id + "': " + return propagateModification(
stringify(doc || '') + " !== " + context,
stringify(remote_doc || ''), destination,
409); source,
}); remote_doc,
} remote_hash,
id,
skip_document_dict,
{use_post: ((options.use_revert_post) &&
(local_hash === null)),
create_new_document: ((local_hash === null) &&
(status_hash !== null))}
);
}
function checkLocalDeletion(queue, destination, id, source, // Minimize conflict if it can be resolved
conflict_force, conflict_revert, if (remote_hash === null) {
conflict_ignore, options) { // Copy remote modification remotely
var status_hash; return propagateModification(context, source, destination, doc,
queue local_hash, id, skip_document_dict,
.push(function () { {use_post: options.use_post,
return context._signature_sub_storage.get(id); create_new_document:
}) (status_hash !== null)});
.push(function (result) { }
status_hash = result.hash; doc = doc || local_hash;
return checkAndPropagate(status_hash, null, null, remote_doc = remote_doc || remote_hash;
throw new jIO.util.jIOError("Conflict on '" + id + "': " +
stringify(doc) + " !== " +
stringify(remote_doc),
409);
});
}
function checkLocalDeletion(queue, context, skip_document_dict,
cache, destination_key,
destination, id, source,
conflict_force, conflict_revert,
conflict_ignore, options) {
var status_hash;
queue
.push(function () {
return context._signature_sub_storage.get(id);
})
.push(function (result) {
status_hash = result.hash;
return checkAndPropagate(context, skip_document_dict,
cache, destination_key,
status_hash, null, null,
source, destination, id,
conflict_force, conflict_revert,
conflict_ignore,
options);
});
}
function checkSignatureDifference(queue, context, skip_document_dict,
cache, destination_key,
source, destination, id,
conflict_force, conflict_revert,
conflict_ignore,
local_hash, status_hash,
options) {
queue
.push(function () {
if (local_hash === null) {
// Hash was not provided by the allDocs query
return source.get(id);
}
return null;
})
.push(function (doc) {
if (local_hash === null) {
// Hash was not provided by the allDocs query
local_hash = generateHash(stringify(doc));
}
if (local_hash !== status_hash) {
return checkAndPropagate(context, skip_document_dict,
cache, destination_key,
status_hash, local_hash, doc,
source, destination, id, source, destination, id,
conflict_force, conflict_revert, conflict_force, conflict_revert,
conflict_ignore, conflict_ignore,
options); options);
}); }
} });
}
function checkSignatureDifference(queue, source, destination, id, function pushStorage(context, skip_document_dict,
conflict_force, conflict_revert, skip_deleted_document_dict,
conflict_ignore, cache, source_key, destination_key,
is_creation, is_modification, source, destination, signature_allDocs, options) {
getMethod, options) { var argument_list = [],
queue argument_list_deletion = [];
.push(function () { if (!options.hasOwnProperty("use_post")) {
// Optimisation to save a get call to signature storage options.use_post = false;
if (is_creation === true) {
return RSVP.all([
getMethod(id),
{hash: null}
]);
}
if (is_modification === true) {
return RSVP.all([
getMethod(id),
context._signature_sub_storage.get(id)
]);
}
throw new jIO.util.jIOError("Unexpected call of"
+ " checkSignatureDifference",
409);
})
.push(function (result_list) {
var doc = result_list[0],
local_hash = generateHash(stringify(doc)),
status_hash = result_list[1].hash;
if (local_hash !== status_hash) {
return checkAndPropagate(status_hash, local_hash, doc,
source, destination, id,
conflict_force, conflict_revert,
conflict_ignore,
options);
}
});
} }
if (!options.hasOwnProperty("use_revert_post")) {
function checkBulkSignatureDifference(queue, source, destination, id_list, options.use_revert_post = false;
document_status_list, options,
conflict_force, conflict_revert,
conflict_ignore) {
queue
.push(function () {
return source.bulk(id_list);
})
.push(function (result_list) {
var i,
argument_list = [];
function getResult(j) {
return function (id) {
if (id !== id_list[j].parameter_list[0]) {
throw new Error("Does not access expected ID " + id);
}
return result_list[j];
};
}
for (i = 0; i < result_list.length; i += 1) {
argument_list[i] = [undefined, source, destination,
id_list[i].parameter_list[0],
conflict_force, conflict_revert,
conflict_ignore,
document_status_list[i].is_creation,
document_status_list[i].is_modification,
getResult(i), options];
}
return dispatchQueue(
checkSignatureDifference,
argument_list,
options.operation_amount
);
});
} }
return callAllDocsOnStorage(context, source, cache, source_key)
function pushStorage(source, destination, options) { .push(function (source_allDocs) {
var queue = new RSVP.Queue(), var i,
argument_list = [], local_dict = {},
argument_list_deletion = []; signature_dict = {},
if (!options.hasOwnProperty("use_post")) { is_modification,
options.use_post = false; is_creation,
} status_hash,
if (!options.hasOwnProperty("use_revert_post")) { local_hash,
options.use_revert_post = false; key,
} queue = new RSVP.Queue();
return queue for (key in source_allDocs) {
.push(function () { if (source_allDocs.hasOwnProperty(key)) {
return RSVP.all([ if (!skip_document_dict.hasOwnProperty(key)) {
source.allDocs(context._query_options), local_dict[key] = source_allDocs[key];
context._signature_sub_storage.allDocs()
]);
})
.push(function (result_list) {
var i,
local_dict = {},
document_list = [],
document_status_list = [],
signature_dict = {},
is_modification,
is_creation,
key;
for (i = 0; i < result_list[0].data.total_rows; i += 1) {
if (!skip_document_dict.hasOwnProperty(
result_list[0].data.rows[i].id
)) {
local_dict[result_list[0].data.rows[i].id] = i;
} }
} }
for (i = 0; i < result_list[1].data.total_rows; i += 1) { }
if (!skip_document_dict.hasOwnProperty( /*
result_list[1].data.rows[i].id for (i = 0; i < source_allDocs.data.total_rows; i += 1) {
)) { if (!skip_document_dict.hasOwnProperty(
signature_dict[result_list[1].data.rows[i].id] = i; source_allDocs.data.rows[i].id
} )) {
local_dict[source_allDocs.data.rows[i].id] =
source_allDocs.data.rows[i].value;
} }
i = 0; }
for (key in local_dict) { */
if (local_dict.hasOwnProperty(key)) { for (i = 0; i < signature_allDocs.data.total_rows; i += 1) {
is_modification = signature_dict.hasOwnProperty(key) if (!skip_document_dict.hasOwnProperty(
&& options.check_modification; signature_allDocs.data.rows[i].id
is_creation = !signature_dict.hasOwnProperty(key) )) {
&& options.check_creation; signature_dict[signature_allDocs.data.rows[i].id] =
if (is_modification === true || is_creation === true) { signature_allDocs.data.rows[i].value.hash;
if (options.use_bulk_get === true) { }
document_list.push({ }
method: "get", for (key in local_dict) {
parameter_list: [key] if (local_dict.hasOwnProperty(key)) {
}); is_modification = signature_dict.hasOwnProperty(key)
document_status_list.push({ && options.check_modification;
is_creation: is_creation, is_creation = !signature_dict.hasOwnProperty(key)
is_modification: is_modification && options.check_creation;
});
} else { if (is_creation === true) {
argument_list[i] = [undefined, source, destination, status_hash = null;
key, } else if (is_modification === true) {
options.conflict_force, status_hash = signature_dict[key];
options.conflict_revert, }
options.conflict_ignore,
is_creation, is_modification, local_hash = null;
source.get.bind(source), if (options.signature_hash_key !== undefined) {
options]; local_hash = local_dict[key][options.signature_hash_key];
i += 1; if (is_modification === true) {
// Bypass fetching all documents and calculating the sha
// Compare the select list values returned by allDocs calls
is_modification = false;
if (local_hash !== status_hash) {
is_modification = true;
} }
} }
} }
if (is_modification === true || is_creation === true) {
argument_list.push([undefined, context, skip_document_dict,
cache, destination_key,
source, destination,
key,
options.conflict_force,
options.conflict_revert,
options.conflict_ignore,
local_hash, status_hash,
options]);
}
} }
queue }
.push(function () { queue
return dispatchQueue( .push(function () {
checkSignatureDifference, return dispatchQueue(
argument_list, context,
options.operation_amount checkSignatureDifference,
); argument_list,
}); options.operation_amount
if (options.check_deletion === true) { );
i = 0; });
for (key in signature_dict) { for (key in signature_dict) {
if (signature_dict.hasOwnProperty(key)) { if (signature_dict.hasOwnProperty(key)) {
if (!local_dict.hasOwnProperty(key)) { if (!local_dict.hasOwnProperty(key)) {
argument_list_deletion[i] = [undefined, if (options.check_deletion === true) {
destination, key, argument_list_deletion.push([undefined,
source, context,
options.conflict_force, skip_document_dict,
options.conflict_revert, cache, destination_key,
options.conflict_ignore, destination, key,
options]; source,
i += 1; options.conflict_force,
} options.conflict_revert,
options.conflict_ignore,
options]);
} else {
skip_deleted_document_dict[key] = null;
} }
} }
queue.push(function () {
return dispatchQueue(
checkLocalDeletion,
argument_list_deletion,
options.operation_amount
);
});
} }
if ((options.use_bulk_get === true) && (document_list.length !== 0)) { }
checkBulkSignatureDifference(queue, source, destination, if (argument_list_deletion.length !== 0) {
document_list, document_status_list, queue.push(function () {
options, return dispatchQueue(
options.conflict_force, context,
options.conflict_revert, checkLocalDeletion,
options.conflict_ignore); argument_list_deletion,
} options.operation_amount
}); );
} });
}
function repairDocument(queue, id) { return queue;
queue.push(function () {
return repairDocumentAttachment(id);
}); });
} }
function repairDocument(queue, context, id) {
queue.push(function () {
return repairDocumentAttachment(context, id);
});
}
ReplicateStorage.prototype.repair = function () {
var context = this,
argument_list = arguments,
skip_document_dict = {},
skip_deleted_document_dict = {},
cache = {};
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
// Ensure that the document storage is usable // Ensure that the document storage is usable
return context._signature_sub_storage.__storage._sub_storage.get( if (context._custom_signature_sub_storage === false) {
context._signature_hash // Do not sync the signature document
); skip_document_dict[context._signature_hash] = null;
return context._signature_sub_storage.__storage._sub_storage
.__storage._sub_storage.get(
context._signature_hash
);
}
}) })
.push(undefined, function (error) { .push(undefined, function (error) {
if ((error instanceof jIO.util.jIOError) && if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) { (error.status_code === 404)) {
return context._signature_sub_storage.__storage._sub_storage.put( return context._signature_sub_storage.__storage._sub_storage
context._signature_hash, .__storage._sub_storage.put(
{} context._signature_hash,
); {}
);
} }
throw error; throw error;
}) })
...@@ -9417,11 +9529,28 @@ return new Parser; ...@@ -9417,11 +9529,28 @@ return new Parser;
}) })
.push(function () { .push(function () {
if (context._check_local_modification ||
context._check_local_creation ||
context._check_local_deletion ||
context._check_remote_modification ||
context._check_remote_creation ||
context._check_remote_deletion) {
return context._signature_sub_storage.allDocs({
select_list: ['hash']
});
}
})
.push(function (signature_allDocs) {
if (context._check_local_modification || if (context._check_local_modification ||
context._check_local_creation || context._check_local_creation ||
context._check_local_deletion) { context._check_local_deletion) {
return pushStorage(context._local_sub_storage, return pushStorage(context, skip_document_dict,
skip_deleted_document_dict,
cache, 'local', 'remote',
context._local_sub_storage,
context._remote_sub_storage, context._remote_sub_storage,
signature_allDocs,
{ {
use_post: context._use_remote_post, use_post: context._use_remote_post,
conflict_force: (context._conflict_handling === conflict_force: (context._conflict_handling ===
...@@ -9433,28 +9562,25 @@ return new Parser; ...@@ -9433,28 +9562,25 @@ return new Parser;
check_modification: context._check_local_modification, check_modification: context._check_local_modification,
check_creation: context._check_local_creation, check_creation: context._check_local_creation,
check_deletion: context._check_local_deletion, check_deletion: context._check_local_deletion,
operation_amount: context._parallel_operation_amount operation_amount: context._parallel_operation_amount,
signature_hash_key: context._signature_hash_key
})
.push(function () {
return signature_allDocs;
}); });
} }
return signature_allDocs;
}) })
.push(function () { .push(function (signature_allDocs) {
// Autoactivate bulk if substorage implements it
// Keep it like this until the bulk API is stabilized
var use_bulk_get = false;
try {
use_bulk_get = context._remote_sub_storage.hasCapacity("bulk_get");
} catch (error) {
if (!((error instanceof jIO.util.jIOError) &&
(error.status_code === 501))) {
throw error;
}
}
if (context._check_remote_modification || if (context._check_remote_modification ||
context._check_remote_creation || context._check_remote_creation ||
context._check_remote_deletion) { context._check_remote_deletion) {
return pushStorage(context._remote_sub_storage, return pushStorage(context, skip_document_dict,
context._local_sub_storage, { skip_deleted_document_dict,
use_bulk_get: use_bulk_get, cache, 'remote', 'local',
context._remote_sub_storage,
context._local_sub_storage,
signature_allDocs, {
use_revert_post: context._use_remote_post, use_revert_post: context._use_remote_post,
conflict_force: (context._conflict_handling === conflict_force: (context._conflict_handling ===
CONFLICT_KEEP_REMOTE), CONFLICT_KEEP_REMOTE),
...@@ -9465,7 +9591,8 @@ return new Parser; ...@@ -9465,7 +9591,8 @@ return new Parser;
check_modification: context._check_remote_modification, check_modification: context._check_remote_modification,
check_creation: context._check_remote_creation, check_creation: context._check_remote_creation,
check_deletion: context._check_remote_deletion, check_deletion: context._check_remote_deletion,
operation_amount: context._parallel_operation_amount operation_amount: context._parallel_operation_amount,
signature_hash_key: context._signature_hash_key
}); });
} }
}) })
...@@ -9481,17 +9608,25 @@ return new Parser; ...@@ -9481,17 +9608,25 @@ return new Parser;
return context._signature_sub_storage.allDocs() return context._signature_sub_storage.allDocs()
.push(function (result) { .push(function (result) {
var i, var i,
argument_list = [], local_argument_list = [],
id,
len = result.data.total_rows; len = result.data.total_rows;
for (i = 0; i < len; i += 1) { for (i = 0; i < len; i += 1) {
argument_list.push( id = result.data.rows[i].id;
[undefined, result.data.rows[i].id] // Do not synchronize attachment if one version of the document
); // is deleted but not pushed to the other storage
if (!skip_deleted_document_dict.hasOwnProperty(id) ||
skip_document_dict.hasOwnProperty(id)) {
local_argument_list.push(
[undefined, context, id]
);
}
} }
return dispatchQueue( return dispatchQueue(
context,
repairDocument, repairDocument,
argument_list, local_argument_list,
context._parallel_operation_amount context._parallel_operation_amount
); );
}); });
...@@ -11154,56 +11289,6 @@ return new Parser; ...@@ -11154,56 +11289,6 @@ return new Parser;
}); });
}; };
ERP5Storage.prototype.bulk = function (request_list) {
var i,
storage = this,
bulk_list = [];
for (i = 0; i < request_list.length; i += 1) {
if (request_list[i].method !== "get") {
throw new Error("ERP5Storage: not supported " +
request_list[i].method + " in bulk");
}
bulk_list.push({
relative_url: request_list[i].parameter_list[0],
view: storage._default_view_reference
});
}
return getSiteDocument(storage)
.push(function (site_hal) {
var form_data = new FormData();
form_data.append("bulk_list", JSON.stringify(bulk_list));
return jIO.util.ajax({
"type": "POST",
"url": site_hal._actions.bulk.href,
"data": form_data,
// "headers": {
// "Content-Type": "application/json"
// },
"xhrFields": {
withCredentials: true
}
});
})
.push(function (response) {
var result_list = [],
hateoas = JSON.parse(response.target.responseText);
function pushResult(json) {
return extractPropertyFromFormJSON(json)
.push(function (json2) {
return convertJSONToGet(json2);
});
}
for (i = 0; i < hateoas.result_list.length; i += 1) {
result_list.push(pushResult(hateoas.result_list[i]));
}
return RSVP.all(result_list);
});
};
ERP5Storage.prototype.post = function (data) { ERP5Storage.prototype.post = function (data) {
var context = this, var context = this,
new_id; new_id;
...@@ -11430,7 +11515,7 @@ return new Parser; ...@@ -11430,7 +11515,7 @@ return new Parser;
ERP5Storage.prototype.hasCapacity = function (name) { ERP5Storage.prototype.hasCapacity = function (name) {
return ((name === "list") || (name === "query") || return ((name === "list") || (name === "query") ||
(name === "select") || (name === "limit") || (name === "select") || (name === "limit") ||
(name === "sort")) || (name === "bulk_get"); (name === "sort"));
}; };
function isSingleLocalRoles(parsed_query) { function isSingleLocalRoles(parsed_query) {
...@@ -12588,14 +12673,18 @@ return new Parser; ...@@ -12588,14 +12673,18 @@ return new Parser;
}); });
}; };
function handleGet(request, resolve, reject) { function handleGet(store, id, resolve, reject) {
var request = store.get(id);
request.onerror = reject; request.onerror = reject;
request.onsuccess = function () { request.onsuccess = function () {
if (request.result) { if (request.result) {
resolve(request.result); resolve(request.result);
} else { } else {
// XXX How to get ID reject(new jIO.util.jIOError(
reject(new jIO.util.jIOError("Cannot find document", 404)); "IndexedDB: cannot find object '" + id + "' in the '" +
store.name + "' store",
404
));
} }
}; };
} }
...@@ -12606,7 +12695,8 @@ return new Parser; ...@@ -12606,7 +12695,8 @@ return new Parser;
return new RSVP.Promise(function (resolve, reject) { return new RSVP.Promise(function (resolve, reject) {
var transaction = openTransaction(db, ["metadata"], "readonly"); var transaction = openTransaction(db, ["metadata"], "readonly");
handleGet( handleGet(
transaction.objectStore("metadata").get(id), transaction.objectStore("metadata"),
id,
resolve, resolve,
reject reject
); );
...@@ -12639,7 +12729,8 @@ return new Parser; ...@@ -12639,7 +12729,8 @@ return new Parser;
); );
} }
handleGet( handleGet(
transaction.objectStore("metadata").get(id), transaction.objectStore("metadata"),
id,
getAttachments, getAttachments,
reject reject
); );
...@@ -12767,7 +12858,8 @@ return new Parser; ...@@ -12767,7 +12858,8 @@ return new Parser;
result_list.push(result); result_list.push(result);
} }
i += 1; i += 1;
handleGet(store.get(buildKeyPath([id, name, i])), handleGet(store,
buildKeyPath([id, name, i]),
(i <= end_index) ? getPart(i) : resolver, (i <= end_index) ? getPart(i) : resolver,
reject reject
); );
...@@ -12776,8 +12868,8 @@ return new Parser; ...@@ -12776,8 +12868,8 @@ return new Parser;
getPart(start_index - 1)(); getPart(start_index - 1)();
} }
// XXX Should raise if key is not good // XXX Should raise if key is not good
handleGet(transaction.objectStore("attachment") handleGet(transaction.objectStore("attachment"),
.get(buildKeyPath([id, name])), buildKeyPath([id, name]),
getBlob, getBlob,
reject reject
); );
...@@ -13007,12 +13099,12 @@ return new Parser; ...@@ -13007,12 +13099,12 @@ return new Parser;
}) })
.push(function (dataURL) { .push(function (dataURL) {
//string->arraybuffer //string->arraybuffer
var strLen = dataURL.currentTarget.result.length, var strLen = dataURL.target.result.length,
buf = new ArrayBuffer(strLen), buf = new ArrayBuffer(strLen),
bufView = new Uint8Array(buf), bufView = new Uint8Array(buf),
i; i;
dataURL = dataURL.currentTarget.result; dataURL = dataURL.target.result;
for (i = 0; i < strLen; i += 1) { for (i = 0; i < strLen; i += 1) {
bufView[i] = dataURL.charCodeAt(i); bufView[i] = dataURL.charCodeAt(i);
} }
...@@ -13049,7 +13141,7 @@ return new Parser; ...@@ -13049,7 +13141,7 @@ return new Parser;
.push(function (coded) { .push(function (coded) {
var initializaton_vector; var initializaton_vector;
coded = coded.currentTarget.result; coded = coded.target.result;
initializaton_vector = new Uint8Array(coded.slice(0, 12)); initializaton_vector = new Uint8Array(coded.slice(0, 12));
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
...@@ -13268,7 +13360,7 @@ return new Parser; ...@@ -13268,7 +13360,7 @@ return new Parser;
return jIO.util.readBlobAsDataURL(blob); return jIO.util.readBlobAsDataURL(blob);
}) })
.push(function (strBlob) { .push(function (strBlob) {
argument_list[index + 2].push(strBlob.currentTarget.result); argument_list[index + 2].push(strBlob.target.result);
return; return;
}); });
} }
...@@ -13451,4 +13543,4 @@ return new Parser; ...@@ -13451,4 +13543,4 @@ return new Parser;
jIO.addStorage('websql', WebSQLStorage); jIO.addStorage('websql', WebSQLStorage);
}(jIO, RSVP, Blob, openDatabase)); }(jIO, RSVP, Blob, openDatabase));
\ No newline at end of file
...@@ -236,7 +236,7 @@ ...@@ -236,7 +236,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>959.8888.26905.39645</string> </value> <value> <string>960.25571.62873.4317</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -254,7 +254,7 @@ ...@@ -254,7 +254,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1494334109.43</float> <float>1499172288.9</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment