зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 6 changesets (bug 854169) to investigate OSX Mn bustage on a CLOSED TREE.
Backed out changeset 236a0eba3a8a (bug 854169) Backed out changeset bd7733e5d5cf (bug 854169) Backed out changeset cbf7e38a49aa (bug 854169) Backed out changeset c0f9bfe37d74 (bug 854169) Backed out changeset 224d0d4df434 (bug 854169) Backed out changeset 1b339f171b0a (bug 854169)
This commit is contained in:
Родитель
092cf48d76
Коммит
496633aabc
|
@ -43,7 +43,6 @@ PARALLEL_DIRS += [
|
|||
'viewconfig',
|
||||
'viewsource',
|
||||
'workerloader',
|
||||
'workerlz4',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_SOCIAL']:
|
||||
|
|
|
@ -730,21 +730,18 @@ File.makeDir = function makeDir(path, options) {
|
|||
*
|
||||
* @param {string} path The path to the file.
|
||||
* @param {number=} bytes Optionally, an upper bound to the number of bytes
|
||||
* to read. DEPRECATED - please use options.bytes instead.
|
||||
* 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.
|
||||
* - {number} bytes An upper bound to the number of bytes to read.
|
||||
* - {string} compression If "lz4" and if the file is compressed using the lz4
|
||||
* compression algorithm, decompress the file contents on the fly.
|
||||
*
|
||||
* @resolves {Uint8Array} A buffer holding the bytes
|
||||
* read from the file.
|
||||
*/
|
||||
File.read = function read(path, bytes, options = {}) {
|
||||
File.read = function read(path, bytes, options) {
|
||||
let promise = Scheduler.post("read",
|
||||
[Type.path.toMsg(path), bytes, options], path);
|
||||
return promise.then(
|
||||
|
|
|
@ -93,11 +93,10 @@ if (this.Components) {
|
|||
// instances of |OS.File.Error|)
|
||||
self.postMessage({fail: exports.OS.File.Error.toMsg(exn), id:id, durationMs: durationMs});
|
||||
} else {
|
||||
LOG("Sending back regular error", exn, exn.stack, "id is", id);
|
||||
// Other exceptions do not, and should be propagated through DOM's
|
||||
// built-in mechanism for uncaught errors, although this mechanism
|
||||
// may lose interesting information.
|
||||
LOG("Sending back regular error", exn, exn.stack, "id is", id);
|
||||
|
||||
throw exn;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -43,7 +43,6 @@ let EXPORTED_SYMBOLS = [
|
|||
"declareFFI",
|
||||
"declareLazy",
|
||||
"declareLazyFFI",
|
||||
"normalizeToPointer",
|
||||
"projectValue",
|
||||
"isTypedArray",
|
||||
"defineLazyGetter",
|
||||
|
@ -1048,51 +1047,6 @@ let offsetBy =
|
|||
};
|
||||
exports.offsetBy = offsetBy;
|
||||
|
||||
/**
|
||||
* Utility function used to normalize a Typed Array or C
|
||||
* pointer into a uint8_t C pointer.
|
||||
*
|
||||
* Future versions might extend this to other data structures.
|
||||
*
|
||||
* @param {Typed array | C pointer} candidate The buffer. If
|
||||
* a C pointer, it must be non-null.
|
||||
* @param {number} bytes The number of bytes that |candidate| should contain.
|
||||
* Used for sanity checking if the size of |candidate| can be determined.
|
||||
*
|
||||
* @return {ptr:{C pointer}, bytes:number} A C pointer of type uint8_t,
|
||||
* corresponding to the start of |candidate|.
|
||||
*/
|
||||
function normalizeToPointer(candidate, bytes) {
|
||||
if (!candidate) {
|
||||
throw new TypeError("Expecting a Typed Array or a C pointer");
|
||||
}
|
||||
let ptr;
|
||||
if ("isNull" in candidate) {
|
||||
if (candidate.isNull()) {
|
||||
throw new TypeError("Expecting a non-null pointer");
|
||||
}
|
||||
ptr = Type.uint8_t.out_ptr.cast(candidate);
|
||||
if (bytes == null) {
|
||||
throw new TypeError("C pointer missing bytes indication.");
|
||||
}
|
||||
} else if (isTypedArray(candidate)) {
|
||||
// Typed Array
|
||||
ptr = Type.uint8_t.out_ptr.implementation(candidate.buffer);
|
||||
if (bytes == null) {
|
||||
bytes = candidate.byteLength;
|
||||
} else if (candidate.byteLength < bytes) {
|
||||
throw new TypeError("Buffer is too short. I need at least " +
|
||||
bytes +
|
||||
" bytes but I have only " +
|
||||
candidate.byteLength +
|
||||
"bytes");
|
||||
}
|
||||
} else {
|
||||
throw new TypeError("Expecting a Typed Array or a C pointer");
|
||||
}
|
||||
return {ptr: ptr, bytes: bytes};
|
||||
};
|
||||
exports.normalizeToPointer = normalizeToPointer;
|
||||
|
||||
///////////////////// OS interactions
|
||||
|
||||
|
|
|
@ -16,8 +16,7 @@ if (typeof Components != "undefined") {
|
|||
|
||||
let SharedAll =
|
||||
require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
|
||||
let Lz4 =
|
||||
require("resource://gre/modules/workers/lz4.js");
|
||||
|
||||
let LOG = SharedAll.LOG.bind(SharedAll, "Shared front-end");
|
||||
let clone = SharedAll.clone;
|
||||
|
||||
|
@ -83,7 +82,7 @@ AbstractFile.prototype = {
|
|||
* less than |bytes| if the file did not contain that many bytes left.
|
||||
*/
|
||||
readTo: function readTo(buffer, options = {}) {
|
||||
let {ptr, bytes} = SharedAll.normalizeToPointer(buffer, options.bytes);
|
||||
let {ptr, bytes} = AbstractFile.normalizeToPointer(buffer, options.bytes);
|
||||
let pos = 0;
|
||||
while (pos < bytes) {
|
||||
let chunkSize = this._read(ptr, bytes - pos, options);
|
||||
|
@ -117,7 +116,7 @@ AbstractFile.prototype = {
|
|||
write: function write(buffer, options = {}) {
|
||||
|
||||
let {ptr, bytes} =
|
||||
SharedAll.normalizeToPointer(buffer, options.bytes || undefined);
|
||||
AbstractFile.normalizeToPointer(buffer, options.bytes || undefined);
|
||||
|
||||
let pos = 0;
|
||||
while (pos < bytes) {
|
||||
|
@ -187,6 +186,51 @@ AbstractFile.openUnique = function openUnique(path, options = {}) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility function used to normalize a Typed Array or C
|
||||
* pointer into a uint8_t C pointer.
|
||||
*
|
||||
* Future versions might extend this to other data structures.
|
||||
*
|
||||
* @param {Typed array | C pointer} candidate The buffer. If
|
||||
* a C pointer, it must be non-null.
|
||||
* @param {number} bytes The number of bytes that |candidate| should contain.
|
||||
* Used for sanity checking if the size of |candidate| can be determined.
|
||||
*
|
||||
* @return {ptr:{C pointer}, bytes:number} A C pointer of type uint8_t,
|
||||
* corresponding to the start of |candidate|.
|
||||
*/
|
||||
AbstractFile.normalizeToPointer = function normalizeToPointer(candidate, bytes) {
|
||||
if (!candidate) {
|
||||
throw new TypeError("Expecting a Typed Array or a C pointer");
|
||||
}
|
||||
let ptr;
|
||||
if ("isNull" in candidate) {
|
||||
if (candidate.isNull()) {
|
||||
throw new TypeError("Expecting a non-null pointer");
|
||||
}
|
||||
ptr = SharedAll.Type.uint8_t.out_ptr.cast(candidate);
|
||||
if (bytes == null) {
|
||||
throw new TypeError("C pointer missing bytes indication.");
|
||||
}
|
||||
} else if (SharedAll.isTypedArray(candidate)) {
|
||||
// Typed Array
|
||||
ptr = SharedAll.Type.uint8_t.out_ptr.implementation(candidate.buffer);
|
||||
if (bytes == null) {
|
||||
bytes = candidate.byteLength;
|
||||
} else if (candidate.byteLength < bytes) {
|
||||
throw new TypeError("Buffer is too short. I need at least " +
|
||||
bytes +
|
||||
" bytes but I have only " +
|
||||
candidate.byteLength +
|
||||
"bytes");
|
||||
}
|
||||
} else {
|
||||
throw new TypeError("Expecting a Typed Array or a C pointer");
|
||||
}
|
||||
return {ptr: ptr, bytes: bytes};
|
||||
};
|
||||
|
||||
/**
|
||||
* Code shared by iterators.
|
||||
*/
|
||||
|
@ -311,29 +355,16 @@ 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. DEPRECATED - please use options.bytes instead.
|
||||
* @param {object=} options Optionally, an object with some of the following
|
||||
* fields:
|
||||
* - {number} bytes An upper bound to the number of bytes to read.
|
||||
* - {string} compression If "lz4" and if the file is compressed using the lz4
|
||||
* compression algorithm, decompress the file contents on the fly.
|
||||
* 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, options = {}) {
|
||||
if (bytes && typeof bytes == "object") {
|
||||
options = bytes;
|
||||
bytes = options.bytes || null;
|
||||
}
|
||||
let file = exports.OS.File.open(path);
|
||||
try {
|
||||
let buffer = file.read(bytes, options);
|
||||
if (options.compression == "lz4") {
|
||||
return Lz4.decompressFileContent(buffer, options);
|
||||
} else {
|
||||
return buffer;
|
||||
}
|
||||
return file.read(bytes, options);
|
||||
} finally {
|
||||
file.close();
|
||||
}
|
||||
|
@ -374,10 +405,6 @@ AbstractFile.read = function read(path, bytes, options = {}) {
|
|||
* if the system shuts down improperly (typically due to a kernel freeze
|
||||
* or a power failure) or if the device is disconnected before the buffer
|
||||
* is flushed, the file has more chances of not being corrupted.
|
||||
* - {string} compression - If empty or unspecified, do not compress the file.
|
||||
* If "lz4", compress the contents of the file atomically using lz4. For the
|
||||
* time being, the container format is specific to Mozilla and cannot be read
|
||||
* by means other than OS.File.read(..., { compression: "lz4"})
|
||||
*
|
||||
* @return {number} The number of bytes actually written.
|
||||
*/
|
||||
|
@ -399,12 +426,6 @@ AbstractFile.writeAtomic =
|
|||
buffer = new TextEncoder(encoding).encode(buffer);
|
||||
}
|
||||
|
||||
if (options.compression == "lz4") {
|
||||
buffer = Lz4.compressFileContent(buffer, options);
|
||||
options = Object.create(options);
|
||||
options.bytes = buffer.byteLength;
|
||||
}
|
||||
|
||||
let bytesWritten = 0;
|
||||
|
||||
if (!options.tmpPath) {
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function test_compress_lz4() {
|
||||
let path = OS.Path.join(OS.Constants.Path.tmpDir, "compression.lz");
|
||||
let array = new Uint8Array(1024);
|
||||
for (let i = 0; i < array.byteLength; ++i) {
|
||||
array[i] = i;
|
||||
}
|
||||
|
||||
do_print("Writing data with lz4 compression");
|
||||
let bytes = yield OS.File.writeAtomic(path, array, { compression: "lz4" });
|
||||
do_print("Compressed " + array.byteLength + " bytes into " + bytes);
|
||||
|
||||
do_print("Reading back with lz4 decompression");
|
||||
let decompressed = yield OS.File.read(path, { compression: "lz4" });
|
||||
do_print("Decompressed into " + decompressed.byteLength + " bytes");
|
||||
do_check_eq(Array.prototype.join.call(array), Array.prototype.join.call(decompressed));
|
||||
});
|
||||
|
||||
add_task(function test_uncompressed() {
|
||||
do_print("Writing data without compression");
|
||||
let path = OS.Path.join(OS.Constants.Path.tmpDir, "no_compression.tmp");
|
||||
let array = new Uint8Array(1024);
|
||||
for (let i = 0; i < array.byteLength; ++i) {
|
||||
array[i] = i;
|
||||
}
|
||||
let bytes = yield OS.File.writeAtomic(path, array); // No compression
|
||||
|
||||
let exn;
|
||||
// Force decompression, reading should fail
|
||||
try {
|
||||
yield OS.File.read(path, { compression: "lz4" });
|
||||
} catch (ex) {
|
||||
exn = ex;
|
||||
}
|
||||
do_check_true(!!exn);
|
||||
do_check_true(exn.message.indexOf("Invalid header") != -1);
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
do_test_finished();
|
||||
});
|
|
@ -22,4 +22,3 @@ tail =
|
|||
[test_shutdown.js]
|
||||
[test_unique.js]
|
||||
[test_open.js]
|
||||
[test_compression.js]
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
#include "mozilla/Compression.h"
|
||||
|
||||
/**
|
||||
* LZ4 is a very fast byte-wise compression algorithm.
|
||||
*
|
||||
* Compared to Google's Snappy it is faster to compress and decompress and
|
||||
* generally produces output of about the same size.
|
||||
*
|
||||
* Compared to zlib it compresses at about 10x the speed, decompresses at about
|
||||
* 4x the speed and produces output of about 1.5x the size.
|
||||
*
|
||||
*/
|
||||
|
||||
using namespace mozilla::Compression;
|
||||
|
||||
/**
|
||||
* Compresses 'inputSize' bytes from 'source' into 'dest'.
|
||||
* Destination buffer must be already allocated,
|
||||
* and must be sized to handle worst cases situations (input data not compressible)
|
||||
* Worst case size evaluation is provided by function LZ4_compressBound()
|
||||
*
|
||||
* @param inputSize is the input size. Max supported value is ~1.9GB
|
||||
* @param return the number of bytes written in buffer dest
|
||||
*/
|
||||
extern "C" MOZ_EXPORT size_t
|
||||
workerlz4_compress(const char* source, size_t inputSize, char* dest) {
|
||||
return LZ4::compress(source, inputSize, dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the source stream is malformed, the function will stop decoding
|
||||
* and return a negative result, indicating the byte position of the
|
||||
* faulty instruction
|
||||
*
|
||||
* This function never writes outside of provided buffers, and never
|
||||
* modifies input buffer.
|
||||
*
|
||||
* note : destination buffer must be already allocated.
|
||||
* its size must be a minimum of 'outputSize' bytes.
|
||||
* @param outputSize is the output size, therefore the original size
|
||||
* @return true/false
|
||||
*/
|
||||
extern "C" MOZ_EXPORT int
|
||||
workerlz4_decompress(const char* source, size_t inputSize,
|
||||
char* dest, size_t maxOutputSize,
|
||||
size_t *bytesOutput) {
|
||||
return LZ4::decompress(source, inputSize,
|
||||
dest, maxOutputSize,
|
||||
bytesOutput);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Provides the maximum size that LZ4 may output in a "worst case"
|
||||
scenario (input data not compressible) primarily useful for memory
|
||||
allocation of output buffer.
|
||||
note : this function is limited by "int" range (2^31-1)
|
||||
|
||||
@param inputSize is the input size. Max supported value is ~1.9GB
|
||||
@return maximum output size in a "worst case" scenario
|
||||
*/
|
||||
extern "C" MOZ_EXPORT size_t
|
||||
workerlz4_maxCompressedSize(size_t inputSize)
|
||||
{
|
||||
return LZ4::maxCompressedSize(inputSize);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
if (typeof Components != "undefined") {
|
||||
throw new Error("This file is meant to be loaded in a worker");
|
||||
}
|
||||
if (!module || !exports) {
|
||||
throw new Error("Please load this module with require()");
|
||||
}
|
||||
|
||||
const SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
|
||||
const Internals = require("resource://gre/modules/workers/lz4_internal.js");
|
||||
|
||||
const MAGIC_NUMBER = new Uint8Array([109, 111, 122, 76, 122, 52, 48, 0]); // "mozLz4a\0"
|
||||
|
||||
const BYTES_IN_SIZE_HEADER = ctypes.uint32_t.size;
|
||||
|
||||
const HEADER_SIZE = MAGIC_NUMBER.byteLength + BYTES_IN_SIZE_HEADER;
|
||||
|
||||
const EXPECTED_HEADER_TYPE = new ctypes.ArrayType(ctypes.uint8_t, HEADER_SIZE);
|
||||
const EXPECTED_SIZE_BUFFER_TYPE = new ctypes.ArrayType(ctypes.uint8_t, BYTES_IN_SIZE_HEADER);
|
||||
|
||||
/**
|
||||
* An error during (de)compression
|
||||
*
|
||||
* @param {string} operation The name of the operation ("compress", "decompress")
|
||||
* @param {string} reason A reason to be used when matching errors. Must start
|
||||
* with "because", e.g. "becauseInvalidContent".
|
||||
* @param {string} message A human-readable message.
|
||||
*/
|
||||
function LZError(operation, reason, message) {
|
||||
SharedAll.OSError.call(this);
|
||||
this.operation = operation;
|
||||
this[reason] = true;
|
||||
this.message = message;
|
||||
}
|
||||
LZError.prototype = Object.create(SharedAll.OSError);
|
||||
LZError.prototype.toString = function toString() {
|
||||
return this.message;
|
||||
};
|
||||
exports.Error = LZError;
|
||||
|
||||
/**
|
||||
* Compress a block to a form suitable for writing to disk.
|
||||
*
|
||||
* Compatibility note: For the moment, we are basing our code on lz4
|
||||
* 1.3, which does not specify a *file* format. Therefore, we define
|
||||
* our own format. Once lz4 defines a complete file format, we will
|
||||
* migrate both |compressFileContent| and |decompressFileContent| to this file
|
||||
* format. For backwards-compatibility, |decompressFileContent| will however
|
||||
* keep the ability to decompress files provided with older versions of
|
||||
* |compressFileContent|.
|
||||
*
|
||||
* Compressed files have the following layout:
|
||||
*
|
||||
* | MAGIC_NUMBER (8 bytes) | content size (uint32_t, little endian) | content, as obtained from lz4_compress |
|
||||
*
|
||||
* @param {TypedArray|void*} buffer The buffer to write to the disk.
|
||||
* @param {object=} options An object that may contain the following fields:
|
||||
* - {number} bytes The number of bytes to read from |buffer|. If |buffer|
|
||||
* is an |ArrayBuffer|, |bytes| defaults to |buffer.byteLength|. If
|
||||
* |buffer| is a |void*|, |bytes| MUST be provided.
|
||||
* @return {Uint8Array} An array of bytes suitable for being written to the
|
||||
* disk.
|
||||
*/
|
||||
function compressFileContent(array, options = {}) {
|
||||
// Prepare the output array
|
||||
let inputBytes;
|
||||
if (SharedAll.isTypedArray(array) && !(options && "bytes" in options)) {
|
||||
inputBytes = array.byteLength;
|
||||
} else if (options && options.bytes) {
|
||||
inputBytes = options.bytes;
|
||||
} else {
|
||||
throw new TypeError("compressFileContent requires a size");
|
||||
}
|
||||
let maxCompressedSize = Internals.maxCompressedSize(inputBytes);
|
||||
let outputArray = new Uint8Array(HEADER_SIZE + maxCompressedSize);
|
||||
|
||||
// Compress to output array
|
||||
let payload = new Uint8Array(outputArray.buffer, outputArray.byteOffset + HEADER_SIZE);
|
||||
let compressedSize = Internals.compress(array, inputBytes, payload);
|
||||
|
||||
// Add headers
|
||||
outputArray.set(MAGIC_NUMBER);
|
||||
let view = new DataView(outputArray.buffer);
|
||||
view.setUint32(MAGIC_NUMBER.byteLength, inputBytes, true);
|
||||
|
||||
return new Uint8Array(outputArray.buffer, 0, HEADER_SIZE + compressedSize);
|
||||
}
|
||||
exports.compressFileContent = compressFileContent;
|
||||
|
||||
function decompressFileContent(array, options = {}) {
|
||||
let {ptr, bytes} = SharedAll.normalizeToPointer(array, options.bytes);
|
||||
if (bytes < HEADER_SIZE) {
|
||||
throw new LZError("decompress", "becauseLZNoHeader", "Buffer is too short (no header)");
|
||||
}
|
||||
|
||||
// Read headers
|
||||
let expectMagicNumber = ctypes.cast(ptr, EXPECTED_HEADER_TYPE.ptr).contents;
|
||||
for (let i = 0; i < MAGIC_NUMBER.byteLength; ++i) {
|
||||
if (expectMagicNumber[i] != MAGIC_NUMBER[i]) {
|
||||
throw new LZError("decompress", "becauseLZWrongMagicNumber", "Invalid header (no magic number");
|
||||
}
|
||||
}
|
||||
|
||||
let sizeBuf =
|
||||
ctypes.cast(
|
||||
SharedAll.offsetBy(ptr, MAGIC_NUMBER.byteLength),
|
||||
EXPECTED_SIZE_BUFFER_TYPE.ptr).contents;
|
||||
let expectDecompressedSize =
|
||||
sizeBuf[0] + (sizeBuf[1] << 8) + (sizeBuf[2] << 16) + (sizeBuf[3] << 24);
|
||||
if (expectDecompressedSize == 0) {
|
||||
// The underlying algorithm cannot handle a size of 0
|
||||
return new Uint8Array(0);
|
||||
}
|
||||
|
||||
// Prepare the input buffer
|
||||
let inputPtr = SharedAll.offsetBy(ptr, HEADER_SIZE);
|
||||
|
||||
// Prepare the output buffer
|
||||
let outputBuffer = new Uint8Array(expectDecompressedSize);
|
||||
let decompressedBytes = (new SharedAll.Type.size_t.implementation(0));
|
||||
|
||||
// Decompress
|
||||
let success = Internals.decompress(inputPtr, bytes - HEADER_SIZE,
|
||||
outputBuffer, outputBuffer.byteLength,
|
||||
decompressedBytes.address());
|
||||
if (!success) {
|
||||
throw new LZError("decompress", "becauseLZInvalidContent", "Invalid content:Decompression stopped at " + decompressedBytes.value);
|
||||
}
|
||||
return new Uint8Array(outputBuffer.buffer, outputBuffer.byteOffset, decompressedBytes.value);
|
||||
}
|
||||
exports.decompressFileContent = decompressFileContent;
|
|
@ -1,58 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
if (typeof Components != "undefined") {
|
||||
throw new Error("This file is meant to be loaded in a worker");
|
||||
}
|
||||
if (!module || !exports) {
|
||||
throw new Error("Please load this module with require()");
|
||||
}
|
||||
|
||||
let SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
|
||||
let libxul = ctypes.open(SharedAll.Constants.Path.libxul);
|
||||
let declareLazyFII = SharedAll.declareLazyFFI;
|
||||
let Type = SharedAll.Type;
|
||||
|
||||
let Primitives = {};
|
||||
|
||||
declareLazyFII(Primitives, "compress", libxul,
|
||||
"workerlz4_compress",
|
||||
null,
|
||||
/*return*/ Type.size_t,
|
||||
/*const source*/ Type.void_t.in_ptr,
|
||||
/*inputSize*/ Type.size_t,
|
||||
/*dest*/ Type.void_t.out_ptr
|
||||
);
|
||||
|
||||
declareLazyFII(Primitives, "decompress", libxul,
|
||||
"workerlz4_decompress",
|
||||
null,
|
||||
/*return*/ Type.int,
|
||||
/*const source*/ Type.void_t.in_ptr,
|
||||
/*inputSize*/ Type.size_t,
|
||||
/*dest*/ Type.void_t.out_ptr,
|
||||
/*maxOutputSize*/ Type.size_t,
|
||||
/*actualOutputSize*/ Type.size_t.out_ptr
|
||||
);
|
||||
|
||||
declareLazyFII(Primitives, "maxCompressedSize", libxul,
|
||||
"workerlz4_maxCompressedSize",
|
||||
null,
|
||||
/*return*/ Type.size_t,
|
||||
/*inputSize*/ Type.size_t
|
||||
);
|
||||
|
||||
module.exports = {
|
||||
get compress() {
|
||||
return Primitives.compress;
|
||||
},
|
||||
get decompress() {
|
||||
return Primitives.decompress;
|
||||
},
|
||||
get maxCompressedSize() {
|
||||
return Primitives.maxCompressedSize;
|
||||
}
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/workers'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'lz4.js',
|
||||
'lz4_internal.js',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'lz4.cpp',
|
||||
]
|
||||
|
||||
TEST_DIRS += ['tests']
|
||||
|
||||
EXPORT_LIBRARY = True
|
||||
FINAL_LIBRARY = 'xul'
|
|
@ -1,7 +0,0 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['xpcshell/xpcshell.ini']
|
|
@ -1 +0,0 @@
|
|||
content test_lz4 ./
|
Двоичные данные
toolkit/components/workerlz4/tests/xpcshell/data/compression.lz
Двоичные данные
toolkit/components/workerlz4/tests/xpcshell/data/compression.lz
Двоичный файл не отображается.
|
@ -1,146 +0,0 @@
|
|||
importScripts("resource://gre/modules/workers/require.js");
|
||||
importScripts("resource://gre/modules/osfile.jsm");
|
||||
|
||||
|
||||
function do_print(x) {
|
||||
//self.postMessage({kind: "do_print", args: [x]});
|
||||
dump("TEST-INFO: " + x + "\n");
|
||||
}
|
||||
|
||||
function do_check_true(x) {
|
||||
self.postMessage({kind: "do_check_true", args: [!!x]});
|
||||
if (x) {
|
||||
dump("TEST-PASS: " + x + "\n");
|
||||
} else {
|
||||
throw new Error("do_check_true failed");
|
||||
}
|
||||
}
|
||||
|
||||
function do_check_eq(a, b) {
|
||||
let result = a == b;
|
||||
self.postMessage({kind: "do_check_true", args: [result]});
|
||||
if (!result) {
|
||||
throw new Error("do_check_eq failed " + a + " != " + b);
|
||||
}
|
||||
}
|
||||
|
||||
function do_test_complete() {
|
||||
self.postMessage({kind: "do_test_complete", args:[]});
|
||||
}
|
||||
|
||||
self.onmessage = function() {
|
||||
try {
|
||||
run_test();
|
||||
} catch (ex) {
|
||||
let {message, moduleStack, moduleName, lineNumber} = ex;
|
||||
let error = new Error(message, moduleName, lineNumber);
|
||||
error.stack = moduleStack;
|
||||
dump("Uncaught error: " + error + "\n");
|
||||
dump("Full stack: " + moduleStack + "\n");
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
let Lz4;
|
||||
let Internals;
|
||||
function test_import() {
|
||||
Lz4 = require("resource://gre/modules/workers/lz4.js");
|
||||
Internals = require("resource://gre/modules/workers/lz4_internal.js");
|
||||
}
|
||||
|
||||
function test_bound() {
|
||||
for (let k of ["compress", "decompress", "maxCompressedSize"]) {
|
||||
try {
|
||||
do_print("Checking the existence of " + k + "\n");
|
||||
do_check_true(!!Internals[k]);
|
||||
do_print(k + " exists");
|
||||
} catch (ex) {
|
||||
// Ignore errors
|
||||
do_print(k + " doesn't exist!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function test_reference_file() {
|
||||
do_print("Decompress reference file");
|
||||
let path = OS.Path.join("data", "compression.lz");
|
||||
let data = OS.File.read(path);
|
||||
let decompressed = Lz4.decompressFileContent(data);
|
||||
let text = (new TextDecoder()).decode(decompressed);
|
||||
do_check_eq(text, "Hello, lz4");
|
||||
}
|
||||
|
||||
function compare_arrays(a, b) {
|
||||
return Array.prototype.join.call(a) == Array.prototype.join.call(a);
|
||||
}
|
||||
|
||||
function run_rawcompression(name, array) {
|
||||
do_print("Raw compression test " + name);
|
||||
let length = array.byteLength;
|
||||
let compressedArray = new Uint8Array(Internals.maxCompressedSize(length));
|
||||
let compressedBytes = Internals.compress(array, length, compressedArray);
|
||||
compressedArray = new Uint8Array(compressedArray.buffer, 0, compressedBytes);
|
||||
do_print("Raw compressed: " + length + " into " + compressedBytes);
|
||||
|
||||
let decompressedArray = new Uint8Array(length);
|
||||
let decompressedBytes = new ctypes.size_t();
|
||||
let success = Internals.decompress(compressedArray, compressedBytes,
|
||||
decompressedArray, length,
|
||||
decompressedBytes.address());
|
||||
do_print("Raw decompression success? " + success);
|
||||
do_print("Raw decompression size: " + decompressedBytes.value);
|
||||
do_check_true(compare_arrays(array, decompressedArray));
|
||||
}
|
||||
|
||||
function run_filecompression(name, array) {
|
||||
do_print("File compression test " + name);
|
||||
let compressed = Lz4.compressFileContent(array);
|
||||
do_print("Compressed " + array.byteLength + " bytes into " + compressed.byteLength);
|
||||
|
||||
let decompressed = Lz4.decompressFileContent(compressed);
|
||||
do_print("Decompressed " + compressed.byteLength + " bytes into " + decompressed.byteLength);
|
||||
do_check_true(compare_arrays(array, decompressed));
|
||||
}
|
||||
|
||||
function run_faileddecompression(name, array) {
|
||||
do_print("invalid decompression test " + name);
|
||||
|
||||
// Ensure that raw decompression doesn't segfault
|
||||
let length = 1 << 14;
|
||||
let decompressedArray = new Uint8Array(length);
|
||||
let decompressedBytes = new ctypes.size_t();
|
||||
Internals.decompress(array, array.byteLength,
|
||||
decompressedArray, length,
|
||||
decompressedBytes.address());
|
||||
|
||||
// File decompression should fail with an acceptable exception
|
||||
let exn = null;
|
||||
try {
|
||||
Lz4.decompressFileContent(array);
|
||||
} catch (ex) {
|
||||
exn = ex;
|
||||
}
|
||||
do_check_true(exn);
|
||||
if (array.byteLength < 10) {
|
||||
do_check_true(exn.becauseLZNoHeader);
|
||||
} else {
|
||||
do_check_true(exn.becauseLZWrongMagicNumber);
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
test_import();
|
||||
test_bound();
|
||||
test_reference_file();
|
||||
for (let length of [0, 1, 1024]) {
|
||||
let array = new Uint8Array(length);
|
||||
for (let i = 0; i < length; ++i) {
|
||||
array[i] = i % 256;
|
||||
}
|
||||
let name = length + " bytes";
|
||||
run_rawcompression(name, array);
|
||||
run_filecompression(name, array);
|
||||
run_faileddecompression(name, array);
|
||||
}
|
||||
do_test_complete();
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
let WORKER_SOURCE_URI = "chrome://test_lz4/content/worker_lz4.js";
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
||||
add_task(function() {
|
||||
let worker = new ChromeWorker(WORKER_SOURCE_URI);
|
||||
let deferred = Promise.defer();
|
||||
worker.onmessage = function(event) {
|
||||
let data = event.data;
|
||||
switch (data.kind) {
|
||||
case "do_check_true":
|
||||
try {
|
||||
do_check_true(data.args[0]);
|
||||
} catch (ex) {
|
||||
// Ignore errors
|
||||
}
|
||||
return;
|
||||
case "do_test_complete":
|
||||
deferred.resolve();
|
||||
worker.terminate();
|
||||
break;
|
||||
case "do_print":
|
||||
do_print(data.args[0]);
|
||||
}
|
||||
};
|
||||
worker.onerror = function(event) {
|
||||
let error = new Error(event.message, event.filename, event.lineno);
|
||||
worker.terminate();
|
||||
deferred.reject(error);
|
||||
};
|
||||
worker.postMessage("START");
|
||||
return deferred.promise;
|
||||
});
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
[DEFAULT]
|
||||
head =
|
||||
tail =
|
||||
support-files =
|
||||
data/worker_lz4.js
|
||||
data/chrome.manifest
|
||||
data/compression.lz
|
||||
|
||||
[test_lz4.js]
|
Загрузка…
Ссылка в новой задаче