mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 961665 - Native implementation of OS.File.read, js code. r=froydnj
This commit is contained in:
parent
c5a137c09e
commit
bdd8e6a2a6
@ -10,6 +10,7 @@ EXTRA_JS_MODULES += [
|
||||
'_PromiseWorker.jsm',
|
||||
'osfile_async_front.jsm',
|
||||
'osfile_async_worker.js',
|
||||
'osfile_native.jsm',
|
||||
'osfile_shared_allthreads.jsm',
|
||||
'osfile_shared_front.jsm',
|
||||
'osfile_unix_allthreads.jsm',
|
||||
|
@ -58,6 +58,7 @@ Cu.import("resource://gre/modules/osfile/_PromiseWorker.jsm", this);
|
||||
Cu.import("resource://gre/modules/Services.jsm", this);
|
||||
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
|
||||
Cu.import("resource://gre/modules/AsyncShutdown.jsm", this);
|
||||
let Native = Cu.import("resource://gre/modules/osfile/osfile_native.jsm", {});
|
||||
|
||||
/**
|
||||
* Constructors for decoding standard exceptions
|
||||
@ -348,7 +349,7 @@ const PREF_OSFILE_LOG_REDIRECT = "toolkit.osfile.log.redirect";
|
||||
* @param bool oldPref
|
||||
* An optional value that the DEBUG flag was set to previously.
|
||||
*/
|
||||
let readDebugPref = function readDebugPref(prefName, oldPref = false) {
|
||||
function readDebugPref(prefName, oldPref = false) {
|
||||
let pref = oldPref;
|
||||
try {
|
||||
pref = Services.prefs.getBoolPref(prefName);
|
||||
@ -379,6 +380,19 @@ Services.prefs.addObserver(PREF_OSFILE_LOG_REDIRECT,
|
||||
}, false);
|
||||
SharedAll.Config.TEST = readDebugPref(PREF_OSFILE_LOG_REDIRECT, false);
|
||||
|
||||
|
||||
/**
|
||||
* If |true|, use the native implementaiton of OS.File methods
|
||||
* whenever possible. Otherwise, force the use of the JS version.
|
||||
*/
|
||||
let nativeWheneverAvailable = true;
|
||||
const PREF_OSFILE_NATIVE = "toolkit.osfile.native";
|
||||
Services.prefs.addObserver(PREF_OSFILE_NATIVE,
|
||||
function prefObserver(aSubject, aTopic, aData) {
|
||||
nativeWheneverAvailable = readDebugPref(PREF_OSFILE_NATIVE, nativeWheneverAvailable);
|
||||
}, false);
|
||||
|
||||
|
||||
// Update worker's DEBUG flag if it's true.
|
||||
// Don't start the worker just for this, though.
|
||||
if (SharedAll.Config.DEBUG && Scheduler.launched) {
|
||||
@ -913,12 +927,32 @@ File.makeDir = function makeDir(path, options) {
|
||||
* read from the file.
|
||||
*/
|
||||
File.read = function read(path, bytes, options = {}) {
|
||||
if (typeof bytes == "object") {
|
||||
// Passing |bytes| as an argument is deprecated.
|
||||
// We should now be passing it as a field of |options|.
|
||||
options = bytes || {};
|
||||
} else {
|
||||
options = clone(options, ["outExecutionDuration"]);
|
||||
if (typeof bytes != "undefined") {
|
||||
options.bytes = bytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.compression || !nativeWheneverAvailable) {
|
||||
// We need to use the JS implementation.
|
||||
let promise = Scheduler.post("read",
|
||||
[Type.path.toMsg(path), bytes, options], path);
|
||||
return promise.then(
|
||||
function onSuccess(data) {
|
||||
if (typeof data == "string") {
|
||||
return data;
|
||||
}
|
||||
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
||||
});
|
||||
}
|
||||
|
||||
// Otherwise, use the native implementation.
|
||||
return Scheduler.push(() => Native.read(path, options));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -362,6 +362,9 @@ const EXCEPTION_NAMES = {
|
||||
},
|
||||
read: function read(path, bytes, options) {
|
||||
let data = File.read(Type.path.fromMsg(path), bytes, options);
|
||||
if (typeof data == "string") {
|
||||
return data;
|
||||
}
|
||||
return new Meta({
|
||||
buffer: data.buffer,
|
||||
byteOffset: data.byteOffset,
|
||||
|
70
toolkit/components/osfile/modules/osfile_native.jsm
Normal file
70
toolkit/components/osfile/modules/osfile_native.jsm
Normal file
@ -0,0 +1,70 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Native (xpcom) implementation of key OS.File functions
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["read"];
|
||||
|
||||
let {results: Cr, utils: Cu, interfaces: Ci} = Components;
|
||||
|
||||
let SharedAll = Cu.import("resource://gre/modules/osfile/osfile_shared_allthreads.jsm", {});
|
||||
|
||||
let SysAll = {};
|
||||
if (SharedAll.Constants.Win) {
|
||||
Cu.import("resource://gre/modules/osfile/osfile_win_allthreads.jsm", SysAll);
|
||||
} else if (SharedAll.Constants.libc) {
|
||||
Cu.import("resource://gre/modules/osfile/osfile_unix_allthreads.jsm", SysAll);
|
||||
} else {
|
||||
throw new Error("I am neither under Windows nor under a Posix system");
|
||||
}
|
||||
let {Promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
|
||||
|
||||
/**
|
||||
* The native service holding the implementation of the functions.
|
||||
*/
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"Internals",
|
||||
"@mozilla.org/toolkit/osfile/native-internals;1",
|
||||
"nsINativeOSFileInternalsService");
|
||||
|
||||
/**
|
||||
* Native implementation of OS.File.read
|
||||
*
|
||||
* This implementation does not handle option |compression|.
|
||||
*/
|
||||
this.read = function(path, options = {}) {
|
||||
// Sanity check on types of options
|
||||
if ("encoding" in options && typeof options.encoding != "string") {
|
||||
return Promise.reject(new TypeError("Invalid type for option encoding"));
|
||||
}
|
||||
if ("compression" in options && typeof options.compression != "string") {
|
||||
return Promise.reject(new TypeError("Invalid type for option compression"));
|
||||
}
|
||||
if ("bytes" in options && typeof options.bytes != "number") {
|
||||
return Promise.reject(new TypeError("Invalid type for option bytes"));
|
||||
}
|
||||
|
||||
let deferred = Promise.defer();
|
||||
Internals.read(path,
|
||||
options,
|
||||
function onSuccess(success) {
|
||||
success.QueryInterface(Ci.nsINativeOSFileResult);
|
||||
if ("outExecutionDuration" in options) {
|
||||
options.outExecutionDuration =
|
||||
success.executionDurationMS +
|
||||
(options.outExecutionDuration || 0);
|
||||
}
|
||||
deferred.resolve(success.result);
|
||||
},
|
||||
function onError(operation, oserror) {
|
||||
deferred.reject(new SysAll.Error(operation, oserror, path));
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
};
|
@ -331,14 +331,35 @@ AbstractFile.read = function read(path, bytes, options = {}) {
|
||||
options = bytes;
|
||||
bytes = options.bytes || null;
|
||||
}
|
||||
if ("encoding" in options && typeof options.encoding != "string") {
|
||||
throw new TypeError("Invalid type for option encoding");
|
||||
}
|
||||
if ("compression" in options && typeof options.compression != "string") {
|
||||
throw new TypeError("Invalid type for option compression: " + options.compression);
|
||||
}
|
||||
if ("bytes" in options && typeof options.bytes != "number") {
|
||||
throw new TypeError("Invalid type for option bytes");
|
||||
}
|
||||
let file = exports.OS.File.open(path);
|
||||
try {
|
||||
let buffer = file.read(bytes, options);
|
||||
if ("compression" in options && options.compression == "lz4") {
|
||||
return Lz4.decompressFileContent(buffer, options);
|
||||
if ("compression" in options) {
|
||||
if (options.compression == "lz4") {
|
||||
buffer = Lz4.decompressFileContent(buffer, options);
|
||||
} else {
|
||||
throw OS.File.Error.invalidArgument("Compression");
|
||||
}
|
||||
}
|
||||
if (!("encoding" in options)) {
|
||||
return buffer;
|
||||
}
|
||||
let decoder;
|
||||
try {
|
||||
decoder = new TextDecoder(options.encoding);
|
||||
} catch (ex if ex instanceof TypeError) {
|
||||
throw OS.File.Error.invalidArgument("Decode");
|
||||
}
|
||||
return decoder.decode(buffer);
|
||||
} finally {
|
||||
file.close();
|
||||
}
|
||||
|
@ -139,6 +139,15 @@ Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
|
||||
return this.unixErrno == Const.EACCES;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* |true| if the error was raised because some invalid argument was passed,
|
||||
* |false| otherwise.
|
||||
*/
|
||||
Object.defineProperty(OSError.prototype, "becauseInvalidArgument", {
|
||||
get: function becauseInvalidArgument() {
|
||||
return this.unixErrno == Const.EINVAL;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Serialize an instance of OSError to something that can be
|
||||
@ -331,6 +340,10 @@ OSError.noSuchFile = function noSuchFile(operation, path) {
|
||||
return new OSError(operation, Const.ENOENT, path);
|
||||
};
|
||||
|
||||
OSError.invalidArgument = function invalidArgument(operation) {
|
||||
return new OSError(operation, Const.EINVAL);
|
||||
};
|
||||
|
||||
let EXPORTED_SYMBOLS = [
|
||||
"declareFFI",
|
||||
"libc",
|
||||
|
@ -161,6 +161,15 @@ Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
|
||||
return this.winLastError == Const.ERROR_ACCESS_DENIED;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* |true| if the error was raised because some invalid argument was passed,
|
||||
* |false| otherwise.
|
||||
*/
|
||||
Object.defineProperty(OSError.prototype, "becauseInvalidArgument", {
|
||||
get: function becauseInvalidArgument() {
|
||||
return this.winLastError == Const.ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Serialize an instance of OSError to something that can be
|
||||
@ -368,6 +377,10 @@ OSError.noSuchFile = function noSuchFile(operation, path) {
|
||||
return new OSError(operation, Const.ERROR_FILE_NOT_FOUND, path);
|
||||
};
|
||||
|
||||
OSError.invalidArgument = function invalidArgument(operation) {
|
||||
return new OSError(operation, Const.ERROR_NOT_SUPPORTED);
|
||||
};
|
||||
|
||||
let EXPORTED_SYMBOLS = [
|
||||
"declareFFI",
|
||||
"libc",
|
||||
|
Loading…
Reference in New Issue
Block a user