Bug 865387 - Changes to |options| and |clone| in OS.File. r=Yoric

This commit is contained in:
Sankha Narayan Guria 2013-08-23 19:42:30 +05:30
parent 709f8a57a1
commit 70ec065ce1
4 changed files with 68 additions and 59 deletions

View File

@ -93,48 +93,10 @@ if (!("localProfileDir" in OS.Constants.Path)) {
});
}
/**
* A global constant used as a default refs parameter value when cloning.
*/
const noRefs = [];
/**
* Return a shallow clone of the enumerable properties of an object.
*
* Utility used whenever normalizing options requires making (shallow)
* changes to an option object. The copy ensures that we do not modify
* a client-provided object by accident.
*
* Note: to reference and not copy specific fields, provide an optional
* |refs| argument containing their names.
*
* @param {JSON} object Options to be cloned.
* @param {Array} refs An optional array of field names to be passed by
* reference instead of copying.
*/
let clone = function clone(object, refs = noRefs) {
let result = {};
// Make a reference between result[key] and object[key].
let refer = function refer(result, key, object) {
Object.defineProperty(result, key, {
enumerable: true,
get: function() {
return object[key];
},
set: function(value) {
object[key] = value;
}
});
};
for (let k in object) {
if (refs.indexOf(k) < 0) {
result[k] = object[k];
} else {
refer(result, k, object);
}
}
return result;
};
let clone = SharedAll.clone;
let worker = new PromiseWorker(
"resource://gre/modules/osfile/osfile_async_worker.js", LOG);
@ -367,9 +329,8 @@ File.prototype = {
// If |buffer| is a typed array and there is no |bytes| options, we
// need to extract the |byteLength| now, as it will be lost by
// communication
if (isTypedArray(buffer) && (!options || !("bytes" in options))) {
// Preserve the reference to |outExecutionDuration| option if it is
// passed.
if (isTypedArray(buffer) && !("bytes" in options)) {
// Preserve reference to option |outExecutionDuration|, if it is passed.
options = clone(options, ["outExecutionDuration"]);
options.bytes = buffer.byteLength;
}
@ -405,9 +366,8 @@ File.prototype = {
// If |buffer| is a typed array and there is no |bytes| options,
// we need to extract the |byteLength| now, as it will be lost
// by communication
if (isTypedArray(buffer) && (!options || !("bytes" in options))) {
// Preserve the reference to |outExecutionDuration| option if it is
// passed.
if (isTypedArray(buffer)) {
// Preserve reference to option |outExecutionDuration|, if it is passed.
options = clone(options, ["outExecutionDuration"]);
options.bytes = buffer.byteLength;
}
@ -428,13 +388,14 @@ File.prototype = {
* @param {number=} bytes If unspecified, read all the remaining bytes from
* this file. If specified, read |bytes| bytes, or less if the file does not
* contain that many bytes.
* @param {JSON} options
* @return {promise}
* @resolves {Uint8Array} An array containing the bytes read.
*/
read: function read(nbytes) {
read: function read(nbytes, options = {}) {
let promise = Scheduler.post("File_prototype_read",
[this._fdmsg,
nbytes]);
nbytes, options]);
return promise.then(
function onSuccess(data) {
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
@ -639,6 +600,11 @@ File.makeDir = function makeDir(path, options) {
* @param {number=} bytes Optionally, an upper bound to the number of bytes
* to read.
* @param {JSON} options Additional options.
* - {boolean} sequential A flag that triggers a population of the page cache
* with data from a file so that subsequent reads from that file would not
* block on disk I/O. If |true| or unspecified, inform the system that the
* contents of the file will be read in order. Otherwise, make no such
* assumption. |true| by default.
*
* @resolves {Uint8Array} A buffer holding the bytes
* read from the file.

View File

@ -272,7 +272,7 @@ if (this.Components) {
});
},
read: function read(path, bytes, options) {
let data = File.read(Type.path.fromMsg(path), bytes);
let data = File.read(Type.path.fromMsg(path), bytes, options);
return new Transfer({buffer: data.buffer, byteOffset: data.byteOffset, byteLength: data.byteLength}, [data.buffer]);
},
exists: function exists(path) {

View File

@ -34,6 +34,7 @@ if (typeof Components != "undefined") {
let EXPORTED_SYMBOLS = [
"LOG",
"clone",
"Config",
"Constants",
"Type",
@ -162,6 +163,46 @@ let LOG = function (...args) {
exports.LOG = LOG;
/**
* Return a shallow clone of the enumerable properties of an object.
*
* Utility used whenever normalizing options requires making (shallow)
* changes to an option object. The copy ensures that we do not modify
* a client-provided object by accident.
*
* Note: to reference and not copy specific fields, provide an optional
* |refs| argument containing their names.
*
* @param {JSON} object Options to be cloned.
* @param {Array} refs An optional array of field names to be passed by
* reference instead of copying.
*/
let clone = function (object, refs = []) {
let result = {};
// Make a reference between result[key] and object[key].
let refer = function refer(result, key, object) {
Object.defineProperty(result, key, {
enumerable: true,
get: function() {
return object[key];
},
set: function(value) {
object[key] = value;
}
});
};
for (let k in object) {
if (refs.indexOf(k) < 0) {
result[k] = object[k];
} else {
refer(result, k, object);
}
}
return result;
};
exports.clone = clone;
///////////////////// Abstractions above js-ctypes
/**
@ -974,6 +1015,7 @@ exports.OS = {
Constants: exports.Constants,
Shared: {
LOG: LOG,
clone: clone,
Type: Type,
HollowStructure: HollowStructure,
Error: OSError,
@ -1015,4 +1057,3 @@ if (typeof Components != "undefined") {
this[symbol] = exports[symbol];
}
}

View File

@ -17,6 +17,7 @@ if (typeof Components != "undefined") {
exports.OS = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm").OS;
let LOG = exports.OS.Shared.LOG.bind(OS.Shared, "Shared front-end");
let clone = exports.OS.Shared.clone;
/**
* Code shared by implementations of File.
@ -44,17 +45,17 @@ AbstractFile.prototype = {
* Read bytes from this file to a new buffer.
*
* @param {number=} bytes If unspecified, read all the remaining bytes from
* this file. If specified, read |bytes| bytes, or less if the file does not
* this file. If specified, read |bytes| bytes, or less if the file does notclone
* contain that many bytes.
* @param {JSON} options
* @return {Uint8Array} An array containing the bytes read.
*/
read: function read(bytes) {
if (bytes == null) {
bytes = this.stat().size;
}
let buffer = new Uint8Array(bytes);
let size = this.readTo(buffer, {bytes: bytes});
if (size == bytes) {
read: function read(bytes, options = {}) {
options = clone(options);
options.bytes = bytes == null ? this.stat().size : bytes;
let buffer = new Uint8Array(options.bytes);
let size = this.readTo(buffer, options);
if (size == options.bytes) {
return buffer;
} else {
return buffer.subarray(0, size);
@ -291,14 +292,15 @@ AbstractFile.normalizeOpenMode = function normalizeOpenMode(mode) {
* @param {string} path The path to the file.
* @param {number=} bytes Optionally, an upper bound to the number of bytes
* to read.
* @param {JSON} options Optionally contains additional options.
*
* @return {Uint8Array} A buffer holding the bytes
* and the number of bytes read from the file.
*/
AbstractFile.read = function read(path, bytes) {
AbstractFile.read = function read(path, bytes, options = {}) {
let file = exports.OS.File.open(path);
try {
return file.read(bytes);
return file.read(bytes, options);
} finally {
file.close();
}