From 8b43e6ce4d327e418a5a93ef2d3cbe5fbbd37bda Mon Sep 17 00:00:00 2001 From: Greg Magolan Date: Fri, 4 Oct 2019 09:38:42 -0700 Subject: [PATCH] feat(typescript): add JSNamedModuleInfo provider to ts_library outputs --- WORKSPACE | 9 +-- internal/common/devmode_js_sources.bzl | 26 ++++--- internal/common/node_module_info.bzl | 73 ++++++------------ internal/common/sources_aspect.bzl | 61 --------------- internal/linker/link_node_modules.bzl | 6 +- internal/node.bzl | 2 - internal/node/node.bzl | 29 ++++--- internal/node/npm_package_bin.bzl | 14 +++- internal/npm_install/generate_build_file.js | 16 ++-- internal/npm_install/generate_build_file.ts | 14 ++-- internal/npm_install/node_module_library.bzl | 38 ++++----- internal/npm_install/npm_umd_bundle.bzl | 6 +- .../golden/@angular/core/BUILD.bazel.golden | 2 +- internal/npm_package/npm_package.bzl | 40 +++++----- internal/rollup/rollup_bundle.bzl | 21 ++--- packages/jasmine/docs/BUILD.bazel | 1 + packages/karma/docs/BUILD.bazel | 1 + packages/karma/src/karma_web_test.bzl | 77 +++++++++++-------- packages/karma/src/web_test.bzl | 4 +- .../labs/src/protobufjs/ts_proto_library.bzl | 5 +- packages/protractor/docs/BUILD.bazel | 1 + .../protractor/src/protractor_web_test.bzl | 68 +++++++++------- .../protractor/test/protractor-2/BUILD.bazel | 11 ++- packages/rollup/src/rollup_bundle.bzl | 10 +-- .../typescript/src/internal/build_defs.bzl | 30 ++++---- .../src/internal/devserver/ts_devserver.bzl | 37 +++++---- .../devmode_consumer/devmode_consumer.bzl | 21 +++-- providers.bzl | 45 +++++++++++ 28 files changed, 349 insertions(+), 319 deletions(-) delete mode 100644 internal/common/sources_aspect.bzl diff --git a/WORKSPACE b/WORKSPACE index 60801ed33f..61b90fb148 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -67,11 +67,10 @@ yarn_install( name = "npm", # The @npm//:node_modules_filegroup generated by manual_build_file_contents # is used in the //packages/typescript/test/reference_types_directive:tsconfig_types - # test. For now we're still supporting node_modules as a filegroup tho this - # may change in the future. The default generated //:node_modules target is a - # node_module_library rule which provides NodeModuleInfo and NodeModuleSources - # but that rule is not yet in the public API and we have not yet dropped support - # for filegroup based node_modules target. + # test. For now we're still supporting node_modules as a filegroup tho this may + # change in the future. The default generated //:node_modules target is a node_module_library + # rule which provides NodeModuleInfo but that rule is not yet in the public API and we + # have not yet dropped support for filegroup based node_modules target. manual_build_file_contents = """ filegroup( name = "node_modules_filegroup", diff --git a/internal/common/devmode_js_sources.bzl b/internal/common/devmode_js_sources.bzl index f19d32b7c5..8c5b348f69 100644 --- a/internal/common/devmode_js_sources.bzl +++ b/internal/common/devmode_js_sources.bzl @@ -17,7 +17,7 @@ Outputs a manifest file with the sources listed. """ -load(":sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") # Avoid using non-normalized paths (workspace/../other_workspace/path) def _to_manifest_path(ctx, file): @@ -27,26 +27,30 @@ def _to_manifest_path(ctx, file): return ctx.workspace_name + "/" + file.short_path def _devmode_js_sources_impl(ctx): - files = depset() - - for d in ctx.attr.deps: - if hasattr(d, "node_sources"): - files = depset(transitive = [files, d.node_sources]) - elif hasattr(d, "files"): - files = depset(transitive = [files, d.files]) + sources_depsets = [] + for dep in ctx.attr.deps: + if JSNamedModuleInfo in dep: + sources_depsets.append(dep[JSNamedModuleInfo].sources) + if hasattr(dep, "files"): + sources_depsets.append(dep.files) + sources = depset(transitive = sources_depsets) ctx.actions.write(ctx.outputs.manifest, "".join([ _to_manifest_path(ctx, f) + "\n" - for f in files.to_list() + for f in sources.to_list() + if f.path.endswith(".js") or f.path.endswith(".mjs") ])) - return [DefaultInfo(files = files)] + + return [DefaultInfo( + files = sources, + runfiles = ctx.runfiles(transitive_files = sources), + )] devmode_js_sources = rule( implementation = _devmode_js_sources_impl, attrs = { "deps": attr.label_list( allow_files = True, - aspects = [sources_aspect], ), }, outputs = { diff --git a/internal/common/node_module_info.bzl b/internal/common/node_module_info.bzl index 044daed558..4f5cc8f95c 100644 --- a/internal/common/node_module_info.bzl +++ b/internal/common/node_module_info.bzl @@ -12,63 +12,40 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""NodeModuleInfo & NodeModuleSources providers and apsect to collect node_modules from deps. +"""NodeModuleInfo providers and apsect to collect node_modules from deps. """ -# NodeModuleInfo provider is only provided by targets that are npm dependencies by the -# `node_module_library` rule. This provider is currently used by different rules to filter out -# npm dependencies such as -# ``` -# [d for d in ctx.attr.deps if not NodeModuleInfo in d] -# ``` -# in `packages/typescript/internal/build_defs.bzl` or -# ``` -# hasattr(target, "files") and not NodeModuleInfo in target: -# ``` -# in `internal/common/sources_aspect.bzl`. -# Similar filtering is done in downstream repositories such as angular/angular so this provider -# needs to go through a deprecation period before it can be phased out. -NodeModuleInfo = provider( - doc = "Provides information about npm dependencies installed with yarn_install and npm_install rules", - fields = { - "workspace": "The workspace name that the npm dependencies are provided from", - }, -) - -# NodeModuleSources provider is provided by targets that are npm dependencies by the +# NodeModuleInfo provider is provided by targets that are npm dependencies by the # `node_module_library` rule as well as other targets that have direct or transitive deps on -# `node_module_library` targets via the `collect_node_modules_aspect` below. -# TODO: rename to NodeModuleSourcesInfo so name doesn't trigger name-conventions warning -# buildozer: disable=name-conventions -NodeModuleSources = provider( - doc = "Provides sources for npm dependencies installed with yarn_install and npm_install rules", +# `node_module_library` targets via the `node_modules_aspect` below. +NodeModuleInfo = provider( + doc = "Provides information about npm dependencies", fields = { - "scripts": "Source files that are javascript named-UMD or named-AMD modules for use in rules such as ts_devserver", - "sources": "Source files that are npm dependencies", + "sources": "Source files that are direct & transitive npm depedendencies", "workspace": "The workspace name that the npm dependencies are provided from", }, ) -def _collect_node_modules_aspect_impl(target, ctx): - nm_wksp = None - - if NodeModuleSources in target: - return [] +def _node_modules_aspect_impl(target, ctx): + providers = [] - if hasattr(ctx.rule.attr, "deps"): + # provide NodeModuleInfo if it is not already provided there are NodeModuleInfo deps + if not NodeModuleInfo in target: sources = depset() - for dep in ctx.rule.attr.deps: - if NodeModuleSources in dep: - if nm_wksp and dep[NodeModuleSources].workspace != nm_wksp: - fail("All npm dependencies need to come from a single workspace. Found '%s' and '%s'." % (nm_wksp, dep[NodeModuleSources].workspace)) - nm_wksp = dep[NodeModuleSources].workspace - sources = depset(transitive = [dep[NodeModuleSources].sources, sources]) - if sources: - return [NodeModuleSources(sources = sources, workspace = nm_wksp)] - - return [] - -collect_node_modules_aspect = aspect( - implementation = _collect_node_modules_aspect_impl, + nm_wksp = None + if hasattr(ctx.rule.attr, "deps"): + for dep in ctx.rule.attr.deps: + if NodeModuleInfo in dep: + if nm_wksp and dep[NodeModuleInfo].workspace != nm_wksp: + fail("All npm dependencies need to come from a single workspace. Found '%s' and '%s'." % (nm_wksp, dep[NodeModuleInfo].workspace)) + nm_wksp = dep[NodeModuleInfo].workspace + sources = depset(transitive = [dep[NodeModuleInfo].sources, sources]) + if nm_wksp: + providers.extend([NodeModuleInfo(sources = sources, workspace = nm_wksp)]) + + return providers + +node_modules_aspect = aspect( + _node_modules_aspect_impl, attr_aspects = ["deps"], ) diff --git a/internal/common/sources_aspect.bzl b/internal/common/sources_aspect.bzl deleted file mode 100644 index 2da1c284ed..0000000000 --- a/internal/common/sources_aspect.bzl +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2017 The Bazel Authors. All rights reserved. -# -# 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. - -"""Aspect to collect es5 js sources and scripts from deps. -""" - -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "NodeModuleSources") - -def _sources_aspect_impl(target, ctx): - # TODO(kyliau): node_sources here is a misnomer because it implies that - # the sources have got something to do with node modules. In fact, - # node_sources collects es5 output from typescript and "javascript-like" - # targets that are *not* node modules. This name is kept as-is to maintain - # compatibility with existing rules but should be renamed and cleaned up. - node_sources = depset() - - # dev_scripts is a collection of "scripts" from "node-module-like" targets - # such as `node_module_library` - dev_scripts = depset() - - # Note layering: until we have JS interop providers, this needs to know how to - # get TypeScript outputs. - if hasattr(target, "typescript"): - node_sources = depset(transitive = [node_sources, target.typescript.es5_sources]) - elif hasattr(target, "files") and not NodeModuleInfo in target: - # Sources from npm fine grained deps should not be included - node_sources = depset( - [f for f in target.files.to_list() if f.path.endswith(".js")], - transitive = [node_sources], - ) - - if NodeModuleSources in target: - dev_scripts = depset(target[NodeModuleSources].scripts) - - if hasattr(ctx.rule.attr, "deps"): - for dep in ctx.rule.attr.deps: - if hasattr(dep, "node_sources"): - node_sources = depset(transitive = [node_sources, dep.node_sources]) - if hasattr(dep, "dev_scripts"): - dev_scripts = depset(transitive = [dev_scripts, dep.dev_scripts]) - - return struct( - node_sources = node_sources, - dev_scripts = dev_scripts, - ) - -sources_aspect = aspect( - _sources_aspect_impl, - attr_aspects = ["deps"], -) diff --git a/internal/linker/link_node_modules.bzl b/internal/linker/link_node_modules.bzl index 710286f98c..ff3ee8c12d 100644 --- a/internal/linker/link_node_modules.bzl +++ b/internal/linker/link_node_modules.bzl @@ -10,7 +10,7 @@ linker, which uses the mappings to link a node_modules directory for runtimes to locate all the first-party packages. """ -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo") def _debug(vars, *args): if "VERBOSE_LOGS" in vars.keys(): @@ -42,8 +42,8 @@ def register_node_modules_linker(ctx, args, inputs): # Look through data/deps attributes to find... for dep in getattr(ctx.attr, "data", []) + getattr(ctx.attr, "deps", []): # ...the root directory for the third-party node_modules; we'll symlink the local "node_modules" to it - if NodeModuleSources in dep: - possible_root = "/".join([dep[NodeModuleSources].workspace, "node_modules"]) + if NodeModuleInfo in dep: + possible_root = "/".join([dep[NodeModuleInfo].workspace, "node_modules"]) if not node_modules_root: node_modules_root = possible_root elif node_modules_root != possible_root: diff --git a/internal/node.bzl b/internal/node.bzl index c8115f6f82..cd80d47fdf 100644 --- a/internal/node.bzl +++ b/internal/node.bzl @@ -23,7 +23,5 @@ load( "//internal/common:expand_into_runfiles.bzl", _expand_location_into_runfiles = "expand_location_into_runfiles", ) -load("//internal/common:sources_aspect.bzl", _sources_aspect = "sources_aspect") -sources_aspect = _sources_aspect expand_location_into_runfiles = _expand_location_into_runfiles diff --git a/internal/node/node.bzl b/internal/node/node.bzl index 3cb0dd3cd7..462c9bb48d 100644 --- a/internal/node/node.bzl +++ b/internal/node/node.bzl @@ -20,10 +20,11 @@ They support module mapping: any targets in the transitive dependencies with a `module_name` attribute can be `require`d by that name. """ -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//:declaration_provider.bzl", "DeclarationInfo") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "node_modules_aspect") load("//internal/common:expand_into_runfiles.bzl", "expand_location_into_runfiles") load("//internal/common:module_mappings.bzl", "module_mappings_runtime_aspect") -load("//internal/common:sources_aspect.bzl", "sources_aspect") load("//internal/common:windows_utils.bzl", "create_windows_native_launcher_script", "is_windows") def _trim_package_node_modules(package_name): @@ -48,8 +49,8 @@ def _compute_node_modules_root(ctx): """ node_modules_root = None if ctx.attr.node_modules: - if NodeModuleSources in ctx.attr.node_modules: - node_modules_root = "/".join([ctx.attr.node_modules[NodeModuleSources].workspace, "node_modules"]) + if NodeModuleInfo in ctx.attr.node_modules: + node_modules_root = "/".join([ctx.attr.node_modules[NodeModuleInfo].workspace, "node_modules"]) elif ctx.files.node_modules: # ctx.files.node_modules is not an empty list workspace = ctx.attr.node_modules.label.workspace_root.split("/")[1] if ctx.attr.node_modules.label.workspace_root else ctx.workspace_name @@ -59,8 +60,8 @@ def _compute_node_modules_root(ctx): "node_modules", ] if f]) for d in ctx.attr.data: - if NodeModuleSources in d: - possible_root = "/".join([d[NodeModuleSources].workspace, "node_modules"]) + if NodeModuleInfo in d: + possible_root = "/".join([d[NodeModuleInfo].workspace, "node_modules"]) if not node_modules_root: node_modules_root = possible_root elif node_modules_root != possible_root: @@ -130,10 +131,10 @@ def _nodejs_binary_impl(ctx): node_modules = depset(ctx.files.node_modules) # Also include files from npm fine grained deps as inputs. - # These deps are identified by the NodeModuleSources provider. + # These deps are identified by the NodeModuleInfo provider. for d in ctx.attr.data: - if NodeModuleSources in d: - node_modules = depset(transitive = [node_modules, d[NodeModuleSources].sources]) + if NodeModuleInfo in d: + node_modules = depset(transitive = [node_modules, d[NodeModuleInfo].sources]) # Using a depset will allow us to avoid flattening files and sources # inside this loop. This should reduce the performances hits, @@ -141,8 +142,12 @@ def _nodejs_binary_impl(ctx): sources = depset() for d in ctx.attr.data: - if hasattr(d, "node_sources"): - sources = depset(transitive = [sources, d.node_sources]) + if DeclarationInfo in d: + sources = depset(transitive = [sources, d[DeclarationInfo].transitive_declarations]) + + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in d: + sources = depset(transitive = [sources, d[JSNamedModuleInfo].sources]) if hasattr(d, "files"): sources = depset(transitive = [sources, d.files]) @@ -262,7 +267,7 @@ _NODEJS_EXECUTABLE_ATTRS = { "data": attr.label_list( doc = """Runtime dependencies which may be loaded during execution.""", allow_files = True, - aspects = [sources_aspect, module_mappings_runtime_aspect, collect_node_modules_aspect], + aspects = [node_modules_aspect, module_mappings_runtime_aspect], ), "default_env_vars": attr.string_list( doc = """Default environment variables that are added to `configuration_env_vars`. diff --git a/internal/node/npm_package_bin.bzl b/internal/node/npm_package_bin.bzl index 3b40f729a8..3d4ea86308 100644 --- a/internal/node/npm_package_bin.bzl +++ b/internal/node/npm_package_bin.bzl @@ -1,5 +1,6 @@ "A generic rule to run a tool that appears in node_modules/.bin" +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "node_modules_aspect") load("@build_bazel_rules_nodejs//internal/linker:link_node_modules.bzl", "module_mappings_aspect", "register_node_modules_linker") # Note: this API is chosen to match nodejs_binary @@ -7,7 +8,7 @@ load("@build_bazel_rules_nodejs//internal/linker:link_node_modules.bzl", "module _ATTRS = { "outs": attr.output_list(), "args": attr.string_list(mandatory = True), - "data": attr.label_list(allow_files = True, aspects = [module_mappings_aspect]), + "data": attr.label_list(allow_files = True, aspects = [module_mappings_aspect, node_modules_aspect]), "output_dir": attr.bool(), "tool": attr.label( executable = True, @@ -23,6 +24,15 @@ def _expand_location(ctx, s): s = s.replace("$@", "/".join([ctx.bin_dir.path, ctx.label.package, ctx.attr.name])) return ctx.expand_location(s, targets = ctx.attr.data) +def _inputs(ctx): + # Also include files from npm fine grained deps as inputs. + # These deps are identified by the NodeModuleInfo provider. + inputs_depsets = [] + for d in ctx.attr.data: + if NodeModuleInfo in d: + inputs_depsets.append(d[NodeModuleInfo].sources) + return depset(ctx.files.data, transitive = inputs_depsets).to_list() + def _impl(ctx): if ctx.attr.output_dir and ctx.attr.outs: fail("Only one of output_dir and outs may be specified") @@ -30,7 +40,7 @@ def _impl(ctx): fail("One of output_dir and outs must be specified") args = ctx.actions.args() - inputs = ctx.files.data[:] + inputs = _inputs(ctx) outputs = [] if ctx.attr.output_dir: outputs = [ctx.actions.declare_directory(ctx.attr.name)] diff --git a/internal/npm_install/generate_build_file.js b/internal/npm_install/generate_build_file.js index 67ccb664c1..f364f75333 100644 --- a/internal/npm_install/generate_build_file.js +++ b/internal/npm_install/generate_build_file.js @@ -798,14 +798,14 @@ def _maybe(repo_rule, name, **kwargs): const dtsSources = filterFiles(pkg._files, ['.d.ts']); // TODO(gmagolan): add UMD & AMD scripts to scripts even if not an APF package _but_ only if they // are named? - const scripts = getNgApfScripts(pkg); + const namedSources = getNgApfScripts(pkg); const deps = [pkg].concat(pkg._dependencies.filter(dep => dep !== pkg && !dep._isNested)); - let scriptStarlark = ''; - if (scripts.length) { - scriptStarlark = ` + let namedSourcesStarlark = ''; + if (namedSources.length) { + namedSourcesStarlark = ` # subset of srcs that are javascript named-UMD or named-AMD scripts - scripts = [ - ${scripts.map((f) => `"//:node_modules/${pkg._dir}/${f}",`).join('\n ')} + named_sources = [ + ${namedSources.map((f) => `"//:node_modules/${pkg._dir}/${f}",`).join('\n ')} ],`; } let srcsStarlark = ''; @@ -852,7 +852,7 @@ node_module_library( # circular dependencies errors node_module_library( name = "${pkg._name}__contents", - srcs = [":${pkg._name}__files"],${scriptStarlark} + srcs = [":${pkg._name}__files"],${namedSourcesStarlark} ) # ${pkg._name}__typings is the subset of ${pkg._name}__contents that are declarations @@ -1026,4 +1026,4 @@ node_module_library( `; } }); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVfYnVpbGRfZmlsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2ludGVybmFsL25wbV9pbnN0YWxsL2dlbmVyYXRlX2J1aWxkX2ZpbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0lBQUE7Ozs7Ozs7Ozs7Ozs7OztPQWVHO0lBQ0g7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FzQkc7SUFDSCxZQUFZLENBQUM7O0lBR2IseUJBQXlCO0lBQ3pCLDZCQUE2QjtJQUM3QixpQ0FBaUM7SUFFakMsU0FBUyxXQUFXLENBQUMsR0FBRyxDQUFRO1FBQzlCLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1lBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQywwQkFBMEIsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JGLENBQUM7SUFFRCxNQUFNLGlCQUFpQixHQUFHOzs7Ozs7Q0FNekIsQ0FBQTtJQUVELE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25DLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxQixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUIsTUFBTSxvQkFBb0IsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0MsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9CLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ3pELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDO0lBRWpELElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUU7UUFDM0IsSUFBSSxFQUFFLENBQUM7S0FDUjtJQUVEOzs7T0FHRztJQUNILFNBQVMsTUFBTSxDQUFDLENBQVM7UUFDdkIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDckIsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN4QixFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ2pCO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILFNBQVMsYUFBYSxDQUFDLENBQVMsRUFBRSxPQUFlO1FBQy9DLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEIsRUFBRSxDQUFDLGFBQWEsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxJQUFJO1FBQ1gsZ0VBQWdFO1FBQ2hFLE1BQU0sSUFBSSxHQUFHLFlBQVksRUFBRSxDQUFDO1FBRTVCLHVCQUF1QjtRQUN2QixtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUUxQiw0QkFBNEI7UUFDNUIsdUJBQXVCLENBQUMsSUFBSSxDQUFDLENBQUE7UUFFN0IsMkJBQTJCO1FBQzNCLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFBO0lBQzFCLENBQUM7SUFFRCxNQUFNLENBQUMsT0FBTyxHQUFHO1FBQ2YsSUFBSTtRQUNKLGVBQWU7UUFDZixzQkFBc0I7UUFDdEIsYUFBYTtLQUNkLENBQUM7SUFFRjs7T0FFRztJQUNILFNBQVMsa0JBQWtCLENBQUMsSUFBVztRQUNyQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQTtRQUN6RCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMseUJBQXlCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNsRixVQUFVLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUN0RSxDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLG1CQUFtQixDQUFDLElBQVc7UUFDdEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLGNBQWMsQ0FBQyxHQUFRO1FBQzlCLE1BQU0saUJBQWlCLEdBQUcsV0FBVyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7UUFDOUUsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUNqQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3JDLE1BQU0sVUFBVSxHQUFHLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUMxQyxJQUFJLFVBQVUsS0FBSyxPQUFPLElBQUksVUFBVSxLQUFLLGFBQWEsRUFBRTtnQkFDMUQsMEVBQTBFO2dCQUMxRSwyRUFBMkU7Z0JBQzNFLHdFQUF3RTtnQkFDeEUsa0ZBQWtGO2dCQUNsRixtRUFBbUU7Z0JBQ25FLCtFQUErRTtnQkFDL0Usc0VBQXNFO2dCQUN0RSx5RkFBeUY7Z0JBQ3pGLGVBQWU7Z0JBQ2YsSUFBSSxDQUFDLGlCQUFpQixJQUFJLG9CQUFvQixFQUFFO29CQUM5QyxPQUFPLENBQUMsS0FBSyxDQUFDLGdCQUFnQixHQUFHLENBQUMsSUFBSSxXQUFXLFNBQVMsSUFBSSxTQUFTOzBCQUNyRCxJQUFJOzsrQkFFQyxDQUFDLENBQUM7b0JBQ3pCLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ2pCO3FCQUFNO29CQUNMLCtEQUErRDtvQkFDL0QsMkVBQTJFO29CQUMzRSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksUUFBUSxFQUFFLENBQUMsQ0FBQztvQkFDcEUsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7b0JBQ2hFLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO29CQUNuRSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztvQkFDaEMsT0FBTyxPQUFPLENBQUM7aUJBQ2hCO2FBQ0Y7WUFDRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxxQkFBcUIsQ0FBQyxJQUFXO1FBQ3hDLElBQUksZUFBZSxHQUFHLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQzdCLGVBQWUsSUFBSSxxQkFBcUIsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDO0NBQ3JFLENBQUM7WUFDYSxDQUFDLENBQUMsQ0FBQTtRQUFBLENBQUMsQ0FBQyxDQUFDO1FBRWxCLElBQUksWUFBWSxHQUFHLEVBQUUsQ0FBQztRQUN0QixJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDZixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxLQUFLLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN4RixZQUFZLEdBQUc7OztVQUdULElBQUk7T0FDUCxDQUFDO1NBQ0w7UUFFRCxJQUFJLFlBQVksR0FBRyxFQUFFLENBQUM7UUFDdEIsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2YsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksSUFBSSxHQUFHLENBQUMsS0FBSyxjQUFjLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDM0YsWUFBWSxHQUFHOzs7VUFHVCxJQUFJO09BQ1AsQ0FBQztTQUNMO1FBRUQsSUFBSSxTQUFTLEdBQUcsaUJBQWlCO1lBQzdCOzs7RUFHSixlQUFlOzs7Ozs7OzRCQU9XLFlBQVksR0FBRyxZQUFZOzs7Q0FHdEQsQ0FBQTtRQUVDLG9EQUFvRDtRQUNwRCxJQUFJO1lBQ0YsU0FBUyxJQUFJLEVBQUUsQ0FBQyxZQUFZLENBQUMsNEJBQTRCLEVBQUUsRUFBQyxRQUFRLEVBQUUsTUFBTSxFQUFDLENBQUMsQ0FBQztTQUNoRjtRQUFDLE9BQU8sQ0FBQyxFQUFFO1NBQ1g7UUFFRCxhQUFhLENBQUMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRDs7T0FFRztJQUNILFNBQVMseUJBQXlCLENBQUMsR0FBUTtRQUN6QyxJQUFJLFNBQVMsR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFbEMsTUFBTSxZQUFZLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzFDLElBQUksWUFBWSxDQUFDLE1BQU0sRUFBRTtZQUN2QixhQUFhLENBQ1QsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsYUFBYSxDQUFDLEVBQUUsaUJBQWlCLEdBQUcsWUFBWSxDQUFDLENBQUM7U0FDeEY7UUFFRCxNQUFNLFNBQVMsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDckMsSUFBSSxTQUFTLENBQUMsTUFBTSxFQUFFO1lBQ3BCLGFBQWEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ2pFLFNBQVMsR0FBRyxHQUFHLFNBQVM7OztDQUczQixDQUFDO1NBQ0M7UUFFRCxhQUFhLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxhQUFhLENBQUMsRUFBRSxpQkFBaUIsR0FBRyxTQUFTLENBQUMsQ0FBQztJQUN6RixDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLHVCQUF1QixDQUFDLElBQVc7UUFDMUMsTUFBTSxVQUFVLEdBQWdCLEVBQUUsQ0FBQztRQUVuQyxLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksRUFBRTtZQUN0QixJQUFJLENBQUMsR0FBRyxDQUFDLGVBQWUsRUFBRTtnQkFDeEIsU0FBUzthQUNWO1lBRUQsS0FBSyxNQUFNLFNBQVMsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsRUFBRTtnQkFDeEQseURBQXlEO2dCQUN6RCxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRTtvQkFDekIsT0FBTyxDQUFDLEtBQUssQ0FDVCxtQ0FBbUMsU0FBUyxvQkFBb0I7d0JBQ2hFLFdBQVcsR0FBRyxDQUFDLElBQUksSUFBSSxHQUFHLENBQUMsT0FBTyxzQkFBc0IsVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztvQkFDckYsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDakI7Z0JBRUQsc0JBQXNCLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2dCQUV2QywyRUFBMkU7Z0JBQzNFLFVBQVUsQ0FBQyxTQUFTLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxJQUFJLElBQUksR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO2FBQ3REO1NBQ0Y7UUFFRCxrREFBa0Q7UUFDbEQsZ0NBQWdDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRDs7T0FFRztJQUNILFNBQVMsc0JBQXNCLENBQUMsR0FBUSxFQUFFLFNBQWlCO1FBQ3pELElBQUksT0FBTyxHQUFHOzs7Ozs7Q0FNZixDQUFDO1FBRUEsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxRQUFRLENBQUM7UUFDekQsSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNiLE9BQU8sQ0FBQyxLQUFLLENBQ1QsMENBQTBDLEdBQUcsQ0FBQyxJQUFJLElBQUksR0FBRyxDQUFDLE9BQU8sSUFBSTtnQkFDckUsa0NBQWtDLFNBQVMsR0FBRyxDQUFDLENBQUM7WUFDcEQsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNqQjtRQUVELGtFQUFrRTtRQUNsRSx3RUFBd0U7UUFDeEUsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDdEUsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDNUIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDeEIsSUFBSSxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ25DLHNDQUFzQztnQkFDdEMsT0FBTzthQUNSO1lBQ0QsSUFBSSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDN0MsSUFBSSxRQUFRLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUM3QixzQ0FBc0M7Z0JBQ3RDLE9BQU87YUFDUjtZQUNELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDckMsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzFDLDZGQUE2RjtZQUM3RixrQ0FBa0M7WUFDbEMsSUFBSSxVQUFVLEtBQUssUUFBUSxJQUFJLFVBQVUsS0FBSyxjQUFjLEVBQUU7Z0JBQzVELFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUN4RTtZQUNELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzVELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQzVELE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDM0IsRUFBRSxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDN0IsQ0FBQyxDQUFDLENBQUM7UUFFSCwrRUFBK0U7UUFDL0UsNEVBQTRFO1FBQzVFLGlGQUFpRjtRQUNqRixzQ0FBc0M7UUFDdEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsRUFBRTtZQUNwQyxhQUFhLENBQ1QsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsYUFBYSxDQUFDLEVBQ25ELHNEQUFzRCxDQUFDLENBQUM7U0FDN0Q7UUFDRCxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzlDLFNBQVMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsRUFBQyxRQUFRLEVBQUUsTUFBTSxFQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RFLGFBQWEsQ0FDVCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSx5QkFBeUIsQ0FBQyxFQUMvRCx5REFBeUQsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFeEYsT0FBTyxJQUFJLGVBQWUsU0FBUzs7O2tCQUduQixTQUFTOzBCQUNELFNBQVMsaUJBQWlCLFNBQVM7O0NBRTVELENBQUM7UUFFQSxhQUFhLENBQUMsV0FBVyxTQUFTLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLGdDQUFnQyxDQUFDLFVBQW9CO1FBQzVELElBQUksT0FBTyxHQUFHO0NBQ2YsQ0FBQztRQUNBLFVBQVUsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUU7WUFDN0IsT0FBTyxJQUFJLG1CQUFtQixTQUFTLHFCQUFxQixTQUFTO0NBQ3hFLENBQUM7UUFDQSxDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sSUFBSTs7Q0FFWixDQUFDO1FBQ0EsVUFBVSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUM3QixPQUFPLElBQUksZUFBZSxTQUFTO0NBQ3RDLENBQUM7UUFDQSxDQUFDLENBQUMsQ0FBQztRQUVILGFBQWEsQ0FBQyxnQ0FBZ0MsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLHVCQUF1QixDQUFDLEtBQWEsRUFBRSxJQUFXO1FBQ3pELE1BQU0sU0FBUyxHQUFHLGlCQUFpQixHQUFHLFVBQVUsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDOUQsYUFBYSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLE1BQU0sQ0FBQyxDQUFTO1FBQ3ZCLE9BQU8sRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ3JELENBQUM7SUFFRDs7T0FFRztJQUNILFNBQVMsV0FBVyxDQUFDLENBQVM7UUFDNUIsT0FBTyxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDMUQsQ0FBQztJQUVEOzs7T0FHRztJQUNILFNBQVMsU0FBUyxDQUFDLE9BQWUsRUFBRSxTQUFpQixFQUFFO1FBQ3JELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUM3QyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQ3JCLE9BQU8sRUFBRSxDQUFDO1NBQ1g7UUFDRCxPQUFPLEVBQUUsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDO2FBQ3JCLE1BQU0sQ0FDSCxDQUFDLEtBQWUsRUFBRSxJQUFJLEVBQUUsRUFBRTtZQUN4QixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDNUMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzlDLE1BQU0sY0FBYyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDL0QsSUFBSSxJQUFJLENBQUM7WUFDVCxJQUFJO2dCQUNGLElBQUksR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQzlCO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1YsSUFBSSxjQUFjLEVBQUU7b0JBQ2xCLHNFQUFzRTtvQkFDdEUsdURBQXVEO29CQUN2RCxPQUFPLEtBQUssQ0FBQztpQkFDZDtnQkFDRCxNQUFNLENBQUMsQ0FBQzthQUNUO1lBQ0QsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3ZDLElBQUksV0FBVyxJQUFJLGNBQWMsRUFBRTtnQkFDakMsc0VBQXNFO2dCQUN0RSx5RUFBeUU7Z0JBQ3pFLDhEQUE4RDtnQkFDOUQsZ0VBQWdFO2dCQUNoRSx5REFBeUQ7Z0JBQ3pELGdEQUFnRDtnQkFDaEQsT0FBTyxLQUFLLENBQUM7YUFDZDtZQUNELE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN6RixDQUFDLEVBQ0QsRUFBRSxDQUFDO1lBQ1AscUZBQXFGO1lBQ3JGLHNFQUFzRTthQUNyRSxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDckMsc0RBQXNEO1lBQ3RELHFDQUFxQzthQUNwQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRDs7O09BR0c7SUFDSCxTQUFTLGdCQUFnQixDQUFDLEdBQVEsRUFBRSxRQUFnQjtRQUNsRCxLQUFLLE1BQU0sSUFBSSxJQUFJLEdBQUcsQ0FBQyxNQUFNLEVBQUU7WUFDN0IsZ0VBQWdFO1lBQ2hFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzNELElBQUksTUFBTSxLQUFLLFFBQVEsSUFBSSxNQUFNLEtBQUssY0FBYyxFQUFFO2dCQUNwRCxPQUFPLElBQUksQ0FBQzthQUNiO1NBQ0Y7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFHRCxTQUFTLHNCQUFzQixDQUFDLElBQVcsRUFBRSxZQUFZLEdBQUcsWUFBWTtRQUN0RSxTQUFTLEtBQUssQ0FBQyxJQUFZLEVBQUUsQ0FBTTtZQUNqQyxpRkFBaUY7WUFDakYsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFdBQVcsVUFBVSxDQUFDO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1lBRTdELE1BQU0sS0FBSyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDMUMsSUFBSSxJQUFJLEtBQUssS0FBSztnQkFBRSxPQUFPLElBQUksQ0FBQztZQUVoQyx5QkFBeUI7WUFDekIsSUFBSSxLQUFLLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUMzRixPQUFPLElBQUksQ0FBQzthQUNiO1lBRUQsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUNmLENBQUMsQ0FBQyxvQkFBb0I7Z0JBQ2xCLElBQUksQ0FBQyxNQUFNO2dCQUNILHNCQUFzQjtnQkFDdEIsc0VBQXNFO2dCQUN0RSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVc7b0JBQ3RELEtBQUssQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO3FCQUMvQixHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxJQUFJLElBQUksR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDcEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLFlBQVksQ0FBQyxDQUFDLEdBQUcsY0FBYztRQUN0QyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ25CLE9BQU8sRUFBRSxDQUFDO1NBQ1g7UUFFRCxNQUFNLElBQUksR0FBVSxFQUFFLENBQUM7UUFFdkIsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVsQyxNQUFNLFFBQVEsR0FBRyxPQUFPO1lBQ0gsb0JBQW9CO2FBQ25CLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNoQyxxREFBcUQ7WUFDckQsd0RBQXdEO2FBQ3ZELE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUMvQixHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7YUFDL0IsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFbEQsUUFBUSxDQUFDLE9BQU8sQ0FDWixDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUUxRixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUNqQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7YUFDL0IsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEQsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRW5ELHNCQUFzQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTdCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxVQUFVO1FBQ2pCLE1BQU0sQ0FBQyxHQUFHLGNBQWMsQ0FBQztRQUN6QixJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ25CLE9BQU8sRUFBRSxDQUFDO1NBQ1g7UUFFRCxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWxDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQ2pDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQzthQUMvQixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDM0IsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRS9ELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsU0FBUyxZQUFZLENBQUMsQ0FBUztRQUM3Qiw4Q0FBOEM7UUFDOUMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxFQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5RCxFQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUMsQ0FBQztRQUVyRCxrREFBa0Q7UUFDbEQsZ0NBQWdDO1FBQ2hDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUU1QyxrREFBa0Q7UUFDbEQsR0FBRyxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUV0QyxpRUFBaUU7UUFDakUsNENBQTRDO1FBQzVDLEdBQUcsQ0FBQyxXQUFXLEdBQUcsR0FBRyxDQUFDLElBQUksSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLElBQUksR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRXpELHdEQUF3RDtRQUN4RCxHQUFHLENBQUMsU0FBUyxHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUUzQyxzREFBc0Q7UUFDdEQsR0FBRyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFMUIsNkNBQTZDO1FBQzdDLDJEQUEyRDtRQUMzRCxHQUFHLENBQUMsYUFBYSxHQUFHLEVBQUUsQ0FBQztRQUV2Qiw4REFBOEQ7UUFDOUQsZ0VBQWdFO1FBQ2hFLDREQUE0RDtRQUM1RCxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFcEIsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLGNBQWMsQ0FBQyxLQUFVO1FBQ2hDLE9BQU8seUJBQXlCLENBQUMsS0FBSyxDQUFDLElBQUksMEJBQTBCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0UsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyx5QkFBeUIsQ0FBQyxLQUFVO1FBQzNDLE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxFQUFFLENBQUM7SUFDbkQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsU0FBUywwQkFBMEIsQ0FBQyxLQUFrQjtRQUNwRCxtREFBbUQ7UUFDbkQsT0FBTyxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtZQUNyQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNsRixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsU0FBUyxjQUFjLENBQUMsQ0FBUztRQUMvQixDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDMUIsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUN6QixDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoQjtRQUNELE9BQU8sQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsU0FBUyxxQkFBcUIsQ0FBQyxDQUFTO1FBQ3RDLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ3pCLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ2hCO1FBQ0QsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQ25CLENBQUMsSUFBSSxVQUFVLENBQUM7U0FDakI7UUFDRCxPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsU0FBUyxhQUFhLENBQUMsR0FBUSxFQUFFLElBQVk7UUFDM0MsTUFBTSxTQUFTLEdBQUcscUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDOUMsbUNBQW1DO1FBQ25DLE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsU0FBUyxDQUFDLElBQUksUUFBUSxDQUFDLEdBQUcsRUFBRSxHQUFHLFNBQVMsS0FBSyxDQUFDLENBQUM7UUFDL0UsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNkLG1FQUFtRTtZQUNuRSxrQkFBa0I7WUFDbEIsNkVBQTZFO1lBQzdFLGlFQUFpRTtZQUNqRSxXQUFXLENBQ1AsMkNBQTJDLFNBQVMseUJBQXlCLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1NBQy9GO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILFNBQVMsZUFBZSxDQUFDLEdBQVEsRUFBRSxZQUFvQjtRQUNyRCxNQUFNLGNBQWMsR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFFekMsSUFBSSxjQUFjLEVBQUU7WUFDbEIsSUFBSSxPQUFPLGNBQWMsS0FBSyxRQUFRLEVBQUU7Z0JBQ3RDLE9BQU8sYUFBYSxDQUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsQ0FBQTthQUUxQztpQkFBTSxJQUFJLE9BQU8sY0FBYyxLQUFLLFFBQVEsSUFBSSxZQUFZLEtBQUssU0FBUyxFQUFFO2dCQUMzRSwyQ0FBMkM7Z0JBQzNDLDJGQUEyRjtnQkFDM0YsTUFBTSxlQUFlLEdBQUcsY0FBYyxDQUFDLFVBQVUsQ0FBQyxJQUFJLGNBQWMsQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDbkYsSUFBSSxlQUFlLEVBQUU7b0JBQ25CLE9BQU8sYUFBYSxDQUFDLEdBQUcsRUFBRSxlQUFlLENBQUMsQ0FBQTtpQkFDM0M7YUFDRjtTQUNGO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsU0FBUyxrQkFBa0IsQ0FBQyxHQUFRO1FBQ2xDLDZDQUE2QztRQUM3QywrREFBK0Q7UUFDL0QsRUFBRTtRQUNGLCtGQUErRjtRQUMvRixTQUFTO1FBQ1QsTUFBTSxhQUFhLEdBQUcsQ0FBQyxTQUFTLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBRS9DLEtBQUssTUFBTSxRQUFRLElBQUksYUFBYSxFQUFFO1lBQ3hDLE1BQU0sZ0JBQWdCLEdBQUcsZUFBZSxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUN4RCxJQUFJLGdCQUFnQixFQUFFO2dCQUNwQixPQUFPLGdCQUFnQixDQUFDO2FBQ3pCO1NBQ0Y7UUFFRCwyREFBMkQ7UUFDM0Qsc0RBQXNEO1FBQ3RELE1BQU0sY0FBYyxHQUFHLGFBQWEsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDdEQsSUFBSSxjQUFjLEVBQUU7WUFDbEIsT0FBTyxjQUFjLENBQUE7U0FDdEI7UUFFRCxNQUFNLG1CQUFtQixHQUFHLGFBQWEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxHQUFHLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQztRQUNsRSxJQUFJLG1CQUFtQixFQUFFO1lBQ3ZCLE9BQU8sbUJBQW1CLENBQUM7U0FDNUI7UUFFRCxrREFBa0Q7UUFDbEQsV0FBVyxDQUFDLDhDQUE4QyxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUV2RSxzRUFBc0U7UUFDdEUsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQU9EOzs7T0FHRztJQUNILFNBQVMsc0JBQXNCLENBQUMsR0FBUSxFQUFFLEdBQVEsRUFBRSxPQUF5QjtRQUMzRSxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO1lBQ3pDLHNCQUFzQjtZQUN0QixPQUFPO1NBQ1I7UUFDRCxHQUFHLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM1QixNQUFNLFFBQVEsR0FBRyxVQUFTLFVBQXVCLEVBQUUsUUFBaUIsRUFBRSxPQUFlO1lBQ25GLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQztpQkFDeEIsR0FBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFO2dCQUNmLG1DQUFtQztnQkFDbkMsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ3hDLE9BQU8sV0FBVyxDQUFDLE1BQU0sRUFBRTtvQkFDekIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxXQUFXLEVBQUUsY0FBYyxFQUFFLFNBQVMsQ0FBQyxDQUFDO29CQUN6RSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUU7d0JBQ3RCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztxQkFDM0I7b0JBQ0QsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDO2lCQUNuQjtnQkFDRCxpQ0FBaUM7Z0JBQ2pDLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsRUFBRTtvQkFDMUIsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2lCQUMvQjtnQkFDRCx1QkFBdUI7Z0JBQ3ZCLElBQUksUUFBUSxFQUFFO29CQUNaLE9BQU8sQ0FBQyxLQUFLLENBQUMsa0JBQWtCLE9BQU8sS0FBSyxTQUFTLFNBQVMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7b0JBQzNFLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ2pCO2dCQUNELE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQyxDQUFDO2lCQUNELE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7aUJBQ3BCLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxHQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNsRSxDQUFDLENBQUM7UUFDRiw4REFBOEQ7UUFDOUQsaUVBQWlFO1FBQ2pFLHdEQUF3RDtRQUN4RCwrQ0FBK0M7UUFDL0MsSUFBSSxHQUFHLENBQUMsWUFBWSxJQUFJLEdBQUcsQ0FBQyxvQkFBb0IsRUFBRTtZQUNoRCxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsRUFBRTtnQkFDMUQsT0FBTyxHQUFHLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3ZDLENBQUMsQ0FBQyxDQUFDO1NBQ0o7UUFFRCxRQUFRLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDL0MsUUFBUSxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUN4RCw2REFBNkQ7UUFDN0QsaUVBQWlFO1FBQ2pFLGdFQUFnRTtRQUNoRSxrREFBa0Q7UUFDbEQsK0RBQStEO1FBQy9ELDBEQUEwRDtRQUMxRCxnRUFBZ0U7UUFDaEUsNERBQTREO1FBQzVELDJDQUEyQztRQUMzQyxRQUFRLENBQUMsR0FBRyxDQUFDLG9CQUFvQixFQUFFLEtBQUssRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFFRDs7O09BR0c7SUFDSCxTQUFTLFNBQVMsQ0FBQyxHQUFRO1FBQ3pCLDBFQUEwRTtRQUMxRSx3QkFBd0I7UUFDeEIsTUFBTSxNQUFNLHFCQUFZLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLE1BQU0sQ0FBQyxhQUFhLEdBQUcsR0FBRyxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDOUQsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxTQUFTLFdBQVcsQ0FBQyxLQUFlLEVBQUUsT0FBaUIsRUFBRTtRQUN2RCxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDZixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3RDLEtBQUssR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUN2QixvREFBb0Q7Z0JBQ3BELElBQUksV0FBVyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7b0JBQUUsT0FBTyxJQUFJLENBQUM7Z0JBQ2pELHVCQUF1QjtnQkFDdkIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUMzQixLQUFLLE1BQU0sQ0FBQyxJQUFJLElBQUksRUFBRTtvQkFDcEIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsRUFBRTt3QkFDckMsT0FBTyxJQUFJLENBQUM7cUJBQ2I7aUJBQ0Y7Z0JBQ0QsT0FBTyxLQUFLLENBQUM7WUFDZixDQUFDLENBQUMsQ0FBQTtTQUNIO1FBQ0Qsd0RBQXdEO1FBQ3hELE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUN6QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3JELElBQUksVUFBVSxLQUFLLFFBQVEsSUFBSSxVQUFVLEtBQUssY0FBYyxFQUFFO2dCQUM1RCxPQUFPLEtBQUssQ0FBQzthQUNkO1lBQ0QsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsU0FBUyxjQUFjLENBQUMsR0FBUTtRQUM5QixNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDaEMsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLEVBQUU7WUFDOUIsb0VBQW9FO1lBQ3BFLHdEQUF3RDtZQUN4RCxPQUFPLElBQUksQ0FBQztTQUNiO1FBQ0QsTUFBTSxXQUFXLEdBQUcsbUJBQW1CLENBQUM7UUFDeEMsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQzlCLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRTtnQkFDMUIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQ25ELElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRTtvQkFDcEIsT0FBTyxJQUFJLENBQUM7aUJBQ2I7YUFDRjtZQUNELE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsU0FBUyxlQUFlLENBQUMsR0FBUTtRQUMvQixPQUFPLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3hCLFdBQVcsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsU0FBUyxFQUFFLGVBQWUsRUFBRSxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDeEUsRUFBRSxDQUFDO0lBQ1QsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxRQUFRLENBQUMsR0FBUSxFQUFFLENBQVM7UUFDbkMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzNCLEtBQUssTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sRUFBRTtZQUMxQixJQUFJLENBQUMsQ0FBQyxXQUFXLEVBQUUsS0FBSyxFQUFFLEVBQUU7Z0JBQzFCLE9BQU8sQ0FBQyxDQUFDO2FBQ1Y7U0FDRjtRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRDs7T0FFRztJQUNILFNBQVMsWUFBWSxDQUFDLEdBQVE7UUFDNUIsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDeEQsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3RELGlHQUFpRztRQUNqRyxhQUFhO1FBQ2IsTUFBTSxPQUFPLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBRTFGLElBQUksY0FBYyxHQUFHLEVBQUUsQ0FBQztRQUN4QixJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUU7WUFDbEIsY0FBYyxHQUFHOzs7VUFHWCxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxvQkFBb0IsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUM7T0FDdkYsQ0FBQztTQUNMO1FBRUQsSUFBSSxZQUFZLEdBQUcsRUFBRSxDQUFDO1FBQ3RCLElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRTtZQUNsQixZQUFZLEdBQUc7UUFDWCxHQUFHLENBQUMsSUFBSTs7VUFFTixPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxvQkFBb0IsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUM7T0FDdkYsQ0FBQztTQUNMO1FBRUQsSUFBSSxZQUFZLEdBQUcsRUFBRSxDQUFDO1FBQ3RCLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNmLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLElBQUksR0FBRyxDQUFDLEtBQUssY0FBYyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzNGLFlBQVksR0FBRzs7O1VBR1QsSUFBSTtPQUNQLENBQUM7U0FDTDtRQUVELElBQUksV0FBVyxHQUFHLEVBQUUsQ0FBQztRQUNyQixJQUFJLFVBQVUsQ0FBQyxNQUFNLEVBQUU7WUFDckIsV0FBVyxHQUFHO1FBQ1YsR0FBRyxDQUFDLElBQUk7O1VBRU4sVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLG9CQUFvQixHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQztPQUNoRixDQUFDO1NBQ0w7UUFFRCxJQUFJLE1BQU0sR0FDTjs7dUNBRWlDLEdBQUcsQ0FBQyxJQUFJO0VBQzdDLFNBQVMsQ0FBQyxHQUFHLENBQUM7OztjQUdGLEdBQUcsQ0FBQyxLQUFLLFlBQVksWUFBWTs7OztjQUlqQyxHQUFHLENBQUMsS0FBSzs7Z0JBRVAsR0FBRyxDQUFDLEtBQUssYUFBYSxZQUFZOzs7SUFHOUMsR0FBRyxDQUFDLEtBQUs7OztjQUdDLEdBQUcsQ0FBQyxLQUFLO2dCQUNQLEdBQUcsQ0FBQyxLQUFLLGFBQWEsY0FBYzs7O0lBR2hELEdBQUcsQ0FBQyxLQUFLLDhCQUE4QixHQUFHLENBQUMsS0FBSzs7Y0FFdEMsR0FBRyxDQUFDLEtBQUssY0FBYyxXQUFXOzs7Q0FHL0MsQ0FBQztRQUVBLElBQUksY0FBYyxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBRTVDLHVFQUF1RTtRQUN2RSxhQUFhO1FBQ2IsSUFBSSxjQUFjLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLEdBQUcsR0FBRyxDQUFDLEtBQUssU0FBUyxDQUFDLEVBQUU7WUFDM0QsTUFBTTtnQkFDRjs7O2NBR00sR0FBRyxDQUFDLEtBQUs7c0JBQ0QsR0FBRyxDQUFDLEtBQUs7cUNBQ00sR0FBRyxDQUFDLElBQUksSUFBSSxjQUFjO2tCQUM3QyxHQUFHLENBQUMsS0FBSzs7O0NBRzFCLENBQUM7U0FDQztRQUVELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxTQUFTLGdCQUFnQixDQUFDLEdBQVE7UUFDaEMsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUU5QixtREFBbUQ7UUFDbkQscUNBQXFDO1FBQ3JDLGdEQUFnRDtRQUNoRCxJQUFJLGNBQWMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDM0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUU7Z0JBQ2xCLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUU7b0JBQzFCLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQyxFQUFFO3dCQUN2QixXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO3FCQUN2RDt5QkFBTTt3QkFDTCw4Q0FBOEM7cUJBQy9DO2lCQUNGO3FCQUFNLElBQUksT0FBTyxHQUFHLENBQUMsR0FBRyxLQUFLLFFBQVEsRUFBRTtvQkFDdEMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLGNBQWMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztpQkFDcEQ7cUJBQU0sSUFBSSxPQUFPLEdBQUcsQ0FBQyxHQUFHLEtBQUssUUFBUSxFQUFFO29CQUN0QyxLQUFLLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLEVBQUU7d0JBQ3ZCLElBQUkseUJBQXlCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFOzRCQUMzQyxXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7eUJBQ3BEO3FCQUNGO2lCQUNGO2FBQ0Y7U0FDRjtRQUVELE9BQU8sV0FBVyxDQUFDO0lBQ3JCLENBQUM7SUFFRCx5Q0FBeUM7SUFDekMsTUFBTTtJQUNOLGdCQUFnQjtJQUNoQixxQkFBcUI7SUFDckIsZ0NBQWdDO0lBQ2hDLGtEQUFrRDtJQUNsRCxNQUFNO0lBQ04sS0FBSztJQUNMLE1BQU07SUFDTixTQUFTLG9CQUFvQixDQUFDLEdBQVEsRUFBRSxJQUFZO1FBQ2xELElBQUksb0JBQW9CLEdBQUcsRUFBRSxDQUFDO1FBQzlCLElBQUksR0FBRyxDQUFDLFFBQVEsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsb0JBQW9CLEVBQUU7WUFDakYsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQztZQUN0RCxLQUFLLE1BQU0sUUFBUSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQ3pDLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDbEMsb0JBQW9CLElBQUksU0FBUyxRQUFRLE1BQU0sU0FBUyxHQUFHLENBQUM7YUFDN0Q7U0FDRjtRQUNELE9BQU8sb0JBQW9CLENBQUM7SUFDOUIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxlQUFlLENBQUMsR0FBUTtRQUMvQixJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFDaEIsTUFBTSxXQUFXLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDMUMsSUFBSSxXQUFXLENBQUMsSUFBSSxFQUFFO1lBQ3BCLE1BQU0sR0FBRzs7Q0FFWixDQUFDO1lBQ0UsTUFBTSxJQUFJLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxJQUFJLElBQUksR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDNUMsSUFBSSxHQUFHLENBQUMsb0JBQW9CLEVBQUU7Z0JBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsb0JBQW9CLENBQUMsQ0FBQzthQUN4QztZQUVELEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxXQUFXLENBQUMsT0FBTyxFQUFFLEVBQUU7Z0JBQ2hELE1BQU0sSUFBSSxpQ0FBaUMsSUFBSTs7Y0FFdkMsSUFBSTtxQ0FDbUIsR0FBRyxDQUFDLElBQUksSUFBSSxJQUFJOztjQUV2QyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxvQkFBb0IsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDOzs7Q0FHbkYsQ0FBQzthQUNHO1NBQ0Y7UUFFRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQsU0FBUyxhQUFhLENBQUMsR0FBUTtRQUM3QixJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFDaEIsTUFBTSxXQUFXLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDMUMsSUFBSSxXQUFXLENBQUMsSUFBSSxFQUFFO1lBQ3BCLE1BQU0sR0FBRzs7Q0FFWixDQUFDO1lBQ0UsTUFBTSxJQUFJLEdBQUcsQ0FBQyxJQUFJLFNBQVMsS0FBSyxHQUFHLENBQUMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQ3pELElBQUksR0FBRyxDQUFDLG9CQUFvQixFQUFFO2dCQUM1QixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLG9CQUFvQixDQUFDLENBQUM7YUFDeEM7WUFFRCxLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksV0FBVyxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUNoRCxNQUFNLEdBQUcsR0FBRyxNQUFNOzttQ0FFVyxJQUFJO01BQ2pDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQzs7O21DQUdNLFNBQVMsS0FBSyxHQUFHLENBQUMsSUFBSSxRQUMvQyxJQUFJOzs7OEJBR2dCLFNBQVMsbUJBQW1CLEdBQUcsQ0FBQyxJQUFJLElBQUksSUFBSTs7c0JBRXBELElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyw4QkFDOUMsb0JBQW9CLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQzs7O0dBR3RDLENBQUM7YUFDQztTQUNGO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQVVEOztPQUVHO0lBQ0gsU0FBUyxVQUFVLENBQUMsS0FBYSxFQUFFLElBQVc7UUFDNUMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDOUUsSUFBSSxJQUFJLEdBQVUsRUFBRSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDakIsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3RixDQUFDLENBQUMsQ0FBQztRQUNILDRCQUE0QjtRQUM1QixJQUFJLEdBQUcsQ0FBQyxHQUFHLElBQUksRUFBRSxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFFbkMsSUFBSSxZQUFZLEdBQUcsRUFBRSxDQUFDO1FBQ3RCLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNmLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLElBQUksR0FBRyxDQUFDLEtBQUssV0FBVyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3hGLFlBQVksR0FBRzs7O1VBR1QsSUFBSTtPQUNQLENBQUM7U0FDTDtRQUVELElBQUksWUFBWSxHQUFHLEVBQUUsQ0FBQztRQUN0QixJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDZixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxLQUFLLGNBQWMsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUMzRixZQUFZLEdBQUc7OztVQUdULElBQUk7T0FDUCxDQUFDO1NBQ0w7UUFFRCxPQUFPOzttQ0FFMEIsS0FBSzs7Y0FFMUIsS0FBSyxLQUFLLFlBQVksR0FBRyxZQUFZOzs7Q0FHbEQsQ0FBQztJQUNGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBUaGUgQmF6ZWwgQXV0aG9ycy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICpcbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbi8qKlxuICogQGZpbGVvdmVydmlldyBUaGlzIHNjcmlwdCBnZW5lcmF0ZXMgQlVJTEQuYmF6ZWwgZmlsZXMgYnkgYW5hbHl6aW5nXG4gKiB0aGUgbm9kZV9tb2R1bGVzIGZvbGRlciBsYXllZCBvdXQgYnkgeWFybiBvciBucG0uIEl0IGdlbmVyYXRlc1xuICogZmluZSBncmFpbmVkIEJhemVsIGBub2RlX21vZHVsZV9saWJyYXJ5YCB0YXJnZXRzIGZvciBlYWNoIHJvb3QgbnBtIHBhY2thZ2VcbiAqIGFuZCBhbGwgZmlsZXMgZm9yIHRoYXQgcGFja2FnZSBhbmQgaXRzIHRyYW5zaXRpdmUgZGVwcyBhcmUgaW5jbHVkZWRcbiAqIGluIHRoZSB0YXJnZXQuIEZvciBleGFtcGxlLCBgQDx3b3Jrc3BhY2U+Ly9qYXNtaW5lYCB3b3VsZFxuICogaW5jbHVkZSBhbGwgZmlsZXMgaW4gdGhlIGphc21pbmUgbnBtIHBhY2thZ2UgYW5kIGFsbCBvZiBpdHNcbiAqIHRyYW5zaXRpdmUgZGVwZW5kZW5jaWVzLlxuICpcbiAqIG5vZGVqc19iaW5hcnkgdGFyZ2V0cyBhcmUgYWxzbyBnZW5lcmF0ZWQgZm9yIGFsbCBgYmluYCBzY3JpcHRzXG4gKiBpbiBlYWNoIHBhY2thZ2UuIEZvciBleGFtcGxlLCB0aGUgYEA8d29ya3NwYWNlPi8vamFzbWluZS9iaW46amFzbWluZWBcbiAqIHRhcmdldCB3aWxsIGJlIGdlbmVyYXRlZCBmb3IgdGhlIGBqYXNtaW5lYCBiaW5hcnkgaW4gdGhlIGBqYXNtaW5lYFxuICogbnBtIHBhY2thZ2UuXG4gKlxuICogQWRkaXRpb25hbGx5LCBhIGBAPHdvcmtzcGFjZT4vLzpub2RlX21vZHVsZXNgIGBub2RlX21vZHVsZV9saWJyYXJ5YFxuICogaXMgZ2VuZXJhdGVkIHRoYXQgaW5jbHVkZXMgYWxsIHBhY2thZ2VzIHVuZGVyIG5vZGVfbW9kdWxlc1xuICogYXMgd2VsbCBhcyB0aGUgLmJpbiBmb2xkZXIuXG4gKlxuICogVGhpcyB3b3JrIGlzIGJhc2VkIG9mZiB0aGUgZmluZSBncmFpbmVkIGRlcHMgY29uY2VwdHMgaW5cbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9wdWJyZWYvcnVsZXNfbm9kZSBkZXZlbG9wZWQgYnkgQHBjai5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL2RvY3VtZW50L2QvMUFmakhNTFZ5RV92WXdsSFNLN2s3eVdfSUlHcHBTeHNRdFBtOVBUcjF4RW9cbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnY3J5cHRvJztcblxuZnVuY3Rpb24gbG9nX3ZlcmJvc2UoLi4ubTogYW55W10pIHtcbiAgaWYgKCEhcHJvY2Vzcy5lbnZbJ1ZFUkJPU0VfTE9HUyddKSBjb25zb2xlLmVycm9yKCdbZ2VuZXJhdGVfYnVpbGRfZmlsZS5qc10nLCAuLi5tKTtcbn1cblxuY29uc3QgQlVJTERfRklMRV9IRUFERVIgPSBgIyBHZW5lcmF0ZWQgZmlsZSBmcm9tIHlhcm5faW5zdGFsbC9ucG1faW5zdGFsbCBydWxlLlxuIyBTZWUgJChiYXplbCBpbmZvIG91dHB1dF9iYXNlKS9leHRlcm5hbC9idWlsZF9iYXplbF9ydWxlc19ub2RlanMvaW50ZXJuYWwvbnBtX2luc3RhbGwvZ2VuZXJhdGVfYnVpbGRfZmlsZS5qc1xuXG4jIEFsbCBydWxlcyBpbiBvdGhlciByZXBvc2l0b3JpZXMgY2FuIHVzZSB0aGVzZSB0YXJnZXRzXG5wYWNrYWdlKGRlZmF1bHRfdmlzaWJpbGl0eSA9IFtcIi8vdmlzaWJpbGl0eTpwdWJsaWNcIl0pXG5cbmBcblxuY29uc3QgYXJncyA9IHByb2Nlc3MuYXJndi5zbGljZSgyKTtcbmNvbnN0IFdPUktTUEFDRSA9IGFyZ3NbMF07XG5jb25zdCBSVUxFX1RZUEUgPSBhcmdzWzFdO1xuY29uc3QgRVJST1JfT05fQkFaRUxfRklMRVMgPSBwYXJzZUludChhcmdzWzJdKTtcbmNvbnN0IExPQ0tfRklMRV9QQVRIID0gYXJnc1szXTtcbmNvbnN0IElOQ0xVREVEX0ZJTEVTID0gYXJnc1s0XSA/IGFyZ3NbNF0uc3BsaXQoJywnKSA6IFtdO1xuY29uc3QgRFlOQU1JQ19ERVBTID0gSlNPTi5wYXJzZShhcmdzWzVdIHx8ICd7fScpO1xuXG5pZiAocmVxdWlyZS5tYWluID09PSBtb2R1bGUpIHtcbiAgbWFpbigpO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIG5ldyBkaXJlY3RvcnkgYW5kIGFueSBuZWNlc3Nhcnkgc3ViZGlyZWN0b3JpZXNcbiAqIGlmIHRoZXkgZG8gbm90IGV4aXN0LlxuICovXG5mdW5jdGlvbiBta2RpcnAocDogc3RyaW5nKSB7XG4gIGlmICghZnMuZXhpc3RzU3luYyhwKSkge1xuICAgIG1rZGlycChwYXRoLmRpcm5hbWUocCkpO1xuICAgIGZzLm1rZGlyU3luYyhwKTtcbiAgfVxufVxuXG4vKipcbiAqIFdyaXRlcyBhIGZpbGUsIGZpcnN0IGVuc3VyaW5nIHRoYXQgdGhlIGRpcmVjdG9yeSB0b1xuICogd3JpdGUgdG8gZXhpc3RzLlxuICovXG5mdW5jdGlvbiB3cml0ZUZpbGVTeW5jKHA6IHN0cmluZywgY29udGVudDogc3RyaW5nKSB7XG4gIG1rZGlycChwYXRoLmRpcm5hbWUocCkpO1xuICBmcy53cml0ZUZpbGVTeW5jKHAsIGNvbnRlbnQpO1xufVxuXG4vKipcbiAqIE1haW4gZW50cnlwb2ludC5cbiAqL1xuZnVuY3Rpb24gbWFpbigpIHtcbiAgLy8gZmluZCBhbGwgcGFja2FnZXMgKGluY2x1ZGluZyBwYWNrYWdlcyBpbiBuZXN0ZWQgbm9kZV9tb2R1bGVzKVxuICBjb25zdCBwa2dzID0gZmluZFBhY2thZ2VzKCk7XG5cbiAgLy8gZmxhdHRlbiBkZXBlbmRlbmNpZXNcbiAgZmxhdHRlbkRlcGVuZGVuY2llcyhwa2dzKTtcblxuICAvLyBnZW5lcmF0ZSBCYXplbCB3b3Jrc3BhY2VzXG4gIGdlbmVyYXRlQmF6ZWxXb3Jrc3BhY2VzKHBrZ3MpXG5cbiAgLy8gZ2VuZXJhdGUgYWxsIEJVSUxEIGZpbGVzXG4gIGdlbmVyYXRlQnVpbGRGaWxlcyhwa2dzKVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgbWFpbixcbiAgcHJpbnRQYWNrYWdlQmluLFxuICBhZGREeW5hbWljRGVwZW5kZW5jaWVzLFxuICBwcmludEluZGV4QnpsLFxufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYWxsIGJ1aWxkIGZpbGVzXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlQnVpbGRGaWxlcyhwa2dzOiBEZXBbXSkge1xuICBnZW5lcmF0ZVJvb3RCdWlsZEZpbGUocGtncy5maWx0ZXIocGtnID0+ICFwa2cuX2lzTmVzdGVkKSlcbiAgcGtncy5maWx0ZXIocGtnID0+ICFwa2cuX2lzTmVzdGVkKS5mb3JFYWNoKHBrZyA9PiBnZW5lcmF0ZVBhY2thZ2VCdWlsZEZpbGVzKHBrZykpO1xuICBmaW5kU2NvcGVzKCkuZm9yRWFjaChzY29wZSA9PiBnZW5lcmF0ZVNjb3BlQnVpbGRGaWxlcyhzY29wZSwgcGtncykpO1xufVxuXG4vKipcbiAqIEZsYXR0ZW5zIGRlcGVuZGVuY2llcyBvbiBhbGwgcGFja2FnZXNcbiAqL1xuZnVuY3Rpb24gZmxhdHRlbkRlcGVuZGVuY2llcyhwa2dzOiBEZXBbXSkge1xuICBjb25zdCBwa2dzTWFwID0gbmV3IE1hcCgpO1xuICBwa2dzLmZvckVhY2gocGtnID0+IHBrZ3NNYXAuc2V0KHBrZy5fZGlyLCBwa2cpKTtcbiAgcGtncy5mb3JFYWNoKHBrZyA9PiBmbGF0dGVuUGtnRGVwZW5kZW5jaWVzKHBrZywgcGtnLCBwa2dzTWFwKSk7XG59XG5cbi8qKlxuICogSGFuZGxlcyBCYXplbCBmaWxlcyBpbiBucG0gZGlzdHJpYnV0aW9ucy5cbiAqL1xuZnVuY3Rpb24gaGlkZUJhemVsRmlsZXMocGtnOiBEZXApIHtcbiAgY29uc3QgaGFzSGlkZUJhemVsRmlsZXMgPSBpc0RpcmVjdG9yeSgnbm9kZV9tb2R1bGVzL0BiYXplbC9oaWRlLWJhemVsLWZpbGVzJyk7XG4gIHBrZy5fZmlsZXMgPSBwa2cuX2ZpbGVzLm1hcChmaWxlID0+IHtcbiAgICBjb25zdCBiYXNlbmFtZSA9IHBhdGguYmFzZW5hbWUoZmlsZSk7XG4gICAgY29uc3QgYmFzZW5hbWVVYyA9IGJhc2VuYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgaWYgKGJhc2VuYW1lVWMgPT09ICdCVUlMRCcgfHwgYmFzZW5hbWVVYyA9PT0gJ0JVSUxELkJBWkVMJykge1xuICAgICAgLy8gSWYgYmF6ZWwgZmlsZXMgYXJlIGRldGVjdGVkIGFuZCB0aGVyZSBpcyBubyBAYmF6ZWwvaGlkZS1iYXplbC1maWxlcyBucG1cbiAgICAgIC8vIHBhY2thZ2UgdGhlbiBlcnJvciBvdXQgYW5kIHN1Z2dlc3QgYWRkaW5nIHRoZSBwYWNrYWdlLiBJdCBpcyBwb3NzaWJsZSB0b1xuICAgICAgLy8gaGF2ZSBiYXplbCBCVUlMRCBmaWxlcyB3aXRoIHRoZSBwYWNrYWdlIGluc3RhbGxlZCBhcyBpdCdzIHBvc3RpbnN0YWxsXG4gICAgICAvLyBzdGVwLCB3aGljaCBoaWRlcyBiYXplbCBCVUlMRCBmaWxlcywgb25seSBydW5zIHdoZW4gdGhlIEBiYXplbC9oaWRlLWJhemVsLWZpbGVzXG4gICAgICAvLyBpcyBpbnN0YWxsZWQgYW5kIG5vdCB3aGVuIG5ldyBwYWNrYWdlcyBhcmUgYWRkZWQgKHZpYSBgeWFybiBhZGRgXG4gICAgICAvLyBmb3IgZXhhbXBsZSkgYWZ0ZXIgdGhlIGluaXRpYWwgaW5zdGFsbC4gSW4gdGhpcyBjYXNlLCBob3dldmVyLCB0aGUgcmVwbyBydWxlXG4gICAgICAvLyB3aWxsIHJlLXJ1biBhcyB0aGUgcGFja2FnZS5qc29uICYmIGxvY2sgZmlsZSBoYXMgY2hhbmdlZCBzbyB3ZSBqdXN0XG4gICAgICAvLyBoaWRlIHRoZSBhZGRlZCBCVUlMRCBmaWxlcyBkdXJpbmcgdGhlIHJlcG8gcnVsZSBydW4gaGVyZSBzaW5jZSBAYmF6ZWwvaGlkZS1iYXplbC1maWxlc1xuICAgICAgLy8gd2FzIG5vdCBydW4uXG4gICAgICBpZiAoIWhhc0hpZGVCYXplbEZpbGVzICYmIEVSUk9SX09OX0JBWkVMX0ZJTEVTKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYG5wbSBwYWNrYWdlICcke3BrZy5fZGlyfScgZnJvbSBAJHtXT1JLU1BBQ0V9ICR7UlVMRV9UWVBFfSBydWxlXG5oYXMgYSBCYXplbCBCVUlMRCBmaWxlICcke2ZpbGV9Jy4gVXNlIHRoZSBAYmF6ZWwvaGlkZS1iYXplbC1maWxlcyB1dGlsaXR5IHRvIGhpZGUgdGhlc2UgZmlsZXMuXG5TZWUgaHR0cHM6Ly9naXRodWIuY29tL2JhemVsYnVpbGQvcnVsZXNfbm9kZWpzL2Jsb2IvbWFzdGVyL3BhY2thZ2VzL2hpZGUtYmF6ZWwtZmlsZXMvUkVBRE1FLm1kXG5mb3IgaW5zdGFsbGF0aW9uIGluc3RydWN0aW9ucy5gKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQWxsIEJhemVsIGZpbGVzIGluIHRoZSBucG0gZGlzdHJpYnV0aW9uIHNob3VsZCBiZSByZW5hbWVkIGJ5XG4gICAgICAgIC8vIGFkZGluZyBhIGBfYCBwcmVmaXggc28gdGhhdCBmaWxlIHRhcmdldHMgZG9uJ3QgY3Jvc3MgcGFja2FnZSBib3VuZGFyaWVzLlxuICAgICAgICBjb25zdCBuZXdGaWxlID0gcGF0aC5wb3NpeC5qb2luKHBhdGguZGlybmFtZShmaWxlKSwgYF8ke2Jhc2VuYW1lfWApO1xuICAgICAgICBjb25zdCBzcmNQYXRoID0gcGF0aC5wb3NpeC5qb2luKCdub2RlX21vZHVsZXMnLCBwa2cuX2RpciwgZmlsZSk7XG4gICAgICAgIGNvbnN0IGRzdFBhdGggPSBwYXRoLnBvc2l4LmpvaW4oJ25vZGVfbW9kdWxlcycsIHBrZy5fZGlyLCBuZXdGaWxlKTtcbiAgICAgICAgZnMucmVuYW1lU3luYyhzcmNQYXRoLCBkc3RQYXRoKTtcbiAgICAgICAgcmV0dXJuIG5ld0ZpbGU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmaWxlO1xuICB9KTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgdGhlIHJvb3QgQlVJTEQgZmlsZS5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVSb290QnVpbGRGaWxlKHBrZ3M6IERlcFtdKSB7XG4gIGxldCBleHBvcnRzU3RhcmxhcmsgPSAnJztcbiAgcGtncy5mb3JFYWNoKHBrZyA9PiB7cGtnLl9maWxlcy5mb3JFYWNoKGYgPT4ge1xuICAgICAgICAgICAgICAgICBleHBvcnRzU3RhcmxhcmsgKz0gYCAgICBcIm5vZGVfbW9kdWxlcy8ke3BrZy5fZGlyfS8ke2Z9XCIsXG5gO1xuICAgICAgICAgICAgICAgfSl9KTtcblxuICBsZXQgc3Jjc1N0YXJsYXJrID0gJyc7XG4gIGlmIChwa2dzLmxlbmd0aCkge1xuICAgIGNvbnN0IGxpc3QgPSBwa2dzLm1hcChwa2cgPT4gYFwiLy8ke3BrZy5fZGlyfToke3BrZy5fbmFtZX1fX2ZpbGVzXCIsYCkuam9pbignXFxuICAgICAgICAnKTtcbiAgICBzcmNzU3RhcmxhcmsgPSBgXG4gICAgIyBkaXJlY3Qgc291cmNlcyBsaXN0ZWQgZm9yIHN0cmljdCBkZXBzIHN1cHBvcnRcbiAgICBzcmNzID0gW1xuICAgICAgICAke2xpc3R9XG4gICAgXSxgO1xuICB9XG5cbiAgbGV0IGRlcHNTdGFybGFyayA9ICcnO1xuICBpZiAocGtncy5sZW5ndGgpIHtcbiAgICBjb25zdCBsaXN0ID0gcGtncy5tYXAocGtnID0+IGBcIi8vJHtwa2cuX2Rpcn06JHtwa2cuX25hbWV9X19jb250ZW50c1wiLGApLmpvaW4oJ1xcbiAgICAgICAgJyk7XG4gICAgZGVwc1N0YXJsYXJrID0gYFxuICAgICMgZmxhdHRlbmVkIGxpc3Qgb2YgZGlyZWN0IGFuZCB0cmFuc2l0aXZlIGRlcGVuZGVuY2llcyBob2lzdGVkIHRvIHJvb3QgYnkgdGhlIHBhY2thZ2UgbWFuYWdlclxuICAgIGRlcHMgPSBbXG4gICAgICAgICR7bGlzdH1cbiAgICBdLGA7XG4gIH1cblxuICBsZXQgYnVpbGRGaWxlID0gQlVJTERfRklMRV9IRUFERVIgK1xuICAgICAgYGxvYWQoXCJAYnVpbGRfYmF6ZWxfcnVsZXNfbm9kZWpzLy9pbnRlcm5hbC9ucG1faW5zdGFsbDpub2RlX21vZHVsZV9saWJyYXJ5LmJ6bFwiLCBcIm5vZGVfbW9kdWxlX2xpYnJhcnlcIilcblxuZXhwb3J0c19maWxlcyhbXG4ke2V4cG9ydHNTdGFybGFya31dKVxuXG4jIFRoZSBub2RlX21vZHVsZXMgZGlyZWN0b3J5IGluIG9uZSBjYXRjaC1hbGwgbm9kZV9tb2R1bGVfbGlicmFyeS5cbiMgTkI6IFVzaW5nIHRoaXMgdGFyZ2V0IG1heSBoYXZlIGJhZCBwZXJmb3JtYW5jZSBpbXBsaWNhdGlvbnMgaWZcbiMgdGhlcmUgYXJlIG1hbnkgZmlsZXMgaW4gdGFyZ2V0LlxuIyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2JhemVsYnVpbGQvYmF6ZWwvaXNzdWVzLzUxNTMuXG5ub2RlX21vZHVsZV9saWJyYXJ5KFxuICAgIG5hbWUgPSBcIm5vZGVfbW9kdWxlc1wiLCR7c3Jjc1N0YXJsYXJrfSR7ZGVwc1N0YXJsYXJrfVxuKVxuXG5gXG5cbiAgLy8gQWRkIHRoZSBtYW51YWwgYnVpbGQgZmlsZSBjb250ZW50cyBpZiB0aGV5IGV4aXN0c1xuICB0cnkge1xuICAgIGJ1aWxkRmlsZSArPSBmcy5yZWFkRmlsZVN5bmMoYG1hbnVhbF9idWlsZF9maWxlX2NvbnRlbnRzYCwge2VuY29kaW5nOiAndXRmOCd9KTtcbiAgfSBjYXRjaCAoZSkge1xuICB9XG5cbiAgd3JpdGVGaWxlU3luYygnQlVJTEQuYmF6ZWwnLCBidWlsZEZpbGUpO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlcyBhbGwgQlVJTEQgJiBiemwgZmlsZXMgZm9yIGEgcGFja2FnZS5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVQYWNrYWdlQnVpbGRGaWxlcyhwa2c6IERlcCkge1xuICBsZXQgYnVpbGRGaWxlID0gcHJpbnRQYWNrYWdlKHBrZyk7XG5cbiAgY29uc3QgYmluQnVpbGRGaWxlID0gcHJpbnRQYWNrYWdlQmluKHBrZyk7XG4gIGlmIChiaW5CdWlsZEZpbGUubGVuZ3RoKSB7XG4gICAgd3JpdGVGaWxlU3luYyhcbiAgICAgICAgcGF0aC5wb3NpeC5qb2luKHBrZy5fZGlyLCAnYmluJywgJ0JVSUxELmJhemVsJyksIEJVSUxEX0ZJTEVfSEVBREVSICsgYmluQnVpbGRGaWxlKTtcbiAgfVxuXG4gIGNvbnN0IGluZGV4RmlsZSA9IHByaW50SW5kZXhCemwocGtnKTtcbiAgaWYgKGluZGV4RmlsZS5sZW5ndGgpIHtcbiAgICB3cml0ZUZpbGVTeW5jKHBhdGgucG9zaXguam9pbihwa2cuX2RpciwgJ2luZGV4LmJ6bCcpLCBpbmRleEZpbGUpO1xuICAgIGJ1aWxkRmlsZSA9IGAke2J1aWxkRmlsZX1cbiMgRm9yIGludGVncmF0aW9uIHRlc3RpbmdcbmV4cG9ydHNfZmlsZXMoW1wiaW5kZXguYnpsXCJdKVxuYDtcbiAgfVxuXG4gIHdyaXRlRmlsZVN5bmMocGF0aC5wb3NpeC5qb2luKHBrZy5fZGlyLCAnQlVJTEQuYmF6ZWwnKSwgQlVJTERfRklMRV9IRUFERVIgKyBidWlsZEZpbGUpO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIGluc3RhbGxfPHdvcmtzcGFjZV9uYW1lPi5iemwgZmlsZXMgd2l0aCBmdW5jdGlvbiB0byBpbnN0YWxsIGVhY2ggd29ya3NwYWNlLlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUJhemVsV29ya3NwYWNlcyhwa2dzOiBEZXBbXSkge1xuICBjb25zdCB3b3Jrc3BhY2VzOiBCYWc8c3RyaW5nPiA9IHt9O1xuXG4gIGZvciAoY29uc3QgcGtnIG9mIHBrZ3MpIHtcbiAgICBpZiAoIXBrZy5iYXplbFdvcmtzcGFjZXMpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgd29ya3NwYWNlIG9mIE9iamVjdC5rZXlzKHBrZy5iYXplbFdvcmtzcGFjZXMpKSB7XG4gICAgICAvLyBBIGJhemVsIHdvcmtzcGFjZSBjYW4gb25seSBiZSBzZXR1cCBieSBvbmUgbnBtIHBhY2thZ2VcbiAgICAgIGlmICh3b3Jrc3BhY2VzW3dvcmtzcGFjZV0pIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgICAgIGBDb3VsZCBub3Qgc2V0dXAgQmF6ZWwgd29ya3NwYWNlICR7d29ya3NwYWNlfSByZXF1ZXN0ZWQgYnkgbnBtIGAgK1xuICAgICAgICAgICAgYHBhY2thZ2UgJHtwa2cuX2Rpcn1AJHtwa2cudmVyc2lvbn0uIEFscmVhZHkgc2V0dXAgYnkgJHt3b3Jrc3BhY2VzW3dvcmtzcGFjZV19YCk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgIH1cblxuICAgICAgZ2VuZXJhdGVCYXplbFdvcmtzcGFjZShwa2csIHdvcmtzcGFjZSk7XG5cbiAgICAgIC8vIEtlZXAgdHJhY2sgb2Ygd2hpY2ggbnBtIHBhY2thZ2Ugc2V0dXAgdGhpcyBiYXplbCB3b3Jrc3BhY2UgZm9yIGxhdGVyIHVzZVxuICAgICAgd29ya3NwYWNlc1t3b3Jrc3BhY2VdID0gYCR7cGtnLl9kaXJ9QCR7cGtnLnZlcnNpb259YDtcbiAgICB9XG4gIH1cblxuICAvLyBGaW5hbGx5IGdlbmVyYXRlIGluc3RhbGxfYmF6ZWxfZGVwZW5kZW5jaWVzLmJ6bFxuICBnZW5lcmF0ZUluc3RhbGxCYXplbERlcGVuZGVuY2llcyhPYmplY3Qua2V5cyh3b3Jrc3BhY2VzKSk7XG59XG5cbi8qKlxuICogR2VuZXJhdGUgaW5zdGFsbF88d29ya3NwYWNlPi5iemwgZmlsZSB3aXRoIGZ1bmN0aW9uIHRvIGluc3RhbGwgdGhlIHdvcmtzcGFjZS5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVCYXplbFdvcmtzcGFjZShwa2c6IERlcCwgd29ya3NwYWNlOiBzdHJpbmcpIHtcbiAgbGV0IGJ6bEZpbGUgPSBgIyBHZW5lcmF0ZWQgYnkgdGhlIHlhcm5faW5zdGFsbC9ucG1faW5zdGFsbCBydWxlXG5sb2FkKFwiQGJ1aWxkX2JhemVsX3J1bGVzX25vZGVqcy8vaW50ZXJuYWwvY29weV9yZXBvc2l0b3J5OmNvcHlfcmVwb3NpdG9yeS5iemxcIiwgXCJjb3B5X3JlcG9zaXRvcnlcIilcblxuZGVmIF9tYXliZShyZXBvX3J1bGUsIG5hbWUsICoqa3dhcmdzKTpcbiAgICBpZiBuYW1lIG5vdCBpbiBuYXRpdmUuZXhpc3RpbmdfcnVsZXMoKTpcbiAgICAgICAgcmVwb19ydWxlKG5hbWUgPSBuYW1lLCAqKmt3YXJncylcbmA7XG5cbiAgY29uc3Qgcm9vdFBhdGggPSBwa2cuYmF6ZWxXb3Jrc3BhY2VzW3dvcmtzcGFjZV0ucm9vdFBhdGg7XG4gIGlmICghcm9vdFBhdGgpIHtcbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICBgTWFsZm9ybWVkIGJhemVsV29ya3NwYWNlcyBhdHRyaWJ1dGUgaW4gJHtwa2cuX2Rpcn1AJHtwa2cudmVyc2lvbn0uIGAgK1xuICAgICAgICBgTWlzc2luZyByb290UGF0aCBmb3Igd29ya3NwYWNlICR7d29ya3NwYWNlfS5gKTtcbiAgICBwcm9jZXNzLmV4aXQoMSk7XG4gIH1cblxuICAvLyBDb3B5IGFsbCBmaWxlcyBmb3IgdGhpcyB3b3Jrc3BhY2UgdG8gYSBmb2xkZXIgdW5kZXIgX3dvcmtzcGFjZXNcbiAgLy8gdG8gcmVzdG9yZSB0aGUgQmF6ZWwgZmlsZXMgd2hpY2ggaGF2ZSBiZSByZW5hbWVkIGZyb20gdGhlIG5wbSBwYWNrYWdlXG4gIGNvbnN0IHdvcmtzcGFjZVNvdXJjZVBhdGggPSBwYXRoLnBvc2l4LmpvaW4oJ193b3Jrc3BhY2VzJywgd29ya3NwYWNlKTtcbiAgbWtkaXJwKHdvcmtzcGFjZVNvdXJjZVBhdGgpO1xuICBwa2cuX2ZpbGVzLmZvckVhY2goZmlsZSA9PiB7XG4gICAgaWYgKC9ebm9kZV9tb2R1bGVzWy9cXFxcXS8udGVzdChmaWxlKSkge1xuICAgICAgLy8gZG9uJ3QgY29weSBvdmVyIG5lc3RlZCBub2RlX21vZHVsZXNcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IGRlc3RGaWxlID0gcGF0aC5yZWxhdGl2ZShyb290UGF0aCwgZmlsZSk7XG4gICAgaWYgKGRlc3RGaWxlLnN0YXJ0c1dpdGgoJy4uJykpIHtcbiAgICAgIC8vIHRoaXMgZmlsZSBpcyBub3QgdW5kZXIgdGhlIHJvb3RQYXRoXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGJhc2VuYW1lID0gcGF0aC5iYXNlbmFtZShmaWxlKTtcbiAgICBjb25zdCBiYXNlbmFtZVVjID0gYmFzZW5hbWUudG9VcHBlckNhc2UoKTtcbiAgICAvLyBCYXplbCBCVUlMRCBmaWxlcyBmcm9tIG5wbSBkaXN0cmlidXRpb24gd291bGQgaGF2ZSBiZWVuIHJlbmFtZWQgZWFybGllciB3aXRoIGEgXyBwcmVmaXggc29cbiAgICAvLyB3ZSByZXN0b3JlIHRoZSBuYW1lIG9uIHRoZSBjb3B5XG4gICAgaWYgKGJhc2VuYW1lVWMgPT09ICdfQlVJTEQnIHx8IGJhc2VuYW1lVWMgPT09ICdfQlVJTEQuQkFaRUwnKSB7XG4gICAgICBkZXN0RmlsZSA9IHBhdGgucG9zaXguam9pbihwYXRoLmRpcm5hbWUoZGVzdEZpbGUpLCBiYXNlbmFtZS5zdWJzdHIoMSkpO1xuICAgIH1cbiAgICBjb25zdCBzcmMgPSBwYXRoLnBvc2l4LmpvaW4oJ25vZGVfbW9kdWxlcycsIHBrZy5fZGlyLCBmaWxlKTtcbiAgICBjb25zdCBkZXN0ID0gcGF0aC5wb3NpeC5qb2luKHdvcmtzcGFjZVNvdXJjZVBhdGgsIGRlc3RGaWxlKTtcbiAgICBta2RpcnAocGF0aC5kaXJuYW1lKGRlc3QpKTtcbiAgICBmcy5jb3B5RmlsZVN5bmMoc3JjLCBkZXN0KTtcbiAgfSk7XG5cbiAgLy8gV2UgY3JlYXRlIF9iYXplbF93b3Jrc3BhY2VfbWFya2VyIHRoYXQgaXMgdXNlZCBieSB0aGUgY3VzdG9tIGNvcHlfcmVwb3NpdG9yeVxuICAvLyBydWxlIHRvIHJlc29sdmUgdGhlIHBhdGggdG8gdGhlIHJlcG9zaXRvcnkgc291cmNlIHJvb3QuIEEgcm9vdCBCVUlMRCBmaWxlXG4gIC8vIGlzIHJlcXVpcmVkIHRvIHJlZmVyZW5jZSBfYmF6ZWxfd29ya3NwYWNlX21hcmtlciBhcyBhIHRhcmdldCBzbyB3ZSBhbHNvIGNyZWF0ZVxuICAvLyBhbiBlbXB0eSBvbmUgaWYgb25lIGRvZXMgbm90IGV4aXN0LlxuICBpZiAoIWhhc1Jvb3RCdWlsZEZpbGUocGtnLCByb290UGF0aCkpIHtcbiAgICB3cml0ZUZpbGVTeW5jKFxuICAgICAgICBwYXRoLnBvc2l4LmpvaW4od29ya3NwYWNlU291cmNlUGF0aCwgJ0JVSUxELmJhemVsJyksXG4gICAgICAgICcjIE1hcmtlciBmaWxlIHRoYXQgdGhpcyBkaXJlY3RvcnkgaXMgYSBiYXplbCBwYWNrYWdlJyk7XG4gIH1cbiAgY29uc3Qgc2hhMjU2c3VtID0gY3J5cHRvLmNyZWF0ZUhhc2goJ3NoYTI1NicpO1xuICBzaGEyNTZzdW0udXBkYXRlKGZzLnJlYWRGaWxlU3luYyhMT0NLX0ZJTEVfUEFUSCwge2VuY29kaW5nOiAndXRmOCd9KSk7XG4gIHdyaXRlRmlsZVN5bmMoXG4gICAgICBwYXRoLnBvc2l4LmpvaW4od29ya3NwYWNlU291cmNlUGF0aCwgJ19iYXplbF93b3Jrc3BhY2VfbWFya2VyJyksXG4gICAgICBgIyBNYXJrZXIgZmlsZSB0byB1c2VkIGJ5IGN1c3RvbSBjb3B5X3JlcG9zaXRvcnkgcnVsZVxcbiR7c2hhMjU2c3VtLmRpZ2VzdCgnaGV4Jyl9YCk7XG5cbiAgYnpsRmlsZSArPSBgZGVmIGluc3RhbGxfJHt3b3Jrc3BhY2V9KCk6XG4gICAgX21heWJlKFxuICAgICAgICBjb3B5X3JlcG9zaXRvcnksXG4gICAgICAgIG5hbWUgPSBcIiR7d29ya3NwYWNlfVwiLFxuICAgICAgICBtYXJrZXJfZmlsZSA9IFwiQCR7V09SS1NQQUNFfS8vX3dvcmtzcGFjZXMvJHt3b3Jrc3BhY2V9Ol9iYXplbF93b3Jrc3BhY2VfbWFya2VyXCIsXG4gICAgKVxuYDtcblxuICB3cml0ZUZpbGVTeW5jKGBpbnN0YWxsXyR7d29ya3NwYWNlfS5iemxgLCBiemxGaWxlKTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZSBpbnN0YWxsX2JhemVsX2RlcGVuZGVuY2llcy5iemwgd2l0aCBmdW5jdGlvbiB0byBpbnN0YWxsIGFsbCB3b3Jrc3BhY2VzLlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUluc3RhbGxCYXplbERlcGVuZGVuY2llcyh3b3Jrc3BhY2VzOiBzdHJpbmdbXSkge1xuICBsZXQgYnpsRmlsZSA9IGAjIEdlbmVyYXRlZCBieSB0aGUgeWFybl9pbnN0YWxsL25wbV9pbnN0YWxsIHJ1bGVcbmA7XG4gIHdvcmtzcGFjZXMuZm9yRWFjaCh3b3Jrc3BhY2UgPT4ge1xuICAgIGJ6bEZpbGUgKz0gYGxvYWQoXFxcIjppbnN0YWxsXyR7d29ya3NwYWNlfS5iemxcXFwiLCBcXFwiaW5zdGFsbF8ke3dvcmtzcGFjZX1cXFwiKVxuYDtcbiAgfSk7XG4gIGJ6bEZpbGUgKz0gYGRlZiBpbnN0YWxsX2JhemVsX2RlcGVuZGVuY2llcygpOlxuICAgIFwiXCJcIkluc3RhbGxzIGFsbCB3b3Jrc3BhY2VzIGxpc3RlZCBpbiBiYXplbFdvcmtzcGFjZXMgb2YgYWxsIG5wbSBwYWNrYWdlc1wiXCJcIlxuYDtcbiAgd29ya3NwYWNlcy5mb3JFYWNoKHdvcmtzcGFjZSA9PiB7XG4gICAgYnpsRmlsZSArPSBgICAgIGluc3RhbGxfJHt3b3Jrc3BhY2V9KClcbmA7XG4gIH0pO1xuXG4gIHdyaXRlRmlsZVN5bmMoJ2luc3RhbGxfYmF6ZWxfZGVwZW5kZW5jaWVzLmJ6bCcsIGJ6bEZpbGUpO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIGJ1aWxkIGZpbGVzIGZvciBhIHNjb3BlLlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZVNjb3BlQnVpbGRGaWxlcyhzY29wZTogc3RyaW5nLCBwa2dzOiBEZXBbXSkge1xuICBjb25zdCBidWlsZEZpbGUgPSBCVUlMRF9GSUxFX0hFQURFUiArIHByaW50U2NvcGUoc2NvcGUsIHBrZ3MpO1xuICB3cml0ZUZpbGVTeW5jKHBhdGgucG9zaXguam9pbihzY29wZSwgJ0JVSUxELmJhemVsJyksIGJ1aWxkRmlsZSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgcGF0aCBpcyBhIGZpbGUuXG4gKi9cbmZ1bmN0aW9uIGlzRmlsZShwOiBzdHJpbmcpIHtcbiAgcmV0dXJuIGZzLmV4aXN0c1N5bmMocCkgJiYgZnMuc3RhdFN5bmMocCkuaXNGaWxlKCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgcGF0aCBpcyBhbiBucG0gcGFja2FnZSB3aGljaCBpcyBpcyBhIGRpcmVjdG9yeSB3aXRoIGEgcGFja2FnZS5qc29uIGZpbGUuXG4gKi9cbmZ1bmN0aW9uIGlzRGlyZWN0b3J5KHA6IHN0cmluZykge1xuICByZXR1cm4gZnMuZXhpc3RzU3luYyhwKSAmJiBmcy5zdGF0U3luYyhwKS5pc0RpcmVjdG9yeSgpO1xufVxuXG4vKipcbiAqIFJldHVybnMgYW4gYXJyYXkgb2YgYWxsIHRoZSBmaWxlcyB1bmRlciBhIGRpcmVjdG9yeSBhcyByZWxhdGl2ZVxuICogcGF0aHMgdG8gdGhlIGRpcmVjdG9yeS5cbiAqL1xuZnVuY3Rpb24gbGlzdEZpbGVzKHJvb3REaXI6IHN0cmluZywgc3ViRGlyOiBzdHJpbmcgPSAnJyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgZGlyID0gcGF0aC5wb3NpeC5qb2luKHJvb3REaXIsIHN1YkRpcik7XG4gIGlmICghaXNEaXJlY3RvcnkoZGlyKSkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICByZXR1cm4gZnMucmVhZGRpclN5bmMoZGlyKVxuICAgICAgLnJlZHVjZShcbiAgICAgICAgICAoZmlsZXM6IHN0cmluZ1tdLCBmaWxlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGgucG9zaXguam9pbihkaXIsIGZpbGUpO1xuICAgICAgICAgICAgY29uc3QgcmVsUGF0aCA9IHBhdGgucG9zaXguam9pbihzdWJEaXIsIGZpbGUpO1xuICAgICAgICAgICAgY29uc3QgaXNTeW1ib2xpY0xpbmsgPSBmcy5sc3RhdFN5bmMoZnVsbFBhdGgpLmlzU3ltYm9saWNMaW5rKCk7XG4gICAgICAgICAgICBsZXQgc3RhdDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHN0YXQgPSBmcy5zdGF0U3luYyhmdWxsUGF0aCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgIGlmIChpc1N5bWJvbGljTGluaykge1xuICAgICAgICAgICAgICAgIC8vIEZpbHRlciBvdXQgYnJva2VuIHN5bWJvbGljIGxpbmtzLiBUaGVzZSBjYXVzZSBmcy5zdGF0U3luYyhmdWxsUGF0aClcbiAgICAgICAgICAgICAgICAvLyB0byBmYWlsIHdpdGggYEVOT0VOVDogbm8gc3VjaCBmaWxlIG9yIGRpcmVjdG9yeSAuLi5gXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZpbGVzO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBpc0RpcmVjdG9yeSA9IHN0YXQuaXNEaXJlY3RvcnkoKTtcbiAgICAgICAgICAgIGlmIChpc0RpcmVjdG9yeSAmJiBpc1N5bWJvbGljTGluaykge1xuICAgICAgICAgICAgICAvLyBGaWx0ZXIgb3V0IHN5bWJvbGljIGxpbmtzIHRvIGRpcmVjdG9yaWVzLiBBbiBpc3N1ZSBpbiB5YXJuIHZlcnNpb25zXG4gICAgICAgICAgICAgIC8vIG9sZGVyIHRoYW4gMS4xMi4xIGNyZWF0ZXMgc3ltYm9saWMgbGlua3MgdG8gZm9sZGVycyBpbiB0aGUgLmJpbiBmb2xkZXJcbiAgICAgICAgICAgICAgLy8gd2hpY2ggbGVhZHMgdG8gQmF6ZWwgdGFyZ2V0cyB0aGF0IGNyb3NzIHBhY2thZ2UgYm91bmRhcmllcy5cbiAgICAgICAgICAgICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9iYXplbGJ1aWxkL3J1bGVzX25vZGVqcy9pc3N1ZXMvNDI4IGFuZFxuICAgICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vYmF6ZWxidWlsZC9ydWxlc19ub2RlanMvaXNzdWVzLzQzOC5cbiAgICAgICAgICAgICAgLy8gVGhpcyBpcyB0ZXN0ZWQgaW4gL2UyZS9maW5lX2dyYWluZWRfc3ltbGlua3MuXG4gICAgICAgICAgICAgIHJldHVybiBmaWxlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpc0RpcmVjdG9yeSA/IGZpbGVzLmNvbmNhdChsaXN0RmlsZXMocm9vdERpciwgcmVsUGF0aCkpIDogZmlsZXMuY29uY2F0KHJlbFBhdGgpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgW10pXG4gICAgICAvLyBGaWxlcyB3aXRoIHNwYWNlcyAoXFx4MjApIG9yIHVuaWNvZGUgY2hhcmFjdGVycyAoPFxceDIwICYmID5cXHg3RSkgYXJlIG5vdCBhbGxvd2VkIGluXG4gICAgICAvLyBCYXplbCBydW5maWxlcy4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9iYXplbGJ1aWxkL2JhemVsL2lzc3Vlcy80MzI3XG4gICAgICAuZmlsdGVyKGYgPT4gIS9bXlxceDIxLVxceDdFXS8udGVzdChmKSlcbiAgICAgIC8vIFdlIHJldHVybiBhIHNvcnRlZCBhcnJheSBzbyB0aGF0IHRoZSBvcmRlciBvZiBmaWxlc1xuICAgICAgLy8gaXMgdGhlIHNhbWUgcmVnYXJkbGVzcyBvZiBwbGF0Zm9ybVxuICAgICAgLnNvcnQoKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIG5wbSBwYWNrYWdlIGRpc3RyaWJ1dGlvbiBjb250YWluZWQgYVxuICogcm9vdCAvQlVJTEQgb3IgL0JVSUxELmJhemVsIGZpbGUuXG4gKi9cbmZ1bmN0aW9uIGhhc1Jvb3RCdWlsZEZpbGUocGtnOiBEZXAsIHJvb3RQYXRoOiBzdHJpbmcpIHtcbiAgZm9yIChjb25zdCBmaWxlIG9mIHBrZy5fZmlsZXMpIHtcbiAgICAvLyBCYXplbCBmaWxlcyB3b3VsZCBoYXZlIGJlZW4gcmVuYW1lZCBlYXJsaWVyIHdpdGggYSBgX2AgcHJlZml4XG4gICAgY29uc3QgZmlsZVVjID0gcGF0aC5yZWxhdGl2ZShyb290UGF0aCwgZmlsZSkudG9VcHBlckNhc2UoKTtcbiAgICBpZiAoZmlsZVVjID09PSAnX0JVSUxEJyB8fCBmaWxlVWMgPT09ICdfQlVJTEQuQkFaRUwnKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5cbmZ1bmN0aW9uIGFkZER5bmFtaWNEZXBlbmRlbmNpZXMocGtnczogRGVwW10sIGR5bmFtaWNfZGVwcyA9IERZTkFNSUNfREVQUykge1xuICBmdW5jdGlvbiBtYXRjaChuYW1lOiBzdHJpbmcsIHA6IERlcCkge1xuICAgIC8vIEF1dG9tYXRpY2FsbHkgaW5jbHVkZSBkeW5hbWljIGRlcGVuZGVuY3kgb24gcGx1Z2lucyBvZiB0aGUgZm9ybSBwa2ctcGx1Z2luLWZvb1xuICAgIGlmIChuYW1lLnN0YXJ0c1dpdGgoYCR7cC5fbW9kdWxlTmFtZX0tcGx1Z2luLWApKSByZXR1cm4gdHJ1ZTtcblxuICAgIGNvbnN0IHZhbHVlID0gZHluYW1pY19kZXBzW3AuX21vZHVsZU5hbWVdO1xuICAgIGlmIChuYW1lID09PSB2YWx1ZSkgcmV0dXJuIHRydWU7XG5cbiAgICAvLyBTdXBwb3J0IHdpbGRjYXJkIG1hdGNoXG4gICAgaWYgKHZhbHVlICYmIHZhbHVlLmluY2x1ZGVzKCcqJykgJiYgbmFtZS5zdGFydHNXaXRoKHZhbHVlLnN1YnN0cmluZygwLCB2YWx1ZS5pbmRleE9mKCcqJykpKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHBrZ3MuZm9yRWFjaChwID0+IHtcbiAgICBwLl9keW5hbWljRGVwZW5kZW5jaWVzID1cbiAgICAgICAgcGtncy5maWx0ZXIoXG4gICAgICAgICAgICAgICAgLy8gRmlsdGVyIGVudHJpZXMgbGlrZVxuICAgICAgICAgICAgICAgIC8vIFwiX2RpclwiOlwiY2hlY2stc2lkZS1lZmZlY3RzL25vZGVfbW9kdWxlcy9yb2xsdXAtcGx1Z2luLW5vZGUtcmVzb2x2ZVwiXG4gICAgICAgICAgICAgICAgeCA9PiAheC5fZGlyLmluY2x1ZGVzKCcvbm9kZV9tb2R1bGVzLycpICYmICEheC5fbW9kdWxlTmFtZSAmJlxuICAgICAgICAgICAgICAgICAgICBtYXRjaCh4Ll9tb2R1bGVOYW1lLCBwKSlcbiAgICAgICAgICAgIC5tYXAoZHluID0+IGAvLyR7ZHluLl9kaXJ9OiR7ZHluLl9uYW1lfWApO1xuICB9KTtcbn1cblxuLyoqXG4gKiBGaW5kcyBhbmQgcmV0dXJucyBhbiBhcnJheSBvZiBhbGwgcGFja2FnZXMgdW5kZXIgYSBnaXZlbiBwYXRoLlxuICovXG5mdW5jdGlvbiBmaW5kUGFja2FnZXMocCA9ICdub2RlX21vZHVsZXMnKSB7XG4gIGlmICghaXNEaXJlY3RvcnkocCkpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBwa2dzOiBEZXBbXSA9IFtdO1xuXG4gIGNvbnN0IGxpc3RpbmcgPSBmcy5yZWFkZGlyU3luYyhwKTtcblxuICBjb25zdCBwYWNrYWdlcyA9IGxpc3RpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgLy8gZmlsdGVyIG91dCBzY29wZXNcbiAgICAgICAgICAgICAgICAgICAgICAgLmZpbHRlcihmID0+ICFmLnN0YXJ0c1dpdGgoJ0AnKSlcbiAgICAgICAgICAgICAgICAgICAgICAgLy8gZmlsdGVyIG91dCBmb2xkZXJzIHN1Y2ggYXMgYC5iaW5gIHdoaWNoIGNhbiBjcmVhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgLy8gaXNzdWVzIG9uIFdpbmRvd3Mgc2luY2UgdGhlc2UgYXJlIFwiaGlkZGVuXCIgYnkgZGVmYXVsdFxuICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKGYgPT4gIWYuc3RhcnRzV2l0aCgnLicpKVxuICAgICAgICAgICAgICAgICAgICAgICAubWFwKGYgPT4gcGF0aC5wb3NpeC5qb2luKHAsIGYpKVxuICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKGYgPT4gaXNEaXJlY3RvcnkoZikpO1xuXG4gIHBhY2thZ2VzLmZvckVhY2goXG4gICAgICBmID0+IHBrZ3MucHVzaChwYXJzZVBhY2thZ2UoZiksIC4uLmZpbmRQYWNrYWdlcyhwYXRoLnBvc2l4LmpvaW4oZiwgJ25vZGVfbW9kdWxlcycpKSkpO1xuXG4gIGNvbnN0IHNjb3BlcyA9IGxpc3RpbmcuZmlsdGVyKGYgPT4gZi5zdGFydHNXaXRoKCdAJykpXG4gICAgICAgICAgICAgICAgICAgICAubWFwKGYgPT4gcGF0aC5wb3NpeC5qb2luKHAsIGYpKVxuICAgICAgICAgICAgICAgICAgICAgLmZpbHRlcihmID0+IGlzRGlyZWN0b3J5KGYpKTtcbiAgc2NvcGVzLmZvckVhY2goZiA9PiBwa2dzLnB1c2goLi4uZmluZFBhY2thZ2VzKGYpKSk7XG5cbiAgYWRkRHluYW1pY0RlcGVuZGVuY2llcyhwa2dzKTtcblxuICByZXR1cm4gcGtncztcbn1cblxuLyoqXG4gKiBGaW5kcyBhbmQgcmV0dXJucyBhbiBhcnJheSBvZiBhbGwgcGFja2FnZSBzY29wZXMgaW4gbm9kZV9tb2R1bGVzLlxuICovXG5mdW5jdGlvbiBmaW5kU2NvcGVzKCkge1xuICBjb25zdCBwID0gJ25vZGVfbW9kdWxlcyc7XG4gIGlmICghaXNEaXJlY3RvcnkocCkpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBsaXN0aW5nID0gZnMucmVhZGRpclN5bmMocCk7XG5cbiAgY29uc3Qgc2NvcGVzID0gbGlzdGluZy5maWx0ZXIoZiA9PiBmLnN0YXJ0c1dpdGgoJ0AnKSlcbiAgICAgICAgICAgICAgICAgICAgIC5tYXAoZiA9PiBwYXRoLnBvc2l4LmpvaW4ocCwgZikpXG4gICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKGYgPT4gaXNEaXJlY3RvcnkoZikpXG4gICAgICAgICAgICAgICAgICAgICAubWFwKGYgPT4gZi5yZXBsYWNlKC9ebm9kZV9tb2R1bGVzXFwvLywgJycpKTtcblxuICByZXR1cm4gc2NvcGVzO1xufVxuXG4vKipcbiAqIEdpdmVuIHRoZSBuYW1lIG9mIGEgdG9wLWxldmVsIGZvbGRlciBpbiBub2RlX21vZHVsZXMsIHBhcnNlIHRoZVxuICogcGFja2FnZSBqc29uIGFuZCByZXR1cm4gaXQgYXMgYW4gb2JqZWN0IGFsb25nIHdpdGhcbiAqIHNvbWUgYWRkaXRpb25hbCBpbnRlcm5hbCBhdHRyaWJ1dGVzIHByZWZpeGVkIHdpdGggJ18nLlxuICovXG5mdW5jdGlvbiBwYXJzZVBhY2thZ2UocDogc3RyaW5nKTogRGVwIHtcbiAgLy8gUGFyc2UgdGhlIHBhY2thZ2UuanNvbiBmaWxlIG9mIHRoaXMgcGFja2FnZVxuICBjb25zdCBwYWNrYWdlSnNvbiA9IHBhdGgucG9zaXguam9pbihwLCAncGFja2FnZS5qc29uJyk7XG4gIGNvbnN0IHBrZyA9IGlzRmlsZShwYWNrYWdlSnNvbikgPyBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhwYWNrYWdlSnNvbiwge2VuY29kaW5nOiAndXRmOCd9KSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3ZlcnNpb246ICcwLjAuMCd9O1xuXG4gIC8vIFRyaW0gdGhlIGxlYWRpbmcgbm9kZV9tb2R1bGVzIGZyb20gdGhlIHBhdGggYW5kXG4gIC8vIGFzc2lnbiB0byBfZGlyIGZvciBmdXR1cmUgdXNlXG4gIHBrZy5fZGlyID0gcC5yZXBsYWNlKC9ebm9kZV9tb2R1bGVzXFwvLywgJycpO1xuXG4gIC8vIFN0YXNoIHRoZSBwYWNrYWdlIGRpcmVjdG9yeSBuYW1lIGZvciBmdXR1cmUgdXNlXG4gIHBrZy5fbmFtZSA9IHBrZy5fZGlyLnNwbGl0KCcvJykucG9wKCk7XG5cbiAgLy8gTW9kdWxlIG5hbWUgb2YgdGhlIHBhY2thZ2UuIFVubGlrZSBcIl9uYW1lXCIgdGhpcyByZXByZXNlbnRzIHRoZVxuICAvLyBmdWxsIHBhY2thZ2UgbmFtZSAoaW5jbHVkaW5nIHNjb3BlIG5hbWUpLlxuICBwa2cuX21vZHVsZU5hbWUgPSBwa2cubmFtZSB8fCBgJHtwa2cuX2Rpcn0vJHtwa2cuX25hbWV9YDtcblxuICAvLyBLZWVwIHRyYWNrIG9mIHdoZXRoZXIgb3Igbm90IHRoaXMgaXMgYSBuZXN0ZWQgcGFja2FnZVxuICBwa2cuX2lzTmVzdGVkID0gL1xcL25vZGVfbW9kdWxlc1xcLy8udGVzdChwKTtcblxuICAvLyBMaXN0IGFsbCB0aGUgZmlsZXMgaW4gdGhlIG5wbSBwYWNrYWdlIGZvciBsYXRlciB1c2VcbiAgcGtnLl9maWxlcyA9IGxpc3RGaWxlcyhwKTtcblxuICAvLyBJbml0aWFsaXplIF9kZXBlbmRlbmNpZXMgdG8gYW4gZW1wdHkgYXJyYXlcbiAgLy8gd2hpY2ggaXMgbGF0ZXIgZmlsbGVkIHdpdGggdGhlIGZsYXR0ZW5lZCBkZXBlbmRlbmN5IGxpc3RcbiAgcGtnLl9kZXBlbmRlbmNpZXMgPSBbXTtcblxuICAvLyBIaWRlIGJhemVsIGZpbGVzIGluIHRoaXMgcGFja2FnZS4gV2UgZG8gdGhpcyBiZWZvcmUgcGFyc2luZ1xuICAvLyB0aGUgbmV4dCBwYWNrYWdlIHRvIHByZXZlbnQgaXNzdWVzIGNhdXNlZCBieSBzeW1saW5rcyBiZXR3ZWVuXG4gIC8vIHBhY2thZ2UgYW5kIG5lc3RlZCBwYWNrYWdlcyBzZXR1cCBieSB0aGUgcGFja2FnZSBtYW5hZ2VyLlxuICBoaWRlQmF6ZWxGaWxlcyhwa2cpO1xuXG4gIHJldHVybiBwa2c7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgYSBiaW4gZW50cnkgaXMgYSBub24tZW1wdHkgcGF0aFxuICovXG5mdW5jdGlvbiBpc1ZhbGlkQmluUGF0aChlbnRyeTogYW55KSB7XG4gIHJldHVybiBpc1ZhbGlkQmluUGF0aFN0cmluZ1ZhbHVlKGVudHJ5KSB8fCBpc1ZhbGlkQmluUGF0aE9iamVjdFZhbHVlcyhlbnRyeSk7XG59XG5cbi8qKlxuICogSWYgZ2l2ZW4gYSBzdHJpbmcsIGNoZWNrIGlmIGEgYmluIGVudHJ5IGlzIGEgbm9uLWVtcHR5IHBhdGhcbiAqL1xuZnVuY3Rpb24gaXNWYWxpZEJpblBhdGhTdHJpbmdWYWx1ZShlbnRyeTogYW55KSB7XG4gIHJldHVybiB0eXBlb2YgZW50cnkgPT09ICdzdHJpbmcnICYmIGVudHJ5ICE9PSAnJztcbn1cblxuLyoqXG4gKiBJZiBnaXZlbiBhbiBvYmplY3QgbGl0ZXJhbCwgY2hlY2sgaWYgYSBiaW4gZW50cnkgb2JqZWN0cyBoYXMgYXQgbGVhc3Qgb25lIGEgbm9uLWVtcHR5IHBhdGhcbiAqIEV4YW1wbGUgMTogeyBlbnRyeTogJy4vcGF0aC90by9zY3JpcHQuanMnIH0gPT0+IFZBTElEXG4gKiBFeGFtcGxlIDI6IHsgZW50cnk6ICcnIH0gPT0+IElOVkFMSURcbiAqIEV4YW1wbGUgMzogeyBlbnRyeTogJy4vcGF0aC90by9zY3JpcHQuanMnLCBlbXB0eTogJycgfSA9PT4gVkFMSURcbiAqL1xuZnVuY3Rpb24gaXNWYWxpZEJpblBhdGhPYmplY3RWYWx1ZXMoZW50cnk6IEJhZzxzdHJpbmc+KTogYm9vbGVhbiB7XG4gIC8vIFdlIGFsbG93IGF0IGxlYXN0IG9uZSB2YWxpZCBlbnRyeSBwYXRoIChpZiBhbnkpLlxuICByZXR1cm4gZW50cnkgJiYgdHlwZW9mIGVudHJ5ID09PSAnb2JqZWN0JyAmJlxuICAgICAgT2JqZWN0Wyd2YWx1ZXMnXShlbnRyeSkuZmlsdGVyKF9lbnRyeSA9PiBpc1ZhbGlkQmluUGF0aChfZW50cnkpKS5sZW5ndGggPiAwO1xufVxuXG4vKipcbiAqIENsZWFudXAgYSBwYWNrYWdlLmpzb24gXCJiaW5cIiBwYXRoLlxuICpcbiAqIEJpbiBwYXRocyB1c3VhbGx5IGNvbWUgaW4gMiBmbGF2b3JzOiAnLi9iaW4vZm9vJyBvciAnYmluL2ZvbycsXG4gKiBzb21ldGltZXMgb3RoZXIgc3R1ZmYgbGlrZSAnbGliL2ZvbycuICBSZW1vdmUgcHJlZml4ICcuLycgaWYgaXRcbiAqIGV4aXN0cy5cbiAqL1xuZnVuY3Rpb24gY2xlYW51cEJpblBhdGgocDogc3RyaW5nKSB7XG4gIHAgPSBwLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgaWYgKHAuaW5kZXhPZignLi8nKSA9PT0gMCkge1xuICAgIHAgPSBwLnNsaWNlKDIpO1xuICB9XG4gIHJldHVybiBwO1xufVxuXG4vKipcbiAqIENsZWFudXAgYSBwYWNrYWdlLmpzb24gZW50cnkgcG9pbnQgc3VjaCBhcyBcIm1haW5cIlxuICpcbiAqIFJlbW92ZXMgJy4vJyBpZiBpdCBleGlzdHMuXG4gKiBBcHBlbmRzIGBpbmRleC5qc2AgaWYgcCBlbmRzIHdpdGggYC9gLlxuICovXG5mdW5jdGlvbiBjbGVhbnVwRW50cnlQb2ludFBhdGgocDogc3RyaW5nKSB7XG4gIHAgPSBwLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgaWYgKHAuaW5kZXhPZignLi8nKSA9PT0gMCkge1xuICAgIHAgPSBwLnNsaWNlKDIpO1xuICB9XG4gIGlmIChwLmVuZHNXaXRoKCcvJykpIHtcbiAgICBwICs9ICdpbmRleC5qcyc7XG4gIH1cbiAgcmV0dXJuIHA7XG59XG5cbi8qKlxuICogQ2xlYW5zIHVwIHRoZSBnaXZlbiBwYXRoXG4gKiBUaGVuIHRyaWVzIHRvIHJlc29sdmUgdGhlIHBhdGggaW50byBhIGZpbGUgYW5kIHdhcm5zIGlmIFZFUkJPU0VfTE9HUyBzZXQgYW5kIHRoZSBmaWxlIGRvc2VuJ3RcbiAqIGV4aXN0XG4gKiBAcGFyYW0ge2FueX0gcGtnXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aFxuICogQHJldHVybnMge3N0cmluZyB8IHVuZGVmaW5lZH1cbiAqL1xuZnVuY3Rpb24gZmluZEVudHJ5RmlsZShwa2c6IERlcCwgcGF0aDogc3RyaW5nKSB7XG4gIGNvbnN0IGNsZWFuUGF0aCA9IGNsZWFudXBFbnRyeVBvaW50UGF0aChwYXRoKTtcbiAgLy8gY2hlY2sgaWYgbWFpbiBlbnRyeSBwb2ludCBleGlzdHNcbiAgY29uc3QgZW50cnlGaWxlID0gZmluZEZpbGUocGtnLCBjbGVhblBhdGgpIHx8IGZpbmRGaWxlKHBrZywgYCR7Y2xlYW5QYXRofS5qc2ApO1xuICBpZiAoIWVudHJ5RmlsZSkge1xuICAgIC8vIElmIGVudHJ5UG9pbnQgZW50cnkgcG9pbnQgbGlzdGVkIGNvdWxkIG5vdCBiZSByZXNvbHZlZCB0byBhIGZpbGVcbiAgICAvLyBUaGlzIGNhbiBoYXBwZW5cbiAgICAvLyBpbiBzb21lIG5wbSBwYWNrYWdlcyB0aGF0IGxpc3QgYW4gaW5jb3JyZWN0IG1haW4gc3VjaCBhcyB2OC1jb3ZlcmFnZUAxLjAuOFxuICAgIC8vIHdoaWNoIGxpc3RzIGBcIm1haW5cIjogXCJpbmRleC5qc1wiYCBidXQgdGhhdCBmaWxlIGRvZXMgbm90IGV4aXN0LlxuICAgIGxvZ192ZXJib3NlKFxuICAgICAgICBgY291bGQgbm90IGZpbmQgZW50cnkgcG9pbnQgZm9yIHRoZSBwYXRoICR7Y2xlYW5QYXRofSBnaXZlbiBieSBucG0gcGFja2FnZSAke3BrZy5fbmFtZX1gKTtcbiAgfVxuICByZXR1cm4gZW50cnlGaWxlO1xufVxuXG4vKipcbiAqIFRyaWVzIHRvIHJlc29sdmUgdGhlIGVudHJ5UG9pbnQgZmlsZSBmcm9tIHRoZSBwa2cgZm9yIGEgZ2l2ZW4gbWFpbkZpbGVOYW1lXG4gKlxuICogQHBhcmFtIHthbnl9IHBrZ1xuICogQHBhcmFtIHsnYnJvd3NlcicgfCAnbW9kdWxlJyB8ICdtYWluJ30gbWFpbkZpbGVOYW1lXG4gKiBAcmV0dXJucyB7c3RyaW5nIHwgdW5kZWZpbmVkfSB0aGUgcGF0aCBvciB1bmRlZmluZWQgaWYgd2UgY2FudCByZXNvbHZlIHRoZSBmaWxlXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVNYWluRmlsZShwa2c6IERlcCwgbWFpbkZpbGVOYW1lOiBzdHJpbmcpIHtcbiAgY29uc3QgbWFpbkVudHJ5RmllbGQgPSBwa2dbbWFpbkZpbGVOYW1lXTtcblxuICBpZiAobWFpbkVudHJ5RmllbGQpIHtcbiAgICBpZiAodHlwZW9mIG1haW5FbnRyeUZpZWxkID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIGZpbmRFbnRyeUZpbGUocGtnLCBtYWluRW50cnlGaWVsZClcblxuICAgIH0gZWxzZSBpZiAodHlwZW9mIG1haW5FbnRyeUZpZWxkID09PSAnb2JqZWN0JyAmJiBtYWluRmlsZU5hbWUgPT09ICdicm93c2VyJykge1xuICAgICAgLy8gYnJvd3NlciBoYXMgYSB3ZWlyZCB3YXkgb2YgZGVmaW5pbmcgdGhpc1xuICAgICAgLy8gdGhlIGJyb3dzZXIgdmFsdWUgaXMgYW4gb2JqZWN0IGxpc3RpbmcgZmlsZXMgdG8gYWxpYXMsIHVzdWFsbHkgcG9pbnRpbmcgdG8gYSBicm93c2VyIGRpclxuICAgICAgY29uc3QgaW5kZXhFbnRyeVBvaW50ID0gbWFpbkVudHJ5RmllbGRbJ2luZGV4LmpzJ10gfHwgbWFpbkVudHJ5RmllbGRbJy4vaW5kZXguanMnXTtcbiAgICAgIGlmIChpbmRleEVudHJ5UG9pbnQpIHtcbiAgICAgICAgcmV0dXJuIGZpbmRFbnRyeUZpbGUocGtnLCBpbmRleEVudHJ5UG9pbnQpXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogVHJpZXMgdG8gcmVzb2x2ZSB0aGUgbWFpbkZpbGUgZnJvbSBhIGdpdmVuIHBrZ1xuICogVGhpcyB1c2VzIHNldmVhbCBtYWluRmlsZU5hbWVzIGluIHByaW9yaXR5IHRvIGZpbmQgYSBjb3JyZWN0IHVzYWJsZSBmaWxlXG4gKiBAcGFyYW0ge2FueX0gcGtnXG4gKiBAcmV0dXJucyB7c3RyaW5nIHwgdW5kZWZpbmVkfVxuICovXG5mdW5jdGlvbiByZXNvbHZlUGtnTWFpbkZpbGUocGtnOiBEZXApIHtcbiAgLy8gZXMyMDE1IGlzIGFub3RoZXIgb3B0aW9uIGZvciBtYWluRmlsZSBoZXJlXG4gIC8vIGJ1dCBpdHMgdmVyeSB1bmNvbW1vbiBhbmQgaW0gbm90IHN1cmUgd2hhdCBwcmlvcml0eSBpdCB0YWtlc1xuICAvL1xuICAvLyB0aGlzIGxpc3QgaXMgb3JkZXJlZCwgd2UgdHJ5IHJlc29sdmUgYGJyb3dzZXJgIGZpcnN0LCB0aGVuIGBtb2R1bGVgIGFuZCBmaW5hbGx5IGZhbGwgYmFjayB0b1xuICAvLyBgbWFpbmBcbiAgY29uc3QgbWFpbkZpbGVOYW1lcyA9IFsnYnJvd3NlcicsICdtb2R1bGUnLCAnbWFpbiddXG5cbiAgICAgIGZvciAoY29uc3QgbWFpbkZpbGUgb2YgbWFpbkZpbGVOYW1lcykge1xuICAgIGNvbnN0IHJlc29sdmVkTWFpbkZpbGUgPSByZXNvbHZlTWFpbkZpbGUocGtnLCBtYWluRmlsZSk7XG4gICAgaWYgKHJlc29sdmVkTWFpbkZpbGUpIHtcbiAgICAgIHJldHVybiByZXNvbHZlZE1haW5GaWxlO1xuICAgIH1cbiAgfVxuXG4gIC8vIGlmIHdlIGNhbnQgZmluZCBhbnkgY29ycmVjdCBmaWxlIHJlZmVyZW5jZXMgZnJvbSB0aGUgcGtnXG4gIC8vIHRoZW4gd2UganVzdCB0cnkgbG9va2luZyBhcm91bmQgZm9yIGNvbW1vbiBwYXR0ZXJuc1xuICBjb25zdCBtYXliZVJvb3RJbmRleCA9IGZpbmRFbnRyeUZpbGUocGtnLCAnaW5kZXguanMnKTtcbiAgaWYgKG1heWJlUm9vdEluZGV4KSB7XG4gICAgcmV0dXJuIG1heWJlUm9vdEluZGV4XG4gIH1cblxuICBjb25zdCBtYXliZVNlbGZOYW1lZEluZGV4ID0gZmluZEVudHJ5RmlsZShwa2csIGAke3BrZy5fbmFtZX0uanNgKTtcbiAgaWYgKG1heWJlU2VsZk5hbWVkSW5kZXgpIHtcbiAgICByZXR1cm4gbWF5YmVTZWxmTmFtZWRJbmRleDtcbiAgfVxuXG4gIC8vIG5vbmUgb2YgdGhlIG1ldGhvZHMgd2UgdHJpZWQgcmVzdWx0ZWQgaW4gYSBmaWxlXG4gIGxvZ192ZXJib3NlKGBjb3VsZCBub3QgZmluZCBlbnRyeSBwb2ludCBmb3IgbnBtIHBhY2thZ2UgJHtwa2cuX25hbWV9YCk7XG5cbiAgLy8gYXQgdGhpcyBwb2ludCB0aGVyZSdzIG5vdGhpbmcgbGVmdCBmb3IgdXMgdG8gdHJ5LCBzbyByZXR1cm4gbm90aGluZ1xuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG50eXBlIEJhZzxUPiA9XG4gICAge1xuICAgICAgW2s6IHN0cmluZ106IFRcbiAgICB9XG5cbi8qKlxuICogRmxhdHRlbnMgYWxsIHRyYW5zaXRpdmUgZGVwZW5kZW5jaWVzIG9mIGEgcGFja2FnZVxuICogaW50byBhIF9kZXBlbmRlbmNpZXMgYXJyYXkuXG4gKi9cbmZ1bmN0aW9uIGZsYXR0ZW5Qa2dEZXBlbmRlbmNpZXMocGtnOiBEZXAsIGRlcDogRGVwLCBwa2dzTWFwOiBNYXA8c3RyaW5nLCBEZXA+KSB7XG4gIGlmIChwa2cuX2RlcGVuZGVuY2llcy5pbmRleE9mKGRlcCkgIT09IC0xKSB7XG4gICAgLy8gY2lyY3VsYXIgZGVwZW5kZW5jeVxuICAgIHJldHVybjtcbiAgfVxuICBwa2cuX2RlcGVuZGVuY2llcy5wdXNoKGRlcCk7XG4gIGNvbnN0IGZpbmREZXBzID0gZnVuY3Rpb24odGFyZ2V0RGVwczogQmFnPHN0cmluZz4sIHJlcXVpcmVkOiBib29sZWFuLCBkZXBUeXBlOiBzdHJpbmcpIHtcbiAgICBPYmplY3Qua2V5cyh0YXJnZXREZXBzIHx8IHt9KVxuICAgICAgICAubWFwKHRhcmdldERlcCA9PiB7XG4gICAgICAgICAgLy8gbG9vayBmb3IgbWF0Y2hpbmcgbmVzdGVkIHBhY2thZ2VcbiAgICAgICAgICBjb25zdCBkaXJTZWdtZW50cyA9IGRlcC5fZGlyLnNwbGl0KCcvJyk7XG4gICAgICAgICAgd2hpbGUgKGRpclNlZ21lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgbWF5YmUgPSBwYXRoLnBvc2l4LmpvaW4oLi4uZGlyU2VnbWVudHMsICdub2RlX21vZHVsZXMnLCB0YXJnZXREZXApO1xuICAgICAgICAgICAgaWYgKHBrZ3NNYXAuaGFzKG1heWJlKSkge1xuICAgICAgICAgICAgICByZXR1cm4gcGtnc01hcC5nZXQobWF5YmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGlyU2VnbWVudHMucG9wKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIGxvb2sgZm9yIG1hdGNoaW5nIHJvb3QgcGFja2FnZVxuICAgICAgICAgIGlmIChwa2dzTWFwLmhhcyh0YXJnZXREZXApKSB7XG4gICAgICAgICAgICByZXR1cm4gcGtnc01hcC5nZXQodGFyZ2V0RGVwKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gZGVwZW5kZW5jeSBub3QgZm91bmRcbiAgICAgICAgICBpZiAocmVxdWlyZWQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYGNvdWxkIG5vdCBmaW5kICR7ZGVwVHlwZX0gJyR7dGFyZ2V0RGVwfScgb2YgJyR7ZGVwLl9kaXJ9J2ApO1xuICAgICAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfSlcbiAgICAgICAgLmZpbHRlcihkZXAgPT4gISFkZXApXG4gICAgICAgIC5mb3JFYWNoKGRlcCA9PiBmbGF0dGVuUGtnRGVwZW5kZW5jaWVzKHBrZywgZGVwISwgcGtnc01hcCkpO1xuICB9O1xuICAvLyBucG0gd2lsbCBpbiBzb21lIGNhc2VzIGFkZCBvcHRpb25hbERlcGVuZGVuY2llcyB0byB0aGUgbGlzdFxuICAvLyBvZiBkZXBlbmRlbmNpZXMgdG8gdGhlIHBhY2thZ2UuanNvbiBpdCB3cml0ZXMgdG8gbm9kZV9tb2R1bGVzLlxuICAvLyBXZSBkZWxldGUgdGhlc2UgaGVyZSBpZiB0aGV5IGV4aXN0IGFzIHRoZXkgbWF5IHJlc3VsdFxuICAvLyBpbiBleHBlY3RlZCBkZXBlbmRlbmNpZXMgdGhhdCBhcmUgbm90IGZvdW5kLlxuICBpZiAoZGVwLmRlcGVuZGVuY2llcyAmJiBkZXAub3B0aW9uYWxEZXBlbmRlbmNpZXMpIHtcbiAgICBPYmplY3Qua2V5cyhkZXAub3B0aW9uYWxEZXBlbmRlbmNpZXMpLmZvckVhY2gob3B0aW9uYWxEZXAgPT4ge1xuICAgICAgZGVsZXRlIGRlcC5kZXBlbmRlbmNpZXNbb3B0aW9uYWxEZXBdO1xuICAgIH0pO1xuICB9XG5cbiAgZmluZERlcHMoZGVwLmRlcGVuZGVuY2llcywgdHJ1ZSwgJ2RlcGVuZGVuY3knKTtcbiAgZmluZERlcHMoZGVwLnBlZXJEZXBlbmRlbmNpZXMsIHRydWUsICdwZWVyIGRlcGVuZGVuY3knKTtcbiAgLy8gYG9wdGlvbmFsRGVwZW5kZW5jaWVzYCB0aGF0IGFyZSBtaXNzaW5nIHNob3VsZCBiZSBzaWxlbnRseVxuICAvLyBpZ25vcmVkIHNpbmNlIHRoZSBucG0veWFybiB3aWxsIG5vdCBmYWlsIGlmIHRoZXNlIGRlcGVuZGVuY2llc1xuICAvLyBmYWlsIHRvIGluc3RhbGwuIFBhY2thZ2VzIHNob3VsZCBoYW5kbGUgdGhlIGNhc2VzIHdoZXJlIHRoZXNlXG4gIC8vIGRlcGVuZGVuY2llcyBhcmUgbWlzc2luZyBncmFjZWZ1bGx5IGF0IHJ1bnRpbWUuXG4gIC8vIEFuIGV4YW1wbGUgb2YgdGhpcyBpcyB0aGUgYGNob2tpZGFyYCBwYWNrYWdlIHdoaWNoIHNwZWNpZmllc1xuICAvLyBgZnNldmVudHNgIGFzIGFuIG9wdGlvbmFsRGVwZW5kZW5jeS4gT24gT1NYLCBgZnNldmVudHNgXG4gIC8vIGlzIGluc3RhbGxlZCBzdWNjZXNzZnVsbHksIGJ1dCBvbiBXaW5kb3dzICYgTGludXgsIGBmc2V2ZW50c2BcbiAgLy8gZmFpbHMgdG8gaW5zdGFsbCBhbmQgdGhlIHBhY2thZ2Ugd2lsbCBub3QgYmUgcHJlc2VudCB3aGVuXG4gIC8vIGNoZWNraW5nIHRoZSBkZXBlbmRlbmNpZXMgb2YgYGNob2tpZGFyYC5cbiAgZmluZERlcHMoZGVwLm9wdGlvbmFsRGVwZW5kZW5jaWVzLCBmYWxzZSwgJ29wdGlvbmFsIGRlcGVuZGVuY3knKTtcbn1cblxuLyoqXG4gKiBSZWZvcm1hdC9wcmV0dHktcHJpbnQgYSBqc29uIG9iamVjdCBhcyBhIHNreWxhcmsgY29tbWVudCAoZWFjaCBsaW5lXG4gKiBzdGFydHMgd2l0aCAnIyAnKS5cbiAqL1xuZnVuY3Rpb24gcHJpbnRKc29uKHBrZzogRGVwKSB7XG4gIC8vIENsb25lIGFuZCBtb2RpZnkgX2RlcGVuZGVuY2llcyB0byBhdm9pZCBjaXJjdWxhciBpc3N1ZXMgd2hlbiBKU09OaWZ5aW5nXG4gIC8vICYgZGVsZXRlIF9maWxlcyBhcnJheVxuICBjb25zdCBjbG9uZWQ6IGFueSA9IHsuLi5wa2d9O1xuICBjbG9uZWQuX2RlcGVuZGVuY2llcyA9IHBrZy5fZGVwZW5kZW5jaWVzLm1hcChkZXAgPT4gZGVwLl9kaXIpO1xuICBkZWxldGUgY2xvbmVkLl9maWxlcztcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGNsb25lZCwgbnVsbCwgMikuc3BsaXQoJ1xcbicpLm1hcChsaW5lID0+IGAjICR7bGluZX1gKS5qb2luKCdcXG4nKTtcbn1cblxuLyoqXG4gKiBBIGZpbHRlciBmdW5jdGlvbiBmb3IgZmlsZXMgaW4gYW4gbnBtIHBhY2thZ2UuIENvbXBhcmlzb24gaXMgY2FzZS1pbnNlbnNpdGl2ZS5cbiAqIEBwYXJhbSBmaWxlcyBhcnJheSBvZiBmaWxlcyB0byBmaWx0ZXJcbiAqIEBwYXJhbSBleHRzIGxpc3Qgb2Ygd2hpdGUgbGlzdGVkIGNhc2UtaW5zZW5zaXRpdmUgZXh0ZW5zaW9uczsgaWYgZW1wdHksIG5vIGZpbHRlciBpc1xuICogICAgICAgICAgICAgZG9uZSBvbiBleHRlbnNpb25zOyAnJyBlbXB0eSBzdHJpbmcgZGVub3RlcyB0byBhbGxvdyBmaWxlcyB3aXRoIG5vIGV4dGVuc2lvbnMsXG4gKiAgICAgICAgICAgICBvdGhlciBleHRlbnNpb25zIGFyZSBsaXN0ZWQgd2l0aCAnLmV4dCcgbm90YXRpb24gc3VjaCBhcyAnLmQudHMnLlxuICovXG5mdW5jdGlvbiBmaWx0ZXJGaWxlcyhmaWxlczogc3RyaW5nW10sIGV4dHM6IHN0cmluZ1tdID0gW10pIHtcbiAgaWYgKGV4dHMubGVuZ3RoKSB7XG4gICAgY29uc3QgYWxsb3dOb0V4dHMgPSBleHRzLmluY2x1ZGVzKCcnKTtcbiAgICBmaWxlcyA9IGZpbGVzLmZpbHRlcihmID0+IHtcbiAgICAgIC8vIGluY2x1ZGUgZmlsZXMgd2l0aCBubyBleHRlbnNpb25zIGlmIG5vRXh0IGlzIHRydWVcbiAgICAgIGlmIChhbGxvd05vRXh0cyAmJiAhcGF0aC5leHRuYW1lKGYpKSByZXR1cm4gdHJ1ZTtcbiAgICAgIC8vIGZpbHRlciBmaWxlcyBpbiBleHRzXG4gICAgICBjb25zdCBsYyA9IGYudG9Mb3dlckNhc2UoKTtcbiAgICAgIGZvciAoY29uc3QgZSBvZiBleHRzKSB7XG4gICAgICAgIGlmIChlICYmIGxjLmVuZHNXaXRoKGUudG9Mb3dlckNhc2UoKSkpIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0pXG4gIH1cbiAgLy8gRmlsdGVyIG91dCBCVUlMRCBmaWxlcyB0aGF0IGNhbWUgd2l0aCB0aGUgbnBtIHBhY2thZ2VcbiAgcmV0dXJuIGZpbGVzLmZpbHRlcihmaWxlID0+IHtcbiAgICBjb25zdCBiYXNlbmFtZVVjID0gcGF0aC5iYXNlbmFtZShmaWxlKS50b1VwcGVyQ2FzZSgpO1xuICAgIGlmIChiYXNlbmFtZVVjID09PSAnX0JVSUxEJyB8fCBiYXNlbmFtZVVjID09PSAnX0JVSUxELkJBWkVMJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgYHBrZ2AgY29uZm9ybXMgdG8gQW5ndWxhciBQYWNrYWdlIEZvcm1hdCAoQVBGKSxcbiAqIGZhbHNlIG90aGVyd2lzZS4gSWYgdGhlIHBhY2thZ2UgY29udGFpbnMgYCoubWV0YWRhdGEuanNvbmAgYW5kIGFcbiAqIGNvcnJlc3BvbmRpbmcgc2libGluZyBgLmQudHNgIGZpbGUsIHRoZW4gdGhlIHBhY2thZ2UgaXMgY29uc2lkZXJlZCB0byBiZSBBUEYuXG4gKi9cbmZ1bmN0aW9uIGlzTmdBcGZQYWNrYWdlKHBrZzogRGVwKSB7XG4gIGNvbnN0IHNldCA9IG5ldyBTZXQocGtnLl9maWxlcyk7XG4gIGlmIChzZXQuaGFzKCdBTkdVTEFSX1BBQ0tBR0UnKSkge1xuICAgIC8vIFRoaXMgZmlsZSBpcyB1c2VkIGJ5IHRoZSBucG0veWFybl9pbnN0YWxsIHJ1bGUgdG8gZGV0ZWN0IEFQRi4gU2VlXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2JhemVsYnVpbGQvcnVsZXNfbm9kZWpzL2lzc3Vlcy85MjdcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBjb25zdCBtZXRhZGF0YUV4dCA9IC9cXC5tZXRhZGF0YVxcLmpzb24kLztcbiAgcmV0dXJuIHBrZy5fZmlsZXMuc29tZSgoZmlsZSkgPT4ge1xuICAgIGlmIChtZXRhZGF0YUV4dC50ZXN0KGZpbGUpKSB7XG4gICAgICBjb25zdCBzaWJsaW5nID0gZmlsZS5yZXBsYWNlKG1ldGFkYXRhRXh0LCAnLmQudHMnKTtcbiAgICAgIGlmIChzZXQuaGFzKHNpYmxpbmcpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0pO1xufVxuXG4vKipcbiAqIElmIHRoZSBwYWNrYWdlIGlzIGluIHRoZSBBbmd1bGFyIHBhY2thZ2UgZm9ybWF0IHJldHVybnMgbGlzdFxuICogb2YgcGFja2FnZSBmaWxlcyB0aGF0IGVuZCB3aXRoIGAudW1kLmpzYCwgYC5uZ2ZhY3RvcnkuanNgIGFuZCBgLm5nc3VtbWFyeS5qc2AuXG4gKi9cbmZ1bmN0aW9uIGdldE5nQXBmU2NyaXB0cyhwa2c6IERlcCkge1xuICByZXR1cm4gaXNOZ0FwZlBhY2thZ2UocGtnKSA/XG4gICAgICBmaWx0ZXJGaWxlcyhwa2cuX2ZpbGVzLCBbJy51bWQuanMnLCAnLm5nZmFjdG9yeS5qcycsICcubmdzdW1tYXJ5LmpzJ10pIDpcbiAgICAgIFtdO1xufVxuXG4vKipcbiAqIExvb2tzIGZvciBhIGZpbGUgd2l0aGluIGEgcGFja2FnZSBhbmQgcmV0dXJucyBpdCBpZiBmb3VuZC5cbiAqL1xuZnVuY3Rpb24gZmluZEZpbGUocGtnOiBEZXAsIG06IHN0cmluZykge1xuICBjb25zdCBtbCA9IG0udG9Mb3dlckNhc2UoKTtcbiAgZm9yIChjb25zdCBmIG9mIHBrZy5fZmlsZXMpIHtcbiAgICBpZiAoZi50b0xvd2VyQ2FzZSgpID09PSBtbCkge1xuICAgICAgcmV0dXJuIGY7XG4gICAgfVxuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogR2l2ZW4gYSBwa2csIHJldHVybiB0aGUgc2t5bGFyayBgbm9kZV9tb2R1bGVfbGlicmFyeWAgdGFyZ2V0cyBmb3IgdGhlIHBhY2thZ2UuXG4gKi9cbmZ1bmN0aW9uIHByaW50UGFja2FnZShwa2c6IERlcCkge1xuICBjb25zdCBzb3VyY2VzID0gZmlsdGVyRmlsZXMocGtnLl9maWxlcywgSU5DTFVERURfRklMRVMpO1xuICBjb25zdCBkdHNTb3VyY2VzID0gZmlsdGVyRmlsZXMocGtnLl9maWxlcywgWycuZC50cyddKTtcbiAgLy8gVE9ETyhnbWFnb2xhbik6IGFkZCBVTUQgJiBBTUQgc2NyaXB0cyB0byBzY3JpcHRzIGV2ZW4gaWYgbm90IGFuIEFQRiBwYWNrYWdlIF9idXRfIG9ubHkgaWYgdGhleVxuICAvLyBhcmUgbmFtZWQ/XG4gIGNvbnN0IHNjcmlwdHMgPSBnZXROZ0FwZlNjcmlwdHMocGtnKTtcbiAgY29uc3QgZGVwcyA9IFtwa2ddLmNvbmNhdChwa2cuX2RlcGVuZGVuY2llcy5maWx0ZXIoZGVwID0+IGRlcCAhPT0gcGtnICYmICFkZXAuX2lzTmVzdGVkKSk7XG5cbiAgbGV0IHNjcmlwdFN0YXJsYXJrID0gJyc7XG4gIGlmIChzY3JpcHRzLmxlbmd0aCkge1xuICAgIHNjcmlwdFN0YXJsYXJrID0gYFxuICAgICMgc3Vic2V0IG9mIHNyY3MgdGhhdCBhcmUgamF2YXNjcmlwdCBuYW1lZC1VTUQgb3IgbmFtZWQtQU1EIHNjcmlwdHNcbiAgICBzY3JpcHRzID0gW1xuICAgICAgICAke3NjcmlwdHMubWFwKChmOiBzdHJpbmcpID0+IGBcIi8vOm5vZGVfbW9kdWxlcy8ke3BrZy5fZGlyfS8ke2Z9XCIsYCkuam9pbignXFxuICAgICAgICAnKX1cbiAgICBdLGA7XG4gIH1cblxuICBsZXQgc3Jjc1N0YXJsYXJrID0gJyc7XG4gIGlmIChzb3VyY2VzLmxlbmd0aCkge1xuICAgIHNyY3NTdGFybGFyayA9IGBcbiAgICAjICR7cGtnLl9kaXJ9IHBhY2thZ2UgZmlsZXMgKGFuZCBmaWxlcyBpbiBuZXN0ZWQgbm9kZV9tb2R1bGVzKVxuICAgIHNyY3MgPSBbXG4gICAgICAgICR7c291cmNlcy5tYXAoKGY6IHN0cmluZykgPT4gYFwiLy86bm9kZV9tb2R1bGVzLyR7cGtnLl9kaXJ9LyR7Zn1cIixgKS5qb2luKCdcXG4gICAgICAgICcpfVxuICAgIF0sYDtcbiAgfVxuXG4gIGxldCBkZXBzU3RhcmxhcmsgPSAnJztcbiAgaWYgKGRlcHMubGVuZ3RoKSB7XG4gICAgY29uc3QgbGlzdCA9IGRlcHMubWFwKGRlcCA9PiBgXCIvLyR7ZGVwLl9kaXJ9OiR7ZGVwLl9uYW1lfV9fY29udGVudHNcIixgKS5qb2luKCdcXG4gICAgICAgICcpO1xuICAgIGRlcHNTdGFybGFyayA9IGBcbiAgICAjIGZsYXR0ZW5lZCBsaXN0IG9mIGRpcmVjdCBhbmQgdHJhbnNpdGl2ZSBkZXBlbmRlbmNpZXMgaG9pc3RlZCB0byByb290IGJ5IHRoZSBwYWNrYWdlIG1hbmFnZXJcbiAgICBkZXBzID0gW1xuICAgICAgICAke2xpc3R9XG4gICAgXSxgO1xuICB9XG5cbiAgbGV0IGR0c1N0YXJsYXJrID0gJyc7XG4gIGlmIChkdHNTb3VyY2VzLmxlbmd0aCkge1xuICAgIGR0c1N0YXJsYXJrID0gYFxuICAgICMgJHtwa2cuX2Rpcn0gcGFja2FnZSBkZWNsYXJhdGlvbiBmaWxlcyAoYW5kIGRlY2xhcmF0aW9uIGZpbGVzIGluIG5lc3RlZCBub2RlX21vZHVsZXMpXG4gICAgc3JjcyA9IFtcbiAgICAgICAgJHtkdHNTb3VyY2VzLm1hcChmID0+IGBcIi8vOm5vZGVfbW9kdWxlcy8ke3BrZy5fZGlyfS8ke2Z9XCIsYCkuam9pbignXFxuICAgICAgICAnKX1cbiAgICBdLGA7XG4gIH1cblxuICBsZXQgcmVzdWx0ID1cbiAgICAgIGBsb2FkKFwiQGJ1aWxkX2JhemVsX3J1bGVzX25vZGVqcy8vaW50ZXJuYWwvbnBtX2luc3RhbGw6bm9kZV9tb2R1bGVfbGlicmFyeS5iemxcIiwgXCJub2RlX21vZHVsZV9saWJyYXJ5XCIpXG5cbiMgR2VuZXJhdGVkIHRhcmdldHMgZm9yIG5wbSBwYWNrYWdlIFwiJHtwa2cuX2Rpcn1cIlxuJHtwcmludEpzb24ocGtnKX1cblxuZmlsZWdyb3VwKFxuICAgIG5hbWUgPSBcIiR7cGtnLl9uYW1lfV9fZmlsZXNcIiwke3NyY3NTdGFybGFya31cbilcblxubm9kZV9tb2R1bGVfbGlicmFyeShcbiAgICBuYW1lID0gXCIke3BrZy5fbmFtZX1cIixcbiAgICAjIGRpcmVjdCBzb3VyY2VzIGxpc3RlZCBmb3Igc3RyaWN0IGRlcHMgc3VwcG9ydFxuICAgIHNyY3MgPSBbXCI6JHtwa2cuX25hbWV9X19maWxlc1wiXSwke2RlcHNTdGFybGFya31cbilcblxuIyAke3BrZy5fbmFtZX1fX2NvbnRlbnRzIHRhcmdldCBpcyB1c2VkIGFzIGRlcCBmb3IgbWFpbiB0YXJnZXRzIHRvIHByZXZlbnRcbiMgY2lyY3VsYXIgZGVwZW5kZW5jaWVzIGVycm9yc1xubm9kZV9tb2R1bGVfbGlicmFyeShcbiAgICBuYW1lID0gXCIke3BrZy5fbmFtZX1fX2NvbnRlbnRzXCIsXG4gICAgc3JjcyA9IFtcIjoke3BrZy5fbmFtZX1fX2ZpbGVzXCJdLCR7c2NyaXB0U3Rhcmxhcmt9XG4pXG5cbiMgJHtwa2cuX25hbWV9X190eXBpbmdzIGlzIHRoZSBzdWJzZXQgb2YgJHtwa2cuX25hbWV9X19jb250ZW50cyB0aGF0IGFyZSBkZWNsYXJhdGlvbnNcbm5vZGVfbW9kdWxlX2xpYnJhcnkoXG4gICAgbmFtZSA9IFwiJHtwa2cuX25hbWV9X190eXBpbmdzXCIsJHtkdHNTdGFybGFya31cbilcblxuYDtcblxuICBsZXQgbWFpbkVudHJ5UG9pbnQgPSByZXNvbHZlUGtnTWFpbkZpbGUocGtnKVxuXG4gIC8vIGFkZCBhbiBgbnBtX3VtZF9idW5kbGVgIHRhcmdldCB0byBnZW5lcmF0ZSBhbiBVTUQgYnVuZGxlIGlmIG9uZSBkb2VzXG4gIC8vIG5vdCBleGlzdHNcbiAgaWYgKG1haW5FbnRyeVBvaW50ICYmICFmaW5kRmlsZShwa2csIGAke3BrZy5fbmFtZX0udW1kLmpzYCkpIHtcbiAgICByZXN1bHQgKz1cbiAgICAgICAgYGxvYWQoXCJAYnVpbGRfYmF6ZWxfcnVsZXNfbm9kZWpzLy9pbnRlcm5hbC9ucG1faW5zdGFsbDpucG1fdW1kX2J1bmRsZS5iemxcIiwgXCJucG1fdW1kX2J1bmRsZVwiKVxuXG5ucG1fdW1kX2J1bmRsZShcbiAgICBuYW1lID0gXCIke3BrZy5fbmFtZX1fX3VtZFwiLFxuICAgIHBhY2thZ2VfbmFtZSA9IFwiJHtwa2cuX25hbWV9XCIsXG4gICAgZW50cnlfcG9pbnQgPSBcIi8vOm5vZGVfbW9kdWxlcy8ke3BrZy5fZGlyfS8ke21haW5FbnRyeVBvaW50fVwiLFxuICAgIHBhY2thZ2UgPSBcIjoke3BrZy5fbmFtZX1cIixcbilcblxuYDtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIF9maW5kRXhlY3V0YWJsZXMocGtnOiBEZXApIHtcbiAgY29uc3QgZXhlY3V0YWJsZXMgPSBuZXcgTWFwKCk7XG5cbiAgLy8gRm9yIHJvb3QgcGFja2FnZXMsIHRyYW5zZm9ybSB0aGUgcGtnLmJpbiBlbnRyaWVzXG4gIC8vIGludG8gYSBuZXcgTWFwIGNhbGxlZCBfZXhlY3V0YWJsZXNcbiAgLy8gTk9URTogd2UgZG8gdGhpcyBvbmx5IGZvciBub24tZW1wdHkgYmluIHBhdGhzXG4gIGlmIChpc1ZhbGlkQmluUGF0aChwa2cuYmluKSkge1xuICAgIGlmICghcGtnLl9pc05lc3RlZCkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkocGtnLmJpbikpIHtcbiAgICAgICAgaWYgKHBrZy5iaW4ubGVuZ3RoID09IDEpIHtcbiAgICAgICAgICBleGVjdXRhYmxlcy5zZXQocGtnLl9kaXIsIGNsZWFudXBCaW5QYXRoKHBrZy5iaW5bMF0pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBzaG91bGQgbm90IGhhcHBlbiwgYnV0IGlnbm9yZSBpdCBpZiBwcmVzZW50XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHBrZy5iaW4gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGV4ZWN1dGFibGVzLnNldChwa2cuX2RpciwgY2xlYW51cEJpblBhdGgocGtnLmJpbikpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcGtnLmJpbiA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgZm9yIChsZXQga2V5IGluIHBrZy5iaW4pIHtcbiAgICAgICAgICBpZiAoaXNWYWxpZEJpblBhdGhTdHJpbmdWYWx1ZShwa2cuYmluW2tleV0pKSB7XG4gICAgICAgICAgICBleGVjdXRhYmxlcy5zZXQoa2V5LCBjbGVhbnVwQmluUGF0aChwa2cuYmluW2tleV0pKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gZXhlY3V0YWJsZXM7XG59XG5cbi8vIEhhbmRsZSBhZGRpdGlvbmFsQXR0cmlidXRlcyBvZiBmb3JtYXQ6XG4vLyBgYGBcbi8vIFwiYmF6ZWxCaW5cIjoge1xuLy8gICBcIm5nYy13cmFwcGVkXCI6IHtcbi8vICAgICBcImFkZGl0aW9uYWxBdHRyaWJ1dGVzXCI6IHtcbi8vICAgICAgIFwiY29uZmlndXJhdGlvbl9lbnZfdmFyc1wiOiBcIltcXFwiY29tcGlsZVxcXCJdXCJcbi8vICAgfVxuLy8gfSxcbi8vIGBgYFxuZnVuY3Rpb24gYWRkaXRpb25hbEF0dHJpYnV0ZXMocGtnOiBEZXAsIG5hbWU6IHN0cmluZykge1xuICBsZXQgYWRkaXRpb25hbEF0dHJpYnV0ZXMgPSAnJztcbiAgaWYgKHBrZy5iYXplbEJpbiAmJiBwa2cuYmF6ZWxCaW5bbmFtZV0gJiYgcGtnLmJhemVsQmluW25hbWVdLmFkZGl0aW9uYWxBdHRyaWJ1dGVzKSB7XG4gICAgY29uc3QgYXR0cnMgPSBwa2cuYmF6ZWxCaW5bbmFtZV0uYWRkaXRpb25hbEF0dHJpYnV0ZXM7XG4gICAgZm9yIChjb25zdCBhdHRyTmFtZSBvZiBPYmplY3Qua2V5cyhhdHRycykpIHtcbiAgICAgIGNvbnN0IGF0dHJWYWx1ZSA9IGF0dHJzW2F0dHJOYW1lXTtcbiAgICAgIGFkZGl0aW9uYWxBdHRyaWJ1dGVzICs9IGBcXG4gICAgJHthdHRyTmFtZX0gPSAke2F0dHJWYWx1ZX0sYDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGFkZGl0aW9uYWxBdHRyaWJ1dGVzO1xufVxuXG4vKipcbiAqIEdpdmVuIGEgcGtnLCByZXR1cm4gdGhlIHNreWxhcmsgbm9kZWpzX2JpbmFyeSB0YXJnZXRzIGZvciB0aGUgcGFja2FnZS5cbiAqL1xuZnVuY3Rpb24gcHJpbnRQYWNrYWdlQmluKHBrZzogRGVwKSB7XG4gIGxldCByZXN1bHQgPSAnJztcbiAgY29uc3QgZXhlY3V0YWJsZXMgPSBfZmluZEV4ZWN1dGFibGVzKHBrZyk7XG4gIGlmIChleGVjdXRhYmxlcy5zaXplKSB7XG4gICAgcmVzdWx0ID0gYGxvYWQoXCJAYnVpbGRfYmF6ZWxfcnVsZXNfbm9kZWpzLy86aW5kZXguYnpsXCIsIFwibm9kZWpzX2JpbmFyeVwiKVxuXG5gO1xuICAgIGNvbnN0IGRhdGEgPSBbYC8vJHtwa2cuX2Rpcn06JHtwa2cuX25hbWV9YF07XG4gICAgaWYgKHBrZy5fZHluYW1pY0RlcGVuZGVuY2llcykge1xuICAgICAgZGF0YS5wdXNoKC4uLnBrZy5fZHluYW1pY0RlcGVuZGVuY2llcyk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBbbmFtZSwgcGF0aF0gb2YgZXhlY3V0YWJsZXMuZW50cmllcygpKSB7XG4gICAgICByZXN1bHQgKz0gYCMgV2lyZSB1cCB0aGUgXFxgYmluXFxgIGVudHJ5IFxcYCR7bmFtZX1cXGBcbm5vZGVqc19iaW5hcnkoXG4gICAgbmFtZSA9IFwiJHtuYW1lfVwiLFxuICAgIGVudHJ5X3BvaW50ID0gXCIvLzpub2RlX21vZHVsZXMvJHtwa2cuX2Rpcn0vJHtwYXRofVwiLFxuICAgIGluc3RhbGxfc291cmNlX21hcF9zdXBwb3J0ID0gRmFsc2UsXG4gICAgZGF0YSA9IFske2RhdGEubWFwKHAgPT4gYFwiJHtwfVwiYCkuam9pbignLCAnKX1dLCR7YWRkaXRpb25hbEF0dHJpYnV0ZXMocGtnLCBuYW1lKX1cbilcblxuYDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBwcmludEluZGV4QnpsKHBrZzogRGVwKSB7XG4gIGxldCByZXN1bHQgPSAnJztcbiAgY29uc3QgZXhlY3V0YWJsZXMgPSBfZmluZEV4ZWN1dGFibGVzKHBrZyk7XG4gIGlmIChleGVjdXRhYmxlcy5zaXplKSB7XG4gICAgcmVzdWx0ID0gYGxvYWQoXCJAYnVpbGRfYmF6ZWxfcnVsZXNfbm9kZWpzLy86aW5kZXguYnpsXCIsIFwibm9kZWpzX2JpbmFyeVwiLCBcIm5wbV9wYWNrYWdlX2JpblwiKVxuXG5gO1xuICAgIGNvbnN0IGRhdGEgPSBbYEAke1dPUktTUEFDRX0vLyR7cGtnLl9kaXJ9OiR7cGtnLl9uYW1lfWBdO1xuICAgIGlmIChwa2cuX2R5bmFtaWNEZXBlbmRlbmNpZXMpIHtcbiAgICAgIGRhdGEucHVzaCguLi5wa2cuX2R5bmFtaWNEZXBlbmRlbmNpZXMpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgW25hbWUsIHBhdGhdIG9mIGV4ZWN1dGFibGVzLmVudHJpZXMoKSkge1xuICAgICAgcmVzdWx0ID0gYCR7cmVzdWx0fVxuXG4jIEdlbmVyYXRlZCBoZWxwZXIgbWFjcm8gdG8gY2FsbCAke25hbWV9XG5kZWYgJHtuYW1lLnJlcGxhY2UoLy0vZywgJ18nKX0oKiprd2FyZ3MpOlxuICAgIG91dHB1dF9kaXIgPSBrd2FyZ3MucG9wKFwib3V0cHV0X2RpclwiLCBGYWxzZSlcbiAgICBpZiBcIm91dHNcIiBpbiBrd2FyZ3Mgb3Igb3V0cHV0X2RpcjpcbiAgICAgICAgbnBtX3BhY2thZ2VfYmluKHRvb2wgPSBcIkAke1dPUktTUEFDRX0vLyR7cGtnLl9kaXJ9L2Jpbjoke1xuICAgICAgICAgIG5hbWV9XCIsIG91dHB1dF9kaXIgPSBvdXRwdXRfZGlyLCAqKmt3YXJncylcbiAgICBlbHNlOlxuICAgICAgICBub2RlanNfYmluYXJ5KFxuICAgICAgICAgICAgZW50cnlfcG9pbnQgPSBcIkAke1dPUktTUEFDRX0vLzpub2RlX21vZHVsZXMvJHtwa2cuX2Rpcn0vJHtwYXRofVwiLFxuICAgICAgICAgICAgaW5zdGFsbF9zb3VyY2VfbWFwX3N1cHBvcnQgPSBGYWxzZSxcbiAgICAgICAgICAgIGRhdGEgPSBbJHtkYXRhLm1hcChwID0+IGBcIiR7cH1cImApLmpvaW4oJywgJyl9XSArIGt3YXJncy5wb3AoXCJkYXRhXCIsIFtdKSwke1xuICAgICAgICAgIGFkZGl0aW9uYWxBdHRyaWJ1dGVzKHBrZywgbmFtZSl9XG4gICAgICAgICAgICAqKmt3YXJnc1xuICAgICAgICApXG4gIGA7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbnR5cGUgRGVwID0ge1xuICBfZGlyOiBzdHJpbmcsXG4gIF9pc05lc3RlZDogYm9vbGVhbixcbiAgX2RlcGVuZGVuY2llczogRGVwW10sXG4gIF9maWxlczogc3RyaW5nW10sXG4gIFtrOiBzdHJpbmddOiBhbnlcbn1cblxuLyoqXG4gKiBHaXZlbiBhIHNjb3BlLCByZXR1cm4gdGhlIHNreWxhcmsgYG5vZGVfbW9kdWxlX2xpYnJhcnlgIHRhcmdldCBmb3IgdGhlIHNjb3BlLlxuICovXG5mdW5jdGlvbiBwcmludFNjb3BlKHNjb3BlOiBzdHJpbmcsIHBrZ3M6IERlcFtdKSB7XG4gIHBrZ3MgPSBwa2dzLmZpbHRlcihwa2cgPT4gIXBrZy5faXNOZXN0ZWQgJiYgcGtnLl9kaXIuc3RhcnRzV2l0aChgJHtzY29wZX0vYCkpO1xuICBsZXQgZGVwczogRGVwW10gPSBbXTtcbiAgcGtncy5mb3JFYWNoKHBrZyA9PiB7XG4gICAgZGVwcyA9IGRlcHMuY29uY2F0KHBrZy5fZGVwZW5kZW5jaWVzLmZpbHRlcihkZXAgPT4gIWRlcC5faXNOZXN0ZWQgJiYgIXBrZ3MuaW5jbHVkZXMocGtnKSkpO1xuICB9KTtcbiAgLy8gZmlsdGVyIG91dCBkdXBsaWNhdGUgZGVwc1xuICBkZXBzID0gWy4uLnBrZ3MsIC4uLm5ldyBTZXQoZGVwcyldO1xuXG4gIGxldCBzcmNzU3RhcmxhcmsgPSAnJztcbiAgaWYgKGRlcHMubGVuZ3RoKSB7XG4gICAgY29uc3QgbGlzdCA9IGRlcHMubWFwKGRlcCA9PiBgXCIvLyR7ZGVwLl9kaXJ9OiR7ZGVwLl9uYW1lfV9fZmlsZXNcIixgKS5qb2luKCdcXG4gICAgICAgICcpO1xuICAgIHNyY3NTdGFybGFyayA9IGBcbiAgICAjIGRpcmVjdCBzb3VyY2VzIGxpc3RlZCBmb3Igc3RyaWN0IGRlcHMgc3VwcG9ydFxuICAgIHNyY3MgPSBbXG4gICAgICAgICR7bGlzdH1cbiAgICBdLGA7XG4gIH1cblxuICBsZXQgZGVwc1N0YXJsYXJrID0gJyc7XG4gIGlmIChkZXBzLmxlbmd0aCkge1xuICAgIGNvbnN0IGxpc3QgPSBkZXBzLm1hcChkZXAgPT4gYFwiLy8ke2RlcC5fZGlyfToke2RlcC5fbmFtZX1fX2NvbnRlbnRzXCIsYCkuam9pbignXFxuICAgICAgICAnKTtcbiAgICBkZXBzU3RhcmxhcmsgPSBgXG4gICAgIyBmbGF0dGVuZWQgbGlzdCBvZiBkaXJlY3QgYW5kIHRyYW5zaXRpdmUgZGVwZW5kZW5jaWVzIGhvaXN0ZWQgdG8gcm9vdCBieSB0aGUgcGFja2FnZSBtYW5hZ2VyXG4gICAgZGVwcyA9IFtcbiAgICAgICAgJHtsaXN0fVxuICAgIF0sYDtcbiAgfVxuXG4gIHJldHVybiBgbG9hZChcIkBidWlsZF9iYXplbF9ydWxlc19ub2RlanMvL2ludGVybmFsL25wbV9pbnN0YWxsOm5vZGVfbW9kdWxlX2xpYnJhcnkuYnpsXCIsIFwibm9kZV9tb2R1bGVfbGlicmFyeVwiKVxuXG4jIEdlbmVyYXRlZCB0YXJnZXQgZm9yIG5wbSBzY29wZSAke3Njb3BlfVxubm9kZV9tb2R1bGVfbGlicmFyeShcbiAgICBuYW1lID0gXCIke3Njb3BlfVwiLCR7c3Jjc1N0YXJsYXJrfSR7ZGVwc1N0YXJsYXJrfVxuKVxuXG5gO1xufVxuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVfYnVpbGRfZmlsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2ludGVybmFsL25wbV9pbnN0YWxsL2dlbmVyYXRlX2J1aWxkX2ZpbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0lBQUE7Ozs7Ozs7Ozs7Ozs7OztPQWVHO0lBQ0g7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FzQkc7SUFDSCxZQUFZLENBQUM7O0lBR2IseUJBQXlCO0lBQ3pCLDZCQUE2QjtJQUM3QixpQ0FBaUM7SUFFakMsU0FBUyxXQUFXLENBQUMsR0FBRyxDQUFRO1FBQzlCLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1lBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQywwQkFBMEIsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JGLENBQUM7SUFFRCxNQUFNLGlCQUFpQixHQUFHOzs7Ozs7Q0FNekIsQ0FBQTtJQUVELE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25DLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxQixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUIsTUFBTSxvQkFBb0IsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0MsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9CLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ3pELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFB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XG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgVGhlIEJhemVsIEF1dGhvcnMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgVGhpcyBzY3JpcHQgZ2VuZXJhdGVzIEJVSUxELmJhemVsIGZpbGVzIGJ5IGFuYWx5emluZ1xuICogdGhlIG5vZGVfbW9kdWxlcyBmb2xkZXIgbGF5ZWQgb3V0IGJ5IHlhcm4gb3IgbnBtLiBJdCBnZW5lcmF0ZXNcbiAqIGZpbmUgZ3JhaW5lZCBCYXplbCBgbm9kZV9tb2R1bGVfbGlicmFyeWAgdGFyZ2V0cyBmb3IgZWFjaCByb290IG5wbSBwYWNrYWdlXG4gKiBhbmQgYWxsIGZpbGVzIGZvciB0aGF0IHBhY2thZ2UgYW5kIGl0cyB0cmFuc2l0aXZlIGRlcHMgYXJlIGluY2x1ZGVkXG4gKiBpbiB0aGUgdGFyZ2V0LiBGb3IgZXhhbXBsZSwgYEA8d29ya3NwYWNlPi8vamFzbWluZWAgd291bGRcbiAqIGluY2x1ZGUgYWxsIGZpbGVzIGluIHRoZSBqYXNtaW5lIG5wbSBwYWNrYWdlIGFuZCBhbGwgb2YgaXRzXG4gKiB0cmFuc2l0aXZlIGRlcGVuZGVuY2llcy5cbiAqXG4gKiBub2RlanNfYmluYXJ5IHRhcmdldHMgYXJlIGFsc28gZ2VuZXJhdGVkIGZvciBhbGwgYGJpbmAgc2NyaXB0c1xuICogaW4gZWFjaCBwYWNrYWdlLiBGb3IgZXhhbXBsZSwgdGhlIGBAPHdvcmtzcGFjZT4vL2phc21pbmUvYmluOmphc21pbmVgXG4gKiB0YXJnZXQgd2lsbCBiZSBnZW5lcmF0ZWQgZm9yIHRoZSBgamFzbWluZWAgYmluYXJ5IGluIHRoZSBgamFzbWluZWBcbiAqIG5wbSBwYWNrYWdlLlxuICpcbiAqIEFkZGl0aW9uYWxseSwgYSBgQDx3b3Jrc3BhY2U+Ly86bm9kZV9tb2R1bGVzYCBgbm9kZV9tb2R1bGVfbGlicmFyeWBcbiAqIGlzIGdlbmVyYXRlZCB0aGF0IGluY2x1ZGVzIGFsbCBwYWNrYWdlcyB1bmRlciBub2RlX21vZHVsZXNcbiAqIGFzIHdlbGwgYXMgdGhlIC5iaW4gZm9sZGVyLlxuICpcbiAqIFRoaXMgd29yayBpcyBiYXNlZCBvZmYgdGhlIGZpbmUgZ3JhaW5lZCBkZXBzIGNvbmNlcHRzIGluXG4gKiBodHRwczovL2dpdGh1Yi5jb20vcHVicmVmL3J1bGVzX25vZGUgZGV2ZWxvcGVkIGJ5IEBwY2ouXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9kb2N1bWVudC9kLzFBZmpITUxWeUVfdll3bEhTSzdrN3lXX0lJR3BwU3hzUXRQbTlQVHIxeEVvXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuXG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gJ2NyeXB0byc7XG5cbmZ1bmN0aW9uIGxvZ192ZXJib3NlKC4uLm06IGFueVtdKSB7XG4gIGlmICghIXByb2Nlc3MuZW52WydWRVJCT1NFX0xPR1MnXSkgY29uc29sZS5lcnJvcignW2dlbmVyYXRlX2J1aWxkX2ZpbGUuanNdJywgLi4ubSk7XG59XG5cbmNvbnN0IEJVSUxEX0ZJTEVfSEVBREVSID0gYCMgR2VuZXJhdGVkIGZpbGUgZnJvbSB5YXJuX2luc3RhbGwvbnBtX2luc3RhbGwgcnVsZS5cbiMgU2VlICQoYmF6ZWwgaW5mbyBvdXRwdXRfYmFzZSkvZXh0ZXJuYWwvYnVpbGRfYmF6ZWxfcnVsZXNfbm9kZWpzL2ludGVybmFsL25wbV9pbnN0YWxsL2dlbmVyYXRlX2J1aWxkX2ZpbGUuanNcblxuIyBBbGwgcnVsZXMgaW4gb3RoZXIgcmVwb3NpdG9yaWVzIGNhbiB1c2UgdGhlc2UgdGFyZ2V0c1xucGFja2FnZShkZWZhdWx0X3Zpc2liaWxpdHkgPSBbXCIvL3Zpc2liaWxpdHk6cHVibGljXCJdKVxuXG5gXG5cbmNvbnN0IGFyZ3MgPSBwcm9jZXNzLmFyZ3Yuc2xpY2UoMik7XG5jb25zdCBXT1JLU1BBQ0UgPSBhcmdzWzBdO1xuY29uc3QgUlVMRV9UWVBFID0gYXJnc1sxXTtcbmNvbnN0IEVSUk9SX09OX0JBWkVMX0ZJTEVTID0gcGFyc2VJbnQoYXJnc1syXSk7XG5jb25zdCBMT0NLX0ZJTEVfUEFUSCA9IGFyZ3NbM107XG5jb25zdCBJTkNMVURFRF9GSUxFUyA9IGFyZ3NbNF0gPyBhcmdzWzRdLnNwbGl0KCcsJykgOiBbXTtcbmNvbnN0IERZTkFNSUNfREVQUyA9IEpTT04ucGFyc2UoYXJnc1s1XSB8fCAne30nKTtcblxuaWYgKHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlKSB7XG4gIG1haW4oKTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBuZXcgZGlyZWN0b3J5IGFuZCBhbnkgbmVjZXNzYXJ5IHN1YmRpcmVjdG9yaWVzXG4gKiBpZiB0aGV5IGRvIG5vdCBleGlzdC5cbiAqL1xuZnVuY3Rpb24gbWtkaXJwKHA6IHN0cmluZykge1xuICBpZiAoIWZzLmV4aXN0c1N5bmMocCkpIHtcbiAgICBta2RpcnAocGF0aC5kaXJuYW1lKHApKTtcbiAgICBmcy5ta2RpclN5bmMocCk7XG4gIH1cbn1cblxuLyoqXG4gKiBXcml0ZXMgYSBmaWxlLCBmaXJzdCBlbnN1cmluZyB0aGF0IHRoZSBkaXJlY3RvcnkgdG9cbiAqIHdyaXRlIHRvIGV4aXN0cy5cbiAqL1xuZnVuY3Rpb24gd3JpdGVGaWxlU3luYyhwOiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZykge1xuICBta2RpcnAocGF0aC5kaXJuYW1lKHApKTtcbiAgZnMud3JpdGVGaWxlU3luYyhwLCBjb250ZW50KTtcbn1cblxuLyoqXG4gKiBNYWluIGVudHJ5cG9pbnQuXG4gKi9cbmZ1bmN0aW9uIG1haW4oKSB7XG4gIC8vIGZpbmQgYWxsIHBhY2thZ2VzIChpbmNsdWRpbmcgcGFja2FnZXMgaW4gbmVzdGVkIG5vZGVfbW9kdWxlcylcbiAgY29uc3QgcGtncyA9IGZpbmRQYWNrYWdlcygpO1xuXG4gIC8vIGZsYXR0ZW4gZGVwZW5kZW5jaWVzXG4gIGZsYXR0ZW5EZXBlbmRlbmNpZXMocGtncyk7XG5cbiAgLy8gZ2VuZXJhdGUgQmF6ZWwgd29ya3NwYWNlc1xuICBnZW5lcmF0ZUJhemVsV29ya3NwYWNlcyhwa2dzKVxuXG4gIC8vIGdlbmVyYXRlIGFsbCBCVUlMRCBmaWxlc1xuICBnZW5lcmF0ZUJ1aWxkRmlsZXMocGtncylcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIG1haW4sXG4gIHByaW50UGFja2FnZUJpbixcbiAgYWRkRHluYW1pY0RlcGVuZGVuY2llcyxcbiAgcHJpbnRJbmRleEJ6bCxcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIGFsbCBidWlsZCBmaWxlc1xuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUJ1aWxkRmlsZXMocGtnczogRGVwW10pIHtcbiAgZ2VuZXJhdGVSb290QnVpbGRGaWxlKHBrZ3MuZmlsdGVyKHBrZyA9PiAhcGtnLl9pc05lc3RlZCkpXG4gIHBrZ3MuZmlsdGVyKHBrZyA9PiAhcGtnLl9pc05lc3RlZCkuZm9yRWFjaChwa2cgPT4gZ2VuZXJhdGVQYWNrYWdlQnVpbGRGaWxlcyhwa2cpKTtcbiAgZmluZFNjb3BlcygpLmZvckVhY2goc2NvcGUgPT4gZ2VuZXJhdGVTY29wZUJ1aWxkRmlsZXMoc2NvcGUsIHBrZ3MpKTtcbn1cblxuLyoqXG4gKiBGbGF0dGVucyBkZXBlbmRlbmNpZXMgb24gYWxsIHBhY2thZ2VzXG4gKi9cbmZ1bmN0aW9uIGZsYXR0ZW5EZXBlbmRlbmNpZXMocGtnczogRGVwW10pIHtcbiAgY29uc3QgcGtnc01hcCA9IG5ldyBNYXAoKTtcbiAgcGtncy5mb3JFYWNoKHBrZyA9PiBwa2dzTWFwLnNldChwa2cuX2RpciwgcGtnKSk7XG4gIHBrZ3MuZm9yRWFjaChwa2cgPT4gZmxhdHRlblBrZ0RlcGVuZGVuY2llcyhwa2csIHBrZywgcGtnc01hcCkpO1xufVxuXG4vKipcbiAqIEhhbmRsZXMgQmF6ZWwgZmlsZXMgaW4gbnBtIGRpc3RyaWJ1dGlvbnMuXG4gKi9cbmZ1bmN0aW9uIGhpZGVCYXplbEZpbGVzKHBrZzogRGVwKSB7XG4gIGNvbnN0IGhhc0hpZGVCYXplbEZpbGVzID0gaXNEaXJlY3RvcnkoJ25vZGVfbW9kdWxlcy9AYmF6ZWwvaGlkZS1iYXplbC1maWxlcycpO1xuICBwa2cuX2ZpbGVzID0gcGtnLl9maWxlcy5tYXAoZmlsZSA9PiB7XG4gICAgY29uc3QgYmFzZW5hbWUgPSBwYXRoLmJhc2VuYW1lKGZpbGUpO1xuICAgIGNvbnN0IGJhc2VuYW1lVWMgPSBiYXNlbmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgIGlmIChiYXNlbmFtZVVjID09PSAnQlVJTEQnIHx8IGJhc2VuYW1lVWMgPT09ICdCVUlMRC5CQVpFTCcpIHtcbiAgICAgIC8vIElmIGJhemVsIGZpbGVzIGFyZSBkZXRlY3RlZCBhbmQgdGhlcmUgaXMgbm8gQGJhemVsL2hpZGUtYmF6ZWwtZmlsZXMgbnBtXG4gICAgICAvLyBwYWNrYWdlIHRoZW4gZXJyb3Igb3V0IGFuZCBzdWdnZXN0IGFkZGluZyB0aGUgcGFja2FnZS4gSXQgaXMgcG9zc2libGUgdG9cbiAgICAgIC8vIGhhdmUgYmF6ZWwgQlVJTEQgZmlsZXMgd2l0aCB0aGUgcGFja2FnZSBpbnN0YWxsZWQgYXMgaXQncyBwb3N0aW5zdGFsbFxuICAgICAgLy8gc3RlcCwgd2hpY2ggaGlkZXMgYmF6ZWwgQlVJTEQgZmlsZXMsIG9ubHkgcnVucyB3aGVuIHRoZSBAYmF6ZWwvaGlkZS1iYXplbC1maWxlc1xuICAgICAgLy8gaXMgaW5zdGFsbGVkIGFuZCBub3Qgd2hlbiBuZXcgcGFja2FnZXMgYXJlIGFkZGVkICh2aWEgYHlhcm4gYWRkYFxuICAgICAgLy8gZm9yIGV4YW1wbGUpIGFmdGVyIHRoZSBpbml0aWFsIGluc3RhbGwuIEluIHRoaXMgY2FzZSwgaG93ZXZlciwgdGhlIHJlcG8gcnVsZVxuICAgICAgLy8gd2lsbCByZS1ydW4gYXMgdGhlIHBhY2thZ2UuanNvbiAmJiBsb2NrIGZpbGUgaGFzIGNoYW5nZWQgc28gd2UganVzdFxuICAgICAgLy8gaGlkZSB0aGUgYWRkZWQgQlVJTEQgZmlsZXMgZHVyaW5nIHRoZSByZXBvIHJ1bGUgcnVuIGhlcmUgc2luY2UgQGJhemVsL2hpZGUtYmF6ZWwtZmlsZXNcbiAgICAgIC8vIHdhcyBub3QgcnVuLlxuICAgICAgaWYgKCFoYXNIaWRlQmF6ZWxGaWxlcyAmJiBFUlJPUl9PTl9CQVpFTF9GSUxFUykge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBucG0gcGFja2FnZSAnJHtwa2cuX2Rpcn0nIGZyb20gQCR7V09SS1NQQUNFfSAke1JVTEVfVFlQRX0gcnVsZVxuaGFzIGEgQmF6ZWwgQlVJTEQgZmlsZSAnJHtmaWxlfScuIFVzZSB0aGUgQGJhemVsL2hpZGUtYmF6ZWwtZmlsZXMgdXRpbGl0eSB0byBoaWRlIHRoZXNlIGZpbGVzLlxuU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9iYXplbGJ1aWxkL3J1bGVzX25vZGVqcy9ibG9iL21hc3Rlci9wYWNrYWdlcy9oaWRlLWJhemVsLWZpbGVzL1JFQURNRS5tZFxuZm9yIGluc3RhbGxhdGlvbiBpbnN0cnVjdGlvbnMuYCk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEFsbCBCYXplbCBmaWxlcyBpbiB0aGUgbnBtIGRpc3RyaWJ1dGlvbiBzaG91bGQgYmUgcmVuYW1lZCBieVxuICAgICAgICAvLyBhZGRpbmcgYSBgX2AgcHJlZml4IHNvIHRoYXQgZmlsZSB0YXJnZXRzIGRvbid0IGNyb3NzIHBhY2thZ2UgYm91bmRhcmllcy5cbiAgICAgICAgY29uc3QgbmV3RmlsZSA9IHBhdGgucG9zaXguam9pbihwYXRoLmRpcm5hbWUoZmlsZSksIGBfJHtiYXNlbmFtZX1gKTtcbiAgICAgICAgY29uc3Qgc3JjUGF0aCA9IHBhdGgucG9zaXguam9pbignbm9kZV9tb2R1bGVzJywgcGtnLl9kaXIsIGZpbGUpO1xuICAgICAgICBjb25zdCBkc3RQYXRoID0gcGF0aC5wb3NpeC5qb2luKCdub2RlX21vZHVsZXMnLCBwa2cuX2RpciwgbmV3RmlsZSk7XG4gICAgICAgIGZzLnJlbmFtZVN5bmMoc3JjUGF0aCwgZHN0UGF0aCk7XG4gICAgICAgIHJldHVybiBuZXdGaWxlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmlsZTtcbiAgfSk7XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIHRoZSByb290IEJVSUxEIGZpbGUuXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlUm9vdEJ1aWxkRmlsZShwa2dzOiBEZXBbXSkge1xuICBsZXQgZXhwb3J0c1N0YXJsYXJrID0gJyc7XG4gIHBrZ3MuZm9yRWFjaChwa2cgPT4ge3BrZy5fZmlsZXMuZm9yRWFjaChmID0+IHtcbiAgICAgICAgICAgICAgICAgZXhwb3J0c1N0YXJsYXJrICs9IGAgICAgXCJub2RlX21vZHVsZXMvJHtwa2cuX2Rpcn0vJHtmfVwiLFxuYDtcbiAgICAgICAgICAgICAgIH0pfSk7XG5cbiAgbGV0IHNyY3NTdGFybGFyayA9ICcnO1xuICBpZiAocGtncy5sZW5ndGgpIHtcbiAgICBjb25zdCBsaXN0ID0gcGtncy5tYXAocGtnID0+IGBcIi8vJHtwa2cuX2Rpcn06JHtwa2cuX25hbWV9X19maWxlc1wiLGApLmpvaW4oJ1xcbiAgICAgICAgJyk7XG4gICAgc3Jjc1N0YXJsYXJrID0gYFxuICAgICMgZGlyZWN0IHNvdXJjZXMgbGlzdGVkIGZvciBzdHJpY3QgZGVwcyBzdXBwb3J0XG4gICAgc3JjcyA9IFtcbiAgICAgICAgJHtsaXN0fVxuICAgIF0sYDtcbiAgfVxuXG4gIGxldCBkZXBzU3RhcmxhcmsgPSAnJztcbiAgaWYgKHBrZ3MubGVuZ3RoKSB7XG4gICAgY29uc3QgbGlzdCA9IHBrZ3MubWFwKHBrZyA9PiBgXCIvLyR7cGtnLl9kaXJ9OiR7cGtnLl9uYW1lfV9fY29udGVudHNcIixgKS5qb2luKCdcXG4gICAgICAgICcpO1xuICAgIGRlcHNTdGFybGFyayA9IGBcbiAgICAjIGZsYXR0ZW5lZCBsaXN0IG9mIGRpcmVjdCBhbmQgdHJhbnNpdGl2ZSBkZXBlbmRlbmNpZXMgaG9pc3RlZCB0byByb290IGJ5IHRoZSBwYWNrYWdlIG1hbmFnZXJcbiAgICBkZXBzID0gW1xuICAgICAgICAke2xpc3R9XG4gICAgXSxgO1xuICB9XG5cbiAgbGV0IGJ1aWxkRmlsZSA9IEJVSUxEX0ZJTEVfSEVBREVSICtcbiAgICAgIGBsb2FkKFwiQGJ1aWxkX2JhemVsX3J1bGVzX25vZGVqcy8vaW50ZXJuYWwvbnBtX2luc3RhbGw6bm9kZV9tb2R1bGVfbGlicmFyeS5iemxcIiwgXCJub2RlX21vZHVsZV9saWJyYXJ5XCIpXG5cbmV4cG9ydHNfZmlsZXMoW1xuJHtleHBvcnRzU3Rhcmxhcmt9XSlcblxuIyBUaGUgbm9kZV9tb2R1bGVzIGRpcmVjdG9yeSBpbiBvbmUgY2F0Y2gtYWxsIG5vZGVfbW9kdWxlX2xpYnJhcnkuXG4jIE5COiBVc2luZyB0aGlzIHRhcmdldCBtYXkgaGF2ZSBiYWQgcGVyZm9ybWFuY2UgaW1wbGljYXRpb25zIGlmXG4jIHRoZXJlIGFyZSBtYW55IGZpbGVzIGluIHRhcmdldC5cbiMgU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9iYXplbGJ1aWxkL2JhemVsL2lzc3Vlcy81MTUzLlxubm9kZV9tb2R1bGVfbGlicmFyeShcbiAgICBuYW1lID0gXCJub2RlX21vZHVsZXNcIiwke3NyY3NTdGFybGFya30ke2RlcHNTdGFybGFya31cbilcblxuYFxuXG4gIC8vIEFkZCB0aGUgbWFudWFsIGJ1aWxkIGZpbGUgY29udGVudHMgaWYgdGhleSBleGlzdHNcbiAgdHJ5IHtcbiAgICBidWlsZEZpbGUgKz0gZnMucmVhZEZpbGVTeW5jKGBtYW51YWxfYnVpbGRfZmlsZV9jb250ZW50c2AsIHtlbmNvZGluZzogJ3V0ZjgnfSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgfVxuXG4gIHdyaXRlRmlsZVN5bmMoJ0JVSUxELmJhemVsJywgYnVpbGRGaWxlKTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgYWxsIEJVSUxEICYgYnpsIGZpbGVzIGZvciBhIHBhY2thZ2UuXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlUGFja2FnZUJ1aWxkRmlsZXMocGtnOiBEZXApIHtcbiAgbGV0IGJ1aWxkRmlsZSA9IHByaW50UGFja2FnZShwa2cpO1xuXG4gIGNvbnN0IGJpbkJ1aWxkRmlsZSA9IHByaW50UGFja2FnZUJpbihwa2cpO1xuICBpZiAoYmluQnVpbGRGaWxlLmxlbmd0aCkge1xuICAgIHdyaXRlRmlsZVN5bmMoXG4gICAgICAgIHBhdGgucG9zaXguam9pbihwa2cuX2RpciwgJ2JpbicsICdCVUlMRC5iYXplbCcpLCBCVUlMRF9GSUxFX0hFQURFUiArIGJpbkJ1aWxkRmlsZSk7XG4gIH1cblxuICBjb25zdCBpbmRleEZpbGUgPSBwcmludEluZGV4QnpsKHBrZyk7XG4gIGlmIChpbmRleEZpbGUubGVuZ3RoKSB7XG4gICAgd3JpdGVGaWxlU3luYyhwYXRoLnBvc2l4LmpvaW4ocGtnLl9kaXIsICdpbmRleC5iemwnKSwgaW5kZXhGaWxlKTtcbiAgICBidWlsZEZpbGUgPSBgJHtidWlsZEZpbGV9XG4jIEZvciBpbnRlZ3JhdGlvbiB0ZXN0aW5nXG5leHBvcnRzX2ZpbGVzKFtcImluZGV4LmJ6bFwiXSlcbmA7XG4gIH1cblxuICB3cml0ZUZpbGVTeW5jKHBhdGgucG9zaXguam9pbihwa2cuX2RpciwgJ0JVSUxELmJhemVsJyksIEJVSUxEX0ZJTEVfSEVBREVSICsgYnVpbGRGaWxlKTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZSBpbnN0YWxsXzx3b3Jrc3BhY2VfbmFtZT4uYnpsIGZpbGVzIHdpdGggZnVuY3Rpb24gdG8gaW5zdGFsbCBlYWNoIHdvcmtzcGFjZS5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVCYXplbFdvcmtzcGFjZXMocGtnczogRGVwW10pIHtcbiAgY29uc3Qgd29ya3NwYWNlczogQmFnPHN0cmluZz4gPSB7fTtcblxuICBmb3IgKGNvbnN0IHBrZyBvZiBwa2dzKSB7XG4gICAgaWYgKCFwa2cuYmF6ZWxXb3Jrc3BhY2VzKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHdvcmtzcGFjZSBvZiBPYmplY3Qua2V5cyhwa2cuYmF6ZWxXb3Jrc3BhY2VzKSkge1xuICAgICAgLy8gQSBiYXplbCB3b3Jrc3BhY2UgY2FuIG9ubHkgYmUgc2V0dXAgYnkgb25lIG5wbSBwYWNrYWdlXG4gICAgICBpZiAod29ya3NwYWNlc1t3b3Jrc3BhY2VdKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICBgQ291bGQgbm90IHNldHVwIEJhemVsIHdvcmtzcGFjZSAke3dvcmtzcGFjZX0gcmVxdWVzdGVkIGJ5IG5wbSBgICtcbiAgICAgICAgICAgIGBwYWNrYWdlICR7cGtnLl9kaXJ9QCR7cGtnLnZlcnNpb259LiBBbHJlYWR5IHNldHVwIGJ5ICR7d29ya3NwYWNlc1t3b3Jrc3BhY2VdfWApO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICB9XG5cbiAgICAgIGdlbmVyYXRlQmF6ZWxXb3Jrc3BhY2UocGtnLCB3b3Jrc3BhY2UpO1xuXG4gICAgICAvLyBLZWVwIHRyYWNrIG9mIHdoaWNoIG5wbSBwYWNrYWdlIHNldHVwIHRoaXMgYmF6ZWwgd29ya3NwYWNlIGZvciBsYXRlciB1c2VcbiAgICAgIHdvcmtzcGFjZXNbd29ya3NwYWNlXSA9IGAke3BrZy5fZGlyfUAke3BrZy52ZXJzaW9ufWA7XG4gICAgfVxuICB9XG5cbiAgLy8gRmluYWxseSBnZW5lcmF0ZSBpbnN0YWxsX2JhemVsX2RlcGVuZGVuY2llcy5iemxcbiAgZ2VuZXJhdGVJbnN0YWxsQmF6ZWxEZXBlbmRlbmNpZXMoT2JqZWN0LmtleXMod29ya3NwYWNlcykpO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIGluc3RhbGxfPHdvcmtzcGFjZT4uYnpsIGZpbGUgd2l0aCBmdW5jdGlvbiB0byBpbnN0YWxsIHRoZSB3b3Jrc3BhY2UuXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlQmF6ZWxXb3Jrc3BhY2UocGtnOiBEZXAsIHdvcmtzcGFjZTogc3RyaW5nKSB7XG4gIGxldCBiemxGaWxlID0gYCMgR2VuZXJhdGVkIGJ5IHRoZSB5YXJuX2luc3RhbGwvbnBtX2luc3RhbGwgcnVsZVxubG9hZChcIkBidWlsZF9iYXplbF9ydWxlc19ub2RlanMvL2ludGVybmFsL2NvcHlfcmVwb3NpdG9yeTpjb3B5X3JlcG9zaXRvcnkuYnpsXCIsIFwiY29weV9yZXBvc2l0b3J5XCIpXG5cbmRlZiBfbWF5YmUocmVwb19ydWxlLCBuYW1lLCAqKmt3YXJncyk6XG4gICAgaWYgbmFtZSBub3QgaW4gbmF0aXZlLmV4aXN0aW5nX3J1bGVzKCk6XG4gICAgICAgIHJlcG9fcnVsZShuYW1lID0gbmFtZSwgKiprd2FyZ3MpXG5gO1xuXG4gIGNvbnN0IHJvb3RQYXRoID0gcGtnLmJhemVsV29ya3NwYWNlc1t3b3Jrc3BhY2VdLnJvb3RQYXRoO1xuICBpZiAoIXJvb3RQYXRoKSB7XG4gICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgYE1hbGZvcm1lZCBiYXplbFdvcmtzcGFjZXMgYXR0cmlidXRlIGluICR7cGtnLl9kaXJ9QCR7cGtnLnZlcnNpb259LiBgICtcbiAgICAgICAgYE1pc3Npbmcgcm9vdFBhdGggZm9yIHdvcmtzcGFjZSAke3dvcmtzcGFjZX0uYCk7XG4gICAgcHJvY2Vzcy5leGl0KDEpO1xuICB9XG5cbiAgLy8gQ29weSBhbGwgZmlsZXMgZm9yIHRoaXMgd29ya3NwYWNlIHRvIGEgZm9sZGVyIHVuZGVyIF93b3Jrc3BhY2VzXG4gIC8vIHRvIHJlc3RvcmUgdGhlIEJhemVsIGZpbGVzIHdoaWNoIGhhdmUgYmUgcmVuYW1lZCBmcm9tIHRoZSBucG0gcGFja2FnZVxuICBjb25zdCB3b3Jrc3BhY2VTb3VyY2VQYXRoID0gcGF0aC5wb3NpeC5qb2luKCdfd29ya3NwYWNlcycsIHdvcmtzcGFjZSk7XG4gIG1rZGlycCh3b3Jrc3BhY2VTb3VyY2VQYXRoKTtcbiAgcGtnLl9maWxlcy5mb3JFYWNoKGZpbGUgPT4ge1xuICAgIGlmICgvXm5vZGVfbW9kdWxlc1svXFxcXF0vLnRlc3QoZmlsZSkpIHtcbiAgICAgIC8vIGRvbid0IGNvcHkgb3ZlciBuZXN0ZWQgbm9kZV9tb2R1bGVzXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBkZXN0RmlsZSA9IHBhdGgucmVsYXRpdmUocm9vdFBhdGgsIGZpbGUpO1xuICAgIGlmIChkZXN0RmlsZS5zdGFydHNXaXRoKCcuLicpKSB7XG4gICAgICAvLyB0aGlzIGZpbGUgaXMgbm90IHVuZGVyIHRoZSByb290UGF0aFxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBiYXNlbmFtZSA9IHBhdGguYmFzZW5hbWUoZmlsZSk7XG4gICAgY29uc3QgYmFzZW5hbWVVYyA9IGJhc2VuYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgLy8gQmF6ZWwgQlVJTEQgZmlsZXMgZnJvbSBucG0gZGlzdHJpYnV0aW9uIHdvdWxkIGhhdmUgYmVlbiByZW5hbWVkIGVhcmxpZXIgd2l0aCBhIF8gcHJlZml4IHNvXG4gICAgLy8gd2UgcmVzdG9yZSB0aGUgbmFtZSBvbiB0aGUgY29weVxuICAgIGlmIChiYXNlbmFtZVVjID09PSAnX0JVSUxEJyB8fCBiYXNlbmFtZVVjID09PSAnX0JVSUxELkJBWkVMJykge1xuICAgICAgZGVzdEZpbGUgPSBwYXRoLnBvc2l4LmpvaW4ocGF0aC5kaXJuYW1lKGRlc3RGaWxlKSwgYmFzZW5hbWUuc3Vic3RyKDEpKTtcbiAgICB9XG4gICAgY29uc3Qgc3JjID0gcGF0aC5wb3NpeC5qb2luKCdub2RlX21vZHVsZXMnLCBwa2cuX2RpciwgZmlsZSk7XG4gICAgY29uc3QgZGVzdCA9IHBhdGgucG9zaXguam9pbih3b3Jrc3BhY2VTb3VyY2VQYXRoLCBkZXN0RmlsZSk7XG4gICAgbWtkaXJwKHBhdGguZGlybmFtZShkZXN0KSk7XG4gICAgZnMuY29weUZpbGVTeW5jKHNyYywgZGVzdCk7XG4gIH0pO1xuXG4gIC8vIFdlIGNyZWF0ZSBfYmF6ZWxfd29ya3NwYWNlX21hcmtlciB0aGF0IGlzIHVzZWQgYnkgdGhlIGN1c3RvbSBjb3B5X3JlcG9zaXRvcnlcbiAgLy8gcnVsZSB0byByZXNvbHZlIHRoZSBwYXRoIHRvIHRoZSByZXBvc2l0b3J5IHNvdXJjZSByb290LiBBIHJvb3QgQlVJTEQgZmlsZVxuICAvLyBpcyByZXF1aXJlZCB0byByZWZlcmVuY2UgX2JhemVsX3dvcmtzcGFjZV9tYXJrZXIgYXMgYSB0YXJnZXQgc28gd2UgYWxzbyBjcmVhdGVcbiAgLy8gYW4gZW1wdHkgb25lIGlmIG9uZSBkb2VzIG5vdCBleGlzdC5cbiAgaWYgKCFoYXNSb290QnVpbGRGaWxlKHBrZywgcm9vdFBhdGgpKSB7XG4gICAgd3JpdGVGaWxlU3luYyhcbiAgICAgICAgcGF0aC5wb3NpeC5qb2luKHdvcmtzcGFjZVNvdXJjZVBhdGgsICdCVUlMRC5iYXplbCcpLFxuICAgICAgICAnIyBNYXJrZXIgZmlsZSB0aGF0IHRoaXMgZGlyZWN0b3J5IGlzIGEgYmF6ZWwgcGFja2FnZScpO1xuICB9XG4gIGNvbnN0IHNoYTI1NnN1bSA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKTtcbiAgc2hhMjU2c3VtLnVwZGF0ZShmcy5yZWFkRmlsZVN5bmMoTE9DS19GSUxFX1BBVEgsIHtlbmNvZGluZzogJ3V0ZjgnfSkpO1xuICB3cml0ZUZpbGVTeW5jKFxuICAgICAgcGF0aC5wb3NpeC5qb2luKHdvcmtzcGFjZVNvdXJjZVBhdGgsICdfYmF6ZWxfd29ya3NwYWNlX21hcmtlcicpLFxuICAgICAgYCMgTWFya2VyIGZpbGUgdG8gdXNlZCBieSBjdXN0b20gY29weV9yZXBvc2l0b3J5IHJ1bGVcXG4ke3NoYTI1NnN1bS5kaWdlc3QoJ2hleCcpfWApO1xuXG4gIGJ6bEZpbGUgKz0gYGRlZiBpbnN0YWxsXyR7d29ya3NwYWNlfSgpOlxuICAgIF9tYXliZShcbiAgICAgICAgY29weV9yZXBvc2l0b3J5LFxuICAgICAgICBuYW1lID0gXCIke3dvcmtzcGFjZX1cIixcbiAgICAgICAgbWFya2VyX2ZpbGUgPSBcIkAke1dPUktTUEFDRX0vL193b3Jrc3BhY2VzLyR7d29ya3NwYWNlfTpfYmF6ZWxfd29ya3NwYWNlX21hcmtlclwiLFxuICAgIClcbmA7XG5cbiAgd3JpdGVGaWxlU3luYyhgaW5zdGFsbF8ke3dvcmtzcGFjZX0uYnpsYCwgYnpsRmlsZSk7XG59XG5cbi8qKlxuICogR2VuZXJhdGUgaW5zdGFsbF9iYXplbF9kZXBlbmRlbmNpZXMuYnpsIHdpdGggZnVuY3Rpb24gdG8gaW5zdGFsbCBhbGwgd29ya3NwYWNlcy5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVJbnN0YWxsQmF6ZWxEZXBlbmRlbmNpZXMod29ya3NwYWNlczogc3RyaW5nW10pIHtcbiAgbGV0IGJ6bEZpbGUgPSBgIyBHZW5lcmF0ZWQgYnkgdGhlIHlhcm5faW5zdGFsbC9ucG1faW5zdGFsbCBydWxlXG5gO1xuICB3b3Jrc3BhY2VzLmZvckVhY2god29ya3NwYWNlID0+IHtcbiAgICBiemxGaWxlICs9IGBsb2FkKFxcXCI6aW5zdGFsbF8ke3dvcmtzcGFjZX0uYnpsXFxcIiwgXFxcImluc3RhbGxfJHt3b3Jrc3BhY2V9XFxcIilcbmA7XG4gIH0pO1xuICBiemxGaWxlICs9IGBkZWYgaW5zdGFsbF9iYXplbF9kZXBlbmRlbmNpZXMoKTpcbiAgICBcIlwiXCJJbnN0YWxscyBhbGwgd29ya3NwYWNlcyBsaXN0ZWQgaW4gYmF6ZWxXb3Jrc3BhY2VzIG9mIGFsbCBucG0gcGFja2FnZXNcIlwiXCJcbmA7XG4gIHdvcmtzcGFjZXMuZm9yRWFjaCh3b3Jrc3BhY2UgPT4ge1xuICAgIGJ6bEZpbGUgKz0gYCAgICBpbnN0YWxsXyR7d29ya3NwYWNlfSgpXG5gO1xuICB9KTtcblxuICB3cml0ZUZpbGVTeW5jKCdpbnN0YWxsX2JhemVsX2RlcGVuZGVuY2llcy5iemwnLCBiemxGaWxlKTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZSBidWlsZCBmaWxlcyBmb3IgYSBzY29wZS5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVTY29wZUJ1aWxkRmlsZXMoc2NvcGU6IHN0cmluZywgcGtnczogRGVwW10pIHtcbiAgY29uc3QgYnVpbGRGaWxlID0gQlVJTERfRklMRV9IRUFERVIgKyBwcmludFNjb3BlKHNjb3BlLCBwa2dzKTtcbiAgd3JpdGVGaWxlU3luYyhwYXRoLnBvc2l4LmpvaW4oc2NvcGUsICdCVUlMRC5iYXplbCcpLCBidWlsZEZpbGUpO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHBhdGggaXMgYSBmaWxlLlxuICovXG5mdW5jdGlvbiBpc0ZpbGUocDogc3RyaW5nKSB7XG4gIHJldHVybiBmcy5leGlzdHNTeW5jKHApICYmIGZzLnN0YXRTeW5jKHApLmlzRmlsZSgpO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHBhdGggaXMgYW4gbnBtIHBhY2thZ2Ugd2hpY2ggaXMgaXMgYSBkaXJlY3Rvcnkgd2l0aCBhIHBhY2thZ2UuanNvbiBmaWxlLlxuICovXG5mdW5jdGlvbiBpc0RpcmVjdG9yeShwOiBzdHJpbmcpIHtcbiAgcmV0dXJuIGZzLmV4aXN0c1N5bmMocCkgJiYgZnMuc3RhdFN5bmMocCkuaXNEaXJlY3RvcnkoKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGFuIGFycmF5IG9mIGFsbCB0aGUgZmlsZXMgdW5kZXIgYSBkaXJlY3RvcnkgYXMgcmVsYXRpdmVcbiAqIHBhdGhzIHRvIHRoZSBkaXJlY3RvcnkuXG4gKi9cbmZ1bmN0aW9uIGxpc3RGaWxlcyhyb290RGlyOiBzdHJpbmcsIHN1YkRpcjogc3RyaW5nID0gJycpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGRpciA9IHBhdGgucG9zaXguam9pbihyb290RGlyLCBzdWJEaXIpO1xuICBpZiAoIWlzRGlyZWN0b3J5KGRpcikpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgcmV0dXJuIGZzLnJlYWRkaXJTeW5jKGRpcilcbiAgICAgIC5yZWR1Y2UoXG4gICAgICAgICAgKGZpbGVzOiBzdHJpbmdbXSwgZmlsZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLnBvc2l4LmpvaW4oZGlyLCBmaWxlKTtcbiAgICAgICAgICAgIGNvbnN0IHJlbFBhdGggPSBwYXRoLnBvc2l4LmpvaW4oc3ViRGlyLCBmaWxlKTtcbiAgICAgICAgICAgIGNvbnN0IGlzU3ltYm9saWNMaW5rID0gZnMubHN0YXRTeW5jKGZ1bGxQYXRoKS5pc1N5bWJvbGljTGluaygpO1xuICAgICAgICAgICAgbGV0IHN0YXQ7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBzdGF0ID0gZnMuc3RhdFN5bmMoZnVsbFBhdGgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICBpZiAoaXNTeW1ib2xpY0xpbmspIHtcbiAgICAgICAgICAgICAgICAvLyBGaWx0ZXIgb3V0IGJyb2tlbiBzeW1ib2xpYyBsaW5rcy4gVGhlc2UgY2F1c2UgZnMuc3RhdFN5bmMoZnVsbFBhdGgpXG4gICAgICAgICAgICAgICAgLy8gdG8gZmFpbCB3aXRoIGBFTk9FTlQ6IG5vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnkgLi4uYFxuICAgICAgICAgICAgICAgIHJldHVybiBmaWxlcztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaXNEaXJlY3RvcnkgPSBzdGF0LmlzRGlyZWN0b3J5KCk7XG4gICAgICAgICAgICBpZiAoaXNEaXJlY3RvcnkgJiYgaXNTeW1ib2xpY0xpbmspIHtcbiAgICAgICAgICAgICAgLy8gRmlsdGVyIG91dCBzeW1ib2xpYyBsaW5rcyB0byBkaXJlY3Rvcmllcy4gQW4gaXNzdWUgaW4geWFybiB2ZXJzaW9uc1xuICAgICAgICAgICAgICAvLyBvbGRlciB0aGFuIDEuMTIuMSBjcmVhdGVzIHN5bWJvbGljIGxpbmtzIHRvIGZvbGRlcnMgaW4gdGhlIC5iaW4gZm9sZGVyXG4gICAgICAgICAgICAgIC8vIHdoaWNoIGxlYWRzIHRvIEJhemVsIHRhcmdldHMgdGhhdCBjcm9zcyBwYWNrYWdlIGJvdW5kYXJpZXMuXG4gICAgICAgICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYmF6ZWxidWlsZC9ydWxlc19ub2RlanMvaXNzdWVzLzQyOCBhbmRcbiAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2JhemVsYnVpbGQvcnVsZXNfbm9kZWpzL2lzc3Vlcy80MzguXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXMgdGVzdGVkIGluIC9lMmUvZmluZV9ncmFpbmVkX3N5bWxpbmtzLlxuICAgICAgICAgICAgICByZXR1cm4gZmlsZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaXNEaXJlY3RvcnkgPyBmaWxlcy5jb25jYXQobGlzdEZpbGVzKHJvb3REaXIsIHJlbFBhdGgpKSA6IGZpbGVzLmNvbmNhdChyZWxQYXRoKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIFtdKVxuICAgICAgLy8gRmlsZXMgd2l0aCBzcGFjZXMgKFxceDIwKSBvciB1bmljb2RlIGNoYXJhY3RlcnMgKDxcXHgyMCAmJiA+XFx4N0UpIGFyZSBub3QgYWxsb3dlZCBpblxuICAgICAgLy8gQmF6ZWwgcnVuZmlsZXMuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYmF6ZWxidWlsZC9iYXplbC9pc3N1ZXMvNDMyN1xuICAgICAgLmZpbHRlcihmID0+ICEvW15cXHgyMS1cXHg3RV0vLnRlc3QoZikpXG4gICAgICAvLyBXZSByZXR1cm4gYSBzb3J0ZWQgYXJyYXkgc28gdGhhdCB0aGUgb3JkZXIgb2YgZmlsZXNcbiAgICAgIC8vIGlzIHRoZSBzYW1lIHJlZ2FyZGxlc3Mgb2YgcGxhdGZvcm1cbiAgICAgIC5zb3J0KCk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBucG0gcGFja2FnZSBkaXN0cmlidXRpb24gY29udGFpbmVkIGFcbiAqIHJvb3QgL0JVSUxEIG9yIC9CVUlMRC5iYXplbCBmaWxlLlxuICovXG5mdW5jdGlvbiBoYXNSb290QnVpbGRGaWxlKHBrZzogRGVwLCByb290UGF0aDogc3RyaW5nKSB7XG4gIGZvciAoY29uc3QgZmlsZSBvZiBwa2cuX2ZpbGVzKSB7XG4gICAgLy8gQmF6ZWwgZmlsZXMgd291bGQgaGF2ZSBiZWVuIHJlbmFtZWQgZWFybGllciB3aXRoIGEgYF9gIHByZWZpeFxuICAgIGNvbnN0IGZpbGVVYyA9IHBhdGgucmVsYXRpdmUocm9vdFBhdGgsIGZpbGUpLnRvVXBwZXJDYXNlKCk7XG4gICAgaWYgKGZpbGVVYyA9PT0gJ19CVUlMRCcgfHwgZmlsZVVjID09PSAnX0JVSUxELkJBWkVMJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuXG5mdW5jdGlvbiBhZGREeW5hbWljRGVwZW5kZW5jaWVzKHBrZ3M6IERlcFtdLCBkeW5hbWljX2RlcHMgPSBEWU5BTUlDX0RFUFMpIHtcbiAgZnVuY3Rpb24gbWF0Y2gobmFtZTogc3RyaW5nLCBwOiBEZXApIHtcbiAgICAvLyBBdXRvbWF0aWNhbGx5IGluY2x1ZGUgZHluYW1pYyBkZXBlbmRlbmN5IG9uIHBsdWdpbnMgb2YgdGhlIGZvcm0gcGtnLXBsdWdpbi1mb29cbiAgICBpZiAobmFtZS5zdGFydHNXaXRoKGAke3AuX21vZHVsZU5hbWV9LXBsdWdpbi1gKSkgcmV0dXJuIHRydWU7XG5cbiAgICBjb25zdCB2YWx1ZSA9IGR5bmFtaWNfZGVwc1twLl9tb2R1bGVOYW1lXTtcbiAgICBpZiAobmFtZSA9PT0gdmFsdWUpIHJldHVybiB0cnVlO1xuXG4gICAgLy8gU3VwcG9ydCB3aWxkY2FyZCBtYXRjaFxuICAgIGlmICh2YWx1ZSAmJiB2YWx1ZS5pbmNsdWRlcygnKicpICYmIG5hbWUuc3RhcnRzV2l0aCh2YWx1ZS5zdWJzdHJpbmcoMCwgdmFsdWUuaW5kZXhPZignKicpKSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBwa2dzLmZvckVhY2gocCA9PiB7XG4gICAgcC5fZHluYW1pY0RlcGVuZGVuY2llcyA9XG4gICAgICAgIHBrZ3MuZmlsdGVyKFxuICAgICAgICAgICAgICAgIC8vIEZpbHRlciBlbnRyaWVzIGxpa2VcbiAgICAgICAgICAgICAgICAvLyBcIl9kaXJcIjpcImNoZWNrLXNpZGUtZWZmZWN0cy9ub2RlX21vZHVsZXMvcm9sbHVwLXBsdWdpbi1ub2RlLXJlc29sdmVcIlxuICAgICAgICAgICAgICAgIHggPT4gIXguX2Rpci5pbmNsdWRlcygnL25vZGVfbW9kdWxlcy8nKSAmJiAhIXguX21vZHVsZU5hbWUgJiZcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2goeC5fbW9kdWxlTmFtZSwgcCkpXG4gICAgICAgICAgICAubWFwKGR5biA9PiBgLy8ke2R5bi5fZGlyfToke2R5bi5fbmFtZX1gKTtcbiAgfSk7XG59XG5cbi8qKlxuICogRmluZHMgYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgYWxsIHBhY2thZ2VzIHVuZGVyIGEgZ2l2ZW4gcGF0aC5cbiAqL1xuZnVuY3Rpb24gZmluZFBhY2thZ2VzKHAgPSAnbm9kZV9tb2R1bGVzJykge1xuICBpZiAoIWlzRGlyZWN0b3J5KHApKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgcGtnczogRGVwW10gPSBbXTtcblxuICBjb25zdCBsaXN0aW5nID0gZnMucmVhZGRpclN5bmMocCk7XG5cbiAgY29uc3QgcGFja2FnZXMgPSBsaXN0aW5nXG4gICAgICAgICAgICAgICAgICAgICAgIC8vIGZpbHRlciBvdXQgc2NvcGVzXG4gICAgICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoZiA9PiAhZi5zdGFydHNXaXRoKCdAJykpXG4gICAgICAgICAgICAgICAgICAgICAgIC8vIGZpbHRlciBvdXQgZm9sZGVycyBzdWNoIGFzIGAuYmluYCB3aGljaCBjYW4gY3JlYXRlXG4gICAgICAgICAgICAgICAgICAgICAgIC8vIGlzc3VlcyBvbiBXaW5kb3dzIHNpbmNlIHRoZXNlIGFyZSBcImhpZGRlblwiIGJ5IGRlZmF1bHRcbiAgICAgICAgICAgICAgICAgICAgICAgLmZpbHRlcihmID0+ICFmLnN0YXJ0c1dpdGgoJy4nKSlcbiAgICAgICAgICAgICAgICAgICAgICAgLm1hcChmID0+IHBhdGgucG9zaXguam9pbihwLCBmKSlcbiAgICAgICAgICAgICAgICAgICAgICAgLmZpbHRlcihmID0+IGlzRGlyZWN0b3J5KGYpKTtcblxuICBwYWNrYWdlcy5mb3JFYWNoKFxuICAgICAgZiA9PiBwa2dzLnB1c2gocGFyc2VQYWNrYWdlKGYpLCAuLi5maW5kUGFja2FnZXMocGF0aC5wb3NpeC5qb2luKGYsICdub2RlX21vZHVsZXMnKSkpKTtcblxuICBjb25zdCBzY29wZXMgPSBsaXN0aW5nLmZpbHRlcihmID0+IGYuc3RhcnRzV2l0aCgnQCcpKVxuICAgICAgICAgICAgICAgICAgICAgLm1hcChmID0+IHBhdGgucG9zaXguam9pbihwLCBmKSlcbiAgICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoZiA9PiBpc0RpcmVjdG9yeShmKSk7XG4gIHNjb3Blcy5mb3JFYWNoKGYgPT4gcGtncy5wdXNoKC4uLmZpbmRQYWNrYWdlcyhmKSkpO1xuXG4gIGFkZER5bmFtaWNEZXBlbmRlbmNpZXMocGtncyk7XG5cbiAgcmV0dXJuIHBrZ3M7XG59XG5cbi8qKlxuICogRmluZHMgYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgYWxsIHBhY2thZ2Ugc2NvcGVzIGluIG5vZGVfbW9kdWxlcy5cbiAqL1xuZnVuY3Rpb24gZmluZFNjb3BlcygpIHtcbiAgY29uc3QgcCA9ICdub2RlX21vZHVsZXMnO1xuICBpZiAoIWlzRGlyZWN0b3J5KHApKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgbGlzdGluZyA9IGZzLnJlYWRkaXJTeW5jKHApO1xuXG4gIGNvbnN0IHNjb3BlcyA9IGxpc3RpbmcuZmlsdGVyKGYgPT4gZi5zdGFydHNXaXRoKCdAJykpXG4gICAgICAgICAgICAgICAgICAgICAubWFwKGYgPT4gcGF0aC5wb3NpeC5qb2luKHAsIGYpKVxuICAgICAgICAgICAgICAgICAgICAgLmZpbHRlcihmID0+IGlzRGlyZWN0b3J5KGYpKVxuICAgICAgICAgICAgICAgICAgICAgLm1hcChmID0+IGYucmVwbGFjZSgvXm5vZGVfbW9kdWxlc1xcLy8sICcnKSk7XG5cbiAgcmV0dXJuIHNjb3Blcztcbn1cblxuLyoqXG4gKiBHaXZlbiB0aGUgbmFtZSBvZiBhIHRvcC1sZXZlbCBmb2xkZXIgaW4gbm9kZV9tb2R1bGVzLCBwYXJzZSB0aGVcbiAqIHBhY2thZ2UganNvbiBhbmQgcmV0dXJuIGl0IGFzIGFuIG9iamVjdCBhbG9uZyB3aXRoXG4gKiBzb21lIGFkZGl0aW9uYWwgaW50ZXJuYWwgYXR0cmlidXRlcyBwcmVmaXhlZCB3aXRoICdfJy5cbiAqL1xuZnVuY3Rpb24gcGFyc2VQYWNrYWdlKHA6IHN0cmluZyk6IERlcCB7XG4gIC8vIFBhcnNlIHRoZSBwYWNrYWdlLmpzb24gZmlsZSBvZiB0aGlzIHBhY2thZ2VcbiAgY29uc3QgcGFja2FnZUpzb24gPSBwYXRoLnBvc2l4LmpvaW4ocCwgJ3BhY2thZ2UuanNvbicpO1xuICBjb25zdCBwa2cgPSBpc0ZpbGUocGFja2FnZUpzb24pID8gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMocGFja2FnZUpzb24sIHtlbmNvZGluZzogJ3V0ZjgnfSkpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt2ZXJzaW9uOiAnMC4wLjAnfTtcblxuICAvLyBUcmltIHRoZSBsZWFkaW5nIG5vZGVfbW9kdWxlcyBmcm9tIHRoZSBwYXRoIGFuZFxuICAvLyBhc3NpZ24gdG8gX2RpciBmb3IgZnV0dXJlIHVzZVxuICBwa2cuX2RpciA9IHAucmVwbGFjZSgvXm5vZGVfbW9kdWxlc1xcLy8sICcnKTtcblxuICAvLyBTdGFzaCB0aGUgcGFja2FnZSBkaXJlY3RvcnkgbmFtZSBmb3IgZnV0dXJlIHVzZVxuICBwa2cuX25hbWUgPSBwa2cuX2Rpci5zcGxpdCgnLycpLnBvcCgpO1xuXG4gIC8vIE1vZHVsZSBuYW1lIG9mIHRoZSBwYWNrYWdlLiBVbmxpa2UgXCJfbmFtZVwiIHRoaXMgcmVwcmVzZW50cyB0aGVcbiAgLy8gZnVsbCBwYWNrYWdlIG5hbWUgKGluY2x1ZGluZyBzY29wZSBuYW1lKS5cbiAgcGtnLl9tb2R1bGVOYW1lID0gcGtnLm5hbWUgfHwgYCR7cGtnLl9kaXJ9LyR7cGtnLl9uYW1lfWA7XG5cbiAgLy8gS2VlcCB0cmFjayBvZiB3aGV0aGVyIG9yIG5vdCB0aGlzIGlzIGEgbmVzdGVkIHBhY2thZ2VcbiAgcGtnLl9pc05lc3RlZCA9IC9cXC9ub2RlX21vZHVsZXNcXC8vLnRlc3QocCk7XG5cbiAgLy8gTGlzdCBhbGwgdGhlIGZpbGVzIGluIHRoZSBucG0gcGFja2FnZSBmb3IgbGF0ZXIgdXNlXG4gIHBrZy5fZmlsZXMgPSBsaXN0RmlsZXMocCk7XG5cbiAgLy8gSW5pdGlhbGl6ZSBfZGVwZW5kZW5jaWVzIHRvIGFuIGVtcHR5IGFycmF5XG4gIC8vIHdoaWNoIGlzIGxhdGVyIGZpbGxlZCB3aXRoIHRoZSBmbGF0dGVuZWQgZGVwZW5kZW5jeSBsaXN0XG4gIHBrZy5fZGVwZW5kZW5jaWVzID0gW107XG5cbiAgLy8gSGlkZSBiYXplbCBmaWxlcyBpbiB0aGlzIHBhY2thZ2UuIFdlIGRvIHRoaXMgYmVmb3JlIHBhcnNpbmdcbiAgLy8gdGhlIG5leHQgcGFja2FnZSB0byBwcmV2ZW50IGlzc3VlcyBjYXVzZWQgYnkgc3ltbGlua3MgYmV0d2VlblxuICAvLyBwYWNrYWdlIGFuZCBuZXN0ZWQgcGFja2FnZXMgc2V0dXAgYnkgdGhlIHBhY2thZ2UgbWFuYWdlci5cbiAgaGlkZUJhemVsRmlsZXMocGtnKTtcblxuICByZXR1cm4gcGtnO1xufVxuXG4vKipcbiAqIENoZWNrIGlmIGEgYmluIGVudHJ5IGlzIGEgbm9uLWVtcHR5IHBhdGhcbiAqL1xuZnVuY3Rpb24gaXNWYWxpZEJpblBhdGgoZW50cnk6IGFueSkge1xuICByZXR1cm4gaXNWYWxpZEJpblBhdGhTdHJpbmdWYWx1ZShlbnRyeSkgfHwgaXNWYWxpZEJpblBhdGhPYmplY3RWYWx1ZXMoZW50cnkpO1xufVxuXG4vKipcbiAqIElmIGdpdmVuIGEgc3RyaW5nLCBjaGVjayBpZiBhIGJpbiBlbnRyeSBpcyBhIG5vbi1lbXB0eSBwYXRoXG4gKi9cbmZ1bmN0aW9uIGlzVmFsaWRCaW5QYXRoU3RyaW5nVmFsdWUoZW50cnk6IGFueSkge1xuICByZXR1cm4gdHlwZW9mIGVudHJ5ID09PSAnc3RyaW5nJyAmJiBlbnRyeSAhPT0gJyc7XG59XG5cbi8qKlxuICogSWYgZ2l2ZW4gYW4gb2JqZWN0IGxpdGVyYWwsIGNoZWNrIGlmIGEgYmluIGVudHJ5IG9iamVjdHMgaGFzIGF0IGxlYXN0IG9uZSBhIG5vbi1lbXB0eSBwYXRoXG4gKiBFeGFtcGxlIDE6IHsgZW50cnk6ICcuL3BhdGgvdG8vc2NyaXB0LmpzJyB9ID09PiBWQUxJRFxuICogRXhhbXBsZSAyOiB7IGVudHJ5OiAnJyB9ID09PiBJTlZBTElEXG4gKiBFeGFtcGxlIDM6IHsgZW50cnk6ICcuL3BhdGgvdG8vc2NyaXB0LmpzJywgZW1wdHk6ICcnIH0gPT0+IFZBTElEXG4gKi9cbmZ1bmN0aW9uIGlzVmFsaWRCaW5QYXRoT2JqZWN0VmFsdWVzKGVudHJ5OiBCYWc8c3RyaW5nPik6IGJvb2xlYW4ge1xuICAvLyBXZSBhbGxvdyBhdCBsZWFzdCBvbmUgdmFsaWQgZW50cnkgcGF0aCAoaWYgYW55KS5cbiAgcmV0dXJuIGVudHJ5ICYmIHR5cGVvZiBlbnRyeSA9PT0gJ29iamVjdCcgJiZcbiAgICAgIE9iamVjdFsndmFsdWVzJ10oZW50cnkpLmZpbHRlcihfZW50cnkgPT4gaXNWYWxpZEJpblBhdGgoX2VudHJ5KSkubGVuZ3RoID4gMDtcbn1cblxuLyoqXG4gKiBDbGVhbnVwIGEgcGFja2FnZS5qc29uIFwiYmluXCIgcGF0aC5cbiAqXG4gKiBCaW4gcGF0aHMgdXN1YWxseSBjb21lIGluIDIgZmxhdm9yczogJy4vYmluL2Zvbycgb3IgJ2Jpbi9mb28nLFxuICogc29tZXRpbWVzIG90aGVyIHN0dWZmIGxpa2UgJ2xpYi9mb28nLiAgUmVtb3ZlIHByZWZpeCAnLi8nIGlmIGl0XG4gKiBleGlzdHMuXG4gKi9cbmZ1bmN0aW9uIGNsZWFudXBCaW5QYXRoKHA6IHN0cmluZykge1xuICBwID0gcC5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gIGlmIChwLmluZGV4T2YoJy4vJykgPT09IDApIHtcbiAgICBwID0gcC5zbGljZSgyKTtcbiAgfVxuICByZXR1cm4gcDtcbn1cblxuLyoqXG4gKiBDbGVhbnVwIGEgcGFja2FnZS5qc29uIGVudHJ5IHBvaW50IHN1Y2ggYXMgXCJtYWluXCJcbiAqXG4gKiBSZW1vdmVzICcuLycgaWYgaXQgZXhpc3RzLlxuICogQXBwZW5kcyBgaW5kZXguanNgIGlmIHAgZW5kcyB3aXRoIGAvYC5cbiAqL1xuZnVuY3Rpb24gY2xlYW51cEVudHJ5UG9pbnRQYXRoKHA6IHN0cmluZykge1xuICBwID0gcC5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gIGlmIChwLmluZGV4T2YoJy4vJykgPT09IDApIHtcbiAgICBwID0gcC5zbGljZSgyKTtcbiAgfVxuICBpZiAocC5lbmRzV2l0aCgnLycpKSB7XG4gICAgcCArPSAnaW5kZXguanMnO1xuICB9XG4gIHJldHVybiBwO1xufVxuXG4vKipcbiAqIENsZWFucyB1cCB0aGUgZ2l2ZW4gcGF0aFxuICogVGhlbiB0cmllcyB0byByZXNvbHZlIHRoZSBwYXRoIGludG8gYSBmaWxlIGFuZCB3YXJucyBpZiBWRVJCT1NFX0xPR1Mgc2V0IGFuZCB0aGUgZmlsZSBkb3Nlbid0XG4gKiBleGlzdFxuICogQHBhcmFtIHthbnl9IHBrZ1xuICogQHBhcmFtIHtzdHJpbmd9IHBhdGhcbiAqIEByZXR1cm5zIHtzdHJpbmcgfCB1bmRlZmluZWR9XG4gKi9cbmZ1bmN0aW9uIGZpbmRFbnRyeUZpbGUocGtnOiBEZXAsIHBhdGg6IHN0cmluZykge1xuICBjb25zdCBjbGVhblBhdGggPSBjbGVhbnVwRW50cnlQb2ludFBhdGgocGF0aCk7XG4gIC8vIGNoZWNrIGlmIG1haW4gZW50cnkgcG9pbnQgZXhpc3RzXG4gIGNvbnN0IGVudHJ5RmlsZSA9IGZpbmRGaWxlKHBrZywgY2xlYW5QYXRoKSB8fCBmaW5kRmlsZShwa2csIGAke2NsZWFuUGF0aH0uanNgKTtcbiAgaWYgKCFlbnRyeUZpbGUpIHtcbiAgICAvLyBJZiBlbnRyeVBvaW50IGVudHJ5IHBvaW50IGxpc3RlZCBjb3VsZCBub3QgYmUgcmVzb2x2ZWQgdG8gYSBmaWxlXG4gICAgLy8gVGhpcyBjYW4gaGFwcGVuXG4gICAgLy8gaW4gc29tZSBucG0gcGFja2FnZXMgdGhhdCBsaXN0IGFuIGluY29ycmVjdCBtYWluIHN1Y2ggYXMgdjgtY292ZXJhZ2VAMS4wLjhcbiAgICAvLyB3aGljaCBsaXN0cyBgXCJtYWluXCI6IFwiaW5kZXguanNcImAgYnV0IHRoYXQgZmlsZSBkb2VzIG5vdCBleGlzdC5cbiAgICBsb2dfdmVyYm9zZShcbiAgICAgICAgYGNvdWxkIG5vdCBmaW5kIGVudHJ5IHBvaW50IGZvciB0aGUgcGF0aCAke2NsZWFuUGF0aH0gZ2l2ZW4gYnkgbnBtIHBhY2thZ2UgJHtwa2cuX25hbWV9YCk7XG4gIH1cbiAgcmV0dXJuIGVudHJ5RmlsZTtcbn1cblxuLyoqXG4gKiBUcmllcyB0byByZXNvbHZlIHRoZSBlbnRyeVBvaW50IGZpbGUgZnJvbSB0aGUgcGtnIGZvciBhIGdpdmVuIG1haW5GaWxlTmFtZVxuICpcbiAqIEBwYXJhbSB7YW55fSBwa2dcbiAqIEBwYXJhbSB7J2Jyb3dzZXInIHwgJ21vZHVsZScgfCAnbWFpbid9IG1haW5GaWxlTmFtZVxuICogQHJldHVybnMge3N0cmluZyB8IHVuZGVmaW5lZH0gdGhlIHBhdGggb3IgdW5kZWZpbmVkIGlmIHdlIGNhbnQgcmVzb2x2ZSB0aGUgZmlsZVxuICovXG5mdW5jdGlvbiByZXNvbHZlTWFpbkZpbGUocGtnOiBEZXAsIG1haW5GaWxlTmFtZTogc3RyaW5nKSB7XG4gIGNvbnN0IG1haW5FbnRyeUZpZWxkID0gcGtnW21haW5GaWxlTmFtZV07XG5cbiAgaWYgKG1haW5FbnRyeUZpZWxkKSB7XG4gICAgaWYgKHR5cGVvZiBtYWluRW50cnlGaWVsZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBmaW5kRW50cnlGaWxlKHBrZywgbWFpbkVudHJ5RmllbGQpXG5cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBtYWluRW50cnlGaWVsZCA9PT0gJ29iamVjdCcgJiYgbWFpbkZpbGVOYW1lID09PSAnYnJvd3NlcicpIHtcbiAgICAgIC8vIGJyb3dzZXIgaGFzIGEgd2VpcmQgd2F5IG9mIGRlZmluaW5nIHRoaXNcbiAgICAgIC8vIHRoZSBicm93c2VyIHZhbHVlIGlzIGFuIG9iamVjdCBsaXN0aW5nIGZpbGVzIHRvIGFsaWFzLCB1c3VhbGx5IHBvaW50aW5nIHRvIGEgYnJvd3NlciBkaXJcbiAgICAgIGNvbnN0IGluZGV4RW50cnlQb2ludCA9IG1haW5FbnRyeUZpZWxkWydpbmRleC5qcyddIHx8IG1haW5FbnRyeUZpZWxkWycuL2luZGV4LmpzJ107XG4gICAgICBpZiAoaW5kZXhFbnRyeVBvaW50KSB7XG4gICAgICAgIHJldHVybiBmaW5kRW50cnlGaWxlKHBrZywgaW5kZXhFbnRyeVBvaW50KVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFRyaWVzIHRvIHJlc29sdmUgdGhlIG1haW5GaWxlIGZyb20gYSBnaXZlbiBwa2dcbiAqIFRoaXMgdXNlcyBzZXZlYWwgbWFpbkZpbGVOYW1lcyBpbiBwcmlvcml0eSB0byBmaW5kIGEgY29ycmVjdCB1c2FibGUgZmlsZVxuICogQHBhcmFtIHthbnl9IHBrZ1xuICogQHJldHVybnMge3N0cmluZyB8IHVuZGVmaW5lZH1cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVBrZ01haW5GaWxlKHBrZzogRGVwKSB7XG4gIC8vIGVzMjAxNSBpcyBhbm90aGVyIG9wdGlvbiBmb3IgbWFpbkZpbGUgaGVyZVxuICAvLyBidXQgaXRzIHZlcnkgdW5jb21tb24gYW5kIGltIG5vdCBzdXJlIHdoYXQgcHJpb3JpdHkgaXQgdGFrZXNcbiAgLy9cbiAgLy8gdGhpcyBsaXN0IGlzIG9yZGVyZWQsIHdlIHRyeSByZXNvbHZlIGBicm93c2VyYCBmaXJzdCwgdGhlbiBgbW9kdWxlYCBhbmQgZmluYWxseSBmYWxsIGJhY2sgdG9cbiAgLy8gYG1haW5gXG4gIGNvbnN0IG1haW5GaWxlTmFtZXMgPSBbJ2Jyb3dzZXInLCAnbW9kdWxlJywgJ21haW4nXVxuXG4gICAgICBmb3IgKGNvbnN0IG1haW5GaWxlIG9mIG1haW5GaWxlTmFtZXMpIHtcbiAgICBjb25zdCByZXNvbHZlZE1haW5GaWxlID0gcmVzb2x2ZU1haW5GaWxlKHBrZywgbWFpbkZpbGUpO1xuICAgIGlmIChyZXNvbHZlZE1haW5GaWxlKSB7XG4gICAgICByZXR1cm4gcmVzb2x2ZWRNYWluRmlsZTtcbiAgICB9XG4gIH1cblxuICAvLyBpZiB3ZSBjYW50IGZpbmQgYW55IGNvcnJlY3QgZmlsZSByZWZlcmVuY2VzIGZyb20gdGhlIHBrZ1xuICAvLyB0aGVuIHdlIGp1c3QgdHJ5IGxvb2tpbmcgYXJvdW5kIGZvciBjb21tb24gcGF0dGVybnNcbiAgY29uc3QgbWF5YmVSb290SW5kZXggPSBmaW5kRW50cnlGaWxlKHBrZywgJ2luZGV4LmpzJyk7XG4gIGlmIChtYXliZVJvb3RJbmRleCkge1xuICAgIHJldHVybiBtYXliZVJvb3RJbmRleFxuICB9XG5cbiAgY29uc3QgbWF5YmVTZWxmTmFtZWRJbmRleCA9IGZpbmRFbnRyeUZpbGUocGtnLCBgJHtwa2cuX25hbWV9LmpzYCk7XG4gIGlmIChtYXliZVNlbGZOYW1lZEluZGV4KSB7XG4gICAgcmV0dXJuIG1heWJlU2VsZk5hbWVkSW5kZXg7XG4gIH1cblxuICAvLyBub25lIG9mIHRoZSBtZXRob2RzIHdlIHRyaWVkIHJlc3VsdGVkIGluIGEgZmlsZVxuICBsb2dfdmVyYm9zZShgY291bGQgbm90IGZpbmQgZW50cnkgcG9pbnQgZm9yIG5wbSBwYWNrYWdlICR7cGtnLl9uYW1lfWApO1xuXG4gIC8vIGF0IHRoaXMgcG9pbnQgdGhlcmUncyBub3RoaW5nIGxlZnQgZm9yIHVzIHRvIHRyeSwgc28gcmV0dXJuIG5vdGhpbmdcbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxudHlwZSBCYWc8VD4gPVxuICAgIHtcbiAgICAgIFtrOiBzdHJpbmddOiBUXG4gICAgfVxuXG4vKipcbiAqIEZsYXR0ZW5zIGFsbCB0cmFuc2l0aXZlIGRlcGVuZGVuY2llcyBvZiBhIHBhY2thZ2VcbiAqIGludG8gYSBfZGVwZW5kZW5jaWVzIGFycmF5LlxuICovXG5mdW5jdGlvbiBmbGF0dGVuUGtnRGVwZW5kZW5jaWVzKHBrZzogRGVwLCBkZXA6IERlcCwgcGtnc01hcDogTWFwPHN0cmluZywgRGVwPikge1xuICBpZiAocGtnLl9kZXBlbmRlbmNpZXMuaW5kZXhPZihkZXApICE9PSAtMSkge1xuICAgIC8vIGNpcmN1bGFyIGRlcGVuZGVuY3lcbiAgICByZXR1cm47XG4gIH1cbiAgcGtnLl9kZXBlbmRlbmNpZXMucHVzaChkZXApO1xuICBjb25zdCBmaW5kRGVwcyA9IGZ1bmN0aW9uKHRhcmdldERlcHM6IEJhZzxzdHJpbmc+LCByZXF1aXJlZDogYm9vbGVhbiwgZGVwVHlwZTogc3RyaW5nKSB7XG4gICAgT2JqZWN0LmtleXModGFyZ2V0RGVwcyB8fCB7fSlcbiAgICAgICAgLm1hcCh0YXJnZXREZXAgPT4ge1xuICAgICAgICAgIC8vIGxvb2sgZm9yIG1hdGNoaW5nIG5lc3RlZCBwYWNrYWdlXG4gICAgICAgICAgY29uc3QgZGlyU2VnbWVudHMgPSBkZXAuX2Rpci5zcGxpdCgnLycpO1xuICAgICAgICAgIHdoaWxlIChkaXJTZWdtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IG1heWJlID0gcGF0aC5wb3NpeC5qb2luKC4uLmRpclNlZ21lbnRzLCAnbm9kZV9tb2R1bGVzJywgdGFyZ2V0RGVwKTtcbiAgICAgICAgICAgIGlmIChwa2dzTWFwLmhhcyhtYXliZSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHBrZ3NNYXAuZ2V0KG1heWJlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRpclNlZ21lbnRzLnBvcCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBsb29rIGZvciBtYXRjaGluZyByb290IHBhY2thZ2VcbiAgICAgICAgICBpZiAocGtnc01hcC5oYXModGFyZ2V0RGVwKSkge1xuICAgICAgICAgICAgcmV0dXJuIHBrZ3NNYXAuZ2V0KHRhcmdldERlcCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIGRlcGVuZGVuY3kgbm90IGZvdW5kXG4gICAgICAgICAgaWYgKHJlcXVpcmVkKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBjb3VsZCBub3QgZmluZCAke2RlcFR5cGV9ICcke3RhcmdldERlcH0nIG9mICcke2RlcC5fZGlyfSdgKTtcbiAgICAgICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH0pXG4gICAgICAgIC5maWx0ZXIoZGVwID0+ICEhZGVwKVxuICAgICAgICAuZm9yRWFjaChkZXAgPT4gZmxhdHRlblBrZ0RlcGVuZGVuY2llcyhwa2csIGRlcCEsIHBrZ3NNYXApKTtcbiAgfTtcbiAgLy8gbnBtIHdpbGwgaW4gc29tZSBjYXNlcyBhZGQgb3B0aW9uYWxEZXBlbmRlbmNpZXMgdG8gdGhlIGxpc3RcbiAgLy8gb2YgZGVwZW5kZW5jaWVzIHRvIHRoZSBwYWNrYWdlLmpzb24gaXQgd3JpdGVzIHRvIG5vZGVfbW9kdWxlcy5cbiAgLy8gV2UgZGVsZXRlIHRoZXNlIGhlcmUgaWYgdGhleSBleGlzdCBhcyB0aGV5IG1heSByZXN1bHRcbiAgLy8gaW4gZXhwZWN0ZWQgZGVwZW5kZW5jaWVzIHRoYXQgYXJlIG5vdCBmb3VuZC5cbiAgaWYgKGRlcC5kZXBlbmRlbmNpZXMgJiYgZGVwLm9wdGlvbmFsRGVwZW5kZW5jaWVzKSB7XG4gICAgT2JqZWN0LmtleXMoZGVwLm9wdGlvbmFsRGVwZW5kZW5jaWVzKS5mb3JFYWNoKG9wdGlvbmFsRGVwID0+IHtcbiAgICAgIGRlbGV0ZSBkZXAuZGVwZW5kZW5jaWVzW29wdGlvbmFsRGVwXTtcbiAgICB9KTtcbiAgfVxuXG4gIGZpbmREZXBzKGRlcC5kZXBlbmRlbmNpZXMsIHRydWUsICdkZXBlbmRlbmN5Jyk7XG4gIGZpbmREZXBzKGRlcC5wZWVyRGVwZW5kZW5jaWVzLCB0cnVlLCAncGVlciBkZXBlbmRlbmN5Jyk7XG4gIC8vIGBvcHRpb25hbERlcGVuZGVuY2llc2AgdGhhdCBhcmUgbWlzc2luZyBzaG91bGQgYmUgc2lsZW50bHlcbiAgLy8gaWdub3JlZCBzaW5jZSB0aGUgbnBtL3lhcm4gd2lsbCBub3QgZmFpbCBpZiB0aGVzZSBkZXBlbmRlbmNpZXNcbiAgLy8gZmFpbCB0byBpbnN0YWxsLiBQYWNrYWdlcyBzaG91bGQgaGFuZGxlIHRoZSBjYXNlcyB3aGVyZSB0aGVzZVxuICAvLyBkZXBlbmRlbmNpZXMgYXJlIG1pc3NpbmcgZ3JhY2VmdWxseSBhdCBydW50aW1lLlxuICAvLyBBbiBleGFtcGxlIG9mIHRoaXMgaXMgdGhlIGBjaG9raWRhcmAgcGFja2FnZSB3aGljaCBzcGVjaWZpZXNcbiAgLy8gYGZzZXZlbnRzYCBhcyBhbiBvcHRpb25hbERlcGVuZGVuY3kuIE9uIE9TWCwgYGZzZXZlbnRzYFxuICAvLyBpcyBpbnN0YWxsZWQgc3VjY2Vzc2Z1bGx5LCBidXQgb24gV2luZG93cyAmIExpbnV4LCBgZnNldmVudHNgXG4gIC8vIGZhaWxzIHRvIGluc3RhbGwgYW5kIHRoZSBwYWNrYWdlIHdpbGwgbm90IGJlIHByZXNlbnQgd2hlblxuICAvLyBjaGVja2luZyB0aGUgZGVwZW5kZW5jaWVzIG9mIGBjaG9raWRhcmAuXG4gIGZpbmREZXBzKGRlcC5vcHRpb25hbERlcGVuZGVuY2llcywgZmFsc2UsICdvcHRpb25hbCBkZXBlbmRlbmN5Jyk7XG59XG5cbi8qKlxuICogUmVmb3JtYXQvcHJldHR5LXByaW50IGEganNvbiBvYmplY3QgYXMgYSBza3lsYXJrIGNvbW1lbnQgKGVhY2ggbGluZVxuICogc3RhcnRzIHdpdGggJyMgJykuXG4gKi9cbmZ1bmN0aW9uIHByaW50SnNvbihwa2c6IERlcCkge1xuICAvLyBDbG9uZSBhbmQgbW9kaWZ5IF9kZXBlbmRlbmNpZXMgdG8gYXZvaWQgY2lyY3VsYXIgaXNzdWVzIHdoZW4gSlNPTmlmeWluZ1xuICAvLyAmIGRlbGV0ZSBfZmlsZXMgYXJyYXlcbiAgY29uc3QgY2xvbmVkOiBhbnkgPSB7Li4ucGtnfTtcbiAgY2xvbmVkLl9kZXBlbmRlbmNpZXMgPSBwa2cuX2RlcGVuZGVuY2llcy5tYXAoZGVwID0+IGRlcC5fZGlyKTtcbiAgZGVsZXRlIGNsb25lZC5fZmlsZXM7XG4gIHJldHVybiBKU09OLnN0cmluZ2lmeShjbG9uZWQsIG51bGwsIDIpLnNwbGl0KCdcXG4nKS5tYXAobGluZSA9PiBgIyAke2xpbmV9YCkuam9pbignXFxuJyk7XG59XG5cbi8qKlxuICogQSBmaWx0ZXIgZnVuY3Rpb24gZm9yIGZpbGVzIGluIGFuIG5wbSBwYWNrYWdlLiBDb21wYXJpc29uIGlzIGNhc2UtaW5zZW5zaXRpdmUuXG4gKiBAcGFyYW0gZmlsZXMgYXJyYXkgb2YgZmlsZXMgdG8gZmlsdGVyXG4gKiBAcGFyYW0gZXh0cyBsaXN0IG9mIHdoaXRlIGxpc3RlZCBjYXNlLWluc2Vuc2l0aXZlIGV4dGVuc2lvbnM7IGlmIGVtcHR5LCBubyBmaWx0ZXIgaXNcbiAqICAgICAgICAgICAgIGRvbmUgb24gZXh0ZW5zaW9uczsgJycgZW1wdHkgc3RyaW5nIGRlbm90ZXMgdG8gYWxsb3cgZmlsZXMgd2l0aCBubyBleHRlbnNpb25zLFxuICogICAgICAgICAgICAgb3RoZXIgZXh0ZW5zaW9ucyBhcmUgbGlzdGVkIHdpdGggJy5leHQnIG5vdGF0aW9uIHN1Y2ggYXMgJy5kLnRzJy5cbiAqL1xuZnVuY3Rpb24gZmlsdGVyRmlsZXMoZmlsZXM6IHN0cmluZ1tdLCBleHRzOiBzdHJpbmdbXSA9IFtdKSB7XG4gIGlmIChleHRzLmxlbmd0aCkge1xuICAgIGNvbnN0IGFsbG93Tm9FeHRzID0gZXh0cy5pbmNsdWRlcygnJyk7XG4gICAgZmlsZXMgPSBmaWxlcy5maWx0ZXIoZiA9PiB7XG4gICAgICAvLyBpbmNsdWRlIGZpbGVzIHdpdGggbm8gZXh0ZW5zaW9ucyBpZiBub0V4dCBpcyB0cnVlXG4gICAgICBpZiAoYWxsb3dOb0V4dHMgJiYgIXBhdGguZXh0bmFtZShmKSkgcmV0dXJuIHRydWU7XG4gICAgICAvLyBmaWx0ZXIgZmlsZXMgaW4gZXh0c1xuICAgICAgY29uc3QgbGMgPSBmLnRvTG93ZXJDYXNlKCk7XG4gICAgICBmb3IgKGNvbnN0IGUgb2YgZXh0cykge1xuICAgICAgICBpZiAoZSAmJiBsYy5lbmRzV2l0aChlLnRvTG93ZXJDYXNlKCkpKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9KVxuICB9XG4gIC8vIEZpbHRlciBvdXQgQlVJTEQgZmlsZXMgdGhhdCBjYW1lIHdpdGggdGhlIG5wbSBwYWNrYWdlXG4gIHJldHVybiBmaWxlcy5maWx0ZXIoZmlsZSA9PiB7XG4gICAgY29uc3QgYmFzZW5hbWVVYyA9IHBhdGguYmFzZW5hbWUoZmlsZSkudG9VcHBlckNhc2UoKTtcbiAgICBpZiAoYmFzZW5hbWVVYyA9PT0gJ19CVUlMRCcgfHwgYmFzZW5hbWVVYyA9PT0gJ19CVUlMRC5CQVpFTCcpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIGBwa2dgIGNvbmZvcm1zIHRvIEFuZ3VsYXIgUGFja2FnZSBGb3JtYXQgKEFQRiksXG4gKiBmYWxzZSBvdGhlcndpc2UuIElmIHRoZSBwYWNrYWdlIGNvbnRhaW5zIGAqLm1ldGFkYXRhLmpzb25gIGFuZCBhXG4gKiBjb3JyZXNwb25kaW5nIHNpYmxpbmcgYC5kLnRzYCBmaWxlLCB0aGVuIHRoZSBwYWNrYWdlIGlzIGNvbnNpZGVyZWQgdG8gYmUgQVBGLlxuICovXG5mdW5jdGlvbiBpc05nQXBmUGFja2FnZShwa2c6IERlcCkge1xuICBjb25zdCBzZXQgPSBuZXcgU2V0KHBrZy5fZmlsZXMpO1xuICBpZiAoc2V0LmhhcygnQU5HVUxBUl9QQUNLQUdFJykpIHtcbiAgICAvLyBUaGlzIGZpbGUgaXMgdXNlZCBieSB0aGUgbnBtL3lhcm5faW5zdGFsbCBydWxlIHRvIGRldGVjdCBBUEYuIFNlZVxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9iYXplbGJ1aWxkL3J1bGVzX25vZGVqcy9pc3N1ZXMvOTI3XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgY29uc3QgbWV0YWRhdGFFeHQgPSAvXFwubWV0YWRhdGFcXC5qc29uJC87XG4gIHJldHVybiBwa2cuX2ZpbGVzLnNvbWUoKGZpbGUpID0+IHtcbiAgICBpZiAobWV0YWRhdGFFeHQudGVzdChmaWxlKSkge1xuICAgICAgY29uc3Qgc2libGluZyA9IGZpbGUucmVwbGFjZShtZXRhZGF0YUV4dCwgJy5kLnRzJyk7XG4gICAgICBpZiAoc2V0LmhhcyhzaWJsaW5nKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9KTtcbn1cblxuLyoqXG4gKiBJZiB0aGUgcGFja2FnZSBpcyBpbiB0aGUgQW5ndWxhciBwYWNrYWdlIGZvcm1hdCByZXR1cm5zIGxpc3RcbiAqIG9mIHBhY2thZ2UgZmlsZXMgdGhhdCBlbmQgd2l0aCBgLnVtZC5qc2AsIGAubmdmYWN0b3J5LmpzYCBhbmQgYC5uZ3N1bW1hcnkuanNgLlxuICovXG5mdW5jdGlvbiBnZXROZ0FwZlNjcmlwdHMocGtnOiBEZXApIHtcbiAgcmV0dXJuIGlzTmdBcGZQYWNrYWdlKHBrZykgP1xuICAgICAgZmlsdGVyRmlsZXMocGtnLl9maWxlcywgWycudW1kLmpzJywgJy5uZ2ZhY3RvcnkuanMnLCAnLm5nc3VtbWFyeS5qcyddKSA6XG4gICAgICBbXTtcbn1cblxuLyoqXG4gKiBMb29rcyBmb3IgYSBmaWxlIHdpdGhpbiBhIHBhY2thZ2UgYW5kIHJldHVybnMgaXQgaWYgZm91bmQuXG4gKi9cbmZ1bmN0aW9uIGZpbmRGaWxlKHBrZzogRGVwLCBtOiBzdHJpbmcpIHtcbiAgY29uc3QgbWwgPSBtLnRvTG93ZXJDYXNlKCk7XG4gIGZvciAoY29uc3QgZiBvZiBwa2cuX2ZpbGVzKSB7XG4gICAgaWYgKGYudG9Mb3dlckNhc2UoKSA9PT0gbWwpIHtcbiAgICAgIHJldHVybiBmO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIEdpdmVuIGEgcGtnLCByZXR1cm4gdGhlIHNreWxhcmsgYG5vZGVfbW9kdWxlX2xpYnJhcnlgIHRhcmdldHMgZm9yIHRoZSBwYWNrYWdlLlxuICovXG5mdW5jdGlvbiBwcmludFBhY2thZ2UocGtnOiBEZXApIHtcbiAgY29uc3Qgc291cmNlcyA9IGZpbHRlckZpbGVzKHBrZy5fZmlsZXMsIElOQ0xVREVEX0ZJTEVTKTtcbiAgY29uc3QgZHRzU291cmNlcyA9IGZpbHRlckZpbGVzKHBrZy5fZmlsZXMsIFsnLmQudHMnXSk7XG4gIC8vIFRPRE8oZ21hZ29sYW4pOiBhZGQgVU1EICYgQU1EIHNjcmlwdHMgdG8gc2NyaXB0cyBldmVuIGlmIG5vdCBhbiBBUEYgcGFja2FnZSBfYnV0XyBvbmx5IGlmIHRoZXlcbiAgLy8gYXJlIG5hbWVkP1xuICBjb25zdCBuYW1lZFNvdXJjZXMgPSBnZXROZ0FwZlNjcmlwdHMocGtnKTtcbiAgY29uc3QgZGVwcyA9IFtwa2ddLmNvbmNhdChwa2cuX2RlcGVuZGVuY2llcy5maWx0ZXIoZGVwID0+IGRlcCAhPT0gcGtnICYmICFkZXAuX2lzTmVzdGVkKSk7XG5cbiAgbGV0IG5hbWVkU291cmNlc1N0YXJsYXJrID0gJyc7XG4gIGlmIChuYW1lZFNvdXJjZXMubGVuZ3RoKSB7XG4gICAgbmFtZWRTb3VyY2VzU3RhcmxhcmsgPSBgXG4gICAgIyBzdWJzZXQgb2Ygc3JjcyB0aGF0IGFyZSBqYXZhc2NyaXB0IG5hbWVkLVVNRCBvciBuYW1lZC1BTUQgc2NyaXB0c1xuICAgIG5hbWVkX3NvdXJjZXMgPSBbXG4gICAgICAgICR7bmFtZWRTb3VyY2VzLm1hcCgoZjogc3RyaW5nKSA9PiBgXCIvLzpub2RlX21vZHVsZXMvJHtwa2cuX2Rpcn0vJHtmfVwiLGApLmpvaW4oJ1xcbiAgICAgICAgJyl9XG4gICAgXSxgO1xuICB9XG5cbiAgbGV0IHNyY3NTdGFybGFyayA9ICcnO1xuICBpZiAoc291cmNlcy5sZW5ndGgpIHtcbiAgICBzcmNzU3RhcmxhcmsgPSBgXG4gICAgIyAke3BrZy5fZGlyfSBwYWNrYWdlIGZpbGVzIChhbmQgZmlsZXMgaW4gbmVzdGVkIG5vZGVfbW9kdWxlcylcbiAgICBzcmNzID0gW1xuICAgICAgICAke3NvdXJjZXMubWFwKChmOiBzdHJpbmcpID0+IGBcIi8vOm5vZGVfbW9kdWxlcy8ke3BrZy5fZGlyfS8ke2Z9XCIsYCkuam9pbignXFxuICAgICAgICAnKX1cbiAgICBdLGA7XG4gIH1cblxuICBsZXQgZGVwc1N0YXJsYXJrID0gJyc7XG4gIGlmIChkZXBzLmxlbmd0aCkge1xuICAgIGNvbnN0IGxpc3QgPSBkZXBzLm1hcChkZXAgPT4gYFwiLy8ke2RlcC5fZGlyfToke2RlcC5fbmFtZX1fX2NvbnRlbnRzXCIsYCkuam9pbignXFxuICAgICAgICAnKTtcbiAgICBkZXBzU3RhcmxhcmsgPSBgXG4gICAgIyBmbGF0dGVuZWQgbGlzdCBvZiBkaXJlY3QgYW5kIHRyYW5zaXRpdmUgZGVwZW5kZW5jaWVzIGhvaXN0ZWQgdG8gcm9vdCBieSB0aGUgcGFja2FnZSBtYW5hZ2VyXG4gICAgZGVwcyA9IFtcbiAgICAgICAgJHtsaXN0fVxuICAgIF0sYDtcbiAgfVxuXG4gIGxldCBkdHNTdGFybGFyayA9ICcnO1xuICBpZiAoZHRzU291cmNlcy5sZW5ndGgpIHtcbiAgICBkdHNTdGFybGFyayA9IGBcbiAgICAjICR7cGtnLl9kaXJ9IHBhY2thZ2UgZGVjbGFyYXRpb24gZmlsZXMgKGFuZCBkZWNsYXJhdGlvbiBmaWxlcyBpbiBuZXN0ZWQgbm9kZV9tb2R1bGVzKVxuICAgIHNyY3MgPSBbXG4gICAgICAgICR7ZHRzU291cmNlcy5tYXAoZiA9PiBgXCIvLzpub2RlX21vZHVsZXMvJHtwa2cuX2Rpcn0vJHtmfVwiLGApLmpvaW4oJ1xcbiAgICAgICAgJyl9XG4gICAgXSxgO1xuICB9XG5cbiAgbGV0IHJlc3VsdCA9XG4gICAgICBgbG9hZChcIkBidWlsZF9iYXplbF9ydWxlc19ub2RlanMvL2ludGVybmFsL25wbV9pbnN0YWxsOm5vZGVfbW9kdWxlX2xpYnJhcnkuYnpsXCIsIFwibm9kZV9tb2R1bGVfbGlicmFyeVwiKVxuXG4jIEdlbmVyYXRlZCB0YXJnZXRzIGZvciBucG0gcGFja2FnZSBcIiR7cGtnLl9kaXJ9XCJcbiR7cHJpbnRKc29uKHBrZyl9XG5cbmZpbGVncm91cChcbiAgICBuYW1lID0gXCIke3BrZy5fbmFtZX1fX2ZpbGVzXCIsJHtzcmNzU3Rhcmxhcmt9XG4pXG5cbm5vZGVfbW9kdWxlX2xpYnJhcnkoXG4gICAgbmFtZSA9IFwiJHtwa2cuX25hbWV9XCIsXG4gICAgIyBkaXJlY3Qgc291cmNlcyBsaXN0ZWQgZm9yIHN0cmljdCBkZXBzIHN1cHBvcnRcbiAgICBzcmNzID0gW1wiOiR7cGtnLl9uYW1lfV9fZmlsZXNcIl0sJHtkZXBzU3Rhcmxhcmt9XG4pXG5cbiMgJHtwa2cuX25hbWV9X19jb250ZW50cyB0YXJnZXQgaXMgdXNlZCBhcyBkZXAgZm9yIG1haW4gdGFyZ2V0cyB0byBwcmV2ZW50XG4jIGNpcmN1bGFyIGRlcGVuZGVuY2llcyBlcnJvcnNcbm5vZGVfbW9kdWxlX2xpYnJhcnkoXG4gICAgbmFtZSA9IFwiJHtwa2cuX25hbWV9X19jb250ZW50c1wiLFxuICAgIHNyY3MgPSBbXCI6JHtwa2cuX25hbWV9X19maWxlc1wiXSwke25hbWVkU291cmNlc1N0YXJsYXJrfVxuKVxuXG4jICR7cGtnLl9uYW1lfV9fdHlwaW5ncyBpcyB0aGUgc3Vic2V0IG9mICR7cGtnLl9uYW1lfV9fY29udGVudHMgdGhhdCBhcmUgZGVjbGFyYXRpb25zXG5ub2RlX21vZHVsZV9saWJyYXJ5KFxuICAgIG5hbWUgPSBcIiR7cGtnLl9uYW1lfV9fdHlwaW5nc1wiLCR7ZHRzU3Rhcmxhcmt9XG4pXG5cbmA7XG5cbiAgbGV0IG1haW5FbnRyeVBvaW50ID0gcmVzb2x2ZVBrZ01haW5GaWxlKHBrZylcblxuICAvLyBhZGQgYW4gYG5wbV91bWRfYnVuZGxlYCB0YXJnZXQgdG8gZ2VuZXJhdGUgYW4gVU1EIGJ1bmRsZSBpZiBvbmUgZG9lc1xuICAvLyBub3QgZXhpc3RzXG4gIGlmIChtYWluRW50cnlQb2ludCAmJiAhZmluZEZpbGUocGtnLCBgJHtwa2cuX25hbWV9LnVtZC5qc2ApKSB7XG4gICAgcmVzdWx0ICs9XG4gICAgICAgIGBsb2FkKFwiQGJ1aWxkX2JhemVsX3J1bGVzX25vZGVqcy8vaW50ZXJuYWwvbnBtX2luc3RhbGw6bnBtX3VtZF9idW5kbGUuYnpsXCIsIFwibnBtX3VtZF9idW5kbGVcIilcblxubnBtX3VtZF9idW5kbGUoXG4gICAgbmFtZSA9IFwiJHtwa2cuX25hbWV9X191bWRcIixcbiAgICBwYWNrYWdlX25hbWUgPSBcIiR7cGtnLl9uYW1lfVwiLFxuICAgIGVudHJ5X3BvaW50ID0gXCIvLzpub2RlX21vZHVsZXMvJHtwa2cuX2Rpcn0vJHttYWluRW50cnlQb2ludH1cIixcbiAgICBwYWNrYWdlID0gXCI6JHtwa2cuX25hbWV9XCIsXG4pXG5cbmA7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBfZmluZEV4ZWN1dGFibGVzKHBrZzogRGVwKSB7XG4gIGNvbnN0IGV4ZWN1dGFibGVzID0gbmV3IE1hcCgpO1xuXG4gIC8vIEZvciByb290IHBhY2thZ2VzLCB0cmFuc2Zvcm0gdGhlIHBrZy5iaW4gZW50cmllc1xuICAvLyBpbnRvIGEgbmV3IE1hcCBjYWxsZWQgX2V4ZWN1dGFibGVzXG4gIC8vIE5PVEU6IHdlIGRvIHRoaXMgb25seSBmb3Igbm9uLWVtcHR5IGJpbiBwYXRoc1xuICBpZiAoaXNWYWxpZEJpblBhdGgocGtnLmJpbikpIHtcbiAgICBpZiAoIXBrZy5faXNOZXN0ZWQpIHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KHBrZy5iaW4pKSB7XG4gICAgICAgIGlmIChwa2cuYmluLmxlbmd0aCA9PSAxKSB7XG4gICAgICAgICAgZXhlY3V0YWJsZXMuc2V0KHBrZy5fZGlyLCBjbGVhbnVwQmluUGF0aChwa2cuYmluWzBdKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gc2hvdWxkIG5vdCBoYXBwZW4sIGJ1dCBpZ25vcmUgaXQgaWYgcHJlc2VudFxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwa2cuYmluID09PSAnc3RyaW5nJykge1xuICAgICAgICBleGVjdXRhYmxlcy5zZXQocGtnLl9kaXIsIGNsZWFudXBCaW5QYXRoKHBrZy5iaW4pKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHBrZy5iaW4gPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGZvciAobGV0IGtleSBpbiBwa2cuYmluKSB7XG4gICAgICAgICAgaWYgKGlzVmFsaWRCaW5QYXRoU3RyaW5nVmFsdWUocGtnLmJpbltrZXldKSkge1xuICAgICAgICAgICAgZXhlY3V0YWJsZXMuc2V0KGtleSwgY2xlYW51cEJpblBhdGgocGtnLmJpbltrZXldKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGV4ZWN1dGFibGVzO1xufVxuXG4vLyBIYW5kbGUgYWRkaXRpb25hbEF0dHJpYnV0ZXMgb2YgZm9ybWF0OlxuLy8gYGBgXG4vLyBcImJhemVsQmluXCI6IHtcbi8vICAgXCJuZ2Mtd3JhcHBlZFwiOiB7XG4vLyAgICAgXCJhZGRpdGlvbmFsQXR0cmlidXRlc1wiOiB7XG4vLyAgICAgICBcImNvbmZpZ3VyYXRpb25fZW52X3ZhcnNcIjogXCJbXFxcImNvbXBpbGVcXFwiXVwiXG4vLyAgIH1cbi8vIH0sXG4vLyBgYGBcbmZ1bmN0aW9uIGFkZGl0aW9uYWxBdHRyaWJ1dGVzKHBrZzogRGVwLCBuYW1lOiBzdHJpbmcpIHtcbiAgbGV0IGFkZGl0aW9uYWxBdHRyaWJ1dGVzID0gJyc7XG4gIGlmIChwa2cuYmF6ZWxCaW4gJiYgcGtnLmJhemVsQmluW25hbWVdICYmIHBrZy5iYXplbEJpbltuYW1lXS5hZGRpdGlvbmFsQXR0cmlidXRlcykge1xuICAgIGNvbnN0IGF0dHJzID0gcGtnLmJhemVsQmluW25hbWVdLmFkZGl0aW9uYWxBdHRyaWJ1dGVzO1xuICAgIGZvciAoY29uc3QgYXR0ck5hbWUgb2YgT2JqZWN0LmtleXMoYXR0cnMpKSB7XG4gICAgICBjb25zdCBhdHRyVmFsdWUgPSBhdHRyc1thdHRyTmFtZV07XG4gICAgICBhZGRpdGlvbmFsQXR0cmlidXRlcyArPSBgXFxuICAgICR7YXR0ck5hbWV9ID0gJHthdHRyVmFsdWV9LGA7XG4gICAgfVxuICB9XG4gIHJldHVybiBhZGRpdGlvbmFsQXR0cmlidXRlcztcbn1cblxuLyoqXG4gKiBHaXZlbiBhIHBrZywgcmV0dXJuIHRoZSBza3lsYXJrIG5vZGVqc19iaW5hcnkgdGFyZ2V0cyBmb3IgdGhlIHBhY2thZ2UuXG4gKi9cbmZ1bmN0aW9uIHByaW50UGFja2FnZUJpbihwa2c6IERlcCkge1xuICBsZXQgcmVzdWx0ID0gJyc7XG4gIGNvbnN0IGV4ZWN1dGFibGVzID0gX2ZpbmRFeGVjdXRhYmxlcyhwa2cpO1xuICBpZiAoZXhlY3V0YWJsZXMuc2l6ZSkge1xuICAgIHJlc3VsdCA9IGBsb2FkKFwiQGJ1aWxkX2JhemVsX3J1bGVzX25vZGVqcy8vOmluZGV4LmJ6bFwiLCBcIm5vZGVqc19iaW5hcnlcIilcblxuYDtcbiAgICBjb25zdCBkYXRhID0gW2AvLyR7cGtnLl9kaXJ9OiR7cGtnLl9uYW1lfWBdO1xuICAgIGlmIChwa2cuX2R5bmFtaWNEZXBlbmRlbmNpZXMpIHtcbiAgICAgIGRhdGEucHVzaCguLi5wa2cuX2R5bmFtaWNEZXBlbmRlbmNpZXMpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgW25hbWUsIHBhdGhdIG9mIGV4ZWN1dGFibGVzLmVudHJpZXMoKSkge1xuICAgICAgcmVzdWx0ICs9IGAjIFdpcmUgdXAgdGhlIFxcYGJpblxcYCBlbnRyeSBcXGAke25hbWV9XFxgXG5ub2RlanNfYmluYXJ5KFxuICAgIG5hbWUgPSBcIiR7bmFtZX1cIixcbiAgICBlbnRyeV9wb2ludCA9IFwiLy86bm9kZV9tb2R1bGVzLyR7cGtnLl9kaXJ9LyR7cGF0aH1cIixcbiAgICBpbnN0YWxsX3NvdXJjZV9tYXBfc3VwcG9ydCA9IEZhbHNlLFxuICAgIGRhdGEgPSBbJHtkYXRhLm1hcChwID0+IGBcIiR7cH1cImApLmpvaW4oJywgJyl9XSwke2FkZGl0aW9uYWxBdHRyaWJ1dGVzKHBrZywgbmFtZSl9XG4pXG5cbmA7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gcHJpbnRJbmRleEJ6bChwa2c6IERlcCkge1xuICBsZXQgcmVzdWx0ID0gJyc7XG4gIGNvbnN0IGV4ZWN1dGFibGVzID0gX2ZpbmRFeGVjdXRhYmxlcyhwa2cpO1xuICBpZiAoZXhlY3V0YWJsZXMuc2l6ZSkge1xuICAgIHJlc3VsdCA9IGBsb2FkKFwiQGJ1aWxkX2JhemVsX3J1bGVzX25vZGVqcy8vOmluZGV4LmJ6bFwiLCBcIm5vZGVqc19iaW5hcnlcIiwgXCJucG1fcGFja2FnZV9iaW5cIilcblxuYDtcbiAgICBjb25zdCBkYXRhID0gW2BAJHtXT1JLU1BBQ0V9Ly8ke3BrZy5fZGlyfToke3BrZy5fbmFtZX1gXTtcbiAgICBpZiAocGtnLl9keW5hbWljRGVwZW5kZW5jaWVzKSB7XG4gICAgICBkYXRhLnB1c2goLi4ucGtnLl9keW5hbWljRGVwZW5kZW5jaWVzKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IFtuYW1lLCBwYXRoXSBvZiBleGVjdXRhYmxlcy5lbnRyaWVzKCkpIHtcbiAgICAgIHJlc3VsdCA9IGAke3Jlc3VsdH1cblxuIyBHZW5lcmF0ZWQgaGVscGVyIG1hY3JvIHRvIGNhbGwgJHtuYW1lfVxuZGVmICR7bmFtZS5yZXBsYWNlKC8tL2csICdfJyl9KCoqa3dhcmdzKTpcbiAgICBvdXRwdXRfZGlyID0ga3dhcmdzLnBvcChcIm91dHB1dF9kaXJcIiwgRmFsc2UpXG4gICAgaWYgXCJvdXRzXCIgaW4ga3dhcmdzIG9yIG91dHB1dF9kaXI6XG4gICAgICAgIG5wbV9wYWNrYWdlX2Jpbih0b29sID0gXCJAJHtXT1JLU1BBQ0V9Ly8ke3BrZy5fZGlyfS9iaW46JHtcbiAgICAgICAgICBuYW1lfVwiLCBvdXRwdXRfZGlyID0gb3V0cHV0X2RpciwgKiprd2FyZ3MpXG4gICAgZWxzZTpcbiAgICAgICAgbm9kZWpzX2JpbmFyeShcbiAgICAgICAgICAgIGVudHJ5X3BvaW50ID0gXCJAJHtXT1JLU1BBQ0V9Ly86bm9kZV9tb2R1bGVzLyR7cGtnLl9kaXJ9LyR7cGF0aH1cIixcbiAgICAgICAgICAgIGluc3RhbGxfc291cmNlX21hcF9zdXBwb3J0ID0gRmFsc2UsXG4gICAgICAgICAgICBkYXRhID0gWyR7ZGF0YS5tYXAocCA9PiBgXCIke3B9XCJgKS5qb2luKCcsICcpfV0gKyBrd2FyZ3MucG9wKFwiZGF0YVwiLCBbXSksJHtcbiAgICAgICAgICBhZGRpdGlvbmFsQXR0cmlidXRlcyhwa2csIG5hbWUpfVxuICAgICAgICAgICAgKiprd2FyZ3NcbiAgICAgICAgKVxuICBgO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG50eXBlIERlcCA9IHtcbiAgX2Rpcjogc3RyaW5nLFxuICBfaXNOZXN0ZWQ6IGJvb2xlYW4sXG4gIF9kZXBlbmRlbmNpZXM6IERlcFtdLFxuICBfZmlsZXM6IHN0cmluZ1tdLFxuICBbazogc3RyaW5nXTogYW55XG59XG5cbi8qKlxuICogR2l2ZW4gYSBzY29wZSwgcmV0dXJuIHRoZSBza3lsYXJrIGBub2RlX21vZHVsZV9saWJyYXJ5YCB0YXJnZXQgZm9yIHRoZSBzY29wZS5cbiAqL1xuZnVuY3Rpb24gcHJpbnRTY29wZShzY29wZTogc3RyaW5nLCBwa2dzOiBEZXBbXSkge1xuICBwa2dzID0gcGtncy5maWx0ZXIocGtnID0+ICFwa2cuX2lzTmVzdGVkICYmIHBrZy5fZGlyLnN0YXJ0c1dpdGgoYCR7c2NvcGV9L2ApKTtcbiAgbGV0IGRlcHM6IERlcFtdID0gW107XG4gIHBrZ3MuZm9yRWFjaChwa2cgPT4ge1xuICAgIGRlcHMgPSBkZXBzLmNvbmNhdChwa2cuX2RlcGVuZGVuY2llcy5maWx0ZXIoZGVwID0+ICFkZXAuX2lzTmVzdGVkICYmICFwa2dzLmluY2x1ZGVzKHBrZykpKTtcbiAgfSk7XG4gIC8vIGZpbHRlciBvdXQgZHVwbGljYXRlIGRlcHNcbiAgZGVwcyA9IFsuLi5wa2dzLCAuLi5uZXcgU2V0KGRlcHMpXTtcblxuICBsZXQgc3Jjc1N0YXJsYXJrID0gJyc7XG4gIGlmIChkZXBzLmxlbmd0aCkge1xuICAgIGNvbnN0IGxpc3QgPSBkZXBzLm1hcChkZXAgPT4gYFwiLy8ke2RlcC5fZGlyfToke2RlcC5fbmFtZX1fX2ZpbGVzXCIsYCkuam9pbignXFxuICAgICAgICAnKTtcbiAgICBzcmNzU3RhcmxhcmsgPSBgXG4gICAgIyBkaXJlY3Qgc291cmNlcyBsaXN0ZWQgZm9yIHN0cmljdCBkZXBzIHN1cHBvcnRcbiAgICBzcmNzID0gW1xuICAgICAgICAke2xpc3R9XG4gICAgXSxgO1xuICB9XG5cbiAgbGV0IGRlcHNTdGFybGFyayA9ICcnO1xuICBpZiAoZGVwcy5sZW5ndGgpIHtcbiAgICBjb25zdCBsaXN0ID0gZGVwcy5tYXAoZGVwID0+IGBcIi8vJHtkZXAuX2Rpcn06JHtkZXAuX25hbWV9X19jb250ZW50c1wiLGApLmpvaW4oJ1xcbiAgICAgICAgJyk7XG4gICAgZGVwc1N0YXJsYXJrID0gYFxuICAgICMgZmxhdHRlbmVkIGxpc3Qgb2YgZGlyZWN0IGFuZCB0cmFuc2l0aXZlIGRlcGVuZGVuY2llcyBob2lzdGVkIHRvIHJvb3QgYnkgdGhlIHBhY2thZ2UgbWFuYWdlclxuICAgIGRlcHMgPSBbXG4gICAgICAgICR7bGlzdH1cbiAgICBdLGA7XG4gIH1cblxuICByZXR1cm4gYGxvYWQoXCJAYnVpbGRfYmF6ZWxfcnVsZXNfbm9kZWpzLy9pbnRlcm5hbC9ucG1faW5zdGFsbDpub2RlX21vZHVsZV9saWJyYXJ5LmJ6bFwiLCBcIm5vZGVfbW9kdWxlX2xpYnJhcnlcIilcblxuIyBHZW5lcmF0ZWQgdGFyZ2V0IGZvciBucG0gc2NvcGUgJHtzY29wZX1cbm5vZGVfbW9kdWxlX2xpYnJhcnkoXG4gICAgbmFtZSA9IFwiJHtzY29wZX1cIiwke3NyY3NTdGFybGFya30ke2RlcHNTdGFybGFya31cbilcblxuYDtcbn1cbiJdfQ== \ No newline at end of file diff --git a/internal/npm_install/generate_build_file.ts b/internal/npm_install/generate_build_file.ts index 96fa4d3023..d39599a44a 100644 --- a/internal/npm_install/generate_build_file.ts +++ b/internal/npm_install/generate_build_file.ts @@ -888,15 +888,15 @@ function printPackage(pkg: Dep) { const dtsSources = filterFiles(pkg._files, ['.d.ts']); // TODO(gmagolan): add UMD & AMD scripts to scripts even if not an APF package _but_ only if they // are named? - const scripts = getNgApfScripts(pkg); + const namedSources = getNgApfScripts(pkg); const deps = [pkg].concat(pkg._dependencies.filter(dep => dep !== pkg && !dep._isNested)); - let scriptStarlark = ''; - if (scripts.length) { - scriptStarlark = ` + let namedSourcesStarlark = ''; + if (namedSources.length) { + namedSourcesStarlark = ` # subset of srcs that are javascript named-UMD or named-AMD scripts - scripts = [ - ${scripts.map((f: string) => `"//:node_modules/${pkg._dir}/${f}",`).join('\n ')} + named_sources = [ + ${namedSources.map((f: string) => `"//:node_modules/${pkg._dir}/${f}",`).join('\n ')} ],`; } @@ -948,7 +948,7 @@ node_module_library( # circular dependencies errors node_module_library( name = "${pkg._name}__contents", - srcs = [":${pkg._name}__files"],${scriptStarlark} + srcs = [":${pkg._name}__files"],${namedSourcesStarlark} ) # ${pkg._name}__typings is the subset of ${pkg._name}__contents that are declarations diff --git a/internal/npm_install/node_module_library.bzl b/internal/npm_install/node_module_library.bzl index 913fc73f29..bd802f6223 100644 --- a/internal/npm_install/node_module_library.bzl +++ b/internal/npm_install/node_module_library.bzl @@ -15,19 +15,15 @@ """Contains the node_module_library which is used by yarn_install & npm_install. """ -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "NodeModuleSources") +load("@build_bazel_rules_nodejs//:declaration_provider.bzl", "DeclarationInfo") +load("@build_bazel_rules_nodejs//:providers.bzl", "transitive_js_named_module_info") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo") def _node_module_library_impl(ctx): workspace = ctx.label.workspace_root.split("/")[1] if ctx.label.workspace_root else ctx.workspace_name - # All files in `srcs` and in `deps` - # TODO(gregmagolan): transitive sources should be collected an aspect to go - # into a NodeModuleSources.transitive_sources - sources = depset(ctx.files.srcs, transitive = [dep.files for dep in ctx.attr.deps]) - - # scripts are a subset of sources that are javascript named-UMD or named-AMD scripts for - # use in rules such as ts_devserver - scripts = depset(ctx.files.scripts) + # sources are all files in srcs plus those in direct & transitive dependencies + sources = depset(ctx.files.srcs) # declarations are a subset of sources that are declaration files declarations = depset([ @@ -42,11 +38,13 @@ def _node_module_library_impl(ctx): ]) # transitive_declarations are all .d.ts files in srcs plus those in direct & transitive dependencies - transitive_declarations = depset(transitive = [declarations]) + transitive_declarations = declarations for dep in ctx.attr.deps: - if hasattr(dep, "typescript"): - transitive_declarations = depset(transitive = [transitive_declarations, dep.typescript.transitive_declarations]) + if DeclarationInfo in dep: + transitive_declarations = depset(transitive = [transitive_declarations, dep[DeclarationInfo].transitive_declarations]) + if NodeModuleInfo in dep: + sources = depset(transitive = [sources, dep[NodeModuleInfo].sources]) return struct( typescript = struct( @@ -66,13 +64,17 @@ def _node_module_library_impl(ctx): files = sources, ), NodeModuleInfo( - workspace = workspace, - ), - NodeModuleSources( sources = sources, - scripts = scripts, workspace = workspace, ), + DeclarationInfo( + declarations = declarations, + transitive_declarations = transitive_declarations, + ), + transitive_js_named_module_info( + sources = depset(ctx.files.named_sources), + deps = ctx.attr.deps, + ), ], ) @@ -83,8 +85,8 @@ node_module_library = rule( doc = "The list of files that comprise the package", allow_files = True, ), - "scripts": attr.label_list( - doc = "A subset of srcs that are javascript named-UMD or named-AMD scripts for use in rules such as ts_devserver", + "named_sources": attr.label_list( + doc = "A subset of srcs that are javascript named-UMD or named-AMD for use in rules such as ts_devserver", allow_files = True, ), "deps": attr.label_list( diff --git a/internal/npm_install/npm_umd_bundle.bzl b/internal/npm_install/npm_umd_bundle.bzl index a62c7129bb..1ef82007c4 100644 --- a/internal/npm_install/npm_umd_bundle.bzl +++ b/internal/npm_install/npm_umd_bundle.bzl @@ -17,7 +17,7 @@ For use by yarn_install and npm_install. Not meant to be part of the public API. """ -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "node_modules_aspect") def _npm_umd_bundle(ctx): if len(ctx.attr.entry_point.files.to_list()) != 1: @@ -33,7 +33,7 @@ def _npm_umd_bundle(ctx): args.add(output.path) args.add_joined(ctx.attr.excluded, join_with = ",") - sources = ctx.attr.package[NodeModuleSources].sources.to_list() + sources = ctx.attr.package[NodeModuleInfo].sources.to_list() # Only pass .js and package.json files as inputs to browserify. # The latter is required for module resolution in some cases. @@ -91,7 +91,7 @@ This target would be then be used instead of the generated `@npm//typeorm:typeor "package": attr.label( doc = """The npm package target""", mandatory = True, - aspects = [collect_node_modules_aspect], + aspects = [node_modules_aspect], ), "_browserify_wrapped": attr.label( executable = True, diff --git a/internal/npm_install/test/golden/@angular/core/BUILD.bazel.golden b/internal/npm_install/test/golden/@angular/core/BUILD.bazel.golden index 336aa504e7..bf1c2c036f 100644 --- a/internal/npm_install/test/golden/@angular/core/BUILD.bazel.golden +++ b/internal/npm_install/test/golden/@angular/core/BUILD.bazel.golden @@ -677,7 +677,7 @@ node_module_library( node_module_library( name = "core__contents", srcs = [":core__files"], - scripts = [ + named_sources = [ "//:node_modules/@angular/core/bundles/core-testing.umd.js", "//:node_modules/@angular/core/bundles/core.umd.js", ], diff --git a/internal/npm_package/npm_package.bzl b/internal/npm_package/npm_package.bzl index 0cbf203781..8e512dcf87 100644 --- a/internal/npm_package/npm_package.bzl +++ b/internal/npm_package/npm_package.bzl @@ -6,7 +6,8 @@ If all users of your library code use Bazel, they should just add your library to the `deps` of one of their targets. """ -load("//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:declaration_provider.bzl", "DeclarationInfo") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") # Takes a depset of files and returns a corresponding list of file paths without any files # that aren't part of the specified package path. Also include files from external repositories @@ -95,30 +96,28 @@ def create_package(ctx, deps_sources, nested_packages): return package_dir def _npm_package(ctx): - deps_sources = depset() + sources_depsets = [] + for dep in ctx.attr.deps: - transitive = [ - deps_sources, - # Collect whatever is in the "data" - dep.data_runfiles.files, - ] - - if hasattr(dep, "node_sources"): - # For JavaScript-producing rules, gather up the devmode Node.js sources - transitive.append(dep.node_sources) - else: - # For standalone Output File Targets (aspects not invoked on these) - transitive.append(dep.files) + # Collect whatever is in the "data" + sources_depsets.append(dep.data_runfiles.files) + + # Only collect DefaultInfo files (not transitive) + sources_depsets.append(dep.files) + + # All direct & transitive JavaScript-producing deps + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in dep: + sources_depsets.append(dep[JSNamedModuleInfo].sources) - # ts_library doesn't include .d.ts outputs in the runfiles - # see comment in rules_typescript/internal/common/compilation.bzl - if hasattr(dep, "typescript"): - transitive.append(dep.typescript.transitive_declarations) + # Include all transitive declerations + if DeclarationInfo in dep: + sources_depsets.append(dep[DeclarationInfo].transitive_declarations) - deps_sources = depset(transitive = transitive) + sources = depset(transitive = sources_depsets) # Note: to_list() should be called once per rule! - package_dir = create_package(ctx, deps_sources.to_list(), ctx.files.packages) + package_dir = create_package(ctx, sources.to_list(), ctx.files.packages) return [DefaultInfo( files = depset([package_dir]), @@ -154,7 +153,6 @@ NPM_PACKAGE_ATTRS = { ), "deps": attr.label_list( doc = """Other targets which produce files that should be included in the package, such as `rollup_bundle`""", - aspects = [sources_aspect], allow_files = True, ), "_packager": attr.label( diff --git a/internal/rollup/rollup_bundle.bzl b/internal/rollup/rollup_bundle.bzl index bbffa23185..fa662b7c03 100644 --- a/internal/rollup/rollup_bundle.bzl +++ b/internal/rollup/rollup_bundle.bzl @@ -18,7 +18,7 @@ The versions of Rollup and terser are controlled by the Bazel toolchain. You do not need to install them into your project. """ -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "node_modules_aspect") load("//internal/common:collect_es6_sources.bzl", _collect_es2015_sources = "collect_es6_sources") load("//internal/common:module_mappings.bzl", "get_module_mappings") @@ -64,8 +64,8 @@ def _compute_node_modules_root(ctx): """ node_modules_root = None if ctx.attr.node_modules: - if NodeModuleSources in ctx.attr.node_modules: - node_modules_root = "/".join(["external", ctx.attr.node_modules[NodeModuleSources].workspace, "node_modules"]) + if NodeModuleInfo in ctx.attr.node_modules: + node_modules_root = "/".join(["external", ctx.attr.node_modules[NodeModuleInfo].workspace, "node_modules"]) elif ctx.files.node_modules: # ctx.files.node_modules is not an empty list node_modules_root = "/".join([f for f in [ @@ -74,8 +74,8 @@ def _compute_node_modules_root(ctx): "node_modules", ] if f]) for d in ctx.attr.deps: - if NodeModuleSources in d: - possible_root = "/".join(["external", d[NodeModuleSources].workspace, "node_modules"]) + if NodeModuleInfo in d: + possible_root = "/".join(["external", d[NodeModuleInfo].workspace, "node_modules"]) if not node_modules_root: node_modules_root = possible_root elif node_modules_root != possible_root: @@ -210,14 +210,15 @@ def _run_rollup(ctx, sources, config, output, map_output = None): args.add_joined(["%s:%s" % g for g in ctx.attr.globals.items()], join_with = ",") direct_inputs = [config] - direct_inputs += _filter_js_inputs(ctx.files.node_modules) + if hasattr(ctx.attr, "node_modules"): + direct_inputs += _filter_js_inputs(ctx.files.node_modules) # Also include files from npm fine grained deps as inputs. - # These deps are identified by the NodeModuleSources provider. + # These deps are identified by the NodeModuleInfo provider. for d in ctx.attr.deps: - if NodeModuleSources in d: + if NodeModuleInfo in d: # Note: we can't avoid calling .to_list() on sources - direct_inputs += _filter_js_inputs(d[NodeModuleSources].sources.to_list()) + direct_inputs += _filter_js_inputs(d[NodeModuleInfo].sources.to_list()) if ctx.file.license_banner: direct_inputs += [ctx.file.license_banner] @@ -569,7 +570,7 @@ def _rollup_bundle(ctx): # If users are in a different repo and load the aspect themselves, they will create # different Provider symbols (e.g. NodeModuleInfo) and we won't find them. # So users must use these symbols that are load'ed in rules_nodejs. -ROLLUP_DEPS_ASPECTS = [rollup_module_mappings_aspect, collect_node_modules_aspect] +ROLLUP_DEPS_ASPECTS = [rollup_module_mappings_aspect, node_modules_aspect] ROLLUP_ATTRS = { "srcs": attr.label_list( diff --git a/packages/jasmine/docs/BUILD.bazel b/packages/jasmine/docs/BUILD.bazel index 556c0544f7..0dd1a0fd2e 100644 --- a/packages/jasmine/docs/BUILD.bazel +++ b/packages/jasmine/docs/BUILD.bazel @@ -34,6 +34,7 @@ stardoc( # ``` "//internal/common:bzl", "//internal/node:bzl", + "//:bzl", ], ) diff --git a/packages/karma/docs/BUILD.bazel b/packages/karma/docs/BUILD.bazel index 6cbcd6523f..1b6b13964f 100644 --- a/packages/karma/docs/BUILD.bazel +++ b/packages/karma/docs/BUILD.bazel @@ -35,6 +35,7 @@ stardoc( # ``` "//internal/common:bzl", "//internal/js_library:bzl", + "//:bzl", ], ) diff --git a/packages/karma/src/karma_web_test.bzl b/packages/karma/src/karma_web_test.bzl index f3b5fa8758..2a182cfcf3 100644 --- a/packages/karma/src/karma_web_test.bzl +++ b/packages/karma/src/karma_web_test.bzl @@ -13,7 +13,8 @@ # limitations under the License. "Unit testing with Karma" -load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "node_modules_aspect") load("@build_bazel_rules_nodejs//internal/js_library:js_library.bzl", "write_amd_names_shim") load("@io_bazel_rules_webtesting//web:web.bzl", "web_test_suite") load("@io_bazel_rules_webtesting//web/internal:constants.bzl", "DEFAULT_WRAPPED_TEST_TAGS") @@ -50,7 +51,7 @@ KARMA_GENERIC_WEB_TEST_ATTRS = dict(COMMON_WEB_TEST_ATTRS, **{ These should be a list of targets which produce JavaScript such as `ts_library`. The files will be loaded in the same order they are declared by that rule.""", allow_files = True, - aspects = [sources_aspect], + aspects = [node_modules_aspect], ), "_conf_tmpl": attr.label( default = Label(_CONF_TMPL), @@ -65,7 +66,6 @@ KARMA_WEB_TEST_ATTRS = dict(KARMA_GENERIC_WEB_TEST_ATTRS, **{ certain attributes of this configuration file. Attributes that are overridden will be outputted to the test log.""", allow_single_file = True, - aspects = [sources_aspect], ), }) @@ -92,11 +92,15 @@ def _write_karma_config(ctx, files, amd_names_shim): sibling = ctx.outputs.executable, ) - config_file = "" - if hasattr(ctx.file, "config_file"): - config_file = ctx.file.config_file - if hasattr(ctx.attr.config_file, "typescript"): - config_file = ctx.attr.config_file.typescript.es5_sources.to_list()[0] + config_file = None + + # Check for config_file since ts_web_test does not have this attribute + if hasattr(ctx.attr, "config_file") and ctx.attr.config_file: + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in ctx.attr.config_file: + config_file = ctx.attr.config_file[JSNamedModuleInfo].sources.to_list()[0] + else: + config_file = ctx.file.config_file # The files in the bootstrap attribute come before the require.js support. # Note that due to frameworks = ['jasmine'], a few scripts will come before @@ -130,13 +134,14 @@ def _write_karma_config(ctx, files, amd_names_shim): # Thus they should come after the require.js script, but before any srcs or deps runtime_files = [] for dep in ctx.attr.runtime_deps: - if hasattr(dep, "typescript"): - for src in dep.typescript.es5_sources.to_list(): + if JSNamedModuleInfo in dep: + for src in dep[JSNamedModuleInfo].sources.to_list(): runtime_files.append(_to_manifest_path(ctx, src)) - elif hasattr(dep, "files"): + if not JSNamedModuleInfo in dep and not NodeModuleInfo in dep and hasattr(dep, "files"): # These are javascript files provided by DefaultInfo from a direct - # dep that has no "typescript" provider. These files must be in named - # AMD or named UMD format. + # dep that has no JSNamedModuleInfo provider or NodeModuleInfo + # provider (not an npm dep). These files must be in named AMD or named + # UMD format. for src in dep.files.to_list(): runtime_files.append(_to_manifest_path(ctx, src)) @@ -144,6 +149,7 @@ def _write_karma_config(ctx, files, amd_names_shim): user_entries = [ _to_manifest_path(ctx, f) for f in files.to_list() + if f.path.endswith(".js") ] # Expand static_files paths to runfiles for config @@ -189,19 +195,25 @@ def run_karma_web_test(ctx): Returns: The runfiles for the generated action. """ - files = depset(ctx.files.srcs) - for d in ctx.attr.deps + ctx.attr.runtime_deps: - has_node_sources = hasattr(d, "node_sources") - has_dev_scripts = hasattr(d, "dev_scripts") - if has_node_sources: - files = depset(transitive = [files, d.node_sources]) - if has_dev_scripts: - files = depset(transitive = [files, d.dev_scripts]) - if not has_node_sources and not has_dev_scripts and hasattr(d, "files"): - # These are Javascript files directly specified in "deps". - # They are not collected by `sources_aspect` due to the absence of - # `deps` attr. These files must be in named AMD format. - files = depset(transitive = [files, d.files]) + files_depsets = [depset(ctx.files.srcs)] + for dep in ctx.attr.deps + ctx.attr.runtime_deps: + if JSNamedModuleInfo in dep: + files_depsets.append(dep[JSNamedModuleInfo].sources) + if not JSNamedModuleInfo in dep and not NodeModuleInfo in dep and hasattr(dep, "files"): + # These are javascript files provided by DefaultInfo from a direct + # dep that has no JSNamedModuleInfo provider or NodeModuleInfo + # provider (not an npm dep). These files must be in named AMD or named + # UMD format. + files_depsets.append(dep.files) + files = depset(transitive = files_depsets) + + # Also include files from npm fine grained deps as inputs. + # These deps are identified by the NodeModuleInfo provider. + node_modules_depsets = [] + for dep in ctx.attr.deps + ctx.attr.runtime_deps: + if NodeModuleInfo in dep: + node_modules_depsets.append(dep[NodeModuleInfo].sources) + node_modules = depset(transitive = node_modules_depsets) amd_names_shim = _write_amd_names_shim(ctx) @@ -252,11 +264,14 @@ $KARMA ${{ARGV[@]}} ) config_sources = [] - if hasattr(ctx.file, "config_file"): - if ctx.file.config_file: + + # Check for config_file since ts_web_test does not have this attribute + if hasattr(ctx.attr, "config_file") and ctx.attr.config_file: + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in ctx.attr.config_file: + config_sources = ctx.attr.config_file[JSNamedModuleInfo].sources.to_list() + else: config_sources = [ctx.file.config_file] - if hasattr(ctx.attr.config_file, "node_sources"): - config_sources = ctx.attr.config_file.node_sources.to_list() runfiles = [ configuration, @@ -272,7 +287,7 @@ $KARMA ${{ARGV[@]}} return ctx.runfiles( files = runfiles, - transitive_files = files, + transitive_files = depset(transitive = [files, node_modules]), ).merge(ctx.attr.karma[DefaultInfo].data_runfiles) def _karma_web_test_impl(ctx): diff --git a/packages/karma/src/web_test.bzl b/packages/karma/src/web_test.bzl index 7ebb58b259..23c3433744 100644 --- a/packages/karma/src/web_test.bzl +++ b/packages/karma/src/web_test.bzl @@ -13,7 +13,7 @@ # limitations under the License. "Common web_test attributes" -load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "node_modules_aspect") # Attributes shared by any web_test rule (ts_web_test, karma_web_test, protractor_web_test) COMMON_WEB_TEST_ATTRS = { @@ -35,6 +35,6 @@ COMMON_WEB_TEST_ATTRS = { "deps": attr.label_list( doc = "Other targets which produce JavaScript such as `ts_library`", allow_files = True, - aspects = [sources_aspect], + aspects = [node_modules_aspect], ), } diff --git a/packages/labs/src/protobufjs/ts_proto_library.bzl b/packages/labs/src/protobufjs/ts_proto_library.bzl index dc699945da..34561117cf 100644 --- a/packages/labs/src/protobufjs/ts_proto_library.bzl +++ b/packages/labs/src/protobufjs/ts_proto_library.bzl @@ -14,7 +14,7 @@ "Protocol Buffers" load("@build_bazel_rules_nodejs//:declaration_provider.bzl", "DeclarationInfo") -load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "JSNamedModuleInfo") def _run_pbjs(actions, executable, output_name, proto_files, suffix = ".js", wrap = "amd", amd_name = ""): js_file = actions.declare_file(output_name + suffix) @@ -118,6 +118,9 @@ def _ts_proto_library(ctx): declarations = declarations, transitive_declarations = declarations, ), + JSNamedModuleInfo( + sources = es5_sources, + ), JSEcmaScriptModuleInfo( sources = es6_sources, ), diff --git a/packages/protractor/docs/BUILD.bazel b/packages/protractor/docs/BUILD.bazel index 3d1521037a..f4fba32997 100644 --- a/packages/protractor/docs/BUILD.bazel +++ b/packages/protractor/docs/BUILD.bazel @@ -31,6 +31,7 @@ stardoc( # `@build_bazel_rules_nodejs//foo:bzl` style deps are not found # by the doc generator: # ``` + # Exception in thread "main" java.lang.IllegalStateException: File external/npm_bazel_jasmine/jasmine_node_test.bzl imported '@build_bazel_rules_nodejs//internal/common:devmode_js_sources.bzl', yet internal/common/devmode_js_sources.bzl was not found, even at roots [.]. # ``` "//:bzl", "//internal/common:bzl", diff --git a/packages/protractor/src/protractor_web_test.bzl b/packages/protractor/src/protractor_web_test.bzl index 69dfa02b98..3b8f22c153 100644 --- a/packages/protractor/src/protractor_web_test.bzl +++ b/packages/protractor/src/protractor_web_test.bzl @@ -14,7 +14,8 @@ "Run end-to-end tests with Protractor" load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") -load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "node_modules_aspect") load("@build_bazel_rules_nodejs//internal/common:windows_utils.bzl", "create_windows_native_launcher_script", "is_windows") load("@io_bazel_rules_webtesting//web:web.bzl", "web_test_suite") load("@io_bazel_rules_webtesting//web/internal:constants.bzl", "DEFAULT_WRAPPED_TEST_TAGS") @@ -36,12 +37,25 @@ def _protractor_web_test_impl(ctx): sibling = ctx.outputs.script, ) - files = depset(ctx.files.srcs) - for d in ctx.attr.deps: - if hasattr(d, "node_sources"): - files = depset(transitive = [files, d.node_sources]) - elif hasattr(d, "files"): - files = depset(transitive = [files, d.files]) + files_depsets = [depset(ctx.files.srcs)] + for dep in ctx.attr.deps: + if JSNamedModuleInfo in dep: + files_depsets.append(dep[JSNamedModuleInfo].sources) + if not JSNamedModuleInfo in dep and not NodeModuleInfo in dep and hasattr(dep, "files"): + # These are javascript files provided by DefaultInfo from a direct + # dep that has no JSNamedModuleInfo provider or NodeModuleInfo + # provider (not an npm dep). These files must be in named AMD or named + # UMD format. + files_depsets.append(dep.files) + files = depset(transitive = files_depsets) + + # Also include files from npm fine grained deps as inputs. + # These deps are identified by the NodeModuleInfo provider. + node_modules_depsets = [] + for dep in ctx.attr.deps: + if NodeModuleInfo in dep: + node_modules_depsets.append(dep[NodeModuleInfo].sources) + node_modules = depset(transitive = node_modules_depsets) specs = [ _to_manifest_path(ctx, f) @@ -49,24 +63,26 @@ def _protractor_web_test_impl(ctx): ] configuration_sources = [] - if ctx.file.configuration: - configuration_sources = [ctx.file.configuration] - if hasattr(ctx.attr.configuration, "node_sources"): - configuration_sources = ctx.attr.configuration.node_sources.to_list() - - configuration_file = ctx.file.configuration - if hasattr(ctx.attr.configuration, "typescript"): - configuration_file = ctx.attr.configuration.typescript.es5_sources.to_list()[0] + configuration_file = None + if ctx.attr.configuration: + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in ctx.attr.configuration: + configuration_sources = ctx.attr.configuration[JSNamedModuleInfo].sources.to_list() + configuration_file = ctx.attr.configuration[JSNamedModuleInfo].sources.to_list()[0] + else: + configuration_sources = [ctx.file.configuration] + configuration_file = ctx.file.configuration on_prepare_sources = [] - if ctx.file.on_prepare: - on_prepare_sources = [ctx.file.on_prepare] - if hasattr(ctx.attr.on_prepare, "node_sources"): - on_prepare_sources = ctx.attr.on_prepare.node_sources.to_list() - - on_prepare_file = ctx.file.on_prepare - if hasattr(ctx.attr.on_prepare, "typescript"): - on_prepare_file = ctx.attr.on_prepare.typescript.es5_sources.to_list()[0] + on_prepare_file = None + if ctx.attr.on_prepare: + # TODO: switch to JSModuleInfo when it is available + if JSNamedModuleInfo in ctx.attr.on_prepare: + on_prepare_sources = ctx.attr.on_prepare[JSNamedModuleInfo].sources.to_list() + on_prepare_file = ctx.attr.on_prepare[JSNamedModuleInfo].sources.to_list()[0] + else: + on_prepare_sources = [ctx.file.on_prepare] + on_prepare_file = ctx.file.on_prepare ctx.actions.expand_template( output = configuration, @@ -127,7 +143,7 @@ $PROTRACTOR $CONF files = depset([ctx.outputs.script]), runfiles = ctx.runfiles( files = runfiles, - transitive_files = files, + transitive_files = depset(transitive = [files, node_modules]), # Propagate protractor_bin and its runfiles collect_data = True, collect_default = True, @@ -149,7 +165,6 @@ _protractor_web_test = rule( "configuration": attr.label( doc = "Protractor configuration file", allow_single_file = True, - aspects = [sources_aspect], ), "data": attr.label_list( doc = "Runtime dependencies", @@ -159,7 +174,6 @@ _protractor_web_test = rule( If the script exports a function which returns a promise, protractor will wait for the promise to resolve before beginning tests.""", allow_single_file = True, - aspects = [sources_aspect], ), "protractor": attr.label( doc = "Protractor executable target", @@ -176,7 +190,7 @@ _protractor_web_test = rule( "deps": attr.label_list( doc = "Other targets which produce JavaScript such as `ts_library`", allow_files = True, - aspects = [sources_aspect], + aspects = [node_modules_aspect], ), "_conf_tmpl": attr.label( default = Label(_CONF_TMPL), diff --git a/packages/protractor/test/protractor-2/BUILD.bazel b/packages/protractor/test/protractor-2/BUILD.bazel index fb49f3e4ee..5e6ee6fb86 100644 --- a/packages/protractor/test/protractor-2/BUILD.bazel +++ b/packages/protractor/test/protractor-2/BUILD.bazel @@ -1,6 +1,7 @@ -load("@build_bazel_rules_nodejs//:index.bzl", "rollup_bundle") load("@npm//http-server:index.bzl", "http_server") load("@npm_bazel_protractor//:index.from_src.bzl", "protractor_web_test_suite") +load("@npm_bazel_rollup//:index.from_src.bzl", "rollup_bundle") +load("@npm_bazel_terser//:index.from_src.bzl", "terser_minified") load("@npm_bazel_typescript//:index.bzl", "ts_config") load("@npm_bazel_typescript//:index.from_src.bzl", "ts_devserver", "ts_library") @@ -25,16 +26,20 @@ ts_devserver( rollup_bundle( name = "bundle", - enable_code_splitting = False, entry_point = ":app.ts", deps = [":app"], ) +terser_minified( + name = "bundle.min", + src = ":bundle", +) + http_server( name = "prodserver", data = [ "index.html", - ":bundle.min.js", + ":bundle.min", ], # This repeats the default, but is here for coverage # to make sure the generated index.bzl handles it diff --git a/packages/rollup/src/rollup_bundle.bzl b/packages/rollup/src/rollup_bundle.bzl index 0e3babd356..d42c38c05a 100644 --- a/packages/rollup/src/rollup_bundle.bzl +++ b/packages/rollup/src/rollup_bundle.bzl @@ -1,7 +1,7 @@ "Rules for running Rollup under Bazel" load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo") -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "node_modules_aspect") load("@build_bazel_rules_nodejs//internal/linker:link_node_modules.bzl", "module_mappings_aspect", "register_node_modules_linker") _DOC = """Runs the Rollup.js CLI under Bazel. @@ -152,7 +152,7 @@ Passed to the [`--sourcemap` option](https://github.com/rollup/rollup/blob/maste values = ["inline", "true", "false"], ), "deps": attr.label_list( - aspects = [module_mappings_aspect, collect_node_modules_aspect], + aspects = [module_mappings_aspect, node_modules_aspect], doc = """Other libraries that are required by the code, or by the rollup.config.js""", ), } @@ -250,9 +250,9 @@ def _rollup_bundle(ctx): deps_depsets.append(dep.files) # Also include files from npm deps as inputs. - # These deps are identified by the NodeModuleSources provider. - if NodeModuleSources in dep: - deps_depsets.append(dep[NodeModuleSources].sources) + # These deps are identified by the NodeModuleInfo provider. + if NodeModuleInfo in dep: + deps_depsets.append(dep[NodeModuleInfo].sources) deps_inputs = depset(transitive = deps_depsets).to_list() inputs = _filter_js(ctx.files.entry_point) + _filter_js(ctx.files.entry_points) + ctx.files.srcs + deps_inputs diff --git a/packages/typescript/src/internal/build_defs.bzl b/packages/typescript/src/internal/build_defs.bzl index 76b041445d..01386e28e0 100644 --- a/packages/typescript/src/internal/build_defs.bzl +++ b/packages/typescript/src/internal/build_defs.bzl @@ -14,8 +14,8 @@ "TypeScript compilation" -load("@build_bazel_rules_nodejs//:providers.bzl", "transitive_js_ecma_script_module_info") -load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleSources", "collect_node_modules_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "transitive_js_ecma_script_module_info", "transitive_js_named_module_info") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "node_modules_aspect") # pylint: disable=unused-argument # pylint: disable=missing-docstring @@ -46,7 +46,7 @@ def _trim_package_node_modules(package_name): # but wouldn't work for other rules like nodejs_binary def _uses_bazel_managed_node_modules(ctx): # If the user put a filegroup as the node_modules it will have no provider - return NodeModuleSources in ctx.attr.node_modules + return NodeModuleInfo in ctx.attr.node_modules # This function is similar but slightly different than _compute_node_modules_root # in /internal/node/node.bzl. TODO(gregmagolan): consolidate these functions @@ -61,8 +61,8 @@ def _compute_node_modules_root(ctx): """ node_modules_root = None if ctx.attr.node_modules: - if NodeModuleSources in ctx.attr.node_modules: - node_modules_root = "/".join(["external", ctx.attr.node_modules[NodeModuleSources].workspace, "node_modules"]) + if NodeModuleInfo in ctx.attr.node_modules: + node_modules_root = "/".join(["external", ctx.attr.node_modules[NodeModuleInfo].workspace, "node_modules"]) elif ctx.files.node_modules: # ctx.files.node_modules is not an empty list node_modules_root = "/".join([f for f in [ @@ -71,8 +71,8 @@ def _compute_node_modules_root(ctx): "node_modules", ] if f]) for d in ctx.attr.deps: - if NodeModuleSources in d: - possible_root = "/".join(["external", d[NodeModuleSources].workspace, "node_modules"]) + if NodeModuleInfo in d: + possible_root = "/".join(["external", d[NodeModuleInfo].workspace, "node_modules"]) if not node_modules_root: node_modules_root = possible_root elif node_modules_root != possible_root: @@ -118,11 +118,11 @@ def _compile_action(ctx, inputs, outputs, tsconfig_file, node_opts, description action_inputs.extend(_filter_ts_inputs(ctx.files.node_modules)) # Also include files from npm fine grained deps as action_inputs. - # These deps are identified by the NodeModuleSources provider. + # These deps are identified by the NodeModuleInfo provider. for d in ctx.attr.deps: - if NodeModuleSources in d: + if NodeModuleInfo in d: # Note: we can't avoid calling .to_list() on sources - action_inputs.extend(_filter_ts_inputs(d[NodeModuleSources].sources.to_list())) + action_inputs.extend(_filter_ts_inputs(d[NodeModuleInfo].sources.to_list())) if ctx.file.tsconfig: action_inputs.append(ctx.file.tsconfig) @@ -275,12 +275,16 @@ def _ts_library_impl(ctx): # See design doc https://docs.google.com/document/d/1ggkY5RqUkVL4aQLYm7esRW978LgX3GUCnQirrk5E1C0/edit# # and issue https://github.com/bazelbuild/rules_nodejs/issues/57 for more details. ts_providers["providers"].extend([ + transitive_js_named_module_info( + sources = ts_providers["typescript"]["es5_sources"], + deps = ctx.attr.deps, + ), transitive_js_ecma_script_module_info( sources = ts_providers["typescript"]["es6_sources"], deps = ctx.attr.deps, ), - # TODO: Add remaining shared JS providers from design doc - # (JSModuleInfo and JSNamedModuleInfo) and remove legacy "typescript" provider + # TODO: Add remaining shared JS provider from design doc + # (JSModuleInfo) and remove legacy "typescript" provider # once it is no longer needed. ]) @@ -412,7 +416,7 @@ either: doc = "If using tsickle, instruct it to translate types to ClosureJS format", ), "deps": attr.label_list( - aspects = DEPS_ASPECTS + [collect_node_modules_aspect], + aspects = DEPS_ASPECTS + [node_modules_aspect], doc = "Compile-time dependencies, typically other ts_library targets", ), }), diff --git a/packages/typescript/src/internal/devserver/ts_devserver.bzl b/packages/typescript/src/internal/devserver/ts_devserver.bzl index 66a80c35b8..64abf34d70 100644 --- a/packages/typescript/src/internal/devserver/ts_devserver.bzl +++ b/packages/typescript/src/internal/devserver/ts_devserver.bzl @@ -14,7 +14,8 @@ "Simple development server" -load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") +load("@build_bazel_rules_nodejs//internal/common:node_module_info.bzl", "NodeModuleInfo", "node_modules_aspect") load( "@build_bazel_rules_nodejs//internal/js_library:js_library.bzl", "write_amd_names_shim", @@ -33,15 +34,25 @@ def _to_manifest_path(ctx, file): return ctx.workspace_name + "/" + file.short_path def _ts_devserver(ctx): - files = depset() - dev_scripts = depset() - for d in ctx.attr.deps: - if hasattr(d, "node_sources"): - files = depset(transitive = [files, d.node_sources]) - elif hasattr(d, "files"): - files = depset(transitive = [files, d.files]) - if hasattr(d, "dev_scripts"): - dev_scripts = depset(transitive = [dev_scripts, d.dev_scripts]) + files_depsets = [] + for dep in ctx.attr.deps: + if JSNamedModuleInfo in dep: + files_depsets.append(dep[JSNamedModuleInfo].sources) + if not JSNamedModuleInfo in dep and not NodeModuleInfo in dep and hasattr(dep, "files"): + # These are javascript files provided by DefaultInfo from a direct + # dep that has no JSNamedModuleInfo provider or NodeModuleInfo + # provider (not an npm dep). These files must be in named AMD or named + # UMD format. + files_depsets.append(dep.files) + files = depset(transitive = files_depsets) + + # Also include files from npm fine grained deps as inputs. + # These deps are identified by the NodeModuleInfo provider. + node_modules_depsets = [] + for dep in ctx.attr.deps: + if NodeModuleInfo in dep: + node_modules_depsets.append(dep[NodeModuleInfo].sources) + node_modules = depset(transitive = node_modules_depsets) if ctx.label.workspace_root: # We need the workspace_name for the target being visited. @@ -59,6 +70,7 @@ def _ts_devserver(ctx): ctx.actions.write(ctx.outputs.manifest, "".join([ workspace_name + "/" + f.short_path + "\n" for f in files.to_list() + if f.path.endswith(".js") ])) amd_names_shim = ctx.actions.declare_file( @@ -75,7 +87,6 @@ def _ts_devserver(ctx): script_files.append(ctx.file._requirejs_script) script_files.append(amd_names_shim) script_files.extend(ctx.files.scripts) - script_files.extend(dev_scripts.to_list()) ctx.actions.write(ctx.outputs.scripts_manifest, "".join([ workspace_name + "/" + f.short_path + "\n" for f in script_files @@ -128,7 +139,7 @@ def _ts_devserver(ctx): files = devserver_runfiles, # We don't expect executable targets to depend on the devserver, but if they do, # they can see the JavaScript code. - transitive_files = depset(ctx.files.data, transitive = [files]), + transitive_files = depset(ctx.files.data, transitive = [files, node_modules]), collect_data = True, collect_default = True, ), @@ -192,7 +203,7 @@ ts_devserver = rule( "deps": attr.label_list( doc = "Targets that produce JavaScript, such as `ts_library`", allow_files = True, - aspects = [sources_aspect], + aspects = [node_modules_aspect], ), "_bash_runfile_helpers": attr.label(default = Label("@bazel_tools//tools/bash/runfiles")), "_injector": attr.label( diff --git a/packages/typescript/test/devmode_consumer/devmode_consumer.bzl b/packages/typescript/test/devmode_consumer/devmode_consumer.bzl index b23a4b421d..ed90e109cf 100644 --- a/packages/typescript/test/devmode_consumer/devmode_consumer.bzl +++ b/packages/typescript/test/devmode_consumer/devmode_consumer.bzl @@ -15,26 +15,23 @@ """Example of a rule that requires es2015 (devmode) inputs. """ -load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo") def _devmode_consumer(ctx): - files = depset() - - # Since we apply the sources_aspect to our deps below, we can iterate through - # the deps and grab the attribute attached by that aspect, which is called - # "node_sources". - # See https://github.com/bazelbuild/rules_nodejs/blob/master/internal/node.bzl - for d in ctx.attr.deps: - files = depset(transitive = [files, d.node_sources]) + sources_depsets = [] + for dep in ctx.attr.deps: + if JSNamedModuleInfo in dep: + sources_depsets.append(dep[JSNamedModuleInfo].sources) + sources = depset(transitive = sources_depsets) return [DefaultInfo( - files = files, - runfiles = ctx.runfiles(files.to_list()), + files = sources, + runfiles = ctx.runfiles(transitive_files = sources), )] devmode_consumer = rule( implementation = _devmode_consumer, attrs = { - "deps": attr.label_list(aspects = [sources_aspect]), + "deps": attr.label_list(), }, ) diff --git a/providers.bzl b/providers.bzl index 63512fecbe..9c9f5bf0f4 100644 --- a/providers.bzl +++ b/providers.bzl @@ -22,6 +22,51 @@ If users really need to produce both in a single build, they'll need two rules w differing 'debug' attributes. """ +JSNamedModuleInfo = provider( + doc = """JavaScript files whose module name is self-contained. + +For example named AMD/UMD or goog.module format. +These files can be efficiently served with the concatjs bundler. +These outputs should be named "foo.umd.js" +(note that renaming it from "foo.js" doesn't affect the module id) + +Historical note: this was the typescript.es5_sources output. +""", + fields = { + "sources": "depset of direct and transitive JavaScript files and sourcemaps", + }, +) + +def transitive_js_named_module_info(sources, deps = []): + """Constructs a JSNamedModuleInfo including all transitive sources from JSNamedModuleInfo providers in a list of deps. + +Returns a single JSNamedModuleInfo. +""" + return combine_js_named_module_info([JSNamedModuleInfo(sources = sources)] + collect_js_named_module_infos(deps)) + +def combine_js_named_module_info(modules): + """Combines all JavaScript sources and sourcemaps from a list of JSNamedModuleInfo providers. + +Returns a single JSNamedModuleInfo. +""" + sources_depsets = [] + for module in modules: + sources_depsets.extend([module.sources]) + return JSNamedModuleInfo( + sources = depset(transitive = sources_depsets), + ) + +def collect_js_named_module_infos(deps): + """Collects all JSNamedModuleInfo providers from a list of deps. + +Returns a list of JSNamedModuleInfo providers. +""" + modules = [] + for dep in deps: + if JSNamedModuleInfo in dep: + modules.extend([dep[JSNamedModuleInfo]]) + return modules + JSEcmaScriptModuleInfo = provider( doc = """JavaScript files (and sourcemaps) that are intended to be consumed by downstream tooling.