summaryrefslogtreecommitdiff
path: root/deps/v8/third_party
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2021-07-14 11:30:07 +0200
committerMichaël Zasso <targos@protonmail.com>2021-07-20 15:24:51 +0200
commit6cdd310275bb0f8056aa0ae6d95614e9ca5b70c7 (patch)
tree9ed37b19cd668894854b7f469010f7621e63ef81 /deps/v8/third_party
parentc0f10006c82d2d9896a552de98ed146f9542720d (diff)
downloadnode-new-6cdd310275bb0f8056aa0ae6d95614e9ca5b70c7.tar.gz
deps: update V8 to 9.2.230.21
PR-URL: https://github.com/nodejs/node/pull/38990 Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/v8/third_party')
-rw-r--r--deps/v8/third_party/google_benchmark/BUILD.gn75
-rw-r--r--deps/v8/third_party/google_benchmark/OWNERS3
-rw-r--r--deps/v8/third_party/google_benchmark/README.v821
-rw-r--r--deps/v8/third_party/googletest/BUILD.gn38
-rw-r--r--deps/v8/third_party/googletest/src/googletest/include/gtest/gtest_prod.h6
-rw-r--r--deps/v8/third_party/inspector_protocol/BUILD.gn6
-rw-r--r--deps/v8/third_party/inspector_protocol/README.v82
-rw-r--r--deps/v8/third_party/inspector_protocol/crdtp/serializable.cc5
-rw-r--r--deps/v8/third_party/inspector_protocol/crdtp/status.cc2
-rw-r--r--deps/v8/third_party/inspector_protocol/crdtp/status.h1
-rw-r--r--deps/v8/third_party/inspector_protocol/lib/ValueConversions_cpp.template4
-rw-r--r--deps/v8/third_party/inspector_protocol/lib/base_string_adapter_cc.template5
-rw-r--r--deps/v8/third_party/inspector_protocol/pdl.py3
-rw-r--r--deps/v8/third_party/jsoncpp/BUILD.gn2
-rw-r--r--deps/v8/third_party/zlib/OWNERS1
-rw-r--r--deps/v8/third_party/zlib/google/OWNERS2
-rw-r--r--deps/v8/third_party/zlib/google/zip.cc140
-rw-r--r--deps/v8/third_party/zlib/google/zip.h138
-rw-r--r--deps/v8/third_party/zlib/google/zip_reader_unittest.cc5
-rw-r--r--deps/v8/third_party/zlib/google/zip_unittest.cc187
-rw-r--r--deps/v8/third_party/zlib/google/zip_writer.cc191
-rw-r--r--deps/v8/third_party/zlib/google/zip_writer.h63
22 files changed, 597 insertions, 303 deletions
diff --git a/deps/v8/third_party/google_benchmark/BUILD.gn b/deps/v8/third_party/google_benchmark/BUILD.gn
new file mode 100644
index 0000000000..e746cc421a
--- /dev/null
+++ b/deps/v8/third_party/google_benchmark/BUILD.gn
@@ -0,0 +1,75 @@
+# Copyright 2020 The V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/gclient_args.gni")
+import("../../gni/v8.gni")
+
+if (v8_enable_google_benchmark) {
+ config("benchmark_config") {
+ include_dirs = [ "src/include" ]
+ }
+
+ source_set("google_benchmark") {
+ testonly = true
+
+ public = [ "src/include/benchmark/benchmark.h" ]
+
+ sources = [
+ "src/src/arraysize.h",
+ "src/src/benchmark.cc",
+ "src/src/benchmark_api_internal.cc",
+ "src/src/benchmark_api_internal.h",
+ "src/src/benchmark_name.cc",
+ "src/src/benchmark_register.cc",
+ "src/src/benchmark_register.h",
+ "src/src/benchmark_runner.cc",
+ "src/src/benchmark_runner.h",
+ "src/src/check.h",
+ "src/src/colorprint.cc",
+ "src/src/colorprint.h",
+ "src/src/commandlineflags.cc",
+ "src/src/commandlineflags.h",
+ "src/src/complexity.cc",
+ "src/src/complexity.h",
+ "src/src/console_reporter.cc",
+ "src/src/counter.cc",
+ "src/src/counter.h",
+ "src/src/csv_reporter.cc",
+ "src/src/internal_macros.h",
+ "src/src/json_reporter.cc",
+ "src/src/log.h",
+ "src/src/mutex.h",
+ "src/src/perf_counters.cc",
+ "src/src/perf_counters.h",
+ "src/src/re.h",
+ "src/src/reporter.cc",
+ "src/src/sleep.cc",
+ "src/src/sleep.h",
+ "src/src/statistics.cc",
+ "src/src/statistics.h",
+ "src/src/string_util.cc",
+ "src/src/string_util.h",
+ "src/src/sysinfo.cc",
+ "src/src/thread_manager.h",
+ "src/src/thread_timer.h",
+ "src/src/timers.cc",
+ "src/src/timers.h",
+ ]
+
+ all_dependent_configs = [ ":benchmark_config" ]
+
+ defines = [
+ # Tell google_benchmark to always use standard regular expressions.
+ "HAVE_GNU_POSIX_REGEX=0",
+ "HAVE_POSIX_REGEX=0",
+ "HAVE_STD_REGEX=1",
+ ]
+ }
+
+ source_set("benchmark_main") {
+ testonly = true
+ sources = [ "src/src/benchmark_main.cc" ]
+ public_deps = [ ":google_benchmark" ]
+ }
+}
diff --git a/deps/v8/third_party/google_benchmark/OWNERS b/deps/v8/third_party/google_benchmark/OWNERS
new file mode 100644
index 0000000000..d934f47fe1
--- /dev/null
+++ b/deps/v8/third_party/google_benchmark/OWNERS
@@ -0,0 +1,3 @@
+file:../../INFRA_OWNERS
+
+mlippautz@chromium.org
diff --git a/deps/v8/third_party/google_benchmark/README.v8 b/deps/v8/third_party/google_benchmark/README.v8
new file mode 100644
index 0000000000..fe2ac187ac
--- /dev/null
+++ b/deps/v8/third_party/google_benchmark/README.v8
@@ -0,0 +1,21 @@
+Name: Google Benchmark
+Short Name: benchmark
+URL: https://github.com/google/benchmark
+Version: unknown
+License: Apache 2.0
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+A microbenchmark support library.
+
+To include this library in the V8 checkout, add the following clause to
+your .gclient configuration.
+
+ "custom_vars": {
+ "checkout_google_benchmark": True,
+ }
+
+
+Local Additions:
+* gn file for building in V8
diff --git a/deps/v8/third_party/googletest/BUILD.gn b/deps/v8/third_party/googletest/BUILD.gn
index cfa9205547..4d393efd95 100644
--- a/deps/v8/third_party/googletest/BUILD.gn
+++ b/deps/v8/third_party/googletest/BUILD.gn
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("../../gni/v8.gni")
+
config("gtest_config") {
visibility = [ ":*" ] # gmock also shares this config.
@@ -49,8 +51,6 @@ config("gmock_config") {
source_set("gtest") {
testonly = true
sources = [
- # TODO(crbug.com/829773): Remove this after transitioning off <tr1/tuple>.
- "custom/gmock/internal/custom/gmock-port.h",
"src/googletest/include/gtest/gtest-death-test.h",
"src/googletest/include/gtest/gtest-matchers.h",
"src/googletest/include/gtest/gtest-message.h",
@@ -64,12 +64,9 @@ source_set("gtest") {
"src/googletest/include/gtest/internal/gtest-death-test-internal.h",
"src/googletest/include/gtest/internal/gtest-filepath.h",
"src/googletest/include/gtest/internal/gtest-internal.h",
- "src/googletest/include/gtest/internal/gtest-linked_ptr.h",
- "src/googletest/include/gtest/internal/gtest-param-util-generated.h",
"src/googletest/include/gtest/internal/gtest-param-util.h",
"src/googletest/include/gtest/internal/gtest-port.h",
"src/googletest/include/gtest/internal/gtest-string.h",
- "src/googletest/include/gtest/internal/gtest-tuple.h",
"src/googletest/include/gtest/internal/gtest-type-util.h",
#"src/googletest/src/gtest-all.cc", # Not needed by our build.
@@ -92,6 +89,15 @@ source_set("gtest") {
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
+ # V8-only workaround for http://crbug.com/chromium/1191946. Ensures that
+ # googletest is compiled with the same visibility such as the rest of V8, see
+ # https://source.chromium.org/chromium/chromium/src/+/master:v8/gni/v8.gni
+ if ((is_posix || is_fuchsia) &&
+ (v8_enable_backtrace || v8_monolithic || v8_expose_symbols)) {
+ configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
+ configs += [ "//build/config/gcc:symbol_visibility_default" ]
+ }
+
deps = []
if (is_fuchsia) {
@@ -118,22 +124,16 @@ source_set("gmock") {
"src/googlemock/include/gmock/gmock-actions.h",
"src/googlemock/include/gmock/gmock-cardinalities.h",
"src/googlemock/include/gmock/gmock-function-mocker.h",
- "src/googlemock/include/gmock/gmock-generated-actions.h",
- "src/googlemock/include/gmock/gmock-generated-nice-strict.h",
"src/googlemock/include/gmock/gmock-matchers.h",
"src/googlemock/include/gmock/gmock-more-actions.h",
"src/googlemock/include/gmock/gmock-more-matchers.h",
"src/googlemock/include/gmock/gmock-nice-strict.h",
"src/googlemock/include/gmock/gmock-spec-builders.h",
"src/googlemock/include/gmock/gmock.h",
- "src/googlemock/include/gmock/internal/gmock-generated-internal-utils.h",
"src/googlemock/include/gmock/internal/gmock-internal-utils.h",
"src/googlemock/include/gmock/internal/gmock-port.h",
"src/googlemock/include/gmock/internal/gmock-pp.h",
- # gmock helpers.
- "custom/gmock/internal/custom/gmock-port.h",
-
#"src/googlemock/src/gmock-all.cc", # Not needed by our build.
"src/googlemock/src/gmock-cardinalities.cc",
"src/googlemock/src/gmock-internal-utils.cc",
@@ -142,10 +142,21 @@ source_set("gmock") {
"src/googlemock/src/gmock.cc",
]
+ # V8-only workaround for http://crbug.com/chromium/1191946. Ensures that
+ # googletest is compiled with the same visibility such as the rest of V8, see
+ # https://source.chromium.org/chromium/chromium/src/+/master:v8/gni/v8.gni
+ if ((is_posix || is_fuchsia) &&
+ (v8_enable_backtrace || v8_monolithic || v8_expose_symbols)) {
+ configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
+ configs += [ "//build/config/gcc:symbol_visibility_default" ]
+ }
+
public_configs = [
":gmock_config",
":gtest_config",
]
+
+ deps = [ ":gtest" ]
}
# Do NOT depend on this directly. Use //testing/gmock:gmock_main instead.
@@ -153,5 +164,8 @@ source_set("gmock") {
static_library("gmock_main") {
testonly = true
sources = [ "src/googlemock/src/gmock_main.cc" ]
- deps = [ ":gmock" ]
+ deps = [
+ ":gmock",
+ ":gtest",
+ ]
}
diff --git a/deps/v8/third_party/googletest/src/googletest/include/gtest/gtest_prod.h b/deps/v8/third_party/googletest/src/googletest/include/gtest/gtest_prod.h
index e651671ebd..38b9d85a51 100644
--- a/deps/v8/third_party/googletest/src/googletest/include/gtest/gtest_prod.h
+++ b/deps/v8/third_party/googletest/src/googletest/include/gtest/gtest_prod.h
@@ -31,8 +31,8 @@
// Google C++ Testing and Mocking Framework definitions useful in production code.
// GOOGLETEST_CM0003 DO NOT DELETE
-#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
-#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
// When you need to test the private or protected members of a class,
// use the FRIEND_TEST macro to declare your tests as friends of the
@@ -58,4 +58,4 @@
#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test
-#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
diff --git a/deps/v8/third_party/inspector_protocol/BUILD.gn b/deps/v8/third_party/inspector_protocol/BUILD.gn
index 880b651c09..94b7fe2677 100644
--- a/deps/v8/third_party/inspector_protocol/BUILD.gn
+++ b/deps/v8/third_party/inspector_protocol/BUILD.gn
@@ -5,7 +5,10 @@
import("../../gni/v8.gni")
config("crdtp_config") {
- visibility = [ "../../src/inspector:*", ":*" ]
+ visibility = [
+ ":*",
+ "../../src/inspector:*",
+ ]
configs = [ "../../:internal_config" ]
include_dirs = [ "../../include" ]
}
@@ -46,6 +49,7 @@ v8_source_set("crdtp_platform") {
"crdtp/json_platform_v8.cc",
]
public_deps = [ "../..:v8_libbase" ]
+ deps = [ "../../:v8_internal_headers" ]
configs = [ ":crdtp_config" ]
}
diff --git a/deps/v8/third_party/inspector_protocol/README.v8 b/deps/v8/third_party/inspector_protocol/README.v8
index 97bc1c3414..cc5e083c6a 100644
--- a/deps/v8/third_party/inspector_protocol/README.v8
+++ b/deps/v8/third_party/inspector_protocol/README.v8
@@ -2,7 +2,7 @@ Name: inspector protocol
Short Name: inspector_protocol
URL: https://chromium.googlesource.com/deps/inspector_protocol/
Version: 0
-Revision: 94298cef795ec994106bdaff002c41182911b767
+Revision: 35e8d2d89cb017d72cf905362672de77c978e1e6
License: BSD
License File: LICENSE
Security Critical: no
diff --git a/deps/v8/third_party/inspector_protocol/crdtp/serializable.cc b/deps/v8/third_party/inspector_protocol/crdtp/serializable.cc
index 20de53ecc0..7a21ffd35f 100644
--- a/deps/v8/third_party/inspector_protocol/crdtp/serializable.cc
+++ b/deps/v8/third_party/inspector_protocol/crdtp/serializable.cc
@@ -4,6 +4,8 @@
#include "serializable.h"
+#include <utility>
+
namespace v8_crdtp {
// =============================================================================
// Serializable - An object to be emitted as a sequence of bytes.
@@ -18,7 +20,8 @@ std::vector<uint8_t> Serializable::Serialize() const {
namespace {
class PreSerialized : public Serializable {
public:
- explicit PreSerialized(std::vector<uint8_t> bytes) : bytes_(bytes) {}
+ explicit PreSerialized(std::vector<uint8_t> bytes)
+ : bytes_(std::move(bytes)) {}
void AppendSerialized(std::vector<uint8_t>* out) const override {
out->insert(out->end(), bytes_.begin(), bytes_.end());
diff --git a/deps/v8/third_party/inspector_protocol/crdtp/status.cc b/deps/v8/third_party/inspector_protocol/crdtp/status.cc
index 4a8e03d389..7181df97d1 100644
--- a/deps/v8/third_party/inspector_protocol/crdtp/status.cc
+++ b/deps/v8/third_party/inspector_protocol/crdtp/status.cc
@@ -113,6 +113,8 @@ std::string Status::Message() const {
return "BINDINGS: string8 value expected";
case Error::BINDINGS_BINARY_VALUE_EXPECTED:
return "BINDINGS: binary value expected";
+ case Error::BINDINGS_DICTIONARY_VALUE_EXPECTED:
+ return "BINDINGS: dictionary value expected";
}
// Some compilers can't figure out that we can't get here.
return "INVALID ERROR CODE";
diff --git a/deps/v8/third_party/inspector_protocol/crdtp/status.h b/deps/v8/third_party/inspector_protocol/crdtp/status.h
index 45e0a57acf..1039156942 100644
--- a/deps/v8/third_party/inspector_protocol/crdtp/status.h
+++ b/deps/v8/third_party/inspector_protocol/crdtp/status.h
@@ -77,6 +77,7 @@ enum class Error {
BINDINGS_STRING_VALUE_EXPECTED = 0x34,
BINDINGS_STRING8_VALUE_EXPECTED = 0x35,
BINDINGS_BINARY_VALUE_EXPECTED = 0x36,
+ BINDINGS_DICTIONARY_VALUE_EXPECTED = 0x37,
};
// A status value with position that can be copied. The default status
diff --git a/deps/v8/third_party/inspector_protocol/lib/ValueConversions_cpp.template b/deps/v8/third_party/inspector_protocol/lib/ValueConversions_cpp.template
index 36c8dcc356..a16b522c38 100644
--- a/deps/v8/third_party/inspector_protocol/lib/ValueConversions_cpp.template
+++ b/deps/v8/third_party/inspector_protocol/lib/ValueConversions_cpp.template
@@ -96,6 +96,10 @@ bool ProtocolTypeTraits<std::unique_ptr<DictionaryValue>>::Deserialize(
std::unique_ptr<Value> res;
if (!ProtocolTypeTraits<std::unique_ptr<Value>>::Deserialize(state, &res))
return false;
+ if (res->type() != Value::TypeObject) {
+ state->RegisterError(Error::BINDINGS_DICTIONARY_VALUE_EXPECTED);
+ return false;
+ }
*value = DictionaryValue::cast(std::move(res));
return true;
}
diff --git a/deps/v8/third_party/inspector_protocol/lib/base_string_adapter_cc.template b/deps/v8/third_party/inspector_protocol/lib/base_string_adapter_cc.template
index e503f5c23e..10488f2243 100644
--- a/deps/v8/third_party/inspector_protocol/lib/base_string_adapter_cc.template
+++ b/deps/v8/third_party/inspector_protocol/lib/base_string_adapter_cc.template
@@ -11,7 +11,6 @@
#include "base/base64.h"
#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
-#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
@@ -141,7 +140,7 @@ std::unique_ptr<base::Value> toBaseValue(Value* value, int depth) {
// static
String StringUtil::fromUTF16LE(const uint16_t* data, size_t length) {
std::string utf8;
- base::UTF16ToUTF8(reinterpret_cast<const base::char16*>(data), length, &utf8);
+ base::UTF16ToUTF8(reinterpret_cast<const char16_t*>(data), length, &utf8);
return utf8;
}
@@ -246,4 +245,4 @@ void ProtocolTypeTraits<Binary>::Serialize(const Binary& value, std::vector<uint
value.AppendSerialized(bytes);
}
-} // namespace {{config.crdtp.namespace}} \ No newline at end of file
+} // namespace {{config.crdtp.namespace}}
diff --git a/deps/v8/third_party/inspector_protocol/pdl.py b/deps/v8/third_party/inspector_protocol/pdl.py
index d7733634e5..9a9fec9898 100644
--- a/deps/v8/third_party/inspector_protocol/pdl.py
+++ b/deps/v8/third_party/inspector_protocol/pdl.py
@@ -27,6 +27,9 @@ def assignType(item, type, is_array=False, map_binary_to_string=False):
type = 'string'
if map_binary_to_string and type == 'binary':
type = 'string'
+ if 'description' in item:
+ item['description'] = (item['description'] +
+ ' (Encoded as a base64 string when passed over JSON)')
if type in primitiveTypes:
item['type'] = type
else:
diff --git a/deps/v8/third_party/jsoncpp/BUILD.gn b/deps/v8/third_party/jsoncpp/BUILD.gn
index 411d2d62e7..6324be019c 100644
--- a/deps/v8/third_party/jsoncpp/BUILD.gn
+++ b/deps/v8/third_party/jsoncpp/BUILD.gn
@@ -21,9 +21,7 @@ source_set("jsoncpp") {
sources = [
"generated/version.h",
"source/include/json/assertions.h",
- "source/include/json/autolink.h",
"source/include/json/config.h",
- "source/include/json/features.h",
"source/include/json/forwards.h",
"source/include/json/json.h",
"source/include/json/reader.h",
diff --git a/deps/v8/third_party/zlib/OWNERS b/deps/v8/third_party/zlib/OWNERS
index 632b3f9f43..0bfa9fb9dd 100644
--- a/deps/v8/third_party/zlib/OWNERS
+++ b/deps/v8/third_party/zlib/OWNERS
@@ -2,4 +2,5 @@ agl@chromium.org
cavalcantii@chromium.org
cblume@chromium.org
mtklein@google.com
+noel@chromium.org
scroggo@google.com
diff --git a/deps/v8/third_party/zlib/google/OWNERS b/deps/v8/third_party/zlib/google/OWNERS
index 868af3cc66..411670ca13 100644
--- a/deps/v8/third_party/zlib/google/OWNERS
+++ b/deps/v8/third_party/zlib/google/OWNERS
@@ -1,3 +1,5 @@
+fdegros@chromium.org
+noel@chromium.org
satorux@chromium.org
# compression_utils*
diff --git a/deps/v8/third_party/zlib/google/zip.cc b/deps/v8/third_party/zlib/google/zip.cc
index 907e5da72e..20cdd57bdf 100644
--- a/deps/v8/third_party/zlib/google/zip.cc
+++ b/deps/v8/third_party/zlib/google/zip.cc
@@ -4,7 +4,7 @@
#include "third_party/zlib/google/zip.h"
-#include <list>
+#include <queue>
#include <string>
#include <vector>
@@ -50,12 +50,12 @@ std::unique_ptr<WriterDelegate> CreateFilePathWriterDelegate(
class DirectFileAccessor : public FileAccessor {
public:
- explicit DirectFileAccessor(base::FilePath src_dir) : src_dir_(src_dir) {}
~DirectFileAccessor() override = default;
std::vector<base::File> OpenFilesForReading(
const std::vector<base::FilePath>& paths) override {
std::vector<base::File> files;
+
for (const auto& path : paths) {
base::File file;
if (base::PathExists(path) && !base::DirectoryExists(path)) {
@@ -63,6 +63,7 @@ class DirectFileAccessor : public FileAccessor {
}
files.push_back(std::move(file));
}
+
return files;
}
@@ -73,103 +74,91 @@ class DirectFileAccessor : public FileAccessor {
std::vector<DirectoryContentEntry> ListDirectoryContent(
const base::FilePath& dir) override {
std::vector<DirectoryContentEntry> files;
+
base::FileEnumerator file_enumerator(
dir, false /* recursive */,
base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
- for (base::FilePath path = file_enumerator.Next(); !path.value().empty();
+ for (base::FilePath path = file_enumerator.Next(); !path.empty();
path = file_enumerator.Next()) {
- files.push_back(DirectoryContentEntry(path, base::DirectoryExists(path)));
+ const bool is_directory = base::DirectoryExists(path);
+ files.push_back({std::move(path), is_directory});
}
+
return files;
}
base::Time GetLastModifiedTime(const base::FilePath& path) override {
base::File::Info file_info;
if (!base::GetFileInfo(path, &file_info)) {
- LOG(ERROR) << "Failed to retrieve file modification time for "
- << path.value();
+ LOG(ERROR) << "Cannot get modification time for '" << path << "'";
}
return file_info.last_modified;
}
-
- private:
- base::FilePath src_dir_;
-
- DISALLOW_COPY_AND_ASSIGN(DirectFileAccessor);
};
} // namespace
-ZipParams::ZipParams(const base::FilePath& src_dir,
- const base::FilePath& dest_file)
- : src_dir_(src_dir),
- dest_file_(dest_file),
- file_accessor_(new DirectFileAccessor(src_dir)) {}
-
-#if defined(OS_POSIX)
-// Does not take ownership of |fd|.
-ZipParams::ZipParams(const base::FilePath& src_dir, int dest_fd)
- : src_dir_(src_dir),
- dest_fd_(dest_fd),
- file_accessor_(new DirectFileAccessor(src_dir)) {}
-#endif
+std::ostream& operator<<(std::ostream& out, const Progress& progress) {
+ return out << progress.bytes << " bytes, " << progress.files << " files, "
+ << progress.directories << " dirs";
+}
bool Zip(const ZipParams& params) {
- // Using a pointer to avoid copies of a potentially large array.
- const std::vector<base::FilePath>* files_to_add = &params.files_to_zip();
- std::vector<base::FilePath> all_files;
- if (files_to_add->empty()) {
- // Include all files from the src_dir (modulo the src_dir itself and
- // filtered and hidden files).
-
- files_to_add = &all_files;
- // Using a list so we can call push_back while iterating.
- std::list<FileAccessor::DirectoryContentEntry> entries;
- entries.push_back(FileAccessor::DirectoryContentEntry(
- params.src_dir(), true /* is directory*/));
- const FilterCallback& filter_callback = params.filter_callback();
- for (auto iter = entries.begin(); iter != entries.end(); ++iter) {
- const base::FilePath& entry_path = iter->path;
- if (iter != entries.begin() && // Don't filter the root dir.
- ((!params.include_hidden_files() && IsHiddenFile(entry_path)) ||
- (filter_callback && !filter_callback.Run(entry_path)))) {
- continue;
- }
+ DirectFileAccessor default_accessor;
+ FileAccessor* const file_accessor = params.file_accessor ?: &default_accessor;
+
+ Paths files_to_add = params.src_files;
- if (iter != entries.begin()) { // Exclude the root dir from the ZIP file.
- // Make the path relative for AddEntryToZip.
- base::FilePath relative_path;
- bool success =
- params.src_dir().AppendRelativePath(entry_path, &relative_path);
+ std::vector<base::FilePath> all_files;
+ if (files_to_add.empty()) {
+ // Perform a Breadth First Search (BFS) of the source tree. Note that the
+ // BFS order might not be optimal when storing files in a ZIP (either for
+ // the storing side, or for the program that will extract this ZIP).
+ for (std::queue<base::FilePath> q({params.src_dir}); !q.empty(); q.pop()) {
+ for (FileAccessor::DirectoryContentEntry& entry :
+ file_accessor->ListDirectoryContent(q.front())) {
+ // Skip hidden and filtered files.
+ if ((!params.include_hidden_files && IsHiddenFile(entry.path)) ||
+ (params.filter_callback && !params.filter_callback.Run(entry.path)))
+ continue;
+
+ // Store relative path.
+ all_files.emplace_back();
+ const bool success =
+ params.src_dir.AppendRelativePath(entry.path, &all_files.back());
DCHECK(success);
- all_files.push_back(relative_path);
- }
- if (iter->is_directory) {
- std::vector<FileAccessor::DirectoryContentEntry> subentries =
- params.file_accessor()->ListDirectoryContent(entry_path);
- entries.insert(entries.end(), subentries.begin(), subentries.end());
+ if (entry.is_directory)
+ q.push(std::move(entry.path));
}
}
+
+ files_to_add = all_files;
}
std::unique_ptr<internal::ZipWriter> zip_writer;
+
#if defined(OS_POSIX)
- if (params.dest_fd() != base::kInvalidPlatformFile) {
- DCHECK(params.dest_file().empty());
+ if (params.dest_fd != base::kInvalidPlatformFile) {
+ DCHECK(params.dest_file.empty());
zip_writer = internal::ZipWriter::CreateWithFd(
- params.dest_fd(), params.src_dir(), params.file_accessor());
+ params.dest_fd, params.src_dir, file_accessor);
if (!zip_writer)
return false;
}
#endif
+
if (!zip_writer) {
- zip_writer = internal::ZipWriter::Create(
- params.dest_file(), params.src_dir(), params.file_accessor());
+ zip_writer = internal::ZipWriter::Create(params.dest_file, params.src_dir,
+ file_accessor);
if (!zip_writer)
return false;
}
- return zip_writer->WriteEntries(*files_to_add);
+
+ zip_writer->SetProgressCallback(params.progress_callback,
+ params.progress_period);
+
+ return zip_writer->WriteEntries(files_to_add);
}
bool Unzip(const base::FilePath& src_file, const base::FilePath& dest_dir) {
@@ -179,7 +168,7 @@ bool Unzip(const base::FilePath& src_file, const base::FilePath& dest_dir) {
bool UnzipWithFilterCallback(const base::FilePath& src_file,
const base::FilePath& dest_dir,
- const FilterCallback& filter_cb,
+ FilterCallback filter_cb,
bool log_skipped_files) {
base::File file(src_file, base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!file.IsValid()) {
@@ -189,14 +178,14 @@ bool UnzipWithFilterCallback(const base::FilePath& src_file,
return UnzipWithFilterAndWriters(
file.GetPlatformFile(),
base::BindRepeating(&CreateFilePathWriterDelegate, dest_dir),
- base::BindRepeating(&CreateDirectory, dest_dir), filter_cb,
+ base::BindRepeating(&CreateDirectory, dest_dir), std::move(filter_cb),
log_skipped_files);
}
bool UnzipWithFilterAndWriters(const base::PlatformFile& src_file,
- const WriterFactory& writer_factory,
- const DirectoryCreator& directory_creator,
- const FilterCallback& filter_cb,
+ WriterFactory writer_factory,
+ DirectoryCreator directory_creator,
+ FilterCallback filter_cb,
bool log_skipped_files) {
ZipReader reader;
if (!reader.OpenFromPlatformFile(src_file)) {
@@ -239,14 +228,15 @@ bool UnzipWithFilterAndWriters(const base::PlatformFile& src_file,
bool ZipWithFilterCallback(const base::FilePath& src_dir,
const base::FilePath& dest_file,
- const FilterCallback& filter_cb) {
+ FilterCallback filter_cb) {
DCHECK(base::DirectoryExists(src_dir));
- ZipParams params(src_dir, dest_file);
- params.set_filter_callback(filter_cb);
- return Zip(params);
+ return Zip({.src_dir = src_dir,
+ .dest_file = dest_file,
+ .filter_callback = std::move(filter_cb)});
}
-bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file,
+bool Zip(const base::FilePath& src_dir,
+ const base::FilePath& dest_file,
bool include_hidden_files) {
if (include_hidden_files) {
return ZipWithFilterCallback(src_dir, dest_file,
@@ -259,12 +249,12 @@ bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file,
#if defined(OS_POSIX)
bool ZipFiles(const base::FilePath& src_dir,
- const std::vector<base::FilePath>& src_relative_paths,
+ Paths src_relative_paths,
int dest_fd) {
DCHECK(base::DirectoryExists(src_dir));
- ZipParams params(src_dir, dest_fd);
- params.set_files_to_zip(src_relative_paths);
- return Zip(params);
+ return Zip({.src_dir = src_dir,
+ .dest_fd = dest_fd,
+ .src_files = src_relative_paths});
}
#endif // defined(OS_POSIX)
diff --git a/deps/v8/third_party/zlib/google/zip.h b/deps/v8/third_party/zlib/google/zip.h
index 4f64a8aca8..ecd7ba02b4 100644
--- a/deps/v8/third_party/zlib/google/zip.h
+++ b/deps/v8/third_party/zlib/google/zip.h
@@ -5,9 +5,13 @@
#ifndef THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_
#define THIRD_PARTY_ZLIB_GOOGLE_ZIP_H_
+#include <cstdint>
+#include <ostream>
+#include <utility>
#include <vector>
#include "base/callback.h"
+#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/files/platform_file.h"
#include "base/time/time.h"
@@ -31,8 +35,6 @@ class FileAccessor {
virtual ~FileAccessor() = default;
struct DirectoryContentEntry {
- DirectoryContentEntry(const base::FilePath& path, bool is_directory)
- : path(path), is_directory(is_directory) {}
base::FilePath path;
bool is_directory = false;
};
@@ -48,72 +50,75 @@ class FileAccessor {
virtual base::Time GetLastModifiedTime(const base::FilePath& path) = 0;
};
-class ZipParams {
- public:
- ZipParams(const base::FilePath& src_dir, const base::FilePath& dest_file);
-#if defined(OS_POSIX)
- // Does not take ownership of |dest_fd|.
- ZipParams(const base::FilePath& src_dir, int dest_fd);
+// Progress of a ZIP creation operation.
+struct Progress {
+ // Total number of bytes read from files getting zipped so far.
+ std::int64_t bytes = 0;
- int dest_fd() const { return dest_fd_; }
-#endif
+ // Number of file entries added to the ZIP so far.
+ // A file entry is added after its bytes have been processed.
+ int files = 0;
+
+ // Number of directory entries added to the ZIP so far.
+ // A directory entry is added before items in it.
+ int directories = 0;
+};
+
+// Prints Progress to output stream.
+std::ostream& operator<<(std::ostream& out, const Progress& progress);
+
+// Callback reporting the progress of a ZIP creation operation.
+//
+// This callback returns a boolean indicating whether the ZIP creation operation
+// should continue. If it returns false once, then the ZIP creation operation is
+// immediately cancelled and the callback won't be called again.
+using ProgressCallback = base::RepeatingCallback<bool(const Progress&)>;
+
+using FilterCallback = base::RepeatingCallback<bool(const base::FilePath&)>;
+
+using Paths = base::span<const base::FilePath>;
+
+// ZIP creation parameters and options.
+struct ZipParams {
+ // Source directory.
+ base::FilePath src_dir;
+
+ // Destination file path.
+ // Either dest_file or dest_fd should be set, but not both.
+ base::FilePath dest_file;
- const base::FilePath& src_dir() const { return src_dir_; }
-
- const base::FilePath& dest_file() const { return dest_file_; }
-
- // Restricts the files actually zipped to the paths listed in
- // |src_relative_paths|. They must be relative to the |src_dir| passed in the
- // constructor and will be used as the file names in the created zip file. All
- // source paths must be under |src_dir| in the file system hierarchy.
- void set_files_to_zip(const std::vector<base::FilePath>& src_relative_paths) {
- src_files_ = src_relative_paths;
- }
- const std::vector<base::FilePath>& files_to_zip() const { return src_files_; }
-
- using FilterCallback = base::RepeatingCallback<bool(const base::FilePath&)>;
- void set_filter_callback(FilterCallback filter_callback) {
- filter_callback_ = filter_callback;
- }
- const FilterCallback& filter_callback() const { return filter_callback_; }
-
- void set_include_hidden_files(bool include_hidden_files) {
- include_hidden_files_ = include_hidden_files;
- }
- bool include_hidden_files() const { return include_hidden_files_; }
-
- // Sets a custom file accessor for file operations. Default is to directly
- // access the files (with fopen and the rest).
- // Useful in cases where running in a sandbox process and file access has to
- // go through IPC, for example.
- void set_file_accessor(std::unique_ptr<FileAccessor> file_accessor) {
- file_accessor_ = std::move(file_accessor);
- }
- FileAccessor* file_accessor() const { return file_accessor_.get(); }
-
- private:
- base::FilePath src_dir_;
-
- base::FilePath dest_file_;
#if defined(OS_POSIX)
- int dest_fd_ = base::kInvalidPlatformFile;
+ // Destination file passed a file descriptor.
+ // Either dest_file or dest_fd should be set, but not both.
+ int dest_fd = base::kInvalidPlatformFile;
#endif
- // The relative paths to the files that should be included in the zip file. If
- // this is empty, all files in |src_dir_| are included.
- std::vector<base::FilePath> src_files_;
+ // The relative paths to the files that should be included in the ZIP file. If
+ // this is empty, all files in |src_dir| are included.
+ //
+ // These paths must be relative to |src_dir| and will be used as the file
+ // names in the created zip file. All files must be under |src_dir| in the
+ // file system hierarchy.
+ Paths src_files;
// Filter used to exclude files from the ZIP file. Only effective when
- // |src_files_| is empty.
- FilterCallback filter_callback_;
+ // |src_files| is empty.
+ FilterCallback filter_callback;
+
+ // Optional progress reporting callback.
+ ProgressCallback progress_callback;
+
+ // Progress reporting period. The final callback is always called when the ZIP
+ // creation operation completes.
+ base::TimeDelta progress_period;
// Whether hidden files should be included in the ZIP file. Only effective
- // when |src_files_| is empty.
- bool include_hidden_files_ = true;
+ // when |src_files| is empty.
+ bool include_hidden_files = true;
- // Abstraction around file system access used to read files. An implementation
- // that accesses files directly is provided by default.
- std::unique_ptr<FileAccessor> file_accessor_;
+ // Abstraction around file system access used to read files. If left null, an
+ // implementation that accesses files directly is used.
+ FileAccessor* file_accessor = nullptr; // Not owned
};
// Zip files specified into a ZIP archives. The source files and ZIP destination
@@ -125,15 +130,15 @@ bool Zip(const ZipParams& params);
// of src_dir will be at the root level of the created zip. For each file in
// src_dir, include it only if the callback |filter_cb| returns true. Otherwise
// omit it.
-using FilterCallback = base::RepeatingCallback<bool(const base::FilePath&)>;
bool ZipWithFilterCallback(const base::FilePath& src_dir,
const base::FilePath& dest_file,
- const FilterCallback& filter_cb);
+ FilterCallback filter_cb);
// Convenience method for callers who don't need to set up the filter callback.
// If |include_hidden_files| is true, files starting with "." are included.
// Otherwise they are omitted.
-bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file,
+bool Zip(const base::FilePath& src_dir,
+ const base::FilePath& dest_file,
bool include_hidden_files);
#if defined(OS_POSIX)
@@ -143,7 +148,7 @@ bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file,
// file names in the created zip file. All source paths must be under |src_dir|
// in the file system hierarchy.
bool ZipFiles(const base::FilePath& src_dir,
- const std::vector<base::FilePath>& src_relative_paths,
+ Paths src_relative_paths,
int dest_fd);
#endif // defined(OS_POSIX)
@@ -152,10 +157,9 @@ bool ZipFiles(const base::FilePath& src_dir,
// returns true. Otherwise omit it.
// If |log_skipped_files| is true, files skipped during extraction are printed
// to debug log.
-using FilterCallback = base::RepeatingCallback<bool(const base::FilePath&)>;
bool UnzipWithFilterCallback(const base::FilePath& zip_file,
const base::FilePath& dest_dir,
- const FilterCallback& filter_cb,
+ FilterCallback filter_cb,
bool log_skipped_files);
// Unzip the contents of zip_file, using the writers provided by writer_factory.
@@ -168,9 +172,9 @@ typedef base::RepeatingCallback<std::unique_ptr<WriterDelegate>(
WriterFactory;
typedef base::RepeatingCallback<bool(const base::FilePath&)> DirectoryCreator;
bool UnzipWithFilterAndWriters(const base::PlatformFile& zip_file,
- const WriterFactory& writer_factory,
- const DirectoryCreator& directory_creator,
- const FilterCallback& filter_cb,
+ WriterFactory writer_factory,
+ DirectoryCreator directory_creator,
+ FilterCallback filter_cb,
bool log_skipped_files);
// Unzip the contents of zip_file into dest_dir.
diff --git a/deps/v8/third_party/zlib/google/zip_reader_unittest.cc b/deps/v8/third_party/zlib/google/zip_reader_unittest.cc
index bba4365298..44134f886e 100644
--- a/deps/v8/third_party/zlib/google/zip_reader_unittest.cc
+++ b/deps/v8/third_party/zlib/google/zip_reader_unittest.cc
@@ -20,6 +20,7 @@
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
+#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/task_environment.h"
@@ -510,12 +511,12 @@ TEST_F(ZipReaderTest, ExtractCurrentEntryToString) {
if (i > 0) {
// Exact byte read limit: must pass.
EXPECT_TRUE(reader.ExtractCurrentEntryToString(i, &contents));
- EXPECT_EQ(base::StringPiece("0123456", i).as_string(), contents);
+ EXPECT_EQ(std::string(base::StringPiece("0123456", i)), contents);
}
// More than necessary byte read limit: must pass.
EXPECT_TRUE(reader.ExtractCurrentEntryToString(16, &contents));
- EXPECT_EQ(base::StringPiece("0123456", i).as_string(), contents);
+ EXPECT_EQ(std::string(base::StringPiece("0123456", i)), contents);
}
reader.Close();
}
diff --git a/deps/v8/third_party/zlib/google/zip_unittest.cc b/deps/v8/third_party/zlib/google/zip_unittest.cc
index 10f2ef7a97..cf914d9f06 100644
--- a/deps/v8/third_party/zlib/google/zip_unittest.cc
+++ b/deps/v8/third_party/zlib/google/zip_unittest.cc
@@ -21,6 +21,7 @@
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/test/bind.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -78,13 +79,10 @@ class VirtualFileSystem : public zip::FileAccessor {
DCHECK(success);
files_[bar2_txt_path] = std::move(file);
- file_tree_[test_dir] = std::vector<DirectoryContentEntry>{
- DirectoryContentEntry(foo_txt_path, /*is_dir=*/false),
- DirectoryContentEntry(bar_dir, /*is_dir=*/true)};
- file_tree_[bar_dir] = std::vector<DirectoryContentEntry>{
- DirectoryContentEntry(bar1_txt_path, /*is_dir=*/false),
- DirectoryContentEntry(bar2_txt_path, /*is_dir=*/false)};
+ file_tree_[test_dir] = {{foo_txt_path, false}, {bar_dir, true}};
+ file_tree_[bar_dir] = {{bar1_txt_path, false}, {bar2_txt_path, false}};
}
+
~VirtualFileSystem() override = default;
private:
@@ -108,7 +106,7 @@ class VirtualFileSystem : public zip::FileAccessor {
auto iter = file_tree_.find(dir);
if (iter == file_tree_.end()) {
NOTREACHED();
- return std::vector<DirectoryContentEntry>();
+ return {};
}
return iter->second;
}
@@ -131,10 +129,7 @@ constexpr char VirtualFileSystem::kBar2Content[];
// Make the test a PlatformTest to setup autorelease pools properly on Mac.
class ZipTest : public PlatformTest {
protected:
- enum ValidYearType {
- VALID_YEAR,
- INVALID_YEAR
- };
+ enum ValidYearType { VALID_YEAR, INVALID_YEAR };
virtual void SetUp() {
PlatformTest::SetUp();
@@ -161,20 +156,17 @@ class ZipTest : public PlatformTest {
base::FilePath(FILE_PATH_LITERAL("foo/bar/.hidden")));
}
- virtual void TearDown() {
- PlatformTest::TearDown();
- }
+ virtual void TearDown() { PlatformTest::TearDown(); }
bool GetTestDataDirectory(base::FilePath* path) {
bool success = base::PathService::Get(base::DIR_SOURCE_ROOT, path);
EXPECT_TRUE(success);
if (!success)
return false;
- *path = path->AppendASCII("third_party");
- *path = path->AppendASCII("zlib");
- *path = path->AppendASCII("google");
- *path = path->AppendASCII("test");
- *path = path->AppendASCII("data");
+ for (const base::StringPiece s :
+ {"third_party", "zlib", "google", "test", "data"}) {
+ *path = path->AppendASCII(s);
+ }
return true;
}
@@ -193,7 +185,8 @@ class ZipTest : public PlatformTest {
ASSERT_TRUE(GetTestDataDirectory(&original_dir));
original_dir = original_dir.AppendASCII("test");
- base::FileEnumerator files(test_dir_, true,
+ base::FileEnumerator files(
+ test_dir_, true,
base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
base::FilePath unzipped_entry_path = files.Next();
size_t count = 0;
@@ -211,15 +204,19 @@ class ZipTest : public PlatformTest {
bool append_relative_path_success =
test_dir_.AppendRelativePath(unzipped_entry_path, &relative_path);
if (!append_relative_path_success) {
- LOG(ERROR) << "Append relative path failed, params: "
- << test_dir_.value() << " and "
- << unzipped_entry_path.value();
+ LOG(ERROR) << "Append relative path failed, params: " << test_dir_
+ << " and " << unzipped_entry_path;
}
base::FilePath original_path = original_dir.Append(relative_path);
- LOG(ERROR) << "Comparing original " << original_path.value()
- << " and unzipped file " << unzipped_entry_path.value()
- << " result: "
- << base::ContentsEqual(original_path, unzipped_entry_path);
+ const bool equal =
+ base::ContentsEqual(original_path, unzipped_entry_path);
+ if (equal) {
+ LOG(INFO) << "Original and unzipped file '" << relative_path
+ << "' are equal";
+ } else {
+ LOG(ERROR) << "Original and unzipped file '" << relative_path
+ << "' are different";
+ }
// EXPECT_TRUE(base::ContentsEqual(original_path, unzipped_entry_path))
// << "Contents differ between original " << original_path.value()
// << " and unzipped file " << unzipped_entry_path.value();
@@ -487,8 +484,8 @@ TEST_F(ZipTest, ZipFiles) {
base::File zip_file(zip_name,
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(zip_file.IsValid());
- EXPECT_TRUE(zip::ZipFiles(src_dir, zip_file_list_,
- zip_file.GetPlatformFile()));
+ EXPECT_TRUE(
+ zip::ZipFiles(src_dir, zip_file_list_, zip_file.GetPlatformFile()));
zip_file.Close();
zip::ZipReader reader;
@@ -524,8 +521,8 @@ TEST_F(ZipTest, UnzipFilesWithIncorrectSize) {
for (int i = 0; i < 8; i++) {
SCOPED_TRACE(base::StringPrintf("Processing %d.txt", i));
- base::FilePath file_path = temp_dir.AppendASCII(
- base::StringPrintf("%d.txt", i));
+ base::FilePath file_path =
+ temp_dir.AppendASCII(base::StringPrintf("%d.txt", i));
int64_t file_size = -1;
EXPECT_TRUE(base::GetFileSize(file_path, &file_size));
EXPECT_EQ(static_cast<int64_t>(i), file_size);
@@ -535,8 +532,11 @@ TEST_F(ZipTest, UnzipFilesWithIncorrectSize) {
TEST_F(ZipTest, ZipWithFileAccessor) {
base::FilePath zip_file;
ASSERT_TRUE(base::CreateTemporaryFile(&zip_file));
- zip::ZipParams params(base::FilePath(FILE_PATH_LITERAL("/test")), zip_file);
- params.set_file_accessor(std::make_unique<VirtualFileSystem>());
+ VirtualFileSystem file_accessor;
+ const zip::ZipParams params{
+ .src_dir = base::FilePath(FILE_PATH_LITERAL("/test")),
+ .dest_file = zip_file,
+ .file_accessor = &file_accessor};
ASSERT_TRUE(zip::Zip(params));
base::ScopedTempDir scoped_temp_dir;
@@ -557,4 +557,125 @@ TEST_F(ZipTest, ZipWithFileAccessor) {
EXPECT_EQ(VirtualFileSystem::kBar2Content, file_content);
}
+// Tests progress reporting while zipping files.
+TEST_F(ZipTest, ZipProgress) {
+ base::FilePath src_dir;
+ ASSERT_TRUE(GetTestDataDirectory(&src_dir));
+ src_dir = src_dir.AppendASCII("test");
+
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
+
+ int progress_count = 0;
+ zip::Progress last_progress;
+
+ zip::ProgressCallback progress_callback =
+ base::BindLambdaForTesting([&](const zip::Progress& progress) {
+ progress_count++;
+ LOG(INFO) << "Progress #" << progress_count << ": " << progress;
+
+ // Progress should only go forwards.
+ EXPECT_GE(progress.bytes, last_progress.bytes);
+ EXPECT_GE(progress.files, last_progress.files);
+ EXPECT_GE(progress.directories, last_progress.directories);
+
+ last_progress = progress;
+ return true;
+ });
+
+ EXPECT_TRUE(zip::Zip({.src_dir = src_dir,
+ .dest_file = zip_file,
+ .progress_callback = std::move(progress_callback)}));
+
+ EXPECT_EQ(progress_count, 14);
+ EXPECT_EQ(last_progress.bytes, 13546);
+ EXPECT_EQ(last_progress.files, 5);
+ EXPECT_EQ(last_progress.directories, 2);
+
+ TestUnzipFile(zip_file, true);
+}
+
+// Tests throttling of progress reporting while zipping files.
+TEST_F(ZipTest, ZipProgressPeriod) {
+ base::FilePath src_dir;
+ ASSERT_TRUE(GetTestDataDirectory(&src_dir));
+ src_dir = src_dir.AppendASCII("test");
+
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
+
+ int progress_count = 0;
+ zip::Progress last_progress;
+
+ zip::ProgressCallback progress_callback =
+ base::BindLambdaForTesting([&](const zip::Progress& progress) {
+ progress_count++;
+ LOG(INFO) << "Progress #" << progress_count << ": " << progress;
+
+ // Progress should only go forwards.
+ EXPECT_GE(progress.bytes, last_progress.bytes);
+ EXPECT_GE(progress.files, last_progress.files);
+ EXPECT_GE(progress.directories, last_progress.directories);
+
+ last_progress = progress;
+ return true;
+ });
+
+ EXPECT_TRUE(zip::Zip({.src_dir = src_dir,
+ .dest_file = zip_file,
+ .progress_callback = std::move(progress_callback),
+ .progress_period = base::TimeDelta::FromHours(1)}));
+
+ // We expect only 2 progress reports: the first one, and the last one.
+ EXPECT_EQ(progress_count, 2);
+ EXPECT_EQ(last_progress.bytes, 13546);
+ EXPECT_EQ(last_progress.files, 5);
+ EXPECT_EQ(last_progress.directories, 2);
+
+ TestUnzipFile(zip_file, true);
+}
+
+// Tests cancellation while zipping files.
+TEST_F(ZipTest, ZipCancel) {
+ base::FilePath src_dir;
+ ASSERT_TRUE(GetTestDataDirectory(&src_dir));
+ src_dir = src_dir.AppendASCII("test");
+
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath zip_file = temp_dir.GetPath().AppendASCII("out.zip");
+
+ // First: establish the number of possible interruption points.
+ int progress_count = 0;
+
+ EXPECT_TRUE(zip::Zip({.src_dir = src_dir,
+ .dest_file = zip_file,
+ .progress_callback = base::BindLambdaForTesting(
+ [&progress_count](const zip::Progress&) {
+ progress_count++;
+ return true;
+ })}));
+
+ EXPECT_EQ(progress_count, 14);
+
+ // Second: exercise each and every interruption point.
+ for (int i = progress_count; i > 0; i--) {
+ int j = 0;
+ EXPECT_FALSE(zip::Zip({.src_dir = src_dir,
+ .dest_file = zip_file,
+ .progress_callback = base::BindLambdaForTesting(
+ [i, &j](const zip::Progress&) {
+ j++;
+ // Callback shouldn't be called again after
+ // having returned false once.
+ EXPECT_LE(j, i);
+ return j < i;
+ })}));
+
+ EXPECT_EQ(j, i);
+ }
+}
+
} // namespace
diff --git a/deps/v8/third_party/zlib/google/zip_writer.cc b/deps/v8/third_party/zlib/google/zip_writer.cc
index 6f38d42b6b..de1930e803 100644
--- a/deps/v8/third_party/zlib/google/zip_writer.cc
+++ b/deps/v8/third_party/zlib/google/zip_writer.cc
@@ -12,35 +12,51 @@
namespace zip {
namespace internal {
-namespace {
+bool ZipWriter::ShouldContinue() {
+ if (!progress_callback_)
+ return true;
-// Numbers of pending entries that trigger writting them to the ZIP file.
-constexpr size_t kMaxPendingEntriesCount = 50;
+ const base::TimeTicks now = base::TimeTicks::Now();
+ if (next_progress_report_time_ > now)
+ return true;
-bool AddFileContentToZip(zipFile zip_file,
- base::File file,
- const base::FilePath& file_path) {
- int num_bytes;
+ next_progress_report_time_ = now + progress_period_;
+ if (progress_callback_.Run(progress_))
+ return true;
+
+ LOG(ERROR) << "Cancelling ZIP creation";
+ return false;
+}
+
+bool ZipWriter::AddFileContent(const base::FilePath& path, base::File file) {
char buf[zip::internal::kZipBufSize];
- do {
- num_bytes = file.ReadAtCurrentPos(buf, zip::internal::kZipBufSize);
-
- if (num_bytes > 0) {
- if (zipWriteInFileInZip(zip_file, buf, num_bytes) != ZIP_OK) {
- DLOG(ERROR) << "Could not write data to zip for path "
- << file_path.value();
- return false;
- }
+
+ while (ShouldContinue()) {
+ const int num_bytes =
+ file.ReadAtCurrentPos(buf, zip::internal::kZipBufSize);
+
+ if (num_bytes < 0) {
+ DPLOG(ERROR) << "Cannot read file '" << path << "'";
+ return false;
}
- } while (num_bytes > 0);
- return true;
+ if (num_bytes == 0)
+ return true;
+
+ if (zipWriteInFileInZip(zip_file_, buf, num_bytes) != ZIP_OK) {
+ DLOG(ERROR) << "Cannot write data from file '" << path << "' to ZIP";
+ return false;
+ }
+
+ progress_.bytes += num_bytes;
+ }
+
+ return false;
}
-bool OpenNewFileEntry(zipFile zip_file,
- const base::FilePath& path,
- bool is_directory,
- base::Time last_modified) {
+bool ZipWriter::OpenNewFileEntry(const base::FilePath& path,
+ bool is_directory,
+ base::Time last_modified) {
std::string str_path = path.AsUTF8Unsafe();
#if defined(OS_WIN)
base::ReplaceSubstringsAfterOffset(&str_path, 0u, "\\", "/");
@@ -48,41 +64,33 @@ bool OpenNewFileEntry(zipFile zip_file,
if (is_directory)
str_path += "/";
- return zip::internal::ZipOpenNewFileInZip(zip_file, str_path, last_modified);
+ return zip::internal::ZipOpenNewFileInZip(zip_file_, str_path, last_modified);
}
-bool CloseNewFileEntry(zipFile zip_file) {
- return zipCloseFileInZip(zip_file) == ZIP_OK;
+bool ZipWriter::CloseNewFileEntry() {
+ return zipCloseFileInZip(zip_file_) == ZIP_OK;
}
-bool AddFileEntryToZip(zipFile zip_file,
- const base::FilePath& path,
- base::File file) {
+bool ZipWriter::AddFileEntry(const base::FilePath& path, base::File file) {
base::File::Info file_info;
if (!file.GetInfo(&file_info))
return false;
- if (!OpenNewFileEntry(zip_file, path, /*is_directory=*/false,
- file_info.last_modified))
- return false;
-
- bool success = AddFileContentToZip(zip_file, std::move(file), path);
- if (!CloseNewFileEntry(zip_file))
+ if (!OpenNewFileEntry(path, /*is_directory=*/false, file_info.last_modified))
return false;
- return success;
+ const bool success = AddFileContent(path, std::move(file));
+ progress_.files++;
+ return CloseNewFileEntry() && success;
}
-bool AddDirectoryEntryToZip(zipFile zip_file,
- const base::FilePath& path,
- base::Time last_modified) {
- return OpenNewFileEntry(zip_file, path, /*is_directory=*/true,
- last_modified) &&
- CloseNewFileEntry(zip_file);
+bool ZipWriter::AddDirectoryEntry(const base::FilePath& path,
+ base::Time last_modified) {
+ progress_.directories++;
+ return OpenNewFileEntry(path, /*is_directory=*/true, last_modified) &&
+ CloseNewFileEntry() && ShouldContinue();
}
-} // namespace
-
#if defined(OS_POSIX)
// static
std::unique_ptr<ZipWriter> ZipWriter::CreateWithFd(
@@ -92,10 +100,12 @@ std::unique_ptr<ZipWriter> ZipWriter::CreateWithFd(
DCHECK(zip_file_fd != base::kInvalidPlatformFile);
zipFile zip_file =
internal::OpenFdForZipping(zip_file_fd, APPEND_STATUS_CREATE);
+
if (!zip_file) {
- DLOG(ERROR) << "Couldn't create ZIP file for FD " << zip_file_fd;
+ DLOG(ERROR) << "Cannot create ZIP file for FD " << zip_file_fd;
return nullptr;
}
+
return std::unique_ptr<ZipWriter>(
new ZipWriter(zip_file, root_dir, file_accessor));
}
@@ -109,10 +119,12 @@ std::unique_ptr<ZipWriter> ZipWriter::Create(
DCHECK(!zip_file_path.empty());
zipFile zip_file = internal::OpenForZipping(zip_file_path.AsUTF8Unsafe(),
APPEND_STATUS_CREATE);
+
if (!zip_file) {
- DLOG(ERROR) << "Couldn't create ZIP file at path " << zip_file_path;
+ DLOG(ERROR) << "Cannot create ZIP file '" << zip_file_path << "'";
return nullptr;
}
+
return std::unique_ptr<ZipWriter>(
new ZipWriter(zip_file, root_dir, file_accessor));
}
@@ -123,80 +135,83 @@ ZipWriter::ZipWriter(zipFile zip_file,
: zip_file_(zip_file), root_dir_(root_dir), file_accessor_(file_accessor) {}
ZipWriter::~ZipWriter() {
- DCHECK(pending_entries_.empty());
+ if (zip_file_)
+ zipClose(zip_file_, nullptr);
}
-bool ZipWriter::WriteEntries(const std::vector<base::FilePath>& paths) {
+bool ZipWriter::WriteEntries(Paths paths) {
return AddEntries(paths) && Close();
}
-bool ZipWriter::AddEntries(const std::vector<base::FilePath>& paths) {
- DCHECK(zip_file_);
- pending_entries_.insert(pending_entries_.end(), paths.begin(), paths.end());
- return FlushEntriesIfNeeded(/*force=*/false);
-}
-
bool ZipWriter::Close() {
- bool success = FlushEntriesIfNeeded(/*force=*/true) &&
- zipClose(zip_file_, nullptr) == ZIP_OK;
+ const bool success = zipClose(zip_file_, nullptr) == ZIP_OK;
zip_file_ = nullptr;
+
+ // Call the progress callback one last time with the final progress status.
+ if (progress_callback_ && !progress_callback_.Run(progress_)) {
+ LOG(ERROR) << "Cancelling ZIP creation at the end";
+ return false;
+ }
+
return success;
}
-bool ZipWriter::FlushEntriesIfNeeded(bool force) {
- if (pending_entries_.size() < kMaxPendingEntriesCount && !force)
- return true;
-
- while (pending_entries_.size() >= kMaxPendingEntriesCount ||
- (force && !pending_entries_.empty())) {
- size_t entry_count =
- std::min(pending_entries_.size(), kMaxPendingEntriesCount);
- std::vector<base::FilePath> relative_paths;
- std::vector<base::FilePath> absolute_paths;
- relative_paths.insert(relative_paths.begin(), pending_entries_.begin(),
- pending_entries_.begin() + entry_count);
- for (auto iter = pending_entries_.begin();
- iter != pending_entries_.begin() + entry_count; ++iter) {
- // The FileAccessor requires absolute paths.
- absolute_paths.push_back(root_dir_.Append(*iter));
+bool ZipWriter::AddEntries(Paths paths) {
+ // Constructed outside the loop in order to reuse its internal buffer.
+ std::vector<base::FilePath> absolute_paths;
+
+ while (!paths.empty()) {
+ // Work with chunks of 50 paths at most.
+ const size_t n = std::min<size_t>(paths.size(), 50);
+ const Paths relative_paths = paths.subspan(0, n);
+ paths = paths.subspan(n, paths.size() - n);
+
+ // FileAccessor requires absolute paths.
+ absolute_paths.clear();
+ absolute_paths.reserve(n);
+ for (const base::FilePath& relative_path : relative_paths) {
+ absolute_paths.push_back(root_dir_.Append(relative_path));
}
- pending_entries_.erase(pending_entries_.begin(),
- pending_entries_.begin() + entry_count);
+
+ DCHECK_EQ(relative_paths.size(), n);
+ DCHECK_EQ(absolute_paths.size(), n);
// We don't know which paths are files and which ones are directories, and
- // we want to avoid making a call to file_accessor_ for each entry. Open the
- // files instead, invalid files are returned for directories.
+ // we want to avoid making a call to file_accessor_ for each entry. Try to
+ // open all of the paths as files. We'll get invalid file descriptors for
+ // directories.
std::vector<base::File> files =
file_accessor_->OpenFilesForReading(absolute_paths);
- DCHECK_EQ(files.size(), relative_paths.size());
- for (size_t i = 0; i < files.size(); i++) {
+ DCHECK_EQ(files.size(), n);
+
+ for (size_t i = 0; i < n; i++) {
const base::FilePath& relative_path = relative_paths[i];
const base::FilePath& absolute_path = absolute_paths[i];
- base::File file = std::move(files[i]);
+ base::File& file = files[i];
+
if (file.IsValid()) {
- if (!AddFileEntryToZip(zip_file_, relative_path, std::move(file))) {
- LOG(ERROR) << "Failed to write file " << relative_path.value()
- << " to ZIP file.";
+ if (!AddFileEntry(relative_path, std::move(file))) {
+ LOG(ERROR) << "Cannot add file '" << relative_path << "' to ZIP";
return false;
}
} else {
- // Missing file or directory case.
- base::Time last_modified =
+ // Either directory or missing file.
+ const base::Time last_modified =
file_accessor_->GetLastModifiedTime(absolute_path);
if (last_modified.is_null()) {
- LOG(ERROR) << "Failed to write entry " << relative_path.value()
- << " to ZIP file.";
+ LOG(ERROR) << "Missing file or directory '" << relative_path << "'";
return false;
}
+
DCHECK(file_accessor_->DirectoryExists(absolute_path));
- if (!AddDirectoryEntryToZip(zip_file_, relative_path, last_modified)) {
- LOG(ERROR) << "Failed to write directory " << relative_path.value()
- << " to ZIP file.";
+ if (!AddDirectoryEntry(relative_path, last_modified)) {
+ LOG(ERROR) << "Cannot add directory '" << relative_path << "' to ZIP";
return false;
}
}
}
}
+
return true;
}
diff --git a/deps/v8/third_party/zlib/google/zip_writer.h b/deps/v8/third_party/zlib/google/zip_writer.h
index bd2a727b94..489984f843 100644
--- a/deps/v8/third_party/zlib/google/zip_writer.h
+++ b/deps/v8/third_party/zlib/google/zip_writer.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/files/file_path.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "third_party/zlib/google/zip.h"
@@ -31,7 +32,7 @@ namespace internal {
class ZipWriter {
public:
// Creates a writer that will write a ZIP file to |zip_file_fd|/|zip_file|
-// and which entries (specifies with AddEntries) are relative to |root_dir|.
+// and which entries (specified with WriteEntries) are relative to |root_dir|.
// All file reads are performed using |file_accessor|.
#if defined(OS_POSIX)
static std::unique_ptr<ZipWriter> CreateWithFd(int zip_file_fd,
@@ -43,36 +44,56 @@ class ZipWriter {
FileAccessor* file_accessor);
~ZipWriter();
- // Writes the files at |paths| to the ZIP file and closes this Zip file.
- // Note that the the FilePaths must be relative to |root_dir| specified in the
+ // Sets the optional progress callback. The callback is called once for each
+ // time |period|. The final callback is always called when the ZIP operation
+ // completes.
+ void SetProgressCallback(ProgressCallback callback, base::TimeDelta period) {
+ progress_callback_ = std::move(callback);
+ progress_period_ = std::move(period);
+ }
+
+ // Writes the files at |paths| to the ZIP file and closes this ZIP file.
+ // The file paths must be relative to |root_dir| specified in the
// Create method.
// Returns true if all entries were written successfuly.
- bool WriteEntries(const std::vector<base::FilePath>& paths);
+ bool WriteEntries(Paths paths);
private:
+ // Takes ownership of |zip_file|.
ZipWriter(zipFile zip_file,
const base::FilePath& root_dir,
FileAccessor* file_accessor);
- // Writes the pending entries to the ZIP file if there are at least
- // |kMaxPendingEntriesCount| of them. If |force| is true, all pending entries
- // are written regardless of how many there are.
- // Returns false if writing an entry fails, true if no entry was written or
- // there was no error writing entries.
- bool FlushEntriesIfNeeded(bool force);
+ // Regularly called during processing to check whether zipping should continue
+ // or should be cancelled.
+ bool ShouldContinue();
// Adds the files at |paths| to the ZIP file. These FilePaths must be relative
// to |root_dir| specified in the Create method.
- bool AddEntries(const std::vector<base::FilePath>& paths);
+ bool AddEntries(Paths paths);
+
+ // Adds file content to currently open file entry.
+ bool AddFileContent(const base::FilePath& path, base::File file);
+
+ // Adds a file entry (including file contents).
+ bool AddFileEntry(const base::FilePath& path, base::File file);
+
+ // Adds a directory entry.
+ bool AddDirectoryEntry(const base::FilePath& path, base::Time last_modified);
+
+ // Opens a file or directory entry.
+ bool OpenNewFileEntry(const base::FilePath& path,
+ bool is_directory,
+ base::Time last_modified);
+
+ // Closes the currently open entry.
+ bool CloseNewFileEntry();
// Closes the ZIP file.
// Returns true if successful, false otherwise (typically if an entry failed
// to be written).
bool Close();
- // The entries that have been added but not yet written to the ZIP file.
- std::vector<base::FilePath> pending_entries_;
-
// The actual zip file.
zipFile zip_file_;
@@ -82,10 +103,22 @@ class ZipWriter {
// Abstraction over file access methods used to read files.
FileAccessor* file_accessor_;
+ // Progress stats.
+ Progress progress_;
+
+ // Optional progress callback.
+ ProgressCallback progress_callback_;
+
+ // Optional progress reporting period.
+ base::TimeDelta progress_period_;
+
+ // Next time to report progress.
+ base::TimeTicks next_progress_report_time_ = base::TimeTicks::Now();
+
DISALLOW_COPY_AND_ASSIGN(ZipWriter);
};
} // namespace internal
} // namespace zip
-#endif // THIRD_PARTY_ZLIB_GOOGLE_ZIP_WRITER_H_ \ No newline at end of file
+#endif // THIRD_PARTY_ZLIB_GOOGLE_ZIP_WRITER_H_