Merge changes from topics "norootintegrationtest", "profileshelltestdatafile"
* changes:
Assert correct callsite name using TP.
Run perfetto_integrationtests from /data/local/tests.
Do not require root for integrationtest.
diff --git a/docs/analysis/metrics.md b/docs/analysis/metrics.md
index 32d52e9..2286bd1 100644
--- a/docs/analysis/metrics.md
+++ b/docs/analysis/metrics.md
@@ -100,7 +100,7 @@
the walkthrough. The prerequisites and Step 4 below give instructions on
how to get trace processor and run the metrics code.
-[gist]: https://gist.github.com/tilal6991/c221cf0cae17e298dfa82b118edf9080
+[gist]: https://gist.github.com/LalitMaganti/c221cf0cae17e298dfa82b118edf9080
### Prerequisites
@@ -330,7 +330,7 @@
_Notes:_
-- If something doesn't work as intended, check that the workspace looks the same as the contents of this [GitHub gist](https://gist.github.com/tilal6991/c221cf0cae17e298dfa82b118edf9080).
+- If something doesn't work as intended, check that the workspace looks the same as the contents of this [GitHub gist](https://gist.github.com/LalitMaganti/c221cf0cae17e298dfa82b118edf9080).
- A good example trace for this metric is the Android example trace used by the Perfetto UI found [here](https://storage.googleapis.com/perfetto-misc/example_android_trace_30s_1).
- stderr is redirected to remove any noise from parsing the trace that trace processor generates.
diff --git a/docs/contributing/build-instructions.md b/docs/contributing/build-instructions.md
index 76d53e3..9afa60f 100644
--- a/docs/contributing/build-instructions.md
+++ b/docs/contributing/build-instructions.md
@@ -80,20 +80,26 @@
Build the UI:
```bash
-gn args out/default # The only relevant arg is is_debug=true|false
-
-# This will generate the static content for serving the UI in out/default/ui/.
-tools/ninja -C out/default ui
+# Will build into ./out/ui by default. Can be changed with --out path/
+# The final bundle will be available at ./ui/out/dist/.
+# The build script creates a symlink from ./ui/out to $OUT_PATH/ui/.
+ui/build
```
Test your changes on a local server using:
```bash
-ui/run-dev-server out/default
+# This will automatically build the UI. There is no need to manually run
+# ui/build before running ui/run-dev-server.
+ui/run-dev-server
```
Navigate to http://localhost:10000/ to see the changes.
+The server supports live reloading of CSS and TS/JS contents. Whenever a ui
+source file is changed it, the script will automatically re-build it and show a
+prompt in the web page.
+
## IDE setup
Use a following command in the checkout directory in order to generate the
diff --git a/include/perfetto/tracing/debug_annotation.h b/include/perfetto/tracing/debug_annotation.h
index 38bc653..86494cf 100644
--- a/include/perfetto/tracing/debug_annotation.h
+++ b/include/perfetto/tracing/debug_annotation.h
@@ -18,6 +18,7 @@
#define INCLUDE_PERFETTO_TRACING_DEBUG_ANNOTATION_H_
#include "perfetto/base/export.h"
+#include "perfetto/tracing/traced_value_forward.h"
#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
#include <stdint.h>
@@ -54,86 +55,10 @@
// Called to write the contents of the debug annotation into the trace.
virtual void Add(protos::pbzero::DebugAnnotation*) const = 0;
+
+ void WriteIntoTracedValue(TracedValue context) const;
};
-namespace internal {
-// Overloads for all the supported built in debug annotation types. Numeric
-// types are handled with templates to avoid problems with overloading
-// platform-specific types (e.g., size_t).
-void PERFETTO_EXPORT WriteDebugAnnotation(protos::pbzero::DebugAnnotation*,
- const char*);
-void PERFETTO_EXPORT WriteDebugAnnotation(protos::pbzero::DebugAnnotation*,
- const std::string&);
-void PERFETTO_EXPORT WriteDebugAnnotation(protos::pbzero::DebugAnnotation*,
- const void*);
-void PERFETTO_EXPORT WriteDebugAnnotation(protos::pbzero::DebugAnnotation*,
- const DebugAnnotation&);
-
-template <typename T>
-void WriteDebugAnnotation(
- protos::pbzero::DebugAnnotation* annotation,
- T value,
- typename std::enable_if<std::is_floating_point<T>::value>::type* =
- nullptr) {
- annotation->set_double_value(static_cast<double>(value));
-}
-
-template <typename T>
-void WriteDebugAnnotation(
- protos::pbzero::DebugAnnotation* annotation,
- T value,
- typename std::enable_if<std::is_integral<T>::value &&
- !std::is_same<T, bool>::value &&
- std::is_signed<T>::value>::type* = nullptr) {
- annotation->set_int_value(static_cast<int64_t>(value));
-}
-
-template <typename T>
-void WriteDebugAnnotation(
- protos::pbzero::DebugAnnotation* annotation,
- T value,
- typename std::enable_if<
- std::is_enum<T>::value &&
- std::is_signed<typename safe_underlying_type<T>::type>::value>::type* =
- nullptr) {
- annotation->set_int_value(static_cast<int64_t>(value));
-}
-
-template <typename T>
-void WriteDebugAnnotation(
- protos::pbzero::DebugAnnotation* annotation,
- T value,
- typename std::enable_if<std::is_enum<T>::value &&
- std::is_unsigned<typename safe_underlying_type<
- T>::type>::value>::type* = nullptr) {
- annotation->set_uint_value(static_cast<uint64_t>(value));
-}
-
-template <typename T>
-void WriteDebugAnnotation(
- protos::pbzero::DebugAnnotation* annotation,
- T value,
- typename std::enable_if<std::is_integral<T>::value &&
- !std::is_same<T, bool>::value &&
- std::is_unsigned<T>::value>::type* = nullptr) {
- annotation->set_uint_value(static_cast<uint64_t>(value));
-}
-
-template <typename T>
-void WriteDebugAnnotation(
- protos::pbzero::DebugAnnotation* annotation,
- T value,
- typename std::enable_if<std::is_same<T, bool>::value>::type* = nullptr) {
- annotation->set_bool_value(static_cast<bool>(value));
-}
-
-template <typename T>
-void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
- const std::unique_ptr<T>& value) {
- WriteDebugAnnotation(annotation, *value);
-}
-
-} // namespace internal
} // namespace perfetto
#endif // INCLUDE_PERFETTO_TRACING_DEBUG_ANNOTATION_H_
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index 747b2ef..bba08db 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -23,6 +23,7 @@
#include "perfetto/tracing/data_source.h"
#include "perfetto/tracing/debug_annotation.h"
#include "perfetto/tracing/trace_writer_base.h"
+#include "perfetto/tracing/traced_value.h"
#include "perfetto/tracing/track.h"
#include "protos/perfetto/common/builtin_clock.pbzero.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
@@ -145,7 +146,8 @@
const char* name,
T&& value) {
auto annotation = AddDebugAnnotation(event_ctx, name);
- WriteDebugAnnotation(annotation, value);
+ WriteIntoTracedValue(internal::CreateTracedValueFromProto(annotation),
+ std::forward<T>(value));
}
// If the given track hasn't been seen by the trace writer yet, write a
diff --git a/include/perfetto/tracing/traced_value.h b/include/perfetto/tracing/traced_value.h
index 6029482..a5481b0 100644
--- a/include/perfetto/tracing/traced_value.h
+++ b/include/perfetto/tracing/traced_value.h
@@ -374,7 +374,7 @@
} // namespace internal
template <typename T>
-PERFETTO_EXPORT void WriteIntoTracedValue(TracedValue context, T&& value) {
+void WriteIntoTracedValue(TracedValue context, T&& value) {
// TODO(altimin): Add a URL to documentation and a list of common failure
// patterns.
static_assert(
@@ -396,20 +396,18 @@
// See WriteWithFallback test in traced_value_unittest.cc for a concrete
// example.
template <typename T>
-PERFETTO_EXPORT
- typename std::enable_if<internal::has_traced_value_support<T>::value>::type
- WriteIntoTracedValueWithFallback(TracedValue context,
- T&& value,
- const std::string&) {
+typename std::enable_if<internal::has_traced_value_support<T>::value>::type
+WriteIntoTracedValueWithFallback(TracedValue context,
+ T&& value,
+ const std::string&) {
WriteIntoTracedValue(std::move(context), std::forward<T>(value));
}
template <typename T>
-PERFETTO_EXPORT
- typename std::enable_if<!internal::has_traced_value_support<T>::value>::type
- WriteIntoTracedValueWithFallback(TracedValue context,
- T&&,
- const std::string& fallback) {
+typename std::enable_if<!internal::has_traced_value_support<T>::value>::type
+WriteIntoTracedValueWithFallback(TracedValue context,
+ T&&,
+ const std::string& fallback) {
std::move(context).WriteString(fallback);
}
diff --git a/include/perfetto/tracing/track_event_category_registry.h b/include/perfetto/tracing/track_event_category_registry.h
index 5e5304d..e51c4d6 100644
--- a/include/perfetto/tracing/track_event_category_registry.h
+++ b/include/perfetto/tracing/track_event_category_registry.h
@@ -282,7 +282,7 @@
}
static constexpr bool IsValidCategoryName(const char* name) {
- return (!name || *name == '\"' || *name == '*')
+ return (!name || *name == '\"' || *name == '*' || *name == ' ')
? false
: *name ? IsValidCategoryName(name + 1) : true;
}
diff --git a/include/perfetto/tracing/track_event_legacy.h b/include/perfetto/tracing/track_event_legacy.h
index d138223..6bd156a 100644
--- a/include/perfetto/tracing/track_event_legacy.h
+++ b/include/perfetto/tracing/track_event_legacy.h
@@ -146,6 +146,7 @@
static constexpr uint8_t TRACE_VALUE_TYPE_STRING = 6;
static constexpr uint8_t TRACE_VALUE_TYPE_COPY_STRING = 7;
static constexpr uint8_t TRACE_VALUE_TYPE_CONVERTABLE = 8;
+static constexpr uint8_t TRACE_VALUE_TYPE_PROTO = 9;
// Enum reflecting the scope of an INSTANT event. Must fit within
// TRACE_EVENT_FLAG_SCOPE_MASK.
diff --git a/src/tracing/core/packet_stream_validator.cc b/src/tracing/core/packet_stream_validator.cc
index 3d2d846..72a20f5 100644
--- a/src/tracing/core/packet_stream_validator.cc
+++ b/src/tracing/core/packet_stream_validator.cc
@@ -72,8 +72,11 @@
varint_ |= static_cast<uint64_t>(octet & 0x7F) << varint_shift_;
if (octet & 0x80) {
varint_shift_ += 7;
- if (varint_shift_ >= 64)
+ if (varint_shift_ >= 64) {
+ // Do not invoke UB on next call.
+ varint_shift_ = 0;
state_ = kInvalidVarInt;
+ }
return 0;
}
uint64_t varint = varint_;
diff --git a/src/tracing/debug_annotation.cc b/src/tracing/debug_annotation.cc
index 81e889c..8b3b0ff 100644
--- a/src/tracing/debug_annotation.cc
+++ b/src/tracing/debug_annotation.cc
@@ -16,33 +16,20 @@
#include "perfetto/tracing/debug_annotation.h"
+#include "perfetto/tracing/traced_value.h"
#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
namespace perfetto {
DebugAnnotation::~DebugAnnotation() = default;
-namespace internal {
-
-void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
- const char* value) {
- annotation->set_string_value(value);
+void DebugAnnotation::WriteIntoTracedValue(TracedValue context) const {
+ if (!context.root_context_) {
+ PERFETTO_DFATAL("DebugAnnotation should not be used in non-root contexts.");
+ std::move(context).WriteString("<not supported>");
+ return;
+ }
+ Add(context.root_context_);
}
-void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
- const std::string& value) {
- annotation->set_string_value(value);
-}
-
-void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
- const void* value) {
- annotation->set_pointer_value(reinterpret_cast<uint64_t>(value));
-}
-
-void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
- const DebugAnnotation& custom_annotation) {
- custom_annotation.Add(annotation);
-}
-
-} // namespace internal
} // namespace perfetto
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index acb86a0..08bd8a3 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -98,7 +98,6 @@
perfetto::Category("cat").SetTags("slow"),
perfetto::Category("cat.verbose").SetTags("debug"),
perfetto::Category("cat-with-dashes"),
- perfetto::Category("cat with spaces"),
perfetto::Category::Group("foo,bar"),
perfetto::Category::Group("baz,bar,quux"),
perfetto::Category::Group("red,green,blue,foo"),
@@ -990,7 +989,7 @@
// Check that the advertised categories match PERFETTO_DEFINE_CATEGORIES (see
// above).
- EXPECT_EQ(8, desc.available_categories_size());
+ EXPECT_EQ(7, desc.available_categories_size());
EXPECT_EQ("test", desc.available_categories()[0].name());
EXPECT_EQ("This is a test category",
desc.available_categories()[0].description());
@@ -1002,9 +1001,8 @@
EXPECT_EQ("cat.verbose", desc.available_categories()[4].name());
EXPECT_EQ("debug", desc.available_categories()[4].tags()[0]);
EXPECT_EQ("cat-with-dashes", desc.available_categories()[5].name());
- EXPECT_EQ("cat with spaces", desc.available_categories()[6].name());
- EXPECT_EQ("disabled-by-default-cat", desc.available_categories()[7].name());
- EXPECT_EQ("slow", desc.available_categories()[7].tags()[0]);
+ EXPECT_EQ("disabled-by-default-cat", desc.available_categories()[6].name());
+ EXPECT_EQ("slow", desc.available_categories()[6].tags()[0]);
}
TEST_P(PerfettoApiTest, TrackEventSharedIncrementalState) {
@@ -1921,6 +1919,10 @@
TRACE_EVENT_BEGIN("test", "E", "enum_arg", ENUM_BAR);
TRACE_EVENT_BEGIN("test", "E", "signed_enum_arg", SIGNED_ENUM_FOO);
TRACE_EVENT_BEGIN("test", "E", "class_enum_arg", MyClassEnum::VALUE);
+ TRACE_EVENT_BEGIN("test", "E", "traced_value",
+ [&](perfetto::TracedValue context) {
+ std::move(context).WriteInt64(42);
+ });
perfetto::TrackEvent::Flush();
tracing_session->get()->StopBlocking();
@@ -1935,7 +1937,7 @@
"B:test.E(ptr_arg=(pointer)baadf00d)",
"B:test.E(size_t_arg=(uint)42)", "B:test.E(ptrdiff_t_arg=(int)-7)",
"B:test.E(enum_arg=(uint)1)", "B:test.E(signed_enum_arg=(int)-1)",
- "B:test.E(class_enum_arg=(int)0)"));
+ "B:test.E(class_enum_arg=(int)0)", "B:test.E(traced_value=(int)42)"));
}
TEST_P(PerfettoApiTest, TrackEventCustomDebugAnnotations) {
@@ -3024,10 +3026,8 @@
EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic"));
EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic_2"));
EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
- EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("cat with spaces"));
- auto* tracing_session =
- NewTraceWithCategories({"foo", "dynamic", "cat with spaces"});
+ auto* tracing_session = NewTraceWithCategories({"foo", "dynamic"});
tracing_session->get()->StartBlocking();
EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("bar"));
@@ -3035,7 +3035,6 @@
EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("dynamic"));
EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic_2"));
EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
- EXPECT_TRUE(TRACE_EVENT_CATEGORY_ENABLED("cat with spaces"));
tracing_session->get()->StopBlocking();
EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("foo"));
@@ -3044,7 +3043,6 @@
EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic"));
EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("dynamic_2"));
EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED(dynamic));
- EXPECT_FALSE(TRACE_EVENT_CATEGORY_ENABLED("cat with spaces"));
}
class TestInterceptor : public perfetto::Interceptor<TestInterceptor> {
diff --git a/test/ci/common.sh b/test/ci/common.sh
index a798448..f4d6d0f 100644
--- a/test/ci/common.sh
+++ b/test/ci/common.sh
@@ -18,13 +18,14 @@
cd $(dirname ${BASH_SOURCE[0]})/../..
OUT_PATH="out/dist"
-if [[ -e buildtools/clang/bin/llvm-symbolizer ]]; then
- export ASAN_SYMBOLIZER_PATH="buildtools/clang/bin/llvm-symbolizer"
- export MSAN_SYMBOLIZER_PATH="buildtools/clang/bin/llvm-symbolizer"
-fi
-
tools/install-build-deps $INSTALL_BUILD_DEPS_ARGS
+# Assumes Linux. Windows should use /win/clang instead.
+if [[ -e buildtools/linux64/clang/bin/llvm-symbolizer ]]; then
+ export ASAN_SYMBOLIZER_PATH="$(readlink -f buildtools/linux64/clang/bin/llvm-symbolizer)"
+ export MSAN_SYMBOLIZER_PATH="$(readlink -f buildtools/linux64/clang/bin/llvm-symbolizer)"
+fi
+
# Performs checks on generated protos and build files.
tools/gn gen out/tmp.protoc --args="is_debug=false cc_wrapper=\"ccache\""
tools/gen_all --check-only out/tmp.protoc
diff --git a/test/ci/ui_tests.sh b/test/ci/ui_tests.sh
index 6b59820..9a1fa3a 100755
--- a/test/ci/ui_tests.sh
+++ b/test/ci/ui_tests.sh
@@ -16,10 +16,8 @@
INSTALL_BUILD_DEPS_ARGS="--ui"
source $(dirname ${BASH_SOURCE[0]})/common.sh
-tools/gn gen ${OUT_PATH} --args="${PERFETTO_TEST_GN_ARGS}" --check
-tools/ninja -C ${OUT_PATH} ${PERFETTO_TEST_NINJA_ARGS} ui
+tools/node ui/build.js --out ${OUT_PATH}
-cp -a ${OUT_PATH}/ui /ci/artifacts/
+cp -a ${OUT_PATH}/ui/dist/ /ci/artifacts/ui
-# Run the tests
-${OUT_PATH}/ui_unittests --ci
+tools/node ui/build.js --out ${OUT_PATH} --no-build --run-tests
diff --git a/tools/run_test_like_ci b/tools/run_test_like_ci
index 4f35def..35497c4 100755
--- a/tools/run_test_like_ci
+++ b/tools/run_test_like_ci
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright (C) 2019 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/ui/.gitignore b/ui/.gitignore
index 4372381..4f807ce 100644
--- a/ui/.gitignore
+++ b/ui/.gitignore
@@ -1,2 +1,2 @@
-/dist
/node_modules/
+/out
diff --git a/ui/BUILD.gn b/ui/BUILD.gn
index a668a29..98aeb5b 100644
--- a/ui/BUILD.gn
+++ b/ui/BUILD.gn
@@ -12,593 +12,43 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import("../gn/gen_perfetto_version_header.gni")
import("../gn/perfetto.gni")
-import("../gn/perfetto_check_build_deps.gni")
-import("../gn/wasm.gni")
-import("../protos/perfetto/trace_processor/proto_files.gni")
# Prevent that this file is accidentally included in embedder builds.
assert(enable_perfetto_ui)
-ui_dir = "$root_build_dir/ui"
-chrome_extension_dir = "$root_build_dir/chrome_extension"
-ui_gen_dir = "$target_out_dir/gen"
nodejs_bin = rebase_path("//tools/node", root_build_dir)
-# +----------------------------------------------------------------------------+
-# | The outer "ui" target to just ninja -C out/xxx ui |
-# +----------------------------------------------------------------------------+
-
group("ui") {
deps = [
- ":chrome_extension_assets_dist",
- ":chrome_extension_bundle_dist",
- ":dist",
- ":gen_dist_file_map",
- ":service_worker_bundle_dist",
- ":test_scripts",
-
- # IMPORTANT: Only add deps here if they are NOT part of the production UI
- # (e.g., tests, extensions, ...). Any UI dep should go in the
- # |ui_dist_targets| list below. The only exception is the service worker
- # target, that depends on that list.
+ ":ui_build($host_toolchain)",
+ "//src/trace_processor:trace_processor.wasm($wasm_toolchain)",
+ "//tools/trace_to_text:trace_to_text.wasm($wasm_toolchain)",
]
}
-# The list of targets that produces dist/ files for the UI. This list is used
-# also by the gen_dist_file_map to generate the map of hashes of all UI files,
-# which is turn used by the service worker code for the offline caching.
-ui_dist_targets = [
- ":assets_dist",
- ":catapult_dist",
- ":controller_bundle_dist",
- ":engine_bundle_dist",
- ":frontend_bundle_dist",
- ":index_dist",
- ":scss",
- ":typefaces_dist",
- ":wasm_dist",
-]
-
-# Builds the ui, but not service worker, tests and extensions.
-group("dist") {
- deps = ui_dist_targets
-}
-
-# A minimal page to profile the WASM engine without the all UI.
-group("query") {
- deps = [
- ":query_bundle_dist",
- ":query_dist",
- ":ui",
- ]
-}
-
-# +----------------------------------------------------------------------------+
-# | Template used to run node binaries using the hermetic node toolchain. |
-# +----------------------------------------------------------------------------+
-template("node_bin") {
- action(target_name) {
- forward_variables_from(invoker,
- [
- "inputs",
- "outputs",
- "depfile",
- ])
- deps = [ ":node_modules" ]
- if (defined(invoker.deps)) {
- deps += invoker.deps
- }
- script = "../gn/standalone/build_tool_wrapper.py"
- _node_cmd = invoker.node_cmd
- args = []
- if (defined(invoker.suppress_stdout) && invoker.suppress_stdout) {
- args += [ "--suppress_stdout" ]
- }
- if (defined(invoker.suppress_stderr) && invoker.suppress_stderr) {
- args += [ "--suppress_stderr" ]
- }
-
- # Some of the node_bin rules *cough*transpile_all_ts*cough* don't
- # accuratly report the output files. This means if they can run,
- # change something, and not cause their dependees to rerun causing
- # bugs. Adding a stamp file which is always rewritten avoids this.
- # See also b/120010518
- stamp_path = "$ui_dir/$target_name.node_bin.stamp"
- outputs += [ stamp_path ]
- args += [
- "--stamp=" + rebase_path(stamp_path, root_build_dir),
- nodejs_bin,
- rebase_path("node_modules/.bin/$_node_cmd", root_build_dir),
- ] + invoker.args
- }
-}
-
-# +----------------------------------------------------------------------------+
-# | Template for "sorcery" the source map resolver. |
-# +----------------------------------------------------------------------------+
-template("sorcery") {
- node_bin(target_name) {
- assert(defined(invoker.input))
- assert(defined(invoker.output))
- forward_variables_from(invoker, [ "deps" ])
- inputs = [ invoker.input ]
- outputs = [
- invoker.output,
- invoker.output + ".map",
- ]
- node_cmd = "sorcery"
- args = [
- "-i",
- rebase_path(invoker.input, root_build_dir),
- "-o",
- rebase_path(invoker.output, root_build_dir),
- ]
- }
-}
-
-# +----------------------------------------------------------------------------+
-# | Template for bundling js |
-# +----------------------------------------------------------------------------+
-template("bundle") {
- node_bin(target_name) {
- assert(defined(invoker.input))
- assert(defined(invoker.output))
- forward_variables_from(invoker, [ "deps" ])
- inputs = [
- invoker.input,
- "rollup.config.js",
- ]
- outputs = [
- invoker.output,
- invoker.output + ".map",
- ]
- node_cmd = "rollup"
- args = [
- "-c",
- rebase_path("rollup.config.js", root_build_dir),
- rebase_path(invoker.input, root_build_dir),
- "-o",
- rebase_path(invoker.output, root_build_dir),
- "-f",
- "iife",
- "-m",
- "--silent",
- ]
- }
-}
-
-# +----------------------------------------------------------------------------+
-# | Bundles all *.js files together resolving CommonJS require() deps. |
-# +----------------------------------------------------------------------------+
-
-# Bundle together all js sources into a bundle.js file, that will ultimately be
-# included by the .html files.
-
-bundle("frontend_bundle") {
- deps = [ ":transpile_all_ts" ]
- input = "$target_out_dir/frontend/index.js"
- output = "$target_out_dir/frontend_bundle.js"
-}
-
-bundle("chrome_extension_bundle") {
- deps = [ ":transpile_all_ts" ]
- input = "$target_out_dir/chrome_extension/index.js"
- output = "$target_out_dir/chrome_extension_bundle.js"
-}
-
-bundle("controller_bundle") {
- deps = [ ":transpile_all_ts" ]
- input = "$target_out_dir/controller/index.js"
- output = "$target_out_dir/controller_bundle.js"
-}
-
-bundle("engine_bundle") {
- deps = [ ":transpile_all_ts" ]
- input = "$target_out_dir/engine/index.js"
- output = "$target_out_dir/engine_bundle.js"
-}
-
-bundle("service_worker_bundle") {
- deps = [ ":transpile_service_worker_ts" ]
- input = "$target_out_dir/service_worker/service_worker.js"
- output = "$target_out_dir/service_worker.js"
-}
-
-bundle("query_bundle") {
- deps = [ ":transpile_all_ts" ]
- input = "$target_out_dir/query/index.js"
- output = "$target_out_dir/query_bundle.js"
-}
-
-# +----------------------------------------------------------------------------+
-# | Protobuf: gen rules to create .js and .d.ts files from protos. |
-# +----------------------------------------------------------------------------+
-node_bin("protos_to_js") {
+action("deprecation_warning") {
+ script = "../gn/standalone/build_tool_wrapper.py"
+ outputs = [ "$target_out_dir/never_written_always_execute_rule-2.stamp" ]
inputs = []
- foreach(proto, trace_processor_protos) {
- inputs += [ "../protos/perfetto/trace_processor/$proto.proto" ]
- }
- inputs += [
- "../protos/perfetto/common/trace_stats.proto",
- "../protos/perfetto/common/tracing_service_capabilities.proto",
- "../protos/perfetto/config/perfetto_config.proto",
- "../protos/perfetto/ipc/consumer_port.proto",
- "../protos/perfetto/ipc/wire_protocol.proto",
- "../protos/perfetto/metrics/metrics.proto",
- ]
- outputs = [ "$ui_gen_dir/protos.js" ]
- node_cmd = "pbjs"
args = [
- "--force-number",
- "-t",
- "static-module",
- "-w",
- "commonjs",
- "-p",
- rebase_path("..", root_build_dir),
- "-o",
- rebase_path(outputs[0], root_build_dir),
- ] + rebase_path(inputs, root_build_dir)
-}
-
-# Protobuf.js requires to first generate .js files from the .proto and then
-# create .ts definitions for them.
-node_bin("protos_to_ts") {
- deps = [ ":protos_to_js" ]
- inputs = [ "$ui_gen_dir/protos.js" ]
- outputs = [ "$ui_gen_dir/protos.d.ts" ]
- node_cmd = "pbts"
- args = [
- "-p",
- rebase_path("..", root_build_dir),
- "-o",
- rebase_path(outputs[0], root_build_dir),
- rebase_path(inputs[0], root_build_dir),
+ "cat",
+ rebase_path("config/gn_deprecation_banner.txt", root_build_dir),
]
}
-# +----------------------------------------------------------------------------+
-# | TypeScript: transpiles all *.ts into .js |
-# +----------------------------------------------------------------------------+
-
-# Builds all .ts sources in the repo under |src|.
-node_bin("transpile_all_ts") {
- deps = [
- ":dist_symlink",
- ":protos_to_ts",
- ":version_ts_gen",
- ":wasm_gen",
- ]
- inputs = [ "tsconfig.json" ]
- outputs = [
- "$target_out_dir/frontend/index.js",
- "$target_out_dir/engine/index.js",
- "$target_out_dir/controller/index.js",
- "$target_out_dir/query/index.js",
- "$target_out_dir/chrome_extension/index.js",
- ]
-
- depfile = root_out_dir + "/tsc.d"
- exec_script("../gn/standalone/glob.py",
- [
- "--root=" + rebase_path(".", root_build_dir),
- "--filter=*.ts",
- "--exclude=node_modules",
- "--exclude=dist",
- "--exclude=service_worker",
- "--deps=obj/ui/frontend/index.js",
- "--output=" + rebase_path(depfile),
- ],
- "")
-
- node_cmd = "tsc"
- args = [
- "--incremental",
- "--project",
- rebase_path(".", root_build_dir),
- "--outDir",
- rebase_path(target_out_dir, root_build_dir),
- ]
-}
-
-node_bin("transpile_service_worker_ts") {
- deps = [
- ":dist_symlink",
- ":gen_dist_file_map",
- ]
+action("ui_build") {
+ deps = [ ":deprecation_warning" ]
+ script = "../gn/standalone/build_tool_wrapper.py"
+ outputs = [ "$target_out_dir/never_written_always_execute_rule.stamp" ]
inputs = [
- "tsconfig.json",
- "src/service_worker/service_worker.ts",
+ "//tools/node",
+ "build.js",
]
- outputs = [ "$target_out_dir/service_worker/service_worker.js" ]
-
- node_cmd = "tsc"
args = [
- "--project",
- rebase_path("src/service_worker", root_build_dir),
- "--outDir",
- rebase_path(target_out_dir, root_build_dir),
+ nodejs_bin,
+ rebase_path("build.js", root_build_dir),
+ "--out",
+ ".",
]
}
-
-# +----------------------------------------------------------------------------+
-# | Build css. |
-# +----------------------------------------------------------------------------+
-
-scss_root = "src/assets/perfetto.scss"
-scss_srcs = [
- "src/assets/analyze_page.scss",
- "src/assets/common.scss",
- "src/assets/details.scss",
- "src/assets/metrics_page.scss",
- "src/assets/modal.scss",
- "src/assets/record.scss",
- "src/assets/sidebar.scss",
- "src/assets/topbar.scss",
- "src/assets/trace_info_page.scss",
- "src/assets/typefaces.scss",
-]
-
-# Build css.
-node_bin("scss") {
- deps = [ ":dist_symlink" ]
- inputs = [ scss_root ] + scss_srcs
- outputs = [ "$ui_dir/perfetto.css" ]
-
- node_cmd = "node-sass"
- args = [
- "--quiet",
- rebase_path(scss_root, root_build_dir),
- rebase_path(outputs[0], root_build_dir),
- ]
-}
-
-# +----------------------------------------------------------------------------+
-# | Copy rules: create the final output directory. |
-# +----------------------------------------------------------------------------+
-copy("index_dist") {
- sources = [ "index.html" ]
- outputs = [ "$ui_dir/index.html" ]
-}
-
-copy("typefaces_dist") {
- sources = [
- "../buildtools/typefaces/MaterialIcons.woff2",
- "../buildtools/typefaces/Raleway-Regular.woff2",
- "../buildtools/typefaces/Raleway-Thin.woff2",
- "../buildtools/typefaces/RobotoCondensed-Light.woff2",
- "../buildtools/typefaces/RobotoCondensed-Regular.woff2",
- "../buildtools/typefaces/RobotoMono-Regular.woff2",
- ]
-
- outputs = [ "$ui_dir/assets/{{source_file_part}}" ]
-}
-
-copy("query_dist") {
- sources = [ "query.html" ]
- outputs = [ "$ui_dir/query.html" ]
-}
-
-copy("assets_dist") {
- sources = [
- "src/assets/brand.png",
- "src/assets/favicon.png",
- "src/assets/logo-3d.png",
- "src/assets/rec_atrace.png",
- "src/assets/rec_battery_counters.png",
- "src/assets/rec_board_voltage.png",
- "src/assets/rec_cpu_coarse.png",
- "src/assets/rec_cpu_fine.png",
- "src/assets/rec_cpu_freq.png",
- "src/assets/rec_cpu_voltage.png",
- "src/assets/rec_ftrace.png",
- "src/assets/rec_gpu_mem_total.png",
- "src/assets/rec_java_heap_dump.png",
- "src/assets/rec_lmk.png",
- "src/assets/rec_logcat.png",
- "src/assets/rec_long_trace.png",
- "src/assets/rec_mem_hifreq.png",
- "src/assets/rec_meminfo.png",
- "src/assets/rec_native_heap_profiler.png",
- "src/assets/rec_one_shot.png",
- "src/assets/rec_ps_stats.png",
- "src/assets/rec_ring_buf.png",
- "src/assets/rec_vmstat.png",
- ] + [ scss_root ] + scss_srcs
- outputs = [ "$ui_dir/assets/{{source_file_part}}" ]
-}
-copy("chrome_extension_assets_dist") {
- sources = [
- "src/assets/logo-128.png",
- "src/chrome_extension/manifest.json",
- ]
- outputs = [ "$chrome_extension_dir/{{source_file_part}}" ]
-}
-
-sorcery("frontend_bundle_dist") {
- deps = [ ":frontend_bundle" ]
- input = "$target_out_dir/frontend_bundle.js"
- output = "$ui_dir/frontend_bundle.js"
-}
-
-sorcery("chrome_extension_bundle_dist") {
- deps = [ ":chrome_extension_bundle" ]
- input = "$target_out_dir/chrome_extension_bundle.js"
- output = "$chrome_extension_dir/chrome_extension_bundle.js"
-}
-
-sorcery("controller_bundle_dist") {
- deps = [ ":controller_bundle" ]
- input = "$target_out_dir/controller_bundle.js"
- output = "$ui_dir/controller_bundle.js"
-}
-
-sorcery("engine_bundle_dist") {
- deps = [ ":engine_bundle" ]
- input = "$target_out_dir/engine_bundle.js"
- output = "$ui_dir/engine_bundle.js"
-}
-
-sorcery("service_worker_bundle_dist") {
- deps = [ ":service_worker_bundle" ]
- input = "$target_out_dir/service_worker.js"
- output = "$ui_dir/service_worker.js"
-}
-
-sorcery("query_bundle_dist") {
- deps = [ ":query_bundle" ]
- input = "$target_out_dir/query_bundle.js"
- output = "$ui_dir/query_bundle.js"
-}
-
-copy("wasm_dist") {
- deps = [
- "//src/trace_processor:trace_processor.wasm($wasm_toolchain)",
- "//tools/trace_to_text:trace_to_text.wasm($wasm_toolchain)",
- ]
- sources = [
- "$root_build_dir/wasm/trace_processor.wasm",
- "$root_build_dir/wasm/trace_to_text.wasm",
- ]
- outputs = [ "$ui_dir/{{source_file_part}}" ]
-}
-
-copy("wasm_gen") {
- deps = [
- ":dist_symlink",
-
- # trace_processor
- "//src/trace_processor:trace_processor.d.ts($wasm_toolchain)",
- "//src/trace_processor:trace_processor.js($wasm_toolchain)",
- "//src/trace_processor:trace_processor.wasm($wasm_toolchain)",
-
- # trace_to_text
- "//tools/trace_to_text:trace_to_text.d.ts($wasm_toolchain)",
- "//tools/trace_to_text:trace_to_text.js($wasm_toolchain)",
- "//tools/trace_to_text:trace_to_text.wasm($wasm_toolchain)",
- ]
- sources = [
- # trace_processor
- "$root_build_dir/wasm/trace_processor.d.ts",
- "$root_build_dir/wasm/trace_processor.js",
- "$root_build_dir/wasm/trace_processor.wasm",
-
- # trace_to_text
- "$root_build_dir/wasm/trace_to_text.d.ts",
- "$root_build_dir/wasm/trace_to_text.js",
- "$root_build_dir/wasm/trace_to_text.wasm",
- ]
- if (is_debug) {
- sources += [
- "$root_build_dir/wasm/trace_processor.wasm.map",
- "$root_build_dir/wasm/trace_to_text.wasm.map",
- ]
- }
- outputs = [ "$ui_gen_dir/{{source_file_part}}" ]
-}
-
-# Copy over the vulcanized legacy trace viewer.
-copy("catapult_dist") {
- sources = [
- "../buildtools/catapult_trace_viewer/catapult_trace_viewer.html",
- "../buildtools/catapult_trace_viewer/catapult_trace_viewer.js",
- ]
- outputs = [ "$ui_dir/assets/{{source_file_part}}" ]
-}
-
-# +----------------------------------------------------------------------------+
-# | Node JS: Creates a symlink in the out directory to node_modules. |
-# +----------------------------------------------------------------------------+
-
-perfetto_check_build_deps("check_ui_deps") {
- args = [ "--ui" ]
- inputs = [ "package-lock.json" ]
-}
-
-# Creates a symlink from out/xxx/ui/node_modules -> ../../../ui/node_modules.
-# This allows to run rollup and other node tools from the out/xxx directory.
-action("node_modules_symlink") {
- deps = [ ":check_ui_deps" ]
- script = "../gn/standalone/build_tool_wrapper.py"
- stamp_file = "$target_out_dir/.$target_name.stamp"
- args = [
- "--stamp",
- rebase_path(stamp_file, root_build_dir),
- "/bin/ln",
- "-fns",
- rebase_path("node_modules", target_out_dir),
- rebase_path("$target_out_dir/node_modules", root_build_dir),
- ]
- outputs = [ stamp_file ]
-}
-
-group("node_modules") {
- deps = [ ":node_modules_symlink" ]
-}
-
-# Creates a symlink from //ui/dist -> ../../out/xxx/ui. Used only for
-# autocompletion in IDEs. The problem this is solving is that in tsconfig.json
-# we can't possibly know the path to ../../out/xxx for outDir. Instead, we set
-# outDir to "./dist" and create a symlink on the first build.
-action("dist_symlink") {
- script = "../gn/standalone/build_tool_wrapper.py"
- stamp_file = "$target_out_dir/.$target_name.stamp"
- args = [
- "--stamp",
- rebase_path(stamp_file, root_build_dir),
- "/bin/ln",
- "-fns",
- rebase_path(target_out_dir, "."),
- rebase_path("dist", root_build_dir),
- ]
- inputs = [ "$root_build_dir" ]
- outputs = [ stamp_file ]
-}
-
-group("test_scripts") {
- deps = [
- ":copy_tests_script",
- ":copy_unittests_script",
- ]
-}
-
-copy("copy_unittests_script") {
- sources = [ "config/ui_unittests_template" ]
- outputs = [ "$root_build_dir/ui_unittests" ]
-}
-
-copy("copy_tests_script") {
- sources = [ "config/ui_tests_template" ]
- outputs = [ "$root_build_dir/ui_tests" ]
-}
-
-# This target generates an map containing all the UI subresources and their
-# hashes. This is used by the service worker code for offline caching.
-# This target needs to be kept at the end of the BUILD.gn file, because of the
-# get_target_outputs() call (fails otherwise due to GN's evaluation order).
-action("gen_dist_file_map") {
- out_file_path = "$ui_gen_dir/dist_file_map.ts"
-
- dist_files = []
- foreach(target, ui_dist_targets) {
- foreach(dist_file, get_target_outputs(target)) {
- dist_files += [ rebase_path(dist_file, root_build_dir) ]
- }
- }
- deps = [ ":dist" ]
- script = "../gn/standalone/write_ui_dist_file_map.py"
- inputs = []
- outputs = [ out_file_path ]
- args = [
- "--out",
- rebase_path(out_file_path, root_build_dir),
- "--strip",
- rebase_path(ui_dir, root_build_dir),
- ] + dist_files
-}
-
-gen_perfetto_version_header("version_ts_gen") {
- ts_out = "$ui_gen_dir/perfetto_version.ts"
-}
diff --git a/ui/OWNERS b/ui/OWNERS
index 1ae6de1..973653f 100644
--- a/ui/OWNERS
+++ b/ui/OWNERS
@@ -1,3 +1,4 @@
hjd@google.com
-taylori@google.com
+eseckler@google.com
dproy@google.com
+primiano@google.com
diff --git a/ui/build b/ui/build
new file mode 100755
index 0000000..8045f2b
--- /dev/null
+++ b/ui/build
@@ -0,0 +1,18 @@
+#!/bin/bash
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+UI_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
+
+$UI_DIR/node $UI_DIR/build.js "$@"
diff --git a/ui/build.js b/ui/build.js
new file mode 100644
index 0000000..c461324
--- /dev/null
+++ b/ui/build.js
@@ -0,0 +1,614 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+// This script takes care of:
+// - The build process for the whole UI and the chrome extension.
+// - The HTTP dev-server with live-reload capabilities.
+// The reason why this is a hand-rolled script rather than a conventional build
+// system is keeping incremental build fast and maintaining the set of
+// dependencies contained.
+// The only way to keep incremental build fast (i.e. O(seconds) for the
+// edit-one-line -> reload html cycles) is to run both the TypeScript compiler
+// and the rollup bundler in --watch mode. Any other attempt, leads to O(10s)
+// incremental-build times.
+// This script allows mixing build tools that support --watch mode (tsc and
+// rollup) and auto-triggering-on-file-change rules via fs.watch().
+// When invoked without any argument (e.g., for production builds), this script
+// just runs all the build tasks serially. It doesn't to do any mtime-based
+// check, it always re-runs all the tasks.
+// When invoked with --watch, it mounts a pipeline of tasks based on fs.watch()
+// and runs them together with tsc --watch and rollup --watch.
+// The output directory structure is carefully crafted so that any change to UI
+// sources causes cascading triggers of the next steps.
+// The overall build graph looks as follows:
+// +----------------+ +-----------------------------+
+// | protos/*.proto |----->| pbjs out/tsc/gen/protos.js |--+
+// +----------------+ +-----------------------------+ |
+// +-----------------------------+ |
+// | pbts out/tsc/gen/protos.d.ts|<-+
+// +-----------------------------+
+// |
+// V +-------------------------+
+// +---------+ +-----+ | out/tsc/frontend/*.js |
+// | ui/*.ts |------------->| tsc |-> +-------------------------+ +--------+
+// +---------+ +-----+ | out/tsc/controller/*.js |-->| rollup |
+// ^ +-------------------------+ +--------+
+// +------------+ | out/tsc/engine/*.js | |
+// +-----------+ |*.wasm.js | +-------------------------+ |
+// |ninja *.cc |->|*.wasm.d.ts | |
+// +-----------+ |*.wasm |-----------------+ |
+// +------------+ | |
+// V V
+// +-----------+ +------+ +------------------------------------------------+
+// | ui/*.scss |->| scss |--->| Final out/dist/ dir |
+// +-----------+ +------+ +------------------------------------------------+
+// +----------------------+ | +----------+ +---------+ +--------------------+|
+// | src/assets/*.png | | | assets/ | |*.wasm.js| | frontend_bundle.js ||
+// +----------------------+ | | *.css | |*.wasm | +--------------------+|
+// | buildtools/typefaces |-->| | *.png | +---------+ |controller_bundle.js||
+// +----------------------+ | | *.woff2 | +--------------------+|
+// | buildtools/legacy_tv | | | tv.html | | engine_bundle.js ||
+// +----------------------+ | +----------+ +--------------------+|
+// +------------------------------------------------+
+
+const argparse = require('argparse');
+const child_process = require('child_process');
+const fs = require('fs');
+const http = require('http');
+const path = require('path');
+const pjoin = path.join;
+
+const ROOT_DIR = path.dirname(__dirname); // The repo root.
+const VERSION_SCRIPT = pjoin(ROOT_DIR, 'tools/write_version_header.py');
+
+const cfg = {
+ watch: false,
+ verbose: false,
+ debug: false,
+ startHttpServer: false,
+ wasmModules: ['trace_processor', 'trace_to_text'],
+ testConfigs: ['jest.unit.config.js'],
+
+ // The fields below will be changed by main() after cmdline parsing.
+ // Directory structure:
+ // out/xxx/ -> outDir : Root build dir, for both ninja/wasm and UI.
+ // ui/ -> outUiDir : UI dir. All outputs from this script.
+ // tsc/ -> outTscDir : Transpiled .ts -> .js.
+ // gen/ -> outGenDir : Auto-generated .ts/.js (e.g. protos).
+ // dist/ -> outDistDir : Final artifacts (JS bundles, assets).
+ // chrome_extension/ : Chrome extension.
+ outDir: pjoin(ROOT_DIR, 'out/ui'),
+ outUiDir: '',
+ outTscDir: '',
+ outGenDir: '',
+ outDistRootDir: '',
+ outDistDir: '',
+ outExtDir: '',
+};
+
+const RULES = [
+ {r: /ui\/src\/assets\/(index.html)/, f: copyIntoDistRoot},
+ {r: /ui\/src\/assets\/((.*)[.]png)/, f: copyAssets},
+ {r: /buildtools\/typefaces\/(.+[.]woff2)/, f: copyAssets},
+ {r: /buildtools\/catapult_trace_viewer\/(.+(js|html))/, f: copyAssets},
+ {r: /ui\/src\/assets\/.+[.]scss/, f: compileScss},
+ {r: /ui\/src\/assets\/.+[.]scss/, f: compileScss},
+ {r: /ui\/src\/chrome_extension\/.*/, f: copyExtensionAssets},
+ {r: /.*\/dist\/(?!service_worker).*/, f: genServiceWorkerDistHashes},
+ {r: /.*\/dist\/.*/, f: notifyLiveServer},
+];
+
+let tasks = [];
+let tasksTot = 0, tasksRan = 0;
+let serverStarted = false;
+let httpWatches = [];
+let tStart = Date.now();
+let subprocesses = [];
+
+function main() {
+ const parser = new argparse.ArgumentParser();
+ parser.addArgument('--out', {help: 'Output directory'});
+ parser.addArgument(['--watch', '-w'], {action: 'storeTrue'});
+ parser.addArgument(['--serve', '-s'], {action: 'storeTrue'});
+ parser.addArgument(['--verbose', '-v'], {action: 'storeTrue'});
+ parser.addArgument(['--no-build', '-n'], {action: 'storeTrue'});
+ parser.addArgument(['--no-wasm', '-W'], {action: 'storeTrue'});
+ parser.addArgument(['--run-tests', '-t'], {action: 'storeTrue'});
+ parser.addArgument(['--debug', '-d'], {action: 'storeTrue'});
+
+ const args = parser.parseArgs();
+ const clean = !args.no_build;
+ cfg.outDir = path.resolve(ensureDir(args.out || cfg.outDir));
+ cfg.outUiDir = ensureDir(pjoin(cfg.outDir, 'ui'), clean);
+ cfg.outExtDir = ensureDir(pjoin(cfg.outUiDir, 'chrome_extension'));
+ cfg.outDistRootDir = ensureDir(pjoin(cfg.outUiDir, 'dist'));
+ // TODO(primiano): for now distDir == distRootDir. In next CLs distDir will
+ // become dist/v1.2.3/.
+ cfg.outDistDir = cfg.outDistRootDir;
+ cfg.outTscDir = ensureDir(pjoin(cfg.outUiDir, 'tsc'));
+ cfg.outGenDir = ensureDir(pjoin(cfg.outUiDir, 'tsc/gen'));
+ cfg.watch = !!args.watch;
+ cfg.verbose = !!args.verbose;
+ cfg.debug = !!args.debug;
+ cfg.startHttpServer = args.serve;
+
+ process.on('SIGINT', () => {
+ console.log('\nSIGINT received. Killing all child processes and exiting');
+ for (const proc of subprocesses) {
+ if (proc) proc.kill('SIGINT');
+ }
+ process.exit(130); // 130 -> Same behavior of bash when killed by SIGINT.
+ });
+
+ // Check that deps are current before starting.
+ const installBuildDeps = pjoin(ROOT_DIR, 'tools/install-build-deps');
+ const depsArgs = ['--check-only', pjoin(cfg.outDir, '.check_deps'), '--ui'];
+ exec(installBuildDeps, depsArgs);
+
+ console.log('Entering', cfg.outDir);
+ process.chdir(cfg.outDir);
+
+ updateSymilnks(); // Links //ui/out -> //out/xxx/ui/
+
+ // Enqueue empty task. This is needed only for --no-build --serve. The HTTP
+ // server is started when the task queue reaches quiescence, but it takes at
+ // least one task for that.
+ addTask(() => {});
+
+ if (!args.no_build) {
+ buildWasm(args.no_wasm);
+ scanDir('ui/src/assets');
+ scanDir('ui/src/chrome_extension');
+ scanDir('buildtools/typefaces');
+ scanDir('buildtools/catapult_trace_viewer');
+ compileProtos();
+ genVersion();
+ transpileTsProject('ui');
+ bundleJs('rollup.config.js');
+
+ // ServiceWorker.
+ genServiceWorkerDistHashes();
+ transpileTsProject('ui/src/service_worker');
+ bundleJs('rollup-serviceworker.config.js');
+
+ // Watches the /dist. When changed:
+ // - Notifies the HTTP live reload clients.
+ // - Regenerates the ServiceWorker file map.
+ scanDir(cfg.outDistRootDir);
+ }
+
+ if (args.run_tests) {
+ runTests();
+ }
+}
+
+// -----------
+// Build rules
+// -----------
+
+function runTests() {
+ const args =
+ ['--rootDir', cfg.outTscDir, '--verbose', '--runInBand', '--forceExit'];
+ for (const cfgFile of cfg.testConfigs) {
+ args.push('--projects', pjoin(ROOT_DIR, 'ui/config', cfgFile));
+ }
+ if (cfg.watch) {
+ args.push('--watchAll');
+ addTask(execNode, ['jest', args, {async: true}]);
+ } else {
+ addTask(execNode, ['jest', args]);
+ }
+}
+
+function copyIntoDistRoot(src, dst) {
+ addTask(cp, [src, pjoin(cfg.outDistRootDir, dst)]);
+}
+
+function copyAssets(src, dst) {
+ addTask(cp, [src, pjoin(cfg.outDistDir, 'assets', dst)]);
+}
+
+function compileScss() {
+ const src = pjoin(ROOT_DIR, 'ui/src/assets/perfetto.scss');
+ const dst = pjoin(cfg.outDistDir, 'perfetto.css');
+ // In watch mode, don't exit(1) if scss fails. It can easily happen by
+ // having a typo in the css. It will still print an errror.
+ const noErrCheck = !!cfg.watch;
+ addTask(execNode, ['node-sass', ['--quiet', src, dst], {noErrCheck}]);
+}
+
+function compileProtos() {
+ const dstJs = pjoin(cfg.outGenDir, 'protos.js');
+ const dstTs = pjoin(cfg.outGenDir, 'protos.d.ts');
+ const inputs = [
+ 'protos/perfetto/trace_processor/trace_processor.proto',
+ 'protos/perfetto/common/trace_stats.proto',
+ 'protos/perfetto/common/tracing_service_capabilities.proto',
+ 'protos/perfetto/config/perfetto_config.proto',
+ 'protos/perfetto/ipc/consumer_port.proto',
+ 'protos/perfetto/ipc/wire_protocol.proto',
+ 'protos/perfetto/metrics/metrics.proto',
+ ];
+ const pbjsArgs = [
+ '--force-number',
+ '-t',
+ 'static-module',
+ '-w',
+ 'commonjs',
+ '-p',
+ ROOT_DIR,
+ '-o',
+ dstJs
+ ].concat(inputs);
+ addTask(execNode, ['pbjs', pbjsArgs]);
+ const pbtsArgs = ['-p', ROOT_DIR, '-o', dstTs, dstJs];
+ addTask(execNode, ['pbts', pbtsArgs]);
+}
+
+// Generates a .ts source that defines the VERSION and SCM_REVISION constants.
+function genVersion() {
+ const cmd = 'python3';
+ const args =
+ [VERSION_SCRIPT, '--ts_out', pjoin(cfg.outGenDir, 'perfetto_version.ts')]
+ addTask(exec, [cmd, args]);
+}
+
+function updateSymilnks() {
+ mklink(cfg.outUiDir, pjoin(ROOT_DIR, 'ui/out'));
+ mklink(
+ pjoin(ROOT_DIR, 'ui/node_modules'), pjoin(cfg.outTscDir, 'node_modules'))
+}
+
+// Invokes ninja for building the {trace_processor, trace_to_text} Wasm modules.
+// It copies the .wasm directly into the out/dist/ dir, and the .js/.ts into
+// out/tsc/, so the typescript compiler and the bundler can pick them up.
+function buildWasm(skipWasmBuild) {
+ if (!skipWasmBuild) {
+ const gnArgs = ['gen', `--args=is_debug=${cfg.debug}`, cfg.outDir];
+ addTask(exec, [pjoin(ROOT_DIR, 'tools/gn'), gnArgs]);
+
+ const ninjaArgs = ['-C', cfg.outDir]
+ ninjaArgs.push(...cfg.wasmModules.map(x => `${x}_wasm`));
+ addTask(exec, [pjoin(ROOT_DIR, 'tools/ninja'), ninjaArgs]);
+ }
+
+ const wasmOutDir = pjoin(cfg.outDir, 'wasm');
+ for (const wasmMod of cfg.wasmModules) {
+ // The .wasm file goes directly into the dist dir (also .map in debug)
+ for (const ext of ['.wasm'].concat(cfg.debug ? ['.wasm.map'] : [])) {
+ const src = `${wasmOutDir}/${wasmMod}${ext}`;
+ addTask(cp, [src, pjoin(cfg.outDistDir, wasmMod + ext)]);
+ }
+ // The .js / .ts go into intermediates, they will be bundled by rollup.
+ for (const ext of ['.js', '.d.ts']) {
+ const fname = `${wasmMod}${ext}`;
+ addTask(cp, [pjoin(wasmOutDir, fname), pjoin(cfg.outGenDir, fname)]);
+ }
+ }
+}
+
+// This transpiles all the sources (frontend, controller, engine, extension) in
+// one go. The only project that has a dedicated invocation is service_worker.
+function transpileTsProject(project) {
+ const args = [
+ '--project',
+ pjoin(ROOT_DIR, project),
+ '--outDir',
+ cfg.outTscDir,
+ ];
+ if (cfg.watch) {
+ args.push('--watch', '--preserveWatchOutput');
+ addTask(execNode, ['tsc', args, {async: true}]);
+ } else {
+ addTask(execNode, ['tsc', args]);
+ }
+}
+
+// Creates the three {frontend, controller, engine}_bundle.js in one invocation.
+function bundleJs(cfgName) {
+ const rcfg = pjoin(ROOT_DIR, 'ui/config', cfgName)
+ const args = ['-c', rcfg, '--no-indent'];
+ args.push(...(cfg.verbose ? [] : ['--silent']));
+ if (cfg.watch) {
+ // --waitForBundleInput is so that we can run tsc --watch and rollup --watch
+ // together, without having to wait that tsc completes the first build.
+ args.push('--watch', '--waitForBundleInput', '--no-watch.clearScreen');
+ addTask(execNode, ['rollup', args, {async: true}]);
+ } else {
+ addTask(execNode, ['rollup', args]);
+ }
+}
+
+// Generates a map of {"dist_file_name" -> "sha256-01234"} used by the SW.
+function genServiceWorkerDistHashes() {
+ function write_ui_dist_file_map() {
+ const distFiles = [];
+ const skipRegex = /(service_worker\.js)|(\.map$)/;
+ walk(cfg.outDistDir, f => distFiles.push(f), skipRegex);
+ const dst = pjoin(cfg.outGenDir, 'dist_file_map.ts');
+ const cmd = 'python3';
+ const args = [
+ pjoin(ROOT_DIR, 'gn/standalone/write_ui_dist_file_map.py'),
+ '--out',
+ dst,
+ '--strip',
+ cfg.outDistDir,
+ ].concat(distFiles);
+ exec(cmd, args);
+ }
+ addTask(write_ui_dist_file_map, []);
+}
+
+function startServer() {
+ const port = 10000;
+ console.log(`Starting HTTP server on http://localhost:${port}`)
+ http.createServer(function(req, res) {
+ console.debug(req.method, req.url);
+ let uri = req.url.split('?', 1)[0];
+ if (uri.endsWith('/')) {
+ uri += 'index.html';
+ }
+
+ if (uri === '/live_reload') {
+ // Implements the Server-Side-Events protocol.
+ const head = {
+ 'Content-Type': 'text/event-stream',
+ 'Connection': 'keep-alive',
+ 'Cache-Control': 'no-cache'
+ };
+ res.writeHead(200, head);
+ const arrayIdx = httpWatches.length;
+ // We never remove from the array, the delete leaves an undefined item
+ // around. It makes keeping track of the index easier at the cost of a
+ // small leak.
+ httpWatches.push(res);
+ req.on('close', () => delete httpWatches[arrayIdx]);
+ return;
+ }
+
+ const absPath = path.normalize(path.join(cfg.outDistRootDir, uri));
+ fs.readFile(absPath, function(err, data) {
+ if (err) {
+ res.writeHead(404);
+ res.end(JSON.stringify(err));
+ return;
+ }
+
+ const mimeMap = {
+ 'html': 'text/html',
+ 'css': 'text/css',
+ 'js': 'application/javascript',
+ 'wasm': 'application/wasm',
+ };
+ const ext = uri.split('.').pop();
+ const cType = mimeMap[ext] || 'octect/stream';
+ const head = {
+ 'Content-Type': cType,
+ 'Content-Length': data.length,
+ 'Last-Modified': fs.statSync(absPath).mtime.toUTCString(),
+ 'Cache-Control': 'no-cache',
+ };
+ res.writeHead(200, head);
+ res.end(data);
+ });
+ })
+ .listen(port);
+}
+
+// Called whenever a change in the out/dist directory is detected. It sends a
+// Server-Side-Event to the live_reload.ts script.
+function notifyLiveServer(changedFile) {
+ for (const cli of httpWatches) {
+ if (cli === undefined) continue;
+ cli.write(
+ 'data: ' + path.relative(cfg.outDistRootDir, changedFile) + '\n\n');
+ }
+}
+
+function copyExtensionAssets() {
+ addTask(cp, [
+ pjoin(ROOT_DIR, 'ui/src/assets/logo-128.png'),
+ pjoin(cfg.outExtDir, 'logo-128.png')
+ ]);
+ addTask(cp, [
+ pjoin(ROOT_DIR, 'ui/src/chrome_extension/manifest.json'),
+ pjoin(cfg.outExtDir, 'manifest.json')
+ ]);
+}
+
+// -----------------------
+// Task chaining functions
+// -----------------------
+
+function addTask(func, args) {
+ const task = new Task(func, args);
+ for (const t of tasks) {
+ if (t.identity === task.identity) {
+ return;
+ }
+ }
+ tasks.push(task);
+ setTimeout(runTasks, 0);
+}
+
+function runTasks() {
+ const snapTasks = tasks.splice(0); // snap = std::move(tasks).
+ tasksTot += snapTasks.length;
+ for (const task of snapTasks) {
+ const DIM = '\u001b[2m';
+ const BRT = '\u001b[37m';
+ const RST = '\u001b[0m';
+ const ms = (new Date(Date.now() - tStart)).toISOString().slice(17, -1);
+ const ts = `[${DIM}${ms}${RST}]`;
+ const descr = task.description.substr(0, 80);
+ console.log(`${ts} ${BRT}${++tasksRan}/${tasksTot}${RST}\t${descr}`);
+ task.func.apply(/*this=*/ undefined, task.args);
+ }
+ // Start the web server once reaching quiescence.
+ if (tasks.length === 0 && !serverStarted && cfg.startHttpServer) {
+ serverStarted = true;
+ startServer();
+ }
+}
+
+// Executes all the RULES that match the given |absPath|.
+function scanFile(absPath) {
+ console.assert(fs.existsSync(absPath));
+ console.assert(path.isAbsolute(absPath));
+ const normPath = path.relative(ROOT_DIR, absPath);
+ for (const rule of RULES) {
+ const match = rule.r.exec(normPath);
+ if (!match || match[0] !== normPath) continue;
+ const captureGroup = match.length > 1 ? match[1] : undefined;
+ rule.f(absPath, captureGroup);
+ }
+}
+
+// Walks the passed |dir| recursively and, for each file, invokes the matching
+// RULES. If --watch is used, it also installs a fs.watch() and re-triggers the
+// matching RULES on each file change.
+function scanDir(dir, regex) {
+ const filterFn = regex ? absPath => regex.test(absPath) : () => true;
+ const absDir = path.isAbsolute(dir) ? dir : pjoin(ROOT_DIR, dir);
+ // Add a fs watch if in watch mode.
+ if (cfg.watch) {
+ fs.watch(absDir, {recursive: true}, (_eventType, fileName) => {
+ const filePath = pjoin(absDir, fileName);
+ if (!filterFn(filePath)) return;
+ if (cfg.verbose) {
+ console.log('File change detected', _eventType, filePath);
+ }
+ if (fs.existsSync(filePath)) {
+ scanFile(filePath, filterFn);
+ }
+ });
+ }
+ walk(absDir, f => {
+ if (filterFn(f)) scanFile(f);
+ });
+}
+
+function exec(cmd, args, opts) {
+ opts = opts || {};
+ opts.stdout = opts.stdout || 'inherit';
+ if (cfg.verbose) console.log(`${cmd} ${args.join(' ')}\n`);
+ const spwOpts = {cwd: cfg.outDir, stdio: ['ignore', opts.stdout, 'inherit']};
+ const checkExitCode = (code, signal) => {
+ if (signal === 'SIGINT' || signal === 'SIGTERM') return;
+ if (code !== 0 && !opts.noErrCheck) {
+ console.error(`${cmd} ${args.join(' ')} failed with code ${code}`);
+ process.exit(1);
+ }
+ };
+ if (opts.async) {
+ const proc = child_process.spawn(cmd, args, spwOpts);
+ const procIndex = subprocesses.length;
+ subprocesses.push(proc);
+ return new Promise((resolve, _reject) => {
+ proc.on('exit', (code, signal) => {
+ delete subprocesses[procIndex];
+ checkExitCode(code, signal);
+ resolve();
+ });
+ });
+ } else {
+ const spawnRes = child_process.spawnSync(cmd, args, spwOpts);
+ checkExitCode(spawnRes.status, spawnRes.signal);
+ return spawnRes;
+ }
+}
+
+function execNode(module, args, opts) {
+ const modPath = pjoin(ROOT_DIR, 'ui/node_modules/.bin', module);
+ const nodeBin = pjoin(ROOT_DIR, 'tools/node');
+ args = [modPath].concat(args || []);
+ const argsJson = JSON.stringify(args);
+ return exec(nodeBin, args, opts);
+}
+
+// ------------------------------------------
+// File system & subprocess utility functions
+// ------------------------------------------
+
+class Task {
+ constructor(func, args) {
+ this.func = func;
+ this.args = args || [];
+ // |identity| is used to dedupe identical tasks in the queue.
+ this.identity = JSON.stringify([this.func.name, this.args]);
+ }
+
+ get description() {
+ const ret = this.func.name.startsWith('exec') ? [] : [this.func.name];
+ const flattenedArgs = [].concat.apply([], this.args);
+ for (const arg of flattenedArgs) {
+ const argStr = `${arg}`;
+ if (argStr.startsWith('/')) {
+ ret.push(path.relative(cfg.outDir, arg));
+ } else {
+ ret.push(argStr);
+ }
+ }
+ return ret.join(' ');
+ }
+}
+
+function walk(dir, callback, skipRegex) {
+ for (const child of fs.readdirSync(dir)) {
+ const childPath = pjoin(dir, child);
+ const stat = fs.lstatSync(childPath);
+ if (skipRegex !== undefined && skipRegex.test(child)) continue;
+ if (stat.isDirectory()) {
+ walk(childPath, callback, skipRegex);
+ } else if (!stat.isSymbolicLink()) {
+ callback(childPath);
+ }
+ }
+}
+
+function ensureDir(dirPath, clean) {
+ const exists = fs.existsSync(dirPath);
+ if (exists && clean) {
+ console.log('rm', dirPath);
+ fs.rmSync(dirPath, {recursive: true});
+ }
+ if (!exists || clean) fs.mkdirSync(dirPath, {recursive: true});
+ return dirPath;
+}
+
+function cp(src, dst) {
+ ensureDir(path.dirname(dst));
+ if (cfg.verbose) {
+ console.log(
+ 'cp', path.relative(ROOT_DIR, src), '->', path.relative(ROOT_DIR, dst));
+ }
+ fs.copyFileSync(src, dst);
+}
+
+function mklink(src, dst) {
+ // If the symlink already points to the right place don't touch it. This is
+ // to avoid changing the mtime of the ui/ dir when unnecessary.
+ if (fs.existsSync(dst)) {
+ if (fs.lstatSync(dst).isSymbolicLink() && fs.readlinkSync(dst) === src) {
+ return;
+ } else {
+ fs.unlinkSync(dst);
+ }
+ }
+ fs.symlinkSync(src, dst);
+}
+
+main();
diff --git a/ui/config/gn_deprecation_banner.txt b/ui/config/gn_deprecation_banner.txt
new file mode 100644
index 0000000..06aed23
--- /dev/null
+++ b/ui/config/gn_deprecation_banner.txt
@@ -0,0 +1,6 @@
+[0;31m
+-------------------------------------------------------
+WARNING: building the UI through GN+ninja is deprecated.
+Going forward use the //ui/build script
+-------------------------------------------------------
+[0;0m
\ No newline at end of file
diff --git a/ui/jest.unit.config.js b/ui/config/jest.headless.config.js
similarity index 77%
copy from ui/jest.unit.config.js
copy to ui/config/jest.headless.config.js
index a58dcbf..723ab25 100644
--- a/ui/jest.unit.config.js
+++ b/ui/config/jest.headless.config.js
@@ -13,8 +13,9 @@
// limitations under the License.
module.exports = {
- "transform": {},
- "testRegex": "_unittest.js$",
- "testEnvironment": "node"
+ transform: {},
+ testRegex: '.*_headlesstest.js$',
+ globalSetup: './headless_setup.js',
+ globalTeardown: './headless_teardown.js',
+ testEnvironment: './headless_environment.js'
}
-
diff --git a/ui/jest.unit.config.js b/ui/config/jest.jsdom.config.js
similarity index 87%
rename from ui/jest.unit.config.js
rename to ui/config/jest.jsdom.config.js
index a58dcbf..dd07d83 100644
--- a/ui/jest.unit.config.js
+++ b/ui/config/jest.jsdom.config.js
@@ -13,8 +13,7 @@
// limitations under the License.
module.exports = {
- "transform": {},
- "testRegex": "_unittest.js$",
- "testEnvironment": "node"
+ transform: {},
+ testRegex: '_jsdomtest.js$',
+ testEnvironment: 'jsdom'
}
-
diff --git a/ui/jest.unit.config.js b/ui/config/jest.unit.config.js
similarity index 86%
copy from ui/jest.unit.config.js
copy to ui/config/jest.unit.config.js
index a58dcbf..a2ddb95 100644
--- a/ui/jest.unit.config.js
+++ b/ui/config/jest.unit.config.js
@@ -13,8 +13,8 @@
// limitations under the License.
module.exports = {
- "transform": {},
- "testRegex": "_unittest.js$",
- "testEnvironment": "node"
+ transform: {},
+ testRegex: '.*_unittest.js$',
+ testEnvironment: 'node',
+ verbose: true,
}
-
diff --git a/ui/config/rollup-serviceworker.config.js b/ui/config/rollup-serviceworker.config.js
new file mode 100644
index 0000000..b7aaf21
--- /dev/null
+++ b/ui/config/rollup-serviceworker.config.js
@@ -0,0 +1,41 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import commonjs from '@rollup/plugin-commonjs';
+import nodeResolve from '@rollup/plugin-node-resolve';
+import sourcemaps from 'rollup-plugin-sourcemaps';
+
+const path = require('path');
+const ROOT_DIR = path.dirname(path.dirname(__dirname)); // The repo root.
+const OUT_SYMLINK = path.join(ROOT_DIR, 'ui/out');
+
+export default [{
+ input: `${OUT_SYMLINK}/tsc/service_worker/service_worker.js`,
+ output: {
+ name: 'service_worker',
+ format: 'iife',
+ esModule: false,
+ file: `${OUT_SYMLINK}/dist/service_worker.js`,
+ sourcemap: true,
+ },
+ plugins: [
+ nodeResolve({
+ mainFields: ['browser'],
+ browser: true,
+ preferBuiltins: false,
+ }),
+ commonjs(),
+ sourcemaps(),
+ ],
+}]
diff --git a/ui/config/rollup.config.js b/ui/config/rollup.config.js
new file mode 100644
index 0000000..0055444
--- /dev/null
+++ b/ui/config/rollup.config.js
@@ -0,0 +1,68 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import commonjs from '@rollup/plugin-commonjs';
+import nodeResolve from '@rollup/plugin-node-resolve';
+import replace from 'rollup-plugin-re';
+import sourcemaps from 'rollup-plugin-sourcemaps';
+
+const path = require('path');
+const ROOT_DIR = path.dirname(path.dirname(__dirname)); // The repo root.
+const OUT_SYMLINK = path.join(ROOT_DIR, 'ui/out');
+
+function defBundle(bundle, distDir) {
+ return {
+ input: `${OUT_SYMLINK}/tsc/${bundle}/index.js`,
+ output: {
+ name: bundle,
+ format: 'iife',
+ esModule: false,
+ file: `${OUT_SYMLINK}/${distDir}/${bundle}_bundle.js`,
+ sourcemap: true,
+ },
+ plugins: [
+ nodeResolve({
+ mainFields: ['browser'],
+ browser: true,
+ preferBuiltins: false,
+ }),
+ // emscripten conditionally executes require('fs') (likewise for
+ // others), when running under node. Rollup can't find those libraries
+ // so expects these to be present in the global scope, which then fails
+ // at runtime. To avoid this we ignore require('fs') and the like.
+ commonjs({
+ ignore: [
+ 'fs',
+ 'path',
+ 'crypto',
+ ]
+ }),
+ // Protobufjs's inquire() uses eval but that's not really needed in
+ // the browser.
+ // See https://github.com/protobufjs/protobuf.js/issues/593
+ replace({
+ patterns: [{test: /eval\(.*\(moduleName\);/g, replace: 'undefined;'}]
+ }),
+ // Translate source maps to point back to the .ts sources.
+ sourcemaps(),
+ ],
+ };
+}
+
+export default [
+ defBundle('frontend', 'dist'),
+ defBundle('controller', 'dist'),
+ defBundle('engine', 'dist'),
+ defBundle('chrome_extension', 'chrome_extension'),
+]
diff --git a/ui/config/ui_tests_template b/ui/config/ui_tests_template
deleted file mode 100755
index be02a37..0000000
--- a/ui/config/ui_tests_template
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-DIR="$(dirname "${BASH_SOURCE[0]}")"
-
-exec ui/node ui/node_modules/jest/bin/jest.js \
- --projects=ui/jest.unit.config.js \
- --projects=ui/jest.jsdom.config.js \
- --projects=ui/jest.headless.config.js \
- --roots=../$DIR/obj/ui "${@:1}"
-
diff --git a/ui/config/ui_unittests_template b/ui/config/ui_unittests_template
deleted file mode 100755
index 8375151..0000000
--- a/ui/config/ui_unittests_template
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-DIR="$(dirname "${BASH_SOURCE[0]}")"
-
-exec ui/node ui/node_modules/jest/bin/jest.js \
- --projects=ui/jest.unit.config.js \
- --projects=ui/jest.jsdom.config.js \
- --roots=../$DIR/obj/ui ${@:1}
-
diff --git a/ui/deploy b/ui/deploy
index 8e11128..6eb0740 100755
--- a/ui/deploy
+++ b/ui/deploy
@@ -36,7 +36,7 @@
CLEAN_OUT_DIR=true
DEPLOY_PROD=false
DEPLOY_STAGING=false
-DEBUG_BUILD=false
+DEBUG_ARG=""
while [[ $# -gt 0 ]]; do
key="$1"
@@ -54,7 +54,7 @@
shift
;;
--debug)
- DEBUG_BUILD=true
+ DEBUG_ARG="--debug"
shift
;;
-h|--help)
@@ -75,13 +75,7 @@
fi
echo_and_do mkdir -p "$UI_DIST_DIR"
-if [ "$DEBUG_BUILD" = true ]; then
- echo_and_do "$PROJECT_ROOT/tools/gn" gen "$OUT_DIR" --args="is_debug=true"
-else
- echo_and_do "$PROJECT_ROOT/tools/gn" gen "$OUT_DIR" --args="is_debug=false"
-fi
-
-echo_and_do "$PROJECT_ROOT/tools/ninja" -C "$OUT_DIR" ui
+echo_and_do "$PROJECT_ROOT/ui/build" --out "$OUT_DIR" $DEBUG_ARG
echo "Writing $UI_DIST_DIR/app.yaml"
cat<<EOF > "$UI_DIST_DIR/app.yaml"
@@ -110,7 +104,7 @@
upload: static/(.*)
EOF
-echo_and_do ln -fs ../ui $UI_DIST_DIR/static
+echo_and_do rm -f $UI_DIST_DIR/static; ln -fs ../ui/dist $UI_DIST_DIR/static
(
echo_and_do cd "$UI_DIST_DIR";
diff --git a/ui/index.html b/ui/index.html
deleted file mode 100644
index ff1ad37..0000000
--- a/ui/index.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!doctype html>
-<html lang="en-us">
-<head>
- <title>Perfetto UI</title>
- <!-- See b/149573396 for CSP rationale. -->
- <!-- TODO(b/121211019): remove script-src-elem rule once fixed. -->
- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src-elem 'self' https://*.google.com https://*.googleusercontent.com https://www.googletagmanager.com https://www.google-analytics.com 'sha256-eYlPNiizBKy/rhHAaz06RXrXVsKmBN6tTFYwmJTvcwc='; object-src 'none'; connect-src 'self' http://127.0.0.1:9001 https://www.google-analytics.com https://*.googleapis.com blob: data:; img-src 'self' https://www.google-analytics.com https://www.googletagmanager.com; navigate-to https://*.perfetto.dev;">
- <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
- <link href="perfetto.css" rel="stylesheet">
- <link rel="icon" type="image/png" href="assets/favicon.png">
- <!-- Global site tag (gtag.js) - Google Analytics -->
- <script async src="https://www.googletagmanager.com/gtag/js?id=UA-137828855-1"></script>
-</head>
-<body>
- <main>
- <div class="full-page-loading-screen"></div>
- </main>
- <div id="main-modal" aria-hidden="true" class="modal micromodal-slide"></div>
-</body>
-</html>
-<script src="frontend_bundle.js"></script>
-<script src="https://storage.cloud.google.com/perfetto-ui-internal/is_internal_user.js" async defer></script>
diff --git a/ui/jest.headless.config.js b/ui/jest.headless.config.js
deleted file mode 100644
index e2487b8..0000000
--- a/ui/jest.headless.config.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-module.exports = {
- "transform": {},
- "testRegex": ".*_headlesstest.js$",
- "globalSetup": './config/headless_setup.js',
- "globalTeardown": './config/headless_teardown.js',
- "testEnvironment": "./config/headless_environment.js"
-}
-
diff --git a/ui/jest.jsdom.config.js b/ui/jest.jsdom.config.js
deleted file mode 100644
index 51c9ede..0000000
--- a/ui/jest.jsdom.config.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-module.exports = {
- "transform": {},
- "testRegex": "_jsdomtest.js$",
- "testEnvironment": "jsdom"
-}
-
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 5c47b71..9d805e9 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -5,28 +5,28 @@
"requires": true,
"dependencies": {
"@babel/code-frame": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
- "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
+ "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
"dev": true,
"requires": {
- "@babel/highlight": "^7.10.4"
+ "@babel/highlight": "^7.12.13"
}
},
"@babel/core": {
- "version": "7.12.10",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz",
- "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.13.tgz",
+ "integrity": "sha512-BQKE9kXkPlXHPeqissfxo0lySWJcYdEP0hdtJOH/iJfDdhOCcgtNCjftCJg3qqauB4h+lz2N6ixM++b9DN1Tcw==",
"dev": true,
"requires": {
- "@babel/code-frame": "^7.10.4",
- "@babel/generator": "^7.12.10",
- "@babel/helper-module-transforms": "^7.12.1",
- "@babel/helpers": "^7.12.5",
- "@babel/parser": "^7.12.10",
- "@babel/template": "^7.12.7",
- "@babel/traverse": "^7.12.10",
- "@babel/types": "^7.12.10",
+ "@babel/code-frame": "^7.12.13",
+ "@babel/generator": "^7.12.13",
+ "@babel/helper-module-transforms": "^7.12.13",
+ "@babel/helpers": "^7.12.13",
+ "@babel/parser": "^7.12.13",
+ "@babel/template": "^7.12.13",
+ "@babel/traverse": "^7.12.13",
+ "@babel/types": "^7.12.13",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.1",
@@ -36,19 +36,10 @@
"source-map": "^0.5.0"
},
"dependencies": {
- "debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "dev": true,
- "requires": {
- "ms": "2.1.2"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
},
"source-map": {
@@ -60,12 +51,12 @@
}
},
"@babel/generator": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz",
- "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==",
+ "version": "7.12.15",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.15.tgz",
+ "integrity": "sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.11",
+ "@babel/types": "^7.12.13",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
},
@@ -79,103 +70,103 @@
}
},
"@babel/helper-function-name": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz",
- "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz",
+ "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==",
"dev": true,
"requires": {
- "@babel/helper-get-function-arity": "^7.12.10",
- "@babel/template": "^7.12.7",
- "@babel/types": "^7.12.11"
+ "@babel/helper-get-function-arity": "^7.12.13",
+ "@babel/template": "^7.12.13",
+ "@babel/types": "^7.12.13"
}
},
"@babel/helper-get-function-arity": {
- "version": "7.12.10",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz",
- "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz",
+ "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.10"
+ "@babel/types": "^7.12.13"
}
},
"@babel/helper-member-expression-to-functions": {
- "version": "7.12.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz",
- "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.13.tgz",
+ "integrity": "sha512-B+7nN0gIL8FZ8SvMcF+EPyB21KnCcZHQZFczCxbiNGV/O0rsrSBlWGLzmtBJ3GMjSVMIm4lpFhR+VdVBuIsUcQ==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.7"
+ "@babel/types": "^7.12.13"
}
},
"@babel/helper-module-imports": {
- "version": "7.12.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz",
- "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz",
+ "integrity": "sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.5"
+ "@babel/types": "^7.12.13"
}
},
"@babel/helper-module-transforms": {
- "version": "7.12.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz",
- "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.13.tgz",
+ "integrity": "sha512-acKF7EjqOR67ASIlDTupwkKM1eUisNAjaSduo5Cz+793ikfnpe7p4Q7B7EWU2PCoSTPWsQkR7hRUWEIZPiVLGA==",
"dev": true,
"requires": {
- "@babel/helper-module-imports": "^7.12.1",
- "@babel/helper-replace-supers": "^7.12.1",
- "@babel/helper-simple-access": "^7.12.1",
- "@babel/helper-split-export-declaration": "^7.11.0",
- "@babel/helper-validator-identifier": "^7.10.4",
- "@babel/template": "^7.10.4",
- "@babel/traverse": "^7.12.1",
- "@babel/types": "^7.12.1",
+ "@babel/helper-module-imports": "^7.12.13",
+ "@babel/helper-replace-supers": "^7.12.13",
+ "@babel/helper-simple-access": "^7.12.13",
+ "@babel/helper-split-export-declaration": "^7.12.13",
+ "@babel/helper-validator-identifier": "^7.12.11",
+ "@babel/template": "^7.12.13",
+ "@babel/traverse": "^7.12.13",
+ "@babel/types": "^7.12.13",
"lodash": "^4.17.19"
}
},
"@babel/helper-optimise-call-expression": {
- "version": "7.12.10",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz",
- "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz",
+ "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.10"
+ "@babel/types": "^7.12.13"
}
},
"@babel/helper-plugin-utils": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
- "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz",
+ "integrity": "sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA==",
"dev": true
},
"@babel/helper-replace-supers": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz",
- "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.13.tgz",
+ "integrity": "sha512-pctAOIAMVStI2TMLhozPKbf5yTEXc0OJa0eENheb4w09SrgOWEs+P4nTOZYJQCqs8JlErGLDPDJTiGIp3ygbLg==",
"dev": true,
"requires": {
- "@babel/helper-member-expression-to-functions": "^7.12.7",
- "@babel/helper-optimise-call-expression": "^7.12.10",
- "@babel/traverse": "^7.12.10",
- "@babel/types": "^7.12.11"
+ "@babel/helper-member-expression-to-functions": "^7.12.13",
+ "@babel/helper-optimise-call-expression": "^7.12.13",
+ "@babel/traverse": "^7.12.13",
+ "@babel/types": "^7.12.13"
}
},
"@babel/helper-simple-access": {
- "version": "7.12.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz",
- "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.13.tgz",
+ "integrity": "sha512-0ski5dyYIHEfwpWGx5GPWhH35j342JaflmCeQmsPWcrOQDtCN6C1zKAVRFVbK53lPW2c9TsuLLSUDf0tIGJ5hA==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.1"
+ "@babel/types": "^7.12.13"
}
},
"@babel/helper-split-export-declaration": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz",
- "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz",
+ "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==",
"dev": true,
"requires": {
- "@babel/types": "^7.12.11"
+ "@babel/types": "^7.12.13"
}
},
"@babel/helper-validator-identifier": {
@@ -185,23 +176,23 @@
"dev": true
},
"@babel/helpers": {
- "version": "7.12.5",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz",
- "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.13.tgz",
+ "integrity": "sha512-oohVzLRZ3GQEk4Cjhfs9YkJA4TdIDTObdBEZGrd6F/T0GPSnuV6l22eMcxlvcvzVIPH3VTtxbseudM1zIE+rPQ==",
"dev": true,
"requires": {
- "@babel/template": "^7.10.4",
- "@babel/traverse": "^7.12.5",
- "@babel/types": "^7.12.5"
+ "@babel/template": "^7.12.13",
+ "@babel/traverse": "^7.12.13",
+ "@babel/types": "^7.12.13"
}
},
"@babel/highlight": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
- "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
+ "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
"dev": true,
"requires": {
- "@babel/helper-validator-identifier": "^7.10.4",
+ "@babel/helper-validator-identifier": "^7.12.11",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
},
@@ -259,9 +250,9 @@
}
},
"@babel/parser": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz",
- "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==",
+ "version": "7.12.15",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.15.tgz",
+ "integrity": "sha512-AQBOU2Z9kWwSZMd6lNjCX0GUgFonL1wAM1db8L8PMk9UDaGsRCArBkU4Sc+UCM3AE4hjbXx+h58Lb3QT4oRmrA==",
"dev": true
},
"@babel/plugin-syntax-async-generators": {
@@ -283,12 +274,12 @@
}
},
"@babel/plugin-syntax-class-properties": {
- "version": "7.12.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz",
- "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
+ "@babel/helper-plugin-utils": "^7.12.13"
}
},
"@babel/plugin-syntax-import-meta": {
@@ -364,54 +355,37 @@
}
},
"@babel/template": {
- "version": "7.12.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz",
- "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz",
+ "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==",
"dev": true,
"requires": {
- "@babel/code-frame": "^7.10.4",
- "@babel/parser": "^7.12.7",
- "@babel/types": "^7.12.7"
+ "@babel/code-frame": "^7.12.13",
+ "@babel/parser": "^7.12.13",
+ "@babel/types": "^7.12.13"
}
},
"@babel/traverse": {
- "version": "7.12.12",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz",
- "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.13.tgz",
+ "integrity": "sha512-3Zb4w7eE/OslI0fTp8c7b286/cQps3+vdLW3UcwC8VSJC6GbKn55aeVVu2QJNuCDoeKyptLOFrPq8WqZZBodyA==",
"dev": true,
"requires": {
- "@babel/code-frame": "^7.12.11",
- "@babel/generator": "^7.12.11",
- "@babel/helper-function-name": "^7.12.11",
- "@babel/helper-split-export-declaration": "^7.12.11",
- "@babel/parser": "^7.12.11",
- "@babel/types": "^7.12.12",
+ "@babel/code-frame": "^7.12.13",
+ "@babel/generator": "^7.12.13",
+ "@babel/helper-function-name": "^7.12.13",
+ "@babel/helper-split-export-declaration": "^7.12.13",
+ "@babel/parser": "^7.12.13",
+ "@babel/types": "^7.12.13",
"debug": "^4.1.0",
"globals": "^11.1.0",
"lodash": "^4.17.19"
- },
- "dependencies": {
- "debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "dev": true,
- "requires": {
- "ms": "2.1.2"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- }
}
},
"@babel/types": {
- "version": "7.12.12",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz",
- "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==",
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.13.tgz",
+ "integrity": "sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.12.11",
@@ -501,32 +475,6 @@
"rimraf": "^3.0.0",
"slash": "^3.0.0",
"strip-ansi": "^6.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
- "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
- "dev": true
- },
- "rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dev": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "strip-ansi": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
- "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
- "dev": true,
- "requires": {
- "ansi-regex": "^5.0.0"
- }
- }
}
},
"@jest/environment": {
@@ -765,9 +713,9 @@
}
},
"@sinonjs/commons": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz",
- "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==",
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz",
+ "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==",
"dev": true,
"requires": {
"type-detect": "4.0.8"
@@ -868,11 +816,6 @@
"@types/node": "*"
}
},
- "@types/gtag.js": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.3.tgz",
- "integrity": "sha512-iRF/4Q3G1t0OTNMjK52tpGSQPgEsYzWQL1IdVXt9BywK6MUK3ypB7LaoEQa8sW9gPXENoU1xAyCxqJhMkB2rCA=="
- },
"@types/istanbul-lib-coverage": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
@@ -915,9 +858,9 @@
"integrity": "sha512-U/wwKZT8hjstY2Q470bLMGVh/fjT2+SgBMzIILn0Z4nmgzzG6j+n18UOAxQ63aI8vXIOkQsbkAdbESt8+jIQdQ=="
},
"@types/node": {
- "version": "14.14.20",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz",
- "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A=="
+ "version": "14.14.25",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz",
+ "integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ=="
},
"@types/normalize-package-data": {
"version": "2.4.0",
@@ -971,9 +914,9 @@
"integrity": "sha512-aaOB3EL5WCWBBOYX7W1MKuzspOM9ZJI9s3iziRVypr1N+QyvIgXzCM4lm1iiOQ1VFzZioUPX9bsa23myCbKK4A=="
},
"@types/yargs": {
- "version": "15.0.12",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.12.tgz",
- "integrity": "sha512-f+fD/fQAo3BCbCDlrUpznF1A5Zp9rB0noS5vnoormHSIPFKL0Z2DcUJ3Gxp5ytH4uLRNxy7AwYUC9exZzqGMAw==",
+ "version": "15.0.13",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz",
+ "integrity": "sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ==",
"dev": true,
"requires": {
"@types/yargs-parser": "*"
@@ -1072,9 +1015,9 @@
}
},
"ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"ansi-styles": {
@@ -1444,14 +1387,6 @@
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
- "bufferutil": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz",
- "integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==",
- "requires": {
- "node-gyp-build": "^4.2.0"
- }
- },
"builtin-modules": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz",
@@ -1476,9 +1411,9 @@
}
},
"call-bind": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.1.tgz",
- "integrity": "sha512-tvAvUwNcRikl3RVF20X9lsYmmepsovzTWeJiXjO0PkJp15uy/6xKFZOQtuiSULwYW+6ToZBprphCgWXC2dSgcQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
@@ -1514,17 +1449,6 @@
}
}
},
- "canvas": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.6.1.tgz",
- "integrity": "sha512-S98rKsPcuhfTcYbtF53UIJhcbgIAK533d1kJKMwsMwAIFgfd58MOyxRud3kktlzWiEkFliaJtvyZCBtud/XVEA==",
- "dev": true,
- "requires": {
- "nan": "^2.14.0",
- "node-pre-gyp": "^0.11.0",
- "simple-get": "^3.0.3"
- }
- },
"capture-exit": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",
@@ -1550,12 +1474,6 @@
"supports-color": "^7.1.0"
}
},
- "chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "dev": true
- },
"ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
@@ -1594,40 +1512,6 @@
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
- "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true
- },
- "string-width": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
- "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
- "dev": true,
- "requires": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.0"
- }
- },
- "strip-ansi": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
- "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
- "dev": true,
- "requires": {
- "ansi-regex": "^5.0.0"
- }
- }
}
},
"co": {
@@ -1764,6 +1648,12 @@
"which": "^1.2.9"
},
"dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
@@ -1831,12 +1721,12 @@
}
},
"debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+ "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"requires": {
- "ms": "^2.1.1"
+ "ms": "2.1.2"
}
},
"decamelize": {
@@ -1851,21 +1741,6 @@
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
"dev": true
},
- "decompress-response": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
- "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
- "dev": true,
- "requires": {
- "mimic-response": "^2.0.0"
- }
- },
- "deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "dev": true
- },
"deep-freeze": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz",
@@ -1945,12 +1820,6 @@
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
"dev": true
},
- "detect-libc": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
- "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
- "dev": true
- },
"detect-newline": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
@@ -2024,22 +1893,24 @@
}
},
"es-abstract": {
- "version": "1.18.0-next.1",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
- "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
+ "version": "1.18.0-next.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz",
+ "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==",
"requires": {
+ "call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
- "is-negative-zero": "^2.0.0",
+ "is-negative-zero": "^2.0.1",
"is-regex": "^1.1.1",
- "object-inspect": "^1.8.0",
+ "object-inspect": "^1.9.0",
"object-keys": "^1.1.1",
- "object.assign": "^4.1.1",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
+ "object.assign": "^4.1.2",
+ "string.prototype.trimend": "^1.0.3",
+ "string.prototype.trimstart": "^1.0.3"
}
},
"es-to-primitive": {
@@ -2425,15 +2296,6 @@
"map-cache": "^0.2.2"
}
},
- "fs-minipass": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
- "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
- "dev": true,
- "requires": {
- "minipass": "^2.6.0"
- }
- },
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -2441,9 +2303,9 @@
"dev": true
},
"fsevents": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz",
- "integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
@@ -2457,6 +2319,17 @@
"inherits": "~2.0.0",
"mkdirp": ">=0.5 0",
"rimraf": "2"
+ },
+ "dependencies": {
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ }
}
},
"function-bind": {
@@ -2478,6 +2351,43 @@
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wide-align": "^1.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
}
},
"gaze": {
@@ -2502,9 +2412,9 @@
"dev": true
},
"get-intrinsic": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz",
- "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
@@ -2579,9 +2489,9 @@
}
},
"graceful-fs": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
- "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.5.tgz",
+ "integrity": "sha512-kBBSQbz2K0Nyn+31j/w36fUfxkBW9/gfwRWdUY1ULReH3iokVJgddZAFcD1D0xlgTmFxJCbUkUclAlc6/IDJkw==",
"dev": true
},
"growly": {
@@ -2622,6 +2532,14 @@
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ }
}
},
"has-flag": {
@@ -2733,6 +2651,17 @@
"requires": {
"agent-base": "^4.3.0",
"debug": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
}
},
"human-signals": {
@@ -2750,15 +2679,6 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
- "ignore-walk": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
- "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
- "dev": true,
- "requires": {
- "minimatch": "^3.0.4"
- }
- },
"immer": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-1.12.1.tgz",
@@ -2810,12 +2730,6 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
- "ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "dev": true
- },
"ip-regex": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
@@ -2863,9 +2777,9 @@
"dev": true
},
"is-callable": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz",
- "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA=="
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
+ "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ=="
},
"is-ci": {
"version": "2.0.0",
@@ -2949,13 +2863,10 @@
"dev": true
},
"is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "dev": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
},
"is-generator-fn": {
"version": "2.1.0",
@@ -3004,10 +2915,11 @@
}
},
"is-regex": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
- "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz",
+ "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==",
"requires": {
+ "call-bind": "^1.0.2",
"has-symbols": "^1.0.1"
}
},
@@ -3105,14 +3017,6 @@
"@istanbuljs/schema": "^0.1.2",
"istanbul-lib-coverage": "^3.0.0",
"semver": "^6.3.0"
- },
- "dependencies": {
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true
- }
}
},
"istanbul-lib-report": {
@@ -3135,23 +3039,6 @@
"debug": "^4.1.1",
"istanbul-lib-coverage": "^3.0.0",
"source-map": "^0.6.1"
- },
- "dependencies": {
- "debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "dev": true,
- "requires": {
- "ms": "2.1.2"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- }
}
},
"istanbul-reports": {
@@ -3379,14 +3266,6 @@
"jest-mock": "^25.5.0",
"jest-util": "^25.5.0",
"semver": "^6.3.0"
- },
- "dependencies": {
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true
- }
}
},
"jest-get-type": {
@@ -3619,14 +3498,6 @@
"natural-compare": "^1.4.0",
"pretty-format": "^25.5.0",
"semver": "^6.3.0"
- },
- "dependencies": {
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true
- }
}
},
"jest-util": {
@@ -3773,9 +3644,9 @@
"dev": true
},
"json5": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
- "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+ "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
@@ -3913,14 +3784,6 @@
"requires": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
- },
- "dependencies": {
- "yallist": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
- "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
- "dev": true
- }
}
},
"magic-string": {
@@ -3939,14 +3802,6 @@
"dev": true,
"requires": {
"semver": "^6.0.0"
- },
- "dependencies": {
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true
- }
}
},
"makeerror": {
@@ -4061,9 +3916,9 @@
"integrity": "sha512-2VDso2a22jWPpqwuWT/4RomVpoU3Bl9qF9D01xzwlNp5UVsImeA0gY4nSpF44vqcQtQOtkiMUV9EZkAJSRxBsg=="
},
"mime": {
- "version": "2.4.7",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.7.tgz",
- "integrity": "sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==",
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz",
+ "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==",
"dev": true
},
"mime-db": {
@@ -4087,12 +3942,6 @@
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true
},
- "mimic-response": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
- "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
- "dev": true
- },
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -4108,25 +3957,6 @@
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
- "minipass": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
- "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
- "dev": true,
- "requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
- }
- },
- "minizlib": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
- "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
- "dev": true,
- "requires": {
- "minipass": "^2.9.0"
- }
- },
"mithril": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/mithril/-/mithril-2.0.4.tgz",
@@ -4163,9 +3993,9 @@
}
},
"ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"nan": {
@@ -4199,17 +4029,6 @@
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true
},
- "needle": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz",
- "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==",
- "dev": true,
- "requires": {
- "debug": "^3.2.6",
- "iconv-lite": "^0.4.4",
- "sax": "^1.2.4"
- }
- },
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@@ -4236,13 +4055,13 @@
"which": "1"
},
"dependencies": {
- "nopt": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
- "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"dev": true,
"requires": {
- "abbrev": "1"
+ "glob": "^7.1.3"
}
},
"semver": {
@@ -4251,17 +4070,6 @@
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
"dev": true
},
- "tar": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
- "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
- "dev": true,
- "requires": {
- "block-stream": "*",
- "fstream": "^1.0.12",
- "inherits": "2"
- }
- },
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
@@ -4273,11 +4081,6 @@
}
}
},
- "node-gyp-build": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz",
- "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg=="
- },
"node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -4304,13 +4107,6 @@
"which": "^1.3.1"
},
"dependencies": {
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true,
- "optional": true
- },
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
@@ -4323,24 +4119,6 @@
}
}
},
- "node-pre-gyp": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz",
- "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==",
- "dev": true,
- "requires": {
- "detect-libc": "^1.0.2",
- "mkdirp": "^0.5.1",
- "needle": "^2.2.1",
- "nopt": "^4.0.1",
- "npm-packlist": "^1.1.6",
- "npmlog": "^4.0.2",
- "rc": "^1.2.7",
- "rimraf": "^2.6.1",
- "semver": "^5.3.0",
- "tar": "^4"
- }
- },
"node-sass": {
"version": "4.14.1",
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz",
@@ -4366,6 +4144,12 @@
"true-case-path": "^1.0.2"
},
"dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
@@ -4395,6 +4179,15 @@
"which": "^1.2.9"
}
},
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
@@ -4418,13 +4211,12 @@
"integrity": "sha512-Wm+otW+drKzdqlSPoSwj34tUEq/Xj1gX6Cr2avrykvTW4IY7d3ngLmP+PErALzS0s9nYRokXvYDM54sbFvLlDA=="
},
"nopt": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
- "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
"dev": true,
"requires": {
- "abbrev": "1",
- "osenv": "^0.1.4"
+ "abbrev": "1"
}
},
"normalize-package-data": {
@@ -4437,6 +4229,14 @@
"resolve": "^1.10.0",
"semver": "2 || 3 || 4 || 5",
"validate-npm-package-license": "^3.0.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
}
},
"normalize-path": {
@@ -4445,32 +4245,6 @@
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
- "npm-bundled": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
- "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
- "dev": true,
- "requires": {
- "npm-normalize-package-bin": "^1.0.1"
- }
- },
- "npm-normalize-package-bin": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
- "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
- "dev": true
- },
- "npm-packlist": {
- "version": "1.4.8",
- "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
- "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
- "dev": true,
- "requires": {
- "ignore-walk": "^3.0.1",
- "npm-bundled": "^1.0.1",
- "npm-normalize-package-bin": "^1.0.1"
- }
- },
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -4682,9 +4456,9 @@
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
},
"parse-json": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz",
- "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
@@ -4878,9 +4652,9 @@
},
"dependencies": {
"@types/node": {
- "version": "13.13.39",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.39.tgz",
- "integrity": "sha512-wct+WgRTTkBm2R3vbrFOqyZM5w0g+D8KnhstG9463CJBVC3UVZHMToge7iMBR1vDl/I+NWFHUeK9X+JcF0rWKw=="
+ "version": "13.13.41",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.41.tgz",
+ "integrity": "sha512-qLT9IvHiXJfdrje9VmsLzun7cQ65obsBTmtU3EOnCSLFOoSHx1hpiRHoBnpdbyFqnzqdUUIv81JcEJQCB8un9g=="
}
}
},
@@ -4934,21 +4708,15 @@
"ws": "^6.1.0"
},
"dependencies": {
- "debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"dev": true,
"requires": {
- "ms": "2.1.2"
+ "glob": "^7.1.3"
}
},
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
"ws": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
@@ -4966,18 +4734,6 @@
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
"dev": true
},
- "rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "dev": true,
- "requires": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- }
- },
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -5213,29 +4969,80 @@
"dev": true
},
"rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"rollup": {
- "version": "2.36.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.36.1.tgz",
- "integrity": "sha512-eAfqho8dyzuVvrGqpR0ITgEdq0zG2QJeWYh+HeuTbpcaXk8vNFc48B7bJa1xYosTCKx0CuW+447oQOW8HgBIZQ==",
+ "version": "2.38.5",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.5.tgz",
+ "integrity": "sha512-VoWt8DysFGDVRGWuHTqZzT02J0ASgjVq/hPs9QcBOGMd7B+jfTr/iqMVEyOi901rE3xq+Deq66GzIT1yt7sGwQ==",
"dev": true,
"requires": {
- "fsevents": "~2.1.2"
+ "fsevents": "~2.3.1"
+ }
+ },
+ "rollup-plugin-re": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-re/-/rollup-plugin-re-1.0.7.tgz",
+ "integrity": "sha1-/hdHBO1ZzahMrwK9ATtYLm/apPY=",
+ "dev": true,
+ "requires": {
+ "magic-string": "^0.16.0",
+ "rollup-pluginutils": "^2.0.1"
},
"dependencies": {
- "fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+ "magic-string": {
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.16.0.tgz",
+ "integrity": "sha1-lw67DacZMwEoX7GqZQ85vdgetFo=",
"dev": true,
- "optional": true
+ "requires": {
+ "vlq": "^0.2.1"
+ }
+ }
+ }
+ },
+ "rollup-plugin-sourcemaps": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz",
+ "integrity": "sha512-paFu+nT1xvuO1tPFYXGe+XnQvg4Hjqv/eIhG8i5EspfYYPBKL57X7iVbfv55aNVASg3dzWvES9dmWsL2KhfByw==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^3.0.9",
+ "source-map-resolve": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map-resolve": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
+ "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
+ "dev": true,
+ "requires": {
+ "atob": "^2.1.2",
+ "decode-uri-component": "^0.2.0"
+ }
+ }
+ }
+ },
+ "rollup-pluginutils": {
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
+ "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
+ "dev": true,
+ "requires": {
+ "estree-walker": "^0.6.1"
+ },
+ "dependencies": {
+ "estree-walker": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
+ "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
+ "dev": true
}
}
},
@@ -5265,26 +5072,6 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
- "sander": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz",
- "integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=",
- "dev": true,
- "requires": {
- "es6-promise": "^3.1.2",
- "graceful-fs": "^4.1.3",
- "mkdirp": "^0.5.1",
- "rimraf": "^2.5.2"
- },
- "dependencies": {
- "es6-promise": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
- "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
- "dev": true
- }
- }
- },
"sane": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz",
@@ -5438,12 +5225,6 @@
"yargs": "^13.3.2"
},
"dependencies": {
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
- "dev": true
- },
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@@ -5586,12 +5367,6 @@
}
}
},
- "sax": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
- "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
- "dev": true
- },
"saxes": {
"version": "3.1.11",
"resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz",
@@ -5623,9 +5398,9 @@
}
},
"semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
},
"set-blocking": {
@@ -5685,23 +5460,6 @@
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
- "simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "dev": true
- },
- "simple-get": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
- "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
- "dev": true,
- "requires": {
- "decompress-response": "^4.2.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
"sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@@ -5842,18 +5600,6 @@
}
}
},
- "sorcery": {
- "version": "0.10.0",
- "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
- "integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=",
- "dev": true,
- "requires": {
- "buffer-crc32": "^0.2.5",
- "minimist": "^1.2.0",
- "sander": "^0.5.0",
- "sourcemap-codec": "^1.3.0"
- }
- },
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -5884,9 +5630,9 @@
}
},
"source-map-url": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
- "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
+ "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
"dev": true
},
"sourcemap-codec": {
@@ -6022,12 +5768,6 @@
"strip-ansi": "^5.2.0"
},
"dependencies": {
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
- "dev": true
- },
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
@@ -6040,14 +5780,14 @@
}
},
"string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+ "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"dev": true,
"requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
}
},
"string.prototype.trimend": {
@@ -6086,12 +5826,20 @@
}
},
"strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
"requires": {
- "ansi-regex": "^2.0.0"
+ "ansi-regex": "^5.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ }
}
},
"strip-bom": {
@@ -6121,12 +5869,6 @@
"get-stdin": "^4.0.1"
}
},
- "strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
- "dev": true
- },
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -6153,18 +5895,14 @@
"dev": true
},
"tar": {
- "version": "4.4.13",
- "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
- "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
+ "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
"dev": true,
"requires": {
- "chownr": "^1.1.1",
- "fs-minipass": "^1.2.5",
- "minipass": "^2.8.6",
- "minizlib": "^1.2.1",
- "mkdirp": "^0.5.0",
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.3"
+ "block-stream": "*",
+ "fstream": "^1.0.12",
+ "inherits": "2"
}
},
"terminal-link": {
@@ -6356,6 +6094,12 @@
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -6506,14 +6250,6 @@
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
"dev": true
},
- "utf-8-validate": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz",
- "integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==",
- "requires": {
- "node-gyp-build": "^4.2.0"
- }
- },
"util": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz",
@@ -6578,6 +6314,12 @@
"extsprintf": "^1.2.0"
}
},
+ "vlq": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
+ "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==",
+ "dev": true
+ },
"w3c-hr-time": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
@@ -6675,6 +6417,39 @@
"dev": true,
"requires": {
"string-width": "^1.0.2 || 2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
}
},
"word-wrap": {
@@ -6692,40 +6467,6 @@
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
- "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true
- },
- "string-width": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
- "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
- "dev": true,
- "requires": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.0"
- }
- },
- "strip-ansi": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
- "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
- "dev": true,
- "requires": {
- "ansi-regex": "^5.0.0"
- }
- }
}
},
"wrappy": {
@@ -6747,9 +6488,9 @@
}
},
"ws": {
- "version": "7.4.2",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz",
- "integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==",
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz",
+ "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==",
"dev": true
},
"xml-name-validator": {
@@ -6771,9 +6512,9 @@
"dev": true
},
"yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
"dev": true
},
"yargs": {
@@ -6793,40 +6534,6 @@
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
- "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true
- },
- "string-width": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
- "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
- "dev": true,
- "requires": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.0"
- }
- },
- "strip-ansi": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
- "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
- "dev": true,
- "requires": {
- "ansi-regex": "^5.0.0"
- }
- }
}
},
"yargs-parser": {
diff --git a/ui/package.json b/ui/package.json
index 955a33c..0013cae 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -10,13 +10,11 @@
"@tsundoku/micromodal_types": "^0.0.1",
"@types/chrome": "0.0.86",
"@types/color-convert": "^1.9.0",
- "@types/gtag.js": "0.0.3",
"@types/mithril": "^1.1.17",
"@types/node": "^14.0.10",
"@types/pako": "^1.0.1",
"@types/uuid": "^3.4.9",
"@types/w3c-web-usb": "^1.0.4",
- "bufferutil": "^4.0.1",
"color-convert": "^2.0.1",
"custom_utils": "file:src/base/utils",
"devtools-protocol": "0.0.681549",
@@ -27,7 +25,6 @@
"noice-json-rpc": "^1.2.0",
"pako": "^1.0.11",
"protobufjs": "^6.9.0",
- "utf-8-validate": "^5.0.2",
"util": "^0.12.3",
"uuid": "^3.4.0"
},
@@ -40,11 +37,15 @@
"jest": "^25.5.4",
"node-sass": "^4.14.1",
"puppeteer": "^1.20.0",
- "rollup": "^2.3.4",
- "sorcery": "^0.10.0",
+ "rollup": "^2.38.5",
+ "rollup-plugin-re": "^1.0.7",
+ "rollup-plugin-sourcemaps": "^0.6.3",
"tslib": "^1.13.0",
"tslint": "^5.20.1",
- "typescript": "^3.9.3",
- "canvas": "^2.6.1"
+ "typescript": "^3.9.3"
+ },
+ "scripts": {
+ "build": "node build.js",
+ "test": "node build.js --run-tests"
}
}
diff --git a/ui/query.html b/ui/query.html
deleted file mode 100644
index bd45758..0000000
--- a/ui/query.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!doctype html>
-<html lang="en-us">
-<head>
- <title>Perfetto - Query</title>
- <link rel="icon" type="image/png" href="assets/favicon.png">
- <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
- <style>
- * {
- box-sizing: border-box;
- }
-
- #root {
- margin: 0 auto;
- max-width: 1200px;
- }
-
- input[type=text] {
- font-size: 150%;
- width: 100%;
- }
-
- .query-list {
- }
-
- .query {
- margin: 2rem 0;
- border-left: 10px grey;
- display: grid;
- grid-template: "text time"
- "content content";
- }
-
- .query-content {
- grid-area: content;
- }
-
- .query-content:empty {
- background: grey;
- }
-
- .query-text {
- grid-area: text;
- font-family: monospace;
- }
-
- .query-time{
- grid-area: time;
- }
-
- table {
- width: 100%;
- margin-left: -1rem;
- }
-
- tr {
- }
-
- tr:hover {
- background-color: #0000000a;
- }
-
- th {
- font-weight: normal;
- font-style: italic;
- }
-
- td {
- padding: 0.25rem 0.25rem;
- }
-
- tr > td:first-child {
- padding-left: 1rem;
- }
-
- tr > td:last-child {
- padding-right: 1rem;
- }
- </style>
-</head>
-<body>
- <div id="root"></div>
- <script src="/query_bundle.js"></script>
-</body>
-</html>
diff --git a/ui/rollup.config.js b/ui/rollup.config.js
deleted file mode 100644
index 421e494..0000000
--- a/ui/rollup.config.js
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import commonjs from '@rollup/plugin-commonjs';
-import nodeResolve from '@rollup/plugin-node-resolve';
-
-export default {
- output: {name: 'perfetto'},
- plugins:
- [
- nodeResolve({
- mainFields: ['browser'],
- browser: true,
- preferBuiltins: false,
- }),
-
- // emscripten conditionally executes require('fs') (likewise for
- // others), when running under node. Rollup can't find those libraries
- // so expects these to be present in the global scope, which then fails
- // at runtime. To avoid this we ignore require('fs') and the like.
- commonjs({
- ignore: [
- 'fs',
- 'path',
- 'crypto',
- ]
- }),
- ],
-}
diff --git a/ui/run-dev-server b/ui/run-dev-server
index 9faf567..6de8927 100755
--- a/ui/run-dev-server
+++ b/ui/run-dev-server
@@ -14,34 +14,4 @@
# limitations under the License.
UI_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
-ROOT_DIR=$(dirname "$UI_DIR")
-
-if [ -z "$1" ]; then
- echo "ERROR: no output directory specified."
- echo "Usage: $0 out/mac_debug"
- exit 127
-fi
-OUT_DIR="$1"
-
-echo 'Initial build:'
-$ROOT_DIR/tools/ninja -C $OUT_DIR ui
-
-UI_OUT_DIR="$OUT_DIR/ui"
-if [ ! -d $UI_OUT_DIR ]; then
- echo "ERROR: cannot find the UI output directory (\"$UI_OUT_DIR\")."
- echo "Did you run ninja ui?"
- exit 127
-fi
-
-$ROOT_DIR/tools/dev_server \
- -p 10000 \
- -i $ROOT_DIR/.git \
- -i $ROOT_DIR/src/traced \
- -i $ROOT_DIR/buildtools \
- -i $ROOT_DIR/out \
- -i $ROOT_DIR/infra \
- -i $ROOT_DIR/ui/node_modules \
- -s $UI_OUT_DIR \
- "$ROOT_DIR/tools/ninja -C $OUT_DIR ui"
-
-
+$UI_DIR/node $UI_DIR/build.js --serve --watch
diff --git a/ui/run-tests b/ui/run-tests
new file mode 100755
index 0000000..d06f7d2
--- /dev/null
+++ b/ui/run-tests
@@ -0,0 +1,18 @@
+#!/bin/bash
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+UI_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
+
+$UI_DIR/node $UI_DIR/build.js --run-tests "$@"
diff --git a/ui/src/assets/index.html b/ui/src/assets/index.html
new file mode 100644
index 0000000..3237423
--- /dev/null
+++ b/ui/src/assets/index.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html lang="en-us">
+<head>
+ <title>Perfetto UI</title>
+ <!-- See b/149573396 for CSP rationale. -->
+ <!-- TODO(b/121211019): remove script-src-elem rule once fixed. -->
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self' 'sha256-LirUKeorCU4uRNtNzr8tlB11uy8rzrdmqHCX38JSwHY='; script-src 'self' https://*.google.com https://*.googleusercontent.com https://www.googletagmanager.com https://www.google-analytics.com; object-src 'none'; connect-src 'self' http://127.0.0.1:9001 https://www.google-analytics.com https://*.googleapis.com blob: data:; img-src 'self' data: blob: https://www.google-analytics.com https://www.googletagmanager.com; navigate-to https://*.perfetto.dev;">
+
+ <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
+ <link href="perfetto.css" rel="stylesheet">
+ <link rel="icon" type="image/png" href="assets/favicon.png">
+</head>
+<body>
+ <main>
+ <div class="full-page-loading-screen"></div>
+ </main>
+ <div id="main-modal" aria-hidden="true" class="modal micromodal-slide"></div>
+</body>
+</html>
+<script src="frontend_bundle.js"></script>
diff --git a/ui/src/frontend/analytics.ts b/ui/src/frontend/analytics.ts
index dc6f051..5abf7ed 100644
--- a/ui/src/frontend/analytics.ts
+++ b/ui/src/frontend/analytics.ts
@@ -19,20 +19,37 @@
export function initAnalytics() {
// Only initialize logging on prod or staging
- if (window.location.origin.endsWith('.perfetto.dev') ||
+ if (window.location.origin.startsWith('http://localhost:') ||
+ window.location.origin.endsWith('.perfetto.dev') ||
window.location.origin.endsWith('staging-dot-perfetto-ui.appspot.com')) {
- return new Analytics();
+ return new AnalyticsImpl();
}
return new NullAnalytics();
}
-export class NullAnalytics {
+const gtagGlobals = window as {} as {
+ // tslint:disable-next-line no-any
+ dataLayer: any[];
+ gtag: (command: string, event: string|Date, args?: {}) => void;
+};
+
+export interface Analytics {
+ initialize(): void;
+ updatePath(_: string): void;
+ logEvent(_x: TraceCategories|null, _y: string): void;
+ logError(_x: string, _y?: boolean): void;
+}
+
+export class NullAnalytics implements Analytics {
+ initialize() {}
updatePath(_: string) {}
logEvent(_x: TraceCategories|null, _y: string) {}
logError(_x: string) {}
}
-export class Analytics {
+class AnalyticsImpl implements Analytics {
+ private initialized_ = false;
+
constructor() {
// The code below is taken from the official Google Analytics docs [1] and
// adapted to TypeScript. We have it here rather than as an inline script
@@ -40,31 +57,54 @@
// play nicely with the CSP policy, at least in Firefox (Firefox doesn't
// support all CSP 3 features we use).
// [1] https://developers.google.com/analytics/devguides/collection/gtagjs .
- const gtagGlobals = window as {} as {
- dataLayer: IArguments[],
- gtag: () => void,
- };
gtagGlobals.dataLayer = gtagGlobals.dataLayer || [];
- if (gtagGlobals.gtag === undefined) {
- gtagGlobals.gtag = () => gtagGlobals.dataLayer.push(arguments);
+
+ // tslint:disable-next-line no-any
+ function gtagFunction(..._: any[]) {
+ // This needs to be a function and not a lambda. |arguments| behaves
+ // slightly differently in a lambda and breaks GA.
+ gtagGlobals.dataLayer.push(arguments);
}
- gtag('js', new Date());
+ gtagGlobals.gtag = gtagFunction;
+ gtagGlobals.gtag('js', new Date());
+ }
+
+ // This is callled only after the script that sets isInternalUser loads.
+ // It is fine to call updatePath() and log*() functions before initialize().
+ // The gtag() function internally enqueues all requests into |dataLayer|.
+ initialize() {
+ if (this.initialized_) return;
+ this.initialized_ = true;
+ const script = document.createElement('script');
+ script.src = 'https://www.googletagmanager.com/gtag/js?id=' + ANALYTICS_ID;
+ script.defer = true;
+ document.head.appendChild(script);
+ const route = globals.state.route || '/';
+ console.log(
+ `GA initialized. route=${route}`,
+ `isInternalUser=${globals.isInternalUser}`);
+ // GA's reccomendation for SPAs is to disable automatic page views and
+ // manually send page_view events. See:
+ // https://developers.google.com/analytics/devguides/collection/gtagjs/pages#manual_pageviews
+ gtagGlobals.gtag('config', ANALYTICS_ID, {
+ anonymize_ip: true,
+ page_path: route,
+ referrer: document.referrer.split('?')[0],
+ send_page_view: false,
+ dimension1: globals.isInternalUser ? '1' : '0',
+ });
+ this.updatePath(route);
}
updatePath(path: string) {
- gtag('config', ANALYTICS_ID, {
- 'anonymize_ip': true,
- 'page_path': path,
- 'referrer': document.referrer.split('?')[0],
- 'dimension1': globals.isInternalUser,
- });
+ gtagGlobals.gtag('event', 'page_view', {page_path: path});
}
logEvent(category: TraceCategories|null, event: string) {
- gtag('event', event, {'event_category': category});
+ gtagGlobals.gtag('event', event, {event_category: category});
}
logError(description: string, fatal = true) {
- gtag('event', 'exception', {description, fatal});
+ gtagGlobals.gtag('event', 'exception', {description, fatal});
}
}
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 2962bf5..38bd7a9 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -136,6 +136,7 @@
private _rafScheduler?: RafScheduler = undefined;
private _serviceWorkerController?: ServiceWorkerController = undefined;
private _logging?: Analytics = undefined;
+ private _isInternalUser: boolean|undefined = undefined;
// TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
private _trackDataStore?: TrackDataStore = undefined;
@@ -172,11 +173,6 @@
count: new Uint8Array(0),
};
- // This variable is set by the is_internal_user.js script if the user is a
- // googler. This is used to avoid exposing features that are not ready yet
- // for public consumption. The gated features themselves are not secret.
- isInternalUser = false;
-
initialize(dispatch: Dispatch, controllerWorker: Worker) {
this._dispatch = dispatch;
this._controllerWorker = controllerWorker;
@@ -430,6 +426,24 @@
};
}
+ // This variable is set by the is_internal_user.js script if the user is a
+ // googler. This is used to avoid exposing features that are not ready yet
+ // for public consumption. The gated features themselves are not secret.
+ // If a user has been detected as a Googler once, make that sticky in
+ // localStorage, so that we keep treating them as such when they connect over
+ // public networks.
+ get isInternalUser() {
+ if (this._isInternalUser === undefined) {
+ this._isInternalUser = localStorage.getItem('isInternalUser') === '1';
+ }
+ return this._isInternalUser;
+ }
+
+ set isInternalUser(value: boolean) {
+ localStorage.setItem('isInternalUser', value ? '1' : '0');
+ this._isInternalUser = value;
+ }
+
// Used when switching to the legacy TraceViewer UI.
// Most resources are cleaned up by replacing the current |window| object,
// however pending RAFs and workers seem to outlive the |window| and need to
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index d4cb2da..a2ba0ac 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -47,6 +47,7 @@
} from './globals';
import {HomePage} from './home_page';
import {openBufferWithLegacyTraceViewer} from './legacy_trace_viewer';
+import {initLiveReloadIfLocalhost} from './live_reload';
import {MetricsPage} from './metrics_page';
import {postMessageHandler} from './post_message_handler';
import {RecordPage, updateAvailableAdbDevices} from './record_page';
@@ -398,10 +399,22 @@
MicroModal.init();
+ // Load the script to detect if this is a Googler (see comments on globals.ts)
+ // and initialize GA after that (or after a timeout if something goes wrong).
+ const script = document.createElement('script');
+ script.src =
+ 'https://storage.cloud.google.com/perfetto-ui-internal/is_internal_user.js';
+ script.async = true;
+ script.onerror = () => globals.logging.initialize();
+ script.onload = () => globals.logging.initialize();
+ setTimeout(() => globals.logging.initialize(), 5000);
+ document.head.appendChild(script);
+
// Will update the chip on the sidebar footer that notifies that the RPC is
// connected. Has no effect on the controller (which will repeat this check
// before creating a new engine).
CheckHttpRpcConnection();
+ initLiveReloadIfLocalhost();
}
main();
diff --git a/ui/src/frontend/live_reload.ts b/ui/src/frontend/live_reload.ts
new file mode 100644
index 0000000..c30b6e0
--- /dev/null
+++ b/ui/src/frontend/live_reload.ts
@@ -0,0 +1,63 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+let lastReloadDialogTime = 0;
+const kMinTimeBetweenDialogsMs = 10000;
+const changedPaths = new Set<string>();
+
+export function initLiveReloadIfLocalhost() {
+ if (!location.origin.startsWith('http://localhost:')) return;
+
+ const monitor = new EventSource('/live_reload');
+ monitor.onmessage = msg => {
+ const change = msg.data;
+ console.log('Live reload:', change);
+ changedPaths.add(change);
+ if (change.endsWith('.css')) {
+ reloadCSS();
+ } else if (change.endsWith('.html') || change.endsWith('.js')) {
+ reloadDelayed();
+ }
+ };
+ monitor.onerror = (err) => {
+ // In most cases the error is fired on reload, when the socket disconnects.
+ // Delay the error and the reconnection, so in the case of a reload we don't
+ // see any midleading message.
+ setTimeout(() => console.error('LiveReload SSE error', err), 1000);
+ };
+}
+
+function reloadCSS() {
+ const css = document.querySelector('link[rel=stylesheet]') as HTMLLinkElement;
+ if (!css) return;
+ const parent = css.parentElement!;
+ parent.removeChild(css);
+ parent.appendChild(css);
+}
+
+function reloadDelayed() {
+ setTimeout(() => {
+ let pathsStr = '';
+ for (const path of changedPaths) {
+ pathsStr += path + '\n';
+ }
+ changedPaths.clear();
+ if (Date.now() - lastReloadDialogTime < kMinTimeBetweenDialogsMs) return;
+ const reload = confirm(`${pathsStr}changed, click to reload`);
+ lastReloadDialogTime = Date.now();
+ if (reload) {
+ window.location.reload();
+ }
+ }, 1000);
+}
diff --git a/ui/src/frontend/post_message_handler.ts b/ui/src/frontend/post_message_handler.ts
index 03efb23..f4ff214 100644
--- a/ui/src/frontend/post_message_handler.ts
+++ b/ui/src/frontend/post_message_handler.ts
@@ -43,17 +43,19 @@
// ready, so the message handler always replies to a 'PING' message with 'PONG',
// which indicates it is ready to receive a trace.
export function postMessageHandler(messageEvent: MessageEvent) {
+ if (messageEvent.origin === 'https://tagassistant.google.com') {
+ // The GA debugger, does a window.open() and sends messages to the GA
+ // script. Ignore them.
+ return;
+ }
+
if (document.readyState !== 'complete') {
console.error('Ignoring message - document not ready yet.');
return;
}
- if (messageEvent.source === null) {
- throw new Error('Incoming message has no source');
- }
-
- // This can happen if an extension tries to postMessage.
- if (messageEvent.source !== window.opener) {
+ if (messageEvent.source === null || messageEvent.source !== window.opener) {
+ // This can happen if an extension tries to postMessage.
return;
}
@@ -77,7 +79,12 @@
} else if (messageEvent.data instanceof ArrayBuffer) {
postedTrace = {title: 'External trace', buffer: messageEvent.data};
} else {
- throw new Error('Incoming message data is not in a usable format');
+ console.warn(
+ 'Unknown postMessage() event received. If you are trying to open a ' +
+ 'trace via postMessage(), this is a bug in your code. If not, this ' +
+ 'could be due to some Chrome extension.');
+ console.log('origin:', messageEvent.origin, 'data:', messageEvent.data);
+ return;
}
if (postedTrace.buffer.byteLength === 0) {
diff --git a/ui/src/gen b/ui/src/gen
index 71d53d9..652818c 120000
--- a/ui/src/gen
+++ b/ui/src/gen
@@ -1 +1 @@
-../dist/gen
\ No newline at end of file
+../out/tsc/gen
\ No newline at end of file
diff --git a/ui/src/query/index.ts b/ui/src/query/index.ts
deleted file mode 100644
index bbb1f2c..0000000
--- a/ui/src/query/index.ts
+++ /dev/null
@@ -1,317 +0,0 @@
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import * as m from 'mithril';
-
-import {Engine} from '../common/engine';
-import {
- RawQueryResult,
- rawQueryResultColumns,
- rawQueryResultIter
-} from '../common/protos';
-import {
- createWasmEngine,
- destroyWasmEngine,
- warmupWasmEngine,
- WasmEngineProxy
-} from '../common/wasm_engine_proxy';
-
-const kEngineId = 'engine';
-const kSliceSize = 1024 * 1024;
-
-
-interface OnReadSlice {
- (blob: Blob, end: number, slice: ArrayBuffer): void;
-}
-
-function readSlice(
- blob: Blob, start: number, end: number, callback: OnReadSlice) {
- const slice = blob.slice(start, end);
- const reader = new FileReader();
- reader.onerror = e => {
- console.error(e);
- };
- reader.onloadend = _ => {
- callback(blob, end, reader.result as ArrayBuffer);
- };
- reader.readAsArrayBuffer(slice);
-}
-
-
-// Represents an in flight or resolved query.
-type QueryState = QueryPendingState|QueryResultState|QueryErrorState;
-
-interface QueryResultState {
- kind: 'QueryResultState';
- id: number;
- query: string;
- result: RawQueryResult;
- executionTimeNs: number;
-}
-
-interface QueryErrorState {
- kind: 'QueryErrorState';
- id: number;
- query: string;
- error: string;
-}
-
-interface QueryPendingState {
- kind: 'QueryPendingState';
- id: number;
- query: string;
-}
-
-function isPending(q: QueryState): q is QueryPendingState {
- return q.kind === 'QueryPendingState';
-}
-
-function isError(q: QueryState): q is QueryErrorState {
- return q.kind === 'QueryErrorState';
-}
-
-function isResult(q: QueryState): q is QueryResultState {
- return q.kind === 'QueryResultState';
-}
-
-
-// Helpers for accessing a query result
-function columns(result: RawQueryResult): string[] {
- return [...rawQueryResultColumns(result)];
-}
-
-function rows(result: RawQueryResult, offset: number, count: number):
- Array<Array<number|string>> {
- const rows: Array<Array<number|string>> = [];
-
- let i = 0;
- for (const value of rawQueryResultIter(result)) {
- if (i < offset) continue;
- if (i > offset + count) break;
- rows.push(Object.values(value));
- i++;
- }
- return rows;
-}
-
-
-// State machine controller for the UI.
-type Input = NewFile|NewQuery|MoreData|QuerySuccess|QueryFailure;
-
-interface NewFile {
- kind: 'NewFile';
- file: File;
-}
-
-interface MoreData {
- kind: 'MoreData';
- end: number;
- source: Blob;
- buffer: ArrayBuffer;
-}
-
-interface NewQuery {
- kind: 'NewQuery';
- query: string;
-}
-
-interface QuerySuccess {
- kind: 'QuerySuccess';
- id: number;
- result: RawQueryResult;
-}
-
-interface QueryFailure {
- kind: 'QueryFailure';
- id: number;
- error: string;
-}
-
-class QueryController {
- engine: Engine|undefined;
- file: File|undefined;
- state: 'initial'|'loading'|'ready';
- render: (state: QueryController) => void;
- nextQueryId: number;
- queries: Map<number, QueryState>;
-
- constructor(render: (state: QueryController) => void) {
- this.render = render;
- this.state = 'initial';
- this.nextQueryId = 0;
- this.queries = new Map();
- this.render(this);
- }
-
- onInput(input: Input) {
- // tslint:disable-next-line no-any
- const f = (this as any)[`${this.state}On${input.kind}`];
- if (f === undefined) {
- throw new Error(`No edge for input '${input.kind}' in '${this.state}'`);
- }
- f.call(this, input);
- this.render(this);
- }
-
- initialOnNewFile(input: NewFile) {
- this.state = 'loading';
- if (this.engine) {
- destroyWasmEngine(kEngineId);
- }
- this.engine = new WasmEngineProxy('engine', createWasmEngine(kEngineId));
-
- this.file = input.file;
- this.readNextSlice(0);
- }
-
- loadingOnMoreData(input: MoreData) {
- if (input.source !== this.file) return;
- this.engine!.parse(new Uint8Array(input.buffer));
- if (input.end === this.file.size) {
- this.engine!.notifyEof();
- this.state = 'ready';
- } else {
- this.readNextSlice(input.end);
- }
- }
-
- readyOnNewQuery(input: NewQuery) {
- const id = this.nextQueryId++;
- this.queries.set(id, {
- kind: 'QueryPendingState',
- id,
- query: input.query,
- });
-
- this.engine!.query(input.query)
- .then(result => {
- if (result.error) {
- this.onInput({
- kind: 'QueryFailure',
- id,
- error: result.error,
- });
- } else {
- this.onInput({
- kind: 'QuerySuccess',
- id,
- result,
- });
- }
- })
- .catch(error => {
- this.onInput({
- kind: 'QueryFailure',
- id,
- error,
- });
- });
- }
-
- readyOnQuerySuccess(input: QuerySuccess) {
- const oldQueryState = this.queries.get(input.id);
- console.log('sucess', input);
- if (!oldQueryState) return;
- this.queries.set(input.id, {
- kind: 'QueryResultState',
- id: oldQueryState.id,
- query: oldQueryState.query,
- result: input.result,
- executionTimeNs: +input.result.executionTimeNs,
- });
- }
-
- readyOnQueryFailure(input: QueryFailure) {
- const oldQueryState = this.queries.get(input.id);
- console.log('failure', input);
- if (!oldQueryState) return;
- this.queries.set(input.id, {
- kind: 'QueryErrorState',
- id: oldQueryState.id,
- query: oldQueryState.query,
- error: input.error,
- });
- }
-
- readNextSlice(start: number) {
- const end = Math.min(this.file!.size, start + kSliceSize);
- readSlice(this.file!, start, end, (source, end, buffer) => {
- this.onInput({
- kind: 'MoreData',
- end,
- source,
- buffer,
- });
- });
- }
-}
-
-function render(root: Element, controller: QueryController) {
- const queries = [...controller.queries.values()].sort((a, b) => b.id - a.id);
- m.render(root, [
- m('h1', controller.state),
- m('input[type=file]', {
- onchange: (e: Event) => {
- if (!(e.target instanceof HTMLInputElement)) return;
- if (!e.target.files) return;
- if (!e.target.files[0]) return;
- const file = e.target.files[0];
- controller.onInput({
- kind: 'NewFile',
- file,
- });
- },
- }),
- m('input[type=text]', {
- disabled: controller.state !== 'ready',
- onchange: (e: Event) => {
- controller.onInput({
- kind: 'NewQuery',
- query: (e.target as HTMLInputElement).value,
- });
- }
- }),
- m('.query-list',
- queries.map(
- q =>
- m('.query',
- {
- key: q.id,
- },
- m('.query-text', q.query),
- m('.query-time',
- isResult(q) ? `${q.executionTimeNs / 1000000}ms` : ''),
- isResult(q) ? m('.query-content', renderTable(q.result)) : null,
- isError(q) ? m('.query-content', q.error) : null,
- isPending(q) ? m('.query-content') : null))),
- ]);
-}
-
-function renderTable(result: RawQueryResult) {
- return m(
- 'table',
- m('tr', columns(result).map(c => m('th', c))),
- rows(result, 0, 1000).map(r => {
- return m('tr', Object.values(r).map(d => m('td', d)));
- }));
-}
-
-function main() {
- warmupWasmEngine();
- const root = document.querySelector('#root');
- if (!root) throw new Error('Could not find root element');
- new QueryController(ctrl => render(root, ctrl));
-}
-
-main();
diff --git a/ui/src/service_worker/service_worker.ts b/ui/src/service_worker/service_worker.ts
index 3289352..668f840 100644
--- a/ui/src/service_worker/service_worker.ts
+++ b/ui/src/service_worker/service_worker.ts
@@ -61,6 +61,7 @@
}
const url = new URL(req.url);
+ if (url.pathname === '/live_reload') return false;
return req.method === 'GET' && url.origin === self.location.origin;
}
diff --git a/ui/tsconfig.base.json b/ui/tsconfig.base.json
index e240301..f8cdfc4 100644
--- a/ui/tsconfig.base.json
+++ b/ui/tsconfig.base.json
@@ -8,7 +8,7 @@
"allowJs": true,
"declaration": false, // Generates corresponding '.d.ts' file.
"sourceMap": true, // Generates corresponding '.map' file.
- "outDir": "./dist", // Redirect output structure to the directory.
+ "outDir": "./out/tsc", // Redirect output structure to the directory.
"removeComments": false, // Do not emit comments to output.
"importHelpers": true, // Import emit helpers from 'tslib'.
"downlevelIteration": true, // Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'.
diff --git a/ui/tsconfig.json b/ui/tsconfig.json
index 8f2c266..ada3c9b 100644
--- a/ui/tsconfig.json
+++ b/ui/tsconfig.json
@@ -4,7 +4,8 @@
"exclude": [
"./node_modules/",
"./src/service_worker/",
- "./src/gen/"
+ "./src/gen/",
+ "./out"
],
"compilerOptions": {
"lib": [