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',
|
'_PromiseWorker.jsm',
|
||||||
'osfile_async_front.jsm',
|
'osfile_async_front.jsm',
|
||||||
'osfile_async_worker.js',
|
'osfile_async_worker.js',
|
||||||
|
'osfile_native.jsm',
|
||||||
'osfile_shared_allthreads.jsm',
|
'osfile_shared_allthreads.jsm',
|
||||||
'osfile_shared_front.jsm',
|
'osfile_shared_front.jsm',
|
||||||
'osfile_unix_allthreads.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/Services.jsm", this);
|
||||||
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
|
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
|
||||||
Cu.import("resource://gre/modules/AsyncShutdown.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
|
* Constructors for decoding standard exceptions
|
||||||
@ -348,7 +349,7 @@ const PREF_OSFILE_LOG_REDIRECT = "toolkit.osfile.log.redirect";
|
|||||||
* @param bool oldPref
|
* @param bool oldPref
|
||||||
* An optional value that the DEBUG flag was set to previously.
|
* 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;
|
let pref = oldPref;
|
||||||
try {
|
try {
|
||||||
pref = Services.prefs.getBoolPref(prefName);
|
pref = Services.prefs.getBoolPref(prefName);
|
||||||
@ -379,6 +380,19 @@ Services.prefs.addObserver(PREF_OSFILE_LOG_REDIRECT,
|
|||||||
}, false);
|
}, false);
|
||||||
SharedAll.Config.TEST = readDebugPref(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.
|
// Update worker's DEBUG flag if it's true.
|
||||||
// Don't start the worker just for this, though.
|
// Don't start the worker just for this, though.
|
||||||
if (SharedAll.Config.DEBUG && Scheduler.launched) {
|
if (SharedAll.Config.DEBUG && Scheduler.launched) {
|
||||||
@ -913,12 +927,32 @@ File.makeDir = function makeDir(path, options) {
|
|||||||
* read from the file.
|
* read from the file.
|
||||||
*/
|
*/
|
||||||
File.read = function read(path, bytes, options = {}) {
|
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",
|
let promise = Scheduler.post("read",
|
||||||
[Type.path.toMsg(path), bytes, options], path);
|
[Type.path.toMsg(path), bytes, options], path);
|
||||||
return promise.then(
|
return promise.then(
|
||||||
function onSuccess(data) {
|
function onSuccess(data) {
|
||||||
|
if (typeof data == "string") {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
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) {
|
read: function read(path, bytes, options) {
|
||||||
let data = File.read(Type.path.fromMsg(path), bytes, options);
|
let data = File.read(Type.path.fromMsg(path), bytes, options);
|
||||||
|
if (typeof data == "string") {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
return new Meta({
|
return new Meta({
|
||||||
buffer: data.buffer,
|
buffer: data.buffer,
|
||||||
byteOffset: data.byteOffset,
|
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;
|
options = bytes;
|
||||||
bytes = options.bytes || null;
|
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);
|
let file = exports.OS.File.open(path);
|
||||||
try {
|
try {
|
||||||
let buffer = file.read(bytes, options);
|
let buffer = file.read(bytes, options);
|
||||||
if ("compression" in options && options.compression == "lz4") {
|
if ("compression" in options) {
|
||||||
return Lz4.decompressFileContent(buffer, options);
|
if (options.compression == "lz4") {
|
||||||
|
buffer = Lz4.decompressFileContent(buffer, options);
|
||||||
} else {
|
} else {
|
||||||
|
throw OS.File.Error.invalidArgument("Compression");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!("encoding" in options)) {
|
||||||
return buffer;
|
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 {
|
} finally {
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,15 @@ Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
|
|||||||
return this.unixErrno == Const.EACCES;
|
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
|
* 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);
|
return new OSError(operation, Const.ENOENT, path);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OSError.invalidArgument = function invalidArgument(operation) {
|
||||||
|
return new OSError(operation, Const.EINVAL);
|
||||||
|
};
|
||||||
|
|
||||||
let EXPORTED_SYMBOLS = [
|
let EXPORTED_SYMBOLS = [
|
||||||
"declareFFI",
|
"declareFFI",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -161,6 +161,15 @@ Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
|
|||||||
return this.winLastError == Const.ERROR_ACCESS_DENIED;
|
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
|
* 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);
|
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 = [
|
let EXPORTED_SYMBOLS = [
|
||||||
"declareFFI",
|
"declareFFI",
|
||||||
"libc",
|
"libc",
|
||||||
|
Loading…
Reference in New Issue
Block a user